← 返回上一頁
Kubernetes

實戰 Kubernetes hostNetwork 與 NetworkPolicy:從主機網路到精細化流量管控

本頁目錄

hostNetwork:讓 Pod 直接使用主機網路

在 Kubernetes 中設定 hostNetwork: true,Pod 就會直接使用節點的網路命名空間——共用節點的 IP、Port 和所有網路設定。這在某些場景下很有用(例如網路監控、Ingress Controller),但也帶來一些需要注意的問題。

DNS 策略設定

使用 hostNetwork 後,Pod 預設會繼承主機的 DNS 設定,無法使用 K8s 內部的 Service DNS 解析。解決方法是設定 DNS 策略為 ClusterFirstWithHostNet

spec:
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet

K8s 提供的四種 DNS 策略:

策略 行為
Default 繼承節點的 DNS 設定(hostNetwork 的預設值)
ClusterFirst 優先用 K8s DNS,無法解析的轉給主機 DNS(一般 Pod 預設值)
ClusterFirstWithHostNet 同 ClusterFirst,但明確適用於 hostNetwork Pod
None 完全自訂,透過 spec.dnsConfig 設定

hostNetwork 範例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

hostPort vs NodePort

特性 hostPort NodePort
開放範圍 只在 Pod 所在節點開端口 所有節點都開端口
實作方式 由 portmap CNI 插件透過 iptables NAT 轉發 kube-proxy 在 KUBE-SERVICES 鏈中設定規則
netstat/lsof 可見 否(iptables 轉發,無實際監聽)
iptables 優先順序 在 KUBE-SERVICES 之前 在 KUBE-SERVICES 之中
生產環境建議 不建議使用 視需求使用

生產環境中不建議使用 hostPort,因為它會佔用節點端口且排障困難。

NetworkPolicy:K8s 的網路防火牆

NetworkPolicy 讓你在 IP 位址和端口層面(L3/L4)控制 Pod 的網路流量。它是一種以應用為中心的防火牆規則,定義哪些流量允許進出 Pod。

前提:CNI 插件必須支援

CNI NetworkPolicy 支援
Flannel 不支援(只提供基本網路連通)
Calico 完整支援,功能豐富
Cilium 完整支援,還支援 L7 策略

如果你用 Flannel,NetworkPolicy 定義了也不會生效——這是很常見的踩坑點。

兩種隔離方向

  • Ingress(入站):控制哪些來源可以存取目標 Pod
  • Egress(出站):控制目標 Pod 可以存取哪些目的地

預設情況下,Pod 的出入站都是完全開放的。一旦有任何 NetworkPolicy 選中了某個 Pod,該 Pod 就進入「隔離」狀態——只有策略明確允許的流量才能通過。

NetworkPolicy 範例解析

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

這個策略做了什麼:

方向 規則
適用對象 default namespace 中帶有 role=db 標籤的 Pod
入站允許 以下三類來源存取 TCP 6379:
1. 同 namespace 帶 role=frontend 的 Pod
2. 帶 project=myproject 標籤的 namespace 中所有 Pod
3. IP 範圍 172.17.0.0/16(排除 172.17.1.0/24)
出站允許 只能連線到 10.0.0.0/24 的 TCP 5978

選擇器的 AND vs OR 邏輯

這是 NetworkPolicy 最容易搞混的地方。看兩個例子:

AND 邏輯(同一個清單元素)

from:
- namespaceSelector:
    matchLabels:
      user: alice
  podSelector:
    matchLabels:
      role: client

= namespace 標籤有 user=alice Pod 標籤有 role=client

OR 邏輯(不同的清單元素)

from:
- namespaceSelector:
    matchLabels:
      user: alice
- podSelector:
    matchLabels:
      role: client

= namespace 標籤有 user=alice 的所有 Pod 同 namespace 中標籤有 role=client 的 Pod

差一個破折號,意思完全不同。寫 YAML 時務必特別小心。

重點整理

  • NetworkPolicy 是白名單機制——只有明確允許的才放行,其餘全擋
  • 沒指定 namespaceSelector 時,規則只作用於 NetworkPolicy 所在的 namespace
  • 多個 NetworkPolicy 是相加的,不會互相衝突
  • 入站和出站需要兩端都允許,連線才能建立
  • hostNetwork Pod 使用 ClusterFirstWithHostNet DNS 策略才能解析 K8s 內部 Service 名稱

參考連結

分享這篇
X LinkedIn Facebook Hacker News Reddit

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料