Kubernetes 安全性對於現代雲端原生應用至關重要。本文探討 Admission Controllers 和 Security Context 兩大機制,如何有效提升叢集安全性。Admission Controllers 在資源物件持久化前進行檢查和修改,分為變異和驗證階段,允許叢集管理員透過 kube-apiserver 的引數設定來管理這些控制器。Security Context 則定義 Pod 或容器的安全設定,包含限制容器許可權、控制 Capabilities、設定安全模組等功能,並可在 Pod 和容器層級靈活應用。此外,文章也探討了 NetworkPolicy 的應用,說明如何利用它來建立網路防火牆,限制 Pod 之間的通訊,進一步提升叢集的安全性,並提供程式碼範例說明如何設定 NetworkPolicy。
Kubernetes 安全機制:Admission Controllers 與 Security Context
Kubernetes 為現代雲端原生應用提供了強大的容器協調能力,但同時也帶來了新的安全挑戰。本章節將探討 Kubernetes 中的 Admission Controllers 和 Security Context 機制,解析如何透過這些功能強化叢集的安全性。
Admission Controllers 的工作原理
Admission Controllers 是 Kubernetes API Server 的關鍵元件,負責在資源物件被持久化儲存之前進行檢查和修改。整個過程分為兩個主要階段:Mutation(變異)和 Validation(驗證)。
變異階段(Mutation Phase)
在變異階段,Mutating Admission Controllers 會對傳入的 API 請求進行修改,以確保其符合叢集的政策要求。這些控制器就像是請求的"塑造者",不僅檢查請求的一致性,還可以自動新增或調整設定。例如:
- 為 Pod 新增缺失的安全註解
- 根據預定義規則調整 Pod 的資源請求和限制
- 為特定功能注入 sidecar 容器
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: main-container
image: nginx:latest
resources:
requests:
cpu: 100m
limits:
cpu: 200m
內容解密:
此 YAML 組態定義了一個名為 example-pod 的 Pod,其中包含一個名為 main-container 的容器,執行 nginx:latest 映象。資源請求和限制被設定為 100m 和 200m CPU。Mutating Admission Controllers 可以根據預定義規則自動調整這些資源設定。
驗證階段(Validation Phase)
驗證階段則是由 Validating Admission Controllers 負責,它們會仔細檢查經過變異處理後的請求,確保其符合叢集的安全標準和政策要求。這些控制器扮演著"守門人"的角色,拒絕任何不符合設定的請求。例如:
- 檢查資源配額是否符合規定
- 驗證安全標準是否達標
- 拒絕違反任何政策的請求並提供錯誤訊息
Admission Controllers 的管理
叢集管理員可以透過組態 kube-apiserver 的 --enable-admission-plugins 引數來啟用或停用特定的 Admission Controllers。例如,在 minikube 環境中,可以透過以下步驟檢視和修改啟用的外掛:
- SSH 登入 minikube 虛擬機器:
minikube ssh - 檢視 kube-apiserver 的組態:
sudo cat /etc/kubernetes/manifests/kube-apiserver.yaml - 搜尋
--enable-admission-plugins引數以檢視目前啟用的外掛
$ minikube ssh 'sudo grep -- "--enable-admission-plugins" /etc/kubernetes/manifests/kube-apiserver.yaml'
- --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
常見的 Admission Controllers
Kubernetes 提供了多種內建的 Admission Controllers,包括:
- 基本控制:AlwaysPullImages
- 安全相關:PodSecurityPolicy、SecurityContextDeny
- 資源管理:LimitRanger、ResourceQuota
- 物件生命週期管理:NamespaceLifecycle、StorageObjectInUseProtection
- Webhook 相關:MutatingAdmissionWebhook、ValidatingAdmissionWebhook
使用 Security Context 加強 Pod 和容器的安全性
Security Context 是 Kubernetes 中用於定義 Pod 或容器安全設定的重要機制。透過設定 Security Context,可以實作以下安全增強功能:
- 限制容器的許可權,避免使用 root 使用者執行應用程式
- 控制容器的能力(Capabilities)
- 設定 SELinux 或 AppArmor 等安全模組
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
containers:
- name: secure-container
image: nginx:latest
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
內容解密:
此組態定義了一個名為 secure-pod 的 Pod,並設定了多項安全相關的引數:
runAsNonRoot: true確保容器不會以 root 使用者執行。runAsUser: 1000指定容器以 UID 1000 的使用者執行。fsGroup: 2000設定檔案系統群組 ID 為 2000。- 在容器層級,
allowPrivilegeEscalation: false禁止許可權提升。 capabilities.drop: - ALL移除所有 Linux Capabilities,進一步限制容器的許可權。
Kubernetes 安全機制:SecurityContext 深度解析
在 Kubernetes 環境中,SecurityContext 扮演著至關重要的角色,用於定義容器或 Pod 的安全組態。透過適當的 SecurityContext 設定,可以有效提升叢集的安全性,防止潛在的安全威脅。
SecurityContext 的關鍵組成
SecurityContext 主要包含以下幾個關鍵組成部分,每一部分都對容器的安全執行環境有著重要影響。
使用者與群組
透過指定 runAsUser 和 runAsGroup,可以控制容器內程式的執行身份,遵循最小許可權原則,避免容器獲得不必要的許可權。
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: app-container
securityContext:
runAsUser: 1000 # 以使用者 ID 1000 執行容器程式
runAsGroup: 1000 # 以群組 ID 1000 執行容器程式
Linux Capabilities
Capabilities 允許為容器分配特定的許可權,而無需賦予完整的 root 許可權。這種機制可以讓容器在不提升至 root 使用者的情況下,執行特定的系統操作。
apiVersion: v1
kind: Pod
metadata:
name: privileged-container
spec:
containers:
- name: app-container
securityContext:
capabilities:
add:
- CAP_NET_ADMIN # 賦予網路管理許可權
特權模式
預設情況下,容器以非特權模式執行。透過設定 privileged: true,可以讓容器以特權模式執行,獲得更多的系統許可權。但需謹慎使用,因為這會增加安全風險。
apiVersion: v1
kind: Pod
metadata:
name: privileged-container
spec:
containers:
- name: app-container
securityContext:
privileged: true # 以特權模式執行容器(需謹慎使用)
唯讀根檔案系統
設定 readOnlyRootFilesystem: true 可以將容器的根檔案系統掛載為唯讀,防止對基礎系統的意外或惡意修改。
apiVersion: v1
kind: Pod
metadata:
name: read-only-container
spec:
containers:
- name: app-container
securityContext:
readOnlyRootFilesystem: true # 將根檔案系統掛載為唯讀
在 Pod 和容器層級應用 SecurityContext
Kubernetes 允許在 Pod 和容器兩個層級上設定 SecurityContext,提供靈活的安全組態選項。
Pod 層級的 SecurityContext
在 Pod 層級設定的 SecurityContext 將被 Pod 內的所有容器繼承,適合用於設定統一的安全組態。
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
securityContext:
runAsUser: 1000 # Pod 內所有容器以使用者 ID 1000 執行
runAsGroup: 1000 # Pod 內所有容器以群組 ID 1000 執行
containers:
- name: app-container
image: my-app-image
- name: sidecar-container
image: my-sidecar-image
容器層級的 SecurityContext
在容器層級設定的 SecurityContext 只會影響特定的容器,允許為不同的容器設定不同的安全組態。
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: app-container
image: my-app-image
securityContext:
runAsUser: 1000 # 此容器以使用者 ID 1000 執行
capabilities:
add: ["CAP_NET_ADMIN"] # 賦予特定的 Capabilities
- name: sidecar-container
image: my-sidecar-image
securityContext:
runAsUser: 2000 # 此容器以使用者 ID 2000 執行
readOnlyRootFilesystem: true # 此容器的根檔案系統為唯讀
範例:套用 SecurityContext 至 Pod
以下範例建立了一個 Pod,其中的容器以非 root 使用者和群組執行,並具有唯讀根檔案系統。
# pod-with-security-context.yaml
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
containers:
- name: app-container
image: nginx:latest
securityContext:
runAsUser: 1000 # 以使用者 ID 1000 執行容器程式
runAsGroup: 1000 # 以群組 ID 1000 執行容器程式
readOnlyRootFilesystem: true # 將根檔案系統掛載為唯讀
volumeMounts:
- name: html-volume
mountPath: /usr/share/nginx/html
volumes:
- name: html-volume
emptyDir: {} # 提供可寫入的空間
建立 Pod 後,可以進入容器內部驗證 SecurityContext 的設定是否生效。
$ kubectl apply -f pod-with-security-context.yaml
pod/security-context-demo created
$ kubectl exec -it security-context-demo -- /bin/sh
~ $ id
程式碼解析:
此範例 YAML 設定了一個名為 security-context-demo 的 Pod,其中包含一個根據 nginx:latest 映象的容器。SecurityContext 設定確保該容器以非 root 身份(UID 和 GID 為 1000)執行,並且根檔案系統為唯讀。為了讓 Nginx 能夠正常運作,我們掛載了一個 emptyDir 捲到 /usr/share/nginx/html,提供可寫入的空間。
runAsUser和runAsGroup設定確保容器程式以指定的非 root 使用者和群組執行。readOnlyRootFilesystem設定將容器的根檔案系統掛載為唯讀,有效防止對基礎系統的修改。volumeMounts和volumes的設定提供了一個可寫入的目錄,讓 Nginx 能夠寫入必要的檔案。
Kubernetes 安全防護:網路隔離與 NetworkPolicy 實作
在 Kubernetes 叢集中,安全議題一直是管理者關注的重點。除了前面提到的安全上下文(Security Context)之外,網路流量控制也是防護措施中的重要一環。本章節將介紹 Kubernetes 中的 NetworkPolicy 物件,說明如何利用它來建立網路防火牆,限制 Pod 之間的通訊。
為何需要 NetworkPolicy?
在微服務架構中,不同應用程式之間的通訊是不可避免的,而這些通訊大多數是透過網路進行。因此,如何確保網路的安全就變得非常重要。Kubernetes 提供了 NetworkPolicy 這種資源,用於定義網路防火牆規則,直接在叢集中實施。
使用 NetworkPolicy 的主要好處包括:
- 能夠根據 CIDR(無類別網域路由)區塊建立出口/入口規則。
- 能夠根據 Pod 的標籤和選擇器建立出口/入口規則。
- 能夠根據名稱空間建立出口/入口規則。
然而,要使 NetworkPolicy 生效,Kubernetes 叢集必須安裝 CNI(容器網路介面)外掛。像 minikube 這樣的本地開發工具,可以透過指定 CNI 外掛(如 Calico)來啟用 NetworkPolicy 功能。
建立 NetworkPolicy:使用標籤和選擇器
首先,建立兩個 nginx Pod,分別位於不同的名稱空間中,以展示如何使用 NetworkPolicy 進行網路隔離。
建立名稱空間與 Pod
# web1-app.yaml
---
apiVersion: v1
kind: Namespace
metadata:
labels:
project: web1
name: web1
---
apiVersion: v1
kind: Pod
metadata:
name: nginx1
namespace: web1
labels:
app: nginx1
spec:
containers:
- name: nginx1
image: nginx
# web2-app.yaml
---
apiVersion: v1
kind: Namespace
metadata:
labels:
project: web2
name: web2
---
apiVersion: v1
kind: Pod
metadata:
name: nginx2
namespace: web2
labels:
app: nginx2
spec:
containers:
- name: nginx2
image: nginx
建立這些資源後,可以看到兩個 Pod 分別執行在不同的名稱空間中,並且具有不同的 IP 位址。
#### 內容解密:
上述 YAML 組態檔定義了兩個名稱空間(web1 和 web2)以及各自的 Pod(nginx1 和 nginx2)。每個 Pod 都執行著 nginx 容器。這樣的設定便於後續示範如何使用 NetworkPolicy 對不同名稱空間中的 Pod 進行網路隔離。
驗證預設網路連通性
在未建立 NetworkPolicy 的情況下,預設所有 Pod 之間的通訊是允許的。可以使用 curl 命令從 nginx1 Pod 向 nginx2 Pod 傳送請求,驗證這一點。
$ kubectl -n web1 exec nginx1 -- curl 10.244.120.72
此命令會從 nginx1 傳送一個 HTTP 請求到 nginx2 的 IP 位址,並接收到 nginx2 的回應,證明在沒有 NetworkPolicy 的情況下,Pod 之間的通訊是開放的。
#### 內容解密:
這裡使用了 kubectl exec 命令在 nginx1 容器內執行 curl 命令,以測試與 nginx2 的連通性。結果表明,在未組態 NetworkPolicy 時,Kubernetes 預設允許所有 Pod 之間的通訊。