これは何
今までdocker stackを利用しており、ブランチ毎の最新のコードをそれぞれの環境にブランチ毎のコンテナイメージタグを付けてデプロイするという運用をしていました。
Kubernetesに移行した際に同じような運用を行おうとした時にハマりどころがあり、その解決方法について書きたいと思います。
前提
Kubernetesではlatestタグイメージの運用は適切なロールバックを行うことが難しいので推奨されていません。
できる限りVersion、もしくはdigest値でのイメージ指定を行いましょう。
latest指定の問題点
通常、違うイメージタグを指定するのであれば公式に書いてあるような、kubectl set imageやkubectl rolling-updateでコンテナイメージの更新を行うことができます。
しかし、同じイメージタグの最新イメージを更新しようとするときは上記の操作では更新されません。
imagePullPolicy: Alwaysを設定すれば更新してくれるかと思いましたが、この設定値はpodが起動するときのポリシーの設定です。
よって、podが起動するときにコンテナイメージリポジトリからlatestがついているコンテナイメージをPullするような動作になります。
解決方法
podを手動で削除する方法
podを手動で削除すると、Deploymentは新規にpodを作成するので、その際にコンテナイメージリポジトリからlatestがついている最新イメージをPullしてきます。しかしながら、手動でpodを削除すると勿論通信障害が発生するのでありえません。
DeploymentのPodTemplate(.spec.template)を書き換える方法
DeploymentのPodTemplateの変更は、rolloutのトリガーとなっているので、新しいpodへのアップデートが自動的に行われます。
新しいpodが作成される際にimagePullPolicy: Alwaysが動作するので、最新のコンテナイメージをPullしてきてくれます。
PodTemplateを書き換える値はメタデータのラベルでも良いので、実際にイメージを更新する際にはkubectl patchコマンドを利用し、以下のようなコマンドで行うことができます。
kubectl patch -n ${Namespace} deployment ${DeploymentName} \
-p "{\"spec\": {\"template\": {\"metadata\": {\"labels\": {\"date\": \"$(date +'%s')\" }}}}}"
終わりに
パッケージとコンテナイメージは適切なバージョニングを行い、複数の環境毎にバージョン指定を行うと、現在動いている環境からソースコードまでたどり着くことが容易です。可能であれば適切なバージョニングを行うようにしましょう。