Навиштани оператор барои Kubernetes дар Голанг

Шарҳ. тарҷума.: Операторҳо нармафзори ёрирасон барои Kubernetes мебошанд, ки барои автоматикунонии иҷрои амалҳои муқаррарӣ дар объектҳои кластер ҳангоми рух додани ҳодисаҳои муайян пешбинӣ шудаанд. Мо аллакай дар бораи операторҳо навишта будем ин мақола, ки онхо дар бораи идеяхо ва принципхои асосии кори худ сухбат карданд. Аммо агар ин мавод бештар аз паҳлӯи корбурди ҷузъҳои омода барои Kubernetes бошад, пас тарҷумаи мақолаи нав, ки ҳоло пешниҳод шудааст, аллакай диди як таҳиягар/муҳандиси DevOps аст, ки аз татбиқи оператори нав ба ҳайрат афтодааст.

Навиштани оператор барои Kubernetes дар Голанг

Ман тасмим гирифтам, ки ин мақоларо бо мисоли воқеии ҳаёт пас аз кӯшиши пайдо кардани ҳуҷҷатҳо оид ба эҷоди оператор барои Kubernetes, ки тавассути омӯзиши код гузаштааст, нависам.

Намунае, ки тавсиф карда мешавад, ин аст: дар кластери Кубернетес мо, ҳар як 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.yamlдар дохили хом)

Яке эҷод кунед RoleBinding Шумо метавонед ин корро дастӣ кунед, аммо пас аз убур кардани аломати сад фазои ном, он кори дилгиркунанда мегардад. Дар ин ҷо операторони Kubernetes муфиданд - онҳо ба шумо имкон медиҳанд, ки эҷоди захираҳои Kubernetes дар асоси тағирот ба захираҳо автоматӣ кунед. Дар ҳолати мо мо мехоҳем эҷод кунем RoleBinding ҳангоми эҷод Namespace.

Пеш аз ҳама, биёед функсияро муайян кунем mainки барои иҷро кардани изҳорот танзимоти заруриро иҷро мекунад ва сипас амали изҳоротро даъват мекунад:

(Шарҳ. тарҷума.: дар ин ҷо ва дар зер шарҳҳои код ба забони русӣ тарҷума шудаанд. Илова бар ин, абзор ба ҷои варақаҳои [дар Гузаштан тавсияшуда] танҳо бо мақсади хондан беҳтар дар дохили тарҳбандии Habr ислоҳ карда шудааст. Пас аз ҳар як рӯйхат истинод ба нусхаи аслӣ дар 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()   // Ожидаем, что все остановлено
}

(main.goдар дохили хом)

Мо корҳои зеринро иҷро мекунем:

  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
}

(controller.goдар дохили хом)

Дар ин ҷо мо танзим мекунем SharedIndexInformer, ки ба таври муассир (бо истифода аз кэш) тағирот дар фазои номҳоро интизор мешавад (дар бораи хабарнигорон дар мақолаи бештар хонед "Нақшасози Kubernetes воқеан чӣ гуна кор мекунад?- тахминан. тарҷума). Пас аз ин мо пайваст мешавем 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))
  }
}

(controller.goдар дохили хом)

Мо фазои номро ҳамчун 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
}

(controller.goдар дохили хом)

Ана гап мезанем WaitGroupки мо горутинро ба кор меандозем ва баъд занг мезанем namespaceInformer, ки пештар муайян карда шуда буд. Вақте ки сигнали қатъ меояд, он функсияро қатъ мекунад, хабар диҳед WaitGroup, ки дигар иҷро намешавад ва ин функсия хориҷ мешавад.

Маълумот дар бораи сохтан ва иҷро кардани ин изҳорот дар кластери Kubernetes метавонад дар анборҳо дар GitHub.

Ин барои операторе, ки эҷод мекунад RoleBinding кай Namespace дар кластери Кубернетес, омода аст.

Манбаъ: will.com

Илова Эзоҳ