こんにちは! Kubernetesのインフラ構築やSREの現場で、日夜クラスタの安定稼働とセキュリティ担保に奔走されている皆さん、お疲れ様です。
Kubernetesを運用していると、こんな悩みを持ったことはありませんか?
「開発チームが勝手に特権コンテナ(`privileged: true`)のPodをデプロイしてしまい、セキュリティ監査で冷や汗をかいた」
「すべてのPodにリクエスト制限(Resource Limits)をつけさせたいのに、誰もマニュアルを読んでくれない」
これを防ぐためにOPA/Gatekeeperを導入したものの、Regoという独自の言語の学習コストに挫折したり、CRDの山に圧倒されたりしたエンジニアを私は何人も見てきました。
そこで今回ご紹介するのが、Kubernetesネイティブなポリシーエンジン 「Kyverno(キベルノ)」 です。
これをマスターすれば、「普段私たちが書いている見慣れたYAMLの形式そのまま」 でKubernetesのガバナンスを完全に自動化できます。しかも、違反を検知するだけでなく 「勝手に修正してデプロイを通す(Mutate)」 という神がかった機能まで持っています。
今回は、初心者の方でも今日からすぐにプロダクション環境で使えるよう、優しく、かつ本質的なハンズオン形式で解説していきますね。これを読めば、あなたのクラスタの安全性は劇的に跳ね上がりますよ!
—
1. Kyvernoとは何か?なぜOPA/Gatekeeperより選ばれるのか
Kubernetesにおけるポリシー管理のデファクトスタンダードといえば、かつては OPA (Open Policy Agent) / Gatekeeper でした。しかし、OPAには大きな壁がありました。それが 「Rego(レゴ)」という独自クエリ言語 です。
「たった一つのラベルがついているかチェックしたいだけなのに、なぜ専用の関数や複雑なロジックを書かなければならないんだ……?」
そう絶望したSREたちの救世主として現れたのが Kyverno です。
Kyvernoの3つの圧倒的アドバンテージ
1. 完全なKubernetesネイティブ(YAMLで書ける)
ポリシー自体を普通のKubernetesリソース(YAML)として記述します。新しい言語を覚える必要はゼロです。
2. バリデーション(検査)だけでなく、ミューテーション(自動修正)とジェネレーション(自動生成)ができる
「間違っているから弾く」だけでなく、「足りない設定ならこっそり補って通す」という大人の解決が可能です。
3. 学習コストの低さと軽量性
クラスタ内のリソース変更をWebhookとして極めて軽量に処理するため、導入のハードルが非常に低いです。
—
2. インストールと基本セットアップ
それでは、手元の検証用Kubernetesクラスタ(KindやMinikube、Docker DesktopのK8sなど)に対して、Kyvernoをサクッとインストールしましょう。
Helmを使うのが最もモダンで確実です。以下のコマンドを叩くだけで、Kyvernoのコントローラーがクラスタに降臨します。
Helmリポジトリの追加
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
名前空間を作成してインストール
kubectl create namespace kyverno
helm install kyverno kyverno/kyverno \
–namespace kyverno \
–set replicaCount=1
インストールが成功したか、ポッドの状態を確認してみましょう。
kubectl get pods -n kyverno
すべてのポッドが `Running` になっていればセットアップ完了です!お疲れ様でした。これだけで、あなたのクラスタはポリシーを受け入れる準備が整いました。
—
3. 【実践その1】Podの必須セキュリティコンテストを強制する(Validate)
まずは基本の「バリデーション(検証)」から始めましょう。
現場で最もよくある要件:「rootユーザーでのコンテナ実行(Privileged Escalation)を絶対に禁止する」 というポリシーをKyvernoで実装します。
以下のマニフェストを `restrict-root-user.yaml` という名前で保存してください。
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-root-user
spec:
# 違反したときにどうするか(enforce: ブロックする / audit: ログに記録するだけ)
validationFailureAction: enforce
background: true
rules:
- name: check-run-as-non-root
match:
any:
- resources:
kinds:
- Pod
validate:
message: “セキュリティポリシー違反です:Podはrootユーザー(UID 0)で実行してはいけません。securityContext.runAsNonRootをtrueに設定してください。”
pattern:
spec:
# 少なくとも1つのコンテナ(Ephemeral, Init, 通常コンテナ)で設定をチェック
=(ephemeralContainers):
- securityContext:
runAsNonRoot: true
=(initContainers):
- securityContext:
runAsNonRoot: true
containers:
- securityContext:
runAsNonRoot: true
このYAMLの美しいポイント
`pattern` の中で、KubernetesのPod仕様をそのまま模倣して記述しています。「`containers` の中の `securityContext` に `runAsNonRoot: true` が書かれていること」を直感的に強制していますね。
これをクラスタに適用します。
kubectl apply -f restrict-root-user.yaml
動作確認:意図的にルールを破ってみる
それでは、あえてセキュリティ的にNGなPod(rootで動く設定のPod)をデプロイしてみましょう。
`bad-pod.yaml` を作成:
apiVersion: v1
kind: Pod
metadata:
name: insecure-nginx
spec:
containers:
- name: nginx
image: nginx:latest
# securityContextをあえて書き忘れた(=デフォルトでrootになり得る)
デプロイを試みます:
kubectl apply -f bad-pod.yaml
結果はどうなるでしょうか?
Error from server: error when creating “bad-pod.yaml”:
admission webhook “validate.kyverno.svc-fail” denied the request:
.spec.containers[0].securityContext.runAsNonRoot: required field missing
見事にAPIサーバーの入口でブロックされました!エラーメッセージも私たちが記述した親切な日本語が出力されています。開発者にとっても「なぜ拒否されたか」が一目でわかるため、問い合わせ対応のコストが劇的に減ります。
—
4. 【実践その2】違反リソースの神・自動修正(Mutate)
「ポリシー違反は弾く」だけがセキュリティではありません。優秀なインフラエンジニアは、「開発者が忘れたボロを、裏でこっそり直して綺麗にデプロイを通す」 優しい自動化を行います。
ここでは、「デプロイされるすべてのPodに、デフォルトでリソース制限(CPU/メモリのrequests/limits)を自動付与する」 というMutateポリシーを作ってみましょう。
`add-default-resources.yaml` を作成:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-default-resources
spec:
rules:
- name: set-default-cpu-memory
match:
any:
- resources:
kinds:
- Pod
mutate:
patchStrategicMerge:
spec:
containers:
# すべてのコンテナに対して適用
- (name): “”
resources:
# もしlimitsやrequestsが未設定なら、以下のデフォルト値を注入する
+usables:
limits:
cpu: “500m”
memory: “512Mi”
requests:
cpu: “100m”
memory: “128Mi”
これを適用します。
kubectl apply -f add-default-resources.yaml
自動修正の魔法を体験する
先ほど拒否された `bad-pod.yaml` に、先ほどの `runAsNonRoot: true` だけを最低限追加して、リソース設定は書かずにデプロイしてみます。
`good-pod.yaml` を作成:
apiVersion: v1
kind: Pod
metadata:
name: auto-fixed-nginx
spec:
containers:
- name: nginx
image: nginx:latest
securityContext:
runAsNonRoot: true
# リソース設定はあえて書いていない!
デプロイ!
kubectl apply -f good-pod.yaml
今度はエラーが出ずに、すんなり作成成功しました。
では、実際にKubernetes内部でこのPodがどう変形(Mutate)されたか、YAMLを覗いてみましょう。
kubectl get pod auto-fixed-nginx -o yaml
出力されたYAMLの `containers` 部分を確認してみてください。
spec:
containers:
- image: nginx:latest
name: nginx
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
securityContext:
runAsNonRoot: true
おぉ……!開発者がリソース設定を書き忘れたにもかかわらず、Kyvernoが裏側でいい感じにデフォルト値を補正して、安全な状態でPodを稼働させてくれました。
これが、現場のSREが思わずガッツポーズしてしまうKyvernoの真骨頂です。
—
5. まとめとさらなる高みへ
お疲れ様でした!今回はKyvernoを使って、以下の2点をハンズオン形式で体験しました。
1. Validate(バリデーション):危険なマニフェストのデプロイを未然に防ぐ。
2. Mutate(自動修正):足りないセキュリティ設定やリソース定義を自動で補う。
Kyvernoの素晴らしいところは、これらを 「使い慣れたKubernetesの文法(YAML)」 で記述できる点です。複雑な言語を新しく覚える必要はもうありません。
これをマスターすれば、開発スピードを落とすことなく、クラスタのセキュリティとガバナンスを鉄壁の要塞へと進化させることができます。「毎日の運用作業が劇的に楽になる」という感覚を、ぜひあなたのチームでも味わってみてください。
さらに深く知りたい方は、公式ドキュメントにある `Generate`(リソースの自動生成:例えばNamespaceを作ったら自動でNetworkPolicyもセットで作るなど)の機能にも挑戦してみてください。世界がさらに広がりますよ。
それでは、素晴らしいKubernetesライフを!