Kubernetes 網路管理涉及多個關鍵元件,理解它們之間的互動至關重要。本文首先介紹網路策略的最佳實踐和服務型別,接著探討服務與網路策略如何協同工作,確保叢集內部通訊安全。更進一步,文章分析了 Ingress 和 Egress 的不同型別與實作方式,以及如何利用它們管理叢集的進出流量。最後,文章深入 eBPF 技術及其在 Calico 中的應用,特別是 Calico eBPF 資料平面如何提升網路效能和安全性。這些技術的整合運用,能有效提升 Kubernetes 叢集的網路效能、安全性和可管理性。
Kubernetes 網路策略與服務深度解析
Kubernetes 的網路策略(Network Policy)與服務(Services)是確保叢集內部通訊安全與高效的關鍵元件。本篇文章將探討網路策略的最佳實踐、服務型別及其應用,以及服務與網路策略之間的互動關係。
網路策略最佳實踐
網路策略是 Kubernetes 中用於控制 Pod 之間通訊的規則。最佳實踐建議為每個 Pod 設定入口(Ingress)和出口(Egress)規則,以限制允許連線的來源和目標。
預設拒絕策略
實施預設拒絕(Default Deny)網路策略可確保未明確允許的流量將被拒絕。這種方法強制團隊在佈署新 Pod 時定義相應的網路策略。
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: default-app-policy
spec:
namespaceSelector: has(projectcalico.org/name) && projectcalico.org/name not in {"kube-system", "calico-system"}
types:
- Ingress
- Egress
egress:
- action: Allow
protocol: UDP
destination:
selector: k8s-app == "kube-dns"
ports:
- 53
內容解密:
此範例使用 Calico 的 GlobalNetworkPolicy 對非系統名稱空間中的 Pod 實施預設拒絕策略,但允許對 kube-dns 的 DNS 查詢。
namespaceSelector:選擇具有特定標籤的名稱空間。egress:定義出口規則,允許對 kube-dns 的 UDP 53 連線埠進行 DNS 查詢。action: Allow:明確允許符合條件的流量。
Kubernetes 服務型別
Kubernetes 服務提供了將一組 Pod 抽象為網路服務的方法。主要有三種型別:ClusterIP、NodePort 和 LoadBalancer。
ClusterIP 服務
ClusterIP 是預設的服務型別,允許在叢集內透過虛擬 IP 位址(Cluster IP)存取服務。服務的 DNS 名稱和 Cluster IP 在服務生命週期內保持不變。
NodePort 服務
NodePort 是最基本的從叢集外部存取服務的方式。它在每個節點上保留一個連線埠,用於存取服務。kube-proxy 負責攔截到 NodePort 的連線並進行負載平衡。
服務與網路策略的互動
網路策略是根據 Pod 而非服務的 Cluster IP 來執行的。對於客戶端 Pod,出口網路策略在 DNAT(目標網路位址轉換)後生效,將連線的目的地 IP 改為所選的服務後端 Pod。入口網路策略對於後端 Pod 而言,看到的來源是原始客戶端 Pod。
圖表說明:Kubernetes 服務與網路策略互動關係
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333
title 圖表說明:Kubernetes 服務與網路策略互動關係
rectangle "存取服務" as node1
rectangle "負載平衡" as node2
rectangle "控制流量" as node3
node1 --> node2
node2 --> node3
@enduml此圖示展示了客戶端 Pod 如何透過 Cluster IP 存取服務,以及網路策略如何控制進出這些 Pod 的流量。
Kubernetes 服務與 Ingress 深入解析
Kubernetes 中的服務(Services)與 Ingress 是兩個重要的網路資源,它們使得應用程式能夠被內外部使用者存取。本章節將探討 Kubernetes Services 的不同型別、如何使用 LoadBalancer 服務、以及 Kubernetes Ingress 的功能和實作原理。
Kubernetes Services 的型別與運作原理
Kubernetes Services 提供了一種抽象的方式來暴露應用程式的網路介面。它支援多種服務型別,包括 ClusterIP、NodePort、LoadBalancer 等。其中,LoadBalancer 型別的服務透過外部網路負載平衡器(NLB)來暴露服務。
LoadBalancer 服務的運作方式
LoadBalancer 服務依賴於公有雲供應商或本地硬體負載平衡器的整合。客戶端可以透過負載平衡器的特定 IP 位址來存取服務。預設情況下,負載平衡器會平均分配流量到後端的節點上。然而,由於流量會經過節點的埠,因此後端的 Pod 無法直接看到客戶端的原始 IP 位址。這對於網路政策的實施有一定影響。
程式碼範例:LoadBalancer 服務設定
apiVersion: v1
kind: Service
metadata:
name: example-service
spec:
selector:
app: example-app
ports:
- name: http
port: 80
targetPort: 8080
type: LoadBalancer
內容解密:
apiVersion和kind定義了 Kubernetes 資源的版本和型別。metadata包含了服務的名稱等資訊。spec.selector指定了服務所對應的 Pod 標籤。spec.ports定義了服務的埠和目標埠的對映關係。spec.type設定為LoadBalancer表示使用負載平衡器暴露服務。
使用 externalTrafficPolicy 最佳化流量路由
預設情況下,Kubernetes 服務會將流量平均分配到所有後端 Pod,無論這些 Pod 是否位於同一節點上。透過設定 externalTrafficPolicy: Local,可以將流量只路由到本地節點上的 Pod。這樣可以減少跨節點的網路跳躍,並保持客戶端的原始 IP 位址,從而使得網路政策能夠根據客戶端 IP 進行存取控制。
程式碼範例:externalTrafficPolicy 設定
apiVersion: v1
kind: Service
metadata:
name: example-service
spec:
selector:
app: example-app
ports:
- name: http
port: 80
targetPort: 8080
type: LoadBalancer
externalTrafficPolicy: Local
內容解密:
externalTrafficPolicy: Local設定使得流量只被路由到具有後端 Pod 的本地節點。
Calico eBPF原生服務處理
Calico 的 eBPF 資料平面支援原生服務處理,可以保留客戶端的原始 IP 位址,簡化網路政策的實施。它還提供了直接伺服器傳回(DSR)功能,減少了傳回流量的網路跳躍次數,並提供了與拓撲結構無關的負載平衡,從而降低了 CPU 使用率和延遲。
Kubernetes Ingress 的作用與實作
Kubernetes Ingress 建構在 Kubernetes Services 之上,提供應用層的負載平衡,將特定的網域名稱或 URL 路徑對映到 Kubernetes 服務。Ingress 可以終止 SSL/TLS 連線,並將請求負載平衡到後端的服務。
Ingress 的實作依賴於 Ingress Controller,它負責監控 Kubernetes Ingress 資源並組態相應的負載平衡器。與 Kubernetes Services 不同,Ingress 工作在應用層(L5-7),因此可以檢查 HTTP/HTTPS 請求並根據請求內容進行路由。
為什麼使用 Kubernetes Ingress?
主要的使用場景是當有多個 HTTP/HTTPS 服務需要透過單一外部 IP 位址暴露時,使用 Ingress 可以簡化客戶端的組態。如果應用架構已經有一個前端微服務,那麼可能不需要額外使用 Ingress,因為前端微服務已經扮演了類別似 Ingress 的角色。
Kubernetes Ingress 與 Egress 深度解析
Kubernetes 的 Ingress 和 Egress 是兩個關鍵概念,分別掌控著叢集內外部的流量管理。Ingress 負責處理進入叢集的流量,而 Egress 則關注從叢集出去的流量。
Ingress 型別與實作
Ingress 解決方案大致可分為兩類別:叢集內 Ingress 和 外部 Ingress。
叢集內 Ingress 解決方案
叢集內 Ingress 解決方案利用在叢集內執行的軟體負載平衡器,例如 NGINX Ingress Controller。這種方法的優點包括:
- 可以水平擴充套件 Ingress 解決方案,以滿足 Kubernetes 的需求
- 可以根據特定的需求選擇合適的 Ingress Controller,例如特定的負載平衡演算法或安全選項
要將 Ingress 流量引導至叢集內的 Ingress Pod,通常會將這些 Pod 以 Kubernetes Service 的形式對外暴露。這樣就可以使用任何標準方式從叢集外部存取這些 Service。
外部 Ingress 解決方案
外部 Ingress 解決方案則是利用叢集外部的應用程式負載平衡器。這種方法的優點是雲端供應商會處理 Ingress 的操作複雜性。然而,其缺點是功能可能不如叢集內 Ingress 解決方案豐富,而且可暴露的 Service 數量可能受限於雲端供應商的特定限制。
Egress 流量管理
Egress 指的是從 Pod 連線到叢集外部的任何資源。與 Ingress 不同,Kubernetes 沒有特定的 Egress 資源型別。Egress 流量的處理方式取決於所使用的 Kubernetes 網路實作或 CNI 外掛程式。
限制 Egress 流量
限制 Egress 流量是一種常見的安全需求和最佳實踐。這通常是透過使用 Network Policy 來定義每個微服務的 Egress 規則,並結合預設拒絕策略來實作的。
然而,使用 Kubernetes Network Policy 來限制對特定外部資源的存取有一個限制,即需要在 Policy 規則中將外部資源指定為 IP 位址(或 IP 位址範圍)。如果外部資源的 IP 位址發生變化,則需要更新所有參照這些 IP 位址的 Policy。
Egress Gateway
除了限制 Egress 流量外,Egress Gateway 也是一種重要的機制。Egress Gateway 可以提供一個統一的出口點,用於從叢集內部存取外部資源。
程式碼範例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80
內容解密:
此 YAML 程式碼定義了一個名為 example-ingress 的 Ingress 資源。它指定了一個規則,將 example.com 的流量導向 example-service Service 的 80 連線埠。其中:
apiVersion和kind指定了資源的 API 版本和型別。metadata部分定義了資源的中繼資料,如名稱。spec部分定義了 Ingress 資源的規格,包括規則和後端 Service 的資訊。rules列出了 Ingress 的規則,每個規則指定了一個主機名稱和相關的 HTTP 路徑組態。backend指定了流量的目標 Service 和連線埠。
此範例展示瞭如何使用 YAML 組態 Kubernetes Ingress 資源,以管理進入叢集的 HTTP 流量。
Kubernetes Egress 的探討
Kubernetes Egress 是指從 Kubernetes 叢集內部到外部服務的連線管理。在本章中,我們將探討 Kubernetes Egress 的相關概念,包括 NAT、Egress gateways 以及其在安全性和網路管理中的重要性。
網路位址轉換(NAT)
網路位址轉換(NAT)是一種將封包中的 IP 位址對映到不同 IP 位址的技術,常用於允許叢集內部的 Pod 連線到外部服務。特別是在 Pod 網路是覆寫網路(overlay network)的情況下,NAT 技術可以將非可路由的來源 IP 位址對映到節點的 IP 位址,使得外部服務可以正確接收請求。
來源網路位址轉換(SNAT)
當 Pod 嘗試連線到叢集外部的 IP 位址時,託管該 Pod 的節點會使用 SNAT 將封包的來源 IP 位址對映到節點的 IP 位址。然後,節點將回應封包映射回原始的 Pod IP 位址,確保雙向通訊的順暢進行。
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333
title 來源網路位址轉換(SNAT)
rectangle "請求" as node1
rectangle "SNAT" as node2
rectangle "回應" as node3
rectangle "反向對映" as node4
node1 --> node2
node2 --> node3
node3 --> node4
@enduml此圖示說明瞭 SNAT 的流程。
Calico 中的 NAT 行為組態
在使用 Calico 的環境中,NAT 行為可以透過 IP 池(IP pools)進行更細粒度的組態。這使得「非可路由」的範圍可以被更精確地定義,而不僅僅侷限於「叢集內部 vs 叢集外部」。
Egress Gateways
Egress gateways 是另一種管理 Kubernetes Egress 的方法,它將所有出站連線透過一個或多個 Egress gateways 進行路由。這些 gateways 使用 SNAT 將連線的來源 IP 位址轉換為 Egress gateway 的 IP 位址,使得外部服務看到的連線來自已知的 IP 位址。
Egress Gateways 的使用場景
Egress gateways 主要用於提高安全性,可以直接控制允許的連線,或者與周邊防火牆(perimeter firewalls)結合使用。例如,周邊防火牆可以根據來自已知 IP 位址(Egress gateways)的連線進行安全控制。
Calico Enterprise 中的 Egress Gateway 功能
Calico Enterprise 提供了 Egress gateway 功能,並且可以將名稱空間(namespaces)甚至個別 Pod 對映到特定的 Egress gateways。這使得周邊防火牆可以有效地為每個名稱空間提供安全控制,即使它們無法識別動態的 Pod IP 位址。
控制 Pod IP 位址範圍
除了使用 Egress gateways,Calico 還允許根據名稱空間、節點或甚至個別 Pod 來控制 Pod IP 位址範圍。這提供了一種簡單的方法,讓周邊防火牆與 Kubernetes 在 ingress 和 egress 流量上進行整合。
程式碼範例:組態 Calico 的 IP 池
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: my-ip-pool
spec:
cidr: 192.168.0.0/16
ipipMode: Always
natOutgoing: true
內容解密:
apiVersion和kind定義了資源的 API 版本和型別,這裡使用的是 Calico 的IPPool資源。metadata.name指定了 IP 池的名稱,這裡命名為my-ip-pool。spec.cidr定義了 IP 池的 CIDR 範圍,這裡設定為192.168.0.0/16。spec.ipipMode設定為Always,表示始終使用 IPIP 隧道模式。spec.natOutgoing設定為true,表示對出站流量進行 NAT。
eBPF 技術深度解析與 Calico 應用實踐
eBPF(extended Berkeley Packet Filter)是一種 Linux 核心技術,能夠在不修改核心程式碼的情況下,實作對網路封包的處理和系統呼叫的監控。Calico 是一個流行的容器網路介面(CNI)外掛,它利用 eBPF 技術實作高效的網路資料平面。
eBPF 鉤點(Hooks)與應用場景
eBPF 提供了多種鉤點,允許開發者在不同階段對網路封包進行處理。主要的鉤點包括:
Traffic Control (tc) 鉤點:允許在網路介面的輸入和輸出階段對封包進行處理。Calico 利用 tc 鉤點實作 Kubernetes 服務的負載平衡、網路策略執行和快速路徑處理。
內容解密:
- tc 鉤點提供對封包的精細控制,能夠修改、丟棄或重新導向封包。
- Calico 的 eBPF 資料平面根據 tc 鉤點,實作高效的網路流量管理。
XDP (eXpress Data Path) 鉤點:在封包進入網路堆積疊之前對其進行處理,提供卓越的效能,適用於 DDoS 防護和入口負載平衡等場景。
內容解密:
- XDP 鉤點需要網路裝置驅動程式的支援,才能達到最佳效能。
- Calico 的標準 Linux 資料平面支援 XDP,用於 DDoS 防護。
Socket 鉤點:允許對 socket 操作進行干預,例如更改新建立 socket 的目標 IP 或強制 socket 繫結到正確的來源 IP 地址。
內容解密:
- Socket 鉤點使得 Calico 能夠實作連線時的負載平衡,減少 DNAT 開銷。
BPF Maps 與資料共用
eBPF 程式透過 BPF Maps 來儲存和檢索長期資料,並與使用者空間程式進行通訊。Calico 使用 BPF Maps 來追蹤活躍連線、組態策略和服務 NAT 資訊。
內容解密:
- BPF Maps 提供了一種靈活的資料共用機制,使得 eBPF 程式能夠與使用者空間程式協同工作。
- Calico 利用 BPF Maps 最佳化服務連線處理和策略執行。
Calico 的 eBPF 資料平面
Calico 的 eBPF 資料平面是其標準 Linux 資料平面的替代方案,專注於效能、延遲和使用者經驗。該資料平面替換了 kube-proxy,使用 eBPF 程式實作 Kubernetes 服務的負載平衡。
特色比較
| 功能特點 | 標準 Linux 資料平面 | eBPF 資料平面 |
|---|---|---|
| 吞吐量設計 | 10GBit+ | 40GBit+ |
| 首個封包延遲 | 較高(受 kube-proxy 影響) | 較低 |
| 後續封包延遲 | 低 | 更低 |
| 保留來源 IP(叢集內) | 是 | 是 |
| 保留外部來源 IP | 需要設定 externalTrafficPolicy: Local | 是 |
| 直接伺服器傳回(DSR) | 不支援 | 支援(需相容的基礎網路) |
架構概述與效能最佳化
Calico 的 eBPF 資料平面將 eBPF 程式附加到每個 Calico 網路介面和資料通道介面上,實作快速路徑處理,繞過 iptables 和其他核心封包處理過程。
內容解密:
- Calico 使用 BPF Maps 儲存 NAT 前端和後端資訊,實作高效的負載平衡。
- 連線時的負載平衡進一步減少了 NAT 開銷,提升了服務連線效能。