更新をリソース枠内に収める

KubernetesBeginner
オンラインで実践に進む

はじめに

Aster Supply は通常のカタログを提供していますが、冬の更新が進まない状態です。名前空間には、通常運用に必要な CPU リクエスト分の余裕はありますが、ローリングアップデート中に要求される追加 Pod の分はありません。固定の割り当て内に収まるロールアウトの許容値を選び、参照用ショップを稼働させたまま、更新したカタログを引き渡します。

基本的なターミナルのパス、簡単な YAML、Pod、Deployment、Service、ラベルを理解していることを前提とします。この実験では、CPU リクエストの単位、ResourceQuota、更新時の許容値の計算を説明します。実際の単一ノードクラスター、アプリケーション、ヘルスチェック、カタログデータは準備済みです。クラスターのインストール、イメージのビルド、アプリケーションのプログラミングは不要です。所要時間には読む時間と通常の操作ミスへの対応を含みますが、作者による見積もりです。

更新を固定のリソース枠に収める

このステップでは、CPU の割り当てを増やしたり、参照用ショップを停止したりせずに、Aster Supply の冬のカタログ更新を完了します。

Shop タブには動作中のカタログが表示されます。Stoneware tray を開いて価格を確認し、Back to collection で戻ります。現在の Everyday essentials コレクションには商品が 3 つあります。要求された The winter edit では Amber cup が追加され、価格が変わります。Reference タブを開きます。Fern Stationery は別の保護対象サービスであり、既存のカタログを維持する必要があります。その Deployment、Service、元の Pod を変更しないでください。その後、Workspace タブに切り替えます。

準備済みのクラスターは、実際の単一ノード Kubernetes です。名前空間は、このコースのリソースをまとめます。ResourceQuota は、その名前空間で受け入れるリソースの合計を制限します。ここで対象にするのは CPU requests だけです。これはスケジューリングのために予約される CPU であり、支出枠や実測 CPU 使用量の上限ではありません。1000m は CPU 1 コア、40m は 0.04 コアを意味します。メモリは準備済みで、この課題のクォータ上のボトルネックではありません。

最初にクォータを読みます。--context=labex-v135 は準備済みのクラスターを選び、-n shop-quota はこのコースの名前空間を選びます。describe はオブジェクトの詳細を表示します。

kubectl --context=labex-v135 -n shop-quota describe resourcequota shop-budget

requests.cpu に Used 140m と Hard 140m が表示されるはずです。これは予約済み CPU であり、現在の使用率ではありません。元のショップはまだ利用できますが、試行中の更新には別の Pod が必要です。利用可能なレプリカとは、readiness チェックに合格し、用意された最小 Ready 期間の 3 秒を経過したものです。Pod を作成しただけでは利用可能にはなりません。Deployment とその ReplicaSet を読みます。ReplicaSet は 1 つの Deployment テンプレートに対応する Pod を維持します。rs は、そのリソース名の短縮形です。

kubectl --context=labex-v135 -n shop-quota get deployments,rs,pods

利用可能なショップのレプリカが 3 つ、参照用のレプリカが 1 つあります。ショップの新しい ReplicaSet は、Pod を作成できません。ショップの両方の ReplicaSet を詳しく表示します。-l app=shop は、それらのラベルを選択します。

kubectl --context=labex-v135 -n shop-quota describe rs -l app=shop

FailedCreate または ReplicaFailure とともに、exceeded quota: shop-budget、requested: requests.cpu=40m、used: requests.cpu=140m、limited: requests.cpu=140m を探してください。これはアドミッション時の拒否であり、その新しい Pod は作成されていません。すでに存在する Pending Pod をスケジューラーが配置できない場合とは異なります。クォータを変更したり、参照用ワークロードを削除したりしてはいけません。

承認済みの新しいカタログと候補マニフェストは、すでに用意されています。ワークスペースに明示的に移動します。pwd は現在のディレクトリを表示し、ls はその中の項目を一覧表示します。

cd /home/labex/project/shop-update
pwd
ls

approved、starter、tools が表示されるはずです。cat は承認済みのカタログを表示します。

cat approved/catalogue.json

sed -n '1,180p' で候補全体を読みます。-n は通常の出力を抑制し、p は 1 行目から 180 行目までを表示します。引用符で囲まれた範囲は、1 つの引数です。

sed -n '1,180p' starter/shop.yaml

ショップには 3 つのレプリカが必要で、それぞれが 40m を要求します。保護対象の参照用サービスは 20m を要求します。変更してよいのは spec.strategy.rollingUpdate だけです。配布された新しいアプリケーションテンプレート、レプリカ数、リソース、セレクター、ヘルスチェックはそのまま維持する必要があります。

リソース枠の内訳 CPU リクエスト
ショップのレプリカ 3 つ 3 × 40m = 120m
保護対象の参照用サービス 20m
定常状態 140m
更新中にショップの Pod を 1 つ追加 合計 180m:140m を超える

ローリングアップデートは、2 つの値のバランスを取ります。maxSurge は、希望するレプリカ数を超える追加 Pod を許可します。maxUnavailable は、希望するレプリカの一部が利用不可になることを許可します。ここでの要件は、観測対象の更新中に少なくとも 2 つのショップレプリカが利用可能であることです。希望するレプリカが 3 つなので、一時的に 1 つが利用不可になっても構いませんが、追加 Pod の余裕はありません。maxSurge: 0 と maxUnavailable: 1 を選びます。両方をゼロにはできません。Recreate、Deployment の削除、リクエスト量の削減、希望数のスケールダウン、クォータの引き上げは、この課題の範囲外です。

編集可能なリリースディレクトリを作成し、用意された候補をコピーします。mkdir はディレクトリを作成し、cp はファイルをコピーします。配布された元ファイルは読み取り専用です。chmod u+w は、コピーに自分のユーザーの書き込み権限を追加します。

mkdir release
cp starter/shop.yaml release/shop.yaml
chmod u+w release/shop.yaml

以前の試行で release がすでに存在する場合は、そのまま残し、編集中のコピーで続けます。パスを打ち間違えた場合は、上の pwd、ls、絶対パスの cd コマンドを使ってから、失敗したコマンドを繰り返してください。パスが見つからなくても、VM をリセットする必要はありません。

sed -i はファイルを直接編集します。各 s/old/new/ 式は、示されたテキストを置き換えます。単一引用符は、空白や句読点をひとまとまりに保ちます。コピー内の 2 つのロールアウト値だけを変更します。

sed -i 's/maxSurge: 1/maxSurge: 0/' release/shop.yaml
sed -i 's/maxUnavailable: 0/maxUnavailable: 1/' release/shop.yaml

適用前に、保存したマニフェストの先頭を読みます。

sed -n '1,35p' release/shop.yaml

replicas: 3、type: "RollingUpdate"、maxSurge: 0、maxUnavailable: 1 が期待されます。apply -f は、このファイルと既存の Deployment の状態を整合させ、Deployment の識別情報を維持します。rollout status は、有限の --timeout を設けて新しいレプリカを待ちます。

kubectl --context=labex-v135 apply -f release/shop.yaml
kubectl --context=labex-v135 -n shop-quota rollout status deployment/shop --timeout=180s

deployment "shop" successfully rolled out が期待されます。コントローラーは、古いレプリカを 1 つ削除し、新しいものを受け入れ、それが利用可能になるのを待ってから続行できます。終了処理中の Pod が短時間はクォータの計上対象に残ることがあるため、一時的に追加の FailedCreate イベントが発生しても自然に復旧する場合があります。クォータを変更する理由にはなりません。ロールアウトの許容値は、終了処理中のあらゆるプロセスの絶対的な上限や、連続稼働を保証するものではありません。

誤った編集で完了できない場合は、保存したファイルを調べ、2 つの戦略値を修正します。失敗した試行や観測期間の条件を満たさない試行から復旧するには、元の承認済みベースラインを再適用し、待ってから、修正したリリースを再試行します。

kubectl --context=labex-v135 apply -f approved/shop.yaml
kubectl --context=labex-v135 -n shop-quota rollout status deployment/shop --timeout=180s

配布された状態確認ツールの --wait-baseline オプションは、新しい試行の前に、古いカタログが最近正常に観測されるまで待ちます。記録された事実を読み取るだけです。

./tools/update-status --wait-baseline
kubectl --context=labex-v135 apply -f release/shop.yaml
kubectl --context=labex-v135 -n shop-quota rollout status deployment/shop --timeout=180s

これらの復旧コマンドは、試行が成功しなかった場合だけ必要です。配布されたベースラインは変更しないでください。読み取り専用の観測プログラムは試行を保持し、ベースラインから更新までを網羅する新しい試行を区別します。復旧しても、以前の証拠は消えません。

最後に、実際のワークロードとクォータをもう一度読みます。

kubectl --context=labex-v135 -n shop-quota get deployments
kubectl --context=labex-v135 -n shop-quota describe resourcequota shop-budget

両方の Deployment が利用可能になっているはずです。ショップは 3/3、参照用は 1/1 です。古い Pod が終了すると、クォータの使用量は 140m に戻り、上限値も同じままです。次のステップでは、利用者が実際に受け取るカタログを確認します。

更新したカタログを引き渡す

このステップでは、新しい顧客体験を調べ、保存済みリリースマニフェストとともに実際のカタログダウンロードを保持します。

Workspace の /home/labex/project/shop-update から始めます。配布された tools/update-status コマンドは、読み取り専用の観測プログラムが記録した、実際の API と HTTP のサンプルを要約します。先頭の ./ は、現在のディレクトリを基準にプログラムを実行します。

./tools/update-status

必要な下限、サンプル数、サンプル中の利用可能なレプリカ数の最小値、最新の更新状態を報告します。最小値は少なくとも 2、完了時には更新済みかつ利用可能なレプリカが 3 つになるはずです。観測プログラムは、約 0.5 秒と API 処理時間ごとにサンプリングし、元のクォータと参照用サービスを確認して、失敗を記録します。この配布された観測プログラムは動かしたままにしてください。サンプル間に何が起きたかを証明したり、本番環境での連続稼働を保証したり、クラスターを修復したりするものではありません。ロールアウト完了直後のチェックでは、完了したサンプルが 2 つそろうまで少し待つ必要がある場合があります。試行中に必要な下限を破ったり、長い観測の空白が生じたりした場合は、修正した試行の前に、前のステップで学んだベースライン復旧を使ってください。

Shop に切り替えてページを再読み込みします。The winter edit、4 つの商品、Stoneware tray $20.00、Linen cloth $14.00、Bud vase $24.00、Amber cup $16.00 が期待されます。Amber cup を開き、価格と Available in store の状態を確認してから、Back to collection で戻ります。これはカタログであり、オンライン購入手続きはありません。

完成したコレクションには、実際の商品カードが 4 つあります。コレクションの見出しと価格を、この稼働例と比較してください。

更新した Aster Supply コレクション

Download catalogue を使います。ブラウザーがダウンロードした catalogue.csv を開いてください。4 行の内容が、サイトのコレクション、商品名、セント単位の価格、提供状況と一致しているはずです。ブラウザーのダウンロードとターミナルのワークスペースは、異なる場所です。次に、引き渡しのため、同じ実際の Service のダウンロードをワークスペースに保存します。

Workspace に戻ります。curl は URL を取得します。--fail は HTTP エラーを報告し、--silent --show-error はエラーを残して進捗表示を隠します。--output は、応答のバイト列を指定したファイルに書き込みます。127.0.0.1:8081 は、元のショップ Service に転送する、準備済みのローカル入口です。

curl --fail --silent --show-error http://127.0.0.1:8081/catalogue.csv --output catalogue.csv
cat catalogue.csv

期待される内容:

id,name,price_cents,available,collection
stone-tray,Stoneware tray,2000,true,The winter edit
linen-cloth,Linen cloth,1400,true,The winter edit
bud-vase,Bud vase,2400,true,The winter edit
amber-cup,Amber cup,1600,true,The winter edit

接続エラーは、ローカル入口に到達できなかったことを意味します。HTTP エラーは、サーバーからの応答です。学んだワークロードとロールアウトのコマンドに戻り、現在の状態を調べてください。静的ファイルを代わりに使ったり、準備済みの転送サービスを変更したりしてはいけません。ダウンロードが不完全だったり、誤って上書きしたりした場合は、正しいカタログが利用可能になってから、同じ curl コマンドを繰り返します。

Reference をもう一度開き、再読み込みします。Fern Stationery は、引き続き Desk essentials、Field notebook $9.00、Clay pencil cup $14.00 を表示する必要があります。商品を開いて戻り、実際のリンクが引き続き機能することを確認します。

引き渡すのは release/shop.yaml と実際の catalogue.csv です。その裏付けとなるのは、完全な新リリース、変更されていないクォータ、元の参照用サービス、有効な観測済みの更新試行です。配布された元ファイル、アプリケーション、Service、読み取り専用の観測プログラムを維持してください。

まとめ

実際の ReplicaSet のクォータ拒否を、ローリングアップデート時の一時的なリソース需要と結び付けました。追加 Pod 数と一時的に利用不可にできるレプリカ数の適切な許容値を計算し、割り当てを増やさずに新しいカタログを完成させました。また、保護対象の参照用サービスを維持し、再利用可能なリリースマニフェストとともに実際の CSV を引き渡しました。

CPU リクエストが表すのはリソースの計上であり、実測の使用率や性能の保証ではありません。有限回のネイティブな観測は、このコースの可用性チェックを支えるものですが、本番環境での連続稼働を証明するものではありません。別の名前空間では、戦略を選ぶ前に、割り当ての余裕と利用可能なレプリカ数の下限を両方とも計算し直してください。