前提条件:
- Deployment を使ってアプリケーションのデプロイ管理を行っている
tl;dr
PodTemplateSpec の Label か Annotation (.spec.template.metadata.[labels|annotations]
) に適当な key-value を追加・上書きする。
value はタイムスタンプにでもしておくと便利。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: awesome-app
labels:
name: awesome-app
role: web
spec:
minReadySeconds: 30
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 50%
maxUnavailable: 0
replicas: 20
template:
metadata:
name: awesome-app
labels:
name: awesome-app
role: web
annotations:
reloaded-at: "20171217190756" # <========== これ
シェルコマンド一発でやるなら以下。エイリアス作っておくと便利。
# "frontend" Deployment 配下の Pod を全部リロードする
$ kubectl patch deployment frontend -p \
"{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"reloaded-at\":\"`date +'%Y%m%d%H%M%S'`\"}}}}}"
Why
Kubernetes で Pod に設定を注入するには ConfigMap や Secret が主に使われます。
これらの中身は Pod 起動時に Pod へコピーされる仕組みとなっているため、アプリケーション起動中に中身を変更してもそれが即反映されるわけではありません。
Pod を作りなおす必要があります。
じゃあどうするか?
今動いている Pod を消す
Running Pod を消せば、ReplicaSet の設定に基づいて Pod が必要な数だけ再作成されます。
…が、当然ながら相当乱暴なやり方です。
Deployment の仕組みに則ってデプロイする
通常のデプロイだと、kubectl set image
などで PodTemplateSpec にある Docker image tag を更新して新しい Pod をデプロイします。
しかし、Kubernetes では差分のない PodTemplateSpec を再度デプロイすることはできません。
つまり、通常のオペレーションでは同じ Docker image をデプロイすることができません。
What
PodTemplateSpec に差分が発生すれば新しい ReplicaSet が作られて Pod がデプロイされます。
なので Docker image や環境変数以外のアプリケーション動作に影響しない Pod spec、つまり Label や Annotation を編集すればよいのです。
いつリロードしたのかわかりやすいように、注入する値はタイムスタンプにでもしておくとよいでしょう。
Deployment の設定に基づいて Pod の再作成が行われるので、(設定をちゃんとしていれば)パフォーマンス劣化やダウンタイムが発生することもない graceful restart となります。