こんにちは、ようこそ。クラウドネイティブの世界へ。
Kubernetes(k8s)という広大な海に漕ぎ出したばかりのあなたにとって、その拡張性や自動化の仕組みは魔法のように見えるかもしれません。しかし、この魔法を「安全に」使いこなすためには、避けては通れない道があります。それが「セキュリティ」です。
多くのエンジニアが「動くこと」を優先するあまり、セキュリティを後回しにしてしまい、後に「特権コンテナの乗っ取り」や「権限設定の不備」による事故で血の気が引くような思いを経験します。私は、あなたにそんな思いをしてほしくありません。
今日は、私が長年の現場経験で培った「これさえ守れば夜も安心して眠れる」というk8sセキュリティの極意を、基礎から丁寧にお教えします。これをマスターすれば、あなたのインフラは「ただ動く」ものから「堅牢でプロフェッショナルな」基盤へと進化しますよ。
—
1. k8sセキュリティの全体像:4つのCを知る
Kubernetesのセキュリティを考える際、私はいつも「4Cモデル」を意識するように伝えています。
1. Cloud(クラウド基盤/物理サーバ)
2. Cluster(k8s自体の設定)
3. Container(イメージの脆弱性)
4. Code(アプリケーションの脆弱性)
今回は、我々SREの主戦場である「Cluster」と「Container」に焦点を絞ります。ここが疎かになると、たとえアプリが完璧でも、インフラの隙から全てを奪われてしまうからです。
—
2. 権限管理の基本:RBAC(Role-Based Access Control)
k8sには「誰が(Subject)」「何に対して(Resource)」「何ができるか(Verb)」を細かく制御するRBACという仕組みがあります。
初心者がやりがちな最大のミスは、全員に `cluster-admin`(神権限)を与えてしまうことです。これは家の鍵をかけずに街中を歩くようなもの。基本は「最小特権の原則(Least Privilege)」です。
【実践】読み取り専用の「閲覧者ロール」を作ってみよう
まずは、特定のNamespace(名前空間)のPodを「見るだけ」の権限を作ってみましょう。
view-pods-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: development
name: pod-reader
rules:
- apiGroups: [“”] # コアAPIグループを指定
resources: [“pods”] # 操作対象のリソース
verbs: [“get”, “watch”, “list”] # 許可する操作(作成や削除は含めない)
—
このRoleを特定のユーザー(ここではServiceAccount)に紐付けます
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-binding
namespace: development
subjects:
- kind: ServiceAccount
name: my-app-sa # アプリケーションが使うID
namespace: development
roleRef:
kind: Role
name: pod-reader # 上で定義したRoleを指定
apiGroup: rbac.authorization.k8s.io
プロの視点:
アプリケーションを実行する際は、デフォルトの `default` ServiceAccountを使わず、アプリごとに専用のServiceAccountを作成してください。これだけで、万が一アプリが乗っ取られた際の被害を最小限に食い止める(爆風半径を抑える)ことができます。
—
3. Pod Security Standards:コンテナに「わがまま」を許さない
次に、Podそのものの挙動を制限します。かつてはPodSecurityPolicyという複雑な仕組みがありましたが、現在はよりシンプルで強力なPod Security Admission (PSA)に統合されました。
PSAには3つのプロファイルがあります:
- Privileged: 無制限(非推奨)
- Baseline: 最小限の制限(一般的なアプリ用)
- Restricted: 極めて厳格(理想。root実行禁止など)
【実践】Namespaceにセキュリティポリシーを強制する
Namespaceにラベルを貼るだけで、その中で動くPodに厳しいルールを課すことができます。
‘production’ 名前空間に ‘restricted’ プロファイルを適用する
これにより、rootユーザーで動くPodなどは起動すらできなくなります
kubectl label –overwrite ns production \
pod-security.kubernetes.io/enforce=restricted
【設定例】「Restricted」に合格するクリーンなPod定義
`restricted` ポリシー下で動作するPodは、以下のように「自分自身の権限を放棄する」設定が必要です。
apiVersion: v1
kind: Pod
metadata:
name: secure-nginx
namespace: production
spec:
securityContext:
# Pod全体での設定:root以外のユーザー(1000番)で実行
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault # OSのシステムコールを制限
containers:
- name: nginx
image: nginxinc/nginx-unprivileged:latest # 非root用のイメージを使うのがコツ
securityContext:
# コンテナ個別の設定
allowPrivilegeEscalation: false # 権限昇格を禁止
capabilities:
drop: [“ALL”] # 不要なOS機能をすべて捨てる
readOnlyRootFilesystem: true # ファイルシステムを読み取り専用にする
現場の知見:
`readOnlyRootFilesystem: true` は非常に強力です。攻撃者がコンテナ内にマルウェアをダウンロードして実行することを物理的に防げます。一時的な書き込みが必要な場合は `emptyDir` ボリュームを特定ディレクトリにマウントしましょう。
—
4. 脆弱性スキャンの導入:敵を知り、己を知る
最後に、コンテナイメージ自体の「健康診断」です。どれだけインフラを固めても、イメージ内に古いライブラリ(OpenSSLの脆弱性など)があれば、そこが突破口になります。
現代のデファクトスタンダードは Trivy です。
【導入と確認】Trivyでイメージをスキャンする
インストールは簡単です(Macなら `brew install aquasecurity/trivy/trivy`)。
nginxイメージの脆弱性をチェック
trivy image nginx:latest
実行すると、深刻度(CRITICAL, HIGH…)ごとに脆弱性がリストアップされます。これをCI/CDパイプライン(GitHub Actionsなど)に組み込み、「CRITICALな脆弱性があるイメージはデプロイさせない」という仕組みを構築するのが、一流のSREへの第一歩です。
—
最後に:セキュリティは「文化」である
今日お伝えしたRBAC、Pod Security、脆弱性スキャン。これらは単なる設定値ではありません。あなたのサービスを利用するユーザーの大切なデータを守るための「盾」です。
最初は少し窮屈に感じるかもしれません。YAMLがエラーで通らないこともあるでしょう。しかし、そのエラーこそが「あなたのインフラが安全に守られた瞬間」なのです。
「これを設定したおかげで、今日も平和に運用できているな」
そう思えるようになった時、あなたはもう立派なKubernetesエンジニアです。一歩ずつ、確実に。あなたの挑戦をいつも応援していますよ。
何か困ったことがあれば、いつでも聞いてくださいね。それでは、安全なk8sライフを!