
pod是随时变化的,动态的伸缩,所以应用程序直接连接pod是不可靠的,所以kubernetes引入service,service是为一组功能相同的pod提供统一入口。
例
1 | kind: Service |
上面例子,我们创建一个名为http-app的deployment,然后创建了个Service,selector labels方式将Service与deployment绑定,service类型为 cluster-ip,也就是内部访问类型
在kubernetes集群任意一个节点curl访问
端口类型
port
Service暴露出来的内部访问端口
targetPort
pod暴露出来的端口
NodePort
NodePort是kubernetes提供外部访问service的暴露端口,它暴露在集群所有宿主机上,默认端口范围为30000~32767
服务类型
ClusterIP(默认)
使用clusterip类型的Service默认会使用一个集群内部ip,通过kube-proxy调用iptables创建规则,将流量转发到pod中,需要注意的是clusterip是一个virtual_ip没有真正的网络设备绑定,所以是ping不通它的,直接在集群内部的访问就好。
NodePort
使用NodePort类型的Service时会在集群内部所有host上暴露一个端口用于外部访问
创建方法
1 | kind: Service |
不指定nodePort端口将从30000~32767里面随机选一个
LoadBlancer
使用loadblance类型时,会向cloud provider申请映射到service本身的负载均衡,比如AWS的ELB、google cloud 的GCP、Azure的azure-load-balancer。
外部访问pod
NodePort
loadblance
ingress

Service负载均衡
kube-proxy 会检测 API Server 上对于 service 和 endpoint 的新增或者移除。对于每个新的 service,在每个 node 上,kube-proxy 都会设置相应的 iptables 的规则来记录应该转发的地址。当一个 service 被删除的时候,kube-proxy 会在所有的 pod 上移除这些 iptables 的规则。默认转发规则是round robin 或session affinity
kube-proxy 模式:userspace、iptables、ipvs(beta)

当创建一个service后,service会后iptables添加如下规则,以上面创建的httpd-deployment service为例,它的cluster-ip为10.43.129.201
cluster-ip转发流程
在集群任意一台节点上查看iptables规则
1 | iptables-save >/tmp/1 |
1 | -A KUBE-SERVICES -d 10.43.129.201/32 -p tcp -m comment --comment "default/httpd-deployment: cluster IP" -m tcp --dport 80 -j KUBE-SVC-KO6WMUDK3F2YFERC |
第一条规则目的ip是cluster-ip,命中规则,然后将请求丢给KUBE-SVC-KO6WMUDK3F2YFERC处理
第二条规则链KUBE-SVC-KO6WMUDK3F2YFERC 实现了将报文按50%的统计概率随机匹配,转给KUBE-SEP-37DWITJLRCDPHWZD
第三条和第五条是指对pod的SNAT操作
第四条和第六条KUBE-SEP-37DWITJLRCDPHWZD链直接进行DNAT操作将cluster-ip的80端口映射到pod的80
NodePort转发流程
修改Service类型为NodePort

查看iptables
1 | -A KUBE-NODEPORTS -p tcp -m comment --comment "default/httpd-deployment:" -m tcp --dport 30080 -j KUBE-SVC-KO6WMUDK3F2YFERC |
第一条规则目的端口味30080的请求转发给KUBE-SVC-KO6WMUDK3F2YFERC处理
第二条规则将请求给cluster-ip10.43.129.201然后转发给KUBE-SVC-KO6WMUDK3F2YFERC
后面就根上面的cluster-ip转发流程是一样的了,所以NodePort就是在cluster-ip转发基础上加了层DNAT到cluster-ip
服务发现
两种方式
环境变量
DNS:1.10版之前是通过kube-dns实现服务发现,1.10版后可以用CoreDns替代kube-dns做服务发现
创建一个Service后,kubernetes会自动将servername做为服务名,添加一条dns记录
比如上面那个例子Service名为httpd-deployment,那么其他pod要访问直接访问httpd-deployment就会解析到对应cluster-ip,跨namespace的只需要在域名后接上.namespace_name 如httpd-deployment.default