はじめに
前回まででKubernetesの理論概要から実際にWorker NodeにPodなどを立ち上げる方法をご紹介しました。今回は、Deploymentなどで変数や認証情報などの機密情報を扱うための概念であるConfigMapやSecretについて実際に、操作しながら説明して行こうと思います。
前提条件
Kubernetesに関する概要やMinikube, Dockerなどのセットアップ方法は前の記事で記載させていただいております。今回も同様の環境を用いますのでもしMinikube, Docker, kubectlコマンドのセットアップが済んでいない場合は、前の記事をご参照の上、事前準備をお願いいたします。
Kubernetesクラスタの基礎的な操作について解説~PodとDeployment, Serviceの立ち上げ~
Kubernetes: ConfigMap と Secret の違い
ConfigMapとSecretは同じく、変数に値を設定して、Pod,Deploymentから参照される変数管理をするための概念というところになりますが両者はどのように使い分けされるのでしょうか。いかにそれぞれの違いをまとめます。
| 項目 | ConfigMap | Secret |
|---|---|---|
| 用途 | 非機密情報の保存(アプリ設定、環境変数など) | 機密情報の保存(パスワード、APIキーなど) |
| データの取り扱い | プレーンテキスト形式で保存される | Base64でエンコードされて保存される(暗号化ではない) |
| セキュリティ | 特別な保護はなし(誰でも読める可能性) | アクセス制御(RBAC)推奨。暗号化の有効化も可能 |
| 主な利用例 | ログレベル、DBホスト名、外部APIのURLなど | DBのパスワード、OAuthトークン、TLS証明書など |
| マウント方法 | 環境変数、コマンドライン、Volume など | 環境変数、Volume など(ConfigMapと同様) |
| CLI作成例 | kubectl create configmap app-config --from-literal=LOG_LEVEL=debug |
kubectl create secret generic db-secret --from-literal=DB_PASSWORD=mypassword |
| アクセス制限 | 少ない(読み取りに制限なし) | 強い(RBACで制御) |
| 暗号化 | されない | Kubernetesの設定で「at rest encryption(静的データ暗号化)」が可能 |
| 表示コマンド |
kubectl get configmap / kubectl describe configmap
|
kubectl get secret / kubectl describe secret(中身の確認にはBase64デコードが必要) |
ポイント: ConfigMap は「設定」、Secret は「機密情報」用。用途を明確に分けて使うことがベストプラクティスです。
実践
それでは早速、ConfigMapやSecretを利用してみましょう。
-
Step4: ConfigMapに記載のある値を返すアプリを作成してみよう
やることのイメージ
- 以下のコマンドでローカルのDockerコマンドがMinikubeの仮想マシン内のDockerデーモンと通信するように環境変数を設定
eval $(minikube docker-env) - FlaskアプリのPythonファイルとコンテナ化するためのDockerfileを作成
# main.py import os from flask import Flask app = Flask(__name__) @app.route('/') def hello(): message = os.environ.get("MESSAGE", "Default Message") return message if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)# Dockerfile FROM python:3.9-slim WORKDIR /app COPY main.py . RUN pip install flask EXPOSE 5000 CMD ["python", "main.py"] - 以下のコマンドを実行してDockerイメージをビルドする
前回の実践でappのイメージがMinikubeのVMに残っている場合はdocker rmiコマンドを実行してから着手してください。また、参照しているdeploymentやpodがrunningになっている場合はエラーになりますので適宜deployment, serviceなどを削除をお願いいたします。以下のコマンドでイメージがビルドされているかを確認docker build -t app:latest .appがあれば成功docker images
- 以下のConfigファイルを作成
# configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: hello-config data: MESSAGE: "Hello World from ConfigMap" - 以下のコマンドを実行してConfigMapをKubernetesクラスターに適用
以下のコマンドで適用されているか確認
kubectl apply -f configmap.yamlkubectl get configmaps
hello-configが確認できれば成功 - 以下のdeploymentとserviceのyamlファイルを作成
# deployment-and-service.yaml apiVersion: apps/v1 kind: Deployment metadata: name: hello-deployment spec: replicas: 2 selector: matchLabels: app: hello template: metadata: labels: app: hello spec: containers: - name: hello-container image: app ports: - containerPort: 5000 imagePullPolicy: Never env: - name: MESSAGE valueFrom: configMapKeyRef: name: hello-config key: MESSAGE --- apiVersion: v1 kind: Service metadata: name: hello-service spec: selector: app: hello type: NodePort ports: - protocol: TCP port: 80 targetPort: 5000 nodePort: 30007 - 以下のコマンドでKubernetesクラスタにDeploymentとServiceを適用
以下のコマンドよりdeployment, service, podが立ち上がっていることを確認
kubectl apply -f deployment-and-service.yamlkubectl get all
deployment, serviceが立ち上がっておりpodのstatusがrunnningになっていれば成功 - Serviceの外部アクセス用URLを表示する
minikube service hello-service --url - curlコマンドで出力を確認(前のプロセスは実行中のまま、別ターミナルで実行)
curl <前手順の出力結果>
Hello World from ConfigMapと出力されれば成功
- 以下のコマンドでローカルのDockerコマンドがMinikubeの仮想マシン内のDockerデーモンと通信するように環境変数を設定
-
Step5: Secretを使ってFlaskアプリの認証を行い、リクエストを通してみよう
やることのイメージ
- 必要に応じて前の手順で作成したDeployment,Service, ConfigMapとDockerイメージを削除
kubectl delete deployment hello-deployment && kubectl delete service hello-service && kubectl delete configmap hello-configdocker rmi - 手順1と手順2のDockerfileまではStep4と同様の手順
- FlaskアプリのPythonファイルを作成
# main.py from flask import Flask, request, jsonify import os app = Flask(__name__) USERNAME = os.environ.get("USERNAME") PASSWORD = os.environ.get("PASSWORD") @app.route("/") def home(): user = request.authorization if user and user.username == USERNAME and user.password == PASSWORD: return "Hello World with authentication", 200 return jsonify({"error": "Unauthorized"}), 401 if __name__ == "__main__": app.run(host="0.0.0.0", port=5000) - 以下のコマンドを実行してDockerイメージをビルドする
docker build -t app:latest .
appというイメージが作成されていることが確認できれば成功 - 以下のSecretを作成
# secret.yaml apiVersion: v1 kind: Secret metadata: name: auth-secret type: Opaque stringData: USERNAME: admin PASSWORD: secret123 - 以下のコマンドによりKubernetesクラスタにSecretを適用する
以下のコマンドでsecretが適用されていることを確認する
kubectl apply -f secret.yamlkubectl get secrets
auth-secretというシークレットが表示されていれば成功 - DeploymentとServiceを記述したyamlファイルを作成
# deployment-and-service.yaml apiVersion: apps/v1 kind: Deployment metadata: name: flask-auth-app spec: replicas: 1 selector: matchLabels: app: flask-auth template: metadata: labels: app: flask-auth spec: containers: - name: flask-auth-container image: app ports: - containerPort: 5000 imagePullPolicy: Never env: - name: USERNAME valueFrom: secretKeyRef: name: auth-secret key: USERNAME - name: PASSWORD valueFrom: secretKeyRef: name: auth-secret key: PASSWORD --- apiVersion: v1 kind: Service metadata: name: flask-auth-service spec: selector: app: flask-auth type: NodePort ports: - protocol: TCP port: 80 targetPort: 5000 nodePort: 30080 - 以下のコマンドよりKubernetesクラスタにDeploymentとServiceを適用
以下のコマンドを実行して確認
kubectl apply -f deployment-and-service.yamlkubectl get all
pod, service, deployment, replicasetが立ち上がっていることを確認できれば成功 - Serviceの外部アクセス用URLを表示する
minikube service flask-auth-service --url - curlコマンドで出力を確認
curl -u admin:secret123 <前手順の出力結果>
Hello World with authenticationと帰ってくれば成功
- 必要に応じて前の手順で作成したDeployment,Service, ConfigMapとDockerイメージを削除
終わりに
本記事では、ConfigMapとSecretの役割と使い分けを実践を通じて学びました。ConfigMapでアプリ設定を、Secretで機密情報を安全に管理する方法を理解し、Kubernetesネイティブな設定注入の重要性を体験しました。これらを活用し、よりセキュアで柔軟なアプリケーション運用を目指しましょう。