1. SecurityContext
SecurityContextはPodまたはContainerの権限とアクセス制御を定義します。
apiVersion: v1
kind: Pod
spec:
securityContext: # Podレベル: 全コンテナに適用
runAsUser: 1000 # コンテナ実行UID
runAsGroup: 3000 # プライマリGID
fsGroup: 2000 # マウントボリュームのGID
runAsNonRoot: true # root実行を拒否
containers:
- name: app
image: myapp
securityContext: # Containerレベル: Podレベルをオーバーライド
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true # ルートFSを読み取り専用にマウント
capabilities:
add: ["NET_BIND_SERVICE"] # capabilityを追加
drop: ["ALL"] # すべてdropし、必要なもののみ追加
| 設定項目 | レベル | 効果 |
|---|---|---|
runAsUser | Pod/Container | 特定のUIDでプロセスを実行 |
runAsNonRoot | Pod/Container | UID = 0(root)の場合は実行を拒否 |
readOnlyRootFilesystem | Container | ルートファイルシステムを読み取り専用でマウント |
allowPrivilegeEscalation | Container | 権限昇格(sudoなど)をブロック |
privileged | Container | 特権モードで実行(ホスト上のrootと同等) |
fsGroup | Pod | ボリュームファイルのGID(共有ボリュームアクセス用) |
試験のポイント: ContainerレベルのsecurityContextはPodレベルの設定をオーバーライドします。Podに
runAsUser: 1000、コンテナにrunAsUser: 2000が設定されている場合、そのコンテナはUID 2000で実行されます。よく出題されるパターン:kubectl exec pod -- idまたはwhoamiでユーザーを確認。
2. Linux Capabilities
Capabilitiesにより、完全なroot権限なしで特定の権限を付与できます。
# よく使われる例:
NET_BIND_SERVICE — 1024未満のポートにバインド(例: ポート80)
NET_ADMIN — ネットワーク管理(ifconfigなど)
SYS_TIME — システムクロックの変更
CHOWN — ファイル所有者の変更
SETUID/SETGID — ユーザー/グループIDの変更
securityContext:
capabilities:
drop: ["ALL"] # ベストプラクティス: まずすべてdrop
add: ["NET_BIND_SERVICE"] # 必要なもののみ再追加
3. ServiceAccounts
PodはKubernetes APIへの認証にServiceAccountを使用します。
# ServiceAccountの作成
kubectl create serviceaccount my-sa
# Roleにバインド
kubectl create rolebinding my-binding \
--role=pod-reader \
--serviceaccount=default:my-sa
# PodにSAを割り当て
spec:
serviceAccountName: my-sa # 特定のSAを使用
automountServiceAccountToken: false # SAトークンの自動マウントを無効化
# デフォルトでは: default SAが /var/run/secrets/kubernetes.io/serviceaccount/ にマウントされる
# トークンファイルを使ってコンテナ内からK8s APIを呼び出せる
| 概念 | 説明 |
|---|---|
| デフォルトSA | 各Namespaceに組み込みのdefault SAがある(最小権限) |
| トークンマウント | 無効化しない限り、トークンはPodに自動マウントされる |
automountServiceAccountToken: false | トークンマウントを無効化(セキュリティのベストプラクティス) |
試験のポイント: PodがKubernetes APIを呼び出す必要がある場合(Operatorパターンなど)、適切な権限を持つServiceAccountが必要です。APIアクセスが不要な場合は、
automountServiceAccountToken: falseを設定するのがベストプラクティスです。CKADでよく出題されるパターン: SAの作成、Roleのバインド、Pod specへのSA設定。
4. readOnlyRootFilesystem + emptyDir
# readOnlyRootFilesystem: true の場合、アプリはルートFSに書き込めない。
# しかし一時ファイルの書き込みが必要な場合がある → emptyDirボリュームを使用:
spec:
containers:
- name: app
image: myapp
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- name: tmp
mountPath: /tmp # 一時ファイルをここに書き込み
- name: cache
mountPath: /app/cache
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
5. チートシート
| タスク | YAML / コマンド |
|---|---|
| 非rootでコンテナを実行 | securityContext: runAsNonRoot: true |
| 特定のUIDで実行 | securityContext: runAsUser: 1000 |
| 読み取り専用ファイルシステム | securityContext: readOnlyRootFilesystem: true |
| 全capabilitiesをdrop | capabilities: drop: ["ALL"] |
| ServiceAccountを割り当て | spec: serviceAccountName: my-sa |
| コンテナ内のユーザーを確認 | kubectl exec pod -- whoami |
6. 練習問題
Q1: Pod specのsecurityContext.runAsUser: 1000がPodレベルに設定されています。Pod内の1つのコンテナにsecurityContext.runAsUser: 2000が設定されています。そのコンテナはどのUIDで実行されますか?
- A) 0(root、Podレベルがオーバーライドするため)
- B) 1000(Podレベルが優先)
- C) 2000(ContainerレベルがPodレベルをオーバーライド) ✓
- D) 両方のUIDで同時に実行
解説: ContainerレベルのsecurityContext設定はPodレベルをオーバーライドします。このコンテナはUID 2000で実行されます。同じPod内でContainer固有のsecurityContextが設定されていない他のコンテナは、PodレベルのUID 1000を継承します。
Q2: アプリケーションコンテナがポート80(1024未満の特権ポート)にバインドする必要がありますが、rootで実行すべきではありません。どう設定しますか?
- A) securityContext.privileged: trueを設定
- B) securityContext.runAsUser: 0を設定
- C) 他のすべてをdropしてNET_BIND_SERVICE capabilityを追加 ✓
- D) ポート80の代わりにNodePort Serviceを使用
解説: Linux capabilitiesにより細かな権限付与が可能です。NET_BIND_SERVICEは完全なroot権限なしで1024未満のポートへのバインドを許可します。ベストプラクティスはまずすべてのcapabilitiesをdropし、必要なもののみ追加: capabilities: { drop: ["ALL"], add: ["NET_BIND_SERVICE"] }。
Q3: readOnlyRootFilesystem: trueで実行中のPodがあります。アプリケーションが/tmpに書き込もうとして失敗します。最適な解決策はどれですか?
- A) readOnlyRootFilesystem: trueを削除
- B) securityContext.privileged: trueを設定
- C) /tmpにemptyDirボリュームをマウント ✓
- D) /tmpにConfigMapをマウント
解説: readOnlyRootFilesystemはコンテナのファイルシステムへの書き込みを防止しますが、emptyDirボリュームは別の書き込み可能なマウントです。/tmpにemptyDirをマウントすることで、ルートファイルシステムは読み取り専用のまま、アプリケーションは一時ファイルを書き込めます。