仮想化通信

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

Kubernetesで名前空間レベルのPod Security Standardsを試してみた

なぜPod Security Standardsが必要なのか

Kubernetesは便利なのですが、デフォルト設定のままのKubernetesは良く言えば自由性が高い、(あえて)悪く言えばセキュリティが緩いとよく評価されてしまいます。

Kubernetesのセキュリティを高める手段の手段の一つとして、Pod Security Policiesという機能がKubernetes 1.3の頃に実装されました。しかし、以下の理由によりKubernetes v1.21で非推奨の機能になり、v1.25でこの機能は機能削除される予定です(執筆日時点の最新安定版が1.24なので、次のメジャーリリースで機能削除されることになりそうです)。

コンテナを使う限り、セキュリティについては注意を払う必要があるものの、正直なところPod Security Policiesは使いにくいものでした。Pod Security Policiesの非推奨化に対し、新しく実装されたのがPod Security Standardsです。これはデフォルトで有効化されている機能なので、クラスターの設定をあれこれ変える必要なく実行できる点がPod Security Policiesよりも使いやすいです。

ポッドセキュリティアドミッション(PSA)は、ベータ版に移行したため、v1.23以降ではデフォルトで有効になっています。ポッドセキュリティアドミッションは、Podsの作成時にPod Security Standardsを適用するアドミッションコントローラです。

Pod Security Standardsは名前空間レベルに対して設定する方法と、クラスタレベルで設定する方法があるようです。クラスタレベルで設定する場合はKubernetes API Serverの設定変更が必要ですが、名前空間レベルの方は特に大きな設定変更をすることなく使えるようです。今回はPod Security Standardsを1つの名前空間に適用するのを試してみます。

Kindのインストール

KubernetesのPod Security Standards機能を試すため、Kubernetesクラスターを作成します。 Kubernetes公式のPod Security StandardsチュートリアルでKindを使っているので、それに合わせてみます。

まずはKindのインストールから。この記事を書いたときの最新はv0.14.0が最新でした。 今回はUbuntu環境にセットアップを想定しているため、バイナリを使ってインストールします(Kindの実行には事前にDockerのインストールが必要です)。

$ curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.14.0/kind-linux-amd64
$ chmod +x ./kind
$ sudo mv ./kind /usr/local/bin
$ kind --version
kind version 0.14.0

他のOSにインストールする場合はKind QuickStartを参考にインストールします。 kubectl CLIも対応するバージョンがインストールされていない場合は導入します。

$ curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.23.6/bin/linux/amd64/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl

Kindでクラスターを作成

クラスターを作る前に、後でアプリの動作確認でNodePortを使いたいため、Kindの設定ファイルを作っておきます。 Podセキュリティ標準のチュートリアルではKubernetesクラスターのバージョンがv1.23を指定していることから、設定ファイルにKuberentes v1.23のバージョンを指定しています。 ここで指定できるバージョンはKindリリースに書かれているものが指定できます。

1.24も利用できますが、今回はチュートリアルに合わせてv1.23で確認しました。

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  image: kindest/node:v1.23.6@sha256:b1fa224cc6c7ff32455e0b1fd9cbfd3d3bc87ecaa8fcb06961ed1afb3db0f9ae
  extraPortMappings:
  - containerPort: 30080
    hostPort: 30080
  - containerPort: 30443
    hostPort: 30443

設定ファイルを使ってクラスターを作成します。

$ kind create cluster --name psa-wo-cluster-pss --config=config.yaml

問題なければ次のような感じでログ出力されます。

Creating cluster "psa-wo-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-wo-cluster-pss"
You can now use your cluster with:

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

Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂

メッセージが表示されていたように、コマンドを実行してみます。 次のような感じで出力されれば、クラスターとして稼働していることがわかります。

$ kubectl cluster-info --context kind-psa-wo-cluster-pss
Kubernetes control plane is running at https://127.0.0.1:38679
CoreDNS is running at https://127.0.0.1:38679/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.6", GitCommit:"ad3338546da947756e8a88aa6822e9c11e7eac22", GitTreeState:"clean", BuildDate:"2022-04-14T08:49:13Z", GoVersion:"go1.17.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.6", GitCommit:"ad3338546da947756e8a88aa6822e9c11e7eac22", GitTreeState:"clean", BuildDate:"2022-05-19T19:39:28Z", GoVersion:"go1.17.9", Compiler:"gc", Platform:"linux/amd64"}

テスト用の名前空間を作成する

今回のテストを試すために使う名前空間を作成します。exampleという名前空間を使ってみます。

$ kubectl create ns example
namespace/example created

Pod Security Standardsを有効化する

  • 組み込みのPodセキュリティアドミッションでサポートされているラベルを使用して、この名前空間でPodセキュリティ標準を有効にします。 このステップでは、最新バージョンのベースラインPodセキュリティ標準(デフォルト)について警告します。
$ kubectl label --overwrite ns example \
   pod-security.kubernetes.io/warn=baseline \
   pod-security.kubernetes.io/warn-version=latest

ここで指定できるフラグは次の3つのようです。

設定値 内容
enforce Podの作成を拒否します
audit audit logを記録します。Podの作成は拒否しません
warn 警告を表示します。Podの作成は拒否しません
  • ラベルを使用して、任意の名前空間で複数のポッドセキュリティ標準を有効にできます。 次のコマンドは、ベースラインのPodセキュリティ標準を適用しますが、最新バージョン(デフォルト値)の制限されたPodセキュリティ標準について警告および監査します。
$ kubectl label --overwrite ns example \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/enforce-version=latest \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/warn-version=latest \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/audit-version=latest

Pod Security Standardsを試す

こんなファイルを作ってPodを作成して、Podセキュリティ標準の動きを試してみます。

$ mkdir -p /tmp/pss
$ touch /tmp/pss/nginx-pod.yaml
$ 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 Security Standardsを定義した名前空間である「example」でPodを作ってみます。

$ kubectl apply -n example -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    #警告は出ているが、Podは作成される

$ kubectl get pods -n example
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          59s

次に、同じマニフェストファイルを使って、名前空間「default」にPodを作成してみます。

$ kubectl apply -n default -f /tmp/pss/nginx-pod.yaml

こちらは警告が表示されることなく、Podが作成されます。

pod/nginx created

$ kubectl get pods -n default
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          13s

Pod Security Standardsは、サンプルの名前空間(本例ではexample)にのみ適用されるのを確認できました。同様に、デフォルトの名前空間では警告なしで同じ(マニフェストファイルを使って)Podを作成できることがか確認できました。

次回はクラスターレベルのPod Security Standardsについて試してみる予定です。