動機
最近飼い始めたハムの日記をつけよう、ということでhelm使ってwordpress立ててみたら、意外に苦戦したのでメモしておく。
前提条件
- kubernetesとhelmが利用できる環境
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"11", GitVersion:"v1.11.1", GitCommit:"b1b29978270dc22fecc592ac55d903350454310a", GitTreeState:"clean", BuildDate:"2018-07-17T18:53:20Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.5", GitCommit:"32ac1c9073b132b8ba18aa830f46b77dcceb0723", GitTreeState:"clean", BuildDate:"2018-06-21T11:34:22Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
$ helm version
Client: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"}
- helmのChartはstable/wordpressで
appVersion: 4.9.7
- 筆者の環境はconjure-up => Juju:lxcで構築したkubernetes(1node)
Persistent Volumeを作成する
インストールするwordpressのhelmチャートは2つのPersistentVolume(PV)が必要なので、作成する。
nfsでのPVの作成方法はこちらを参考にさせてもらった。
Kubernetes: PersistentVolume概要とminikubeでの検証
まず、各PV用のディレクトリを作成。
install --directory --mode=777 /mnt/datahdd01/kube/rwo20g-wordpress01-wordpress
install --directory --mode=777 /mnt/datahdd01/kube/rwo8g-wordpress01-mariadb
次に、上記で作成したディレクトリをめがけたPVのyamlを作成する。
画像やら保存すると足りなくなりそうなのでサイズは多めに設定
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-rwo20g-wordpress01-wordpress
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
# PersistentVolumeClaim を削除した時の動作
persistentVolumeReclaimPolicy: Recycle
mountOptions:
- hard
## マウント先のNFS Serverの情報を記載
nfs:
path: /mnt/datahdd01/kube/rwo20g-wordpress01-wordpress
server: 10.174.70.1
どのぐらい使うかわからないのでhelmチャートデフォルトの8Gに設定
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-rwo8g-wordpress01-mariadb
spec:
capacity:
storage: 8Gi
accessModes:
- ReadWriteOnce
# PersistentVolumeClaim を削除した時の動作
persistentVolumeReclaimPolicy: Recycle
mountOptions:
- hard
## マウント先のNFS Serverの情報を記載
nfs:
path: /mnt/datahdd01/kube/rwo8g-wordpress01-mariadb
server: 10.174.70.1
作成したPVのyamlをkubernetesに適用し、実際にPVを作成する。
kubectl apply -f ./volumes/nfs/pv-nfs-rwo20g-wordpress01-wordpress.yaml
kubectl apply -f ./volumes/nfs/pv-nfs-rwo8g-wordpress01-mariadb.yaml
helm install
helm installでwordpressをインストールする。
helm install \
--name wordpress01 \
--namespace faru \
--set serviceType=NodePort \
--set mariadb.rootUser.password=***** \
--set mariadb.db.password=***** \
--set persistence.size=20Gi \
--set livenessProbe.initialDelaySeconds=1200 \
stable/wordpress
オプションの意味
オプション | 役割 | 備考 |
---|---|---|
--namespace faru | リリースするkubernetes上のnamespaceを指定する | |
--set serviceType=NodePort | 作成するServiceのType | うちのKubernetesは1NodeしかないのでNodePortを使っている |
--set mariadb.rootUser.password=***** | MariaDBのルートユーザパスワード | *****は置き換える |
--set mariadb.db.password=***** | MariaDBのWordpress用ユーザパスワード | *****は置き換える |
--set persistence.size=20Gi | WordPress用PVCのサイズ | |
--set livenessProbe.initialDelaySeconds=1200 | 生存ヘルスチェックの初期猶予時間 | 詳細説明します |
livenessProbe.initialDelaySeconds
ここが今回詰まったところ。
これを設定せずに起動するとPodsのログが下記のところまで進んだところで、コンテナ再起動してしまい、いつまで待ってもwordpressが起動しなかった。
Welcome to the Bitnami wordpress container
Subscribe to project updates by watching https://github.com/bitnami/bitnami-docker-wordpress
Submit issues and feature requests at https://github.com/bitnami/bitnami-docker-wordpress/issues
WARN ==> You set the environment variable ALLOW_EMPTY_PASSWORD=yes. For safety reasons, do not use this flag in a production environment.
nami INFO Initializing apache
apache INFO ==> Reconfiguring PID file location...
nami INFO apache successfully initialized
nami INFO Initializing php
nami INFO php successfully initialized
nami INFO Initializing mysql-client
nami INFO mysql-client successfully initialized
nami INFO Initializing wordpress
wordpre INFO WordPress has been already initialized, restoring...
mysql-c INFO Trying to connect to MySQL server
mysql-c INFO Found MySQL server listening at wordpress01-mariadb:3306
mysql-c INFO MySQL server listening and working at wordpress01-mariadb:3306
wordpre INFO Upgrading WordPress Database ...
調べてみると公式のissueで同じ症状を見つけた。
参考:kubernetes chart hangs after external DB connection #136
つまり、コンテナ初期化に異様に時間がかかることが原因となり、起動が終わる前にヘルスチェック(livenessProbe)が走ることで、
kubernetesはコンテナが壊れたと認識として再起動をかけてしまうようだ。
この対策として、issueにもあるようにinitialDelaySecondsを大幅に引き上げた。
1200秒は適当。
iptablesでポートフォワード
ローカルでlxc上にkubernetesノードを立てているので、外部公開用にServiceをポートフォワードをする。
kubectlのport-forwardはlocalhostしか使えないみたいなので、iptablesをいじってポートフォワードするシェルスクリプトを作ってみた。
#!/bin/bash
# exit code not 0 error
set -e
### Usage
usage_exit() {
echo "Usage: $0 [-m ADD/DEL] [-i private_if_name] [-p local_port] [-n kube_namespace] [ -s kube_service_name]"
echo "ex) $0 -m ADD -i lxdbr0 -p 8081 -n faru -s metabase01-metabase"
exit 1
}
### opts
while getopts m:i:p:n:s: OPT
do
case $OPT in
m) MODE=$OPTARG
;;
i) PRIVATE_IF_NAME=$OPTARG
;;
p) LOCAL_PORT=$OPTARG
;;
n) NAMESPACE=$OPTARG
;;
s) SERVICE_NAME=$OPTARG
;;
\?) usage_exit
;;
esac
done
if [ $OPTIND -lt 11 ]; then
echo "options are insufficient."
usage_exit
fi
### opts check
case $MODE in
ADD) APPEND_OR_DELETE='I'
APPEND_NUMBER='1'
;;
DEL) APPEND_OR_DELETE='D'
APPEND_NUMBER=''
;;
\?) echo "option m is ADD or DEL"
usage_exit
;;
esac
### private_if_namebash
echo "getting private IP"
PRIVATE_IP=$(ip -f inet address show dev ${PRIVATE_IF_NAME} | grep -o 'inet [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+' | grep -o [0-9].* | head -n 1)
echo ">> ${PRIVATE_IP}"
### get info from kubernetes
echo "getting kubernetes service port and IP"
NODE_PORT=$(kubectl get --namespace ${NAMESPACE} -o jsonpath="{.spec.ports[0].nodePort}" services ${SERVICE_NAME})
NODE_IP=$(kubectl get nodes --namespace ${NAMESPACE} -o jsonpath="{.items[0].status.addresses[0].address}")
echo ">> ${NODE_IP}:${NODE_PORT}(${SERVICE_NAME})"
### setting iptables
COMMENT="port forward setting :: port ${LOCAL_PORT} => ${NODE_IP}:${NODE_PORT}(${SERVICE_NAME})"
echo "setting iptables"
# nat:PREROUTING
echo ">> nat:PREROUTING"
iptables -t nat -${APPEND_OR_DELETE} PREROUTING ${APPEND_NUMBER} -p tcp \
--dport ${LOCAL_PORT} -j DNAT --to-destination ${NODE_IP}:${NODE_PORT} \
-m comment --comment "port ${COMMENT}"
# nat:OUTPUT for local packet
echo ">> nat:OUTPUT"
iptables -t nat -${APPEND_OR_DELETE} OUTPUT ${APPEND_NUMBER} -p tcp \
--dport ${LOCAL_PORT} -j DNAT --to-destination ${NODE_IP}:${NODE_PORT} \
-m comment --comment "port ${COMMENT}"
sysctl net.ipv4.conf.${PRIVATE_IF_NAME}.route_localnet=1
# nat:POSTROUTING
echo ">> nat:POSTROUTING"
iptables -t nat -${APPEND_OR_DELETE} POSTROUTING ${APPEND_NUMBER} -p tcp \
--dst ${NODE_IP} --dport ${NODE_PORT} -j SNAT --to-source ${PRIVATE_IP} \
-m comment --comment "${COMMENT}"
echo ">> ${MODE} ${COMMENT}"
echo "Finished!!"
exit 0
ローカルの8083から今回作成したwordpressのサービス(wordrpess01-wordpress)にポートフォワードする。
sudo ./commands/setup_port_forward_for_kubernetes.sh \
-m ADD -i lxdbr0 -p 8083 -n faru \
-s wordpress01-wordpress
ここまでくると、ブラウザからhttp://localhost:8083/ or http://<IPアドレス>:8083/にアクセスするとwordpress初期ページが表示される。
まとめ
helmでwordpressをデプロイする方法を紹介した。
- kubernetesでコンテナの初期化に時間を要する場合はlivenessProbeのinitialDelaySecondsを伸ばす
- lxcで構築したkubernetesでサービスを公開するためにiptablesを使ってポートフォワードするスクリプトを作成した
感想
- helmの簡単インストールもまだまだこんな感じで動かないことが多い
- helmに関する日本語の記事がほとんどない
- 記事の中でおかしいところ、もっと簡単にできるってところがあればコメント頂ければ幸いである