kubectl apply vs set: リソース更新のための適切なコマンドの選択
主要なコンテナオーケストレーションプラットフォームであるKubernetesは、アプリケーションのライフサイクルを管理するための強力なツールを提供しています。この管理の核となる側面は、Deployment、Service、ConfigMapなどの既存リソースの更新です。kubectlはこの目的に対していくつかのコマンドを提供していますが、kubectl applyと、kubectl set/kubectl edit群のコマンドは、宣言的(declarative)な更新と命令的(imperative)な更新という、根本的に異なる2つの哲学を表しています。
それぞれのアプローチをいつ、どのように使用するかを理解することは、安定的で信頼性が高く、監査可能なKubernetesデプロイメントを維持するために不可欠です。これらのコマンドを誤って使用すると、設定の乖離(configuration drift)、デバッグの困難さ、運用上の不整合につながる可能性があります。本記事では、kubectl apply、kubectl set、およびkubectl editの機微を掘り下げ、リソース更新戦略について情報に基づいた意思決定を行うための知識を提供します。
中核となる課題:リソース状態の管理
Kubernetesでは、稼働中のPodからネットワークServiceに至るまで、すべてのコンポーネントがAPIオブジェクトとして表現されます。これらのオブジェクトには、YAMLまたはJSONマニフェストファイルで定義する「望ましい状態(desired state)」と、クラスター内の現在の実態を反映する「観測された状態(observed state)」があります。kubectlの更新コマンドの主な目標は、これら2つの状態を調和させることですが、その調和の方法は大きく異なります。
kubectl applyの理解:宣言的アプローチ
kubectl applyは、Kubernetesにおける宣言的リソース管理の基礎となるものです。このアプローチでは、リソースの望ましい状態をローカルの設定ファイル(またはファイルのディレクトリ)で定義し、Kubernetesにクラスターの状態をその定義に一致させるように指示します。
kubectl applyの仕組み(3者間マージ)
kubectl apply -f your-manifest.yamlを実行すると、Kubernetesは高度な3者間マージ(three-way merge)を実行します。
- 最終適用設定(Last Applied Configuration):
kubectl applyを使用して最後に適用されたリソースの状態。この状態は、ライブオブジェクトのアノテーション(kubectl.kubernetes.io/last-applied-configuration)に保存されます。 - ライブ設定(Live Configuration): Kubernetes APIサーバー内のリソースの現在の状態。
- 新規設定(New Configuration):
your-manifest.yamlファイルで定義された状態。
マージアルゴリズムは、これら3つのバージョンを比較して、どのような変更が必要かを決定します。それはインテリジェントに競合を処理し、新しい設定からの変更を優先しつつ、前回のapply以降に命令的に修正されたフィールド(これについては後述するように問題を引き起こす可能性があります)を尊重します。
このプロセスにより冪等性(idempotency)が保証されます。つまり、同じマニフェストを複数回適用しても、他の変更が発生していない限り、意図しない副作用なしに同じクラスター状態になります。
実践例:Deploymentの適用
deployment.yamlファイルがあるとします。
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-webapp
labels:
app: my-webapp
spec:
replicas: 3
selector:
matchLabels:
app: my-webapp
template:
metadata:
labels:
app: my-webapp
spec:
containers:
- name: webapp-container
image: nginx:1.21.0
ports:
- containerPort: 80
このDeploymentを作成または更新するには、以下を実行します。
kubectl apply -f deployment.yaml
後でdeployment.yaml内のimageをnginx:1.22.0に変更して再度kubectl applyを実行すると、Kubernetesは他の設定を維持しつつ、新しいイメージを使用するようにDeploymentを更新します。
kubectl applyの利点
- 信頼できる唯一の情報源(Source of Truth): 設定ファイルが、クラスターの望ましい状態に対する信頼できる唯一の情報源となります。これはGitOpsの原則とよく合致します。
- 監査可能性とバージョン管理: 変更はバージョン管理システム(例:Git)で追跡され、明確な監査証跡と容易なロールバックを提供します。
- 一貫性: 環境間(開発、ステージング、本番)での一貫性を保証します。
- 冪等性:
apply操作を繰り返しても同じ効果が得られ、意図しない変更を防ぎます。 - 複雑な更新: 複数のリソースタイプが関わる複雑な更新や、多くのフィールドにわたる大幅な変更を処理します。
kubectl applyを使用すべき時
- すべてのリソース作成および更新の主要な方法として。
- CI/CDパイプラインを介してアプリケーションをデプロイする場合。
- コードとしてのインフラストラクチャ(Infrastructure-as-code)を管理する場合。
- チームで作業し、一貫した設定を確保する場合。
kubectl applyに関するヒントと注意点
- マニフェストファイルを常に望ましい状態に保つこと。マニフェストファイルに反映されていない
kubectl setやkubectl editによる変更は、次回のapply時に上書きされるか、マージの競合を引き起こします。 - フィールドマネージャー: Kubernetes 1.16以降で導入されたサーバーサイド適用(Server-Side Apply: SSA)は、リソース内の各フィールドを担当する「フィールドマネージャー」(例:
kubectl、コントローラー)を追跡します。これにより、複数のソースが同じリソースを変更する際の競合を防ぐのに役立ちます。強力ですが、異なるツールがフィールド管理とどのように連携するかを認識しておく必要があります。
kubectl setとkubectl editの理解:命令的アプローチ
kubectl setとkubectl editは、命令型(imperative)コマンド群に属します。ファイル内で望ましい状態を定義するのではなく、特定の操作を実行したり、クラスター内のライブオブジェクトを直接変更したりするようKubernetesに指示します。これらのコマンドは、迅速なアドホックな変更には優れていますが、特定の注意点があります。
kubectl set:集中的な命令的修正
kubectl setは、マニフェストファイルに触れることなく、リソースに対する特定で一般的な修正を行うために設計されています。特定のフィールドを変更するためのいくつかのサブコマンドを提供しています。
kubectl setの仕組み
kubectl setは、提供されたコマンドライン引数に基づいて、Kubernetes APIサーバー内のライブオブジェクトを直接変更します。ローカルのマニフェストファイルとは連携せず、last-applied-configurationアノテーションも更新しません。
実践例:イメージの設定
my-webappという名前のDeployment内のコンテナのイメージを更新するには:
kubeclt set image deployment/my-webapp webapp-container=nginx:1.22.0
このコマンドは、my-webapp Deployment内のwebapp-containerのimageフィールドを直接変更します。もし以前にmy-webappをkubectl applyで管理していた場合、この変更により、ローカルのdeployment.yamlとライブクラスターの状態との間に「乖離(drift)」が生じます。
他の一般的なkubectl setコマンド:
kubectl set resources: リソースの要求/制限を設定するため。kubectl set env: 環境変数を追加または更新するため。kubectl set selector: リソースのセレクターを変更するため。
kubectl edit:対話的な命令的修正
kubectl editを使用すると、設定されたデフォルトのテキストエディタ(例:vi、nano)を使用して、クラスター内のライブリソースオブジェクトの任意のフィールドを直接修正できます。
kubectl editの仕組み
kubectl edit <resource-type>/<resource-name>を実行すると:
kubectlは、APIサーバーからライブリソースの現在のYAML定義を取得します。- それをローカルのテキストエディタで開きます。
- 目的の変更を行い、ファイルを保存します。
- その後、
kubectlは修正された定義をAPIサーバーに送り返し、APIサーバーが変更を適用しようと試みます。構文エラーや無効なフィールドがある場合、変更は拒否されます。
kubectl setと同様に、kubectl editもライブオブジェクトに対して直接操作を行い、ローカルのマニフェストファイルやlast-applied-configurationアノテーションを更新しません。
実践例:Editing a Deployment
エディタでmy-webapp Deploymentを開くには:
kubeclt edit deployment/my-webapp
エディタはライブDeploymentのYAML表現で開きます。そこで、replicasやimageのようなフィールドを変更したり、新しいアノテーションやラベルを追加したりできます。エディタを保存して閉じると、kubectlがそれらの変更を適用しようと試みます。
kubectl setとkubectl editの利点
- 速度: 開発環境での迅速な一時的な修正やデバッグに優れています。
- 柔軟性: リソースの任意のフィールドを直接修正できます(
editを使用)。 - アドホックな変更: マニフェストファイルがすぐに入手できない場合や、些細な変更のために作成したくない場合に役立ちます。
kubectl set/kubectl editを使用すべき時
- 開発クラスターでのデバッグ: 一時的にレプリカ数を増やしたり、修正をテストするためにイメージを変更したりする場合。
- 非本番環境での小さく、重要ではない、一時的な変更。
- リソース定義の調査:
kubectl editは、リソースの完全なライブYAMLを確認する便利な方法です。
kubectl setとkubectl editに関する警告
- 設定の乖離(Configuration Drift):
setまたはeditで行われた変更は、ローカルのマニフェストファイルには反映されません。マニフェストからの次回のkubectl applyは、これらの命令的な変更を上書きするか、競合を引き起こします。 - 監査可能性の欠如: これらの変更はバージョン管理で追跡されないため、誰が、いつ、何を変更したのかを知ることが難しくなり、デバッグやコンプライアンスを妨げます。
- 非冪等性: 初期状態が不明な場合、同じ命令的な変更を繰り返すと予期せぬ動作につながる可能性があります。
- エラーのリスク: 手動編集(特に
editを使用)は、構文エラーや無効な設定を導入する可能性を高めます。
主な違い:kubectl apply vs. kubectl set/kubectl edit
中核となる違いを要約します。
| 機能 | kubectl apply(宣言的) |
kubectl set/kubectl edit(命令的) |
|---|---|---|
| アプローチ | ファイルで望ましい状態を定義し、Kubernetesが調和させる。 | ライブオブジェクトまたは特定のフィールドを直接操作する。 |
| 信頼できる情報源 | ローカル構成ファイル(例:Gitリポジトリ)。 | ライブクラスターオブジェクト自体(一時的)。 |
| 冪等性 | はい、同じファイルを適用すると同じ結果が得られます。 | いいえ、本質的には違います。各コマンドは明示的なアクションです。 |
| 監査可能性 | 高い(変更はGit、last-applied-configurationで追跡)。 |
低い(バージョン管理なし、変更はクラスター上で即時)。 |
| 競合管理 | 3者間マージ、last-applied-configurationアノテーションを使用。 |
直接上書き(setの場合)または対話的にマージ(editの場合)。 |
| ユースケース | 本番デプロイメント、CI/CD、GitOps、チームコラボレーション。 | クイックフィックス、デバッグ、非本番環境でのアドホックな変更。 |
| 乖離のリスク | 低い、ファイルが最新に保たれている限り。 | 高い、ソースファイルからの設定の乖離を引き起こす可能性が非常に高い。 |
適切なコマンドの選択:ベストプラクティス
本番環境および共同作業を行うチームにとって、選択は明確です。
- Kubernetesリソースの管理には、常に
kubectl apply(またはArgo CDやFlux CDなどのそれに基づいたGitOpsツール)を優先してください。 これにより、クラスターの状態がバージョン管理され、監査可能で一貫性が保たれます。 - Kubernetesマニフェストファイルを信頼できる唯一の情報源として扱ってください。 リソース構成へのすべての変更は、理想的にはこれらのファイルから発生し、バージョン管理にコミットされるべきです。
kubectl setやkubectl editのような命令型コマンドは、以下の目的のためにとっておかれるべきです。
- 開発/ステージングクラスターでの一時的なデバッグまたはテスト。使用する場合は、変更を元に戻すか、新しい状態を反映するためにソースマニフェストファイルを直ちに更新するようにしてください。
- 望ましい長期的な状態を表さない、一度きりの一時的な操作(例:デプロイメントを短時間一時停止すること)。
ハイブリッドアプローチ(注意して使用)
いくつかのシナリオでは、本番環境で何かを迅速にホットフィックスする必要に迫られるかもしれません。一般的には推奨されませんが、kubectl editを使用しなければならない場合は:
- 設定の乖離がもたらす影響を理解してください。
kubectl get <resource> -o yaml > new-manifest.yamlを実行して、変更を直ちにキャプチャしてください。- これらの変更を、できるだけ早くバージョン管理されたマニフェストファイルに統合し直してください。
警告: ソースマニフェストを更新せずに本番環境で定期的にkubectl editまたはkubectl setを使用すると、実際の構成がチームがそうあるべきと考えているものから大きく逸脱し、管理不能で回復不能なクラスター状態につながります。
結論
kubectl apply、kubectl set、およびkubectl editはすべて、Kubernetesクラスターとやり取りするための強力なツールです。しかし、それぞれ異なる目的を果たし、リソース管理の明確な哲学を体現しています。kubectl applyの宣言的な性質と、kubectl setおよびkubectl editの命令的な性質を理解することで、より安定的で信頼性が高く、保守性の高いKubernetesデプロイメントにつながるベストプラクティスを採用できます。
ほぼすべての永続的なリソース管理、特に本番環境では、kubectl applyを採用し、設定ファイルをバージョン管理してください。命令型コマンドは、一時的なアドホックなトラブルシューティングのために予約し、重要な変更は必ず宣言的マニフェストに迅速に反映させるようにしてください。この規律は、Kubernetes環境内でのスムーズな運用とシームレスなコラボレーションにとって非常に貴重なものとなるでしょう。