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
640
プロダクトライフサイクルに合わせた 「技術選定」の実践
onsd
1
580
kubefork - development experience like owning your own cluster
onsd
1
1.8k
Other Decks in Programming
See All in Programming
コーディングルールの鮮度を保ちたい for SRE NEXT 2026 / keep-fresh-go-internal-conventions-sre-next-2026
handlename
0
160
継続モナドとリアクティブプログラミング
yukikurage
3
670
AIエージェントで 変わるAndroid開発環境
takahirom
2
760
作るコストが小さくなった時代 幸せに働くために改めて考えたいこと 〜エンジニアとして価値を出し続けるために注視している二分野〜
yuppeeng
0
170
torikago - Ruby::Boxで照らすモジュラモノリスの実行境界
se4weed
1
310
5分で問診!Composer セキュリティ健康診断
codmoninc
0
780
AWS CDK を「作」ってみた 〜フルスクラッチで見えた CDK の裏側〜 / aws-cdk-from-scratch
gotok365
3
2.7k
メールのエイリアス機能を履き違えない
isshinfunada
0
200
Claude Opus 4.6以後の受託開発エンジニアの変化(Claude Code開発ノウハウ大公開スペシャルbyクラスメソッド)
iidatakuma
1
930
変わらないものが、変わるものを決める — 意図駆動開発 × イベントソーシング × イミュータブル | What Doesn't Change Decides What Can — IDD × Event Sourcing × Immutability
tomohisa
0
970
仕様駆動開発へのトライを機に チームに適合する手法を模索し続けている話
freee
PRO
0
150
全PRの83%がAIレビューだけでマージできるようになった開発組織はその後どうなったか
athug
0
1.1k
Featured
See All Featured
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
450
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
650
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
460
The untapped power of vector embeddings
frankvandijk
2
1.8k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
53k
Become a Pro
speakerdeck
PRO
31
6k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.7k
HDC tutorial
michielstock
2
760
The agentic SEO stack - context over prompts
schlessera
0
860
Paper Plane
katiecoart
PRO
2
52k
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 ΘΕ͍ͯ·͢ ϓϩμΫγϣϯͷΞϓϦέʔγϣϯ͔Βɺࣾπʔϧ·Ͱ ·ͱΊ ॲཧΛ࠶ར༻Ͱ͖Δ͘͠ΈΛͭ͘Ζ͏