このドキュメントは The Kubectl Book の翻訳です。翻訳の GitHub リポジトリはこちら。
- リソース構成から追加また削除されたフィールドは Apply を実行することでリソースにマージされる
- すでにリソースが存在していれば、Apply を実行するとリソースが更新され、ローカルにあるリソース構成がリモートのリソースにマージされる
- リソース構成から除かれたフィールドは、リモートのリソースから削除される
フィールドのマージ
この章には高度な内容が含まれるため、読み飛ばして後から戻っても構いません。
フィールドはマージされるのはいつか?
このページでは、リソース構成がどのようにリソースとマージされるか、あるいはどのように他のリソース構成とマージされるかを説明します。マージされるタイミングは以下です。
- リソース構成の更新をクラスタ内で稼働中のリソースに適用する
kustomization.yaml
の中でresources
および bases 上にパッチを定義する
リソース構成の更新を適用する
Apply は新しいリソース構成を使ってリソースを置換するのではなく、新しいリソース構成を稼働中のリソースにマージします。そのために制御プレーンによって設定されうる値、たとえば autoscaler により設定される replicas
の値などを保持します。
パッチを定義する
patches
は疎なリソース構成で、他のリソース構成の中で定義された値を上書きするフィールドのサブセットを含みます。上書き対象となるリソースは、同じグループ / バージョン / Kind / 名前空間をもつものです。これはリソース構成をフォークせずに、リソース構成で定義された値を変更するために使用されます。
動機 (Apply)
このページではリソース構成をマージするための意味論を説明します。
リソースフィールドの所有権は、人間の手で書かれた宣言的なリソース構成と、クラスタ内で稼働するコントローラが設定した値との間で共有されます。status
や clusterIp
のようないくつかのフィールドは、コントローラが排他的に所有します。namespace
などのフィールドは、リソースを管理する人間が排他的に所有します。
replicas
のような他のフィールドは、人間が所有することもありますし、apiserver やコントローラが所有することもあります。たとえば、replicas
はユーザーが排他的に設定することもできますが、apiserver が暗黙的にデフォルト値を設定することもあり、あるいは HorizontalPodAutoscaler のようなコントローラが継続的に調整することもあります。
前回適用されたリソース構成
Apply はリソースを作成または更新するときに、適用されたリソース構成をリソース上のアノテーションに書き込みます。これによって前回適用されたリソース構成と今回のリソース構成を比較することができ、削除されたフィールドを特定できます。
# deployment.yaml (Resource Config)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
# Original Resource
Doesn't Exist
# Applied Resource
kind: Deployment
metadata:
annotations:
# ...
# This is the deployment.yaml Resource Config written as an annotation on the object
# It was written by kubectl apply when the object was created
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment",
"metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
"spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
"spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx"}]}}}}
# ...
spec:
# ...
status:
# ...
リソースをマージする
以下はリソースをマージするときの意味論です。
フィールドの追加
- リソース構成に存在しているがリソースに欠落しているフィールドは、リソースに追加される
- フィールドは前回適用されたリソース構成に追加される
# deployment.yaml (Resource Config)
apiVersion: apps/v1
kind: Deployment
metadata:
# ...
name: nginx-deployment
spec:
# ...
minReadySeconds: 3
# Original Resource
kind: Deployment
metadata:
# ...
name: nginx-deployment
spec:
# ...
status:
# ...
# Applied Resource
kind: Deployment
metadata:
# ...
name: nginx-deployment
spec:
# ...
minReadySeconds: 3
status:
# ...
フィールドの更新
- リソース構成にもリソースにも存在しているフィールドは、再帰的にマージされ、末端のプリミティブ値のフィールドが更新されるか、またはフィールドが追加 / 削除される
- フィールドは前回適用されたリソース構成の中で更新される
# deployment.yaml (Resource Config)
apiVersion: apps/v1
kind: Deployment
metadata:
# ...
name: nginx-deployment
spec:
# ...
replicas: 2
# Original Resource
kind: Deployment
metadata:
# ...
name: nginx-deployment
spec:
# ...
# could be defaulted or set by Resource Config
replicas: 1
status:
# ...
# Applied Resource
kind: Deployment
metadata:
# ...
name: nginx-deployment
spec:
# ...
# updated
replicas: 2
status:
# ...
フィールドの削除
- 前回適用されたリソース構成に存在するが現在のリソース構成で除かれたフィールドは、リソースから削除される
- リソース構成で null 値で存在しているフィールドはリソースから削除される
- フィールドは前回適用されたリソース構成から除かれる
# deployment.yaml (Resource Config)
apiVersion: apps/v1
kind: Deployment
metadata:
# ...
name: nginx-deployment
spec:
# ...
# Original Resource
kind: Deployment
metadata:
# ...
name: nginx-deployment
# Containers replicas and minReadySeconds
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment", "spec":{"replicas": "2", "minReadySeconds": "3", ...}, "metadata": {...}}
spec:
# ...
minReadySeconds: 3
replicas: 2
status:
# ...
# Applied Resource
kind: Deployment
metadata:
# ...
name: nginx-deployment
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment", "spec":{...}, "metadata": {...}}
spec:
# ...
# deleted and then defaulted, but not in Last Applied
replicas: 1
# minReadySeconds deleted
status:
# ...
リソース構成から単にフィールドを除くだけでは所有権がクラスタに移ることはありません。そうではなくリソースからフィールドを削除します。もしフィールドがリソース構成の中に設定され、ユーザーが所有権を放棄したい (たとえば replicas
をリソース構成から除いて autoscaler に頼る) と思ったら、最初に、クラスタに保存されている前回適用されたリソース構成からフィールドを削除しなければなりません。
これを実行するには、kubectl apply edit-last-applied
コマンドを使い、前回適用されたリソース構成から replicas
を削除し、次にリソース構成からも削除します。
フィールドのマージの意味論
プリミティブ値のマージ
プリミティブ値のフィールドは現在の値を新しい値に置換することでマージします。
フィールドの作成: プリミティブ値のフィールドを追加
フィールドの更新: プリミティブ値のフィールドの値を変更
フィールドの削除: プリミティブ値のフィールドを削除
リソース構成内のフィールド | リソース内のフィールド | 前回適用されたフィールド | アクション |
---|---|---|---|
Yes | Yes | - | 稼働中のリソースにリソース構成の値を設定 |
Yes | No | - | 稼働中のリソースにリソース構成の値を設定 |
No | - | Yes | リソースから削除 |
No | - | No | 何もしない |
オブジェクトのマージ
オブジェクトのフィールドは下位のフィールドを (フィールド名で) 再帰的にマージすることによって更新します。マージは末端でプリミティブ値のフィールドが見つかるか、フィールドを追加 / 削除するまで続きます。
フィールドの作成: オブジェクトのフィールドを追加
フィールドの更新: 再帰的にオブジェクトの下位のフィールドを見て値を比較し、マージする
フィールドの削除: オブジェクトのフィールドを削除
テーブルのマージ: 各フィールドに対してリソース構成と同名のリソースの値をマージ
リソース構成内のフィールド | リソース内のフィールド | 前回適用されたフィールド | アクション |
---|---|---|---|
Yes | Yes | - | 再帰的にリソース構成とリソースの値をマージする |
Yes | No | - | 稼働中のリソースにリソース構成の値を設定 |
No | - | Yes | リソースからフィールドを削除する |
No | - | No | 何もしない |
マップのマージ
マップフィールドは要素を (キーで) マージします。マージは末端でプリミティブ値のフィールドが見つかるか、値が追加 / 削除されるまで続きます。
フィールドの削除: マップフィールドを追加
フィールドの更新: 再帰的にマップの値をキーで比較し、マージする
フィールドの削除: マップフィールドを削除
テーブルのマージ: 各マップの要素に対してリソース構成と同キーのリソースの値をマージ
リソース構成内のキー | リソース内のキー | 前回適用されたリソース構成内のキー | アクション |
---|---|---|---|
Yes | Yes | - | 再帰的にリソース構成とリソースの値をマージする |
Yes | No | - | 稼働中のリソースにリソース構成の値を設定 |
No | - | Yes | リソースから要素を削除 |
No | - | No | 何もしない |
プリミティブ値のリストのマージ
プリミティブ値のリストは、フィールドに patch strategy: merge
が設定されていればマージされ、そうでなければ置換されます。 Finalizer list example
マージ戦略
- プリミティブ値のリストのマージは ordered set の挙動と似ています
- プリミティブ値のリストの置換はマージ時に置換されます
順序付け: リソース構成の中で定義された順序を使用します。リソース構成に定義されていない要素は、リソース構成内の要素に関して順序の保証はありません。
マージテーブル: 各リストの要素はリソース構成とリソースの要素を同じ値でマージします
リソース構成の要素 | リソースの要素 | 前回適用されたリソース構成の要素 | アクション |
---|---|---|---|
Yes | Yes | - | 何もしない |
Yes | No | - | リストに追加 |
No | - | Yes | リストから除く |
No | - | No | 何もしない |
このマージ戦略は patch merge key を使ってリスト内のコンテナ要素を識別し、マージします。patch merge key
はフィールド上の Kubernetes API で定義されています。
# Last Applied
args: ["a", "b"]
# Resource Config (Local)
args: ["a", "c"]
# Resource (Live)
args: ["a", "b", "d"]
# Applied Resource
args: ["a", "c", "d"]
オブジェクトのリストのマージ
マージ戦略: プリミティブ値のリストはマージされるか置換されるかします。リストの patch strategy
が merge でリストフィールドに patch merge key
があるとき、リストはマージされます。 Container list example
マージキー: patch merge key
はリスト内の同じ要素を識別するために使用されます。 map の要素 (キーによるキー) やオブジェクトのフィールド (フィールド名によるキー) と違って、リストは各要素を区別するビルトインの識別子がありません (インデックスは同一性を定義しません)。オブジェクトのフィールドの代わりに、マージする要素に対して人工のキー / バリューとして使われます。このフィールドは patch merge key
です。同じ patch merge key をもつ要素はリストがマージされるときにマージされます。
順序: リソース構成の中で定義された順序を使用します。リソース構成の中で定義されていない要素は順序が保証されません。
マージテーブル: 各リストの要素に対してリソース構成とリソースの要素をマージしますが、patch merge key
の値が同じ要素をマージします。
リソース構成の要素 | リソースの要素 | 前回適用されたリソース構成の要素 | アクション |
---|---|---|---|
Yes | - | - | 再帰的にリソース構成とリソースの値をマージする |
Yes | No | - | リストに追加 |
No | - | Yes | リストから除く |
No | - | No | 何もしない |
このマージ戦略は patch merge key を使ってリスト内のコンテナ要素を識別し、マージします。patch merge key
はフィールド上の Kubernetes API で定義されています。
# Last Applied Resource Config
containers:
- name: nginx # key: nginx
image: nginx:1.10
- name: nginx-helper-a # key: nginx-helper-a; will be deleted in result
image: helper:1.3
- name: nginx-helper-b # key: nginx-helper-b; will be retained
image: helper:1.3
# Resource Config (Local)
containers:
- name: nginx
image: nginx:1.10
- name: nginx-helper-b
image: helper:1.3
- name: nginx-helper-c # key: nginx-helper-c; will be added in result
image: helper:1.3
# Resource (Live)
containers:
- name: nginx
image: nginx:1.10
- name: nginx-helper-a
image: helper:1.3
- name: nginx-helper-b
image: helper:1.3
args: ["run"] # Field will be retained
- name: nginx-helper-d # key: nginx-helper-d; will be retained
image: helper:1.3
# Applied Resource
containers:
- name: nginx
image: nginx:1.10
# Element nginx-helper-a was Deleted
- name: nginx-helper-b
image: helper:1.3
# Field was Ignored
args: ["run"]
# Element was Added
- name: nginx-helper-c
image: helper:1.3
# Element was Ignored
- name: nginx-helper-d
image: helper:1.3
kubectl edit
と kubectl set
は前回適用されたリソース構成を無視しますが、Apply は、kubectl edit
や kubectl set
でセットされたリソース構成の値を変更します。kubectl edit
や kubectl set
でセットされた値を無視するには、以下のようにします。
kubectl apply edit-last-applied
を使って前回適用されたリソース構成から (もし存在すれば) 値を削除します- リソース構成からフィールドを削除します
これは autoscaler のようなクラスタコンポーネントによって設定された値を保持するのと同じテクニックです。