Docker & Kubernetes完全攻略 第9編:ConfigMap、Secret、Ingressの活用
Docker & Kubernetes Complete Guide Part 9: ConfigMap, Secret, and Ingress
序論:設定管理と外部アクセスの重要性
コンテナ化されたアプリケーションを運用する際の最も重要な課題の1つは、設定の分離です。アプリケーションコードと設定を分離すれば、同じイメージを開発、ステージング、プロダクション環境で再利用できます。KubernetesはこのためにConfigMapとSecretというリソースを提供します。
また、クラスター外部から内部サービスにアクセスするには、適切なルーティングメカニズムが必要です。Ingressは、HTTP/HTTPSトラフィックをクラスター内部のサービスにルーティングするL7ロードバランサーの役割を果たします。この編では、これら3つのコアリソースを詳しく見ていきます。
1. 設定管理の重要性
1.1 なぜ設定を分離すべきか?
12-Factor App方法論で強調されているように、設定はコードから分離されるべきです:
- 環境別デプロイ:同じイメージをさまざまな環境(開発、テスト、プロダクション)にデプロイできます
- セキュリティ強化:機密情報をコードリポジトリに含める必要がありません
- 柔軟な変更:設定変更時にイメージの再ビルドなしで適用できます
- チームコラボレーション:開発者と運用者がそれぞれの領域を独立して管理できます
1.2 Kubernetesの設定管理方式
Kubernetesは2つのリソースで設定を管理します:
| リソース | 用途 | 保存方式 |
|---|---|---|
| ConfigMap | 一般的な設定データ | 平文(Plain text) |
| Secret | 機密情報 | Base64エンコーディング |
2. ConfigMapの作成と使用
2.1 ConfigMapとは?
ConfigMapは、キーと値のペアで構成された設定データを保存するKubernetesリソースです。アプリケーションの環境変数、設定ファイル、コマンドライン引数などを保存できます。
2.2 ConfigMapの作成方法
方法1:リテラル値で作成
# 単一のキーと値のペア
kubectl create configmap app-config --from-literal=APP_ENV=production
# 複数のキーと値のペア
kubectl create configmap app-config \
--from-literal=APP_ENV=production \
--from-literal=LOG_LEVEL=info \
--from-literal=MAX_CONNECTIONS=100
方法2:ファイルから作成
# 単一ファイル
kubectl create configmap nginx-config --from-file=nginx.conf
# ディレクトリ全体
kubectl create configmap app-configs --from-file=./configs/
方法3:YAMLマニフェストで作成
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: default
data:
# 単純なキーと値のペア
APP_ENV: "production"
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"
# 複数行の設定ファイル
application.properties: |
server.port=8080
spring.datasource.url=jdbc:mysql://mysql:3306/mydb
spring.jpa.hibernate.ddl-auto=update
logging.level.root=INFO
# JSON形式の設定
config.json: |
{
"apiEndpoint": "https://api.example.com",
"timeout": 30,
"retryCount": 3
}
kubectl apply -f configmap.yaml
2.3 ConfigMapの使用:環境変数
個別のキーを環境変数として使用
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:latest
env:
# 特定のキーのみ環境変数として注入
- name: APPLICATION_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: APP_ENV
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
すべてのキーを環境変数として使用
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:latest
envFrom:
- configMapRef:
name: app-config
# プレフィックスの追加も可能
- configMapRef:
name: app-config
prefix: CONFIG_
2.4 ConfigMapの使用:ボリュームマウント
設定ファイルが必要な場合はボリュームとしてマウントできます:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d
readOnly: true
volumes:
- name: config-volume
configMap:
name: nginx-config
# 特定のキーのみマウントする場合
items:
- key: nginx.conf
path: default.conf
3. Secretの作成と使用
3.1 Secretとは?
Secretは、パスワード、OAuthトークン、SSHキーなどの機密情報を保存するリソースです。ConfigMapと似ていますが、データがBase64でエンコードされて保存されます。
3.2 Secretのタイプ
| タイプ | 説明 | 使用例 |
|---|---|---|
| Opaque | 任意のユーザー定義データ | パスワード、APIキー |
| kubernetes.io/tls | TLS証明書 | HTTPS証明書 |
| kubernetes.io/dockerconfigjson | Dockerレジストリ認証 | プライベートレジストリアクセス |
| kubernetes.io/basic-auth | 基本認証情報 | ユーザー名/パスワード |
| kubernetes.io/ssh-auth | SSH認証 | SSH秘密鍵 |
3.3 Opaque Secretの作成
方法1:コマンドラインで作成
# リテラル値で作成
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password=s3cr3tP@ssw0rd
# ファイルから作成
kubectl create secret generic ssh-key \
--from-file=ssh-privatekey=/path/to/id_rsa
方法2:YAMLマニフェストで作成
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
# Base64エンコードされた値
# echo -n 'admin' | base64 -> YWRtaW4=
username: YWRtaW4=
# echo -n 's3cr3tP@ssw0rd' | base64 -> czNjcjN0UEBzc3cwcmQ=
password: czNjcjN0UEBzc3cwcmQ=
---
# stringDataを使用(自動的にBase64エンコード)
apiVersion: v1
kind: Secret
metadata:
name: api-credentials
type: Opaque
stringData:
api-key: my-super-secret-api-key
api-secret: another-secret-value
3.4 Secretの使用
環境変数として注入
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:latest
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
ボリュームとしてマウント
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:latest
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-credentials
# ファイル権限の設定
defaultMode: 0400
3.5 Secretのセキュリティ考慮事項
Secretは基本的にBase64エンコードのみで暗号化されていません。以下のセキュリティ対策を検討する必要があります:
- etcd暗号化:etcdに保存されるSecretを暗号化します
- RBAC制限:Secretへのアクセス権限を最小化します
- 外部Secret管理ツールの使用:HashiCorp Vault、AWS Secrets Manager、Azure Key Vaultなど
- Secretのローテーション:定期的にSecret値を変更します
- 監査ログ:Secretアクセスに対する監査ログを有効化します
4. Ingressとは?
4.1 Ingressの概念
Ingressは、クラスター外部から内部サービスへのHTTP/HTTPSトラフィックを管理するAPIオブジェクトです。L7(アプリケーション層)ロードバランサーとして以下の機能を提供します:
- ホストベースルーティング:ドメイン名に応じて異なるサービスにルーティング
- パスベースルーティング:URLパスに応じて異なるサービスにルーティング
- TLS/SSL終端:HTTPSトラフィックの処理
- ロードバランシング:複数のPodにトラフィックを分散
4.2 Ingress vs Service(NodePort/LoadBalancer)
| 特性 | NodePort | LoadBalancer | Ingress |
|---|---|---|---|
| レイヤー | L4 | L4 | L7 |
| プロトコル | TCP/UDP | TCP/UDP | HTTP/HTTPS |
| URLルーティング | 不可 | 不可 | 可能 |
| TLS終端 | 不可 | 不可 | 可能 |
| コスト | 無料 | クラウド費用発生 | 単一LBで複数サービス |
5. Ingress Controller
5.1 Ingress Controllerとは?
Ingressリソースは宣言的なルーティングルールにすぎず、実際に動作するにはIngress Controllerが必要です。Ingress Controllerは、Ingressリソースを監視し、それに応じてロードバランサーを構成します。
5.2 主要なIngress Controller
Nginx Ingress Controller
# Nginx Ingress Controllerのインストール(Helm)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install nginx-ingress ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace
# またはマニフェストでインストール
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
Traefik Ingress Controller
# Traefikのインストール(Helm)
helm repo add traefik https://helm.traefik.io/traefik
helm repo update
helm install traefik traefik/traefik \
--namespace traefik \
--create-namespace
6. Ingress YAMLの作成
6.1 基本的なIngress構造
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
# Ingress Controller固有の設定
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx # 使用するIngress Controllerを指定
rules:
- host: example.com # ホストベースルーティング
http:
paths:
- path: / # パスベースルーティング
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
6.2 ホストベースルーティング
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: host-based-ingress
spec:
ingressClassName: nginx
rules:
# api.example.com -> api-service
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
# web.example.com -> web-service
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
6.3 パスベースルーティング
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-based-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
# example.com/api/* -> api-service
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-service
port:
number: 8080
# example.com/web/* -> web-service
- path: /web(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: web-service
port:
number: 80
# example.com/*(デフォルト)-> frontend-service
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
7. TLS設定
7.1 TLS Secretの作成
# 自己署名証明書の生成(テスト用)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key \
-out tls.crt \
-subj "/CN=example.com"
# TLS Secretの作成
kubectl create secret tls example-tls \
--cert=tls.crt \
--key=tls.key
7.2 IngressにTLSを適用
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- example.com
- www.example.com
secretName: example-tls
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
7.3 cert-managerによる自動証明書管理
# cert-managerのインストール
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
# Let's Encrypt ClusterIssuerの設定
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: your-email@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
---
# 自動証明書発行Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auto-tls-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- example.com
secretName: example-tls-auto # cert-managerが自動生成
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
8. 結論
この第9編では、Kubernetesのコア設定管理リソースであるConfigMapとSecret、そして外部トラフィックを管理するIngressについて学びました:
- ConfigMap:一般的な設定データを管理し、環境変数やボリュームとしてPodに注入できます
- Secret:機密情報を安全に保存し、追加のセキュリティ対策が必要です
- Ingress:L7ロードバランサーとして、ホスト/パスベースルーティングとTLS終端を提供します
- Ingress Controller:Ingressリソースを実際に実装するコンポーネントです
次の第10編では、KubernetesパッケージマネージャーであるHelmとCI/CDパイプラインの構築について学びます。Helm Chartを活用したアプリケーションデプロイと、GitOpsベースの自動化されたデプロイ戦略を扱う予定です。