仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

KubernetesのクラスタレベルでのPod Security Standardsの適用を試す

Pod Securityは、新しいPodが作成されたときにKubernetes Pod Security Standardsに対するチェックを実行するアドミッションコントローラーです。 端的にいうと、Podを作成するときのセキュリティ上のルールを定義して、それに従わせるためのものです。Pod Securityを適切に使うことで、Kubernetesクラスターの安全性がより高まります。

tech.virtualtech.jp

前回は特定の名前空間でのみ適用されるPod Security Standardsを試しましたが、今回はチュートリアル「Apply Pod Security Standards at Cluster level」をもとに、クラスター内のすべての名前空間に標準構成を適用するクラスターレベルでPod Security Standardsを適用するのを試してみます。

ポリシーについておさらい

Pod Security Standardsで設定できるポリシーについては、次にまとめられています。

kubernetes.io

特権(Privileged)、ベースライン、制限(Restricted)と言うポリシーがあり、特権(Privileged)は何も制限がかけられていないポリシー、ベースラインは容易に適用しやすく、かつ既知の特権昇格を防ぐことを意図するようなポリシーが定義されています。制限(Restricted)は柔軟性を犠牲にして、できるかぎりセキュリティを担保するためのポリシーのようです。

ちなみにベースラインのSELinuxやAppArmorについては、それぞれがホストで実行されるOSで一般的に使える状態でないと利用できないと思われます。例えばDebianやUbuntuなどではAppArmor、RHELやRHELクローンではSELinuxが設定できます。

ポリシーを定義する

今回はベースラインは強制し、制限(Restricted)は警告とAuditログを出力する設定をクラスターに行ってみます。 これらの仕様でPod Security Standardsを実装するために、Podセキュリティアドミッションコントローラの設定ファイルを作成します。

$ mkdir -p /tmp/pss
$ cat <<EOF > /tmp/pss/cluster-level-pss.yaml 
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
  configuration:
    apiVersion: pod-security.admission.config.k8s.io/v1beta1
    kind: PodSecurityConfiguration
    defaults:
      enforce: "baseline"
      enforce-version: "latest"
      audit: "restricted"
      audit-version: "latest"
      warn: "restricted"
      warn-version: "latest"
    exemptions:
      usernames: []
      runtimeClasses: []
      namespaces: [kube-system]
EOF

公式チュートリアルに説明が特にありませんが、exemptionsで例外を設定できます。クラスタレベルでPod Security Standardsを設定するのにあたり、Kubernetesシステムにこの影響が出ないようにするため、Kubernetesシステムが主に動く名前空間kube-systemを除外しています。

Kindクラスター作成マニフェストの作成

Kindでクラスターを作成するため、次のようなマニフェストファイルを作成します。前回とは異なり、色々な設定を仕込んでいます。

cat <<EOF > /tmp/pss/cluster-config.yaml 
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  image: kindest/node:v1.23.6@sha256:b1fa224cc6c7ff32455e0b1fd9cbfd3d3bc87ecaa8fcb06961ed1afb3db0f9ae  #バージョンを指定
  kubeadmConfigPatches:  #以下APIの設定変更
  - |
    kind: ClusterConfiguration
    apiServer:
        extraArgs:
          admission-control-config-file: /etc/config/cluster-level-pss.yaml
        extraVolumes:
          - name: accf
            hostPath: /etc/config
            mountPath: /etc/config
            readOnly: false
            pathType: "DirectoryOrCreate"
  extraMounts:
  - hostPath: /tmp/pss
    containerPath: /etc/config
    # optional: if set, the mount is read-only.
    # default false
    readOnly: false
    # optional: if set, the mount needs SELinux relabeling.
    # default false
    selinuxRelabel: false
    # optional: set propagation mode (None, HostToContainer or Bidirectional)
    # see https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation
    # default None
    propagation: None
EOF

KindでKubernrtesクラスターの作成

まずはクラスターを作成します。

$ kind create cluster --name psa-with-cluster-pss --config /tmp/pss/cluster-config.yaml
Creating cluster "psa-with-cluster-pss" ...
 ✓ Ensuring node image (kindest/node:v1.23.6) 🖼 
 ✓ Preparing nodes 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Set kubectl context to "kind-psa-with-cluster-pss"
You can now use your cluster with:

kubectl cluster-info --context kind-psa-with-cluster-pss

Have a nice day! 👋

Podの作成

前の記事でも使ったマニフェストを使ってPodを作成します。

$ cat <<EOF > /tmp/pss/nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - image: nginx
      name: nginx
      ports:
        - containerPort: 80
EOF

Podを作ると警告が表示されるがPodは作成されます。

$ kubectl apply -n default -f /tmp/pss/nginx-pod.yaml
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "nginx" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
pod/nginx created

$ kubectl get po -n default
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          131m

名前空間testでPodを作っても同様になります。これにより、クラスタレベルのPod Security Standardsが設定されていることが確認できました。

$ kubectl create ns test
namespace/test created

$ kubectl apply -n test -f /tmp/pss/nginx-pod.yaml
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "nginx" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
pod/nginx created

$ kubectl get po -n test
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          131m

本番環境ではPod Security Standardsは設定したほうが良いと感じました。Pod Security Policiesを現在導入しているクラスターについてはKubernetes 1.25で機能が削除されるので、現在のKubernetesクラスターのバージョンがサポートされている間にPod Security Standardsへの移行を早めに行っておくべきでしょう。