10日で覚えるKubernetesDay 7: ConfigMapとSecret

Day 7: ConfigMapとSecret

今日学ぶこと

  • ConfigMapによる設定データの管理
  • Secretによる機密データの管理
  • 環境変数とボリュームマウントでの利用方法
  • Docker Composeの.envファイルからの移行

なぜ設定を分離するのか

Docker書籍では、環境変数やdocker-compose.ymlのenvironmentセクション、.envファイルで設定を管理しました。KubernetesではConfigMapSecretでこれをより体系的に管理します。

flowchart TB
    subgraph Docker["Docker Compose"]
        ENV[".envファイル"]
        DENV["environment:\n  DB_HOST: db"]
    end
    subgraph K8s["Kubernetes"]
        CM["ConfigMap\n(一般設定)"]
        SEC["Secret\n(機密情報)"]
    end
    ENV -->|"移行"| CM
    ENV -->|"機密データ"| SEC
    DENV -->|"移行"| CM
    style Docker fill:#f59e0b,color:#fff
    style K8s fill:#3b82f6,color:#fff
Docker Kubernetes 用途
environment: ConfigMap 一般的な設定値
.env ファイル ConfigMap / Secret 設定と機密情報
docker secret Secret パスワード、APIキー等

ConfigMap

ConfigMapは機密性のない設定データをキーバリューペアで保存するリソースです。

ConfigMapの作成方法

1. YAMLで作成

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: "production"
  APP_PORT: "3000"
  LOG_LEVEL: "info"
  DATABASE_HOST: "postgres-service"

2. コマンドで作成

# リテラル値から
kubectl create configmap app-config \
  --from-literal=APP_ENV=production \
  --from-literal=APP_PORT=3000

# ファイルから
kubectl create configmap nginx-config \
  --from-file=nginx.conf

# ディレクトリから
kubectl create configmap configs \
  --from-file=./config-dir/

3. 設定ファイルをまるごと保存

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx.conf: |
    server {
        listen 80;
        server_name localhost;
        location / {
            root /usr/share/nginx/html;
            index index.html;
        }
    }

ConfigMapの利用方法

環境変数として注入

apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
    - name: app
      image: nginx:1.27
      envFrom:
        - configMapRef:
            name: app-config
      # または個別に指定
      env:
        - name: MY_ENV
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: APP_ENV

ボリュームとしてマウント

apiVersion: v1
kind: Pod
metadata:
  name: web
spec:
  containers:
    - name: web
      image: nginx:1.27
      volumeMounts:
        - name: config-volume
          mountPath: /etc/nginx/conf.d
  volumes:
    - name: config-volume
      configMap:
        name: nginx-config

ボリュームマウントの場合、ConfigMapの更新が自動的にPodに反映されます(数分のラグあり)。環境変数の場合はPodの再起動が必要です。


Secret

Secretはパスワード、トークン、キーなどの機密データを保存するリソースです。

ConfigMapとSecretの違い

項目 ConfigMap Secret
用途 一般設定データ 機密データ
データ形式 平文 Base64エンコード
サイズ制限 1MiB 1MiB
メモリ保存 ディスク tmpfs(メモリ)

Secretの作成方法

1. YAMLで作成

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  username: YWRtaW4=          # echo -n "admin" | base64
  password: c2VjcmV0MTIz      # echo -n "secret123" | base64

2. stringDataで作成(Base64不要)

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
stringData:
  username: admin
  password: secret123

3. コマンドで作成

kubectl create secret generic db-secret \
  --from-literal=username=admin \
  --from-literal=password=secret123

Secretの利用方法

環境変数として注入

apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
    - name: app
      image: my-app:1.0
      env:
        - name: DB_USERNAME
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: username
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: password

ボリュームとしてマウント

apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
    - name: app
      image: my-app:1.0
      volumeMounts:
        - name: secret-volume
          mountPath: /etc/secrets
          readOnly: true
  volumes:
    - name: secret-volume
      secret:
        secretName: db-secret

Secretのタイプ

タイプ 用途
Opaque 汎用的な機密データ(デフォルト)
kubernetes.io/dockerconfigjson Dockerレジストリの認証情報
kubernetes.io/tls TLS証明書と秘密鍵
kubernetes.io/basic-auth Basic認証の資格情報

TLS Secret の例

kubectl create secret tls my-tls-secret \
  --cert=path/to/cert.pem \
  --key=path/to/key.pem

実践: 完全な構成例

Docker Composeの.envファイルとenvironmentをKubernetesに移行する例です。

Docker Compose(移行元)

# docker-compose.yml
services:
  web:
    image: my-web-app:1.0
    environment:
      - APP_ENV=production
      - DB_HOST=db
      - DB_PORT=5432
      - DB_NAME=myapp
      - DB_USER=admin
      - DB_PASSWORD=secret123

Kubernetes(移行先)

# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: "production"
  DB_HOST: "postgres-service"
  DB_PORT: "5432"
  DB_NAME: "myapp"
---
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
type: Opaque
stringData:
  DB_USER: admin
  DB_PASSWORD: secret123
---
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: my-web-app:1.0
          ports:
            - containerPort: 3000
          envFrom:
            - configMapRef:
                name: app-config
            - secretRef:
                name: app-secret
flowchart TB
    CM["ConfigMap\napp-config"] -->|"envFrom"| POD["Pod"]
    SEC["Secret\napp-secret"] -->|"envFrom"| POD
    POD -->|"DB_HOST=postgres-service"| DB["PostgreSQL\nService"]
    style CM fill:#3b82f6,color:#fff
    style SEC fill:#ef4444,color:#fff
    style POD fill:#22c55e,color:#fff

ConfigMapとSecretの管理

# ConfigMapの確認
kubectl get configmaps
kubectl describe configmap app-config
kubectl get configmap app-config -o yaml

# Secretの確認
kubectl get secrets
kubectl describe secret app-secret

# Secretの値をデコード
kubectl get secret app-secret -o jsonpath='{.data.DB_PASSWORD}' | base64 --decode

# ConfigMapの更新
kubectl edit configmap app-config

# Secretの更新
kubectl edit secret app-secret

Secretのセキュリティ注意点

重要: KubernetesのSecretはデフォルトではBase64エンコードされているだけで、暗号化されていません。

本番環境では以下の対策を検討してください:

対策 説明
etcdの暗号化 etcdに保存されるSecretデータを暗号化
RBAC Secretへのアクセスをロールベースで制御
外部シークレット管理 AWS Secrets Manager、HashiCorp Vault等と連携
GitへのSecret非コミット Secret YAMLをGitに含めない

まとめ

概念 説明
ConfigMap 一般的な設定データをキーバリューで管理
Secret 機密データをBase64エンコードで管理
envFrom ConfigMap/Secretを環境変数として一括注入
ボリュームマウント 設定ファイルとしてPodにマウント
stringData Base64エンコード不要でSecretを記述

重要ポイント

  1. 設定データはConfigMap、機密データはSecretに分離する
  2. envFromで一括注入、valueFromで個別注入が可能
  3. SecretはBase64エンコードであって暗号化ではない。本番環境では追加のセキュリティ対策が必要

練習問題

問題1: 基本

以下の設定をConfigMapとSecretに分離してください。

  • APP_NAME: "MyApp"(ConfigMap)
  • LOG_LEVEL: "debug"(ConfigMap)
  • API_KEY: "abc123xyz"(Secret)
  • JWT_SECRET: "my-jwt-secret"(Secret)

問題2: ファイルマウント

Nginxの設定ファイル(nginx.conf)をConfigMapに格納し、Podにボリュームマウントしてください。

チャレンジ問題

ConfigMapを更新した場合、既存のPodにどのように反映されるか実験してください。環境変数注入とボリュームマウントの場合で動作がどう違うか比較しましょう。


参考リンク


次回予告: Day 8では「Ingressと外部公開」について学びます。NodePortやLoadBalancerよりも柔軟なHTTPルーティングを実現するIngressの使い方を習得しましょう。