Kubernetes 服務提供穩定的網路介面,讓後端 Pod 可被統一存取,並非與 Deployment 一對一繫結,而是透過標籤選擇器動態連線 Pod,支援藍綠佈署等策略。kube-proxy 透過操作 iptables 規則管理 Service 虛擬 IP 連線,將流量導向後端 Pod。服務探索方面,Kubernetes 主要透過 DNS 解析 Service 名稱,並利用 kube-proxy 設定的 iptables 規則將請求轉發至後端 Pod。此外,環境變數也提供另一種服務探索方式,Kubernetes 會自動注入 Service 相關的環境變數供 Pod 使用。NetworkPolicy 則可控制 Pod 間的網路流量,透過 Ingress 和 Egress 規則限制 Pod 的網路存取許可權,實作微隔離。服務網格則進一步增強了網路管理能力,提供流量管理、可觀察性和安全性等功能,簡化微服務環境中的網路複雜性。
Kubernetes 服務探索與 kube-proxy 的運作原理
在 Kubernetes 叢集中,服務(Service)資源的實作提供了穩定的網路介面,讓後端的多個 Pod 可以被統一管理與存取。許多使用者剛開始接觸 Kubernetes 時,通常會以為 Deployment 與 Service 之間是一對一的關係,但事實上,由於 Service 是透過標籤選擇器(label selector)與 Pod 相連線,因此任何具備相應標籤的 Pod 都會被視為該 Service 的端點。這種設計使得多個 Pod 可以動態地成為某個 Service 的後端,甚至支援像是藍綠佈署(blue/green deployment)或金絲雀發布(canary rollout)等進階佈署策略。
kube-proxy 的運作機制
在 Kubernetes 中,讓 Service 能夠正常運作的核心元件是 kube-proxy。它通常以特權容器(privileged container)的形式執行,負責管理 Service 虛擬 IP 的連線。kube-proxy 最初是以使用者空間代理(userspace proxy)的形式實作,但目前最常見的實作方式是直接操作每台節點上的 iptables 規則。這些 iptables 規則會將目標為 Service IP 的流量重新導向到後端的端點 IP。
檢視 kube-proxy 如何操作 iptables 規則
假設我們已經在叢集中定義了一個名為 kubernetes-dashboard 的 Service,我們可以透過以下指令檢視其相關設定:
$ kubectl get svc -n kube-system kubernetes-dashboard
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes-dashboard ClusterIP 10.104.154.139 <none> 443/TCP 40d
$ kubectl get ep -n kube-system kubernetes-dashboard
NAME ENDPOINTS AGE
kubernetes-dashboard 192.168.63.200:8443,192.168.63.201:8443 40d
接著,我們可以檢視 kube-proxy 在節點上設定的 iptables 規則:
$ sudo iptables-save | grep KUBE | grep "kubernetes-dashboard"
-A KUBE-SEP-3HWS5OGCGRHMJ23K -s 192.168.63.201/32 -m comment --comment "kube-system/kubernetes-dashboard:" -j KUBE-MARK-MASQ
-A KUBE-SEP-3HWS5OGCGRHMJ23K -p tcp -m comment --comment "kube-system/kubernetes-dashboard:" -m tcp -j DNAT --to-destination 192.168.63.201:8443
-A KUBE-SEP-XWHZMKM53W55IFOX -s 192.168.63.200/32 -m comment --comment "kube-system/kubernetes-dashboard:" -j KUBE-MARK-MASQ
-A KUBE-SEP-XWHZMKM53W55IFOX -p tcp -m comment --comment "kube-system/kubernetes-dashboard:" -m tcp -j DNAT --to-destination 192.168.63.200:8443
-A KUBE-SERVICES ! -s 192.168.0.0/16 -d 10.104.154.139/32 -p tcp -m comment --comment "kube-system/kubernetes-dashboard: cluster IP" -m tcp --dport 443 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.104.154.139/32 -p tcp -m comment --comment "kube-system/kubernetes-dashboard: cluster IP" -m tcp --dport 443 -j KUBE-SVC-XGLOHA7QRQ3V22RZ
-A KUBE-SVC-XGLOHA7QRQ3V22RZ -m comment --comment "kube-system/kubernetes-dashboard:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-XWHZMKM53W55IFOX
-A KUBE-SVC-XGLOHA7QRQ3V22RZ -m comment --comment "kube-system/kubernetes-dashboard:" -j KUBE-SEP-3HWS5OGCGRHMJ23K
iptables 規則解析
這些 iptables 規則的作用是將目標為 kubernetes-dashboard Service 的 ClusterIP(10.104.154.139)的流量,隨機導向到後端兩個 Pod 端點(192.168.63.200:8443 和 192.168.63.201:8443)。這樣一來,每個節點上的 Pod 都可以透過 kube-proxy 組態的 iptables 規則來存取定義好的 Service。
#### 內容解密:
- iptables規則的作用:這些規則是由kube-proxy動態生成的,用於實作Service的負載平衡。
- DNAT的作用:DNAT(Destination Network Address Translation)用於修改封包的目的IP地址和埠,將流量導向後端Pod。
- 隨機分配流量:透過statistic模組的random模式,將流量隨機分配到不同的後端Pod,實作負載平衡。
- KUBE-MARK-MASQ的作用:該規則用於標記需要進行SNAT(Source Network Address Translation)的封包,以確保回包能夠正確傳回。
Kubernetes 中的服務探索
在動態排程的環境中,服務探索(Service Discovery)是至關重要的。Kubernetes 中最常見的服務探索方式是透過 DNS。Kubernetes 本身並不包含 DNS 控制器,但社群維護了像是 kube-dns 和 CoreDNS 等附加元件,用於為 Service 資源提供 DNS 解析。
DNS 在 Kubernetes 中的應用
在 Kubernetes 中,DNS 是預設的服務探索機制。當我們建立一個 Service 時,相關的 DNS 紀錄會被自動建立,讓其他 Pod 可以透過 DNS 名稱來存取該 Service。
Kubernetes Service 與 kube-proxy 的運作流程
此圖示說明瞭 Kubernetes 中 Client Pod 如何透過 DNS 解析 Service 名稱,並經由 kube-proxy 組態的 iptables 規則,將請求轉發到後端的 Pod,最終傳回回應給客戶端。
Kubernetes 網路策略與服務探索
Kubernetes 提供多種網路管理與服務探索機制,包括 DNS、環境變數及網路策略(NetworkPolicy)。這些功能使叢集內的服務能夠互相通訊,並確保網路安全。
服務探索機制
DNS 服務發現
Kubernetes 使用 DNS 作為主要的服務探索機制。叢集內的每個 Service 在建立時都會被分配一個 DNS A 記錄,格式為 <service-name>.<namespace>.svc.cluster.local>。例如:
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 35d
# kubectl run --image=alpine dns-test -it -- /bin/sh
/ # nslookup kubernetes
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: kubernetes.default.svc.cluster.local
Address: 10.96.0.1
對於無頭服務(Headless Services),DNS 解析會傳回後端 Pod 的 IP 地址:
/ # nslookup kube-headless
Name: kube-headless
Address 1: 192.168.136.154 ip-192-168-136-154.ec2.internal
Address 2: 192.168.241.42 ip-192-168-241-42.ec2.internal
環境變數服務發現
除了 DNS,Kubernetes 還支援透過環境變數進行服務探索。當 Pod 啟動時,Kubernetes 會自動注入與該名稱空間內 Service 相關的環境變數:
# kubectl get svc test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
test ClusterIP 10.102.163.244 <none> 8080/TCP 9m
# 環境變數範例
TEST_SERVICE_HOST=10.102.163.244
TEST_SERVICE_PORT=8080
TEST_PORT=tcp://10.102.163.244:8080
程式碼解析:環境變數注入機制
import os
def get_service_address():
host = os.getenv('TEST_SERVICE_HOST')
port = os.getenv('TEST_SERVICE_PORT')
return f"http://{host}:{port}"
print(get_service_address())
內容解密:
os.getenv()用於取得環境變數的值。TEST_SERVICE_HOST和TEST_SERVICE_PORT是 Kubernetes 自動注入的環境變數,分別代表 Service 的 IP 和埠。- 該程式碼片段展示瞭如何在應用程式中動態取得 Service 的連線資訊。
網路策略(NetworkPolicy)
網路策略用於控制 Pod 之間的網路流量,提供微隔離功能。透過定義 Ingress 和 Egress 規則,可以限制特定 Pod 的網路存取許可權。
網路策略範例
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: api-backend
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
project: api-midtier
- podSelector:
matchLabels:
role: api-management
ports:
- protocol: TCP
port: 3306
egress:
- to:
- ipBlock:
cidr: 10.3.4.5/32
ports:
- protocol: TCP
port: 22
網路策略流程圖
此圖示展示了網路策略的執行流程,包括入口(Ingress)和出口(Egress)規則的比對過程。
網路策略關鍵概念解析
- podSelector:定義該網路策略適用的 Pod 範圍。
- policyTypes:指定該策略包含的規則型別(Ingress 或 Egress)。
- ingress:定義允許進入 Pod 的流量來源。
- egress:定義允許從 Pod 發出的流量目標。
Kubernetes 網路策略與服務網格
在 Kubernetes 中,網路策略(NetworkPolicy)用於控制 Pod 之間的流量。預設情況下,Kubernetes 沒有任何網路限制,但透過 NetworkPolicy,可以開始鎖定 Pod 之間的互連性。
網路策略範例
以下是一個簡單的 NetworkPolicy 範例,限制對特定 Pod 的存取:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-allow
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
role: api-management
- ports:
- 3306
egress:
- to:
- ipBlock:
cidr: 10.3.4.5/32
- ports:
- 22
內容解密:
podSelector指定了此 NetworkPolicy 作用的 Pod,範例中選擇了標籤role: db的 Pod。policyTypes定義了此策略適用的流量型別,包括入口(Ingress)和出口(Egress)流量。ingress部分定義了允許進入 Pod 的流量來源,本例中允許來自標籤role: api-management的 Pod 對 3306 連線埠的存取。egress部分定義了允許從 Pod 出去的流量目的地,本例中允許到達10.3.4.5的 SSH 伺服器。
服務網格
在微服務環境中,流量可能會透過 Ingress、Service 和多個 Pod 複本進行流轉。這使得流量追蹤變得複雜,而服務網格(Service Mesh)解決方案可以幫助解決這個問題。
服務網格是一組「智慧」代理,能夠幫助使用者處理東西向(Pod-to-Pod)網路需求。這些代理可以作為 sidecar 容器執行在應用程式 Pod 中,也可以作為 DaemonSets 執行,提供節點本地的基礎設施元件。
服務網格的主要功能:
- 流量管理:可以實作高階的流量控制模式,如 canary 和 blue/green 佈署。
- 可觀察性:提供分散式追蹤機制,幫助除錯連線問題和識別慢速應用程式。
- 安全性:在基礎網路不提供預設加密的情況下,提供相互 TLS(Transport Layer Security)加密所有東西向流量。
常見的服務網格解決方案
常見的服務網格解決方案包括 Istio、Linkerd 和 Conduit。這些專案提供了上述功能,並且可以根據具體需求進行選擇。
Kubernetes 監控
設定或使用來自公共雲供應商的 Kubernetes 叢集固然重要,但若沒有正確的策略來監控指標和日誌,並在出現問題時發出適當的警示,那麼所建立的叢集就如同埋下了災難的定時炸彈。
監控目標
監控的主要目標是確保叢集和應用程式的可靠性。例如,若控制器管理器(二進位制檔案)停止正常運作,服務發現將開始慢慢過時。現有的服務已經正確傳播到叢集中的 DNS 伺服器,但新的服務或因滾動更新或擴充套件操作而更改的服務,將無法更新其 DNS。
主要監控目標:
- 可靠性:確保叢集和應用程式的穩定運作。
- 效能:監控叢集和應用程式的效能指標。
- 日誌管理:收集、儲存和分析日誌,以便於故障排除和安全稽核。
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Kubernetes服務探索與網路策略詳解
package "Kubernetes Cluster" {
package "Control Plane" {
component [API Server] as api
component [Controller Manager] as cm
component [Scheduler] as sched
database [etcd] as etcd
}
package "Worker Nodes" {
component [Kubelet] as kubelet
component [Kube-proxy] as proxy
package "Pods" {
component [Container 1] as c1
component [Container 2] as c2
}
}
}
api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2
note right of api
核心 API 入口
所有操作經由此處
end note
@enduml
此圖示顯示了流量從 Ingress 經過 Service 到達多個 Pod 的流程,並展示了 Service Mesh 在其中扮演的角色。
圖示說明:
- Ingress 負責接收外部流量並將其導向 Service。
- Service 將流量分配給後端的 Pod(如 Pod1 和 Pod2)。
- Pod1 和 Pod2 可能會透過 Service Mesh 與其他 Pod(如 Pod3)進行通訊。