如何通路pod
kubernetes Pod不可能一直正常運作。而是會出現各種問題導緻發送故障而死掉。Deployment等controller會通過動态建立和銷毀Pod來保證應用整體的健康。
每個 Pod 都有自己的 IP 位址。當 controller 用新 Pod 替代發生故障的 Pod 時,新 Pod 會配置設定到新的 IP 位址。這樣就産生了一個問題:
如果一組 Pod 對外提供服務(比如 HTTP),它們的 IP 很有可能發生變化,那麼用戶端如何找到并通路這個服務呢?
Kubernetes 給出的解決方案是 Service。
建立Service
Kubernetes Service 從邏輯上代表了一組 Pod,具體是哪些 Pod 則是由 label 來挑選。Service 有自己 IP,而且這個 IP 是不變的。用戶端隻需要通路 Service 的 IP,Kubernetes 則負責建立和維護 Service 與 Pod 的映射關系。無論後端 Pod 如何變化,對用戶端不會有任何影響,因為 Service 沒有變。
來看個例子,建立下面的這個 Deployment:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: httpd-deployment
spec:
replicas: 2
template:
metadata:
labels:
name: httpd
spec:
containers:
- name: httpd-app
image: httpd:latest
建立Service檔案
vim httpd-svc.yml
apiVersion: v1
kind: Service
metadata:
name: httpd-svc
spec:
ports:
- port: 8080
targetPort: 80
protocol: TCP
selector:
run: httpd
kubectl get svc 檢視資訊
[[email protected] yaml]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd-svc ClusterIP 10.68.132.230 <none> 8080/TCP 47s
kubernetes ClusterIP 10.68.0.1 <none> 443/TCP 1d
配置設定到一個 CLUSTER-IP 10.68.132.230。可以通過該IP通路後端的httpd Pod
curl 10.68.132.230:8080
根據前面的端口映射,這裡要使用 8080 端口。另外,除了我們建立的 httpd-svc,還有一個 Service kubernetes,Cluster 内部通過這個 Service 通路 kubernetes API Server。
通過 kubectl describe 可以檢視 httpd-svc 與 Pod 的對應關系。
kubectl describe service httpd-svc
kubectl get pod -o wide
Service IP 原理:
Service Cluster IP 是一個虛拟 IP,是由 Kubernetes 節點上的 iptables 規則管理的。
可以通過 iptables-save 指令列印出目前節點的 iptables 規則,因為輸出較多,這裡隻截取與 httpd-svc Cluster IP 10.68.132.230 相關的資訊:

這條規則的含義是:
如果 Cluster 内的 Pod要通路 httpd-svc,跳轉到規則 KUBE-SVC-RL3JAE4GN7VOGDGP
KUBE-SVC-RL3JAE4GN7VOGDGP 規則如下:
- 1/2的機率跳轉到規則 KUBE-SEP-GSULT7CRYYSEJLVK。
- 1/2 的機率(剩下 2/3 的一半)跳轉到規則 KUBE-SEP-VYMFHNMHVUQT37BD。
上面兩個跳轉的規則如下:
即将請求分别轉發到後端的兩個 Pod。通過上面的分析,我們得到如下結論:
iptables 将通路 Service 的流量轉發到後端 Pod,而且使用類似輪詢的負載均衡政策。
另外需要補充一點:Cluster 的每一個節點都配置了相同的 iptables 規則,這樣就確定了整個 Cluster 都能夠通過 Service 的 Cluster IP 通路 Service。
DNS通路service
在 Cluster 中,除了可以通過 Cluster IP 通路 Service,Kubernetes 還提供了更為友善的 DNS 通路。
dns元件
kubeadm 部署時會預設安裝 kube-dns 元件。
coredns 是一個 DNS 伺服器。每當有新的 Service 被建立,coredns 會添加該 Service 的 DNS 記錄。Cluster 中的 Pod 可以通過 <SERVICE_NAME>.<NAMESPACE_NAME> 通路 Service。
比如可以用 httpd-svc.default 通路 Service httpd-svc。
kubectl run busybox --rm -ti --image=reg.yunwei.edu/learn/busybox:latest /bin/sh
wget httpd-svc:8080
外網通路 Service:
外網如何通路 Service?
除了 Cluster 内部可以通路 Service,很多情況我們也希望應用的 Service 能夠暴露給 Cluster 外部。Kubernetes 提供了多種類型的 Service,預設是 ClusterIP。
ClusterIP
Service 通過 Cluster 内部的 IP 對外提供服務,隻有 Cluster 内的節點和 Pod 可通路,這是預設的 Service 類型,前面實驗中的 Service 都是 ClusterIP。
NodePort
Service 通過 Cluster 節點的靜态端口對外提供服務。Cluster 外部可以通過 : 通路 Service。
LoadBalancer
Service 利用 cloud provider 特有的 load balancer 對外提供服務,cloud provider 負責将 load balancer 的流量導向 Service。目前支援的 cloud provider 有 GCP、AWS、Azur 等。
下面我們來實踐 NodePort,Service httpd-svc 的配置檔案修改如下:
添加 type: NodePort,重新建立 httpd-svc。
Kubernetes 依然會為 httpd-svc 配置設定一個 ClusterIP,不同的是:
- EXTERNAL-IP 為 none,表示可通過 Cluster 每個節點自身的 IP 通路 Service。
-
PORT(S) 為 8080:26044。8080 是 ClusterIP 監聽的端口,26044
則是節點上監聽的端口。Kubernetes 會從 30000-32767 中配置設定一個可用的端口,每個節點都會監聽此端口并将請求轉發給
Service。
K8s通路pod建立ServiceDNS通路service外網通路 Service:
下面測試 NodePort 是否正常工作。
通過兩個節點 IP + 26044 端口都能夠通路 httpd-svc。
NodePort 預設是的随機選擇,不過我們可以用 nodePort 指定某個特定端口。
現在配置檔案中就有三個 Port 了:
nodePort 是節點上監聽的端口。
port 是 ClusterIP 上監聽的端口。
targetPort 是 Pod 監聽的端口。
注:Pod和service可以都寫到了一個編排檔案裡面:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: httpd-deployment
spec:
replicas: 3
template:
metadata:
labels:
name: httpd
run: httpd
spec:
containers:
- name: httpd-app
image: httpd:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: httpd-svc
spec:
type: NodePort
ports:
- port: 8080
targetPort: 80
protocol: TCP
nodePort: 26055
selector:
run: httpd