Kubernetes Pod Security Standards

Kubernetes Pod Security Standards and Admission Control

前言

隨著 Kubernetes 在企業環境中的廣泛應用,Pod 安全性成為叢集管理的重要議題。Kubernetes 1.25 版本正式移除了 Pod Security Policies (PSP),取而代之的是更為簡潔且易於管理的 Pod Security Standards (PSS)Pod Security Admission (PSA) 控制器。本文將深入探討這套新的安全機制,協助您建立更安全的 Kubernetes 環境。

Pod Security Standards 概述

Pod Security Standards (PSS) 定義了三個不同的安全等級,用於規範 Pod 的安全配置。這些標準涵蓋了 Pod 規格中的安全敏感欄位,提供了一套清晰且可預測的安全政策框架。

為什麼需要 Pod Security Standards?

  • 簡化安全管理:相較於 PSP 的複雜配置,PSS 提供了預定義的安全等級
  • 降低學習曲線:管理員只需選擇適當的安全等級即可
  • 內建於 Kubernetes:作為核心功能,無需額外安裝元件
  • 漸進式導入:支援 warn、audit、enforce 三種模式

三個安全等級

1. Privileged(特權模式)

這是最寬鬆的安全等級,幾乎不限制任何安全配置。適用於需要系統層級存取權限的工作負載。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Privileged 等級允許的配置範例
apiVersion: v1
kind: Pod
metadata:
  name: privileged-pod
spec:
  hostNetwork: true
  hostPID: true
  hostIPC: true
  containers:
  - name: privileged-container
    image: nginx:latest
    securityContext:
      privileged: true
      runAsUser: 0
      capabilities:
        add: ["ALL"]

適用場景

  • 系統 DaemonSet(如 CNI plugins、日誌收集器)
  • 節點監控代理
  • 需要存取主機資源的特殊工作負載

2. Baseline(基準模式)

這是中等安全等級,阻止已知的權限提升,同時保持足夠的彈性以運行大多數應用程式。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Baseline 等級的合規 Pod 範例
apiVersion: v1
kind: Pod
metadata:
  name: baseline-pod
spec:
  containers:
  - name: app
    image: nginx:latest
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: ["ALL"]
        add: ["NET_BIND_SERVICE"]
    ports:
    - containerPort: 80

Baseline 等級限制

  • 禁止 hostNetworkhostPIDhostIPC
  • 禁止 privileged 容器
  • 限制 hostPath volumes 類型
  • 限制可新增的 Linux capabilities
  • 禁止 procMount 設定為 Unmasked

3. Restricted(受限模式)

這是最嚴格的安全等級,遵循當前 Pod 安全強化的最佳實務。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Restricted 等級的合規 Pod 範例
apiVersion: v1
kind: Pod
metadata:
  name: restricted-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: nginx:latest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
    volumeMounts:
    - name: tmp
      mountPath: /tmp
  volumes:
  - name: tmp
    emptyDir: {}

Restricted 等級額外要求

  • 必須以非 root 身份運行 (runAsNonRoot: true)
  • 必須明確丟棄所有 capabilities
  • 禁止權限提升 (allowPrivilegeEscalation: false)
  • 必須設定 Seccomp profile
  • 限制可使用的 volume 類型

Pod Security Admission 控制器

Pod Security Admission (PSA) 是 Kubernetes 內建的 admission controller,負責在 Pod 建立時驗證其是否符合指定的安全標準。

三種執行模式

模式說明行為
enforce強制執行拒絕違規的 Pod
audit稽核模式記錄違規但允許建立
warn警告模式顯示警告但允許建立

啟用 PSA 控制器

在 Kubernetes 1.23+ 版本中,PSA 預設啟用。若需手動配置,可在 API server 中設定:

1
2
3
4
5
# 確認 PSA 已啟用
kubectl api-versions | grep admission

# 查看 admission controller 配置
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep -A5 enable-admission-plugins

PSA 配置檔案

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# /etc/kubernetes/psa/admission-configuration.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
  configuration:
    apiVersion: pod-security.admission.config.k8s.io/v1
    kind: PodSecurityConfiguration
    defaults:
      enforce: "baseline"
      enforce-version: "latest"
      audit: "restricted"
      audit-version: "latest"
      warn: "restricted"
      warn-version: "latest"
    exemptions:
      usernames: []
      runtimeClasses: []
      namespaces: ["kube-system"]

Namespace 層級設定

PSS 透過 Namespace labels 進行配置,提供細緻的安全控制。

設定 Namespace 安全等級

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 建立具有安全設定的 Namespace
kubectl create namespace secure-app

# 設定 enforce 模式為 restricted
kubectl label namespace secure-app \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=v1.28

# 設定 warn 模式
kubectl label namespace secure-app \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/warn-version=latest

# 設定 audit 模式
kubectl label namespace secure-app \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/audit-version=latest

Namespace 配置範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: v1.28
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: latest
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: latest

驗證 Namespace 設定

1
2
3
4
5
6
7
8
# 檢視 Namespace 的安全標籤
kubectl get namespace secure-app -o yaml | grep pod-security

# 列出所有 Namespace 及其安全等級
kubectl get namespaces -L pod-security.kubernetes.io/enforce

# 測試 Pod 是否符合標準(dry-run)
kubectl apply --dry-run=server -f pod.yaml -n secure-app

從 PSP 遷移指南

遷移策略概述

  1. 評估現有 PSP:分析目前使用的 Pod Security Policies
  2. 對應安全等級:將 PSP 規則對應到 PSS 等級
  3. 漸進式導入:先使用 warn/audit 模式測試
  4. 逐步強制執行:確認無問題後切換至 enforce 模式
  5. 移除 PSP:完成遷移後停用 PSP

評估現有 PSP

1
2
3
4
5
6
7
8
# 列出所有 PSP
kubectl get psp

# 查看 PSP 詳細配置
kubectl get psp <psp-name> -o yaml

# 分析哪些 Pod 使用了哪些 PSP
kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.metadata.annotations.kubernetes\.io/psp}{"\n"}{end}'

PSP 到 PSS 對應表

PSP 設定PrivilegedBaselineRestricted
privileged: true允許禁止禁止
hostNetwork: true允許禁止禁止
hostPID: true允許禁止禁止
runAsUser: MustRunAsNonRoot不要求不要求要求
allowPrivilegeEscalation: false不要求不要求要求

遷移腳本範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/bin/bash
# migrate-psp-to-pss.sh

# 為所有非系統 Namespace 設定 warn 模式
for ns in $(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}'); do
  if [[ ! "$ns" =~ ^kube- ]] && [[ "$ns" != "default" ]]; then
    echo "Setting warn mode for namespace: $ns"
    kubectl label namespace "$ns" \
      pod-security.kubernetes.io/warn=baseline \
      pod-security.kubernetes.io/audit=baseline \
      --overwrite
  fi
done

# 檢查是否有違規 Pod
echo "Checking for policy violations..."
kubectl get pods --all-namespaces -o wide

遷移驗證

1
2
3
4
5
6
7
8
# 在 dry-run 模式下測試現有工作負載
kubectl label namespace test-ns \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=v1.28 \
  --dry-run=server -o yaml

# 檢視 audit 日誌中的違規記錄
kubectl logs -n kube-system -l component=kube-apiserver | grep "pod-security"

政策豁免設定

某些工作負載(如系統元件)可能需要豁免安全限制。PSA 支援三種豁免類型。

豁免類型

  1. Usernames:特定使用者或服務帳號
  2. RuntimeClasses:特定 RuntimeClass
  3. Namespaces:特定 Namespace

叢集層級豁免配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# admission-configuration.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
  configuration:
    apiVersion: pod-security.admission.config.k8s.io/v1
    kind: PodSecurityConfiguration
    defaults:
      enforce: "restricted"
      enforce-version: "latest"
      audit: "restricted"
      audit-version: "latest"
      warn: "restricted"
      warn-version: "latest"
    exemptions:
      # 豁免特定使用者
      usernames:
        - system:serviceaccount:kube-system:calico-node
        - system:serviceaccount:kube-system:fluentd
      # 豁免特定 RuntimeClass
      runtimeClasses:
        - kata-runtime
        - gvisor
      # 豁免特定 Namespace
      namespaces:
        - kube-system
        - kube-node-lease
        - kube-public
        - monitoring

服務帳號豁免範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 為需要特權的服務帳號設定豁免
apiVersion: v1
kind: ServiceAccount
metadata:
  name: privileged-sa
  namespace: monitoring
---
# 在 PSA 配置中加入此服務帳號
# usernames:
#   - system:serviceaccount:monitoring:privileged-sa

動態豁免策略

1
2
3
4
5
6
7
8
9
# 使用 kubectl auth can-i 驗證權限
kubectl auth can-i create pods --as=system:serviceaccount:monitoring:privileged-sa

# 建立特權 Pod 測試豁免是否生效
kubectl run test-pod \
  --image=nginx \
  --overrides='{"spec":{"serviceAccountName":"privileged-sa"}}' \
  -n monitoring \
  --dry-run=server

監控與稽核

啟用 Audit Logging

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
  resources:
  - group: ""
    resources: ["pods"]
  namespaces: ["*"]
  verbs: ["create", "update", "patch"]

- level: RequestResponse
  users: ["system:anonymous"]
  resources:
  - group: ""
    resources: ["pods"]

設定 API Server 稽核

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 在 kube-apiserver 中啟用稽核
# /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
  containers:
  - command:
    - kube-apiserver
    - --audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml
    - --audit-log-path=/var/log/kubernetes/audit/audit.log
    - --audit-log-maxage=30
    - --audit-log-maxbackup=10
    - --audit-log-maxsize=100

使用 Prometheus 監控

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# ServiceMonitor for PSA metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: kube-apiserver
  namespace: monitoring
spec:
  endpoints:
  - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
    interval: 30s
    port: https
    scheme: https
    tlsConfig:
      insecureSkipVerify: true
  selector:
    matchLabels:
      component: apiserver

PSA 相關指標

1
2
3
4
5
6
# 查詢 PSA 違規指標
kubectl get --raw /metrics | grep pod_security

# 常見指標:
# pod_security_evaluations_total - 評估總數
# pod_security_exemptions_total - 豁免總數

使用 Falco 進行執行時期監控

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# falco-rules.yaml
- rule: Pod Created in Privileged Mode
  desc: Detect privileged pod creation
  condition: >
    kevt and
    kcreate and
    pod and
    ka.req.pod.containers.privileged = true    
  output: >
    Privileged pod created
    (user=%ka.user.name pod=%ka.resp.name ns=%ka.target.namespace)    
  priority: WARNING
  tags: [k8s, pod, privileged]

最佳實務與範例

1. 漸進式導入策略

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 第一階段:開啟警告模式
kubectl label namespace production \
  pod-security.kubernetes.io/warn=restricted

# 第二階段:開啟稽核模式
kubectl label namespace production \
  pod-security.kubernetes.io/audit=restricted

# 第三階段:觀察一段時間後強制執行
kubectl label namespace production \
  pod-security.kubernetes.io/enforce=restricted

2. 建立安全的 Deployment 範本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# secure-deployment-template.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: secure-app
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: secure-app
  template:
    metadata:
      labels:
        app: secure-app
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 10000
        runAsGroup: 10000
        fsGroup: 10000
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: app
        image: myapp:latest
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          capabilities:
            drop:
              - ALL
        resources:
          limits:
            cpu: "500m"
            memory: "256Mi"
          requests:
            cpu: "100m"
            memory: "128Mi"
        volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: cache
          mountPath: /var/cache
      volumes:
      - name: tmp
        emptyDir: {}
      - name: cache
        emptyDir: {}
      serviceAccountName: secure-app-sa
      automountServiceAccountToken: false

3. 使用 Kyverno 補充 PSS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# kyverno-policy.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-run-as-nonroot
spec:
  validationFailureAction: Enforce
  background: true
  rules:
  - name: check-runAsNonRoot
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      message: "Running as root is not allowed"
      pattern:
        spec:
          securityContext:
            runAsNonRoot: true
          containers:
          - securityContext:
              runAsNonRoot: true

4. CI/CD 整合驗證

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# .gitlab-ci.yml
stages:
  - validate

validate-pod-security:
  stage: validate
  image: bitnami/kubectl:latest
  script:
    - |
      for file in $(find ./k8s -name "*.yaml"); do
        echo "Validating: $file"
        kubectl apply --dry-run=server \
          -f "$file" \
          --namespace=test-restricted \
          2>&1 | tee -a validation.log
      done      
    - |
      if grep -q "violat" validation.log; then
        echo "Pod Security Standard violations found!"
        exit 1
      fi      

5. 多環境配置策略

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# namespace-configs.yaml
---
# 開發環境 - 寬鬆
apiVersion: v1
kind: Namespace
metadata:
  name: development
  labels:
    environment: dev
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/warn: restricted
---
# 測試環境 - 中等
apiVersion: v1
kind: Namespace
metadata:
  name: staging
  labels:
    environment: staging
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
---
# 正式環境 - 嚴格
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    environment: prod
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

6. 常見問題排解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 檢查 Pod 為何被拒絕
kubectl describe pod <pod-name> -n <namespace>

# 查看詳細的安全驗證結果
kubectl get events -n <namespace> --field-selector reason=FailedCreate

# 分析 Pod spec 的安全問題
kubectl auth can-i create pods --as=system:serviceaccount:<ns>:<sa> -n <namespace>

# 使用 kubectl debug 進行偵錯
kubectl debug -it <pod-name> --image=busybox --target=<container-name>

總結

Pod Security Standards 為 Kubernetes 提供了一套標準化且易於管理的安全機制。透過三個清晰的安全等級(Privileged、Baseline、Restricted)和三種執行模式(enforce、audit、warn),管理員可以靈活地控制叢集中的 Pod 安全性。

重點回顧

  1. 選擇適當的安全等級:根據工作負載需求選擇 Privileged、Baseline 或 Restricted
  2. 漸進式導入:先使用 warn/audit 模式測試,再逐步切換至 enforce
  3. 善用豁免機制:為系統元件設定適當的豁免
  4. 持續監控:透過 audit logging 和 metrics 監控安全狀態
  5. 自動化驗證:將安全檢查整合至 CI/CD pipeline

透過正確實施 Pod Security Standards,您可以大幅提升 Kubernetes 叢集的安全性,同時降低維運複雜度。

參考資源

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy