2026年7月1日

2026年7月1日

KubernetesのConfigMapとSecretの使い分けと管理方法|作成・Podへの渡し方・更新の反映

Kubernetesでは、アプリケーションの設定をコンテナイメージに埋め込まず、ConfigMap(一般の設定)とSecret(パスワードやAPIキーなどの機密情報)として別に管理し、Podに渡します。こうすると、同じイメージを開発・検証・本番で使い回し、環境ごとに設定だけを変えられます。

この記事では、2つの違い、作り方、Podへの渡し方、更新したときの反映のされ方、Secretを守るための注意点を説明します。内容は2026年10月時点のKubernetes公式ドキュメント(kubernetes.io)に合わせています。

ConfigMapとSecretの違い

項目 ConfigMap Secret
用途 機密でない設定(ログレベル、接続先のホスト名、設定ファイル) パスワード、APIキー、TLSの証明書と鍵、レジストリの認証情報
data の値 そのままの文字列 base64でエンコードした文字列(stringData なら平文で書ける)
大きさの上限 1MiB 1MiB
暗号化 されない 既定ではされない(後述の保存時の暗号化を設定した場合のみ)
種類 なし Opaque(汎用)、kubernetes.io/tls、kubernetes.io/dockerconfigjson など

注意したいのは、Secretのbase64はエンコードであって暗号化ではないことです。公式ドキュメントでも、Secretは既定ではAPIサーバーのデータストア(etcd)に暗号化されずに保存され、APIにアクセスできる人やetcdにアクセスできる人は読み書きできると説明しています。Secretという名前だけで守られるわけではないので、後半の設定もあわせて行います。

どちらも名前空間(namespace)ごとのリソースで、Podが参照できるのは同じ名前空間のConfigMapとSecretだけです。

ConfigMapを作る

kubectlのコマンドで作る

# キーと値を直接指定する
kubectl create configmap app-config \
  --from-literal=LOG_LEVEL=info \
  --from-literal=API_HOST=api.example.com

# ファイルの中身を1つのキーとして登録する(キー名はファイル名になる)
kubectl create configmap nginx-conf --from-file=default.conf

# 内容を確認する
kubectl get configmap app-config -o yaml

YAMLで作る

設定をGitで管理する場合はYAMLで書きます。複数行の設定ファイルは | を使ってそのまま書けます。

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  LOG_LEVEL: "info"
  API_HOST: "api.example.com"
  app.json: |
    {
      "featureX": true,
      "timeoutSeconds": 30
    }
kubectl apply -f configmap.yaml

Secretを作る

kubectlのコマンドで作る

kubectl create secret generic を使うと、base64へのエンコードは自動で行われます。

kubectl create secret generic db-secret \
  --from-literal=DB_USER=appuser \
  --from-literal=DB_PASSWORD='change-me'

コマンドラインに書いた値はシェルの履歴に残ります。本番の値は、ファイルから読み込む(--from-file)か、履歴に残らない方法で渡してください。

YAMLで作る

data に書く値はbase64でエンコードしたものです。

echo -n 'appuser' | base64
# YXBwdXNlcg==

-n を付けないと改行までエンコードされ、パスワードの末尾に改行が入ってしまいます。手作業のエンコードを避けたい場合は、stringData に平文で書けます(保存時に data に変換されます)。

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  DB_USER: YXBwdXNlcg==
stringData:
  DB_PASSWORD: change-me

同じキーが data と stringData の両方にある場合は、stringData の値が使われます。平文のパスワードを書いたYAMLをそのままGitに入れないでください。

中身の確認は次のとおりです。-o yaml で見えるのはbase64の値なので、デコードして確かめます。

kubectl get secret db-secret -o jsonpath='{.data.DB_USER}' | base64 -d

Podに渡す

渡し方は主に「環境変数」と「ファイル(ボリューム)」の2つです。

環境変数として渡す

キーを1つずつ指定する方法(valueFrom)と、全部のキーをまとめて渡す方法(envFrom)があります。

apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
    - name: app
      image: nginx:1.27
      env:
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: LOG_LEVEL
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: DB_PASSWORD
      envFrom:
        - configMapRef:
            name: app-config

envFrom を使うと、ConfigMapのキー名がそのまま環境変数名になります。この例では app.json のような設定ファイル用のキーまで環境変数になるので、必要なキーだけを渡したい場合は env で1つずつ指定します。

確認は次のとおりです。

kubectl exec app -- printenv LOG_LEVEL

ファイルとして渡す

ボリュームとしてマウントすると、キーごとに1つのファイルができます。ファイル名がキー名、中身が値です。

apiVersion: v1
kind: Pod
metadata:
  name: app-files
spec:
  containers:
    - name: app
      image: nginx:1.27
      volumeMounts:
        - name: config
          mountPath: /etc/app
          readOnly: true
        - name: secret
          mountPath: /etc/app-secret
          readOnly: true
  volumes:
    - name: config
      configMap:
        name: app-config
        items:
          - key: app.json
            path: app.json
    - name: secret
      secret:
        secretName: db-secret
        defaultMode: 0400

items を書くと、指定したキーだけがファイルになります(この例では /etc/app/app.json だけ)。省略すると全部のキーがファイルになります。Secretの defaultMode はファイルの権限で、YAMLでは先頭に 0 を付けた8進数で書けます。

kubectl exec app-files -- cat /etc/app/app.json
kubectl exec app-files -- ls -l /etc/app-secret/

SecretがPod内のどこに置かれるかは、mountPath で指定した場所です。マウントしていないSecretは、Pod内のファイルとしては存在しません。

更新したときの反映のされ方

ConfigMapやSecretを書き換えても、使い方によって反映のされ方が違います。

渡し方 更新後の動き
ボリュームとしてマウント kubeletが定期的に確認し、少し遅れてファイルが新しい内容に置き換わる
subPath でマウント 更新されない
環境変数(env・envFrom) 更新されない。Podを作り直す必要がある

ファイルが置き換わっても、アプリケーションが起動時に1回だけ設定を読む作りなら、再読み込みしない限り反映されません。環境変数で渡した値を反映させるには、Deploymentの場合は次のようにPodを順に作り直します。

kubectl rollout restart deployment/app

変更しないものはimmutableにする

immutable: true を付けたConfigMapとSecretは、内容を変更できなくなります(Kubernetes 1.21で正式機能)。誤って書き換えて障害になるのを防げるほか、kubeletが変更を監視しなくてよくなるので、大量に使うクラスターではAPIサーバーの負荷が下がります。

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config-v2
data:
  LOG_LEVEL: "warn"
immutable: true

一度immutableにすると元に戻せず、変更するには削除して作り直します。運用では、app-config-v2 のように名前に版を付けて新しいものを作り、Podの参照先を切り替える方法が扱いやすくなります。

Secretを守るための設定

公式ドキュメントでは、Secretを安全に使うために少なくとも次を行うよう求めています。

  1. 保存時の暗号化(Encryption at Rest)を有効にする: kube-apiserverに EncryptionConfiguration を設定すると、etcdに保存されるSecretが暗号化されます。マネージドサービス(EKS、GKE、AKSなど)では各サービスの設定方法に従います。
  2. RBACで最小権限にする: Secretの get・list・watch を許可するロールは、必要な人とサービスアカウントに限ります。list でも中身まで取得できる点に注意します。
  3. Secretを使うコンテナを限定する: 必要なコンテナだけにマウントや環境変数で渡します。
  4. 外部のシークレットストアの利用を検討する: クラウドのシークレット管理サービスなどと連携させる方法があります。

あわせて、公式ドキュメントには、名前空間の中でPodを作成できる人は、その名前空間のSecretを(Deploymentの作成などを通じて間接的にも)読めるという注意があります。Podを作れる権限もSecretへのアクセス権の一部として扱ってください。

よくあるつまずき

  • Podが起動しない: 参照しているConfigMap・Secret、またはそのキーが存在しない。環境変数で参照している場合は CreateContainerConfigError、ボリュームの場合は ContainerCreating のまま止まる。kubectl describe pod <Pod名> のEventsに、見つからない名前が表示される。存在しなくても起動させたい参照には optional: true を付ける
  • パスワードが合わない: YAMLに書くbase64を echo の -n なしで作り、末尾に改行が入っている
  • 値を変えたのに反映されない: 環境変数や subPath で渡している(上の表を参照)

まとめ

  • 機密でない設定はConfigMap、機密情報はSecretに入れ、どちらも1MiBまで
  • Secretのbase64は暗号化ではない。保存時の暗号化とRBACで守る
  • Podへは環境変数(env・envFrom)かボリュームで渡す
  • ボリュームで渡した値は少し遅れて更新されるが、環境変数と subPath は更新されない
  • 変更しない設定は immutable: true にして、名前に版を付けて切り替える

関連記事:

お気軽にご相談ください

お見積りへ お問い合わせへ
▲