Kubernetes 安全設定與 Pod 的有效排程是確保叢集穩定執行的關鍵。本文首先介紹如何利用網路策略限制 Pod 間的網路流量,並透過 TLS 憑證加密通訊通道,提升叢集安全性。接著,探討 gVisor 和 Kata Containers 等容器執行時技術,強化容器隔離性和安全性。最後,深入研究節點親和性、汙點和容忍度等進階 Pod 排程策略,讓開發者能更精細地控制 Pod 的佈署位置,最佳化資源分配和應用程式效能。
Kubernetes 安全防護:網路策略與 TLS 憑證
網路策略的實務應用
在 Kubernetes 環境中,網路安全是至關重要的議題。預設情況下,Kubernetes 允許叢集內所有 Pod 之間的通訊,但這可能導致安全風險。網路策略(NetworkPolicy)提供了一種控制 Pod 間流量的方法,讓管理員能夠精細地控管叢集內的網路存取。
預設拒絕所有入口流量
要明確封鎖所有進入 web2 名稱空間的流量,可以建立一個預設的網路策略。以下是一個範例 YAML 檔案:
# default-deny-ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
ingress: []
內容解密:
podSelector: {}:選擇此網路策略適用的 Pod。在此例中,{}表示選擇名稱空間內的所有 Pod。policyTypes: - Ingress:指定所套用的策略型別為「入口(Ingress)」,控制進入所選 Pod 的流量。ingress: []:定義網路策略的入口規則。由於列表為空,表示預設拒絕所有進入所選 Pod 的流量。
將此策略套用到 web2 名稱空間:
$ kubectl apply -f default-deny-ingress.yaml -n web2
測試結果顯示,從 web1 名稱空間中的 nginx1 Pod 無法存取 web2 名稱空間中的 nginx2 Pod:
$ kubectl -n web1 exec nginx1 -- curl 10.244.120.72
允許特定來源的流量
要允許來自 web1 名稱空間中 nginx1 Pod 的流量,可以建立以下網路策略:
# allow-from-web1-netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-web1-netpol
namespace: web2
spec:
podSelector:
matchLabels:
app: nginx2
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
project: web1
- podSelector:
matchLabels:
app: nginx1
ports:
- protocol: TCP
port: 80
內容解密:
podSelector.matchLabels.app: nginx2:選擇標籤為app: nginx2的 Pod。namespaceSelector.matchLabels.project: web1:選擇標籤為project: web1的名稱空間。podSelector.matchLabels.app: nginx1:選擇標籤為app: nginx1的 Pod。ports.protocol: TCP, port: 80:允許 TCP 協定在 80 連線埠上的流量。
套用此網路策略後,從 nginx1 Pod 可以成功存取 nginx2 Pod:
$ kubectl -n web1 exec nginx1 -- curl 10.244.120.72
使用 TLS 憑證保護 Kubernetes 元件間的通訊
在 Kubernetes 中,各元件之間的通訊安全至關重要。傳輸層安全性(TLS)憑證用於加密資料傳輸並驗證服務身份。
TLS 憑證的使用場景
- API Server 與 etcd 之間的通訊:使用雙向 TLS(mTLS)確保叢集狀態資料的安全。
- Ingress Controller 與後端服務之間:實施 mTLS 以確保只有授權服務能夠接收流量。
- 內部服務之間的通訊:服務可以使用 mTLS 確保彼此之間的通訊安全。
- 服務網格(如 Istio):提供自動化的 mTLS 功能,簡化微服務之間的安全通訊。
使用 TLS 憑證和網路策略,可以顯著提升 Kubernetes 叢集的安全性,確保資料傳輸的機密性和完整性。建議在佈署 Pod 時一併使用網路策略,以達到最佳的安全防護效果。
Kubernetes 安全強化:TLS、gVisor 和 Kata Containers
在 Kubernetes 叢集中,安全性的重要性不言而喻。為了保護叢集內部通訊的安全,管理員可以採用多種方法來加強安全性,例如使用 TLS(Transport Layer Security)憑證、啟用 IPSec,以及採用特殊的容器執行時,如 gVisor 和 Kata Containers。
使用 TLS 強化叢集內部通訊安全
在 Kubernetes 中,叢集內部通訊的安全至關重要。透過佈署 TLS 憑證並啟用 mTLS(mutual TLS),管理員可以顯著提升叢集的安全性。這種方法不僅加密了通訊路徑,還驗證了通訊元件的身份,從而降低了未經授權的資料存取或竄改風險。
應用場景
- Load Balancers:在負載平衡器和後端服務之間使用 TLS 加密通訊,確保資料在整個傳輸路徑中保持加密狀態。
- IPSec:在 Kubernetes 叢集中啟用 IPSec,以加密節點之間的網路流量,保護雲端環境或不同資料中心之間的流量。
容器安全:gVisor 和 Kata Containers
傳統的容器分享主機作業系統核心,這可能帶來安全風險。gVisor 和 Kata Containers 提供了替代的容器執行時技術,優先考慮安全性。
gVisor:輕量級虛擬機器
gVisor 是一個在使用者空間實作的輕量級虛擬機器,作為每個容器的沙箱,將其與主機核心和其他容器隔離。gVisor 虛擬化了每個容器的核心功能,確保容器漏洞無法直接損害主機系統。
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
runtimeClassName: gvisor
containers:
- name: my-app
image: my-secure-image
Kata Containers:輕量級虛擬機器
Kata Containers 使用類別似於傳統虛擬機器的輕量級虛擬機器,但針對容器工作負載進行了最佳化。Kata Containers 在輕量級虛擬機器中隔離容器,提供比標準容器更強的安全性,同時保持效能效率。
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
runtimeClassName: kata-containers
containers:
- name: my-app
image: my-secure-image
使用 RuntimeClass 設定安全性組態
在 Kubernetes 中,可以使用 runtimeClassName 欄位指定容器執行時環境。例如,使用 Kata Containers 執行時來增強安全性隔離。
管理機密資訊和登入檔憑證
在 Kubernetes 中,需要登入檔憑證來安全地從需要身份驗證的私有登入檔中提取容器映像。管理這些憑證的安全性至關重要,以確保只有授權的 Pod 可以檢索和使用特定的容器映像。
使用 kubectl create secret docker-registry 管理登入檔憑證
使用 kubectl create secret docker-registry 命令可以簡化 Kubernetes 中容器登入檔憑證的管理。它透過加密靜態的機密資訊,確保只有授權的節點可以存取,從而提高安全性。
$ kubectl create secret docker-registry my-registry-secret \
--docker-server=your-registry.com \
--docker-username=your_username \
--docker-password=your_password \
--docker-email=[email protected]
更新 Pod YAML 以使用新建立的機密資訊從私有登入檔中提取映像:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
imagePullSecrets:
- name: my-registry-secret
containers:
- name: my-app
image: your-registry.com/my-secure-image
內容解密:
kubectl create secret docker-registry命令用於建立 Docker 登入檔機密資訊。--docker-server、--docker-username、--docker-password和--docker-email引數用於指定登入檔的相關資訊。- 在 Pod YAML 中,使用
imagePullSecrets欄位指定要使用的機密資訊。
本章節介紹了多種強化 Kubernetes 安全性的技術,包括使用 TLS、gVisor 和 Kata Containers,以及管理機密資訊和登入檔憑證。這些技術可以顯著提升 Kubernetes 叢集的安全性,保護叢集內部通訊和容器工作負載。
進階 Pod 排程技術
在本文的開頭,第2章《Kubernetes 架構 - 從容器映象到執行中的 Pod》中,我們解釋了 Kubernetes 排程器(kube-scheduler)控制平面元件背後的原理及其在叢集中的關鍵作用。簡而言之,它負責排程容器工作負載(Kubernetes Pod)並將它們分配給滿足執行特定工作負載所需標準的健康節點。
本章將介紹如何控制叢集中 Pod 排程的標準。我們將特別關注節點親和性(Node affinity)、汙點(taints)和容忍(tolerations)對 Pod 的影響。我們還將更深入地探討排程策略,這些策略使 kube-scheduler 在優先處理 Pod 工作負載時具有靈活性。您會發現這些概念對於執行雲規模的生產叢集非常重要。
在本章中,我們將涵蓋以下主題:
- 回顧 – 什麼是 kube-scheduler?
- 管理節點親和性
- 使用節點汙點和容忍度
- 瞭解 Kubernetes 中的靜態 Pod
- Kubernetes 中的擴充套件排程器組態
技術要求
本章需要以下內容:
- 需要一個多節點 Kubernetes 叢集。擁有多節點叢集將使理解節點親和性、汙點和容忍度變得更加容易。
- 在本地機器上安裝 Kubernetes CLI(kubectl)並組態它來管理您的 Kubernetes 叢集。
回顧 – 什麼是 kube-scheduler?
在 Kubernetes 叢集中,kube-scheduler 是控制平面的一個關鍵元件。該元件的主要職責是排程容器工作負載(Pod)並將它們分配給滿足執行特定工作負載所需標準的健康計算節點(也稱為工作節點)。回顧一下,Pod 是一組一個或多個具有分享網路和儲存的容器,是 Kubernetes 系統中最小的佈署單元。您通常使用不同的 Kubernetes 控制器(如 Deployment 物件和 StatefulSet 物件)來管理您的 Pod,但最終是由 kube-scheduler 將建立的 Pod 分配給叢集中的特定節點。
kube-scheduler 定期查詢 Kubernetes API 伺服器(kube-apiserver),以列出尚未排程的 Pod。在建立時,Pod 被標記為未排程 – 這意味著沒有選擇節點來執行它們。未排程的 Pod 將被註冊在 etcd 叢集狀態中,但沒有分配任何節點,因此沒有執行中的 kubelet 會知道這個 Pod。最終,Pod 規範中描述的容器不會執行。
在內部,儲存在 etcd 中的 Pod 物件具有一個名為 nodeName 的屬性。顧名思義,此屬性應包含將託管 Pod 的節點的名稱。當設定此屬性時,我們說 Pod 處於已排程狀態;否則,Pod 處於待處理狀態。
我們需要找到一種方法來填充這個 nodeName 值,這就是 kube-scheduler 的作用。為此,kube-scheduler 定期輪詢 kube-apiserver。它查詢 nodeName 屬性為空的 Pod 資源。一旦找到這樣的 Pod,它將執行一個演算法來選舉一個節點,並透過向 kube-apiserver 發出請求來更新 Pod 物件中的 nodeName 屬性。在為 Pod 選擇節點時,kube-scheduler 將考慮其內部排程策略和您為 Pod 定義的標準。最後,負責在所選節點上執行 Pod 的 kubelet 將注意到該節點有一個新的處於已排程狀態的 Pod,並嘗試啟動該 Pod。這些原理已在下圖中視覺化:
圖 19.1:kube-scheduler 和 kube-apiserver 的互動
對於雲中的受管 Kubernetes 叢集,如 Azure Kubernetes Service(AKS)或 Amazon Elastic Kubernetes Service(EKS),您通常無法存取控制平面或控制器節點,因為它們由雲端服務提供商管理。這意味著您無法直接存取 kube-scheduler 等元件,也無法控制其組態(如排程策略)。但是,您仍然可以控制影響 Pod 排程的所有引數。
Pod 的排程過程分為兩個階段:
- 過濾:kube-scheduler 確定能夠執行給定 Pod 的節點集。這包括檢查節點的實際狀態並驗證 Pod 定義指定的任何資源需求和標準。此時,如果沒有節點可以執行給定的 Pod,則 Pod 無法被排程並保持待處理狀態。
- 評分:kube-scheduler 根據一組排程策略為每個節點分配分數。然後,排程器將 Pod 分配給具有最高分數的節點。我們將在本章的後面部分介紹排程策略。
# 以下是一個示例 YAML 檔案,用於演示如何使用 nodeName 屬性
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: your-registry.com/your-image:tag
nodeName: node1
內容解密:
此 YAML 檔案定義了一個簡單的 Pod,其中包含一個容器,並指定了 nodeName 屬性。在這個例子中,Pod 被排程到名為 node1 的節點上。nodeName 屬性是 kube-scheduler 在排程 Pod 時設定的屬性。在手動指定 nodeName 時,需要確保該節點存在且可用。
管理節點親和性
節點親和性是一種機制,允許您根據節點的標籤來控制 Pod 可以被排程到哪些節點上。它提供了比 nodeName 更靈活的方式來控制 Pod 的排程。
apiVersion: v1
kind: Pod
metadata:
name: my-pod-with-affinity
spec:
containers:
- name: my-container
image: your-registry.com/your-image:tag
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
內容解密:
此 YAML 檔案定義了一個具有節點親和性的 Pod。該 Pod 將被排程到具有標籤 kubernetes.io/e2e-az-name 且值為 e2e-az1 或 e2e-az2 的節點上。requiredDuringSchedulingIgnoredDuringExecution 規則意味著在排程期間必須滿足此條件,但在 Pod 執行期間,如果節點的標籤發生變化,則不會影響已經執行的 Pod。
使用節點汙點和容忍度
節點汙點是一種機制,用於阻止 Pod 被排程到特定的節點上,除非該 Pod 具有相應的容忍度。
apiVersion: v1
kind: Pod
metadata:
name: my-pod-with-toleration
spec:
containers:
- name: my-container
image: your-registry.com/your-image:tag
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
內容解密:
此 YAML 檔案定義了一個具有容忍度的 Pod。該 Pod 可以被排程到具有汙點 key1=value1:NoSchedule 的節點上。容忍度的 operator 為 Equal,表示必須完全匹配指定的鍵值對。effect 為 NoSchedule,表示如果 Pod 不具有此容忍度,則不會被排程到具有此汙點的節點上。
本章小結
本章介紹了 Kubernetes 中進階的 Pod 排程技術,包括 kube-scheduler 的工作原理、節點親和性、汙點和容忍度等。這些技術可以幫助您更好地控制 Pod 在叢集中的排程,提高叢集的利用率和穩定性。
下一章,我們將繼續探討 Kubernetes 中的其他高階主題。