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

Go design theory learned from Kubernetes

Go design theory learned from Kubernetes

Takamichi Omori

April 24, 2021
Tweet

More Decks by Takamichi Omori

Other Decks in Programming

Transcript

  1. ©2021 Wantedly, Inc.
    Kubernetes ͔ΒֶΜͩ

    Go ͷઃܭ࿦
    (P$POGFSFODF4QSJOH 0OMJOF

    "QS 5BLBNJDIJ0NPSJ!POTE@

    View Slide

  2. ©2021 Wantedly, Inc.
    Takamichi Omori @onsd_
    DX Squad Intern, Wantedly, Inc.
    Love Kubernetes, Go, etc
    *BN
    2
    https://www.wantedly.com/id/onsd_

    View Slide

  3. ©2021 Wantedly, Inc.
    /42
    8BOUFEMZͱ(P
    ຊ൪ͷ͸(P
    ύϑΥʔϚϯε͕༏ઌ͞ΕΔͱ͜Ζ
    ௨஌؅ཧͳͲͷج൫
    Kubernetes ؔ࿈
    CLIπʔϧ
    3

    View Slide

  4. ©2021 Wantedly, Inc.
    /42
    %94RVBEͱ͸ʁ
    %FWFMPQFSF9QFSJFODF4RVBE
    https://event.cloudnativedays.jp/cndo2021/talks/281
    ٕज़ج൫νʔϜͱ঺հ͞ΕΔ͜ͱ΋ଟ͍Ͱ͢
    ະདྷͷ։ൃମݧΛͭ͘Δ
    ։ൃऀͷੜ࢈ੑΛ޲্ͤ͞ΔͨΊʹ͸ԿͰ΋΍͍ͬͯ͘νʔϜ
    ৽͍͠ Microservice ͷ։ൃମݧ
    ෳࡶͳMicroservice Ͱ΋։ൃ͕؆୯ʹߦ͑ΔΑ͏ͳ࢓૊Έ࡞Γ
    ৽͍͠։ൃମݧ ʹ͍ͭͯৄ͘͠͸
    4

    View Slide

  5. ©2021 Wantedly, Inc.
    /42
    ࠓ೔࿩͢͜ͱ
    ,VCFSOFUFT͔ΒֶΜͩ(Pͷઃܭ࿦
    5
    ࣮ྫɿCustom Controller ͷ࣮૷͔ΒֶΜͩઃܭ࿦
    • Package Λ෼͚ͯॲཧΛΘ͔Γ΍͘͢͢Δํ๏
    • εφοϓγϣοτςετʹ͍ͭͯ

    View Slide

  6. ©2021 Wantedly, Inc.
    $VTUPN$POUSPMMFSͱ͸
    Photo by NeONBRAND on Unsplash
    6

    View Slide

  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 ͸ɺಠࣗʹઃܭͨ͠ϦιʔεΛίϯτϩʔϧ͢ΔͨΊͷΞϓϦέʔγϣϯ

    View Slide

  8. ©2021 Wantedly, Inc.
    ୊ࡐͱ͢Δ Custom Controller ͷಛ௃
    Photo by Nikolai Chernichenko on Unsplash
    8

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  12. ©2021 Wantedly, Inc.
    /42
    3FDPODJMF
    3FDPODJMF
    ͋ΔϦιʔεͷঢ়ଶ͔ΒΫϥελͷঢ়ଶΛߋ৽͢Δॲཧ



    Kubebuilder Λ࢖͍ͬͯΔ৔߹ɺ

    ඞཁͳϦιʔεΛ࡞੒͢ΔॲཧΛReconcile ʹॻ͘
    12

    View Slide

  13. ©2021 Wantedly, Inc.
    /42
    ૉ௚ʹॻ͍͍ͯͬͨ৔߹
    3FDPODJMFʹ͢΂ͯΛॻ͘ੈք
    1. ཧ૝తͳϦιʔεͷঢ়ଶΛܭࢉ


    2. ࠩ෼͕͋Δ৔߹͸ߋ৽


    3. ඞཁ͕ͳ͘ͳͬͨϦιʔε͕͋Δ৔߹͸ফ͢

    ࠓճͷྫͩͱɺෳ਺ͷϦιʔεΛ࡞੒ɾߋ৽ɾ࡟আ

    ͢Δඞཁ͕͋ͬͨ
    13

    View Slide

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

    View Slide

  15. ©2021 Wantedly, Inc.
    /42
    ෳ਺ͷDPOUSPMMFSΛؚΉ৔߹ͷ໰୊఺
    3FDPODJMFʹ͢΂ͯΛॻ͘
    ෳ਺ͷController ͔Β

    ߋ৽͞ΕΔϦιʔε͕͋Δ



    Reconciler ʹ௚઀ॲཧΛॻ͘ͱɺ

    ಉ͡ॲཧ͕ෳ਺ͷՕॴͰॏෳͯ͠͠·͏
    15

    View Slide

  16. ©2021 Wantedly, Inc.
    /42
    6QEBUFSͷಋೖ
    6QEBUFS
    ಛఆͷϦιʔεΛ࡞੒ɾߋ৽ɾ࡟আ͢ΔྲྀΕΛ·ͱΊͯ

    Updaterͱ࣮ͯ͠૷͢Δ


    Controller ʹ௚઀ॻ͍ͨ৔߹ͱൺ΂ͯɺॲཧͷڞ௨Խ
    ͕ਤΕΔ


    16

    View Slide

  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

    }

    View Slide

  18. ©2021 Wantedly, Inc.
    /42
    6QEBUFS͕શͯͷॲཧΛߦ͏ͱ͖ͷ໰୊఺
    ͢΂ͯͷ৚݅Λ໢ཏ͢Δͷ͕େม
    ӈͷྫͩͱɺ࡟আ͢Δॲཧ·ͰUpdaterͰ΍͍ͬͯΔɻ


    - ࡟আ͢Δ৚݅


    - ԿΛͲ͜·Ͱফ͍͍ͯ͠ͷ͔


    ͳͲ͕Θ͔ΓͮΒ͘ͳΓɺ࣮૷͕େมʹͳΔɻ
    18

    View Slide

  19. ©2021 Wantedly, Inc.
    /42
    3FGSFTIFSͷಋೖ
    3FGSFTIFS
    ཧ૝తͳϦιʔεͷঢ়ଶ͕౉͞ΕΔͱɺΫϥελ্ͷ

    Ϧιʔε͕ཧ૝తͳঢ়ଶʹͳΔΑ͏ʹ

    ௥Ճɾߋ৽ɾ࡟আΛߦ͏ϢʔςΟϦςΟϥΠϒϥϦ


    19

    View Slide

  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

    }

    View Slide

  21. ©2021 Wantedly, Inc.
    /42
    3FGSFTIFS͕͋ΔͱԿ͕خ͍͠ͷ͔
    ໰୊ͷ؆ུԽ
    ཧ૝ঢ়ଶΛड͚औΓɺෆཁͳϦιʔε͸࡟আ͢Δ
    RefresherΛಋೖ͢Δ͜ͱͰ

    UpdaterΛ࣮૷͢Δࡍʹඞཁͳͷ͸ɺཧ૝తͳ
    ϦιʔεͷϦετΛ࡞Δॲཧ͚ͩʹͳͬͨ
    21
    ॲཧͷڞ௨Խ
    Ϧιʔεʹ਌ࢠؔ܎͕͋Δ৔߹ɺRefresherΛ

    ࢖͏͜ͱͰॲཧͷڞ௨Խ͕Ͱ͖Δ

    View Slide

  22. ©2021 Wantedly, Inc.
    /42
    3FGSFTIFS͕ݱঢ়Λཧ૝ʹ͚ۙͮΔํ๏
    ࡟আ͢ΔϦιʔεͷಛఆ
    Refresher ͸ɺ਌Ϧιʔεͱཧ૝తͳࢠϦιʔεͷ

    ϦετΛड͚औΔ


    ਌Ϧιʔε͔Β͢Ͱʹଘࡏ͢ΔࢠϦιʔεΛಛఆ͠ɺ

    ड͚औͬͨϦιʔεͱൺֱ͢Δ͜ͱͰ࡟আ͢Δ΂͖

    ϦιʔεΛಛఆͰ͖Δ
    ਌ࢠؔ܎ͷ੍໿
    ͋ΔϦιʔε͸ඞͣ਌ϦιʔεΛ࣋ͭͱ͍͏੍໿


    22

    View Slide

  23. ©2021 Wantedly, Inc.
    /42
    ,VCFSOFUFT্Ͱ਌ࢠؔ܎Λࣔ͢ํ๏
    0XOFS3FGFSFODF
    23
    Ϧιʔεʹ͍ͭͯɺͦͷΦʔφʔϦιʔεΛࣔ͢ϑΟʔϧυ
    OwnerReference ͷϝϦοτ
    Owner ͕ফ͑ͨͱ͖ʹGC ͕ࢠϦιʔεΛফͯ͘͠ΕΔ
    πϦʔߏ଄Λ࣋ͭϦιʔεΛ؅ཧ͢Δͱ͖͚͓ͭͯ͘ͱศར

    View Slide

  24. ©2021 Wantedly, Inc.
    /42
    #VJMEFSͷಋೖ
    #VJMEFS
    • ͋ΔϦιʔεʹ͍ͭͯɺཧ૝తͳঢ়ଶΛܭࢉ͢Δ


    • ܭࢉͨ݁͠ՌΛRefresherʹΘͨ͢


    24

    View Slide

  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
    )

    }

    View Slide

  26. ©2021 Wantedly, Inc.
    /42
    ϨΠϠʔ෼͚ͷ·ͱΊ
    Updater
    Builder
    Refresher
    ͋ΔϦιʔεʹ͍ͭͯͷॲཧΛ·ͱΊΔ
    ͋ΔϦιʔεʹ͍ͭͯɺཧ૝తͳঢ়ଶΛͭ͘Δ
    Builder͕౉͢Ϧετʹଇͬͯ
    ཧ૝తͳঢ়ଶΛ࣮ݱ͢ΔϥΠϒϥϦ
    26

    View Slide

  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

    }

    View Slide

  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

    }

    View Slide

  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

    View Slide

  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
    ϦιʔεͷϦετΛड͚औΓ

    Ϋϥελͷঢ়ଶΛ߹ΘͤΔ

    View Slide

  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
    ϦιʔεͷϦετΛड͚औΓ

    Ϋϥελͷঢ়ଶΛ߹ΘͤΔ

    View Slide

  32. ©2021 Wantedly, Inc.
    ಈ࡞֬ೝͱςετͷॻ͖ํ
    32

    View Slide

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


    • Builder


    • ͋ΔϦιʔε͕ଘࡏ͍ͯ͠Δͱ͖ʹɺద੾ͳϦιʔε͕࡞੒͞ΕΔ͔͔֬Ί͍ͨ


    • Refresher


    • ͋ΔϦιʔε͕ଘࡏ͍ͯ͠Δͱ͖ʹɺड͚औͬͨϦιʔεͰΫϥελͷঢ়ଶΛมߋ͍ͨ͠


    • มߋ͞ΕͨΫϥελͷঢ়ଶ͕ཧ૝తͰ͋Δ͔͔֬Ί͍ͨ


    33

    View Slide

  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

    View Slide

  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

    View Slide

  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
    )

    })

    View Slide

  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
    )

    }
    )

    ςετͷͨΊͷઃఆ

    View Slide

  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
    )

    }
    )

    ςετͷͨΊͷઃఆ
    ؔ਺Λ࣮ߦ

    View Slide

  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
    )

    }
    )

    ςετͷͨΊͷઃఆ
    ؔ਺Λ࣮ߦ
    ݁ՌΛऔಘ

    View Slide

  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

    }
    )

    ςετͷͨΊͷઃఆ
    ؔ਺Λ࣮ߦ
    ݁ՌΛऔಘ
    औಘͨ݁͠ՌΛอଘ

    View Slide

  41. ©2021 Wantedly, Inc.
    /42
    4OBQTIPUςετͷϝϦοτɾσϝϦοτ
    ˓ؾܰʹςετ͕Ͱ͖Δ
    มߋ͢ΔՕॴͷϦετΛऔಘͯ͠อଘ͢Δ͚ͩ

    ·ͨɺऔಘͷॲཧ΋͕͔͔࣌ؒΒͳ͍ͷͰಋೖ͸͠΍͍͢
    ✕4OBQTIPU͕େྔʹอଘ͞ΕΔ
    ໢ཏతʹ͢Δͱsnapshot ͕େྔʹͳͬͯ PR ͕ٯʹݟͮΒ͘ͳΔ

    ૝ఆ֎ͷͱ͜Ζʹ diff ͕ग़Δͱ൑ఆ͕೉͘͠ͳΔ
    ˓ͲΜͲΜ࣮૷͍͚ͯ͠Δ
    ؾܰʹςετ͕Ͱ͖ΔͷͰͲΜͲΜ࣮૷͍ͯ͘͠ϑΣʔζʹ޲͍͍ͯΔ


    ࢓༷͕มΘͬͨͱ͖ʹ snapshot ʹࠩ෼͕ͰΔͷͰΘ͔Γ΍͍͢
    41

    View Slide

  42. ©2021 Wantedly, Inc.
    /42
    42
    Kubernetes ͔ΒֶΜͩ Go ͷઃܭ࿦
    ෳࡶͳ໰୊͸؆୯ͳ໰୊ʹ੾Γग़ͦ͏
    Custom Controller Λ࡞Δ্Ͱ௚໘͕ͪ͠ͳ໰୊ͱͦͷղܾ
    ΄͍͠Ϧιʔεͷ࡞੒ͱΫϥελͷঢ়ଶͷߋ৽ΛΘ͚Δͱ͏·͍͘͘
    ద੾ͳ package ෼͚͸΍͸Γେࣄ
    Wantedly Ͱ͸ Go ΋࢖ΘΕ͍ͯ·͢
    ϓϩμΫγϣϯͷΞϓϦέʔγϣϯ͔Βɺࣾ಺πʔϧ·Ͱ
    ·ͱΊ
    ॲཧΛ࠶ར༻Ͱ͖Δ͘͠ΈΛͭ͘Ζ͏

    View Slide