Kubernetes セキュリティベストプラクティス

KubernetesセキュリティDevOpsRBACコンテナ

Kubernetes セキュリティベストプラクティス

本番環境でKubernetesを安全に運用するための包括的なセキュリティガイド。RBAC設定、ネットワークポリシー、Pod セキュリティ、シークレット管理など、実践的なセキュリティ強化手法を詳しく解説します。

概要

Kubernetesは現代のコンテナ化されたアプリケーションの基盤として不可欠な存在ですが、その複雑な分散アーキテクチャは多様なセキュリティ課題を生み出します。本記事では、Kubernetes 1.30以降の最新セキュリティ機能を含む、本番環境での堅牢なセキュリティ実装について詳しく解説します。

Kubernetesセキュリティの重要性

現代的な脅威の状況

2024年には、350以上の組織のKubernetesクラスターが設定ミスにより公開状態となり、機密データや重要なアプリケーションが危険にさらされる事件が発生しました。この事例は、Kubernetesセキュリティが理論的リスクではなく、現実的な脅威であることを示しています。

セキュリティが重要な理由

  1. 機密データの保護: コンテナ環境には機密コード、システム認証情報、顧客データが含まれる
  2. 複雑な攻撃面: 分散システム、マイクロサービス、広範な設定可能性による複雑性
  3. 規制要件への準拠: GDPR、HIPAA、CCPAなどの法的要件
  4. サービス可用性の維持: 高可用性アプリケーションの継続的運用
  5. 財務・評判リスクの軽減: セキュリティインシデントによる損失防止

Kubernetesセキュリティの基本原則

多層防御戦略

Kubernetesセキュリティは、以下の層で構成される包括的なアプローチが必要です:

  1. インフラストラクチャー層: ノード、ネットワーク、ストレージ
  2. クラスター層: コントロールプレーン、etcd、API Server
  3. ワークロード層: Pod、コンテナ、アプリケーション
  4. アプリケーション層: コード、ランタイム、データ

ゼロトラストモデル

全てのコンポーネントを信頼せず、常に検証・認証・認可を行う原則です。

1. Pod Security Standards(PSS)- Kubernetes 1.30+の新機能

Pod Security Standardsの概要

Kubernetes 1.30以降では、Pod Security Standardsが大幅に強化されています。

3つのセキュリティレベル

# 1. Privileged - 制限なし(本番環境では避ける)
# 2. Baseline - 最小限の制限
# 3. Restricted - 厳格なセキュリティ制御

名前空間レベルでのPod Security Standards設定

apiVersion: v1
kind: Namespace
metadata:
  name: production-apps
  labels:
    # ベースライン強制、制限付きで警告・監査
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/enforce-version: v1.30
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: v1.30
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: v1.30

クラスター全体でのPod Security設定

# cluster-level-pss.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
  configuration:
    apiVersion: pod-security.admission.config.k8s.io/v1
    kind: PodSecurityConfiguration
    defaults:
      enforce: "baseline"
      enforce-version: "latest"
      audit: "restricted"
      audit-version: "latest"
      warn: "restricted"
      warn-version: "latest"
    exemptions:
      usernames: []
      runtimeClasses: []
      namespaces: [kube-system]

制限付きPodの実装例

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
  namespace: production-apps
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: myapp:latest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      runAsNonRoot: true
      runAsUser: 1000
      capabilities:
        drop:
          - ALL
        add:
          - NET_BIND_SERVICE
      seccompProfile:
        type: RuntimeDefault
    resources:
      limits:
        memory: "512Mi"
        cpu: "500m"
      requests:
        memory: "256Mi"
        cpu: "250m"
    volumeMounts:
    - name: tmp
      mountPath: /tmp
    - name: app-data
      mountPath: /app/data
      readOnly: true
  volumes:
  - name: tmp
    emptyDir: {}
  - name: app-data
    configMap:
      name: app-config

Kubernetes 1.30の新機能: User Namespaces

# User Namespace対応Pod(アルファ機能)
apiVersion: v1
kind: Pod
metadata:
  name: user-namespace-pod
spec:
  hostUsers: false  # User Namespaceを有効化
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
  containers:
  - name: app
    image: busybox
    command: ["sleep", "infinity"]
    securityContext:
      runAsNonRoot: true

2. Role-Based Access Control (RBAC)

RBAC の基本原則

最小権限の原則に基づき、必要最小限のアクセス権のみを付与します。

サービスアカウントの作成

apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-service-account
  namespace: production-apps
automountServiceAccountToken: false  # 自動マウントを無効化

Role の定義

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production-apps
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get"]
  resourceNames: ["app-config"]  # 特定のリソースのみ

RoleBinding の設定

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-binding
  namespace: production-apps
subjects:
- kind: ServiceAccount
  name: app-service-account
  namespace: production-apps
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRole の実装(クラスター全体のリソース)

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-reader
rules:
- apiGroups: [""]
  resources: ["nodes", "nodes/metrics", "services", "endpoints", "pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["metrics.k8s.io"]
  resources: ["nodes", "pods"]
  verbs: ["get", "list"]

RBAC監査とベストプラクティス

# 現在のRBAC権限を確認
kubectl auth can-i --list --as=system:serviceaccount:production-apps:app-service-account

# 特定の操作権限を確認
kubectl auth can-i create pods --as=system:serviceaccount:production-apps:app-service-account

# RBAC分析(kubectl-who-can プラグイン使用)
kubectl who-can create pods
kubectl who-can get secrets --all-namespaces

3. ネットワークポリシー

Default Deny ポリシー

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production-apps
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

段階的なネットワークセキュリティ

# フロントエンドからバックエンドへの通信を許可
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-access-policy
  namespace: production-apps
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432
  - to: []  # DNS解決のため
    ports:
    - protocol: UDP
      port: 53

外部接続制御

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: external-access-policy
  namespace: production-apps
spec:
  podSelector:
    matchLabels:
      app: api-gateway
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/8  # 内部ネットワーク
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 169.254.169.254/32  # メタデータサービスをブロック
        - 127.0.0.0/8        # ローカルホストをブロック
    ports:
    - protocol: TCP
      port: 443  # HTTPSのみ許可

4. シークレット管理

Kubernetes Secretsのベストプラクティス

apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
  namespace: production-apps
  annotations:
    # 秘密の検索を容易にする
    secret-type: "database-credentials"
type: Opaque
data:
  # Base64エンコード済み
  username: <base64-encoded-username>
  password: <base64-encoded-password>

etcdでのSecret暗号化

# encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - aescbc:
      keys:
      - name: key1
        secret: <32-byte-base64-encoded-key>
  - identity: {}

External Secrets Operator

# 外部のシークレット管理システムとの統合
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: vault-backend
  namespace: production-apps
spec:
  provider:
    vault:
      server: "https://vault.company.com"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "app-role"
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-secret
  namespace: production-apps
spec:
  refreshInterval: 15s
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: app-secrets
    creationPolicy: Owner
  data:
  - secretKey: password
    remoteRef:
      key: database
      property: password

Secret使用のベストプラクティス

apiVersion: v1
kind: Pod
metadata:
  name: app-with-secrets
spec:
  containers:
  - name: app
    image: myapp:latest
    env:
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: app-secrets
          key: password
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secrets
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: app-secrets
      defaultMode: 0400  # 読み取り専用
      items:
      - key: certificate
        path: tls.crt

5. コンテナイメージセキュリティ

脆弱性スキャンとTrivy

# イメージの脆弱性スキャン
trivy image myapp:latest

# 重大度高以上のみ表示
trivy image --severity HIGH,CRITICAL myapp:latest

# JSON形式での出力
trivy image --format json myapp:latest > scan-results.json

# Kubernetesクラスターのスキャン
trivy k8s cluster

イメージ署名とCosign

# イメージの署名
cosign sign --key cosign.key myregistry/myapp:latest

# 署名の検証
cosign verify --key cosign.pub myregistry/myapp:latest

# キーレス署名(OIDC)
cosign sign myregistry/myapp:latest

# Admission Controller での自動検証

安全なベースイメージ

# Distrolessイメージの使用
FROM gcr.io/distroless/java:11

# 特権ユーザーを避ける
FROM node:18-alpine
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
USER nextjs

# マルチステージビルド
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM gcr.io/distroless/nodejs:18
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
USER 1001
CMD ["dist/index.js"]

Admission Controller によるイメージポリシー

# OPA Gatekeeper ConstraintTemplate
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: allowedrepositories
spec:
  crd:
    spec:
      names:
        kind: AllowedRepositories
      validation:
        properties:
          repos:
            type: array
            items:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package allowedrepositories
        
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not starts_with(container.image, input.parameters.repos[_])
          msg := sprintf("Container image %v is not from allowed repository", [container.image])
        }
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: AllowedRepositories
metadata:
  name: must-come-from-trusted-registry
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    repos:
      - "myregistry.company.com/"
      - "gcr.io/my-project/"

6. ランタイムセキュリティ

Falcoによる脅威検知

# Falco DaemonSet設定
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: falco
  namespace: falco-system
spec:
  selector:
    matchLabels:
      app: falco
  template:
    metadata:
      labels:
        app: falco
    spec:
      serviceAccount: falco
      hostNetwork: true
      hostPID: true
      containers:
      - name: falco
        image: falcosecurity/falco:latest
        securityContext:
          privileged: true
        volumeMounts:
        - name: dev
          mountPath: /host/dev
        - name: proc
          mountPath: /host/proc
          readOnly: true
        - name: boot
          mountPath: /host/boot
          readOnly: true
        - name: lib-modules
          mountPath: /host/lib/modules
          readOnly: true
        - name: usr
          mountPath: /host/usr
          readOnly: true
        - name: etc
          mountPath: /host/etc
          readOnly: true
      volumes:
      - name: dev
        hostPath:
          path: /dev
      - name: proc
        hostPath:
          path: /proc
      - name: boot
        hostPath:
          path: /boot
      - name: lib-modules
        hostPath:
          path: /lib/modules
      - name: usr
        hostPath:
          path: /usr
      - name: etc
        hostPath:
          path: /etc

カスタムFalcoルール

# カスタムセキュリティルール
apiVersion: v1
kind: ConfigMap
metadata:
  name: falco-custom-rules
  namespace: falco-system
data:
  custom_rules.yaml: |
    - rule: Suspicious shell in container
      desc: Shell spawned in a container other than those in a whitelist
      condition: >
        spawned_process and container and
        shell_procs and
        not proc.pname in (docker_binaries) and
        not container.image.repository in (allowed_images)
      output: >
        Shell spawned in container (user=%user.name container_id=%container.id 
        container_name=%container.name shell=%proc.name parent=%proc.pname 
        cmdline=%proc.cmdline image=%container.image.repository)
      priority: WARNING
      tags: [container, shell, mitre_execution]
    
    - list: allowed_images
      items: [
        "alpine/git",
        "busybox",
        "debug-tools"
      ]
    
    - rule: Unauthorized process in production
      desc: Unexpected process started in production namespace
      condition: >
        spawned_process and k8s.ns.name=production-apps and
        not proc.name in (allowed_processes)
      output: >
        Unauthorized process in production (user=%user.name proc=%proc.name 
        parent=%proc.pname cmdline=%proc.cmdline container=%container.name 
        image=%container.image.repository)
      priority: CRITICAL
    
    - list: allowed_processes
      items: [
        "node",
        "nginx", 
        "java",
        "python"
      ]

セキュリティレスポンス自動化

# Falco Sidekick による自動レスポンス
apiVersion: apps/v1
kind: Deployment
metadata:
  name: falco-sidekick
  namespace: falco-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: falco-sidekick
  template:
    metadata:
      labels:
        app: falco-sidekick
    spec:
      containers:
      - name: falco-sidekick
        image: falcosecurity/falco-sidekick:latest
        env:
        - name: SLACK_WEBHOOK_URL
          valueFrom:
            secretKeyRef:
              name: alerting-config
              key: slack-webhook
        - name: KUBELESS_NAMESPACE
          value: "kubeless"
        - name: KUBELESS_FUNCTION
          value: "security-response"
        ports:
        - containerPort: 2801

7. Service Mesh によるセキュリティ

Istio による mTLS

# PeerAuthentication でmTLSを強制
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production-apps
spec:
  mtls:
    mode: STRICT  # 全ての通信でmTLSを強制
---
# 特定のポートでのmTLS設定
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: api-server
  namespace: production-apps
spec:
  selector:
    matchLabels:
      app: api-server
  portLevelMtls:
    8080:
      mode: STRICT
    9090:
      mode: PERMISSIVE  # メトリクス用ポートは段階的移行

認可ポリシー

# 細かい粒度での認可制御
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: frontend-to-backend
  namespace: production-apps
spec:
  selector:
    matchLabels:
      app: backend
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/production-apps/sa/frontend-sa"]
  - to:
    - operation:
        methods: ["GET", "POST"]
        paths: ["/api/v1/*"]
  - when:
    - key: request.headers[authorization]
      values: ["Bearer *"]
---
# API レート制限
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: rate-limit-policy
  namespace: production-apps
spec:
  selector:
    matchLabels:
      app: api-gateway
  rules:
  - to:
    - operation:
        methods: ["POST"]
        paths: ["/api/auth/*"]
    when:
    - key: source.ip
      notValues: ["10.0.0.0/8"]  # 内部IPを除外

Gateway と VirtualService のセキュリティ

# セキュアな Gateway 設定
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: secure-gateway
  namespace: production-apps
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: api-tls-secret
    hosts:
    - api.company.com
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - api.company.com
    tls:
      httpsRedirect: true  # HTTPをHTTPSにリダイレクト
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: api-routes
  namespace: production-apps
spec:
  hosts:
  - api.company.com
  gateways:
  - secure-gateway
  http:
  - match:
    - headers:
        user-agent:
          regex: ".*bot.*"  # ボットアクセスをブロック
    fault:
      abort:
        percentage:
          value: 100
        httpStatus: 403
  - match:
    - uri:
        prefix: "/api/v1/"
    route:
    - destination:
        host: backend-service
        port:
          number: 8080

8. 監査とコンプライアンス

Kubernetes監査ログ

# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# 機密操作を詳細にログ
- level: RequestResponse
  resources:
  - group: ""
    resources: ["secrets", "configmaps"]
  - group: "rbac.authorization.k8s.io"
    resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]

# 認証失敗をログ
- level: Metadata
  omitStages:
    - RequestReceived
  resources:
  - group: ""
    resources: ["*"]
  namespaces: ["production-apps"]

# exec/attach操作を監視
- level: Request
  verbs: ["create"]
  resources:
  - group: ""
    resources: ["pods/exec", "pods/attach", "pods/portforward"]

# 証明書要求を監視
- level: Request
  resources:
  - group: "certificates.k8s.io"
    resources: ["certificatesigningrequests"]

CIS Kubernetes Benchmarkに基づく監査

# kube-bench による CIS準拠チェック
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml

# 結果の確認
kubectl logs job/kube-bench

# Kubescape による総合評価
kubescape scan --submit --account-id YOUR_ACCOUNT_ID

# 特定のフレームワークでの評価
kubescape scan framework nsa,mitre

# YAML設定ファイルのスキャン
kubescape scan *.yaml

OPA Gatekeeper による継続的ポリシー管理

# リソース制限を強制するConstraintTemplate
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: containerlimits
spec:
  crd:
    spec:
      names:
        kind: ContainerLimits
      validation:
        properties:
          cpu:
            type: string
          memory:
            type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package containerlimits
        
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.resources.limits.cpu
          msg := "Container must have CPU limits"
        }
        
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.resources.limits.memory
          msg := "Container must have memory limits"
        }
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: ContainerLimits
metadata:
  name: must-have-limits
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces: ["kube-system", "kube-public"]
  parameters:
    cpu: "1000m"
    memory: "1Gi"

9. 継続的セキュリティモニタリング

Prometheus + Grafana でのセキュリティメトリクス

# セキュリティ関連メトリクス用のServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: falco-metrics
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: falco
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics
---
# アラートルール
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: security-alerts
  namespace: monitoring
spec:
  groups:
  - name: security
    rules:
    - alert: PrivilegedContainerRunning
      expr: increase(falco_events_total{rule_name="Run shell untrusted"}[5m]) > 0
      for: 0m
      labels:
        severity: critical
      annotations:
        summary: "Privileged container detected"
        description: "Falco detected a privileged container running"
    
    - alert: FailedAuthenticationSpike
      expr: rate(apiserver_audit_total{verb="create",objectRef_resource="tokenreviews"}[5m]) > 10
      for: 2m
      labels:
        severity: warning
      annotations:
        summary: "High rate of authentication failures"
        description: "Authentication failure rate is above normal threshold"

セキュリティ自動化とレスポンス

#!/bin/bash
# security-automation.sh

# 脆弱性の高いPodを自動隔離
kubectl get pods --all-namespaces -o json | \
jq -r '.items[] | select(.metadata.annotations."vulnerability-scan" == "critical") | "\(.metadata.namespace) \(.metadata.name)"' | \
while read namespace pod; do
  echo "Isolating critical vulnerability pod: $namespace/$pod"
  kubectl label pod $pod -n $namespace security.isolation=true
  kubectl annotate pod $pod -n $namespace network-policy.isolation=deny-all
done

# 異常なネットワーク活動の検出
kubectl logs -n falco-system daemonset/falco | \
grep "Outbound or inbound traffic not to or from" | \
tail -10 | \
while read line; do
  echo "Suspicious network activity detected: $line"
  # Slackやメール通知の送信
done

10. インシデント対応とフォレンジック

セキュリティインシデント対応プレイブック

# インシデント対応用の緊急Namespace
apiVersion: v1
kind: Namespace
metadata:
  name: incident-response
  labels:
    security-level: high
    pod-security.kubernetes.io/enforce: restricted
---
# フォレンジック用Pod
apiVersion: v1
kind: Pod
metadata:
  name: forensic-toolkit
  namespace: incident-response
spec:
  hostNetwork: false
  hostPID: false
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
  containers:
  - name: forensic-tools
    image: forensic-toolkit:latest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
          - ALL
    volumeMounts:
    - name: evidence
      mountPath: /evidence
    - name: tmp
      mountPath: /tmp
  volumes:
  - name: evidence
    emptyDir: {}
  - name: tmp
    emptyDir: {}

侵害されたPodの隔離

# 侵害されたPodの即座隔離
isolate_compromised_pod() {
  local namespace=$1
  local pod_name=$2
  
  echo "Isolating compromised pod: $namespace/$pod_name"
  
  # ネットワーク隔離
  kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: isolate-$pod_name
  namespace: $namespace
spec:
  podSelector:
    matchLabels:
      app: $pod_name
  policyTypes:
  - Ingress
  - Egress
EOF

  # ラベル付けとアノテーション
  kubectl label pod $pod_name -n $namespace security.status=compromised
  kubectl annotate pod $pod_name -n $namespace security.incident-id=$(date +%s)
  
  # 証跡保存
  kubectl logs $pod_name -n $namespace > /evidence/logs-$pod_name-$(date +%s).log
  kubectl describe pod $pod_name -n $namespace > /evidence/describe-$pod_name-$(date +%s).yaml
}

まとめ

Kubernetesセキュリティは、単なる設定の問題ではなく、継続的なプロセスです。本記事で紹介したベストプラクティスを組み合わせることで、以下の効果が期待できます:

主要な成果指標

  1. インシデント発生率の削減: 適切なセキュリティ制御により、セキュリティインシデントを70-80%削減
  2. 平均検出時間の短縮: ランタイムモニタリングにより、脅威検出時間を数時間から数分に短縮
  3. コンプライアンス準拠: 自動化されたポリシー管理により、監査準備時間を90%削減
  4. 開発速度の向上: 自動化されたセキュリティチェックにより、開発スピードを維持しながらセキュリティを強化

実装ロードマップ

  1. 第1段階(1-2週間): Pod Security Standards、基本的なRBAC、ネットワークポリシーの実装
  2. 第2段階(3-4週間): イメージスキャン、シークレット管理、監査ログの設定
  3. 第3段階(1-2ヶ月): ランタイムセキュリティ、Service Mesh、OPAによるポリシー管理
  4. 第4段階(継続的): 継続的モニタリング、インシデント対応、セキュリティ自動化の拡張

成功のための重要ポイント

  • 段階的実装: 全てを一度に実装せず、重要度の高いものから順次適用
  • 開発チームとの協力: セキュリティを後付けではなく、開発プロセスに組み込む
  • 継続的改善: 脅威の進化に応じてセキュリティ対策を継続的にアップデート
  • 教育と訓練: チーム全体のセキュリティ意識向上とスキル開発

Kubernetesセキュリティは複雑ですが、体系的なアプローチと適切なツールの使用により、堅牢で安全な本番環境を構築できます。セキュリティは一度設定すれば終わりではなく、継続的な監視と改善が必要なプロセスであることを忘れずに取り組んでください。