Day 7: ConfigMapとSecret
今日学ぶこと
- ConfigMapによる設定データの管理
- Secretによる機密データの管理
- 環境変数とボリュームマウントでの利用方法
- Docker Composeの.envファイルからの移行
なぜ設定を分離するのか
Docker書籍では、環境変数やdocker-compose.ymlのenvironmentセクション、.envファイルで設定を管理しました。KubernetesではConfigMapとSecretでこれをより体系的に管理します。
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を記述 |
重要ポイント
- 設定データはConfigMap、機密データはSecretに分離する
envFromで一括注入、valueFromで個別注入が可能- 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の使い方を習得しましょう。