Posted at

kubernetesで動かすソフトウェアの設定をConfigMapで記述する

More than 1 year has passed since last update.


まとめ

nginx.confなどの設定ファイルをkubernetesのConfigMapで記述し、Volumeとしてマウントすることが出来る。


ドキュメントはこの辺り。

実際のyamlファイルはGistにある。


何が課題か

kubernetesで動かすDockerコンテナ内にどうやって各アプリケーションが使用する設定ファイルを差し込むか、という話。

例えばnginx.confなどの設定ファイルをどうやって管理するか。

いくつか方法がある。


  • Dockerイメージの中に入れておく



    • ADDした状態でdocker buildしておく



  • ファイルにしておいてコンテナにVolumeとしてマウントする


    • デプロイするホストのディレクトリをマウントする

    • 永続ディスクを作成してそこに配置しておいてマウントする



  • どこかのストレージに置いておいてダウンロードする

あたりが一般的な気がする(要出典)。

しかし、それぞれ難点がある


  • Dockerイメージの中に入れておく


    • 例えばNginxの公式イメージをそのまま使えない


    • docker build, docker pushして使う必要があって面倒



  • ファイルにしておいてコンテナにVolumeとしてマウントする


    • ファイルを置くNodeの状態を管理しないといけない

    • 設定を変更するたびにストレージを変更するのは面倒



  • どこかのストレージに置いておいてダウンロードする


    • 権限とか考えないといけなくて面倒



と、どれを選んでも一長一短という感じ。


そこでConfigMap

kubernetesにはConfigMapというものがあり、簡単にいうとkey-valueで値を持てるもの。

環境変数にイメージは近いが、上に書いたような設定ファイルも持つことが出来る。

さらに、ConfigMapはvolumeとしてもマウントできるようになっているのがポイント。


ドキュメント


設定ファイルをConfigMapで定義する

yamlでは改行を含む文字列を定義できる。

YAMLの基本について - TASK NOTES

pipe(|)を使うと改行を含んでいても一つのスカラ値として扱うことが出来る。

こんな感じ。

message: |

hello
world

|+とか|-とか>もあって少しずつ違うが|で大体は問題ないはず。

/etc/nginx/nginx.confと/etc/nginx/virtualhost/virtualhost.confをConfigMapで定義してみる。

data項目の下に、nginx.confvirtualhost.confとしてそれぞれ記述する。

apiVersion: v1

kind: ConfigMap
metadata:
name: nginx-conf
data:
nginx.conf: |
user nginx;
worker_processes 3;
error_log /var/log/nginx/error.log;
events {
worker_connections 10240;
}
http {
log_format main
'remote_addr:$remote_addr\t'
'time_local:$time_local\t'
'method:$request_method\t'
'uri:$request_uri\t'
'host:$host\t'
'status:$status\t'
'bytes_sent:$body_bytes_sent\t'
'referer:$http_referer\t'
'useragent:$http_user_agent\t'
'forwardedfor:$http_x_forwarded_for\t'
'request_time:$request_time';

access_log /var/log/nginx/access.log main;

server {
listen 80;
server_name _;

location / {
root html;
index index.html index.htm;
}
}
include /etc/nginx/virtualhost/virtualhost.conf;
}
virtualhost.conf: |
upstream app {
server localhost:8080; # localhost:8080で受け付けるWebアプリがあるとして
keepalive 1024;
}

server {
listen 80 default_server;
server_name _;
root /usr/local/app;

access_log /var/log/nginx/app.access_log main;
error_log /var/log/nginx/app.error_log;

location / {
proxy_pass http://app/;
proxy_http_version 1.1;
}
}

こうやって定義したCofigMapを公式のnginxイメージに適用してみる。

---

apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx # /etc/nginxにvolumesのnginx-confをmountする
readOnly: true
name: nginx-conf
- mountPath: /var/log/nginx
name: log
volumes:
- name: nginx-conf # volumeMountsで/etc/nginxにmountするやつ
configMap:
name: nginx-conf # ConfigMapのnginx-confを/etc/nginx以下に配置する
items:
- key: nginx.conf # nginx-confのkey
path: nginx.conf # nginx.confというファイル名
- key: virtualhost.conf
path: virtualhost/virtualhost.conf # ディレクトリを掘ることも可能
- name: log
emptyDir: {}

---
apiVersion: v1
kind: Service # nginxにアクセスする用のservice
metadata:
name: nginx
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: nginx


デプロイ,動作確認

実際にkubernetesにデプロイして、ConfigMapがファイルとして存在しているかどうかを確認してみる。

$ kubectl create namespace nginx-sample

namespace "nginx-sample" created

$ kubectl --namespace=nginx-sample apply -f ./nginx-sample.yaml
configmap "nginx-conf" created
deployment "nginx" created
service "nginx" created

$ kubectl --namespace=nginx-sample get po
NAME READY STATUS RESTARTS AGE
nginx-d78988cbc-js2fx 1/1 Running 0 10s

ここまでで起動できたので、kubectl execでファイルを見てみると正しく配置されていることが分かる。

$ kubectl exec  --namespace=nginx-sample -it nginx-d78988cbc-js2fx -c nginx -- ls -lhR /etc/nginx/

/etc/nginx/:
total 4.0K
lrwxrwxrwx 1 root root 17 Mar 11 01:38 nginx.conf -> ..data/nginx.conf
drwxr-xr-x 2 root root 4.0K Mar 11 01:38 virtualhost

/etc/nginx/virtualhost:
total 0
lrwxrwxrwx 1 root root 38 Mar 11 01:38 virtualhost.conf -> ../..data/virtualhost/virtualhost.conf

続けてnginx.confの設定が正しく反映されていることを確認してみる。

$ curl $(minikube service --namespace=nginx-sample nginx --url) -I # localhost:8080で動くサービスがないのでエラーになるけど気にしない

HTTP/1.1 502 Bad Gateway
Server: nginx/1.13.9
Date: Sun, 18 Mar 2018 08:07:08 GMT
Content-Type: text/html
Content-Length: 173
Connection: keep-alive

$ kubectl exec --namespace=nginx-sample -it nginx-d78988cbc-js2fx -- cat /var/log/nginx/app.access_log # logの中見を見る
remote_addr:172.17.0.1 time_local:18/Mar/2018:08:07:08 +0000 method:HEAD uri:/ host:192.168.99.100 status:502 bytes_sent:0 referer:- useragent:curl/7.54.0 forwardedfor:- request_time:0.000

log_formatで指定したようなログになっていることが確認できた。