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

Kubernetesオペレータのアンチパターン&ベストプラクティス

 Kubernetesオペレータのアンチパターン&ベストプラクティス

CloudNative Days Tokyo 2021の発表資料です。
https://event.cloudnativedays.jp/cndt2021/talks/1207

補足資料
https://git.io/operator-bestpractice

Akihiro Ikezoe

November 04, 2021
Tweet

More Decks by Akihiro Ikezoe

Other Decks in Programming

Transcript

  1. View Slide




  2. View Slide




  3. View Slide

  4. View Slide




  5. View Slide

  6. View Slide



  7. View Slide

  8. View Slide

  9. type Reconciler interface {
    // コントローラのReconcile処理の実装
    // 受け取ったRequestの内容に応じてリソースの作成や削除などの処理をおこなう
    // 処理の結果に応じてResultとerrorを返す
    Reconcile(context.Context, Request) (Result, error)
    }
    type Request struct {
    // コントローラが対象とするKubernetesオブジェクトのNamespaceとName
    types.NamespacedName
    }
    type Result struct {
    // コントローラにReconcileを再実行するように指示する
    Requeue bool
    // コントローラに指定した時間が経過した後にReconcileを再実行するように指示する
    RequeueAfter time.Duration
    }

    View Slide





  10. View Slide

  11. View Slide







  12. 😫

    View Slide

  13. func (r *reconciler) reconcileXxxx(ctx context.Context) error {
    result, err := ctrl.CreateOrUpdate(ctx, r.Client, res, func() error {
    // リソースの更新処理を実行
    })
    if err != nil {
    return err
    }
    if result != controllerutil.OperationResultNone {
    err = r.updateStatus()
    if err != nil {
    return err
    }
    }
    return nil
    }

    View Slide


  14. 😊

    View Slide

  15. View Slide

  16. ss, err := p.GatherStatus(ctx)
    if err != nil {
    return false, err
    }
    if err := p.updateStatus(ctx, ss); err != nil {
    return false, err
    }
    switch ss.State {
    case StateCloning:
    // 省略
    return redo, nil
    case StateRestoring:
    return false, nil
    case StateHealthy, StateDegraded:
    // 省略
    return false, nil
    case StateFailed:
    // 省略
    return true, nil

    View Slide




  17. 😫

    View Slide





  18. 😊

    View Slide

  19. _, err := ctrl.CreateOrUpdate(ctx, r.Client, certificate, func() error {
    // 省略
    }
    if err != nil {
    return ctrl.Result{}, err
    }
    secret := &corev1.Secret{}
    err = r.Get(ctx, key, secret)
    if err != nil {
    if apierrors.IsNotFound(err) {
    return ctrl.Result{
    RequeueAfter: 10 * time.Second,
    }, nil
    }
    return ctrl.Result{}, err
    }
    // 次の処理を実行

    View Slide




  20. View Slide





  21. View Slide






  22. 😫

    View Slide

  23. 😊

    View Slide



  24. View Slide





  25. View Slide



  26. View Slide




  27. View Slide




  28. 😫

    View Slide

  29. View Slide

  30. View Slide


  31. 😊

    View Slide

  32. apiVersion: v1
    kind: Pod
    metadata:
    managedFields:
    - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
    f:metadata:
    f:labels:
    f:v1.controller: {}
    manager: my-controller
    operation: Update

    View Slide

  33. svc := corev1apply.Service(svcName, mdView.Namespace).
    WithSpec(corev1apply.ServiceSpec().
    // 省略
    )
    obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(svc)
    if err != nil {
    return err
    }
    patch := &unstructured.Unstructured{
    Object: obj,
    }
    var current corev1.Service
    err = r.Get(ctx, client.ObjectKey{Namespace: mdView.Namespace, Name: svcName}, &current)
    if err != nil && !errors.IsNotFound(err) {
    return err
    }
    currentSvc, err := corev1apply.ExtractService(&current, constants.ControllerName)
    if err != nil {
    return err
    }
    if equality.Semantic.DeepEqual(svc, currentSvc) {
    return nil
    }
    err = r.Patch(ctx, patch, client.Apply, &client.PatchOptions{
    FieldManager: constants.ControllerName,
    Force: pointer.Bool(true),
    })

    View Slide



  34. 😫

    View Slide








  35. 😊

    View Slide





  36. View Slide





  37. 😫

    View Slide




  38. 😊

    View Slide





  39. View Slide





  40. View Slide


  41. View Slide