kubectl apply と kubectl edit の違い

v1.37 時点(2026年10月21日 確認)

Kubernetes 基本仕様第7回 / 全45回 ・ 第1部 クラスタの仕組み
目次

この記事ではクラスタにあるオブジェクトを更新する 2 つのコマンド kubectl apply と kubectl edit の違いを、図で説明します。それぞれが何をもとに、どこを書き換えるのかがわかります。更新のたびに変わる resourceVersion と、kubectl apply が残す last-applied-configuration(以下、last-applied)の役割もわかります。後半では kind のクラスタで、同じ Deployment を 2 つのコマンドで交互に更新し、この 2 つの値の変化を比べる手順を示します。

マニフェストと宣言的 API を扱った第5回の内容を前提にしています。まだの方は先にこちらをどうぞ。

基本仕様 第5回 マニフェストと宣言的 API の仕組みKubernetes に渡すマニフェストの構造と、望ましい状態を書いて任せる宣言的 API の仕組みを図で説明します。apiVersion・kind・metadata・spec・status の役割と、spec と status を誰が書くのかを押さえ、kind のクラスタで kubectl explain を使い、Pod の spec と status を作成直後と数秒後で比べる手順を紹介します。

以下の図は、kubectl apply と kubectl edit が、kube-apiserver を通して etcd に保存されている同じ Deployment を更新する流れを表しています。

kubectl apply と kubectl edit が Deployment を更新する流れ(kubectl apply は、既定どおり kubectl の側で差分を計算する場合)

kubectl apply は、利用者が手元に置いたマニフェストをもとに、変わった部分だけを計算します。すでにあるオブジェクトを更新するときは、その部分を patch というリクエストで送ります。kubectl edit は、クラスタにある今のオブジェクトを取り出してエディタで開き、利用者が書き換えて保存した内容を送ります。どちらで更新しても、オブジェクトの中身が変わるので、resourceVersion は変わります。last-applied というアノテーションは、kubectl apply が書き換えます。kubectl edit は、--save-config を付けない限り、このアノテーションを変えません。

右の枠は kube-apiserver を表し、中には更新される Deployment と、その注記だけを描いています。kube-apiserver が etcd に書き込む部分と、kubectl が kube-apiserver を呼び出す細かいやり取りは省いています。kubectl apply が比べるために今のオブジェクトを読み取る線も省いています。それぞれの段階は「kubectl apply と kubectl edit の仕組み」で説明します。

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes、kubectl edit | Kubernetes、Kubernetes API Conventions(2026年10月時点の内容)

kubectl apply と kubectl edit とは

kubectl apply は ファイルに書いた設定をリソースに反映するコマンド です。リファレンスによると、リソースがまだ無ければ作ります。第5回で見たとおり、kubectl でオブジェクトを管理する 3 つの方法のうち、宣言的なオブジェクトの設定(Declarative object configuration)にあたります。利用者は作るか更新するかを指定せず、kubectl がオブジェクトごとに判断します。

参考:kubectl apply | Kubernetes、Kubernetes Object Management | Kubernetes

kubectl edit は クラスタにある今のオブジェクトを、エディタで直接書き換えるコマンド です。リファレンスによると、kubectl で取り出せる API のリソースなら、どれでも編集できます。開くエディタは、環境変数 KUBE_EDITOR か EDITOR で指定したものです。どちらも無ければ、Linux では vi、Windows では notepad です。既定では YAML の形式で開きます。

参考:kubectl edit | Kubernetes

公式ドキュメントのうち、命令的なコマンドを使う手順のページでは、kubectl edit は今のオブジェクトを直接更新する方法の 1 つとして挙げられています。説明は「エディタで設定を開き、今のオブジェクトの生の設定を直接編集する」です。同じページは、このやり方では、オブジェクトの構造(スキーマ)をよく理解している必要があるとしています。命令的なコマンドのページに載っているので、3 つの管理の方法で分けると、kubectl edit は命令的なコマンド(Imperative commands)の側です。

参考:Managing Kubernetes Objects Using Imperative Commands | Kubernetes

2 つのコマンドの違いを次の表にまとめます。それぞれの項目は「kubectl apply と kubectl edit の仕組み」で説明します。

項目kubectl applykubectl edit
何をもとに更新するか利用者の手元のマニフェストクラスタにある今のオブジェクト
変更をどこに書くかマニフェスト(ファイル)エディタで開いた一時的な内容
管理の方法(第5回)宣言的なオブジェクトの設定命令的なコマンド
last-applied-configurationマニフェストの中身に書き換える変えない(--save-config を付けたときを除く)
resourceVersion(中身が変わったとき)変わる(中身が変わったとき)変わる
書き手の名前(既定)kubectl-client-side-applykubectl-edit

参考:kubectl apply | Kubernetes、kubectl edit | Kubernetes、Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes、Kubernetes API Conventions(2026年10月時点の内容)

書き手の名前は、フィールドを誰が書き換えたかを見分けるための名前で、公式ドキュメントでは field manager と呼ばれます。表の値は v1.37 時点のリファレンスでの --field-manager の既定値です。どこに記録されるかは「手元で試す」で確かめます。

なぜ kubectl apply と kubectl edit の違いが大事なのか

第5回では設定をマニフェストのファイルに書いておけば、Git などで履歴を残し、反映する前に変更をレビューできると説明しました。kubectl apply で管理しているオブジェクトでは、手元のマニフェストが「こうあってほしい」という記録になります。

参考:Kubernetes Object Management | Kubernetes

kubectl edit は、この記録を経由せずに、クラスタのオブジェクトを直接書き換えます。マニフェストのファイルは変わらないので、ファイルと実際のオブジェクトが食い違います。その食い違いを次の kubectl apply がどう扱うかは、フィールドによって違います。公式ドキュメントの例では、マニフェストに書いていない replicas を kubectl scale(Deployment などの replicas の値を変えて、Pod の数を変えるコマンド)で変えると、その値は次の kubectl apply のあとも残ります。一方で、マニフェストに書いてあるフィールドなら、次の kubectl apply でマニフェストの値に戻ります(理由は「kubectl apply が送る部分を決める仕組み」で説明します)。kubectl edit で直したつもりの値が、あとで誰かが kubectl apply したときに消えることがあるということです。

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

公式ドキュメントは、1 つのオブジェクトは 1 つの管理の方法だけで扱うよう警告しています。同じオブジェクトで方法を混ぜたときの動きは、定められていません(undefined behavior)。kubectl apply で管理しているオブジェクトを変えたいときは、マニフェストを直して kubectl apply するのが、この警告に沿ったやり方です。一方、第5回で見たとおり、公式ドキュメントは命令的なコマンドを、始めるときや一度きりの作業に勧めています。マニフェストで管理していないオブジェクトを手早く直すような場面では、kubectl edit が向いていると考えられます。

参考:Kubernetes Object Management | Kubernetes、Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

もう 1 つ、更新にはほかの書き手とぶつかる問題があります。第5回と第6回で見たとおり、1 つのオブジェクトには、利用者だけでなくコントローラーなども書き込みます。読んでから書き戻すまでのあいだに別の書き手が更新すると、その更新を上書きして消してしまうおそれがあります。これを防ぐのが resourceVersion です(「resourceVersion で変更を見分ける」で説明します)。

参考:Kubernetes API Concepts | Kubernetes

kubectl apply と kubectl edit の仕組み

kubectl apply が送る部分を決める仕組み

kubectl apply でオブジェクトを作ると、kubectl はそのオブジェクトに kubectl.kubernetes.io/last-applied-configuration(last-applied)というアノテーションを付けます。中身は作るのに使ったマニフェストです。第5回で、kubectl apply で作った Pod にこのアノテーションが付くことに触れました。

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

すでにあるオブジェクトに kubectl apply すると、kubectl は patch のリクエストを kube-apiserver に送ります。公式ドキュメントは patch を、オブジェクト全体ではなく特定のフィールドだけを対象にする更新の操作だと説明しています。patch は操作の名前で、HTTP では PATCH というメソッドで送ります。送る内容は、次の 3 つから kubectl が計算します。

材料中身
マニフェスト利用者が今回渡したファイル
今のオブジェクトクラスタに保存されている実際の値(公式ドキュメントでは live configuration)
last-applied前回の kubectl apply で渡したマニフェスト。今のオブジェクトに付いている

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes、Kubernetes API Concepts | Kubernetes

公式ドキュメントによると、last-applied はマニフェストから消したフィールドを見つけるために使います。今のオブジェクトだけでは足りない理由は、明記されていません。同じページの既定値の説明(Default field values の節)と kubectl scale の例から、次のように考えられます。今のオブジェクトには、作るときに書かなかったフィールドに kube-apiserver が入れた既定値や、ほかの書き手が入れた値も入っています。そのため、マニフェストに無いフィールドが今のオブジェクトにあっても、利用者がマニフェストから消したのか、もともと別の書き手が入れたのかは、今のオブジェクトだけでは区別できないと考えられます。前回のマニフェストを last-applied として残しておけば、前回はマニフェストにあったのに今回は無いフィールドを選び出せます。kubectl はそのフィールドを、利用者が消したものとして、今のオブジェクトからも消します。マニフェストにあって、今のオブジェクトと値が違うフィールドは、マニフェストの値にします。最後に last-applied を今回のマニフェストの中身に書き換え、ここまでをまとめて 1 つの patch にして送ります。

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

replicas や image のように、文字列・数値・真偽値を 1 つ持つフィールドの扱いを、公式ドキュメントの表に沿って次の表にまとめます。

マニフェストにあるか今のオブジェクトにあるかlast-applied にあるかkubectl apply がすること
あるある(問わない)マニフェストの値にする
ある無い(問わない)マニフェストの値にする
無い(問わない)ある今のオブジェクトから消す
無い(問わない)無い何もしない。今の値を残す

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

labels や spec のように中にフィールドを持つもの(公式ドキュメントでは map)は、全体を置き換えずに、中のキーごとに同じ考え方で比べます。たとえば metadata.labels に、マニフェストにも last-applied にも無いキーが付いていれば、kubectl apply はそのキーを残します。

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

containers のように項目を並べたもの(list)の扱いは、フィールドごとに決まっています。たとえば containers は、name が同じ項目どうしを比べます。この回では表の 1 行目と 4 行目、つまり「マニフェストに書いたフィールドはマニフェストの値に戻り、どこにも書いていないフィールドは残る」ことを押さえれば十分です。「なぜ」の節で見た kubectl scale の例で replicas が残ったのは、4 行目にあたるからです。

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

この計算をするのは kubectl です。kubectl のように、API を呼び出す側のプログラムをクライアントと呼びます。クライアントの中で計算するので、公式ドキュメントはこのやり方を client-side apply(クライアント側の apply)と呼びます。v1.37 時点の kubectl apply のリファレンスでは、計算を kube-apiserver に任せる --server-side は、付けたときだけ有効になるフラグです。この回では既定の client-side apply を扱います。server-side apply には「注意点」で短く触れます。

参考:Server-Side Apply | Kubernetes、kubectl apply | Kubernetes

kubectl edit が更新する仕組み

kubectl edit の流れを、v1.37 時点のリファレンスに沿って次の表にまとめます。

順番すること
1指定したオブジェクトを kube-apiserver から取り出す
2取り出した内容を、既定では YAML の形式でエディタに開く
3利用者が書き換えて保存し、エディタを閉じる
4kubectl が変更をクラスタに反映する
5反映でエラーになったら、反映できなかった変更を入れた一時ファイルをディスクに作る

参考:kubectl edit | Kubernetes

kubectl edit は、既定では手順 4 で last-applied を変えません。リファレンスによると、--save-config を付けたときだけ、今のオブジェクトの設定をアノテーションに保存します。付けなければアノテーションはそのままです。--save-config は、そのオブジェクトをあとで kubectl apply で扱いたいときに役立つ、と説明されています。

参考:kubectl edit | Kubernetes

kubectl edit で変えた値は、last-applied にもマニフェストのファイルにも残りません。そのため次の kubectl apply では、さきほどの表のとおりに扱われます。マニフェストに書いてあるフィールドを kubectl edit で変えた場合は、表の 1 行目にあたり、マニフェストの値に戻ります。マニフェストにも last-applied にも無いフィールドを加えた場合は、4 行目にあたり、そのまま残ります。

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

手順 4 で kubectl がどの種類のリクエスト(PUT か PATCH か)を送るかは、リファレンスには明記されていません。リファレンスには、編集したときに patch を出力する --output-patch というフラグがあります。そのため、kubectl は変更を patch の形で作るとうかがえます。

参考:kubectl edit | Kubernetes

resourceVersion で変更を見分ける

第5回で見たとおり、metadata.resourceVersion は Kubernetes が値を入れる読み取り専用のフィールドです。API リファレンスでは、オブジェクトの内部のバージョンを表す値で、クライアントがオブジェクトの変化を知るのに使える、と説明されています。Kubernetes の API の規約(開発者向けの文書)によると、オブジェクトが変わるたびに、サーバーが resourceVersion を変えます。利用者の更新だけでなく、コントローラーが status を書き込んだときもオブジェクトは変わるので、resourceVersion は変わります。たとえば Deployment の status.conditions には、Deployment のコントローラーが状態を書き加えます。

参考:ObjectMeta | Kubernetes API Reference、Kubernetes API Conventions(2026年10月時点の内容)、Deployments | Kubernetes

値は文字列です。API リファレンスと API の規約は、クライアントがこの値を中身のわからないもの(opaque)として扱い、変えずにサーバーへ返すよう求めています。規約は、作りを将来変えることもあるので、実装の細部に頼らないようにとも書いています。v1.37 時点の API Concepts のページは、kube-apiserver が扱うリソースの種類では、同じ種類のオブジェクトどうしなら値を整数として順番を比べられるとしています。ただし、値が 1 ずつ増えるとは書かれていません。この回では値の大きさには頼らず、変わったかどうかだけを見ます。

参考:ObjectMeta | Kubernetes API Reference、Kubernetes API Conventions(2026年10月時点の内容)、Kubernetes API Concepts | Kubernetes

resourceVersion は、ほかの書き手の更新を消してしまう問題を防ぐのにも使われます。API の規約は、Kubernetes が resourceVersion を使って楽観的な並行性制御(optimistic concurrency)を実現していると説明しています。楽観的な並行性制御は、複数の書き手が同時に更新しうるときに、書き込む時点で「読んだあとに誰も変えていないか」を確かめ、変わっていたら書き込みを断るやり方です。規約によると、記録を更新しようとするときに、そのバージョンを前に控えた値と比べ、合わなければ更新は 409(StatusConflict)で失敗します。409 は HTTP の応答に付く結果の番号(ステータスコード)の 1 つで、Conflict(衝突)を表します。

参考:Kubernetes API Conventions(2026年10月時点の内容)

以下の図は、2 つのクライアントが同じオブジェクトを更新するときに、resourceVersion で間に入った更新を見つける流れを表しています。図は API Concepts のページの PUT の説明に沿った例で、kubectl edit のリクエストを表したものではありません。resourceVersion の値も説明のための例で、実際の値は 1 ずつ増えるとは限りません。

resourceVersion で、読んだあとに入った更新を見つけて書き込みを断る流れ(値は例)

クライアント A が読んだときの resourceVersion は 100 でした。そのあとクライアント B が更新したので、値は 101 に変わっています。A が 100 を添えて書き戻すと、kube-apiserver は値が合わないことに気づき、409 Conflict を返します。もし確かめずに受け付けていたら、B の更新は A の書き戻しで消えていました。

API Concepts のページによると、オブジェクト全体を置き換える PUT(第5回)では、クライアントが resourceVersion を添える責任を持ちます。添えた値が古ければ、kube-apiserver は 409 Conflict を返します。規約によると、このときクライアントがオブジェクトを読み直し、変更をあらためて加えてから送り直すのが正しい対応です。一方、patch は今の値によらない変更に向いているとされています。patch でも、更新を消すおそれを確実に防ぎたいときは、resourceVersion を条件に付けられます。

参考:Kubernetes API Concepts | Kubernetes、Kubernetes API Conventions(2026年10月時点の内容)

これを 2 つのコマンドに当てはめます。kubectl apply は違う部分だけを patch で送ります。そのため、ほかの書き手がほかのフィールドに加えた変更は送る内容に入らず、そのまま残ります(第5回)。kubectl apply の patch が resourceVersion を条件に付けるかどうかは、このメディアで確かめた範囲の公式ドキュメントには書かれていません。kubectl edit では、取り出してから保存するまでのあいだに、利用者がエディタで作業する時間が空きます。そのあいだに、別の書き手が同じオブジェクトを変えることがあります。

参考:Kubernetes Object Management | Kubernetes、Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

kubectl edit のリファレンスも、更新でいちばんよくあるエラーは、ほかの誰かがサーバー上のリソースを変えたことだとしています。そのときは、変更を新しいバージョンのリソースに加え直すか、保存された一時ファイルを最新の resource version を含むように直す必要があります。どのような場合にこのエラーになるかの細かい条件は、このメディアで確かめた範囲の公式ドキュメントには書かれていません。

参考:kubectl edit | Kubernetes

手元で試す

ここまでの内容を、手元の kind のクラスタで試す手順を示します。同じ Deployment を kubectl apply と kubectl edit で交互に更新し、resourceVersion と last-applied の変化を比べます。コマンドは macOS や Linux のシェル(bash や zsh)で実行する前提で書いています。Windows では WSL(Windows の中で Linux を動かす仕組み)などを使ってください。試す環境は次のとおりです。

項目内容
kindv0.33.0
Kubernetesv1.37.0(kind v0.33.0 の既定のノードイメージ)
ノード構成シングルノード(クラスタ名 kind):コントロールプレーン 1
必要なものDocker、kubectl(v1.36〜v1.38)、テキストエディタ

参考:Release v0.33.0 · kubernetes-sigs/kind、Version Skew Policy | Kubernetes

kind でクラスタを作る手順は、以下の記事で解説しています。この回ではシングルノードのクラスタを使います。ノードの数に関係しない仕組みを試すからです。

基本仕様 第2回 kind で検証用のクラスタを作るDocker のコンテナをノードにして、手元のマシンに Kubernetes のクラスタを作るツール kind の仕組みを図で説明します。kind create cluster で何が起きるかを押さえ、シングルノードとマルチノードのクラスタを作って、ノードの正体が Docker のコンテナであることを確かめる手順を紹介します。

シングルノードのクラスタを用意する

まず、前の回のクラスタが残っていないかを確かめます。

console
$ kind get clusters

kind が表示されたら、作り直さずにそのまま使えるので、クラスタを作る次のコマンドは飛ばします。表示されなければ、クラスタを作ってから、もう一度一覧します。

console
$ kind create cluster
$ kind get clusters

kind get clusters に kind が表示されれば、クラスタができています。第3回で決めたとおり、ここからのコマンドには --context kind-kind を付けて、操作するクラスタをはっきりさせます。

参考:Quick Start | kind

続けて、ノードを一覧します。

console
$ kubectl get nodes --context kind-kind

ノードが 1 つ表示され、STATUS 列が Ready になっていれば準備ができています。Ready になっていなければ、少し待ってからもう一度実行します。

参考:kubectl get | Kubernetes、Node Status | Kubernetes

kubectl apply で Deployment を作る

第6回と同じ、nginx の Pod を 3 つ動かす Deployment のマニフェストを使います。公式ドキュメントの例をそのまま引用しています。nginx-deployment.yaml という名前で、コマンドを実行するディレクトリに保存します。

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

参考:Deployments | Kubernetes

前の回のクラスタを使い続けている場合は、先に kubectl get deployments --context kind-kind を実行し、nginx-deployment が無いことを確かめてください。あった場合は、この回の「片付け」の kubectl delete -f nginx-deployment.yaml --context kind-kind で消してから進みます。kubectl apply は last-applied をもとに計算するので、別の手順で作られたものが残っていると、この先の結果が説明と変わることがあります。

Deployment を作り、READY 列が 3/3 になるまで待ちます。

console
$ kubectl apply -f nginx-deployment.yaml --context kind-kind
$ kubectl get deployments --context kind-kind

READY 列が 3/3 になっていなければ、少し待ってから kubectl get deployments をもう一度実行します。

参考:Deployments | Kubernetes

続けて、resourceVersion を取り出します。-o jsonpath は、第5回で使った、フィールドを指定して取り出す出力の形式です。

console
$ kubectl get deployment nginx-deployment -o jsonpath='{.metadata.resourceVersion}{"\n"}' --context kind-kind

表示された値を控えておきます。ここではこの値を「1 回目」と呼びます。値そのものは手元の環境ごとに違います。

resourceVersion は、自分の更新のあとに、コントローラーが status を書き込むたびにも変わります。そのため、この回では毎回、READY 列が落ち着いてから、このコマンドをもう一度実行して値を控えます。値は 1 ずつ増えるとは限らないので、差の大きさは気にしなくて構いません。

参考:JSONPath Support | Kubernetes、ObjectMeta | Kubernetes API Reference、Kubernetes API Conventions(2026年10月時点の内容)、Deployments | Kubernetes

次に、last-applied の中身を表示します。kubectl apply view-last-applied は、last-applied のアノテーションを種類と名前で指定して表示するコマンドです。既定では YAML の形式で表示します。

console
$ kubectl apply view-last-applied deployment/nginx-deployment --context kind-kind

参考:kubectl apply view-last-applied | Kubernetes

公式ドキュメントによると、作ったときの last-applied の中身は、作るのに使ったマニフェストと同じです。表示の中に replicas: 3 と image: nginx:1.14.2 があることを確かめてください。アノテーションの中身そのものは JSON の文字列です。kubectl apply view-last-applied は既定でこれを YAML の形式で表示するので、マニフェストに近い見た目で読めます。公式ドキュメントのアノテーションの例では、中身に "annotations":{} や "namespace":"default" も入っています。手元でも、マニフェストに書いていない、このような項目が加わっていることがあると考えられます。

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes、Well-Known Labels, Annotations and Taints | Kubernetes

マニフェストを変えて kubectl apply する

nginx-deployment.yaml の spec の replicas: 3 を replicas: 2 に書き換えて保存します。ほかの行は変えません。

反映する前に、kubectl diff で何が変わるかを確かめます(第5回の補足で触れたコマンドです)。

console
$ kubectl diff -f nginx-deployment.yaml --context kind-kind

kubectl diff は、今のオブジェクトと、apply したらそうなる状態を比べて、YAML の形式で違いを表示します。一般に、この表示では先頭が - の行が今の値、+ の行が apply したあとの値になると考えられます。表示には、replicas が 3 から 2 に変わる違いが含まれます。replicas の行のほかに、Kubernetes が値を入れるフィールドの行が並ぶこともあると考えられます。

終了ステータス(コマンドが終わるときに返す番号)は、違いが無ければ 0、違いがあれば 1、kubectl や diff がエラーになれば 1 より大きい値です。ここで返る 1 はエラーではなく「違いがある」という意味です。

参考:kubectl diff | Kubernetes

違いを確かめたら反映し、resourceVersion と last-applied をもう一度表示します。

console
$ kubectl apply -f nginx-deployment.yaml --context kind-kind
$ kubectl get deployment nginx-deployment -o jsonpath='{.metadata.resourceVersion}{"\n"}' --context kind-kind
$ kubectl apply view-last-applied deployment/nginx-deployment --context kind-kind

resourceVersion は 1 回目と違う値になります。オブジェクトが変わるたびに、サーバーが値を変えるからです。このあと deployment-controller と replicaset-controller が Pod を 2 つに減らし(第6回)、Deployment のコントローラーが status を書き換えます。そのたびに resourceVersion も変わるので、時間を空けて実行すると、さらに別の値になっています。last-applied の中身は replicas: 2 に変わっています。kubectl apply は last-applied を今回のマニフェストの中身に書き換えるからです。

参考:Kubernetes API Conventions(2026年10月時点の内容)、Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes、Deployments | Kubernetes

kubectl get deployments --context kind-kind を何度か実行し、READY 列が 2/2 になったら、resourceVersion を取り出すコマンドをもう一度実行します。

console
$ kubectl get deployment nginx-deployment -o jsonpath='{.metadata.resourceVersion}{"\n"}' --context kind-kind

表示された値を「2 回目」として控えます。

kubectl edit で書き換える

同じ Deployment を kubectl edit で開き、2 か所を書き換えます。マニフェストにある replicas と、マニフェストに無いラベルです。

開くエディタは、環境変数 KUBE_EDITOR か EDITOR で指定したものです。どちらも設定していなければ、Linux では vi が開きます。macOS での既定はこのメディアで確かめた範囲の公式ドキュメントには書かれていません。どのエディタが開くかで迷わないように、この回では公式ドキュメントの例にならって、コマンドの前で KUBE_EDITOR を指定します。以下は nano を使う例です。

console
$ KUBE_EDITOR="nano" kubectl edit deployment/nginx-deployment --context kind-kind

参考:kubectl edit | Kubernetes

nano が入っていない場合は、KUBE_EDITOR="vi" にします。2 つのエディタの一般的な操作を次の表にまとめます。公式ドキュメントからではなくエディタの一般的な使い方です。

したいことnanovi
文字を入力するそのまま打つi を押してから打つ
保存して終わるCtrl+O で保存し、Enter を押してから Ctrl+XEsc を押してから :wq と打ち、Enter
保存せずに終わるCtrl+X を押し、保存するか聞かれたら NEsc を押してから :q! と打ち、Enter

保存せずに終われば、何も変わらないので、もう一度 kubectl edit からやり直せると考えられます。

エディタに Deployment の YAML が開きます。マニフェストより多くの行が並び、metadata.annotations には last-applied も見えます。開いた YAML に metadata.managedFields が無くても、異常ではありません。kubectl edit の --show-managed-fields は、第5回で見た kubectl get と同じく、付けたときだけ managedFields を JSON や YAML の表示に残すフラグなので、既定では表示されないと考えられます。last-applied と status には触らずに、次の 2 か所を書き換えます。

場所書き換え前書き換え後
一番上の metadata: の中の labels:(app: nginx の行の下)なしenv: test を、app: nginx と同じ字下げで加える
一番上の spec: の中の replicas:24

labels: は、spec.selector.matchLabels と spec.template.metadata.labels にもあります。書き換えるのは、一番上の metadata: の直下にある labels: だけです。spec.template の中のラベルを変えると、Pod のひな形が変わり、Pod が入れ替わることがあります(第6回)。replicas: も、書き換えるのは一番上の spec: の直下の行だけです。status: の中にも replicas: があり、last-applied の JSON の文字列の中にも "replicas" がありますが、どちらも書き換えません。

書き換えたら保存して、エディタを閉じます。エディタを閉じると、kubectl が変更をクラスタに反映します。公式ドキュメントの Deployment の例(image を書き換える例)では、反映できたときに次のような出力が表示されます。

deployment.apps/nginx-deployment edited

参考:kubectl edit | Kubernetes、Deployments | Kubernetes

反映でエラーになったときは、反映できなかった変更を入れた一時ファイルが作られます。その場合は、次に示す表示のコマンドで今の値を確かめ、変わっていなければ、同じ kubectl edit のコマンドからやり直します。

反映できたら、resourceVersion、last-applied、今の値を表示します。--show-labels は、ラベルを最後の列に表示する指定です。

console
$ kubectl get deployment nginx-deployment -o jsonpath='{.metadata.resourceVersion}{"\n"}' --context kind-kind
$ kubectl apply view-last-applied deployment/nginx-deployment --context kind-kind
$ kubectl get deployment nginx-deployment --show-labels --context kind-kind

参考:kubectl get | Kubernetes

見るところを次の表にまとめます。

見るところ起きていること
resourceVersion が 2 回目と違う値になるkubectl edit の更新でもオブジェクトが変わったので、サーバーが値を変えた
last-applied は replicas: 2 のままで、env のラベルも無いkubectl edit は --save-config を付けなければ last-applied を変えない
READY 列の / の右側(望ましい数)が 4 になる(しばらくすると 4/4)今のオブジェクトの spec.replicas は 4 になった
LABELS 列に app=nginx と env=test が並ぶ今のオブジェクトにラベルが加わった

参考:Kubernetes API Conventions(2026年10月時点の内容)、kubectl edit | Kubernetes、Deployments | Kubernetes

この時点で、手元のマニフェスト(replicas: 2)、last-applied(replicas: 2)、今のオブジェクト(replicas: 4、env: test のラベル)の 3 つが食い違っています。

READY 列が 4/4 になったら、resourceVersion を取り出すコマンドをもう一度実行し、表示された値を「3 回目」として控えます。Pod が増えるあいだにコントローラーが status を書き換えるので、さきほど表示した値とも違っていることがあります。

console
$ kubectl get deployment nginx-deployment -o jsonpath='{.metadata.resourceVersion}{"\n"}' --context kind-kind

もう一度 kubectl apply する

マニフェストは変えずに、もう一度 kubectl diff で違いを確かめます。

console
$ kubectl diff -f nginx-deployment.yaml --context kind-kind

「kubectl apply が送る部分を決める仕組み」の表に当てはめると、2 つの書き換えは次のように扱われます。

フィールドマニフェストlast-applied今のオブジェクト表の行kubectl apply がすること
spec.replicas2241 行目マニフェストの値の 2 にする
metadata.labels の env無い無いtest4 行目何もしない。env: test を残す

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

そのため、kubectl diff には replicas が 4 から 2 に戻る違いが表示され、env のラベルを消す違いは表示されません。replicas の行のほかに、Kubernetes が値を入れるフィールドの行が並ぶこともあると考えられます。

確かめたら反映し、もう一度表示します。

console
$ kubectl apply -f nginx-deployment.yaml --context kind-kind
$ kubectl get deployment nginx-deployment -o jsonpath='{.metadata.resourceVersion}{"\n"}' --context kind-kind
$ kubectl get deployment nginx-deployment --show-labels --context kind-kind

resourceVersion は 3 回目と違う値になります。READY 列の / の右側(望ましい数)は 2 に戻り、しばらくすると 2/2 になります。kubectl edit で変えた replicas: 4 は、kubectl apply で消えたことになります。一方、LABELS 列には env=test が残ります。マニフェストにも last-applied にも無いキーなので、kubectl apply が扱わないからです。

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes、Kubernetes API Conventions(2026年10月時点の内容)

env: test のラベルはマニフェストのどこにも書かれていないのに、クラスタのオブジェクトにだけ残っています。マニフェストを見ただけでは、このラベルがあることはわかりません。「なぜ」の節で見た、記録と実際の食い違いです。

書き手の名前を確かめる

最後に、apply と edit がオブジェクトに別の書き手として記録されていることを確かめます。第5回で見たとおり、kubectl get の -o yaml は既定では managedFields を表示しないので、--show-managed-fields を付けます。表示が長いので、grep(指定した文字列を含む行だけを表示するコマンド)で、書き手の名前と操作の行だけを取り出します。-E を付けると、| で区切ったどれか 1 つを含む行を取り出せます。

console
$ kubectl get deployment nginx-deployment -o yaml --show-managed-fields --context kind-kind | grep -E 'manager:|operation:|subresource:'

参考:kubectl get | Kubernetes

API リファレンスによると、managedFields の項目ごとに、manager は書き手の名前、operation は項目を作った操作の種類(Apply か Update)、subresource は更新に使ったサブリソース(/status のような、オブジェクトの一部を更新する別のパス。第5回)の名前です。v1.37 時点の既定の書き手の名前は、kubectl apply が kubectl-client-side-apply、kubectl edit が kubectl-edit です。そのため、表示にはこの 2 つの名前が並ぶと考えられます。Server-Side Apply のページによると、operation は、そのフィールドを最後に変えたリクエストが server-side apply の patch なら Apply、それ以外なら Update です。この回の apply は client-side apply なので、kubectl-client-side-apply の項目の operation は Update になるはずです。ほかに、subresource: status の項目や、見慣れない名前の項目が並ぶこともあると考えられます。Deployment の status を書き込んだコントロールプレーンのコンポーネントの項目と考えられるので、気にしなくて構いません。

参考:ManagedFieldsEntry | Kubernetes API Reference、kubectl apply | Kubernetes、kubectl edit | Kubernetes、Server-Side Apply | Kubernetes

片付け

作った Deployment を、マニフェストを指定して削除します。

console
$ kubectl delete -f nginx-deployment.yaml --context kind-kind
$ kubectl get deployments,rs,pods --context kind-kind

第6回で見たとおり、Deployment を消すと、その ReplicaSet と Pod も消えます。消えきるまでは、Pod が Terminating で表示されることがあります。少し待ってから kubectl get をもう一度実行し、nginx-deployment の Deployment、ReplicaSet、Pod がどれも表示されなければ、削除できています。公式ドキュメントは kubectl apply で管理しているオブジェクトを消すときに、kubectl delete -f <ファイル> を勧めています。命令的な削除は宣言的な管理と組み合わせてよい、とも書かれています。

参考:kubectl delete | Kubernetes、Garbage Collection | Kubernetes、Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

最後に、クラスタを削除し、消えたことを確かめます。

console
$ kind delete cluster
$ kind get clusters

kind delete cluster は、存在しないクラスタを指定してもエラーを返しません。kind get clusters に kind が表示されなくなったことを確かめます。kubeconfig に kind-kind のコンテキストが残っていたら、第3回の片付けと同じく kubectl config delete-context kind-kind で消します。

参考:Quick Start | kind、kubectl config | Kubernetes

注意点

kubectl apply と kubectl edit を使うときにつまずきやすい点と、バージョンで変わる点を、次の表にまとめます。

項目内容
apply で管理しているものは edit で変えない公式ドキュメントは、1 つのオブジェクトを 1 つの管理の方法だけで扱うよう警告している。マニフェストにあるフィールドを edit で変えても、次の apply でマニフェストの値に戻る
edit で加えたフィールドは記録に残らないマニフェストにも last-applied にも無いフィールドは apply が扱わないので、クラスタにだけ残り続ける
edit は既定では last-applied を変えない--save-config を付けたときだけ、今の設定を last-applied に保存する
apply で扱うなら最初から apply で作るリファレンスは、apply を使うなら最初に apply か create --save-config で作るよう求めている。宣言的な管理の手順のページも、create や replace と apply を混ぜることはサポートされていないと警告している
resourceVersion の値の中身に頼らない中身は opaque として扱い、変えずに返す決まり(v1.37 時点では、kube-apiserver が扱うリソースの種類なら、同じ種類どうしで順序を比べることは認められている)。オブジェクトが変わるたびに変わるので、コントローラーの status の書き込みでも変わる。この回では変わったかどうかだけを見る
edit の保存に失敗したら一時ファイルを見る反映できなかった変更は一時ファイルに残る。よくある原因は、ほかの誰かが同じリソースを変えたこと
last-applied は古い仕組み(v1.37 時点)公式ドキュメントは、last-applied で変更を追うのはレガシーの仕組みで、server-side apply に置き換えられたとしている。ただし kubectl apply の既定は今も client-side apply

参考:Kubernetes Object Management | Kubernetes、Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes、kubectl edit | Kubernetes、kubectl apply | Kubernetes、ObjectMeta | Kubernetes API Reference、Kubernetes API Concepts | Kubernetes、Kubernetes API Conventions(2026年10月時点の内容)、Deployments | Kubernetes、Well-Known Labels, Annotations and Taints | Kubernetes、Server-Side Apply | Kubernetes

マニフェストにあるフィールドを、apply ではなく kubectl scale などで変え続けたいときの手順も、公式ドキュメントにあります。マニフェストからそのフィールドを消し、今のオブジェクトの last-applied からも手で消す、という手順です。この説明は「Kubernetes 1.5 の時点では」という書き方のまま、v1.37 時点のページに載っています。

参考:Declarative Management of Kubernetes Objects Using Configuration Files | Kubernetes

関連記事

マニフェストのフィールドと、resourceVersion などの Kubernetes が値を入れるフィールドについては、以下の記事で解説しています。

基本仕様 第5回 マニフェストと宣言的 API の仕組みKubernetes に渡すマニフェストの構造と、望ましい状態を書いて任せる宣言的 API の仕組みを図で説明します。apiVersion・kind・metadata・spec・status の役割と、spec と status を誰が書くのかを押さえ、kind のクラスタで kubectl explain を使い、Pod の spec と status を作成直後と数秒後で比べる手順を紹介します。

この回で使った Deployment が、Pod の数を replicas に合わせ続ける仕組みについては、以下の記事で解説しています。

基本仕様 第6回 消した Pod が戻ってくる仕組み(調整ループ)コントローラーが実際の状態を望ましい状態に近づけ続ける調整ループの仕組みを図で説明します。Deployment・ReplicaSet・Pod の関係と、Pod を消したときに誰が気づいて代わりを作るのかを押さえ、kind のクラスタで Deployment の Pod を手で削除し、作り直される様子を観察する手順を紹介します。

Kubernetes で動かす最小の単位である Pod と、Pod を直接作って消したときの動きについては、以下の記事で解説しています。

基本仕様 第8回 ・ 準備中 Pod を動かして理解する 公開したら、ここから読めるようになります。

Kubernetes 基本仕様の目次へ