
前回の記事では、Dockerコンテナの手動構築とDockerfileでの構築、docker-composeでの構築を行いました。
最近ではKubernetesを使用したシステムも多くなっているようですので、Kubernetesについても少しふれておきたいと思います。
とはいえ、Kubernetesを使ったシステムはインフラ構築をすることと同じぐらいのバリエーションがありますので、ここで紹介するのはほんの一部です。
どういったものなのかということの「さわり」程度が理解できるところまでは紹介したいと思います。
Kubernetesとは
wikipediaでは以下のように説明されています。
Wikipedia:「コンテナ化したアプリケーションのデプロイ、スケーリング、および管理を行うための、オープンソースのコンテナオーケストレーションシステムである」
https://ja.wikipedia.org/wiki/Kubernetes
kubernetesは「クーベルネテス」などと読むようです。
docker-composeでもオーケストレーション的なことはできますが構築や起動を行うための機能でした。
それに対してkubernetesはシステムを運用するための仕組みといえます。
どちらかというとコンテナの構築より管理がメインの機能となります。
たとえば、コンテナの起動に関しても冗長化した状態で起動し、障害発生時には自動的に別のノードが起動するようになっています。
また、コンテナの更新を行う場合でもシステムが停止しないようにノードを順次入れ替える機能などもあるようです。(実際に動かしたことはないですが。。。)
具体的な機能としては以下のものがあります。
- コンテナオーケストレーション
- デプロイやアップデート(アプリケーション)
- アプリケーションリソースの自動スケーリング
- リリース効率化の実現
- ローリングアップデート
- 自動回復機能
kubernetesを使ったシステムの構造
kubernetesを使ったシステムは以下のような構造となっています。
kubernetesは自身が仮想化の仕組みを持っておらず、ユーザが(Docker,VertualBox,podmanなど)どの仮想化の仕組みを使うか選べれるようになっています。
そのため、仮想化の仕組みをどれを使うかをユーザが指定する必要がありますが、基本的にはインストールされているものが利用されるようです。
今回の環境の場合、Dockerがインストールされているので、kubernetesのインスタンスはDockerコンテナの一つとして立ち上がってきます。

kubernetesの内部は各ノードで分かれており、メインノードとワーカーノードがあります。
メインノードはkubernetesの本体でOSのようなものです。
ユーザ(我々)が意識しなければいけないのはワーカーノードのほうで、こちらでコンテナを動かしたりネットワークを構成したりします。
メインノードはこれらの機能を実現するためのシステムが動いているので、リソースは必要となりますが構造などをあまり意識する必要はないと思います。

ワーカーノードの中は上記のような構造です。
何層にもなっているのでわかりにくいですが、冗長化構成などを実現するために必要な階層となっています。
ただ、毎回このような複雑な階層の構築をしたくないので、各層はデフォルトで動くようになっています。
最小単位は”pod”で、”pod”の中でDockerコンテナなどを動かします。
“Replicas”や”pod”単位で冗長化することができ、冗長化された”pod”は”deployment”でまとめられます。
“service”はネットワークを制御するもの(と思われます)で”deployment”に対してポートの開放などを行います。
一般的な用語としては”deployment”はアプリなどをサーバー配置することに使われますがkubernetesでは”pod”をまとめるオブジェクトとして扱われます。
“service”も一般の意味と少し違うようなので、勘違いしないように気を付けてください。
kubernetesの種類
kubernetesは以下のような派生版が存在します。
- K8s
- K3s
- K0s
- minikube
- microK8s
初期に作られたkubernetesはk8sと表現されます。kとsの間に8文字あるからだそうです。(どこからそういった発想になるんでしょうねぇ。。。)
kubernetesはハードウェアリソースを多く使うので、小規模でも使えるk3sやminikubeができたようです。
構造や機能についてはあまり差はないようです。
今回はminikubeを使用してみます。
minikubeでシステム構築してみよう
前回作成したDockerイメージを使用してminikubeを使ったシステム構築をやってみましょう。
ますは、Dockerサービスを起動しておきます。
sudo systemctl start docker
minikubeではアンダースコア(“_”)が使えないことが多いので以下のファイルを修正しておきます。
nano docker-compose.yml
version: "3"
services:
ap:
build:
context: ./python/
ports:
- 8080:8080
environment:
TZ: "Asia/Tokyo"
container_name: python-server
web:
build: ./nginx
ports:
- 80:80
expose:
- 80
environment:
APSVHOST: "python-server"
APSVPORT: "8080"
TZ: "Asia/Tokyo"
container_name: "nginx-server"
depends_on:
- ap
nano nginx/nginx.conf.template
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
server_tokens off;
keepalive_timeout 65;
#gzip on;
upstream unit-python {
server ${APSVHOST}:${APSVPORT};
}
server {
listen 80;
server_name localhost;
location /html {
root /var/www;
}
location / {
proxy_pass http://unit-python;
proxy_set_header Host $host;
}
location /static/ {
alias /app/static/;
}
}
}
実行時の環境変数を使ってpytho-serverに接続するようにunit.configの生成とunitdの起動をシェルに置き換えます。
nano nginx/Dockerfile
FROM registry.access.redhat.com/ubi9/ubi:latest
RUN yum install -y --disableplugin=subscription-manager nginx nano gettext && \
yum clean all
RUN mkdir -p /var/www/html
COPY ./index.html /var/www/html/
RUN mkdir -p /etc/nginx/templates
COPY ./nginx.conf.template /etc/nginx/templates/
# ENV APSVHOST=python_server
# ENV APSVPORT=8080
# RUN cat /etc/nginx/templates/nginx.conf.template | envsubst '${APSVHOST},${APSVPORT}' > /etc/nginx/nginx.conf
EXPOSE 80/tcp
# CMD ["nginx", "-g", "daemon off;", "-c", "/etc/nginx/nginx.conf"]
COPY ./nginx.sh /etc/nginx/
RUN chmod 755 /etc/nginx/nginx.sh
CMD ["/etc/nginx/nginx.sh"]
nano nginx/nginx.sh
#!/bin/sh
cat /etc/nginx/templates/nginx.conf.template | envsubst '${APSVHOST},${APSVPORT}' > /etc/nginx/nginx.conf
nginx -g "daemon off;" -c /etc/nginx/nginx.conf
ファイルを更新したのでイメージを再構築しておきましょう。
sudo docker compose build
前述の通り、minikubeは仮想環境が必要です。
すでにDockerをインストールしてありますが、root権限以外のユーザでないとdockerの脆弱性対策(?)の影響でminikubeがうまく動いてくれないようです。
なので、rootユーザ以外でdockerコマンドが動くようにしておきましょう。
今回はホストPCとしてVertualBox上のubuntuを使用している関係で、”vboxuser”というユーザに権限を与えます。
sudo gpasswd -a vboxuser docker
cd /var/run/
sudo chown vboxuser:vboxuser docker.sock
以下のコマンドが動けばOKです。
docker version
minikubeインストール
以下のコマンドでインストールします。
使用するホストPCごとにインストールコマンドが異なるので、正規サイトで環境を選択してインストールするようにしてください。
# インストール
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube_latest_amd64.deb
sudo dpkg -i minikube_latest_amd64.deb
# インストール確認
minikube version
インストール出来たら起動しましょう
minikube start
“docker ps -a”を実行すると、Dockerコンテナとして動作していることが確認できます。
続いて”kubectl”をインストール(?)しておきます。
“kubectl”はデプロイした”pod”や”service”の状態を確認したり削除したりするときに使用する重要なツールになります。
以下のコマンドで使用できるようになります。
minikube kubectl version
“kubectl”コマンドは”minikube kubectl”という感じで使用することになるのですが、毎回、これを入力するのは面倒なので”kubectl”だけで使用できるようにしておきましょう。
alias kubectl="minikube kubectl --"
この設定はminikubeを再起動すると無効になってしまうので、再起動したら再度設定してください。
minikube、kubectlコマンドは以下のものがあります。
# minikubeを終了する
minikube stop
# minikubeを削除する
minikube delete
# minikubeの起動状態を確認する
minikube status
# minikubeのIPアドレスを確認する
minikube ip
# minikubeにSSH接続する
minikube ssh
# minikubeのアドオンリストを表示する
minikube addons list
# Kubernetesダッシュボードを起動する
minikube dashboard
# クラスタ一覧を表示する
kubectl cluster-info
# ノード一覧を表示する
kubectl get node
# サービス一覧を表示する
kubectl get service
minikubeの状況はダッシュボードを使用してブラウザ上のGUIで見ることができます。
以下のコマンドを実行するとURLが表示されるのでホストPC上のブラウザに入力すると以下のような画面が表示されます。(Linuxディスクトップ上のコンソールの場合はブラウザが自動的に起動します。)
minikube dashboard

minikubeにシステムを構築してみる
前回作成したDockerイメージを使用してminikube上にシステムを構築してみましょう。
minikubeにDockerイメージを読み込ませてシステムを構築していきます。
まず、イメージにタグをつけておきます。(”latest”だとうまくいかなかったので”v1″にしています。)
docker tag docker-web nginx-server:v1
docker tag docker-ap python-server:v1
イメージをminikubeにロードします。
minikube image load nginx-server:v1
minikube image load python-server:v1
ロードしたイメージは以下のコマンドで確認できます。
minikube image ls
手動でpythonサーバーのみ構築してみましょう
前回と同様、まずは手動でシステムを構築してみたいと思います。
nginx-serverとpython-serverを連携させるのは難しいので、python-serverのみデプロイしてアクセスしてみましょう。
以下のコマンドでロードしたイメージを使用して”deployment”を作成します。
“deployment”を作成すると”default”クラスタ、”default”レプリカセットに”pod”が自動的に作成されます。
kubectl create deployment python-deployment --image=python-server:v1
デプロイ結果は以下のコマンドで確認できます。
# deployment一覧
kubectl get deployment
# pod一覧
kubectl get pod
次に”service”を作成してポートを開放し、外部からのアクセスができるようにします。
kubectl expose deployment python-deployment --type=NodePort --port=8080
サービス構築の結果は以下のコマンドで確認できます。
# サービス一覧
kubectl get service
# 外部からアクセスするときのURL
minikube service python-deployment --url
ホストPCから”http://localhost:8080″でアクセスできるようにポートフォワードを実行します。
kubectl port-forward service/python-deployment 8080:8080
別コンソールで以下を実行するとFlaskの実行結果が返ってきます。
curl http://localhost:8080
次は定義ファイルを作成してnginx-serverと一緒にデプロイしてみます。
手動で作ったものは、一旦、削除しましょう。
# サービスを削除
kubectl delete service python-deployment
# デプロイメント(pod)を削除
kubectl delete deployment python-deployment
定義ファイルを使って構築してみよう
では、nginx-server、python-serverをデプロイする定義ファイルを作成しましょう。
nano deployment.yaml
apiVersion: apps/v1
# 定義の種類
kind: Deployment
metadata:
name: python-nginx-deployment
spec:
# レプリカ数: レプリカとは複数のことで、ここの数字分の Pod を常に起動させる
replicas: 3
# 指定した条件に一致する Pod をこの Deployment が管理する (ここではlabelが一致すること)
selector:
matchLabels:
app: python-nginx-deployment
# 作成する Pod の定義
template:
metadata:
labels:
app: python-nginx-deployment
spec:
# Pod で起動するコンテナの定義 (Docker hubから取ってくる image を記載する)
containers:
- name: python-server
image: python-server:v1
ports:
- containerPort: 8080
- name: nginx-server
image: nginx-server:v1
ports:
- containerPort: 80
env:
- name: APSVHOST
value: "localhost"
- name: APSVPORT
value: "8080"
同一pod内にnginx-server、python-serverの2つのコンテナを配置する構成としました。
この構成の場合、nginx-serverからpython-serverへのアクセスは”localhost”でアクセスできるようなので、「APSVHOST=”localhost”」としています。
続いて、サービスの定義ファイルを作成します。
nano service.yaml
apiVersion: v1
kind: Service
metadata:
name: python-nginx-service
spec:
ports:
- name: python-server
port: 8080
targetPort: 8080
protocol: TCP
- name: nginx-server
port: 80
targetPort: 80
protocol: TCP
# 指定したラベルにマッチする Pod に Service へのアクセスが割り振られる
type: NodePort
selector:
app: python-nginx-deployment
作成した定義ファイルを使ってデプロイしましょう。
# サービス
kubectl apply -f service.yaml
# デプロイ
kubectl apply -f deployment.yaml
状況は以下のコマンドで確認できます。
# deploymentの状態
kubectl get pod
# podの状態
kubectl get pod
# serviceの状態
kubectl get service
# deploymentの動作状況(podの状態)
kubectl describe service/python-nginx-service
# podのログ
kubectl logs [pod名] --all-containers
# (例)
kubectl logs python-nginx-deployment-85479bf8cf-qzwc5 --all-containers
# podにSSHコンソールで入る
kubectl exec -it [pod名] --container [コンテナ名] /bin/bash
# (例)
kubectl exec -it python-nginx-deployment-56ccc8cd55-dmdj4 --container nginx-server /bin/bash
# サービスの状態
minikube service python-nginx-service
# (出力結果)
|-----------|----------------------|--------------------|---------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|-----------|----------------------|--------------------|---------------------------|
| default | python-nginx-service | python-server/8080 | http://192.168.49.2:30144 |
| | | nginx-server/80 | http://192.168.49.2:32563 |
|-----------|----------------------|--------------------|---------------------------|
最後にポートフォワードしてホストPCからのアクセスを確認してみましょう。
(80番ポートが何かに使われてたみたいなので、8081を使用しています。)
kubectl port-forward service/python-nginx-service 8081:80
curl http://localhost:8081
“minikube dashboard”で起動状態を確認してみてもいいと思います。
まとめ
今回はminikubeを使用してkubernetesを使ったシステム構築を紹介しました。
紹介した構成はpod内にコンテナを2つ配置する構成ですが、python-sever、nginx-serverそれぞれを別のpodに配置してサービスで連携したり、ロードバランサー(kube-loadbalancer)を使ったりすることもできるようです。
kubernetesにはもっとたくさんの機能や使い方がありますので、冗長化やシステム管理のユースケースに応じてpodの構成やReplicaSetの構成、nodeの分散などを行ってもらえればと思います。