一、Service
出现的原因
从上一篇博客Kubernetes教程(七)了解集群、标签、Pod和Deployment可以知道每一个Pod
都会有一个Pod IP
。那有如下情况:
Pod
是可以有多个副本的,那么多个副本情况下,每个Pod
副本的Pod IP
也不同- 随着
Pod
的销毁和重建,Pod
迁移到别的节点上,Pod IP
也随之变化
那么别的业务要访问这个Pod
的接口时,那么多Pod IP
该如何选择呢?常做Java开发的肯定想到用Nginx做负载均衡啊,比如下图的方案:
K8s也采用了类似的做法叫Service
,在每个Node上都运行了一套全局虚拟负载均衡器。K8s还给Service
分配一个全局唯一的虚拟IP(ClusterIP
),在Service
的整个生命周期里,这个ClusterIP
都不会变化。就是说不管Pod
的Pod IP
如何改变,我们只要访问这个不变的ClusterIP
就可以了。
Service
是K8s中的一种资源对象,用于定义一组Pod
的访问规则,提供统一入口Service
提供负载均衡:当有多个Pod
副本时,用负载均衡算法将请求分发给这些Pod
Service
提供服务发现:自动维护后端Pod IP
的变化Service
与Pod
是通过Label
标签关联的,如下图中的app=web
二、Service
的定义
1. Service
的yaml文件格式
apiVersion: v1
kind: Service
metadata: 元数据
name: demo Service的名字,在同一个namespace中必须唯一
namespace: default 命名空间,不指定时默认为"default"
labels: 自定义标签属性列表
- app: demo
annotations: 自定义注解属性列表
- name: string
spec:
type: ClusterIP Service的类型,指定service的访问方式,默认ClusterIP
clusterIP: string 虚拟服务IP地址,当type=ClusterIP时,如不指定,则系统会自动进行分配,也可以手动指定。当type=loadBalancer,需要指定
sessionAffinity: string 是否支持session,可选值为ClietIP,默认值为空。ClientIP表示将同一个客户端(根据客户端IP地址决定)的访问请求都转发到同一个后端Pod
ports: 如果Pod上有多个端口提供服务,可以为每个端口定义一个端口映射规则
- name: string 端口名称
protocol: TCP 端口协议,支持TCP或UDP,默认TCP
port: 8080 服务监听的端口号
targetPort: 8080 需要转发到后端Pod上的端口号
nodePort: int 当type=NodePort时,指定映射到物理机的端口号
selector: 必填,选择具有指定label标签的pod作为管理范围
app: demo
status: 当type=LoadBalancer时,设置外部负载均衡的地址,用于公有云环境
loadBalancer: 外部负载均衡器
ingress:
ip: string 部负载均衡器的IP地址
hostname: string 外部负载均衡器的主机名
2. Service类型
Service
的公开类型定义了Service
如何对外部网络公开,有4种类型:
- ClusterIP:虚拟的服务ip地址,用于k8s集群内部的pod访问,在Node上kube-porxy通过设置的iptables规则进行转发
- NodePort:使用宿主机端口,能够访问各个Node的外部客户端通过Node的IP和端口就能访问服务器
- LoadBalancer:使用外部负载均衡器完成到服务器的负载分发,需要在spec.status.loadBalancer字段指定外部负载均衡服务器的IP,并同时定义nodePort和clusterIP,用于公有云环境。
- ExternalName:映射到外部服务名,需要设置一个DNS域名,表示Service直接指向某个外部服务,而不是集群中的Pod
三、案例
- 假设有一组由
Deployment
管理的Pod
- 这些
Pod
在TCP的80端口提供服务 Pod
的标签为app=nginx
为了将这一组Pod
对外公开,创建如下Service
资源:
apiVersion: v1 # API版本
kind: Service # 资源类型
metadata: # 资源元数据
name: nginx # 资源名称
spec: # 资源规格
ports: # 端口映射列表
- name: # 端口名称
port: 80 # 公开端口
protocol: TCP # 端口协议,支持TCP、UDP和SCTP,默认TCP
targetPort: 80 # 目标端口,即容器内应用程序监听的端口
selector: # 标签选择器
app: nginx # Pod标签,流量转发到有"app=nginx"标签的Pod上