Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Go design theory learned from Kubernetes
Search
Takamichi Omori
April 24, 2021
Programming
3.6k
9
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Go design theory learned from Kubernetes
Takamichi Omori
April 24, 2021
More Decks by Takamichi Omori
See All by Takamichi Omori
小さい仕事をするLLMと精度検証
onsd
3
3.2k
AI-UXを実現する請求書自動分割の裏側
onsd
0
330
pprof で見つけた OOM の真相 #layerxgo
onsd
0
630
プロダクトライフサイクルに合わせた 「技術選定」の実践
onsd
1
580
kubefork - development experience like owning your own cluster
onsd
1
1.8k
Other Decks in Programming
See All in Programming
継続モナドとリアクティブプログラミング
yukikurage
3
410
Vite+ Unified Toolchain for the Web
naokihaba
0
700
コーディングルールの鮮度を保ちたい for SRE NEXT 2026 / keep-fresh-go-internal-conventions-sre-next-2026
handlename
0
120
その問い、本当に正しいですか?AI時代のエンジニアに必要な哲学と認知科学 / ai-philosophy-cognitive-science
minodriven
14
6.7k
SREは、MCPとSRE Agentをこう使え!
kazumax55
0
150
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
0
140
Dataformのリポジトリを立ち上げるときにまずやること / dataform-day0-2026
snhryt
0
210
エンジニアにデザインハーネスを 〜デザインプロセスを規定するためのハーネス〜 / Design harness from an engineer's perspective
rkaga
2
1k
霧の中の代数的エフェクト
funnyycat
1
280
「正の参照」と 「負の導出」で組む ハーネスエンジニアリング
cottpan
1
120
ADKを使って簡単にAIエージェントを作ってみよう
k1mu21
0
290
Contextとはなにか
chiroruxx
1
390
Featured
See All Featured
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
260
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.7k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
A Soul's Torment
seathinner
6
3k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
260
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
250
The Art of Programming - Codeland 2020
erikaheidi
57
14k
GraphQLとの向き合い方2022年版
quramy
50
15k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
600
Done Done
chrislema
186
16k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
Transcript
©2021 Wantedly, Inc. Kubernetes ͔ΒֶΜͩ Go ͷઃܭ (P$POGFSFODF4QSJOH 0OMJOF
"QS 5BLBNJDIJ0NPSJ!POTE@
©2021 Wantedly, Inc. Takamichi Omori @onsd_ DX Squad Intern, Wantedly,
Inc. Love Kubernetes, Go, etc *BN 2 https://www.wantedly.com/id/onsd_
©2021 Wantedly, Inc. /42 8BOUFEMZͱ(P ຊ൪ͷ(P ύϑΥʔϚϯε͕༏ઌ͞ΕΔͱ͜Ζ ௨ཧͳͲͷج൫ Kubernetes ؔ࿈
CLIπʔϧ 3
©2021 Wantedly, Inc. /42 %94RVBEͱʁ %FWFMPQFSF9QFSJFODF4RVBE https://event.cloudnativedays.jp/cndo2021/talks/281 ٕज़ج൫νʔϜͱհ͞ΕΔ͜ͱଟ͍Ͱ͢ ະདྷͷ։ൃମݧΛͭ͘Δ ։ൃऀͷੜ࢈ੑΛ্ͤ͞ΔͨΊʹԿͰ͍ͬͯ͘νʔϜ
৽͍͠ Microservice ͷ։ൃମݧ ෳࡶͳMicroservice Ͱ։ൃ͕؆୯ʹߦ͑ΔΑ͏ͳΈ࡞Γ ৽͍͠։ൃମݧ ʹ͍ͭͯৄ͘͠ 4
©2021 Wantedly, Inc. /42 ࠓ͢͜ͱ ,VCFSOFUFT͔ΒֶΜͩ(Pͷઃܭ 5 ࣮ྫɿCustom Controller ͷ࣮͔ΒֶΜͩઃܭ
• Package Λ͚ͯॲཧΛΘ͔Γ͘͢͢Δํ๏ • εφοϓγϣοτςετʹ͍ͭͯ
©2021 Wantedly, Inc. $VTUPN$POUSPMMFSͱ Photo by NeONBRAND on Unsplash 6
©2021 Wantedly, Inc. /42 $VTUPN$POUSPMMFSͱ ,VCFSOFUFTΛ֦ு͢ΔΈͷҰͭ https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ 7 Kubernetes ʹ
Deployment, Service ͷΑ͏ʹͨ͘͞ΜͷϦιʔε͕ଘࡏ͢Δ Custom Controller ɺಠࣗʹઃܭͨ͠ϦιʔεΛίϯτϩʔϧ͢ΔͨΊͷΞϓϦέʔγϣϯ
©2021 Wantedly, Inc. ࡐͱ͢Δ Custom Controller ͷಛ Photo by Nikolai
Chernichenko on Unsplash 8
©2021 Wantedly, Inc. /42 ࡐͱ͢Δ$VTUPN$POUSPMMFSͷಛ πϦʔߏʹͳ͍ͬͯΔ 9 ͔ΒෳͷϦιʔε͕Ͱ͖Δ
©2021 Wantedly, Inc. /42 ࡐͱ͢Δ$VTUPN$POUSPMMFSͷಛ ϦιʔεҎ֎͔ΒӨڹΛड͚ΔϦιʔε͕͋Δ ผϦιʔε͕มߋ͞Εͨͱ͖ʹࢠϦιʔεΛมߋ͢Δ controller Λผʹ࡞Δඞཁ͕͋Δ 10
©2021 Wantedly, Inc. ෳࡶͳ controller ϨΠϠʔΛ͚Α͏ Photo by Hasan
Almasi on Unsplash 11
©2021 Wantedly, Inc. /42 3FDPODJMF 3FDPODJMF ͋ΔϦιʔεͷঢ়ଶ͔ΒΫϥελͷঢ়ଶΛߋ৽͢Δॲཧ Kubebuilder Λ͍ͬͯΔ߹ɺ
ඞཁͳϦιʔεΛ࡞͢ΔॲཧΛReconcile ʹॻ͘ 12
©2021 Wantedly, Inc. /42 ૉʹॻ͍͍ͯͬͨ߹ 3FDPODJMFʹͯ͢Λॻ͘ੈք 1. ཧతͳϦιʔεͷঢ়ଶΛܭࢉ 2. ͕ࠩ͋Δ߹ߋ৽
3. ඞཁ͕ͳ͘ͳͬͨϦιʔε͕͋Δ߹ফ͢ ࠓճͷྫͩͱɺෳͷϦιʔεΛ࡞ɾߋ৽ɾআ ͢Δඞཁ͕͋ͬͨ 13
©2021 Wantedly, Inc. /42 ࡐͱ͢Δ$VTUPN$POUSPMMFSͷಛ ϦιʔεҎ֎͔ΒӨڹΛड͚ΔϦιʔε͕͋Δ ผϦιʔε͕มߋ͞Εͨͱ͖ʹࢠϦιʔεΛมߋ͢Δ controller Λผʹ࡞Δඞཁ͕͋Δ 14
©2021 Wantedly, Inc. /42 ෳͷDPOUSPMMFSΛؚΉ߹ͷ 3FDPODJMFʹͯ͢Λॻ͘ ෳͷController ͔Β ߋ৽͞ΕΔϦιʔε͕͋Δ
Reconciler ʹॲཧΛॻ͘ͱɺ ಉ͡ॲཧ͕ෳͷՕॴͰॏෳͯ͠͠·͏ 15
©2021 Wantedly, Inc. /42 6QEBUFSͷಋೖ 6QEBUFS ಛఆͷϦιʔεΛ࡞ɾߋ৽ɾআ͢ΔྲྀΕΛ·ͱΊͯ Updaterͱ࣮ͯ͢͠Δ Controller
ʹॻ͍ͨ߹ͱൺͯɺॲཧͷڞ௨Խ ͕ਤΕΔ 16
©2021 Wantedly, Inc. /42 6QEBUFSͷJOUFSGBDF 6QEBUFS 17 // type NamespacedName
struct { / / Namespace strin g / / Name strin g // } type Updater interface { Update(ctx context.Context, slug types.NamespacedName) erro r / / ListOption is used specify namespac e UpdateAll(ctx context.Context, opts ...client.ListOption) erro r }
©2021 Wantedly, Inc. /42 6QEBUFS͕શͯͷॲཧΛߦ͏ͱ͖ͷ ͯ͢ͷ݅Λཏ͢Δͷ͕େม ӈͷྫͩͱɺআ͢Δॲཧ·ͰUpdaterͰ͍ͬͯΔɻ - আ͢Δ݅ -
ԿΛͲ͜·Ͱফ͍͍ͯ͠ͷ͔ ͳͲ͕Θ͔ΓͮΒ͘ͳΓɺ࣮͕େมʹͳΔɻ 18
©2021 Wantedly, Inc. /42 3FGSFTIFSͷಋೖ 3FGSFTIFS ཧతͳϦιʔεͷঢ়ଶ͕͞ΕΔͱɺΫϥελ্ͷ Ϧιʔε͕ཧతͳঢ়ଶʹͳΔΑ͏ʹ
Ճɾߋ৽ɾআΛߦ͏ϢʔςΟϦςΟϥΠϒϥϦ 19
©2021 Wantedly, Inc. /42 3FGSFTIFSͷJOUFSGBDF 3FGSFTIFS 20 ࣮ࡍϨΠϠʔͱ͍͏ΑΓϥΠϒϥϦ // util.Object
represents Kubernetes Resourc e type Refresher interface { Refresh(ctx context.Context , parent util.Object, children []util.Object) erro r }
©2021 Wantedly, Inc. /42 3FGSFTIFS͕͋ΔͱԿ͕خ͍͠ͷ͔ ͷ؆ུԽ ཧঢ়ଶΛड͚औΓɺෆཁͳϦιʔεআ͢Δ RefresherΛಋೖ͢Δ͜ͱͰ UpdaterΛ࣮͢Δࡍʹඞཁͳͷɺཧతͳ
ϦιʔεͷϦετΛ࡞Δॲཧ͚ͩʹͳͬͨ 21 ॲཧͷڞ௨Խ Ϧιʔεʹࢠ͕ؔ͋Δ߹ɺRefresherΛ ͏͜ͱͰॲཧͷڞ௨Խ͕Ͱ͖Δ
©2021 Wantedly, Inc. /42 3FGSFTIFS͕ݱঢ়Λཧʹ͚ۙͮΔํ๏ আ͢ΔϦιʔεͷಛఆ Refresher ɺϦιʔεͱཧతͳࢠϦιʔεͷ ϦετΛड͚औΔ
Ϧιʔε͔Β͢Ͱʹଘࡏ͢ΔࢠϦιʔεΛಛఆ͠ɺ ड͚औͬͨϦιʔεͱൺֱ͢Δ͜ͱͰআ͢Δ͖ ϦιʔεΛಛఆͰ͖Δ ࢠؔͷ੍ ͋ΔϦιʔεඞͣϦιʔεΛ࣋ͭͱ͍͏੍ 22
©2021 Wantedly, Inc. /42 ,VCFSOFUFT্ͰࢠؔΛࣔ͢ํ๏ 0XOFS3FGFSFODF 23 Ϧιʔεʹ͍ͭͯɺͦͷΦʔφʔϦιʔεΛࣔ͢ϑΟʔϧυ OwnerReference ͷϝϦοτ
Owner ͕ফ͑ͨͱ͖ʹGC ͕ࢠϦιʔεΛফͯ͘͠ΕΔ πϦʔߏΛ࣋ͭϦιʔεΛཧ͢Δͱ͖͚͓ͭͯ͘ͱศར
©2021 Wantedly, Inc. /42 #VJMEFSͷಋೖ #VJMEFS • ͋ΔϦιʔεʹ͍ͭͯɺཧతͳঢ়ଶΛܭࢉ͢Δ • ܭࢉͨ݁͠ՌΛRefresherʹΘͨ͢
24
©2021 Wantedly, Inc. /42 #VJMEFSͷJOUFSGBDF #VJMEFS • ͋ΔϦιʔεʹ͍ͭͯɺཧతͳঢ়ଶΛܭࢉ͢Δ • ܭࢉͨ݁͠ՌΛRefresherʹΘͨ͢
25 // util.Object represents Kubernetes Resourc e type Builder interface { Build(ctx context.Context) ([]util.Object, error ) }
©2021 Wantedly, Inc. /42 ϨΠϠʔ͚ͷ·ͱΊ Updater Builder Refresher ͋ΔϦιʔεʹ͍ͭͯͷॲཧΛ·ͱΊΔ ͋ΔϦιʔεʹ͍ͭͯɺཧతͳঢ়ଶΛͭ͘Δ
Builder͕͢Ϧετʹଇͬͯ ཧతͳঢ়ଶΛ࣮ݱ͢ΔϥΠϒϥϦ 26
©2021 Wantedly, Inc. /42 ϨΠϠʔ͚ͷ۩ମྫ 27 // type virtualServiceUpdater struct
{ // client client.Clien t // log logr.Logge r // scheme *runtime.Schem e // } func (r virtualServiceUpdater) Update(ctx context.Context, serviceSlug types.NamespacedName) error { service := &corev1.Service{ } if err := r.client.Get(ctx, serviceSlug, service); err != nil { return errors.WithStack(err ) } objList, err := lister. NewVirtualServiceBuilder(r.client, serviceSlug).Build(ctx ) if err != nil { return errors.WithStack(err ) } ref := refresh.New(r.client, r.scheme ) if err := ref.Refresh(ctx, service, objList); err != nil { return errors.WithStack(err ) } return ni l }
©2021 Wantedly, Inc. /42 VirtualServiceUpdater ͋Δ service ʹඥͮ͘ virtualService
Λ࡞͢Δ Updater ϨΠϠʔ͚ͷ۩ମྫ 28 // type virtualServiceUpdater struct { // client client.Clien t // log logr.Logge r // scheme *runtime.Schem e // } func (r virtualServiceUpdater) Update(ctx context.Context, serviceSlug types.NamespacedName) error { service := &corev1.Service{ } if err := r.client.Get(ctx, serviceSlug, service); err != nil { return errors.WithStack(err ) } objList, err := lister. NewVirtualServiceBuilder(r.client, serviceSlug).Build(ctx ) if err != nil { return errors.WithStack(err ) } ref := refresh.New(r.client, r.scheme ) if err := ref.Refresh(ctx, service, objList); err != nil { return errors.WithStack(err ) } return ni l }
©2021 Wantedly, Inc. /42 VirtualServiceUpdater ͋Δ service ʹඥͮ͘ virtualService
Λ࡞͢Δ Updater ϨΠϠʔ͚ͷ۩ମྫ 29 // type virtualServiceUpdater struct { // client client.Clien t // log logr.Logge r // scheme *runtime.Schem e // } func (r virtualServiceUpdater) Update(ctx context.Context, serviceSlug types.NamespacedName) error { service := &corev1.Service{ } if err := r.client.Get(ctx, serviceSlug, service); err != nil { return errors.WithStack(err ) } objList, err := lister. NewVirtualServiceBuilder(r.client, serviceSlug).Build(ctx ) if err != nil { return errors.WithStack(err ) } ref := refresh.New(r.client, r.scheme ) if err := ref.Refresh(ctx, service, objList); err != nil { return errors.WithStack(err ) } return ni l } VirtualServiceBuilder VirtualServiceʹ͍ͭͯɺ ཧతͳঢ়ଶΛ࡞Δ Builder
©2021 Wantedly, Inc. /42 VirtualServiceUpdater ͋Δ service ʹඥͮ͘ virtualService
Λ࡞͢Δ Updater ϨΠϠʔ͚ͷ۩ମྫ 30 // type virtualServiceUpdater struct { // client client.Clien t // log logr.Logge r // scheme *runtime.Schem e // } func (r virtualServiceUpdater) Update(ctx context.Context, serviceSlug types.NamespacedName) error { service := &corev1.Service{ } if err := r.client.Get(ctx, serviceSlug, service); err != nil { return errors.WithStack(err ) } objList, err := lister. NewVirtualServiceBuilder(r.client, serviceSlug).Build(ctx ) if err != nil { return errors.WithStack(err ) } ref := refresh.New(r.client, r.scheme ) if err := ref.Refresh(ctx, service, objList); err != nil { return errors.WithStack(err ) } return ni l } VirtualServiceBuilder VirtualServiceʹ͍ͭͯɺ ཧతͳঢ়ଶΛ࡞Δ Builder Refresher ϦιʔεͷϦετΛड͚औΓ Ϋϥελͷঢ়ଶΛ߹ΘͤΔ
©2021 Wantedly, Inc. /42 ϨΠϠʔ͚ͷ۩ମྫ 31 // type virtualServiceUpdater struct
{ // client client.Clien t // log logr.Logge r // scheme *runtime.Schem e // } func (r virtualServiceUpdater) Update(ctx context.Context, serviceSlug types.NamespacedName) error { service := &corev1.Service{ } if err := r.client.Get(ctx, serviceSlug, service); err != nil { return errors.WithStack(err ) } objList, err := lister. NewVirtualServiceBuilder(r.client, serviceSlug).Build(ctx ) if err != nil { return errors.WithStack(err ) } ref := refresh.New(r.client, r.scheme ) if err := ref.Refresh(ctx, service, objList); err != nil { return errors.WithStack(err ) } return ni l } VirtualServiceUpdater ͋Δ service ʹඥͮ͘ virtualService Λ࡞͢Δ Updater VirtualServiceBuilder VirtualServiceʹ͍ͭͯɺ ཧతͳঢ়ଶΛ࡞Δ Builder Refresher ϦιʔεͷϦετΛड͚औΓ Ϋϥελͷঢ়ଶΛ߹ΘͤΔ
©2021 Wantedly, Inc. ಈ࡞֬ೝͱςετͷॻ͖ํ 32
©2021 Wantedly, Inc. /42 ςετͷత ςετͰ͔֬Ί͍ͨ͜ͱʁ దͳKubernetesͷObject͕࡞͞ΕΔ͔Ͳ͏͔ • Builder •
͋ΔϦιʔε͕ଘࡏ͍ͯ͠Δͱ͖ʹɺదͳϦιʔε͕࡞͞ΕΔ͔͔֬Ί͍ͨ • Refresher • ͋ΔϦιʔε͕ଘࡏ͍ͯ͠Δͱ͖ʹɺड͚औͬͨϦιʔεͰΫϥελͷঢ়ଶΛมߋ͍ͨ͠ • มߋ͞ΕͨΫϥελͷঢ়ଶ͕ཧతͰ͋Δ͔͔֬Ί͍ͨ 33
©2021 Wantedly, Inc. /42 4OBQTIPUςετ $VQBMPZΛͬͨTOBQTIPUςετ • Kubernetes ͷ Object
List ͷ snapshot ΛࡱΓɺ yaml ͱͯ͠อଘ͢Δ • Yaml ͷࠩ github ্Ͱมߋ͕Θ͔Γ͍͢ͷͰɺReview͍͢͠ Controller ʹมߋΛՃ͑Δͱ͖ 1. ݱঢ়ͷڍಈΛอଘ͢Δ 2. มߋΛՃ͑ɺεφοϓγϣοτΛߋ৽͢Δ • ఆ͍ͯ͠ΔڍಈΛ͍ͯ͠Δ͔Ͳ͏͔Λ͔֬ΊΔ https://github.com/bradleyjkemp/cupaloy 34
©2021 Wantedly, Inc. /42 4OBQTIPUςετ $VQBMPZΛͬͨTOBQTIPUςετ • Kubernetes ͷ Object
List ͷ snapshot ΛࡱΓɺ yaml ͱͯ͠อଘ͢Δ • Yaml ͷࠩ github ্Ͱมߋ͕Θ͔Γ͍͢ͷͰɺReview͍͢͠ Controller ʹมߋΛՃ͑Δͱ͖ 1. ςετ͕ͳ͚ΕՃ • ݱঢ়ͷڍಈΛอଘ͓ͯ͘͠ 2. มߋΛՃ͑ɺςετ͢Δ • ఆ͍ͯ͠ΔڍಈΛ͍ͯ͠Δ͔Ͳ͏͔Λ͔֬ΊΔ https://github.com/bradleyjkemp/cupaloy 35
©2021 Wantedly, Inc. /42 6QEBUFSʹ͓͚Δ4OBQTIPUςετͷྫ 36 t.Run(testcase.name, func(t *testing.T) {
existingResources := testcase.initialStat e clnt := fake.NewFakeClientWithScheme(scheme, existingResources... ) up := updater.NewVirtualServiceUpdater(clnt, ctrl.Log, scheme ) ctx := context.Background( ) err := up.UpdateAll(ctx, &client.ListOptions{Namespace: "some-namespace"} ) if err != nil { t.Fatal(err ) } vsl := &istio.VirtualServiceList{ } err = clnt.List(ctx, vsl, &client.ListOptions{Namespace: "some-namespace"} ) if err != nil { t.Fatal(err ) } ut.SnapshotYaml(t, vsl ) })
©2021 Wantedly, Inc. /42 6QEBUFSʹ͓͚Δ4OBQTIPUςετͷྫ 37 t.Run(tc.name, func(t *testing.T) {
existingResources := tc.initialStat e clnt := fake.NewFakeClientWithScheme(scheme, existingResources... ) up := updater.NewVirtualServiceUpdater(clnt, ctrl.Log, scheme ) ctx := context.Background( ) err := up.UpdateAll(ctx, &client.ListOptions{Namespace: "some-namespace"} ) if err != nil { t.Fatal(err ) } vsl := &istio.VirtualServiceList{ } err = clnt.List(ctx, vsl, &client.ListOptions{Namespace: "some-namespace"} ) if err != nil { t.Fatal(err ) } ut.SnapshotYaml(t, vsl ) } ) ςετͷͨΊͷઃఆ
©2021 Wantedly, Inc. /42 6QEBUFSʹ͓͚Δ4OBQTIPUςετͷྫ 38 t.Run(tc.name, func(t *testing.T) {
existingResources := tc.initialStat e clnt := fake.NewFakeClientWithScheme(scheme, existingResources... ) up := updater.NewVirtualServiceUpdater(clnt, ctrl.Log, scheme ) ctx := context.Background() err := up.UpdateAll(ctx, &client.ListOptions{Namespace: "some-namespace"} ) if err != nil { t.Fatal(err ) } vsl := &istio.VirtualServiceList{ } err = clnt.List(ctx, vsl, &client.ListOptions{Namespace: "some-namespace"} ) if err != nil { t.Fatal(err ) } ut.SnapshotYaml(t, vsl ) } ) ςετͷͨΊͷઃఆ ؔΛ࣮ߦ
©2021 Wantedly, Inc. /42 6QEBUFSʹ͓͚Δ4OBQTIPUςετͷྫ 39 t.Run(tc.name, func(t *testing.T) {
existingResources := tc.initialStat e clnt := fake.NewFakeClientWithScheme(scheme, existingResources... ) up := updater.NewVirtualServiceUpdater(clnt, ctrl.Log, scheme ) ctx := context.Background( ) err := up.UpdateAll(ctx, &client.ListOptions{Namespace: "some-namespace"} ) if err != nil { t.Fatal(err ) } vsl := &istio.VirtualServiceList{ } err = clnt.List(ctx, vsl, &client.ListOptions{Namespace: "some-namespace"} ) if err != nil { t.Fatal(err ) } ut.SnapshotYaml(t, vsl ) } ) ςετͷͨΊͷઃఆ ؔΛ࣮ߦ ݁ՌΛऔಘ
©2021 Wantedly, Inc. /42 6QEBUFSʹ͓͚Δ4OBQTIPUςετͷྫ 40 t.Run(tc.name, func(t *testing.T) {
existingResources := tc.initialStat e clnt := fake.NewFakeClientWithScheme(scheme, existingResources... ) up := updater.NewVirtualServiceUpdater(clnt, ctrl.Log, scheme ) ctx := context.Background( ) err := up.UpdateAll(ctx, &client.ListOptions{Namespace: "some-namespace"} ) if err != nil { t.Fatal(err ) } vsl := &istio.VirtualServiceList{ } err = clnt.List(ctx, vsl, &client.ListOptions{Namespace: "some-namespace"} ) if err != nil { t.Fatal(err ) } ut.SnapshotYaml(t, vsl) // make objectList to string and take snapsho t } ) ςετͷͨΊͷઃఆ ؔΛ࣮ߦ ݁ՌΛऔಘ औಘͨ݁͠ՌΛอଘ
©2021 Wantedly, Inc. /42 4OBQTIPUςετͷϝϦοτɾσϝϦοτ ˓ؾܰʹςετ͕Ͱ͖Δ มߋ͢ΔՕॴͷϦετΛऔಘͯ͠อଘ͢Δ͚ͩ ·ͨɺऔಘͷॲཧ͕͔͔࣌ؒΒͳ͍ͷͰಋೖ͍͢͠ ✕4OBQTIPU͕େྔʹอଘ͞ΕΔ
ཏతʹ͢Δͱsnapshot ͕େྔʹͳͬͯ PR ͕ٯʹݟͮΒ͘ͳΔ ఆ֎ͷͱ͜Ζʹ diff ͕ग़Δͱఆ͕͘͠ͳΔ ˓ͲΜͲΜ࣮͍͚ͯ͠Δ ؾܰʹςετ͕Ͱ͖ΔͷͰͲΜͲΜ࣮͍ͯ͘͠ϑΣʔζʹ͍͍ͯΔ ༷͕มΘͬͨͱ͖ʹ snapshot ʹ͕ࠩͰΔͷͰΘ͔Γ͍͢ 41
©2021 Wantedly, Inc. /42 42 Kubernetes ͔ΒֶΜͩ Go ͷઃܭ ෳࡶͳ؆୯ͳʹΓग़ͦ͏
Custom Controller Λ࡞Δ্Ͱ໘͕ͪ͠ͳͱͦͷղܾ ΄͍͠Ϧιʔεͷ࡞ͱΫϥελͷঢ়ଶͷߋ৽ΛΘ͚Δͱ͏·͍͘͘ దͳ package ͚Γେࣄ Wantedly Ͱ Go ΘΕ͍ͯ·͢ ϓϩμΫγϣϯͷΞϓϦέʔγϣϯ͔Βɺࣾπʔϧ·Ͱ ·ͱΊ ॲཧΛ࠶ར༻Ͱ͖Δ͘͠ΈΛͭ͘Ζ͏