何年か前に思ったのだが、所詮、Kubernetesなんて、熱狂的な人が飛びついて、ユーザ会なんかを作って、適当に盛り上がって終わる。CloudStackやOpenStackみたいな感じになるのではと思っていた。CloudStackは、企業を渡り歩いて今でも製品として存在してはいる。OpenStackも開発はされていて進化をしている。2つともあの時のユーザ会がぁという熱はどうなってしまったんだろうか。OpenStackは結構企業を巻き込んでいたが。。。ユーザ会が立ち上がるものは、なんとなく先がないような気がする。ユーザ会を建てるだけの仕事とかありそう。
Kubernetesはどうやらその道から外れて、結構使われ始めてきたような気がする。
ただ、やはりインフラ屋さんには扱いが難しい。アプリが絡むから。そもそもインフラ屋さんはアプリなんてあんまり気にしないし、アプリを作れと言われても作りたいアプリもそんなに思い浮かばない。いまやAIがプログラムを書いてくれるので、なんか願えばいいのにと思うのだが。そもそもそれ以前の話なのかもしれない。
閑話休題
今更、こんなことを書くのはどうかと思うが、多分知らない人は全く知らないので改めて記載してみた。
Dockerのプライベートレジストリを作る記事を以前書いたが、一体どのように使うのか?
ちなみに、このコンテナ環境は、1台 4vCPU 8GB RAM 100GB HDDのUbuntu Server 22.04あるいは24.04のフレッシュインストール環境に以下のシェルを流しただけの環境。このシェルでKubernetes (k3s)とDocker、プライベートレジストリの環境が全部できる。
https://gist.github.com/masezou/65c29fcff3a761335506b908f97228a3
sudo -i
wget https://gist.github.com/masezou/65c29fcff3a761335506b908f97228a3
bash ./k8s-setup.sh
以後に出てくる”192.168.11.58”というアドレスは、構築した1台のUbuntuサーバのIPアドレス。
余談だが、このスクリプトはライセンスは放棄しているので、勝手にご利用どうぞなんだが。どこかの会社が使いたいからライセンスを決めてくダサいと言われたことがある。一応、M.I.Tでいいと答えたが。もちろん入手元さえ明記してくれれば、無償でどうぞとなっている。確かにインフラの人が理解するための必要な装備が全部入っているから便利かも。
例えばBitnamiのWordpressは以下のようにして簡単に構築することができる。(WordPressもアクセス方法やチューニングにコツがあるのだが、今回はアクセス確認すら割愛)
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install wp-release bitnami/wordpress \
--version 24.2.9 \
--namespace wordpress-bitnami \
--create-namespace
名前空間wordpress-bitnamiでwordpressが展開できた。
以下を実行してみる。
kubectl get pods -n wordpress-bitnami -o jsonpath="{range .items[*]}{.metadata.name}{':\t'}{range .spec.containers[*]}{.image}{'\n'}{end}{end}”
wp-release-mariadb-0: docker.io/bitnami/mariadb:11.4.5-debian-12-r12
wp-release-wordpress-85cfc9b9cd-msmjp: docker.io/bitnami/wordpress:6.8.1-debian-12-r5
名前空間wordpress-bitnamiでは、コンテナイメージは、docker.ioのイメージを使っている。
このようにインターネットからイメージを落とせるので、単純に動かすだけでは、プライベートレジストリはいらない。ただ、コンテナ環境がインターネットにつながっていないのであれば、プライベートイメージに一度コピーをしてから使う必要がある。
docker.ioにあるコンテナイメージをプライベートレジストリ192.168.11.58:5000にコピー(Pull / Push)をしてみる。
docker pull docker.io/bitnami/wordpress:6.8.1-debian-12-r5
docker tag docker.io/bitnami/wordpress:6.8.1-debian-12-r5 192.168.11.58:5000/bitnami/wordpress:6.8.1-debian-12-r5
docker push 192.168.11.58:5000/bitnami/wordpress:6.8.1-debian-12-r5
reg tags -f 192.168.11.58:5000/bitnami/wordpress
docker image rmi bitnami/wordpress:6.8.1-debian-12-r5
docker pull docker.io/bitnami/mariadb:11.4.5-debian-12-r12
docker tag docker.io/bitnami/mariadb:11.4.5-debian-12-r12 192.168.11.58:5000/bitnami/mariadb:11.4.5-debian-12-r12
docker push 192.168.11.58:5000/bitnami/mariadb:11.4.5-debian-12-r12
reg tags -f 192.168.11.58:5000/bitnami/mariadb
docker image rmi bitnami/mariadb:11.4.5-debian-12-r12
プライベートレジストリ192.168.11.58:5000にあるイメージを利用して、名前空間wordpress-bitnami-localで展開してみる。
bitnamiのイメージを手元に持ってきた場合は、 allowInsecureImages: trueをつけないと、mariadbがDigestと違うといってエラーになる。namespaceを変えて展開する。
cat << EOF > values.yaml
global:
imageRegistry: 192.168.11.58:5000
security:
allowInsecureImages: true
image:
repository: bitnami/wordpress
tag: 6.8.1-debian-12-r5
mariadb:
image:
repository: bitnami/mariadb
tag: 11.4.5-debian-12-r12
EOF
helm install wp-release bitnami/wordpress \
--version 24.2.9 \
--namespace wordpress-bitnami-local \
--create-namespace \
-f values.yaml
新しく展開したwordpressのイメージを確認すると、ちゃんとプライベートレジストリから起動している。
kubectl get pods -n wordpress-bitnami-local -o jsonpath="{range .items[*]}{.metadata.name}{':\t'}{range .spec.containers[*]}{.image}{'\n'}{end}{end}”
wp-release-mariadb-0: 192.168.11.58:5000/bitnami/mariadb:11.4.5-debian-12-r12
wp-release-wordpress-85c7f7dc76-kngp8: 192.168.11.58:5000/bitnami/wordpress:6.8.1-debian-12-r5
以下で脆弱性スキャンができる。(grypeのインストールはダウンロードするだけなので割愛)
grype 192.168.11.58:5000/bitnami/wordpress:6.8.1-debian-12-r5
grype 192.168.11.58:5000/bitnami/mariadb:11.4.5-debian-12-r12
いくつかの脆弱性が報告されたと思う。
少なくともベースのdebian-12のパッケージだけでも最新にしたいが、毎回展開のたびにコンテナに入ってapt updateなんかしていられないのでイメージ側で更新しておくべき。
よって、イメージを更新する。
mkdir -p wordpress
cd wordpress
cat << 'EOF' > Dockerfile
FROM bitnami/wordpress:6.8.1-debian-12-r5
USER root
RUN apt-get update && \
apt-get upgrade -y && \
apt-get autoremove -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
USER 1001
EOF
docker build -t bitnami-update/wordpress:1.0.0 -f Dockerfile .
docker tag bitnami-update/wordpress:1.0.0 192.168.11.58:5000/bitnami-update/wordpress:1.0.0
docker tag bitnami-update/wordpress:1.0.0 192.168.11.58:5000/bitnami-update/wordpress:latest
docker push 192.168.11.58:5000/bitnami-update/wordpress:1.0.0
docker push 192.168.11.58:5000/bitnami-update/wordpress:latest
reg tags -f 192.168.11.58:5000/bitnami-update/wordpress
docker image rmi bitnami-update/wordpress:1.0.0
cd ..
mkdir -p mariadb
cd mariadb
cat << 'EOF' > Dockerfile
FROM bitnami/mariadb:11.4.5-debian-12-r12
USER root
RUN apt-get update && \
apt-get upgrade -y && \
apt-get autoremove -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
USER 1001
EOF
docker build -t bitnami-update/mariadb:1.0.0 -f Dockerfile .
docker tag bitnami-update/mariadb:1.0.0 192.168.11.58:5000/bitnami-update/mariadb:1.0.0
docker tag bitnami-update/mariadb:1.0.0 192.168.11.58:5000/bitnami-update/mariadb:latest
docker push 192.168.11.58:5000/bitnami-update/mariadb:1.0.0
docker push 192.168.11.58:5000/bitnami-update/mariadb:latest
reg tags -f 192.168.11.58:5000/bitnami-update/mariadb
docker image rmi bitnami-update/mariadb:1.0.0
cd ..
これで、新しいイメージができた
ので、bitnamiのイメージをレジストリに持ってきただけのwordpress-bitnami-localのイメージを入れ替える。
名前空間wordpress-bitnami-localで動いているdocker.ioから持ってきただけのイメージを修正済みのイメージと入れ替えてみる。
cat << EOF > values.yaml
global:
imageRegistry: 192.168.11.58:5000
security:
allowInsecureImages: true
image:
repository: bitnami-update/wordpress
tag: 1.0.0
mariadb:
image:
repository: bitnami-update/mariadb
tag: 1.0.0
EOF
helm upgrade wp-release bitnami/wordpress \
--version 24.2.9 \
--namespace wordpress-bitnami-local \
-f values.yaml
しばらく待つと、名前空間wordpress-bitnami-localで動作しているイメージが以下のように入れ替わる。
kubectl get pods -n wordpress-bitnami-local -o jsonpath="{range .items[*]}{.metadata.name}{':\t'}{range .spec.containers[*]}{.image}{'\n'}{end}{end}”
wp-release-mariadb-0: 192.168.11.58:5000/bitnami-update/mariadb:1.0.0
wp-release-wordpress-dff6c8568-q7p59: 192.168.11.58:5000/bitnami-update/wordpress:1.0.0
自作のイメージをコンテナに作成する場合のEnd 2 Endのデモ
今までは、作成済みのコンテナイメージに手を入れることをやったが、自作のイメージを動かすためのデモ。
これから作るコンテナイメージは、Horizontal Pod AutoscalerでWebフロントエンドを作成したときに、複数のWebフロントエンド(つまりPod)が応答しているはずだが、実際にどのPodが応答しているか知りたいという目的で作ったもの。WebアクセスをするとPod名が表示されるようになっている。
まずは、コンテナイメージの作成
mkdir demo-nginx
cd demo-nginx
docker pull debian:trixie-slim
# Dockerfile
cat <<'EOF' >Dockerfile
FROM debian:trixie-slim
COPY default.conf /etc/nginx/conf.d/
COPY index.sh /usr/share/nginx/html/
COPY entrypoint.sh /entrypoint.sh
RUN apt-get update && \
apt-get install -y --no-install-recommends nginx fcgiwrap spawn-fcgi procps && \
apt-get autoclean && \
rm -rf /var/lib/apt/lists/* && \
rm -f /etc/nginx/sites-enabled/default && \
chmod 744 /usr/share/nginx/html/index.sh && \
chown www-data:www-data /usr/share/nginx/html/index.sh
ENTRYPOINT ["/entrypoint.sh”]
EOF
# default.conf
cat <<'EOF' >default.conf
server {
listen 80;
server_name localhost;
location ~ \.sh$ {
root /usr/share/nginx/html/;
include /etc/nginx/fastcgi_params;
fastcgi_index index.sh;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
}
}
EOF
# index.sh
cat <<'EOF' >index.sh
#!/bin/sh
host_name=$(cat hostname)
pod_name=$(hostname)
# sleep 5
echo "Content-type:text/html”
echo “”
echo "<html><head>”
echo "<title>${host_name}</title>”
echo '<meta http-equiv="Content-type" content="text/html;charset=UTF-8”>’
echo "</head><body>”
echo "HOSTNAME : ${host_name}”
echo "POD HOSTNAME : ${pod_name}”
echo "</body></html>”
EOF
# entrypoint.sh
cat << 'EOF' > entrypoint.sh
#!/bin/bash
set -e
echo "[INFO] Launching fcgiwrap using spawn-fcgi…”
mkdir -p /var/run
spawn-fcgi -s /var/run/fcgiwrap.socket -U www-data -G www-data -- /usr/sbin/fcgiwrap
if [ ! -S /var/run/fcgiwrap.socket ]; then
echo "[ERROR] fcgiwrap socket not found!”
ls -l /var/run
exit 1
fi
chmod 766 /var/run/fcgiwrap.socket
echo "[INFO] Starting nginx…”
exec nginx -g "daemon off;”
EOF
chmod +x entrypoint.sh
# docker build
docker image build -t nginx-display-hostname .
次に、Dockerレベルでの動作確認
docker run -d --rm --name demo-container -p 8081:80 nginx-display-hostname:latest
curl http://localhost:8081/index.sh
以下のようにコンテナIDが出てくればOK
<html><head>
<title></title>
<meta http-equiv=”Content-type” content=”text/html;charset=UTF-8”>
</head><body>
HOSTNAME :
POD HOSTNAME : 79a7b4116f87
</body></html>
一旦コンテナを止める
docker stop demo-container
プライベートレジストリにこのイメージをPushする。
docker tag debian:trixie-slim 192.168.11.58:5000/debian:trixie-slim
docker push 192.168.11.58:5000/debian:trixie-slim
docker tag nginx-display-hostname:latest 192.168.11.58:5000/nginx-display-hostname:latest
docker push 192.168.11.58:5000/nginx-display-hostname:latest
reg tags -f 192.168.11.58:5000/debian:trixie-slim
reg tags -f 192.168.11.58:5000/nginx-display-hostname:latest
docker rmi debian:trixie-slim
docker rmi nginx-display-hostname
このイメージを利用して、コンテナを作る。
cat << "EOF" > nginx-display.yaml
apiVersion: v1
kind: Namespace
metadata:
name: demo-nginx
—
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-display
namespace: demo-nginx
labels:
app: nginx-display
spec:
replicas: 1
selector:
matchLabels:
app: nginx-display
template:
metadata:
labels:
app: nginx-display
spec:
containers:
- name: nginx-display
image: 192.168.11.58:5000/nginx-display-hostname:latest
ports:
- containerPort: 80
resources:
requests:
cpu: 10m
limits:
cpu: 100m
—
apiVersion: v1
kind: Service
metadata:
name: nginx-display
namespace: demo-nginx
spec:
type: NodePort
selector:
app: nginx-display
ports:
- port: 80
targetPort: 80
nodePort: 30081
—
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nginx-display-hpa
namespace: demo-nginx
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx-display
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 20
EOF
kubectl apply -f nginx-display.yaml
以下のコマンドを実行するとプライベートレジストリからロードされているのがわかる。
kubectl get pods -n demo-nginx -o jsonpath="{range .items[]}{.metadata.name}{':\t'}{range .spec.containers[]}{.image}{'\n'}{end}{end}"
nginx-display-857fdcc8c7-nzj5p: 192.168.11.58:5000/nginx-display-hostname:latest
以下のコマンドを実行して、コンテナが起動したかどうかを確認する。Horizon Pod Autoscalerも設定されているのがわかる。
kubectl -n demo-nginx get all
NAME READY STATUS RESTARTS AGE
pod/nginx-display-857fdcc8c7-nzj5p 1/1 Running 0 19m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx-display NodePort 10.43.99.108 <none> 80:30081/TCP 25m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-display 1/1 1 1 25m
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-display-55786b9bfd 0 0 0 21m
replicaset.apps/nginx-display-6cd85cdc78 0 0 0 25m
replicaset.apps/nginx-display-857fdcc8c7 1 1 1 19m
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/nginx-display-hpa Deployment/nginx-display cpu: 0%/20% 1 2 1 25m
動作確認
curl http://192.168.11.58:30081/index.sh
Pod名が出ているのが確認できる。
<html><head>
<title></title>
<meta http-equiv=”Content-type” content=”text/html;charset=UTF-8”>
</head><body>
HOSTNAME :
POD HOSTNAME : nginx-display-857fdcc8c7-nzj5p
</body></html>
もし、Autoscalerを試したいのであれば
apt -y install apache2-utils
ab -n 500 -c 20 http://192.168.11.58:30081/index.sh
kubectl -n demo-nginx get all
負荷に応じて、Podの数が増えていく。
コンテナイメージの修正から、作成、さらにHorizon Pod Autoscalerまで飛躍してしまったが、このようにプライベートレジストリがあると、インターネットにつながっていなくてもコンテナを展開できたり、イメージの更新、あるいは自作イメージの可動をさせるのに便利。というか無くては始まらない。
もし、プライベートレジストリがないのであれば、環境を作るたびにインターネットからダウンロードあるいは、ビルドしなおしということになってしまう。
多分、これは、仮想マシンレベルしか興味がない、知らない人、言うなれば、AWSやAzureをvSphereもどきだと思って、1インスタンスずつ、インスタンス自体を管理、愛でている人が越えなきゃいけない壁の一つなのかもれない。