前言 在上一篇文章中,我們學習了 Service 的基本概念和四種類型。本篇將更深入地探討 Kubernetes 的網路模型,包括:
服務發現 :Pod 如何找到其他服務?
Ingress :如何將外部流量路由到叢集內部?
網路策略 :如何控制 Pod 之間的網路通訊?
理解這些概念,你就能設計出安全、高效的 K8s 網路架構。
Kubernetes 網路模型 核心原則 K8s 網路模型基於幾個基本原則:
每個 Pod 有唯一 IP :Pod 不共享 IP,簡化通訊模型
Pod 之間可直接通訊 :無需 NAT,任何 Pod 可直接連線到任何其他 Pod
節點與 Pod 可直接通訊 :節點上的程式可直接連線 Pod
Pod 看到的 IP 與其他人看到的相同 :沒有隱藏的 NAT
graph TD
subgraph "Node 1 (10.0.1.1)"
P1[Pod A<br/>10.244.1.5]
P2[Pod B<br/>10.244.1.8]
end
subgraph "Node 2 (10.0.1.2)"
P3[Pod C<br/>10.244.2.3]
P4[Pod D<br/>10.244.2.7]
end
P1 <-->|直接通訊| P3
P2 <-->|直接通訊| P4
P1 <-->|同節點| P2
CNI(Container Network Interface) CNI 是 K8s 網路的插件標準,常見的 CNI 實現:
CNI 插件
特點
適用場景
Calico
性能優異、支援網路策略
生產環境首選
Flannel
簡單易用
入門學習、小型叢集
Cilium
基於 eBPF、功能強大
高度可觀測性需求
Weave
多叢集支援
跨雲環境
服務發現機制 DNS 服務發現 K8s 內建 CoreDNS 提供 DNS 服務發現,這是最推薦的方式。
graph LR
POD[Pod] -->|DNS 查詢| DNS[CoreDNS]
DNS -->|返回 ClusterIP| POD
POD -->|連線| SVC[Service]
SVC -->|負載均衡| P1[Pod 1]
SVC --> P2[Pod 2]
DNS 命名規則 1 2 3 4 5 6 7 8 9 <service-name>.<namespace>.svc.cluster.local nginx-service.default.svc.cluster.local nginx-service nginx-service.default
DNS 查詢實驗 1 2 3 4 5 6 7 8 9 10 11 12 kubectl run debug --image=busybox --rm -it -- /bin/sh nslookup kubernetes nslookup nginx-service.default.svc.cluster.local
環境變數發現 K8s 也會自動注入 Service 相關的環境變數到 Pod 中:
1 2 3 4 5 6 7 {SERVICE_NAME}_SERVICE_HOST {SERVICE_NAME}_SERVICE_PORT echo $NGINX_SERVICE_SERVICE_HOST echo $NGINX_SERVICE_SERVICE_PORT
注意 :環境變數方式有順序依賴(Service 必須在 Pod 前創建),DNS 方式沒有這個限制,推薦使用 DNS。
Ingress:外部流量入口 為什麼需要 Ingress?
方式
問題
NodePort
每個服務需要一個端口,管理複雜
LoadBalancer
每個服務需要一個 LB,成本高昂
Ingress
一個入口管理多個服務,支援路由規則
graph TD
USER[使用者] -->|HTTPS| ING[Ingress Controller]
ING -->|/api| API[API Service]
ING -->|/web| WEB[Web Service]
ING -->|/admin| ADMIN[Admin Service]
API --> AP1[API Pod 1]
API --> AP2[API Pod 2]
WEB --> WP1[Web Pod 1]
WEB --> WP2[Web Pod 2]
ADMIN --> ADP1[Admin Pod]
Ingress 與 Ingress Controller Ingress 是一種 K8s 資源,定義外部存取規則。Ingress Controller 是實際處理流量的組件,需要單獨安裝。
常見的 Ingress Controller:
Controller
特點
Nginx Ingress
最廣泛使用,功能豐富
Traefik
配置簡單,自動服務發現
Kong
豐富的 API 閘道功能
AWS ALB
AWS 原生整合
安裝 Nginx Ingress Controller 1 2 3 4 5 6 7 8 9 10 helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update helm install ingress-nginx ingress-nginx/ingress-nginx minikube addons enable ingress kubectl get pods -n ingress-nginx
Ingress 配置詳解 基於路徑的路由 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: path-based-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules: - host: myapp.example.com http: paths: - path: /api pathType: Prefix backend: service: name: api-service port: number: 80 - path: /web pathType: Prefix backend: service: name: web-service port: number: 80
基於主機的路由 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: host-based-ingress spec: ingressClassName: nginx rules: - host: api.example.com http: paths: - path: / pathType: Prefix backend: service: name: api-service port: number: 80 - host: web.example.com http: paths: - path: / pathType: Prefix backend: service: name: web-service port: number: 80
配置 TLS/HTTPS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: tls-ingress annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" spec: ingressClassName: nginx tls: - hosts: - secure.example.com secretName: tls-secret rules: - host: secure.example.com http: paths: - path: / pathType: Prefix backend: service: name: secure-service port: number: 443
1 2 3 4 kubectl create secret tls tls-secret \ --cert=path/to/cert.pem \ --key=path/to/key.pem
常用 Nginx Ingress 註解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: /$1 nginx.ingress.kubernetes.io/proxy-body-size: "10m" nginx.ingress.kubernetes.io/proxy-connect-timeout: "60" nginx.ingress.kubernetes.io/proxy-read-timeout: "60" nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/limit-rps: "10" nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/8,172.16.0.0/12" nginx.ingress.kubernetes.io/proxy-http-version: "1.1" nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"
網路策略(Network Policy) 為什麼需要網路策略? 預設情況下,K8s 叢集中的所有 Pod 可以互相通訊。這在安全敏感的環境中可能造成風險。
網路策略 允許你定義 Pod 之間的通訊規則。
graph LR
subgraph "前端"
FE[Frontend Pod]
end
subgraph "後端"
BE[Backend Pod]
end
subgraph "資料庫"
DB[(Database Pod)]
end
FE -->|允許| BE
BE -->|允許| DB
FE -.->|阻擋| DB
網路策略範例 拒絕所有入站流量 1 2 3 4 5 6 7 8 9 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-ingress spec: podSelector: {} policyTypes: - Ingress
只允許特定 Pod 存取 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-frontend-to-backend spec: podSelector: matchLabels: app: backend policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: frontend ports: - protocol: TCP port: 8080
只允許同一 Namespace 內通訊 1 2 3 4 5 6 7 8 9 10 11 12 13 14 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-same-namespace namespace: production spec: podSelector: {} policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: name: production
允許特定 IP 段 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-external-ip spec: podSelector: matchLabels: app: api policyTypes: - Ingress ingress: - from: - ipBlock: cidr: 10.0 .0 .0 /8 except: - 10.0 .1 .0 /24 ports: - protocol: TCP port: 443
網路策略最佳實踐
預設拒絕 :先設定拒絕所有,再開放必要的通訊
最小權限 :只開放必要的端口和來源
分層防護 :前端 → 後端 → 資料庫,逐層限制
Namespace 隔離 :不同環境(dev/prod)使用不同 Namespace
負載均衡策略 Service 負載均衡 K8s Service 預設使用 輪詢(Round Robin) 進行負載均衡。
graph LR
SVC[Service] -->|請求 1| P1[Pod 1]
SVC -->|請求 2| P2[Pod 2]
SVC -->|請求 3| P3[Pod 3]
SVC -->|請求 4| P1
Session Affinity(會話親和性) 如果需要將同一客戶端的請求路由到同一 Pod:
1 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: v1 kind: Service metadata: name: sticky-service spec: selector: app: my-app ports: - port: 80 sessionAffinity: ClientIP sessionAffinityConfig: clientIP: timeoutSeconds: 3600
實戰範例:完整網路配置 應用架構 graph TD
USER[使用者] -->|HTTPS| ING[Ingress]
ING -->|/api| APISVC[API Service]
ING -->|/| WEBSVC[Web Service]
APISVC --> API1[API Pod 1]
APISVC --> API2[API Pod 2]
WEBSVC --> WEB1[Web Pod 1]
WEBSVC --> WEB2[Web Pod 2]
API1 --> DBSVC[DB Service]
API2 --> DBSVC
DBSVC --> DB[(Database)]
完整配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 apiVersion: v1 kind: Namespace metadata: name: myapp labels: name: myapp --- apiVersion: apps/v1 kind: Deployment metadata: name: database namespace: myapp spec: replicas: 1 selector: matchLabels: app: database template: metadata: labels: app: database spec: containers: - name: postgres image: postgres:15-alpine ports: - containerPort: 5432 env: - name: POSTGRES_PASSWORD value: secretpassword --- apiVersion: v1 kind: Service metadata: name: database namespace: myapp spec: selector: app: database ports: - port: 5432 --- apiVersion: apps/v1 kind: Deployment metadata: name: api namespace: myapp spec: replicas: 2 selector: matchLabels: app: api template: metadata: labels: app: api spec: containers: - name: api image: my-api:latest ports: - containerPort: 8080 env: - name: DATABASE_URL value: postgres://postgres:secretpassword@database:5432/mydb --- apiVersion: v1 kind: Service metadata: name: api namespace: myapp spec: selector: app: api ports: - port: 80 targetPort: 8080 --- apiVersion: apps/v1 kind: Deployment metadata: name: web namespace: myapp spec: replicas: 2 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: web image: nginx:alpine ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: web namespace: myapp spec: selector: app: web ports: - port: 80 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: myapp-ingress namespace: myapp annotations: nginx.ingress.kubernetes.io/ssl-redirect: "false" spec: ingressClassName: nginx rules: - host: myapp.local http: paths: - path: /api pathType: Prefix backend: service: name: api port: number: 80 - path: / pathType: Prefix backend: service: name: web port: number: 80 --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny namespace: myapp spec: podSelector: {} policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-ingress namespace: myapp spec: podSelector: matchLabels: app: web policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: name: ingress-nginx ports: - port: 80 --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-api-to-db namespace: myapp spec: podSelector: matchLabels: app: database policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: api ports: - port: 5432
本章重點回顧 網路模型
每個 Pod 有唯一 IP
Pod 之間可直接通訊
CNI 負責實現網路
服務發現
DNS 優先 :使用 <service>.<namespace>.svc.cluster.local
CoreDNS :K8s 內建 DNS 服務
Ingress
統一入口 :一個 Ingress 管理多個 Service
需要 Controller :Nginx Ingress 最常用
支援 TLS :配置 HTTPS 憑證
網路策略
預設全通 :需要主動設定限制
白名單模式 :先拒絕所有,再開放必要
分層防護 :按應用層級設定策略
下一篇預告 在下一篇文章中,我們將探討 配置與存儲 :
ConfigMap 配置管理
Secret 密鑰管理
Volume 類型與使用場景
PersistentVolume 與 PersistentVolumeClaim
系列文章導覽
Part 1:入門篇 - 認識 K8s 與核心架構
Part 2:基礎篇 - Pod、Deployment 與 Service
Part 3:網路篇 - 服務發現與流量管理 (本篇)
Part 4:配置與存儲篇 - ConfigMap、Secret 與 Volume
Part 5:進階篇 - 資源管理與自動擴展
Part 6:實戰篇 - 部署完整微服務應用
參考資源