为什么需要使用Kubernetes Service
如前文提到,集群中Pod的IP地址是不稳定的, 会随着Pod的删除、重启、扩缩容等活动发生变动。这就出现了一个问题:无法通过一个固定的地址来访问应用程序。
Kubernetes Service则专门来解决这个问题。
Kubernetes Service
K8s Service有一个固定的IP地址、固定的DNS名称以及固定的端口。通过标签选择器在后端连接所有符合要求的Pod,前端则提供了一个固定的访问平面来接收所有访问Pod的请求,再将这些请求负载均衡到后端的Pod中。可以将Service理解为Pod的网关,一个前端固定而后端随着Pod变化而变化的K8s中间件。
使用Label达到Service与Pod间的松耦合
Service通过标签选择器来选择Pod。如下面的deploy.yml
和svc.yml
文件。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deploy
spec:
replicas: 10
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world # 在Deployment的模板中,定义了Pod所属的标签,即 app=hello-world
spec:
containers:
- name: hello-ctr
image: nigelpoulton/k8sbook:latest
ports:
- containerPort: 8080
通过上面的Deployment部署文件部署的Pod都具有app=hello-world
这一标签。
apiVersion: v1
kind: Service
metadata:
name: hello-svc
spec:
type: NodePort
ports:
- port: 8081
nodePort: 30001
targetPort: 8080
protocol: TCP
selector:
app: hello-world # 选择器selector选择的Pod应具有的标签
上面的Service部署文件则通过选择器选定含有标签为app=hello-world
的Pod,为这些Pod做匹配关联。Pod必须含有Service所指定的全部标签,除此之外还有其他多余的标签也是可以的。
Service与Endpoint
每一个Service在创建时会关联到一个Endpoint对象,该Endpoint对象中维护所有满足Service标签选择器的Pod的列表。
Kubernetes会不断检查Service的Label选择器和当前集群中的健康Pod列表,如果有新的可以匹配该Label选择器的Pod,就将其加入Endpoint中,然后Service从这个Endpoint中选择流量转发的Pod。
Service相关的端口
上述Service部署文件中,出现了这样几个端口:
ports:
- port: 8081
nodePort: 30001
targetPort: 8080
protocol: TCP
-
port:Service监听的端口,集群中通过Service IP访问Pod应用的流量首先需要访问Service IP+port
-
nodePort:为集群外流量开放的端口,可以使用集群中任何一台部署Pod的主机的IP+nodePort访问应用
-
targetPort:Pod所监听的端口,告诉Service将流量转发到Pod的该端口