前言
上文介绍了Kubernetes副本机制,正是因为副本机制你的部署能自动保待运行,并且保持健康,无须任何手动干预;本文继续介绍kubernetes的另一个强大的功能服务,在客户端和pod之间提供一个服务层,提供了单一的接入点,更加方便客户端使用pod。
服务
Kubernetes服务是一种为一组功能相同的pod提供单一不变的接入点的资源;当服务存在时,它的IP地址和端口不会改变,客户端通过IP地址和端口号建立连接,这些连接会被路由到提供该服务的任意一个pod上;
1.创建服务
服务的连接对所有的后端pod是负载均衡的,至于哪些pod被属于哪个服务,通过在定义服务的时候设置标签选择器;
[d:\k8s]$ kubectl create -f kubia-rc.yaml
replicationcontroller/kubia created
[d:\k8s]$ kubectl get pod
NAME READY STATUS RESTARTS AGE
kubia-6dxn7 0/1 ContainerCreating 0 4s
kubia-fhxht 0/1 ContainerCreating 0 4s
kubia-fpvc7 0/1 ContainerCreating 0 4s
使用之前的yaml文件创建pod,模版中设置的标签为app: kubia,所以创建服务的yaml(还有之前介绍的kubectl expose方式也可以创建服务)中也需要指定相同的标签:
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
首先指定的资源类型为Service,然后指定了两个端口分别:port服务提供的端口,targetPort指定pod中进程监听的端口,最后指定标签选择器,相同标签的pod被当前服务管理;
[d:\k8s]$ kubectl create -f kubia-svc.yaml
service/kubia created
[d:\k8s]$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d15h
kubia ClusterIP 10.96.191.193 <none> 80/TCP 4s
[d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.191.193
You've hit kubia-fhxht [d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.191.193 You've hit kubia-fpvc7
创建完服务之后,可以发现给kubia分配了CLUSTER-IP,这是一个内部ip;至于如何测试可以使用kubectl exec命令远程地在一个已经存在的pod容器上执行任何命令;pod名称可以随意指定三个中的任何一个,接收到crul命令的pod,会转发给Service,由Service来决定将请求交给哪个pod处理,所以可以看到多次执行,发现每次处理的pod都不一样;如果希望特定客户端产生的所有请求每次都指向同一个pod, 可以设置服务的sessionAffinity属性为ClientIP;
1.1配置会话黏性
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
sessionAffinity: ClientIP
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
除了添加了sessionAffinity: ClientIP,其他都一样
[d:\k8s]$ kubectl delete svc kubia
service "kubia" deleted
[d:\k8s]$ kubectl create -f kubia-svc-client-ip-session-affinity.yaml
service/kubia created
[d:\k8s]$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d15h
kubia ClusterIP 10.96.51.99 <none> 80/TCP 25s
[d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.51.99
You've hit kubia-fhxht [d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.51.99 You've hit kubia-fhxht
1.2 同一个服务暴露多个端口
如果pod监听了两个或者多个端口,那么服务同样可以暴露多个端口:
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
ports:
- name: http
port: 80
targetPort: 8080
- name: https
port: 443
targetPort: 8080
selector:
app: kubia
因为Node.js只监听了8080一个端口,所以这里在Service里面配置两个端口都指向同一个目标端口,看是否都能访问:
[d:\k8s]$ kubectl create -f kubia-svc-named-ports.yaml
service/kubia created
[d:\k8s]$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d18h
kubia ClusterIP 10.96.13.178 <none> 80/TCP,443/TCP 7s
[d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.13.178
You've hit kubia-fpvc7 [d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.13.178:443 You've hit kubia-fpvc7
可以发现使用两个端口都可以访问;
1.3 使用命名的端口
在Service中指定了端口为8080,如果目标端口变了这里也需要改变,可以在定义pod的模版中给端口命名,在Service中可以直接指定名称:
apiVersion: v1
kind: ReplicationController
metadata:
name: kubia
spec:
replicas: 3
selector:
app: kubia
template:
metadata:
labels:
app: kubia
spec:
containers:
- name: kubia
image: ksfzhaohui/kubia
ports:
- name: http
containerPort: 8080
在之前的ReplicationController中稍作修改,在port是中指定了名称,Service的yaml文件同样做修改,直接使用名称:
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
ports:
- port: 80
targetPort: http
selector:
app: kubia
targetPort直接使用了名称http:
[d:\k8s]$ kubectl create -f kubia-rc2.yaml
replicationcontroller/kubia created
[d:\k8s]$ kubectl get pod
NAME READY STATUS RESTARTS AGE
kubia-4m9nv 1/1 Running 0 66s
kubia-bm6rx 1/1 Running 0 66s
kubia-dh87r 1/1 Running 0 66s
[d:\k8s]$ kubectl create -f kubia-svc2.yaml
service/kubia created
[d:\k8s]$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d
kubia ClusterIP 10.96.106.37 <none> 80/TCP 10s
[d:\k8s]$ kubectl exec kubia-4m9nv -- curl -s http://10.96.106.37
You've hit kubia-dh87r
2.服务发现
服务给我们提供了一个单一不变的ip去访问pod,那是否每次都要先创建服务,然后找到服务的CLUSTER-IP