Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go design theory learned from Kubernetes

Go design theory learned from Kubernetes

F458220c21b5a3508485f7eddaa26cca?s=128

Takamichi Omori

April 24, 2021
Tweet

Transcript

  1. ©2021 Wantedly, Inc. Kubernetes ͔ΒֶΜͩ 
 Go ͷઃܭ࿦ (P$POGFSFODF4QSJOH 0OMJOF

    "QS 5BLBNJDIJ0NPSJ!POTE@
  2. ©2021 Wantedly, Inc. Takamichi Omori @onsd_ DX Squad Intern, Wantedly,

    Inc. Love Kubernetes, Go, etc *BN 2 https://www.wantedly.com/id/onsd_
  3. ©2021 Wantedly, Inc. /42 8BOUFEMZͱ(P ຊ൪ͷ͸(P ύϑΥʔϚϯε͕༏ઌ͞ΕΔͱ͜Ζ ௨஌؅ཧͳͲͷج൫ Kubernetes ؔ࿈

    CLIπʔϧ 3
  4. ©2021 Wantedly, Inc. /42 %94RVBEͱ͸ʁ %FWFMPQFSF9QFSJFODF4RVBE https://event.cloudnativedays.jp/cndo2021/talks/281 ٕज़ج൫νʔϜͱ঺հ͞ΕΔ͜ͱ΋ଟ͍Ͱ͢ ະདྷͷ։ൃମݧΛͭ͘Δ ։ൃऀͷੜ࢈ੑΛ޲্ͤ͞ΔͨΊʹ͸ԿͰ΋΍͍ͬͯ͘νʔϜ

    ৽͍͠ Microservice ͷ։ൃମݧ ෳࡶͳMicroservice Ͱ΋։ൃ͕؆୯ʹߦ͑ΔΑ͏ͳ࢓૊Έ࡞Γ ৽͍͠։ൃମݧ ʹ͍ͭͯৄ͘͠͸ 4
  5. ©2021 Wantedly, Inc. /42 ࠓ೔࿩͢͜ͱ ,VCFSOFUFT͔ΒֶΜͩ(Pͷઃܭ࿦ 5 ࣮ྫɿCustom Controller ͷ࣮૷͔ΒֶΜͩઃܭ࿦

    • Package Λ෼͚ͯॲཧΛΘ͔Γ΍͘͢͢Δํ๏ • εφοϓγϣοτςετʹ͍ͭͯ
  6. ©2021 Wantedly, Inc. $VTUPN$POUSPMMFSͱ͸ Photo by NeONBRAND on Unsplash 6

  7. ©2021 Wantedly, Inc. /42 $VTUPN$POUSPMMFSͱ͸ ,VCFSOFUFTΛ֦ு͢Δ࢓૊ΈͷҰͭ https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ 7 Kubernetes ʹ͸

    Deployment, Service ͷΑ͏ʹͨ͘͞ΜͷϦιʔε͕ଘࡏ͢Δ Custom Controller ͸ɺಠࣗʹઃܭͨ͠ϦιʔεΛίϯτϩʔϧ͢ΔͨΊͷΞϓϦέʔγϣϯ
  8. ©2021 Wantedly, Inc. ୊ࡐͱ͢Δ Custom Controller ͷಛ௃ Photo by Nikolai

    Chernichenko on Unsplash 8
  9. ©2021 Wantedly, Inc. /42 ୊ࡐͱ͢Δ$VTUPN$POUSPMMFSͷಛ௃ πϦʔߏ଄ʹͳ͍ͬͯΔ 9 ਌͔Βෳ਺ͷϦιʔε͕Ͱ͖Δ

  10. ©2021 Wantedly, Inc. /42 ୊ࡐͱ͢Δ$VTUPN$POUSPMMFSͷಛ௃ ਌ϦιʔεҎ֎͔ΒӨڹΛड͚ΔϦιʔε͕͋Δ ผϦιʔε͕มߋ͞Εͨͱ͖ʹࢠϦιʔεΛมߋ͢Δ controller Λผʹ࡞Δඞཁ͕͋Δ 10

  11. ©2021 Wantedly, Inc. ෳࡶͳ controller ͸ ϨΠϠʔΛ෼͚Α͏ Photo by Hasan

    Almasi on Unsplash 11
  12. ©2021 Wantedly, Inc. /42 3FDPODJMF 3FDPODJMF ͋ΔϦιʔεͷঢ়ଶ͔ΒΫϥελͷঢ়ଶΛߋ৽͢Δॲཧ 
 Kubebuilder Λ࢖͍ͬͯΔ৔߹ɺ

    
 ඞཁͳϦιʔεΛ࡞੒͢ΔॲཧΛReconcile ʹॻ͘ 12
  13. ©2021 Wantedly, Inc. /42 ૉ௚ʹॻ͍͍ͯͬͨ৔߹ 3FDPODJMFʹ͢΂ͯΛॻ͘ੈք 1. ཧ૝తͳϦιʔεͷঢ়ଶΛܭࢉ 2. ࠩ෼͕͋Δ৔߹͸ߋ৽

    3. ඞཁ͕ͳ͘ͳͬͨϦιʔε͕͋Δ৔߹͸ফ͢ 
 ࠓճͷྫͩͱɺෳ਺ͷϦιʔεΛ࡞੒ɾߋ৽ɾ࡟আ 
 ͢Δඞཁ͕͋ͬͨ 13
  14. ©2021 Wantedly, Inc. /42 ୊ࡐͱ͢Δ$VTUPN$POUSPMMFSͷಛ௃ ਌ϦιʔεҎ֎͔ΒӨڹΛड͚ΔϦιʔε͕͋Δ ผϦιʔε͕มߋ͞Εͨͱ͖ʹࢠϦιʔεΛมߋ͢Δ controller Λผʹ࡞Δඞཁ͕͋Δ 14

  15. ©2021 Wantedly, Inc. /42 ෳ਺ͷDPOUSPMMFSΛؚΉ৔߹ͷ໰୊఺ 3FDPODJMFʹ͢΂ͯΛॻ͘ ෳ਺ͷController ͔Β 
 ߋ৽͞ΕΔϦιʔε͕͋Δ

    
 Reconciler ʹ௚઀ॲཧΛॻ͘ͱɺ 
 ಉ͡ॲཧ͕ෳ਺ͷՕॴͰॏෳͯ͠͠·͏ 15
  16. ©2021 Wantedly, Inc. /42 6QEBUFSͷಋೖ 6QEBUFS ಛఆͷϦιʔεΛ࡞੒ɾߋ৽ɾ࡟আ͢ΔྲྀΕΛ·ͱΊͯ 
 Updaterͱ࣮ͯ͠૷͢Δ Controller

    ʹ௚઀ॻ͍ͨ৔߹ͱൺ΂ͯɺॲཧͷڞ௨Խ ͕ਤΕΔ 16
  17. ©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 }
  18. ©2021 Wantedly, Inc. /42 6QEBUFS͕શͯͷॲཧΛߦ͏ͱ͖ͷ໰୊఺ ͢΂ͯͷ৚݅Λ໢ཏ͢Δͷ͕େม ӈͷྫͩͱɺ࡟আ͢Δॲཧ·ͰUpdaterͰ΍͍ͬͯΔɻ - ࡟আ͢Δ৚݅ -

    ԿΛͲ͜·Ͱফ͍͍ͯ͠ͷ͔ ͳͲ͕Θ͔ΓͮΒ͘ͳΓɺ࣮૷͕େมʹͳΔɻ 18
  19. ©2021 Wantedly, Inc. /42 3FGSFTIFSͷಋೖ 3FGSFTIFS ཧ૝తͳϦιʔεͷঢ়ଶ͕౉͞ΕΔͱɺΫϥελ্ͷ 
 Ϧιʔε͕ཧ૝తͳঢ়ଶʹͳΔΑ͏ʹ 


    ௥Ճɾߋ৽ɾ࡟আΛߦ͏ϢʔςΟϦςΟϥΠϒϥϦ 19
  20. ©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 }
  21. ©2021 Wantedly, Inc. /42 3FGSFTIFS͕͋ΔͱԿ͕خ͍͠ͷ͔ ໰୊ͷ؆ུԽ ཧ૝ঢ়ଶΛड͚औΓɺෆཁͳϦιʔε͸࡟আ͢Δ RefresherΛಋೖ͢Δ͜ͱͰ 
 UpdaterΛ࣮૷͢Δࡍʹඞཁͳͷ͸ɺཧ૝తͳ

    ϦιʔεͷϦετΛ࡞Δॲཧ͚ͩʹͳͬͨ 21 ॲཧͷڞ௨Խ Ϧιʔεʹ਌ࢠؔ܎͕͋Δ৔߹ɺRefresherΛ 
 ࢖͏͜ͱͰॲཧͷڞ௨Խ͕Ͱ͖Δ
  22. ©2021 Wantedly, Inc. /42 3FGSFTIFS͕ݱঢ়Λཧ૝ʹ͚ۙͮΔํ๏ ࡟আ͢ΔϦιʔεͷಛఆ Refresher ͸ɺ਌Ϧιʔεͱཧ૝తͳࢠϦιʔεͷ 
 ϦετΛड͚औΔ

    ਌Ϧιʔε͔Β͢Ͱʹଘࡏ͢ΔࢠϦιʔεΛಛఆ͠ɺ 
 ड͚औͬͨϦιʔεͱൺֱ͢Δ͜ͱͰ࡟আ͢Δ΂͖ 
 ϦιʔεΛಛఆͰ͖Δ ਌ࢠؔ܎ͷ੍໿ ͋ΔϦιʔε͸ඞͣ਌ϦιʔεΛ࣋ͭͱ͍͏੍໿ 22
  23. ©2021 Wantedly, Inc. /42 ,VCFSOFUFT্Ͱ਌ࢠؔ܎Λࣔ͢ํ๏ 0XOFS3FGFSFODF 23 Ϧιʔεʹ͍ͭͯɺͦͷΦʔφʔϦιʔεΛࣔ͢ϑΟʔϧυ OwnerReference ͷϝϦοτ

    Owner ͕ফ͑ͨͱ͖ʹGC ͕ࢠϦιʔεΛফͯ͘͠ΕΔ πϦʔߏ଄Λ࣋ͭϦιʔεΛ؅ཧ͢Δͱ͖͚͓ͭͯ͘ͱศར
  24. ©2021 Wantedly, Inc. /42 #VJMEFSͷಋೖ #VJMEFS • ͋ΔϦιʔεʹ͍ͭͯɺཧ૝తͳঢ়ଶΛܭࢉ͢Δ • ܭࢉͨ݁͠ՌΛRefresherʹΘͨ͢

    24
  25. ©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 ) }
  26. ©2021 Wantedly, Inc. /42 ϨΠϠʔ෼͚ͷ·ͱΊ Updater Builder Refresher ͋ΔϦιʔεʹ͍ͭͯͷॲཧΛ·ͱΊΔ ͋ΔϦιʔεʹ͍ͭͯɺཧ૝తͳঢ়ଶΛͭ͘Δ

    Builder͕౉͢Ϧετʹଇͬͯ ཧ૝తͳঢ়ଶΛ࣮ݱ͢ΔϥΠϒϥϦ 26
  27. ©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 }
  28. ©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 }
  29. ©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
  30. ©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 ϦιʔεͷϦετΛड͚औΓ 
 Ϋϥελͷঢ়ଶΛ߹ΘͤΔ
  31. ©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 ϦιʔεͷϦετΛड͚औΓ 
 Ϋϥελͷঢ়ଶΛ߹ΘͤΔ
  32. ©2021 Wantedly, Inc. ಈ࡞֬ೝͱςετͷॻ͖ํ 32

  33. ©2021 Wantedly, Inc. /42 ςετͷ໨త ςετͰ͔֬Ί͍ͨ͜ͱ͸ʁ ద੾ͳKubernetesͷObject͕࡞੒͞ΕΔ͔Ͳ͏͔ • Builder •

    ͋ΔϦιʔε͕ଘࡏ͍ͯ͠Δͱ͖ʹɺద੾ͳϦιʔε͕࡞੒͞ΕΔ͔͔֬Ί͍ͨ • Refresher • ͋ΔϦιʔε͕ଘࡏ͍ͯ͠Δͱ͖ʹɺड͚औͬͨϦιʔεͰΫϥελͷঢ়ଶΛมߋ͍ͨ͠ • มߋ͞ΕͨΫϥελͷঢ়ଶ͕ཧ૝తͰ͋Δ͔͔֬Ί͍ͨ 33
  34. ©2021 Wantedly, Inc. /42 4OBQTIPUςετ $VQBMPZΛ࢖ͬͨTOBQTIPUςετ • Kubernetes ͷ Object

    List ͷ snapshot ΛࡱΓɺ yaml ͱͯ͠อଘ͢Δ • Yaml ͷࠩ෼͸ github ্Ͱ΋มߋ͕Θ͔Γ΍͍͢ͷͰɺReview΋͠΍͍͢ Controller ʹมߋΛՃ͑Δͱ͖ 1. ݱঢ়ͷڍಈΛอଘ͢Δ 2. มߋΛՃ͑ɺεφοϓγϣοτΛߋ৽͢Δ • ૝ఆ͍ͯ͠ΔڍಈΛ͍ͯ͠Δ͔Ͳ͏͔Λ͔֬ΊΔ https://github.com/bradleyjkemp/cupaloy 34
  35. ©2021 Wantedly, Inc. /42 4OBQTIPUςετ $VQBMPZΛ࢖ͬͨTOBQTIPUςετ • Kubernetes ͷ Object

    List ͷ snapshot ΛࡱΓɺ yaml ͱͯ͠อଘ͢Δ • Yaml ͷࠩ෼͸ github ্Ͱ΋มߋ͕Θ͔Γ΍͍͢ͷͰɺReview΋͠΍͍͢ Controller ʹมߋΛՃ͑Δͱ͖ 1. ςετ͕ͳ͚Ε͹௥Ճ • ݱঢ়ͷڍಈΛอଘ͓ͯ͘͠ 2. มߋΛՃ͑ɺςετ͢Δ • ૝ఆ͍ͯ͠ΔڍಈΛ͍ͯ͠Δ͔Ͳ͏͔Λ͔֬ΊΔ https://github.com/bradleyjkemp/cupaloy 35
  36. ©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 ) })
  37. ©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 ) } ) ςετͷͨΊͷઃఆ
  38. ©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 ) } ) ςετͷͨΊͷઃఆ ؔ਺Λ࣮ߦ
  39. ©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 ) } ) ςετͷͨΊͷઃఆ ؔ਺Λ࣮ߦ ݁ՌΛऔಘ
  40. ©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 } ) ςετͷͨΊͷઃఆ ؔ਺Λ࣮ߦ ݁ՌΛऔಘ औಘͨ݁͠ՌΛอଘ
  41. ©2021 Wantedly, Inc. /42 4OBQTIPUςετͷϝϦοτɾσϝϦοτ ˓ؾܰʹςετ͕Ͱ͖Δ มߋ͢ΔՕॴͷϦετΛऔಘͯ͠อଘ͢Δ͚ͩ 
 ·ͨɺऔಘͷॲཧ΋͕͔͔࣌ؒΒͳ͍ͷͰಋೖ͸͠΍͍͢ ✕4OBQTIPU͕େྔʹอଘ͞ΕΔ

    ໢ཏతʹ͢Δͱsnapshot ͕େྔʹͳͬͯ PR ͕ٯʹݟͮΒ͘ͳΔ 
 ૝ఆ֎ͷͱ͜Ζʹ diff ͕ग़Δͱ൑ఆ͕೉͘͠ͳΔ ˓ͲΜͲΜ࣮૷͍͚ͯ͠Δ ؾܰʹςετ͕Ͱ͖ΔͷͰͲΜͲΜ࣮૷͍ͯ͘͠ϑΣʔζʹ޲͍͍ͯΔ ࢓༷͕มΘͬͨͱ͖ʹ snapshot ʹࠩ෼͕ͰΔͷͰΘ͔Γ΍͍͢ 41
  42. ©2021 Wantedly, Inc. /42 42 Kubernetes ͔ΒֶΜͩ Go ͷઃܭ࿦ ෳࡶͳ໰୊͸؆୯ͳ໰୊ʹ੾Γग़ͦ͏

    Custom Controller Λ࡞Δ্Ͱ௚໘͕ͪ͠ͳ໰୊ͱͦͷղܾ ΄͍͠Ϧιʔεͷ࡞੒ͱΫϥελͷঢ়ଶͷߋ৽ΛΘ͚Δͱ͏·͍͘͘ ద੾ͳ package ෼͚͸΍͸Γେࣄ Wantedly Ͱ͸ Go ΋࢖ΘΕ͍ͯ·͢ ϓϩμΫγϣϯͷΞϓϦέʔγϣϯ͔Βɺࣾ಺πʔϧ·Ͱ ·ͱΊ ॲཧΛ࠶ར༻Ͱ͖Δ͘͠ΈΛͭ͘Ζ͏