【kubernetes】Pod間に依存関係を持たせるときの一工夫
Kubernetesにアプリをデプロイするにあたり、Podが1つということはあまりないと思う。
かつ複数のPod(AとB)を、Aが起動できてからBを起動させる、みたいに依存関係を持たせるのは一般的に考えられるユースケースだと思う。WEB + DBなんかは特に。
本記事はそんな話。
docker-compose
dockerをインストールすればdocker-composeもKubernetesもインストールできる。
まだKubernetesよりdocker-composeで複数コンテナ作ってみる人のほうが多いのではと思う。のでdocker-composeでのやり方と比較(というほどでもないが)しながら進めたい。
docker-composeはコンテナ間、KubernetesはPod間という違いはある。
depends_onやlinks
docker-comopseではyamlファイルにdepends_onやlinksといったハッシュキーが用意されている。
version2からはこれらの違いは無くて、どちらもコンテナの依存関係を定義し、[エイリアス名]を使用してコンテナにアクセスすることができる。
依存関係を定義しておけば、依存元は依存先が立ち上げるのを待ってから、起動する。
Kubernetes
Kubernetesでは、docker-composeのように依存関係を明記する機能は備わっていない。
とはいえ必要な機能だからか、公式ページにやり方が記載されている。
PostStart
Container Lifecycle Hooksの1つに、PostStartというのがある。
公式ドキュメント
ざっくり訳す。
ここで定義した内容は、コンテナが作成された後に実行される。
ただし、コンテナのENTRYPOINTの前後どちらになるかは保証されない。
ふむ、今回の用途には不向きのようだ。
initContainers
containersとは別にinitContainersというのがある
公式ドキュメント
containersとの違い
こちらもざっくり訳す。
Init Containersでは、普通のContainerと同じfieldやfeatureをサポートしていて、resource limits, volumes, security settingなんかもある。でも、resource requestsやlimitsの扱いはちょっと違っていて、それはResourceのページ見てくれ。あとはreadiness probesはサポートしていない、だってPodがreadyになる前に完了するものだから。
複数のInit Containersがポッドにある場合、順番に走る。前のやつが成功するまで次のやつは走らない。すべてのInit Containersが完了したら、Podが初期化されて通常通りコンテナが実行される。
うん、これならいけそう。サンプルコードもそんな感じ。
nslookupは微妙?
公式のサンプルコードを抜粋する。
initContainers: - name: init-myservice image: busybox:1.28 command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;
nslookupで名前解決できるまで走り続ける。つまり名前解決できた時点でInitContainerは終了して、containersで定義されているものが実行される。
これを使って、DBのポッドが起動した後に、そこに接続するアプリを含んだポッドを定義して試してみた。が、上手くいかない。
おそらく、DB起動コマンドが実行された瞬間にnslookupが成功していて、DBが正常に起動する前にDB接続をトライして失敗してるっぽい。
netcatでやってみる
少し修正し、netcatでポート指定。MySQLなので3306。
initContainers: - name: init-myservice image: busybox:1.28 command: ['sh', '-c', 'until nc -z myservice 3306; do echo waiting for myservice; sleep 2; done;
これだと想定通り、DBがしっかり起動してからアプリのPodが起動し、DB接続も成功した。
まとめ
- KubernetesでPod間に依存関係は作れる
- 公式ページで紹介されている方法だと上手くいかないユースケースもある