💨

PodSecurityPolicy から組み込み PodSecurity Admission Controller への移行

2023/08/14に公開

これはなに?

PodSecurityPolicy (PSP) は Kubernetes バージョン 1.21 で非推奨となり、Kubernetes 1.25 で削除されるため代替手段となる PodSecurity Admission Controller (PSA) への移行方法をまとめたものである。

手順

ネームスペースに対して以下のラベルを設定していく。

  • pod-security.kubernetes.io/audit
  • pod-security.kubernetes.io/enforce
  • pod-security.kubernetes.io/warn

PSA は、privilegedbaseline、およびrestrictedの3つのポリシーレベルを提供するため、ドライランを利用しながらポリシーレベルを調整していくと良い。

ここでは、kube-system ネームスペースに対してドライラン後に更新を実施してみる。

ドライラン

ポリシーレベルは restricted -> baseline -> privileged の順に検証する。

# restricted or baseline or privileged
$ LEVEL="privileged"

$ NAMESPACE="kube-system"

$ kubectl label --dry-run=server --overwrite ns $NAMESPACE pod-security.kubernetes.io/enforce=$LEVEL

namespace/kube-system labeled

上記の様にワーニングが出力されなければ問題ない。

更新

ドライランが問題なければ以下のコマンドで更新をかけていく。

$ kubectl label --overwrite ns $NAMESPACE pod-security.kubernetes.io/audit=$LEVEL

namespace/kube-system labeled

$ kubectl label --overwrite ns $NAMESPACE pod-security.kubernetes.io/enforce=$LEVEL

namespace/kube-system labeled

$ kubectl label --overwrite ns $NAMESPACE pod-security.kubernetes.io/warn=$LEVEL

namespace/kube-system labeled

確認

ネームスペースのラベルが正しく設定されているか確認する。
以下のラベルが設定されていること。

  • pod-security.kubernetes.io/audit
  • pod-security.kubernetes.io/enforce
  • pod-security.kubernetes.io/warn
$ kubectl get ns --show-labels
NAME                STATUS   AGE      LABELS
...
kube-system         Active   2y240d   kubernetes.io/metadata.name=kube-system,pod-security.kubernetes.io/audit=privileged,pod-security.kubernetes.io/enforce=privileged,pod-security.kubernetes.io/warn=privileged
...

さらに、ログ等でエラーが出力されていないか確認しておくとよい。

動作確認

テスト用のネームスペースを作成後、そのネームスペース内で Pod を作成し、PodSecurityAdmission ポリシーが適用されていることを検証する。

$ echo 'apiVersion: v1
kind: Namespace
metadata:
  name: test-psa
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/audit: baseline
    pod-security.kubernetes.io/warn: baseline
' > test-psa.yaml

$ kubectl apply -f test-psa.yaml

namespace/test-psa created

$ kubectl get ns test-psa --show-labels

NAME       STATUS   AGE   LABELS
test-psa   Active   28s   kubernetes.io/metadata.name=test-psa,pod-security.kubernetes.io/audit=baseline,pod-security.kubernetes.io/enforce=baseline,pod-security.kubernetes.io/warn=baseline

$ echo 'apiVersion: v1
kind: Pod
metadata:
  labels:
    app: test-pod
  name: test-pod
  namespace: test-psa
spec:
  containers:
  - name: test-container
    image: nginx
' > test-pod.yaml

$ kubectl apply -f test-pod.yaml

pod/test-pod created

$ kubectl get pod -n test-psa -l app=test-pod

NAME       READY   STATUS    RESTARTS   AGE
test-pod   1/1     Running   0          12s

$ echo 'apiVersion: v1
kind: Pod
metadata:
  labels:
    app: test-pod2
  name: test-pod2
  namespace: test-psa
spec:
  containers:
  - name: test-container2
    image: nginx
    securityContext:
      privileged: true
' > test-pod2.yaml

$ kubectl apply -f test-pod2.yaml

Error from server (Forbidden): error when creating "test-pod2.yaml": pods "test-pod2" is forbidden: violates PodSecurity "baseline:latest": privileged (container "test-container2" must not set securityContext.privileged=true)

-> baseline に違反するのでPodは作成されないはず

$ kubectl delete -f test-pod.yaml

pod "test-pod" deleted

$ kubectl delete -f test-psa.yaml

namespace "test-psa" deleted

$ rm test-psa.yaml
$ rm test-pod*.yaml

Discussion