ಗೊಲಾಂಗ್‌ನಲ್ಲಿ ಕುಬರ್ನೆಟ್ಸ್‌ಗೆ ಆಪರೇಟರ್ ಬರೆಯುವುದು

ಸೂಚನೆ. ಅನುವಾದ.: ನಿರ್ವಾಹಕರು ಕುಬರ್ನೆಟ್ಸ್‌ಗೆ ಸಹಾಯಕ ಸಾಫ್ಟ್‌ವೇರ್ ಆಗಿದ್ದು, ಕೆಲವು ಘಟನೆಗಳು ಸಂಭವಿಸಿದಾಗ ಕ್ಲಸ್ಟರ್ ವಸ್ತುಗಳ ಮೇಲೆ ದಿನನಿತ್ಯದ ಕ್ರಿಯೆಗಳ ಕಾರ್ಯಗತಗೊಳಿಸುವಿಕೆಯನ್ನು ಸ್ವಯಂಚಾಲಿತಗೊಳಿಸಲು ವಿನ್ಯಾಸಗೊಳಿಸಲಾಗಿದೆ. ನಾವು ಈಗಾಗಲೇ ಆಪರೇಟರ್‌ಗಳ ಬಗ್ಗೆ ಬರೆದಿದ್ದೇವೆ ಈ ಲೇಖನ, ಅಲ್ಲಿ ಅವರು ತಮ್ಮ ಕೆಲಸದ ಮೂಲಭೂತ ವಿಚಾರಗಳು ಮತ್ತು ತತ್ವಗಳ ಬಗ್ಗೆ ಮಾತನಾಡಿದರು. ಆದರೆ ಆ ವಸ್ತುವು ಕುಬರ್ನೆಟ್ಸ್‌ಗಾಗಿ ಸಿದ್ಧ-ತಯಾರಿಸಿದ ಘಟಕಗಳನ್ನು ನಿರ್ವಹಿಸುವ ಕಡೆಯಿಂದ ಹೆಚ್ಚಿನ ದೃಷ್ಟಿಕೋನವಾಗಿದ್ದರೆ, ಈಗ ಪ್ರಸ್ತಾಪಿಸಲಾದ ಹೊಸ ಲೇಖನದ ಅನುವಾದವು ಈಗಾಗಲೇ ಹೊಸ ಆಪರೇಟರ್‌ನ ಅನುಷ್ಠಾನದಿಂದ ಗೊಂದಲಕ್ಕೊಳಗಾದ ಡೆವಲಪರ್/ಡೆವೊಪ್ಸ್ ಎಂಜಿನಿಯರ್‌ನ ದೃಷ್ಟಿಯಾಗಿದೆ.

ಗೊಲಾಂಗ್‌ನಲ್ಲಿ ಕುಬರ್ನೆಟ್ಸ್‌ಗೆ ಆಪರೇಟರ್ ಬರೆಯುವುದು

ಕೋಡ್ ಅನ್ನು ಅಧ್ಯಯನ ಮಾಡುವ ಮೂಲಕ ಕುಬರ್ನೆಟ್ಸ್‌ಗಾಗಿ ಆಪರೇಟರ್ ಅನ್ನು ರಚಿಸುವ ದಾಖಲಾತಿಯನ್ನು ಹುಡುಕುವ ನನ್ನ ಪ್ರಯತ್ನಗಳ ನಂತರ ನಾನು ಈ ಪೋಸ್ಟ್ ಅನ್ನು ನಿಜ ಜೀವನದ ಉದಾಹರಣೆಯೊಂದಿಗೆ ಬರೆಯಲು ನಿರ್ಧರಿಸಿದೆ.

ವಿವರಿಸುವ ಉದಾಹರಣೆಯೆಂದರೆ: ನಮ್ಮ ಕುಬರ್ನೆಟ್ಸ್ ಕ್ಲಸ್ಟರ್‌ನಲ್ಲಿ, ಪ್ರತಿಯೊಂದೂ Namespace ತಂಡದ ಸ್ಯಾಂಡ್‌ಬಾಕ್ಸ್ ಪರಿಸರವನ್ನು ಪ್ರತಿನಿಧಿಸುತ್ತದೆ, ಮತ್ತು ತಂಡಗಳು ತಮ್ಮ ಸ್ವಂತ ಸ್ಯಾಂಡ್‌ಬಾಕ್ಸ್‌ಗಳಲ್ಲಿ ಮಾತ್ರ ಆಡುವಂತೆ ನಾವು ಅವರಿಗೆ ಪ್ರವೇಶವನ್ನು ಮಿತಿಗೊಳಿಸಲು ಬಯಸುತ್ತೇವೆ.

ಬಳಕೆದಾರರನ್ನು ಹೊಂದಿರುವ ಗುಂಪನ್ನು ನಿಯೋಜಿಸುವ ಮೂಲಕ ನೀವು ಬಯಸಿದ್ದನ್ನು ಸಾಧಿಸಬಹುದು RoleBinding ನಿರ್ದಿಷ್ಟವಾಗಿ Namespace и ClusterRole ಸಂಪಾದನೆ ಹಕ್ಕುಗಳೊಂದಿಗೆ. YAML ಪ್ರಾತಿನಿಧ್ಯವು ಈ ರೀತಿ ಕಾಣುತ್ತದೆ:

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: kubernetes-team-1
  namespace: team-1
subjects:
- kind: Group
  name: kubernetes-team-1
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: edit
apiGroup: rbac.authorization.k8s.io

(ರೋಲ್‌ಬೈಂಡಿಂಗ್.ಯಾಮ್ಲ್, ಇನ್ ಕಚ್ಚಾ)

ಒಂದನ್ನು ತಯಾರಿಸು RoleBinding ನೀವು ಇದನ್ನು ಹಸ್ತಚಾಲಿತವಾಗಿ ಮಾಡಬಹುದು, ಆದರೆ ನೂರು ನೇಮ್‌ಸ್ಪೇಸ್‌ಗಳನ್ನು ದಾಟಿದ ನಂತರ, ಇದು ಬೇಸರದ ಕೆಲಸವಾಗುತ್ತದೆ. ಕುಬರ್ನೆಟ್ಸ್ ಆಪರೇಟರ್‌ಗಳು ಸೂಕ್ತವಾಗಿ ಬರುವುದು ಇಲ್ಲಿಯೇ-ಸಂಪನ್ಮೂಲಗಳಲ್ಲಿನ ಬದಲಾವಣೆಗಳ ಆಧಾರದ ಮೇಲೆ ಕುಬರ್ನೆಟ್ಸ್ ಸಂಪನ್ಮೂಲಗಳ ರಚನೆಯನ್ನು ಸ್ವಯಂಚಾಲಿತಗೊಳಿಸಲು ಅವರು ನಿಮಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತಾರೆ. ನಮ್ಮ ಸಂದರ್ಭದಲ್ಲಿ ನಾವು ರಚಿಸಲು ಬಯಸುತ್ತೇವೆ RoleBinding ರಚಿಸುವಾಗ Namespace.

ಮೊದಲನೆಯದಾಗಿ, ಕಾರ್ಯವನ್ನು ವ್ಯಾಖ್ಯಾನಿಸೋಣ mainಇದು ಹೇಳಿಕೆಯನ್ನು ಚಲಾಯಿಸಲು ಅಗತ್ಯವಾದ ಸೆಟಪ್ ಅನ್ನು ಮಾಡುತ್ತದೆ ಮತ್ತು ನಂತರ ಹೇಳಿಕೆ ಕ್ರಿಯೆಯನ್ನು ಕರೆಯುತ್ತದೆ:

(ಸೂಚನೆ. ಅನುವಾದ.: ಇಲ್ಲಿ ಮತ್ತು ಕೆಳಗೆ ಕೋಡ್‌ನಲ್ಲಿನ ಕಾಮೆಂಟ್‌ಗಳನ್ನು ರಷ್ಯನ್ ಭಾಷೆಗೆ ಅನುವಾದಿಸಲಾಗಿದೆ. ಹೆಚ್ಚುವರಿಯಾಗಿ, ಹಬ್ರ್ ಲೇಔಟ್‌ನಲ್ಲಿ ಉತ್ತಮ ಓದುವಿಕೆಯ ಉದ್ದೇಶಕ್ಕಾಗಿ ಇಂಡೆಂಟೇಶನ್ ಅನ್ನು [ಗೋದಲ್ಲಿ ಶಿಫಾರಸು ಮಾಡಲಾಗಿದೆ] ಟ್ಯಾಬ್‌ಗಳ ಬದಲಿಗೆ ಸ್ಪೇಸ್‌ಗಳಿಗೆ ಸರಿಪಡಿಸಲಾಗಿದೆ. ಪ್ರತಿ ಪಟ್ಟಿಯ ನಂತರ GitHub ನಲ್ಲಿ ಮೂಲಕ್ಕೆ ಲಿಂಕ್‌ಗಳಿವೆ, ಅಲ್ಲಿ ಇಂಗ್ಲಿಷ್ ಭಾಷೆಯ ಕಾಮೆಂಟ್‌ಗಳು ಮತ್ತು ಟ್ಯಾಬ್‌ಗಳನ್ನು ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ.)

func main() {
  // Устанавливаем вывод логов в консольный STDOUT
  log.SetOutput(os.Stdout)

  sigs := make(chan os.Signal, 1) // Создаем канал для получения сигналов ОС
  stop := make(chan struct{})     // Создаем канал для получения стоп-сигнала

  // Регистрируем получение SIGTERM в канале sigs
  signal.Notify(sigs, os.Interrupt, syscall.SIGTERM, syscall.SIGINT) 

  // Goroutines могут сами добавлять себя в WaitGroup,
 // чтобы завершения их выполнения дожидались
  wg := &sync.WaitGroup{} 

  runOutsideCluster := flag.Bool("run-outside-cluster", false, "Set this flag when running outside of the cluster.")
  flag.Parse()
  // Создаем clientset для взаимодействия с кластером Kubernetes
  clientset, err := newClientSet(*runOutsideCluster)

  if err != nil {
    panic(err.Error())
  }

  controller.NewNamespaceController(clientset).Run(stop, wg)

  <-sigs // Ждем сигналов (до получения сигнала более ничего не происходит)
  log.Printf("Shutting down...")

  close(stop) // Говорим goroutines остановиться
  wg.Wait()   // Ожидаем, что все остановлено
}

(ಮುಖ್ಯ.ಗೋ, ಇನ್ ಕಚ್ಚಾ)

ನಾವು ಈ ಕೆಳಗಿನವುಗಳನ್ನು ಮಾಡುತ್ತೇವೆ:

  1. ನಿರ್ಧಿಷ್ಟ ಆಪರೇಟಿಂಗ್ ಸಿಸ್ಟಂ ಸಿಗ್ನಲ್‌ಗಳಿಗಾಗಿ ನಾವು ಹ್ಯಾಂಡ್ಲರ್ ಅನ್ನು ಕಾನ್ಫಿಗರ್ ಮಾಡುತ್ತೇವೆ ಆಪರೇಟರ್‌ನ ಆಕರ್ಷಕವಾದ ಮುಕ್ತಾಯವನ್ನು ಉಂಟುಮಾಡುತ್ತದೆ.
  2. ನಾವು ಉಪಯೋಗಿಸುತ್ತೀವಿ WaitGroupಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಮುಕ್ತಾಯಗೊಳಿಸುವ ಮೊದಲು ಎಲ್ಲಾ ಗೊರೌಟಿನ್‌ಗಳನ್ನು ಆಕರ್ಷಕವಾಗಿ ನಿಲ್ಲಿಸಲು.
  3. ರಚಿಸುವ ಮೂಲಕ ನಾವು ಕ್ಲಸ್ಟರ್‌ಗೆ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸುತ್ತೇವೆ clientset.
  4. ಆರಂಭ NamespaceController, ಇದರಲ್ಲಿ ನಮ್ಮ ಎಲ್ಲಾ ತರ್ಕಗಳಿವೆ.

ಈಗ ನಮಗೆ ತರ್ಕಕ್ಕೆ ಆಧಾರ ಬೇಕು, ಮತ್ತು ನಮ್ಮ ಸಂದರ್ಭದಲ್ಲಿ ಇದು ಉಲ್ಲೇಖಿಸಲ್ಪಟ್ಟಿದೆ NamespaceController:

// NamespaceController следит через Kubernetes API за изменениями
// в пространствах имен и создает RoleBinding для конкретного namespace.
type NamespaceController struct {
  namespaceInformer cache.SharedIndexInformer
  kclient           *kubernetes.Clientset
}

// NewNamespaceController создает новый NewNamespaceController
func NewNamespaceController(kclient *kubernetes.Clientset) *NamespaceController {
  namespaceWatcher := &NamespaceController{}

  // Создаем информер для слежения за Namespaces
  namespaceInformer := cache.NewSharedIndexInformer(
    &cache.ListWatch{
      ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
        return kclient.Core().Namespaces().List(options)
      },
      WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
        return kclient.Core().Namespaces().Watch(options)
      },
    },
    &v1.Namespace{},
    3*time.Minute,
    cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
  )

  namespaceInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
    AddFunc: namespaceWatcher.createRoleBinding,
  })

  namespaceWatcher.kclient = kclient
  namespaceWatcher.namespaceInformer = namespaceInformer

  return namespaceWatcher
}

(ಕಂಟ್ರೋಲರ್.ಗೋ, ಇನ್ ಕಚ್ಚಾ)

ಇಲ್ಲಿ ನಾವು ಕಾನ್ಫಿಗರ್ ಮಾಡುತ್ತೇವೆ SharedIndexInformer, ಇದು ಪರಿಣಾಮಕಾರಿಯಾಗಿ (ಸಂಗ್ರಹವನ್ನು ಬಳಸಿಕೊಂಡು) ನೇಮ್‌ಸ್ಪೇಸ್‌ಗಳಲ್ಲಿನ ಬದಲಾವಣೆಗಳಿಗಾಗಿ ಕಾಯುತ್ತದೆ (ಲೇಖನದಲ್ಲಿ ಮಾಹಿತಿದಾರರ ಬಗ್ಗೆ ಇನ್ನಷ್ಟು ಓದಿಕುಬರ್ನೆಟ್ಸ್ ಶೆಡ್ಯೂಲರ್ ನಿಜವಾಗಿ ಹೇಗೆ ಕೆಲಸ ಮಾಡುತ್ತದೆ?"- ಅಂದಾಜು ಅನುವಾದ). ಇದರ ನಂತರ ನಾವು ಸಂಪರ್ಕಿಸುತ್ತೇವೆ EventHandler ಮಾಹಿತಿದಾರರಿಗೆ, ಆದ್ದರಿಂದ ನೇಮ್‌ಸ್ಪೇಸ್ ಸೇರಿಸುವಾಗ (Namespace) ಕಾರ್ಯವನ್ನು ಕರೆಯಲಾಗುತ್ತದೆ createRoleBinding.

ಈ ಕಾರ್ಯವನ್ನು ವ್ಯಾಖ್ಯಾನಿಸುವುದು ಮುಂದಿನ ಹಂತವಾಗಿದೆ createRoleBinding:

func (c *NamespaceController) createRoleBinding(obj interface{}) {
  namespaceObj := obj.(*v1.Namespace)
  namespaceName := namespaceObj.Name

  roleBinding := &v1beta1.RoleBinding{
    TypeMeta: metav1.TypeMeta{
      Kind:       "RoleBinding",
      APIVersion: "rbac.authorization.k8s.io/v1beta1",
    },
    ObjectMeta: metav1.ObjectMeta{
      Name:      fmt.Sprintf("ad-kubernetes-%s", namespaceName),
      Namespace: namespaceName,
    },
    Subjects: []v1beta1.Subject{
      v1beta1.Subject{
        Kind: "Group",
        Name: fmt.Sprintf("ad-kubernetes-%s", namespaceName),
      },
    },
    RoleRef: v1beta1.RoleRef{
      APIGroup: "rbac.authorization.k8s.io",
        Kind:     "ClusterRole",
        Name:     "edit",
    },
  }

  _, err := c.kclient.Rbac().RoleBindings(namespaceName).Create(roleBinding)

  if err != nil {
    log.Println(fmt.Sprintf("Failed to create Role Binding: %s", err.Error()))
  } else {
    log.Println(fmt.Sprintf("Created AD RoleBinding for Namespace: %s", roleBinding.Name))
  }
}

(ಕಂಟ್ರೋಲರ್.ಗೋ, ಇನ್ ಕಚ್ಚಾ)

ನಾವು ನೇಮ್‌ಸ್ಪೇಸ್ ಅನ್ನು ಪಡೆಯುತ್ತೇವೆ obj ಮತ್ತು ಅದನ್ನು ವಸ್ತುವಾಗಿ ಪರಿವರ್ತಿಸಿ Namespace. ನಂತರ ನಾವು ವ್ಯಾಖ್ಯಾನಿಸುತ್ತೇವೆ RoleBinding, ಒದಗಿಸಿದ ವಸ್ತುವನ್ನು ಬಳಸಿಕೊಂಡು ಆರಂಭದಲ್ಲಿ ಉಲ್ಲೇಖಿಸಲಾದ YAML ಫೈಲ್ ಅನ್ನು ಆಧರಿಸಿ Namespace ಮತ್ತು ರಚಿಸುವುದು RoleBinding. ಅಂತಿಮವಾಗಿ, ಸೃಷ್ಟಿ ಯಶಸ್ವಿಯಾಗಿದೆಯೇ ಎಂದು ನಾವು ಲಾಗ್ ಮಾಡುತ್ತೇವೆ.

ವ್ಯಾಖ್ಯಾನಿಸಬೇಕಾದ ಕೊನೆಯ ಕಾರ್ಯ Run:

// Run запускает процесс ожидания изменений в пространствах имён
// и действия в соответствии с этими изменениями.
func (c *NamespaceController) Run(stopCh <-chan struct{}, wg *sync.WaitGroup) {
  // Когда эта функция завершена, пометим как выполненную
  defer wg.Done()

  // Инкрементируем wait group, т.к. собираемся вызвать goroutine
  wg.Add(1)

  // Вызываем goroutine
  go c.namespaceInformer.Run(stopCh)

  // Ожидаем получения стоп-сигнала
  <-stopCh
}

(ಕಂಟ್ರೋಲರ್.ಗೋ, ಇನ್ ಕಚ್ಚಾ)

ಇಲ್ಲಿ ನಾವು ಮಾತನಾಡುತ್ತಿದ್ದೇವೆ WaitGroupನಾವು ಗೊರೂಟಿನ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸುತ್ತೇವೆ ಮತ್ತು ನಂತರ ಕರೆ ಮಾಡುತ್ತೇವೆ namespaceInformer, ಇದನ್ನು ಹಿಂದೆ ವ್ಯಾಖ್ಯಾನಿಸಲಾಗಿದೆ. ಸ್ಟಾಪ್ ಸಿಗ್ನಲ್ ಬಂದಾಗ, ಅದು ಕಾರ್ಯವನ್ನು ಕೊನೆಗೊಳಿಸುತ್ತದೆ, ತಿಳಿಸುತ್ತದೆ WaitGroup, ಇದು ಇನ್ನು ಮುಂದೆ ಕಾರ್ಯಗತಗೊಳ್ಳುವುದಿಲ್ಲ, ಮತ್ತು ಈ ಕಾರ್ಯವು ನಿರ್ಗಮಿಸುತ್ತದೆ.

ಕುಬರ್ನೆಟ್ಸ್ ಕ್ಲಸ್ಟರ್‌ನಲ್ಲಿ ಈ ಹೇಳಿಕೆಯನ್ನು ನಿರ್ಮಿಸುವ ಮತ್ತು ನಡೆಸುವ ಬಗ್ಗೆ ಮಾಹಿತಿಯನ್ನು ಕಾಣಬಹುದು GitHub ನಲ್ಲಿ ರೆಪೊಸಿಟರಿಗಳು.

ರಚಿಸುವ ಆಪರೇಟರ್‌ಗೆ ಅದು ಇಲ್ಲಿದೆ RoleBinding ಯಾವಾಗ Namespace ಕುಬರ್ನೆಟ್ಸ್ ಕ್ಲಸ್ಟರ್‌ನಲ್ಲಿ, ಸಿದ್ಧವಾಗಿದೆ.

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ