リビジョン四つでデプロイの歴史を作る
目標
install、upgrade、失敗、rollbackまで、4つのリビジョンを自分で作ってみて、Helmがその履歴をクラスターのどこに、どんな形で残すのかを確認します。
なぜ重要なのか
Helm 3には、クラスターに常駐するサーバーコンポーネントがありません。では、「このreleaseが今何番目のバージョンなのか」は、どこにあるのでしょうか。releaseがインストールされたネームスペースのSecretにあります。名前はsh.helm.release.v1.<릴리스이름>.v<리비전>(プレースホルダーはrelease名とリビジョンです)で、タイプはhelm.sh/release.v1であり、その中に、チャートのメタデータ・レンダリングされたマニフェスト・values・状態が圧縮されて入っています。リビジョンごとにSecretが1つずつ積み上がるので、デプロイの履歴がクラスター自体に残ります。ここで、必ず体で覚えるべきことが2つあります。1つ目は、失敗したアップグレードもリビジョンとして残ることです。状態がfailedとして記録され、実体は直前の状態のまま守られます。2つ目は、ロールバックは元に戻すことではなく、新しいリビジョンを作ることです。リビジョン2にロールバックすると、番号が2に戻るのではなく、リビジョン4が新しくできます。リビジョンは常に前にだけ進みます。
ステップ
/root/helm/rel/lab-appにチャートを1つ作成し(helm create lab-appで十分です)、ネームスペースhelm-labにrelease名lab-appでインストールしてください:helm install lab-app /root/helm/rel/lab-app -n helm-lab --create-namespace --set replicaCount=1。これがリビジョン1です。helm-labに、app.kubernetes.io/managed-by=Helmラベルが付いたDeploymentが1つできている必要があります。出力物のディレクトリ/root/helm/rel/outも、あらかじめ作っておいてください。helm upgrade lab-app /root/helm/rel/lab-app -n helm-lab --set replicaCount=3で、リビジョン2を作成してください。そのあと、そのリビジョンに適用されたユーザー値を/root/helm/rel/out/rev2-values.jsonに保存してください(helm get values lab-app -n helm-lab --revision 2 -o json)。ファイルは正しいJSONで、replicaCountが3である必要があります。helm history lab-app -n helm-lab -o json > /root/helm/rel/out/history.jsonで履歴を保存してください。リビジョンが2つ以上あり、各項目にchart・app_version・statusフィールドがあり、状態がsupersededのリビジョンが最低1つある必要があります。- レンダリングはできるのに、APIサーバーが拒否するアップグレードを、わざと1回行ってください:
helm upgrade lab-app /root/helm/rel/lab-app -n helm-lab --set replicaCount=abc。replicasは整数でなければならないので、マニフェストが拒否されます。標準エラー出力も含めて、出力を/root/helm/rel/out/failed.txtに保存してください(> /root/helm/rel/out/failed.txt 2>&1)。これがリビジョン3で、状態はfailedとして残り、実際のDeploymentのspec.replicasは3のままである必要があります。--atomicは付けないでください。付けると自動でロールバックされて、失敗したリビジョンを観察できません。 helm rollback lab-app 2 -n helm-labで、リビジョン2の状態に戻してください。これがリビジョン4です。履歴の最新のリビジョン番号が4以上で、そのリビジョンの説明にrollbackが入り、状態はdeployed、実際のDeploymentのspec.replicasは3である必要があります。helm get values lab-app -n helm-lab -a -o json > /root/helm/rel/out/all-values.jsonとhelm get values lab-app -n helm-lab -o json > /root/helm/rel/out/user-values.jsonを、それぞれ保存してください。全体の値のファイルには、最上位のキーが3つ以上あり、imageが含まれている必要があり、ユーザー値のファイルのキーの数は、それより少ない必要があります。kubectl get secret -n helm-lab -l owner=helmで、releaseのSecretを確認してください。リビジョンの数の分(4つ以上)あり、タイプはhelm.sh/release.v1、名前はsh.helm.release.v1.lab-app.v<리비전>(プレースホルダーはリビジョンです)の形式である必要があります。確認した内容を/root/helm/rel/out/storage-note.txtに1–2行で書いてください。releaseの状態が、どのネームスペースのどのオブジェクトに保存されるかが入っている必要があります。/root/helm/rel/out/report.jsonを作成してください。キーは4つです。revisionsは、リビジョンごとにrevisionとstatusを入れた配列で、実際の履歴の数と同じである必要があり、statusがfailedの項目が必ず入っている必要があります。current_revisionは現在の最新リビジョン番号、rolled_back_toは2、deployed_replicasは現在のDeploymentのspec.replicasの値です。
参考
- ラボのPodはラボごとに新しく起動するので、ほかのラボで作ったチャートやreleaseは残っていません。チャートもネームスペースも、ここで最初から作ります。チャートがそのまま再現可能なパッケージであるという事実が、ここで現れます。
helm history、helm get values、helm statusは、すべて-nでネームスペースを渡す必要があります。Helmはreleaseをネームスペース単位で記憶します。-a(--all)を付けると、チャートのデフォルト値までマージされた最終的な値が、付けなければ、ユーザーが実際に渡した値だけが出ます。障害対応で「これはデフォルト値か、人が入れた値か」を切り分けるのが、この違いです。- デフォルトの保持リビジョンは10個で、
--history-maxで調整します。Secretが無限に積み上がらない理由です。 - よくある間違い1: ステップ4で
2>&1なしで保存して、ファイルが空になることです。失敗メッセージは標準エラー出力に出ます。 - よくある間違い2: ロールバックするとリビジョン番号が2に戻ると期待することです。ロールバックは、リビジョン2のチャートとvaluesで計算した新しいリビジョンを作ります。
最初のインストールでリビジョン1を作る
/root/helm/rel/lab-appにチャートを1つ作成し(helm create lab-appで十分です)、ネームスペースhelm-labにrelease名lab-appでインストールしてください: helm install lab-app /root/helm/rel/lab-app -n helm-lab --create-namespace --set replicaCount=1。これがリビジョン1です。helm-labに、app.kubernetes.io/managed-by=Helmラベルが付いたDeploymentが1つできている必要があります。出力物のディレクトリ/root/helm/rel/outも、あらかじめ作っておいてください。
releaseはネームスペース単位で記憶されます。存在しないネームスペースにインストールするには、あらかじめ作るか、インストールのオプションで一緒に作れます。レプリカ数は1から始めます。
アップグレードでリビジョン2を作る
helm upgrade lab-app /root/helm/rel/lab-app -n helm-lab --set replicaCount=3で、リビジョン2を作成してください。そのあと、そのリビジョンに適用されたユーザー値を/root/helm/rel/out/rev2-values.jsonに保存してください(helm get values lab-app -n helm-lab --revision 2 -o json)。ファイルは正しいJSONで、replicaCountが3である必要があります。
値を1つだけ変えて再デプロイします。そのあと、そのリビジョンに適用されたユーザー値をJSONで抜き出して保存してください。特定のリビジョンを指定するオプションがあります。
releaseの履歴をJSONで残す
helm history lab-app -n helm-lab -o json > /root/helm/rel/out/history.jsonで履歴を保存してください。リビジョンが2つ以上あり、各項目にchart・app_version・statusフィールドがあり、状態がsupersededのリビジョンが最低1つある必要があります。
履歴には、リビジョンごとに状態とチャートの情報が入っています。新しいリビジョンが上がると、前のリビジョンの状態が何に変わるかを確認してください。
失敗するアップグレードを作る
レンダリングはできるのに、APIサーバーが拒否するアップグレードを、わざと1回行ってください: helm upgrade lab-app /root/helm/rel/lab-app -n helm-lab --set replicaCount=abc。replicasは整数でなければならないので、マニフェストが拒否されます。標準エラー出力も含めて、出力を/root/helm/rel/out/failed.txtに保存してください(> /root/helm/rel/out/failed.txt 2>&1)。これがリビジョン3で、状態はfailedとして残り、実際のDeploymentのspec.replicasは3のままである必要があります。--atomicは付けないでください。付けると自動でロールバックされて、失敗したリビジョンを観察できません。
レンダリングはできるのに、APIサーバーが拒否する値を入れればよいです。レプリカ数の場所に、整数でない値を入れてみてください。エラーは標準エラー出力に出るので、保存するときに一緒に受け取る必要があります。
リビジョン2にロールバックする
helm rollback lab-app 2 -n helm-labで、リビジョン2の状態に戻してください。これがリビジョン4です。履歴の最新のリビジョン番号が4以上で、そのリビジョンの説明にrollbackが入り、状態はdeployed、実際のDeploymentのspec.replicasは3である必要があります。
ロールバックは番号を戻すことではなく、新しいリビジョンを作ることです。ロールバックのあと、履歴の最新の番号と、実際にデプロイされたレプリカ数を、一緒に確認してください。
ユーザー値と全体の値を比べる
helm get values lab-app -n helm-lab -a -o json > /root/helm/rel/out/all-values.jsonとhelm get values lab-app -n helm-lab -o json > /root/helm/rel/out/user-values.jsonを、それぞれ保存してください。全体の値のファイルには、最上位のキーが3つ以上あり、imageが含まれている必要があり、ユーザー値のファイルのキーの数は、それより少ない必要があります。
同じコマンドにオプションを1つ追加すると、チャートのデフォルト値までマージされた結果が出ます。2つの結果のキーの数が違っていれば、正常です。
releaseが保存された場所を確認する
kubectl get secret -n helm-lab -l owner=helmで、releaseのSecretを確認してください。リビジョンの数の分(4つ以上)あり、タイプはhelm.sh/release.v1、名前はsh.helm.release.v1.lab-app.v<리비전>(プレースホルダーはリビジョンです)の形式である必要があります。確認した内容を/root/helm/rel/out/storage-note.txtに1–2行で書いてください。releaseの状態が、どのネームスペースのどのオブジェクトに保存されるかが入っている必要があります。
Helm 3には、クラスターの中に常駐するサーバーがありません。では、状態はどこにあるのでしょうか。ラベルで絞り込むと、リビジョンの数だけ見えます。
ライフサイクルのレポートを作る
/root/helm/rel/out/report.jsonを作成してください。キーは4つです。revisionsは、リビジョンごとにrevisionとstatusを入れた配列で、実際の履歴の数と同じである必要があり、statusがfailedの項目が必ず入っている必要があります。current_revisionは現在の最新リビジョン番号、rolled_back_toは2、deployed_replicasは現在のDeploymentのspec.replicasの値です。
履歴と実際のデプロイ状態から、数字を抜き出して、JSONにまとめます。失敗したリビジョンを除いてはいけません。数字は手で書かずに、コマンドの出力から読み取って入れてください。