kubectl apply vs set: リソース更新に適したコマンドの選び方
kubectl apply、set、editを適切に使い分け、KubernetesオブジェクトとGit間の設定ドリフトを防ぐ方法を理解します。
kubectl apply vs set: リソース更新に適したコマンドの選び方
kubectl applyとkubectl setの違いは単なる構文の問題ではありません。宣言された情報源からKubernetesを管理するのか、ライブオブジェクトを直接変更するのかという違いです。どちらも便利ですが、誤った場所で使うと問題を引き起こす可能性があります。
変更をシステムの望ましい状態にすべき場合はkubectl applyを使用します。一時的または緊急の、焦点を絞ったライブ変更が必要な場合はkubectl setを使用します。ライブオブジェクトを対話的に検査・修正する必要がある場合はkubectl editを使用しますが、これがGitからのドリフトを生み出す最も簡単な方法であることを理解しておいてください。
KubernetesオブジェクトはAPIサーバーに保存された望ましい状態を持っています。Deploymentは、いくつのレプリカが存在すべきか、どのイメージを実行すべきか、どのラベルがPodを識別するか、どのリソースが要求されているかなどを指定します。コントローラーは現実をその望ましい状態に一致させるように動作します。更新コマンドは望ましい状態を変更し、コントローラーが残りの処理を行います。
kubectl applyでは、その望ましい状態をYAMLまたはJSONファイルに保持します。ファイルはレビュー、コミット、昇格、ロールバックの対象です。典型的なコマンドはシンプルです:
kubectl apply -f deployment.yaml
オブジェクトが存在しない場合、Kubernetesはそれを作成します。存在する場合、Kubernetesはマニフェストに一致するように更新します。同じファイルを再度適用しても、新しい動作の変更は発生しません。この冪等性が、applyがCI/CDやGitOpsワークフローでうまく機能する理由の一つです。
クライアントサイドのkubectl applyは歴史的に、変更を計算するために最後に適用されたアノテーションを使用していました。--server-sideで有効になるサーバーサイドapplyは、APIサーバーの管理フィールドを通じてフィールドの所有権を追跡します。詳細は異なりますが、運用上の考え方は同じです:宣言された設定が望ましい状態を所有します。
以下は小さなDeploymentマニフェストです:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
ファイル内のイメージを変更してkubectl apply -f deployment.yamlを実行すると、Deploymentが更新されます。ファイルがGitにある場合、変更はレビュー可能です。ロールアウトが壊れた場合、コミットを元に戻すか、デプロイプロセスがリビジョンを記録する方法に応じてKubernetesのロールアウト履歴を使用できます。
kubectl setは異なる動作をします。ライブオブジェクトの特定のフィールドを変更します。一般的な例はコンテナイメージの変更です:
kubectl set image deployment/web nginx=nginx:1.26
このコマンドは高速で読みやすいです。インシデント発生時にはスピードが重要です。現在のイメージが壊れていて、Deploymentを既知の正常なイメージに移行する必要がある場合、kubectl set imageが最も迅速な方法かもしれません。危険性はその後に起こることです。deployment.yamlがまだnginx:1.25を指定している場合、次のkubectl apply -f deployment.yamlでワークロードが1.25に戻る可能性があります。
この不一致が設定ドリフトです。ライブクラスターはあることを示し、ソースファイルは別のことを示します。ドリフトは常に壊滅的ではありませんが、人々がリポジトリを信頼しなくなるためデバッグが難しくなります。誰かが「本番環境で何が動いているのか?」と尋ねたとき、正直な答えは「クラスターを確認してみます」になります。
kubectl setにはいくつかの便利なサブコマンドがあります:
kubectl set image deployment/web nginx=nginx:1.26
kubectl set env deployment/web FEATURE_FLAG=true
kubectl set resources deployment/web -c=nginx --requests=cpu=200m,memory=256Mi --limits=cpu=500m,memory=512Mi
これらは開発クラスター、デモ、短期テスト、およびフォローアップコミットを伴う緊急本番変更に実用的です。これらは維持されるマニフェストの代替ではありません。
kubectl editはライブオブジェクトを取得し、エディターで開き、保存時に変更されたオブジェクトをAPIサーバーに送り返します:
kubectl edit deployment/web
これは便利です。なぜなら、コントローラーによって追加されたフィールドを含む完全なライブYAMLを確認できるからです。また、ライブオブジェクトには手動で管理すべきでない多くのフィールド(status、生成されたメタデータ、リソースバージョン、管理フィールドなど)が含まれているため、リスクもあります。Kubernetesは一部の無効な編集を無視または拒否しますが、すべての悪い編集が構文的に無効であるとは限りません。
kubectl editの一般的な安全な使用法は、迅速な非本番実験です:レプリカの増加、アノテーションの変更、プローブ値のテストなど。一般的な安全でない使用法は、毎週本番Deploymentを手動編集し、マニフェストを決して更新しないことです。これにより、誰も自信を持って再構築できないクラスターが生まれます。
実用的なルールは次のとおりです:変更を次のデプロイ後も持続させたい場合は、マニフェストに入れてapplyを使用します。ライブオブジェクトに一時的な変更を加えるだけでよい場合は、setまたはeditを使用し、その後変更を元に戻すかGitにバックポートします。
命令型コマンドが許容されるだけでなく役立つケースがいくつかあります。デバッグ中に、ログの詳細度を上げる環境変数を一時的に追加することがあります:
kubectl set env deployment/api LOG_LEVEL=debug
ログを収集した後、削除します:
kubectl set env deployment/api LOG_LEVEL-
デバッグ設定を永続的にする必要がある場合は、代わりにマニフェストにコミットします。記憶に頼らないでください。
もう一つのケースは緊急ロールバックです。デプロイパイプラインが停止し、顧客に影響がある場合、イメージを直接設定することは合理的かもしれません:
kubectl set image deployment/api api=registry.example.com/api:2026-05-23-good
kubectl rollout status deployment/api
フォローアップはすぐに行うべきです:宣言されたマニフェストを緊急状態に一致させるプルリクエストまたはコミットを開くか、パイプラインが正常に戻ったら通常のロールバックプロセスを実行します。ライブ修正は時間を稼ぐものです。新しい文書化されていないデプロイ方法になるべきではありません。
kubectl applyにも落とし穴があります。同じフィールドを管理する複数のツールを混在させると、競合や驚くべき上書きが発生する可能性があります。例えば、GitOpsコントローラー、Helm、および人間が同じDeploymentに対してkubectl applyを実行すると、全員がオブジェクトの一部を所有していると信じる可能性があります。明確な所有権を選択してください。Helmがリソースを管理している場合は、Helmの値を更新し、Helmリリースプロセスを実行します。Argo CDまたはFluxが管理している場合は、Gitを変更し、コントローラーに調整させます。
シークレットと設定については特に注意してください。kubectl set envはDeploymentに迅速な変更を加えることができますが、シェル履歴や監査ログに値を露出させる可能性があります。機密性の高い値については、通常のシークレット管理プロセスを通じてSecretを更新してください。チームが明示的にそのワークフローを受け入れていない限り、本番認証情報をアドホックコマンドに貼り付けないでください。
ライブオブジェクトを変更する前に、それを検査します:
kubectl get deployment web -o yaml
kubectl diff -f deployment.yaml
kubectl diffは過小評価されています。変更を加える前に、applyが何を変更するかを表示します。本番環境では、このプレビューにより、ラベルセレクターの誤った削除、リソース制限の削除、間違った環境のマニフェストの適用などのミスを防ぐことができます。
サーバーサイドapplyの場合、コマンドは次のようになります:
kubectl apply --server-side -f deployment.yaml
サーバーサイドapplyは、複数のアクターが異なるフィールドを管理する場合に役立ちますが、所有権の規律の必要性を排除するものではありません。2つのマネージャーが同じフィールドを所有しようとすると、Kubernetesは競合を報告する可能性があります。これは機能であり、ワークフローがあいまいであることを示しています。
以下は、実際のクラスターで使用している簡単な判断ガイドです。新しいアプリケーションリリース?マニフェストを変更し、パイプラインを通じてapplyを使用します。ステージングで負荷テストのためにレプリカを増やす?元に戻すのであれば、kubectl scaleまたはkubectl setで問題ありません。本番で壊れたイメージをホットフィックス?kubectl set imageは許容されますが、すぐに情報源の変更を作成します。CPU要求を恒久的に調整?マニフェストを更新します。リソースにどのフィールドが存在するか探索?editに頼る前にkubectl get -o yamlを使用します。
チームがこれを正しく行うと、Kubernetesは推論しやすくなります。リポジトリが物語を語ります。クラスターはほとんどの場合リポジトリと一致します。一時的なライブ変更は一時的としてラベル付けされ、クリーンアップされます。インシデントは依然としてストレスフルですが、設定が第二の謎になることはありません。
コマンド自体が重要なのではありません。重要なのは、明日、信頼できるファイルからクラスター状態を再構築できるかどうかです。kubectl applyはその習慣をサポートします。kubectl setとkubectl editは、直接行動が有用な瞬間のための鋭いツールです。その境界を明確に保つことで、多くの回避可能なKubernetesの混乱を避けることができます。
同じ精神的なカテゴリーに入れられる別のコマンドがあります:kubectl patchです。これも命令型ですが、editよりも正確なスクリプト化された変更に適しています。例えば、Deploymentアノテーションをパッチして再起動をトリガーしたり、自動化で小さなフィールドを更新したりできます。同じドリフトルールが適用されます。パッチされたフィールドが長期的な望ましい状態を表す場合は、ソースマニフェストも更新してください。
kubectl patch deployment web -p '{"spec":{"template":{"metadata":{"annotations":{"restartedAt":"2026-05-24T10:00:00Z"}}}}}'
再起動には、目的に特化したコマンドを優先します:
kubectl rollout restart deployment/web
このコマンドもライブオブジェクトを変更しますが、その意図は明確です:現在のPodテンプレートから新しいロールアウトを開始します。Gitでの設定変更の代替ではありません。
GitOps環境では、境界はさらに厳格です。Argo CDまたはFluxがオブジェクトを所有している場合、手動のkubectl set imageは、コントローラーがドリフトを検出してGitに調整するため、自動的に元に戻される可能性があります。これはインシデント中に驚くべきことです。手動の本番変更を行う前に、GitOpsコントローラーが対抗するかどうかを把握してください。時には、適切な緊急対応は、そのアプリケーションの調整を一時停止し、修正を行い、一致するGit変更をコミットして調整を再開することです。
また、生成されたフィールドを盲目的にコミットせずにライブの差分をキャプチャする方法を知っておくべきです。kubectl get deployment web -o yamlには、クリーンなマニフェストに含めるべきでないstatus、リソースバージョン、管理フィールド、その他のデータが含まれています。ホットフィックスをバックポートする必要がある場合は、ソースマニフェストを手動で編集するか、KustomizeやHelm valuesなどのツールを使用し、kubectl diffを実行して意図した変更を確認します。注意深くクリーニングしない限り、ソースファイルを生のライブYAMLで置き換えないでください。
チームにとって、最も健全なポリシーは通常、短く明示的です。本番変更はGitを通じて行われます。緊急のライブ変更は必要な場合に許可されますが、フォローアップのソース変更またはロールバックが必要です。開発クラスターはより緩やかですが、開発を超えて昇格されるものはすべて宣言されなければなりません。このポリシーは、禁止コマンドの長いリストよりも従いやすいです。
これには人間的な側面もあります。障害発生時、クラスターアクセスを持つ人は可能な限り迅速な修正を行うかもしれません。チームがそれを緊急例外として扱う限り問題ありません。それらの例外が通常の運用になると危険です。本番が定期的に手動で修正されている場合、デプロイプロセスが遅すぎる、脆弱すぎる、または信頼されていない可能性があります。より多くのライブ編集テクニックを教えるのではなく、そのプロセスを修正してください。
RBACはワークフローを強化できます。多くのチームは開発では広範なkubectlアクセスを許可しますが、本番書き込みはCI/CDシステム、GitOpsコントローラー、または小規模なオンコールグループに制限します。これは官僚主義のためだけではありません。望ましい状態を変更できるパスを減らします。何かが変更されたとき、監査ログとGit履歴を追跡しやすくなります。
学習のために、使い捨ての名前空間で3つのコマンドすべてを練習する価値はあります。applyでDeploymentを作成し、setでイメージを変更し、kubectl diffでドリフトを検査し、マニフェストを更新して再度適用します。安全な環境で一度ドリフトを経験すると、本番ルールを覚えやすくなります。