はじめに
Kubernetesで作業をしているときに、ブラウザで接続しているコンテナは、どのWorkerで動いているのか気になったため作成しました。
Workerをわざと停止して、接続先を確認する時に使っています。
動作確認した環境
- Raspberry Pi 4
- Ubuntu 20.04
- Docker 19.03.13
イメージ
https://hub.docker.com/r/yasthon/nginx-display-hostname にアップしています。
動かしてみる
ここでは、ホスト名「dockerhost.example.jp」の環境で実行しています。
$ docker pull yasthon/nginx-display-hostname
$ docker container run -d -v /etc/hostname:/usr/share/nginx/html/hostname -p 80:80 yasthon/nginx-display-hostname
$ curl http://localhost/index.sh
<html><head>
<title>dockerhost.example.jp</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head><body>
HOSTNAME : dockerhost.example.jp
</body></html>
ブラウザからも確認します。
http://[DockerホストのIPアドレス]/index.sh
にアクセスします。
HOSTNAME : dockerhost.example.jp
動作
コンテナの起動時に/etc/hostname
をmountしています。
Nginxからshを動かして、hostnameを読んでいます。
Dockerfile
ローカルでビルドする時に使うファイルです。
FROM debian:buster-slim
COPY default.conf /etc/nginx/conf.d/
COPY index.sh /usr/share/nginx/html/
RUN apt-get update && \
apt-get install -y --no-install-recommends nginx fcgiwrap && \
apt-get autoclean && \
rm -rf /var/lib/apt/lists/* && \
echo "daemon off;" >> /etc/nginx/nginx.conf && \
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
CMD /etc/init.d/fcgiwrap start && nginx
普通にOSへインストールした時は簡単に動作したのに、コンテナで実行したら問題が発生しました。
- Nginxのdefault rootは
/usr/share/nginx/html/
だと思いこんでいたら、/var/www/html
を参照していました。コンテナの用途が限定的なので、調査はせずに/etc/nginx/sites-enabled/default
を削除することで解決しました。 -
fcgiwrap.socket
が無かったです。CMDに/etc/init.d/fcgiwrap start
を追加してコンテナ起動時に作成しています。 - permissionエラーでました。
chmod
とchown
を追加しました。 - DockerHubからpullしたNginx Official イメージでは、思うように動作できなかったです。パッケージでインストールを行い動作させました。
default.conf
Nginxの設定ファイルです。
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;
}
}
Dockerfile に比べて、何の問題もなく。
index.sh
mountしたhostnameファイルを読み込んで表示します。
#!/bin/sh
host_name=$(cat hostname)
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 "</body></html>"
同じく、何の問題もなく。
ローカルでビルドする
イメージ名を「nginx-display-hostname」にしています。
3つのファイルを同じディレクトリに置いて、docker build
を実行します。
$ docker image build -t nginx-display-hostname .
$ docker container run -d -v /etc/hostname:/usr/share/nginx/html/hostname -p 80:80 nginx-display-hostname
$ curl http://localhost/index.sh
<html><head>
<title>dockerhost.example.jp</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head><body>
HOSTNAME : dockerhost.example.jp
</body></html>
ブラウザからも確認します。
http://[DockerホストのIPアドレス]/index.sh
にアクセスします。
HOSTNAME : dockerhost.example.jp
Kubernetes上での動作
volumeMountsとvolumesを使用して、/etc/hostname
をmountする必要があります。
apiVersion: v1
kind: Namespace
metadata:
name: nginx-prod # namespace の名前
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment # deployment の名前(replicaset の名前もこれになる)
namespace: nginx-prod # namespace の名前
spec:
selector:
matchLabels: # ラベルがマッチしたPodを対象とするreplicasetの作成
app: nginx-pod
replicas: 2
template: # Pod のテンプレート
metadata:
name: nginx-pod # Pod の名前
namespace: nginx-prod # Pod のnamespace の名前
labels: # Pod のラベル
app: nginx-pod
spec:
containers: # コンテナの設定
- name: nginx-container # コンテナの名前
image: yasthon/nginx-display-hostname # イメージの名前
env:
- name: nginx-container
ports:
- containerPort: 80 # コンテナのポート
volumeMounts:
- name: file-hostname
mountPath: /usr/share/nginx/html/hostname
volumes:
- name: file-hostname
hostPath:
path: /etc/hostname
Podを起動します。
$ kubectl apply -f sample.yaml
namespace/nginx-prod created
deployment.apps/nginx-deployment created
Podの名前を確認します。
$ kubectl get all -n nginx-prod
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-7ff4cc65cd-6r4qv 1/1 Running 0 3m52s
pod/nginx-deployment-7ff4cc65cd-djm9r 1/1 Running 0 3m52s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 2/2 2 2 3m53s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-7ff4cc65cd 2 2 2 3m53s
Podの詳細情報でIPを確認します。
$ kubectl describe pod/nginx-deployment-7ff4cc65cd-djm9r -n nginx-prod | grep ^IP:
IP: 10.244.1.5
Worker上から、確認したIPへアクセスします。
$ curl http://10.244.1.5/index.sh
<html><head>
<title>worker.example.jp</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head><body>
HOSTNAME : worker.example.jp
</body></html>
Pod(nginx-deployment-7ff4cc65cd-6r4qv)は、ホスト worker.example.jp で起動していることが確認できました。
クラスター外からブラウザでアクセスする場合は、Serviceが必要になります。
最後に
すぐに作れるだろう思い作り始めたのですが、予想外に時間がかかりました。
必要としている方のお役に立てれば幸いです。