《深入剖析kubernetes》学习笔记(6)——Service和Ingress
37. Service, DNS和服务发现
-
Service 是由 kube-proxy 组件,加上 iptables 来共同实现的。
-
kubernetes中,service和pod都会被分配DNS名字。
-
service分为两种服务模式:
- 1>ClusterIP模式,service的DNS名字为...svc.cluster.local,根据该记录解析到服务的Virtual IP
- 2>Headless模式,即指定ClusterIP=None,service的DNS名字同上,但根据该记录解析到的是所有被代理的Pod的IP地址集合。(实际使用时,返回一个稳定可用的Pod的IP地址)
-
Service涉及的iptabels规则:
- KUBE-SERVICES或者KUBE-NODEPORTS,对应service的入口
- KUBE-SVC-(hash),负载均衡链,与Endpoints数目一致,probability设置会影响当前规则命中率
- KUBE-SEP-(hash),DNAT链,与Endpoints一一对应
-
DNAT操作:在路由之前,将流入 IP 包的目的地址和端口,改成–to-destination 所指定的新的目的地址和端口,例如:
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.1.7:9376
-
服务发现:pod自身的IP地址是随时会变化的,其数量也会随时增减,这不利于服务方访问POD上的服务,通过创建Service就可以通过单一稳定的访问点(Virtual IP)来访问到Pod,该地址再服务生命周期内保持不变。【服务的VIP是虚拟的,无法ping通】
38. 从外部联通Service的方法
(1) 指定Service类型为NodePort
- 示例:
spec:
type: NodePort
ports:
- nodePort: 8080
targetPort: 80
protocol: TCP
在所有宿主机上打开一个端口8080,将该端口的流量重定向到服务上,再有服务转发到对应Pod的80端口上。
若不显式地声明 nodePort 字段,Kubernetes 就会为你分配随机的可用端口来设置代理。这个端口的范围默认是 30000-32767
- SNAT操作:
client
\ ^
\ \
v \
node 1 <--- node 2
| ^ SNAT
| | --->
v |
endpoint
若实际提供服务的Pod不在客户端访问的宿主机上,则IP包在离开宿主机前进行SNAT操作,即将包的源地址从客户端IP换成了此宿主机IP或者cni0的地址,避免pod在处理完数据后,直接将包返回客户端,造成返回数据的宿主机和客户端发送请求的宿主机不一致,造成客户端报错。
SNAT操作只对Service转发出的包进行,判断的依据是该IP包是否被打上"0x4000"的标记(该标记在DNAT操作之前被打上)。
- 设置请求本地处理:
若将Service 的 spec.externalTrafficPolicy 字段设置为 local,则pod可以看到真正的外部client的地址,原理是,此时iptables规则只会将IP包转发给本宿主机的POD,若此宿主机无相应的pod,则请求会被丢弃。
client
^ / \
/ / \
/ v X
node 1 node 2
^ |
| |
| v
endpoint
(2) 指定Service类型为LoadBalancer
LoadBalancer 类型的 Service 被提交后,Kubernetes 就会调用 CloudProvider 在公有云上为你创建一个负载均衡服务,并且把被代理的 Pod 的 IP 地址配置给负载均衡服务做后端。
(3)指定Service类型为ExternalName
若指定externalName = my.database.example.com,则kube-dns中会添加一条CNAME记录,此时访问
此方法经常用于连接kubernetes集群外部的服务。
(4)为Service分配公有IP
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
expternalIPs:
- 80.11.12.10
此时可以通过访问80.11.12.10:80访问到被代理的pod,但此外部IP必须能够路由到一个Kubernetes节点。
总结
所谓 Service,其实就是 Kubernetes 为 Pod 分配的、固定的、基于 iptables(或者 IPVS)的访问入口。而这些访问入口代理的 Pod 信息,则来自于 Etcd,由 kube-proxy 通过控制循环来维护。
39. Ingress
-
Ingress的必要性:
- 每一个类型为loadBalancer的Service,都会创建一个单独属于该service的负载均衡器,有独立的公有IP,成本高昂。Ingress则可以代理集群所有的service,并提供负载均衡服务。
-
Ingress就是服务的服务。
-
使用流程:
- 部署ingress-controller,一般用ingress-nginx
- 使用nodeport的方式,将ingress-nginx以服务方式暴露出去
- 部署service和ingress
- 访问宿主机上nodeport端口,访问到ingress-controller
- ingress对象访问到service,获得一个endpoint,将请求转发给endpoint
-
一个 Nginx Ingress Controller 为你提供的服务,其实是一个可以根据 Ingress 对象和被代理后端 Service 的变化,来自动进行更新的 Nginx 负载均衡器。
-
每个ingress对象对应一个nginx配置文件和一个nginx服务
-
代码示例
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: cafe-ingress spec: tls: - hosts: - cafe.example.com secretName: cafe-secret rules: - host: cafe.example.com http: paths: - path: /tea backend: serviceName: tea-svc servicePort: 80 - path: /coffee backend: serviceName: coffee-svc servicePort: 80