Mais conteúdo relacionado Semelhante a わかる!metadata.managedFields / Kubernetes Meetup Tokyo 48 (20) Mais de Preferred Networks (20) わかる!metadata.managedFields / Kubernetes Meetup Tokyo 481. Kubernetes Meetup Tokyo #48(2022/02/22)
SUDA Kazuki, Preferred Networks, Inc.
@superbrothers
わかる!metadata.managedFields
2. @superbrothers
!
SUDA Kazuki / @superbrothers
▶ Preferred Networks, Inc. / エンジニア
▶ Scalar, Inc. / 技術アドバイザ
▶ Kubernetes Meetup Tokyo 共同主催者
▶ Cloud Native Ambassador (CNCF)
▶ 「Kubernetes実践⼊⾨」、「みんなのDocker/Kubernetes」共著書
▶ 「⼊⾨ Prometheus」、「Kubernetes で実践するクラウドネイティブ DevOps」監訳書
2
5. @superbrothers
!
😱
消えないラベル(事件編)
ある⽇の、GitOps ツールの Flux2 を導⼊している企業で、開発者がマニフェストファイルのあるラベル
を削除してリポジトリに変更をコミットした。GitOps ツール導⼊企業なので、あとは放っておけば
ツールがクラスタに変更を適⽤してくれる。
数時間後、Flux2 による適⽤が成功しているにも関わらず削除したはずのラベルが実際には削除されて
いないことに開発者が気がついた。
5
! " !
リポジトリ
開発者
!
1. マニフェストファイルを変更して
リポジトリにコミット
2. GitOps ツールがリポジトリに更新があると
マニフェストをクラスタに Apply
3. 数時間後にオブジェクトを確認すると
変更が反映されていないことが判明
!"!#$%&'()*+,-&$./0123456
6. @superbrothers
!
消えないラベル(事件編)
6
証拠品1: Flux2 が適⽤したマニフェスト 証拠品2: 適⽤後のオブジェクトの状態
apiVersion: v1
kind: ConfigMap
metadata:
name: config
labels:
$ kubectl get configmap config -o yaml
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"ann
creationTimestamp: "2022-02-17T12:22:15Z"
labels:
test-data: value2
name: config
namespace: default
resourceVersion: "3758306"
uid: 2c4d5bda-1c3b-450d-b7f7-5fa3e8159f83
test-data ラベルを消したはずが
オブジェクトから消えていない。
📝$#7(89$:;<=>:?@AB:CDEFGHAIJKL
8. @superbrothers
!
嫌われものの metadata.managedFields
8
$ kubectl version --client
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.15",
GitCommit:"8f1e5bf0b9729a899b8df86249b56e2c74aebc55", GitTreeState:"clean", BuildDate:"2022-01-19T17:27:39Z",
GoVersion:"go1.15.15", Compiler:"gc", Platform:"linux/amd64"}
$ kubectl get po nginx-66f6ffdddf-p2kt5 -o yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2022-02-17T05:33:10Z"
generateName: nginx-66f6ffdddf-
labels:
app: nginx
pod-template-hash: 66f6ffdddf
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:generateName: {}
f:labels:
.: {}
f:app: {}
f:pod-template-hash: {}
MNOP>QJ6FHRSIJBTU
9. @superbrothers
!
kubectl v1.21 でデフォルトで出⼒されなくなった
9
$ kubectl version --client
Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.9",
GitCommit:"b631974d68ac5045e076c86a5c66fba6f128dc72", GitTreeState:"clean", BuildDate:"2022-01-19T17:51:12Z",
GoVersion:"go1.16.12", Compiler:"gc", Platform:"linux/amd64"}
$ kubectl get po nginx-66f6ffdddf-p2kt5 -o yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2022-02-17T05:33:10Z"
generateName: nginx-66f6ffdddf-
labels:
app: nginx
pod-template-hash: 66f6ffdddf
name: nginx-66f6ffdddf-p2kt5
namespace: default
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: nginx-66f6ffdddf
V*&*WXY#,X7YZ$[Q]IK
デフォルトで出⼒されなくなっただけで、実際には存在しています。
⾒やすくなってよかったが、⼀⽅で⽬にすることが減り、知る機会がなくなってしまった。
--show-managed-fields ^._`a4b
$$$$$$$$$$$cdedfghSi5
10. $ kubectl get cm config -o yaml --show-managed-fields
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"annotations":{},"labels":{"test-data":"value2"},"name":"config","namespa
creationTimestamp: "2022-02-17T12:59:48Z"
labels:
test-data: value2
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels: {}
manager: flux-controller
operation: Apply
time: "2022-02-17T13:00:42Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:kubectl.kubernetes.io/last-applied-configuration: {}
f:labels:
F:test-data: {}
manager: kubectl-client-side-apply
operation: Update
time: "2022-02-17T13:00:10Z"
name: config
namespace: default
resourceVersion: "3762113"
uid: 5ee6567e-5248-4494-a0aa-d55a5e16b8f3
11. @superbrothers
!
ユーザが metadata.managedFields を理解する必要がある?
11
$ kubectl explain po.metadata.managedFields
KIND: Pod
VERSION: v1
RESOURCE: managedFields <[]Object>
DESCRIPTION:
ManagedFields maps workflow-id and version to the set of fields that are
managed by that workflow. This is mostly for internal housekeeping, and
users typically shouldn't need to set or understand this field. A workflow
can be the user's name, a controller's name, or the name of a specific
apply path like "ci-cd". The set of fields is always in the version that
the workflow used when modifying the object.
ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of
the resource that the fieldset applies to.
13. @superbrothers
!
Server Side Apply(SSA)とは
差分の計算をサーバサイドで実施する Apply(適⽤)のこと
▶ そもそも Kubernetes における Apply(適⽤)は、オブジェクトが存在しなければ作成し、
存在すれば差分(パッチ)を適⽤する操作
▶ 差分を計算するには、ユーザが管理しているフィールドを記憶しておく必要がある
+ 現在のオブジェクトの状態から差分を計算してしまうと、そのフィールドがユーザが管理してい
るものなのか、Kubernetes(コントローラ等)が管理しているものなのかわからない
▶ SSA は誰がそのフィールドを管理しているかの情報を metadata.managedFields に保存する
+ SSA 以外の⼿段によるフィールドの更新も SSA への移⾏や互換性のために同様に記録される
▶ SSA は Kubernetes v1.22 で GA となり、利⽤が広がっている
13
jkl$mno$:$pXq7-rVX&+$ZqX'stXq7,'*Z$uvwxyz{|Ai56
14. @superbrothers
!
サーバサイドがあるなら、クライアントサイドは?🤔
▶ クライアントサイドの Apply には問題があることが分かっているため、SSA が開発された
+ kubectl edit でコンテナイメージを変更したあとにマニフェストが適⽤すると変更が巻き戻る
+ SSA では、フィールドの衝突が検知されて誰かがオブジェクトを変更したことがわかる
+ クライアントサイドにロジックがあることでGo 以外の⾔語や kubectl 以外のツールから使うこと
がむずかしい
+ SSA はサーバサイドで実⾏されるため、curl からでも利⽤できる
+ ユーザの管理しているフィールドの情報のみを保存している
+ SSA は、ユーザに加えてコントローラが管理しているフィールドも含めて保存する
▶ v1.23 時点で kubectl apply はまだクライアントサイドの Apply を使っている
+ --server-side オプションで SSA に変更できるが、いちユーザが積極的に使う理由はない
14
}()X'+7s}()Xt&X+XZs,-~7*Z+•*qq7,XY•'-&€,W(t*+,-&b
FJ•‚ƒ„w_`az…]Ii5L
16. @superbrothers
! 16
apiVersion: v1
kind: ConfigMap
metadata:
name: test-cm
namespace: default
labels:
test-label: test
managedFields:
- manager: kubectl
operation: Apply
apiVersion: v1
fields:
f:metadata:
f:labels:
f:test-label: {}
- manager: kube-controller-manager
operation: Update
apiVersion: v1
time: '2019-03-30T16:00:00.000Z'
fields:
f:data:
f:key: {}
data:
key: new value
フィールドのマネージャ名で⾃分で宣⾔する。
(kubectl apply --server-side の
マネージャ名が kubectl (デフォルト))
どの操作でオブジェクトを変更したか。
SSA は "Apply" 、それ以外で "Update" になる。
managedFields は SSA でしか使われないが
既存の⽅法との互換性を持たせるために
Update も記録されるようになっている。
このマネージャが管理している
フィールドを⽰している
kube-controller-manager があとから SSA 以外の⼿段で
フィールドを追加したことがわかる
V*&*WXY#,X7YZ$[$†()Xt&X+XZ$[{|AIJK‡4
ˆ‰Š‹>ˆŒ•Žd•kB•AI:J‘J’
19. @superbrothers
!
kubectl apply でのコンフリクト
19
$ kubectl apply -f deploy.yaml --server-side
error: Apply failed with 1 conflict: conflict with "kubectl-edit" using apps/
v1: .spec.template.spec.containers[name="nginx-unprivileged"].image
Please review the fields above--they currently have other managers. Here
are the ways you can resolve this warning:
* If you intend to manage all of these fields, please re-run the apply
command with the `--force-conflicts` flag.
* If you do not intend to manage all of the fields, please edit your
manifest to remove references to the fields that should keep their
current managers.
* You may co-own fields by updating your manifest to match the existing
value; in this case, you'll become the manager if the other manager(s)
stop managing the field (remove it from their configuration).
See http://k8s.io/docs/reference/using-api/server-side-apply/#conflicts
“SK‚2_`az”gAIQSI•]–—˜™6😊
21. $ kubectl get cm config -o yaml --show-managed-fields
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"annotations":{},"labels":{"key":"value2"},"name":"config","namespace":"d
creationTimestamp: "2022-02-17T12:59:48Z"
labels:
test-data: value2
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels: {}
manager: flux-controller
operation: Apply
time: "2022-02-17T13:00:42Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:kubectl.kubernetes.io/last-applied-configuration: {}
f:labels:
F:test-data: {}
manager: kubectl-client-side-apply
operation: Update
time: "2022-02-17T13:00:10Z"
name: config
namespace: default
resourceVersion: "3762113"
uid: 5ee6567e-5248-4494-a0aa-d55a5e16b8f3
Flux はたしかに test-data ラベルを所有していない
別のマネージャが test-data ラベルを所有権を保持したままになっている!
VX+*Y*+*sV*&WXY#,X7YZ$>5šI‡›œ[•K6
22. $ kubectl get cm config -o yaml --show-managed-fields
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"annotations":{},"labels":{"test-data":"value2"},"name":"config","namespa
creationTimestamp: "2022-02-17T12:59:48Z"
labels:
test-data: value2
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels: {}
manager: flux-controller
operation: Apply
time: "2022-02-17T13:00:42Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:kubectl.kubernetes.io/last-applied-configuration: {}
f:labels:
f:test-data: {}
manager: kubectl-client-side-apply
operation: Update
time: "2022-02-17T13:00:10Z"
name: config
namespace: default
resourceVersion: "3762113"
uid: 5ee6567e-5248-4494-a0aa-d55a5e16b8f3
▶ kubectl-client-side-apply マネージャのみがこのフィールドを所有している
▶ このマネージャが所有権を放棄すればこのフィールドが削除される
▶ manager と operation から
kubectl apply (クライアントサイド)で変更されていることがわかる
解決策
23. $ cat <<EOL | kubectl apply -f-
apiVersion: v1
kind: ConfigMap
metadata:
name: config
labels:
EOL
configmap/config configured
$ kubectl get cm config -o yaml --show-managed-fields
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"annotations":{},"labels":null,"name":"config","namespace":"default"}}
creationTimestamp: "2022-02-17T12:59:48Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels: {}
manager: flux-controller
operation: Apply
time: "2022-02-17T13:00:42Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:kubectl.kubernetes.io/last-applied-configuration: {}
manager: kubectl-client-side-apply
operation: Update
time: "2022-02-17T13:00:10Z"
test-data ラベルの所有権を放棄できている
ラベルのフィールドが削除されている
test-data ラベルの存在しないマニフェストを kubectl apply(クライアントサイド)で適⽤
24. @superbrothers
!
「消えないラベル」の真相
1. 開発者は Flux2 による適⽤(SSA)を⽌めて⼿元のマニフェストファイルを適⽤した
+ 開発者は test-data ラベルの値を変更し適⽤したことでこのフィールドのマネージャになっていた
(kubectl-client-side-apply マネージャがそれ)
2. 開発者はこの変更でうまく機能したので変更をリポジトリにコミットした
3. 開発者は Flux2 による適⽤(SSA)を再開した
+ test-data ラベルはすでに他のマネージャが所有権を持っている
+ Flux2 はラベルを同じ値で適⽤したので所有権を取得し、共同所有者になった
4. 開発者はその後ラベルがいらなくなったのでマニフェストを変更してリポジトリにコミットした
+ Flux2 は test-data ラベルの削除されたマニフェストを適⽤してラベルを削除しようとするが、
他に共同所有がいるため、所有権を放棄するだけで実際にフィールドは削除されなかった
24
ž:5šIŸ‘B6
25. @superbrothers
!
根本的な解決はむずかしい
▶ 問題1: Flux2 がユーザとは異なるマネージャとして SSA していること
+ SSA を使う前はクライアントサイドの適⽤を使⽤していた("ユーザ"としての適⽤と同等)
+ SSA を採⽤し独⾃のマネージャを使⽤したことで "ユーザ" として適⽤しなくなった
+ "ユーザ" として適⽤してくれれば共同所有にならない(上書きになる)
+ SSA で "ユーザ" として適⽤するには適⽤時に manager 名を kubectl にすればいける
▶ 問題2: kubectl apply がクライアントサイドの適⽤をデフォルトで使⽤していること
+ クライアントサイドの適⽤は manager が "kubectl-client-side-apply", operation が "Update"
+ Flux2 が "ユーザ" として SSA してくれてもユーザがクライアントサイドの適⽤を使ったら
同じユーザにならない
+ すべての⼈間が常に kubectl apply に --server-side オプションをつけるのは困難
現実的には⼈間が変更を kubectl apply で適⽤したら、あとで変更前の状態で
適⽤し直しておくくらいしかできない。しかし⼈間は忘れるのでむずかしい。
25
27. @superbrothers
!
まとめ
▶ metadata.manageFields は Server Side Apply(SSA)でどのユーザまたはコントローラが
オブジェクトのどのフィールドを所有しているのかの管理に使われる
+ SSA は Kubernetes v1.22 で GA となり、利⽤が広がっているが、
いちユーザが kubectl apply で積極的に SSA を使う必要はない
▶ kubectl v1.21 からデフォルトで出⼒されなくなったけど、いなくなったわけじゃない
▶ managedFields は Kubernetes が管理しているので"基本的に"直接書き換えたりしてはいけない
▶ SSA における metadata.managedFields を使ったフィールド管理
+ 1⼈のマネージャが所有している場合と複数で共同所有している場合がある
+ 所有するフィールドが削除されたマニフェストを適⽤することでマネージャは所有権を放棄する
▶ SSA で複数のマネージャが同じフィールドを更新しようとするとコンフリクトする
27
28. 機械学習プラットフォームエンジニア
We're hiring! https://www.preferred.jp/ja/careers/
⼤規模計算基盤エンジニア
▶ ⼤規模な計算基盤の実現に関する企画、設計および研究開発
+ CPU/GPU/MN-Coreを組み合わせた
ドメイン最適化された計算基盤の企画・設計
+ クラスタ型計算機の設計
+ 規模性の⾼い計算機を⽀えるインターコネクトネットワーク
およびデータセンタ規模ネットワーク技術
+ 規模性の⾼い計算機を⽀えるストレージ階層、
ストレージシステム
▶ 規模性の⾼い計算機を⽀える技術の研究開発
+ エネルギー効率の良い⼤規模計算機システム
+ ⾼い電⼒密度をもつ⾼性能計算機の構成技術
+ ⾼い熱密度をもつ⾼性能計算機の構成技術
+ スケーラブルな計算基盤の監視・管理技術
+ 管理運⽤しやすい⼤規模計算システム
▶ ⼤規模なクラスタ計算機の継続的な性能改善
+ 物理的なシステムメトリクス収集とそれを⽤いた
既存システムの改善、新規設計へのフィードバック
▶ ⾃由度・拡張性・使いやすさのトレードオフが取れた⼤規模機械学
習プラットフォームの機能設計と開発
+ 例: 機械学習ワークフローツール、実験管理ツール、
GPUやMN-Core向け統合開発環境の構築
▶ ⼤規模機械学習プラットフォームの運⽤と運⽤改善(⾃動化等)
+ 例: ⾃動サーバプロビジョニング、パブリッククラウド連携に
よる運⽤効率化、インフラ健全性の⾃動診断と保守省⼒化
▶ ⼤規模機械学習プラットフォーム上での計算資源
(GPU, MN-Coreを含む)配分の最適化
+ 例: Kubernetes Schedulerの機能拡張、
リソース利⽤量制限拡張の開発
▶ 最先端の分散計算基盤技術の Proof of Concept 構築及び
プラットフォームでの実⽤化
+ 例: Kubernetes上での分散強化学習実⾏ツール
30. @superbrothers
!
Appendix
▶ Server-Side Apply | Kubernetes
+ https://kubernetes.io/docs/reference/using-api/server-side-apply/
▶ KEP 555 - Apply
+ https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/555-server-side-apply
▶ Kubernetes 1.21: SIG-CLI (kubectl) 変更内容 - Qiita
+ https://qiita.com/superbrothers/items/afeea65db4f3d4d1c5ef
▶ Enable kubectl-get to strip managed
fi
elds by knight42 · Pull Request #96878 · kubernetes/kubernetes
+ https://github.com/kubernetes/kubernetes/pull/96878
▶ Kubernetes 1.14: Server-side Apply (alpha) - Qiita
+ https://qiita.com/superbrothers/items/aeba9406691388b6a19e
▶ Kubernetes: kubectl apply の動作 - Qiita
+ https://qiita.com/tkusumi/items/0bf5417c865ef716b221
▶ Server-side reconciliation is coming | Flux
+ https://
fl
uxcd.io/blog/2021/09/server-side-reconciliation-is-coming/
▶ https://github.com/superbrothers-sandbox/kubernetes-meetup-tokyo-48-metadata-managedFields
30