返回文章列表

Kubernetes 安全強化 AdmissionControllers 與 SecurityContext

本文探討 Kubernetes 的安全機制,包含 Admission Controllers 和 Security Context,並解析如何透過這些功能強化叢集安全性,涵蓋變異與驗證階段、控制器管理、常見控制器型別,以及 Security Context 的組成、Pod 與容器層級應用、網路隔離與

Kubernetes 資安

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 環境中,可以透過以下步驟檢視和修改啟用的外掛:

  1. SSH 登入 minikube 虛擬機器:minikube ssh
  2. 檢視 kube-apiserver 的組態:sudo cat /etc/kubernetes/manifests/kube-apiserver.yaml
  3. 搜尋 --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,並設定了多項安全相關的引數:

  1. runAsNonRoot: true 確保容器不會以 root 使用者執行。
  2. runAsUser: 1000 指定容器以 UID 1000 的使用者執行。
  3. fsGroup: 2000 設定檔案系統群組 ID 為 2000。
  4. 在容器層級,allowPrivilegeEscalation: false 禁止許可權提升。
  5. capabilities.drop: - ALL 移除所有 Linux Capabilities,進一步限制容器的許可權。

Kubernetes 安全機制:SecurityContext 深度解析

在 Kubernetes 環境中,SecurityContext 扮演著至關重要的角色,用於定義容器或 Pod 的安全組態。透過適當的 SecurityContext 設定,可以有效提升叢集的安全性,防止潛在的安全威脅。

SecurityContext 的關鍵組成

SecurityContext 主要包含以下幾個關鍵組成部分,每一部分都對容器的安全執行環境有著重要影響。

使用者與群組

透過指定 runAsUserrunAsGroup,可以控制容器內程式的執行身份,遵循最小許可權原則,避免容器獲得不必要的許可權。

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,提供可寫入的空間。

  • runAsUserrunAsGroup 設定確保容器程式以指定的非 root 使用者和群組執行。
  • readOnlyRootFilesystem 設定將容器的根檔案系統掛載為唯讀,有效防止對基礎系統的修改。
  • volumeMountsvolumes 的設定提供了一個可寫入的目錄,讓 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 之間的通訊。