コンテンツにスキップ

Kubernetes SecurityContext: 重要なのに見落とされがちなセキュリティ設定

SecurityContext とは

KubernetesのPod・Containerに対してセキュリティ設定を行うフィールド。 デフォルトはほぼ無制限なので、本番環境では必ず設定すべき。

PodレベルとContainerレベルの違い

apiVersion: v1
kind: Pod
spec:
  securityContext:        # ← Pod-level: 全コンテナに適用
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  containers:
    - name: app
      securityContext:    # ← Container-level: このコンテナだけに適用(Pod-levelを上書き)
        runAsUser: 2000   # Pod-levelの1000を上書き
        allowPrivilegeEscalation: false

Container-levelの設定がPod-levelより優先される。

主要な設定項目

runAsNonRoot / runAsUser

securityContext:
  runAsNonRoot: true  # rootユーザーで動かすと起動失敗にする
  runAsUser: 1000     # UID 1000 で実行

コンテナがrootで動くと、コンテナ脱出時にホストrootへのアクセスリスクが高まる。

readOnlyRootFilesystem

securityContext:
  readOnlyRootFilesystem: true  # ルートファイルシステムを読み取り専用に

攻撃者がコンテナ内でファイルを書き込めなくなる。書き込みが必要な場合は emptyDir ボリュームを使う。

allowPrivilegeEscalation

securityContext:
  allowPrivilegeEscalation: false  # setuid/setgidによる権限昇格を禁止

sudosetuid バイナリを使った権限昇格攻撃を防ぐ。

capabilities

securityContext:
  capabilities:
    drop:
      - ALL         # 全Linux capabilityを削除
    add:
      - NET_BIND_SERVICE  # 必要なものだけ追加(80/443ポートのバインド)

デフォルトのコンテナは不要なcapabilityを多く持っている。最小権限の原則でdrop: ALL + 必要なものだけadd。

seccompProfile

securityContext:
  seccompProfile:
    type: RuntimeDefault  # コンテナランタイムのデフォルトseccompプロファイルを使用

システムコールを制限してカーネルへの攻撃面を減らす。

ベストプラクティスのYAML例

apiVersion: v1
kind: Pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: myapp:1.0
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop:
            - ALL
      volumeMounts:
        - name: tmp
          mountPath: /tmp           # 書き込みが必要な場所だけemptyDir
  volumes:
    - name: tmp
      emptyDir: {}

なぜ無視されやすいのか

  1. 設定しなくても動くから(デフォルトは緩い)
  2. 開発環境では問題が出にくい
  3. アプリが動かなくなることがある(例: rootで起動しようとするアプリ)

確認コマンド

# PodのSecurityContextを確認
kubectl get pod my-pod -o jsonpath='{.spec.securityContext}'

# KubeLinter / kube-scoreでポリシー違反を検出
kube-score score deployment.yaml