1.Service 背景
問題1:為什么需要服務(wù)發(fā)現(xiàn)
① 容器 Pod 生命周期短暫,容器 IP 地址隨時變化
② Deployment 中的 Pod 組需要統(tǒng)一的訪問入口和負載均衡
③ 應(yīng)用在不同部署環(huán)境需要統(tǒng)一部拓撲和訪問方式
問題2:如何提供外部訪問和負載均衡的能力
Kubernetes Service 具備服務(wù)發(fā)現(xiàn)和負載均衡的功能坐求,即一方面提供了統(tǒng)一的訪問入口蚕泽,另一方面負載均衡到后端 Pod。下圖是 Service 的簡約架構(gòu)圖桥嗤,左側(cè)表示 Service 提供了外部訪問和 Pod 網(wǎng)絡(luò)訪問 须妻,右側(cè)表示對接了一組 Pod,同時把請求負載均衡到這組 Pod泛领。
2.Service 架構(gòu)
① Master 節(jié)點:Kubernetes 管理節(jié)點荒吏,負責(zé)管理和控制整個集群,包含的組件是 APIServer师逸、Controller Manager 和Scheduler司倚。
② Worker 節(jié)點:Kubernetes 工作負載節(jié)點,包含的組件主要有 Kubelet篓像、Kube-proxy动知。
2.1 Service 的關(guān)鍵組件
① APIServer:Kubernetes 所有對象都會注冊到 APIServer上,監(jiān)聽這些對象的變化员辩,例如 Pod盒粮、StatefulSet、Service 等奠滑。
② Controller Manager:負責(zé)配置 LoadBalance 的一個負責(zé)均衡器給外部訪問丹皱。
③ Coredns:負責(zé)把 Service 名字(類似域名)解析為 Service 虛擬 IP 即 ClusterIP,同時觀測 Service 的變化宋税。
④ Kube-proxy:負責(zé)把 Service 虛擬 IP 即 ClusterIP 轉(zhuǎn)換為后端 Pod IP摊崭,同時觀測后端 Pod 的變化。
2.2 訪問鏈路分析
2.2.1 集群內(nèi)部訪問
如上架構(gòu)圖示例杰赛,Client Pod3 訪問 Service 的步驟:
① Coredns 解析出 CluserIP:Client Pod3 拿著 Service name (域名)請求 Coredns呢簸,Coredns 解析域名后返回 ClusterIP。
② Kube-proxy 攔截后負載均衡到后端 Pod:Client Pod3 拿著 ClusterIP 請求宿主機網(wǎng)絡(luò)后乏屯,被 Kube-proxy 所配置的 iptables 攔截了根时,隨后負債均衡轉(zhuǎn)發(fā)到后端 Pod。
2.2.2 集群外部訪問
① LoaderBalancer 轉(zhuǎn)發(fā)請求到某節(jié)點的 NodePort:外部請求通過 LoaderBalancer 轉(zhuǎn)發(fā)到某節(jié)點的 NodePort辰晕,同時 LoaderBalander 通過 Controller Manager 監(jiān)聽 Service 的變化蛤迎。
② Kube-proxy 把 NodePort 轉(zhuǎn)換為 ClusterIP 并轉(zhuǎn)發(fā)到后端 Pod:NodePort 的請求被 Kube-proxy 所配置的 iptables 攔截并轉(zhuǎn)發(fā)到 CluserIP,最終轉(zhuǎn)發(fā)到后端 Pod含友。
3.Service 示例
3.1 創(chuàng)建和查看 Service
# 創(chuàng)建 service
$kubectl apply -f service.yaml
# 查看 service
$kubectl describe service my-service
Name: my-service
Namespace: default
Labels: app=my-service
Selector: app=MyApp
Type: ClusterIP
IP: 172.29.3.27 # Service 虛擬 IP
Port: 80/TCP
TargetPort: 9376/TCP
Endpoints: 192.168.115.236:9376,192.168.115.237:9376,192.168.115.238:9376 # Selector 匹配到的后端 Pod 地址
Session Affinity: None
3.2 集群內(nèi)訪問 Service
3.2.1 ClusterIP 訪問
① 直接使用 ClusterIP
# 查詢 ClusterIP
$kubectl get svc |grep my-service
② 直接使用 Service Name替裆,Codedns 解析
{servicename}.{namespace}.svc.cluster.local
③ 使用環(huán)境變量訪問
MY_SERVICE_PORT_80_TCP_PROTO=tcp
MY_SERVICE_PORT=tcp://172.29.3.27:80
MY_SERVICE_SERVICE_PORT=80
MY_SERVICE_PORT_80_TCP_PORT=80
MY_SERVICE_PORT_80_TCP=tcp://172.29.3.27:80
MY_SERVICE_SERVICE_PORT=80
MY_SERVICE_SERVICE_HOST=172.29.3.27
MY_SERVICE_PORT_80_TCP_ADDR=172.29.3.27
3.2.1 Headless Service
apiVersion: v1
kind: Service
metadata:
name: my-service
label:
app: my-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
selector:
app: myApp
clusterIP: None # 作用是讓 Service 不再通過虛擬 IP 來負載均衡
① 通過 Service Name 可以直接解析到所有后端 Pod IP
② 客戶端可以自主選擇需要訪問的 Pod IP
3.3 集群外訪問 Service
apiVersion: v1
kind: Service
metadata:
name: my-service
label:
app: my-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 30080
selector:
app: myApp
type: NodePort