はじめに

Kubernetes 1.25 での PodSecurityPolicy (PSP) の廃止に伴って、
PSP は PodSecurity Admission (PSA) および Pod Security Standards (PSS) に置き換えられます。

本記事では、Amazon EKS における次の2点について記載しています。

  • PSPの削除手順
  • PSA / PSS の移行手順

EKS クラスタ自体のアップグレードに関する手順、マネコン操作の解説は省略させていただきます。

 

PodSecurityPolicy (PSP) とは

Kubernetes アドミッション コントローラであり、Pod レベルでのセキュリティ制御を行い、
デプロイされたワークロードのセキュリティ構成を細かく制御することができました。

PSP は Kubernetes 1.21 から非推奨となり、1.25 で廃止となります。

EKS クラスタを 1.25 にアップグレードする際には
後述の PodSecurity Admission (PSA) に置き換える必要があります。

 

PodSecurity Admission (PSA) とは

PSA は Kubernetes 1.21 から使用できるようになり、1.25 から必須となる Pod レベルの制御方法です。

Pod Security Standards (PSS) に基づいて Pod の Security Context 設定をチェックし、
必要に応じて Warning メッセージや Audit ログを出力させたり、PSS に違反した Pod の作成を停止することも可能です。

MODE と LEVEL を組み合わせ、Namespace もしくは Pod ごとにラベルを設定します。

 

PSA の MODE

Pod Security Admission labels for namespaces

MODE 説明
enforce ポリシーに違反した場合、Podの起動は拒否されます。
audit ポリシーに違反した場合、監査ログに記録されるイベントに監査アノテーションを追加するトリガーとなりますが、それ以外は許可されます。
warn ポリシーに違反した場合、ユーザーへの警告がトリガーされますが、それ以外は許可されます。

 

PSA の LEVEL

Pod Security Standards

Profile 説明
privileged 無制限のポリシー。可能な限り幅広いレベルの権限を提供します。 このポリシーでは、既知の権限昇格が許可されます。
baseline 既知の権限昇格を防ぐ最小限の制限ポリシー。 デフォルトの (最小限に指定された) Pod 構成を許可します。
restricted 現在のPod 強化のベストプラクティスに従って、厳しく制限されたポリシー。

 

PSP の利用状況確認

現在稼働中の EKS クラスタバージョンと、Worker Node の稼働状況を確認します。
EKS Server (クラスタ)バージョンは 1.24 で稼働しており、1台の Worker Node が起動しています。

$ kubectl version --short
Flag --short has been deprecated, and will be removed in the future. The --short output will become the default.
Client Version: v1.25.4
Kustomize Version: v4.5.7
Server Version: v1.24.17-eks-f8587cb
$ kubectl get nodes -o wide
NAME                                               STATUS   ROLES    AGE     VERSION                INTERNAL-IP     EXTERNAL-IP      OS-IMAGE         KERNEL-VERSION                  CONTAINER-RUNTIME
ip-192-168-24-79.ap-northeast-1.compute.internal   Ready    <none>   4d21h   v1.24.13-eks-0a21954   192.168.24.79   13.231.201.233   Amazon Linux 2   5.10.179-168.710.amzn2.x86_64   containerd://1.6.19

検証のための環境では以下の Pod が稼働しています。

$ kubectl get pods -A
NAMESPACE      NAME                                            READY   STATUS    RESTARTS        AGE
cert-manager   cert-manager-795d7f859d-bjqkw                   1/1     Running   0               129d
cert-manager   cert-manager-cainjector-5fcddc948c-7t8rx        1/1     Running   0               15h
cert-manager   cert-manager-webhook-5b64f87794-8bzq9           1/1     Running   0               129d
default        common-squid-6ff4d9b67f-crmx5                   1/1     Running   0               129d
default        common-squid-6ff4d9b67f-cxdlk                   1/1     Running   0               129d
default        external-dns-f7dcdf675-7tdsc                    1/1     Running   0               129d
kube-system    aws-load-balancer-controller-7897cc48d7-sfl6s   1/1     Running   0               129d
kube-system    aws-node-m9c9t                                  1/1     Running   0               4d21h
kube-system    common-fluentd-cvb44                            1/1     Running   0               4d21h
kube-system    coredns-69769bcfc6-4gvcn                        1/1     Running   0               129d
kube-system    coredns-69769bcfc6-t5gsf                        1/1     Running   0               129d
kube-system    ebs-csi-controller-84f59985bb-pq9t6             6/6     Running   0               129d
kube-system    ebs-csi-controller-84f59985bb-tqx57             6/6     Running   0               129d
kube-system    ebs-csi-node-g2pdd                              3/3     Running   0               4d21h
kube-system    kube-proxy-snxh7                                1/1     Running   0               4d21h
kube-system    kube2iam-9vx5c                                  1/1     Running   0               4d21h
kube-system    metrics-server-6fc695f67c-l889k                 1/1     Running   1 (4d21h ago)   129d

続いて、現在 PSP でセキュリティ制御している namespace を確認します。
ポッドセキュリティポリシー (PSP) の削除に関するよくある質問

クラスター内の PSPs が影響を与えている Pods を確認するには、次のコマンドを実行します。このコマンドは Pod 名、名前空間、PSPs を出力します。

kubectl get pod -A -o jsonpath='{range.items[?(@.metadata.annotations.kubernetes\.io/psp)]}{.metadata.name}{“\t”}{.metadata.namespace}{“\t”}{.metadata.annotations.kubernetes\.io/psp}{“\n”}’

以下の結果から3つの namespace で PSP を使用していることがわかります。

  • default
  • cert-manager
  • kube-system
$ kubectl get pod -A -o jsonpath='{range.items[?(@.metadata.annotations.kubernetes\.io/psp)]}{.metadata.name}{"\t"}{.metadata.namespace}{"\t"}{.metadata.annotations.kubernetes\.io/psp}{"\n"}'
cert-manager-795d7f859d-bjqkw   cert-manager    eks.privileged
cert-manager-cainjector-5fcddc948c-7t8rx        cert-manager    eks.privileged
cert-manager-webhook-5b64f87794-8bzq9   cert-manager    eks.privileged
common-squid-6ff4d9b67f-crmx5   default eks.privileged
common-squid-6ff4d9b67f-cxdlk   default eks.privileged
external-dns-f7dcdf675-7tdsc    default eks.privileged
aws-load-balancer-controller-7897cc48d7-sfl6s   kube-system     eks.privileged
aws-node-m9c9t  kube-system     eks.privileged
common-fluentd-cvb44    kube-system     eks.privileged
coredns-69769bcfc6-4gvcn        kube-system     eks.privileged
coredns-69769bcfc6-t5gsf        kube-system     eks.privileged
ebs-csi-controller-84f59985bb-pq9t6     kube-system     eks.privileged
ebs-csi-controller-84f59985bb-tqx57     kube-system     eks.privileged
ebs-csi-node-g2pdd      kube-system     eks.privileged
kube-proxy-snxh7        kube-system     eks.privileged
kube2iam-9vx5c  kube-system     eks.privileged
metrics-server-6fc695f67c-l889k kube-system     eks.privileged

namespace default について詳細情報を取得すると、Allow Privileged が true であり、
namespace ごとに PSP が設定されていることがわかります。

同様に -n オプションで cert-manager と kube-system を指定し、それぞれ確認することが可能です。

$ kubectl describe -n default psp eks.privileged
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
Name:  eks.privileged

Settings:
  Allow Privileged:                       true
  Allow Privilege Escalation:             true
  Default Add Capabilities:               <none>
  Required Drop Capabilities:             <none>
  Allowed Capabilities:                   *
  Allowed Volume Types:                   *
  Allow Host Network:                     true
  Allow Host Ports:                       0-65535
  Allow Host PID:                         true
  Allow Host IPC:                         true
  Read Only Root Filesystem:              false
  SELinux Context Strategy: RunAsAny      
    User:                                 <none>
    Role:                                 <none>
    Type:                                 <none>
    Level:                                <none>
  Run As User Strategy: RunAsAny          
    Ranges:                               <none>
  FSGroup Strategy: RunAsAny              
    Ranges:                               <none>
  Supplemental Groups Strategy: RunAsAny  
    Ranges:                               <none>

PSP の削除

デフォルトの Amazon EKS Pod セキュリティポリシーを削除する

AWS 公式のドキュメントを参考に、privileged-podsecuritypolicy.yaml というファイル名で
マニフェストを作成し、作業ディレクトリに配置します。

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: eks.privileged
  annotations:
    kubernetes.io/description: 'privileged allows full unrestricted access to
      Pod features, as if the PodSecurityPolicy controller was not enabled.'
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
  labels:
    kubernetes.io/cluster-service: "true"
    eks.amazonaws.com/component: pod-security-policy
spec:
  privileged: true
  allowPrivilegeEscalation: true
  allowedCapabilities:
  - '*'
  volumes:
  - '*'
  hostNetwork: true
  hostPorts:
  - min: 0
    max: 65535
  hostIPC: true
  hostPID: true
  runAsUser:
    rule: 'RunAsAny'
  seLinux:
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'RunAsAny'
  fsGroup:
    rule: 'RunAsAny'
  readOnlyRootFilesystem: false

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: eks:podsecuritypolicy:privileged
  labels:
    kubernetes.io/cluster-service: "true"
    eks.amazonaws.com/component: pod-security-policy
rules:
- apiGroups:
  - policy
  resourceNames:
  - eks.privileged
  resources:
  - podsecuritypolicies
  verbs:
  - use

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: eks:podsecuritypolicy:authenticated
  annotations:
    kubernetes.io/description: 'Allow all authenticated users to create privileged Pods.'
  labels:
    kubernetes.io/cluster-service: "true"
    eks.amazonaws.com/component: pod-security-policy
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: eks:podsecuritypolicy:privileged
subjects:
  - kind: Group
    apiGroup: rbac.authorization.k8s.io
    name: system:authenticated</blockquote>

namespace default を指定し、以下コマンドにて PSP 削除します。

$ kubectl delete -n default -f privileged-podsecuritypolicy.yaml
warning: deleting cluster-scoped resources, not scoped to the provided namespace
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy "eks.privileged" deleted
clusterrole.rbac.authorization.k8s.io "eks:podsecuritypolicy:privileged" deleted
clusterrolebinding.rbac.authorization.k8s.io "eks:podsecuritypolicy:authenticated" deleted

再度、default について詳細情報を取得すると、PSP の利用が無いことを確認できます。
コマンド記載は省略しますが、同様に namespace cert-manager と kube-system でも PSP を削除します。

$ kubectl describe -n default psp eks.privileged
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
Error from server (NotFound): podsecuritypolicies.policy "eks.privileged" not found

PSP を削除したことで EKS クラスタのバージョンを 1.25 にアップグレードする準備が整いました。

PSA / PSS の動作確認

EKS クラスタバージョンを 1.25 にアップグレードし、バージョン情報と Pod の稼働状態を確認します。

$ kubectl version --short
Flag --short has been deprecated, and will be removed in the future. The --short output will become the default.
Client Version: v1.24.17-eks-43840fb
Kustomize Version: v4.5.4
Server Version: v1.25.15-eks-4f4795d

PSA / PSS は何もせずとも標準的に動作し、すべての Pod が正常に起動しています。
pod-security のラベル未設定状態では PSS Level privileged、つまり権限昇格が許可されています。

$ kubectl get pods -A
NAMESPACE      NAME                                            READY   STATUS    RESTARTS      AGE
cert-manager   cert-manager-795d7f859d-zlshs                   1/1     Running   0             11m
cert-manager   cert-manager-cainjector-5fcddc948c-97vcb        1/1     Running   0             11m
cert-manager   cert-manager-webhook-5b64f87794-7jfnc           1/1     Running   0             11m
default        common-squid-6ff4d9b67f-crjdh                   1/1     Running   0             11m
default        common-squid-6ff4d9b67f-l7n8t                   1/1     Running   0             11m
default        external-dns-f7dcdf675-dw9bs                    1/1     Running   0             11m
kube-system    aws-load-balancer-controller-7897cc48d7-4lwtf   1/1     Running   0             11m
kube-system    aws-node-2jckq                                  1/1     Running   0             13m
kube-system    aws-node-l5hrp                                  1/1     Running   0             12m
kube-system    common-fluentd-6k9gn                            1/1     Running   0             12m
kube-system    common-fluentd-p2hf5                            1/1     Running   0             13m
kube-system    coredns-5857dd7484-n6kqd                        1/1     Running   0             11m
kube-system    coredns-5857dd7484-p65jf                        1/1     Running   0             11m
kube-system    ebs-csi-controller-84f59985bb-dlj98             6/6     Running   0             11m
kube-system    ebs-csi-controller-84f59985bb-wts49             6/6     Running   0             10m
kube-system    ebs-csi-node-bkqv7                              3/3     Running   0             12m
kube-system    ebs-csi-node-htt85                              3/3     Running   0             13m
kube-system    kube-proxy-bbzjr                                1/1     Running   0             13m
kube-system    kube-proxy-hrrpx                                1/1     Running   0             12m
kube-system    kube2iam-5xglw                                  1/1     Running   0             12m
kube-system    kube2iam-r6f65                                  1/1     Running   0             13m
kube-system    metrics-server-6fc695f67c-gkrg7                 1/1     Running   1 (11m ago)   11m

namespace ごとのラベルを確認すると、デフォルトでは pod-security のラベルがついていません。

$ kubectl get ns --show-labels
NAME              STATUS   AGE    LABELS
cert-manager      Active   139d   kubernetes.io/metadata.name=cert-manager
default           Active   139d   kubernetes.io/metadata.name=default
kube-node-lease   Active   139d   kubernetes.io/metadata.name=kube-node-lease
kube-public       Active   139d   kubernetes.io/metadata.name=kube-public
kube-system       Active   139d   kubernetes.io/metadata.name=kube-system

前述の通り、pod-security のラベルはつけなくとも暗黙的に PSS Level privileged で動作しますが、
個人的には運用中の混乱を避けるため、明示的につけた方が良いと考えます。

namespace kube-system に PSS Level privileged を設定します。

$ kubectl label --overwrite ns kube-system pod-security.kubernetes.io/enforce=privileged
namespace/kube-system labeled

カンマ区切りで kube-system にラベルが付与されたことが確認できます。

$ kubectl get ns --show-labels
NAME              STATUS   AGE    LABELS
cert-manager      Active   139d   kubernetes.io/metadata.name=cert-manager
default           Active   139d   kubernetes.io/metadata.name=default
kube-node-lease   Active   139d   kubernetes.io/metadata.name=kube-node-lease
kube-public       Active   139d   kubernetes.io/metadata.name=kube-public
kube-system       Active   139d   kubernetes.io/metadata.name=kube-system,pod-security.kubernetes.io/enforce=privileged

pod-security の削除について

PSS MODE や Level を変えて、Pod が起動拒否される、されない、
audit ログを見たい、いや warnだけでいい等、検証したいこともあるかと思います。

検証していたところ、ラベルは PSS MODE 違いで複数付与できたので
MODE enforce と MODE warn のラベルを同時付与することもできてしまいます。

その場合どちらの MODE で動作しているかよくわからなくなってしまうので、
一度付与したラベルは次のコマンドで削除します。

$ kubectl label ns kube-system pod-security.kubernetes.io/enforce-
$ kubectl label ns kube-system pod-security.kubernetes.io/audit-
$ kubectl label ns kube-system pod-security.kubernetes.io/warn-