なぜPod Security Standardsが必要なのか
Kubernetesは便利なのですが、デフォルト設定のままのKubernetesは良く言えば自由性が高い、(あえて)悪く言えばセキュリティが緩いとよく評価されてしまいます。
Kubernetesのセキュリティを高める手段の手段の一つとして、Pod Security Policiesという機能がKubernetes 1.3の頃に実装されました。しかし、以下の理由によりKubernetes v1.21で非推奨の機能になり、v1.25でこの機能は機能削除される予定です(執筆日時点の最新安定版が1.24なので、次のメジャーリリースで機能削除されることになりそうです)。
- PodSecurityPolicy Deprecation: Past, Present, and Future
- KEP-2579: Pod Security Admission Control - Motivation
コンテナを使う限り、セキュリティについては注意を払う必要があるものの、正直なところ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について試してみる予定です。