こんにちは、ルートです。
この記事では、実際の現場を想定してKubernetesでとりあえずアプリを動かしてみようと思います。Kubernetesでは色々なリソースがありますが、その中でも特に使われるのが以下のリソースたちです。
- ConfigMap
- Secret
- Deployment
- Service
今回は、現場で使われるような構成のアプリをとりあえず動かしてみることを目標にするので、各リソースはそこまで凝った作りにはしませんでした。ただ、この記事を読むことで、上に書いたような各種リソースの作り方やそれらを関連付ける方法が学べるので、Kubernetesに興味がある方は、是非読んでいただけると幸いです!
- Secretの概要
- ConfigMapの概要
- Kubernetesを用いた簡単なアプリの作成方法
構成図と概要
早速ですが、この記事で作るWebアプリの構成図を以下に記します:

詳しいことはこの後説明しますが、アプリに必要な設定はConfigMap、パスワード等の情報はSecretに書き、それぞれの情報をReplicaset配下のPodに読み込ませるという構成です。また、このアプリについては、Serviceを通してユーザに公開されます。
Kubernetesの基本については以下の記事で解説しているので、もしKubernetesの基礎から学びたいという方はぜひご覧ください。
ConfigMapとSecret
ConfigMap
コンテナの外部から値を設定するときに使うリソースです。時期やサービスの稼働状況によってある変数の値を変えなくてはいけないとき、プログラム中にその変数がハードコードされていると、変更のたびにシステムをデプロイしなくてはいけません。このような状況を無くすために、各Podで使う値を一度にまとめておくのが、ConfigMapというリソースです。
以下、ConfigMapの具体例です。
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
KEY1: "value1"
KEY2: "value2"実際に値を設定しているのは、dataの部分です。上記の例ではKEY1、KEY2にそれぞれ value1、value2を設定しています。この ConfigMap をPodを作成するときに読み込ませると、Pod内のアプリケーションが KEY1 および KEY2 を value1、value2 として取り扱うことができます。
Secret
アプリケーションが使う各種のパスワード情報をConfigMapに書いてしまうと、ConfigMapを閲覧できる人全員がパスワード情報も取得できてしまい、セキュリティ的によろしくない状況になってしまいます。
そこで登場するのが、Secret というリソースです。Secretにパスワード等の情報を記載しておくことで、比較的安全に各Podに情報を渡すことが可能になります。
ここで説明したSecretの安全性は、クラスタ内の情報のやり取りにおける安全性という意味であり、Secretを定義したYAMLファイル自体が安全というわけではなりません。YAMLファイルを読める場合、Secretに記載した情報はすぐに盗めてしまいます。
それでは、Secreリソースの定義方法をみていきましょう。ConfigMapと同じように書くことができます。
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
APP_PASSWORD: cGFzc3dvcmQ= # base64でエンコードする必要があるここで重要なのが、記載する情報は事前にBase64でエンコードする必要があります。Base64自体は暗号化でもなんでもなく、デコードはすぐにできてしまうため、上記で注意したようにこのYAMLファイルを読めてしまうとすぐにパスワード等の情報を盗まれてしまいます。
そのため、運用をするにあたりどういうセキュリティ対策を取るべきかは議論する必要がありますが、少なくともクラスタ内での機密情報の遣り取りをすることがある場合は、Secretに情報を書いておくとよいでしょう。
とりあえず動くアプリ作成
それでは、実際にこの記事で使うアプリを作成していきましょう。繰り返しにはなりますが、今回作るアプリの概念図は以下になります。

Secretの作成
今回、Secretは以下を用います。アプリに渡すパスワードという設定ですが、今回はcurlコマンドでアクセスした際に表示される文字列をAPP_PASSWORDとしてアプリの環境変数に渡します。
apiVersion: v1
kind: Secret
metadata:
name: demo-secret
type: Opaque
data:
APP_PASSWORD: cGFzc3dvcmQ=ConfigMapの作成
とりあえず動くということを目標にしてるので、ConfigMap は Secret とほぼ同じような構成にします。
apiVersion: v1
kind: ConfigMap
metadata:
name: demo-configmap
data:
APP_MESSAGE: "Hello from ConfigMap"Secretと同じようにして、アプリ内で使う変数 APP_MESSAGE に 「Hello from ConfigMap」という文字列を代入するだけのConfigMapになります。
Serviceの作成
外からのアクセスをアプリに誘導するためのServiceリソースを作成します。今回は詳しいことは省きますが、以下のYAMLファイルを持ちいます。
apiVersion: v1
kind: Service
metadata:
name: secret-demo-svc
spec:
selector:
app: secret-demo
ports:
- port: 8080
targetPort: 8080動かすアプリの作成
今回動かすアプリは、Pyhonで作成します。といっても難しいアプリではなく、Pythonで簡易的なHTTPサーバをたてて、特定の文字列を記載したHTMLを表示させるだけにします。以下がソースコードですが、Secret とConfigMap で指定した文字列を表示させるようにしています。
from http.server import BaseHTTPRequestHandler, HTTPServer
import os
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/secret":
password = os.environ.get("APP_PASSWORD", "NOT_SET")
message = os.environ.get("APP_MESSAGE", "NOT_SET")
body = f"APP_PASSWORD={password}, APP_MESSAGE={message}"
self.send_response(200)
self.end_headers()
self.wfile.write(body.encode())
else:
self.send_response(404)
self.end_headers()
HTTPServer(("", 8080), Handler).serve_forever()
このアプリは、/secretにアクセスがあったときに、Secret と ConfigMap に記載したAPP_PASSWORD と APP_MESSAGE を表示し、それ以外だとステータスコード 404 を返すようにしています。
ただ、このアプリを動かすためには実行するコンテナを作る必要があります。そのため、以下のようなDockerfileを作ってイメージをデプロイしておきます。本当はプライベートレジストリとかに登録したほうが良いかもしれませんが、設定が面倒なので・・・・
FROM python:3.11-slim
COPY app.py /app.py
CMD ["python", "/app.py"]Dockerfileの書き方については、以下の記事で解説しているのでもし気になる方は確認してみてください。
Dockerfileができたら、以下のコマンドでイメージをデプロイします。
docker build ./ -t secret-demoDockerでこのイメージを使う場合はこのままdocker runをすればよいですが、今回使っているクラスタである kind のPodで使うコンテナのイメージとして使うためには、ロードして上げる必要があります。上記のコマンドでデプロイできたら以下のコマンドでkindに読み込ませます。
kind load docker-image secret-demo:latestDeploymentの作成
今回のアプリの要でもあるDeploymentを作成します。少しコードが長くなりますが、以下のDeploymentを今回は使います。
apiVersion: apps/v1
kind: Deployment
metadata:
name: secret-demo
spec:
replicas: 3
selector:
matchLabels:
app: secret-demo
template:
metadata:
labels:
app: secret-demo
spec:
containers:
- name: app
image: secret-demo:latest
# ローカルイメージを使うためにこの下の設定が必要
imagePullPolicy: Never
env:
- name: APP_MESSAGE
valueFrom:
configMapKeyRef:
name: demo-configmap
key: APP_MESSAGE
- name: APP_PASSWORD
valueFrom:
secretKeyRef:
name: demo-secret
key: APP_PASSWORD
ports:
- containerPort: 8080
今回大事になるのが、「imagePullPolicy:」の部分です。これを書かないと、リモートからイメージファイルを取得しようとしてしまうため、ここの値は「Never」にしておきます。
実際に動かしてみる
ここまでくれば、あとは作ったYAMLファイルを適用していくだけです。以下のコマンドを続けて実行してください。
kubectl apply -f secret.yaml
kubectl apply -f configmap.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml以下のようにリソースができていればOKです。
$ kubectl get secret,configmap,deployment,service
NAME TYPE DATA AGE
secret/demo-secret Opaque 1 20m
NAME DATA AGE
configmap/demo-configmap 1 20m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/secret-demo 3/3 3 3 20m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/secret-demo-svc NodePort 10.96.211.31 <none> 8080:30483/TCP 20mそれでは、実際にアクセスしてみましょう。ポートフォワードするために次のコマンドを実行します。
kubectl port-forward deployment/secret-demo 8080:8080別のターミナルアプリを開き、以下のcurlコマンドを実行してみましょう。アプリから応答が来るはずです。
curl http://localhost:8080/secret以下、実行例です。
$ curl http://localhost:8080/secret
APP_PASSWORD=password, APP_MESSAGE=Hello from ConfigMap一応ブラウでも確認すると、次の表示が得られるはずです。

まとめ
今回は実務でも使われるような構成でKubernetesを用いたとりあえず動くアプリを作ってみました。自分自身、Kubernetesを勉強していてもいまいちどうやって使ったらいいのかわからないリソースや機能が多いため、この記事を書きながら改めて各リソースの作り方やYAMLファイルの書き方の振り返りができました。
また、今回の記事については以下の本を参考にしています。実際にいろいろ試しながらKubernetesを学ぶことができるので、もし興味がある方はお手にとって見てください。
ここまで読んでいただきありがとうございました!また次の記事でお会いしましょう。












