Nagsulat kami ug operator para sa Kubernetes sa Golang

Nota. transl.: Ang mga operator kay auxiliary software para sa Kubernetes nga gidesinyo sa pag-automate sa pagpatuman sa naandang mga aksyon sa cluster nga mga butang atol sa pipila ka mga panghitabo. Nakasulat na kami bahin sa mga operator sa kini nga artikulodiin sila naghisgot bahin sa sukaranang mga ideya ug mga prinsipyo sa ilang trabaho. Apan kung kana nga materyal kay usa ka pagtan-aw gikan sa kilid sa operasyon sa mga andam nga sangkap alang sa Kubernetes, nan ang paghubad sa bag-ong artikulo nga gisugyot karon mao na ang panan-awon sa usa ka developer / DevOps engineer, nalibog sa pagpatuman sa usa ka bag-ong operator. .

Nagsulat kami ug operator para sa Kubernetes sa Golang

Nakahukom ko nga isulat kini nga post sa usa ka tinuod nga panig-ingnan sa kinabuhi human sa akong mga pagsulay sa pagpangita og dokumentasyon sa paghimo og operator para sa Kubernetes, miagi sa pagtuon sa code.

Ang pananglitan nga ihulagway mao kini: sa among Kubernetes cluster, matag usa Namespace nagrepresentar sa sandbox environment sa usa ka team, ug gusto namo nga pugngan ang pag-access niini aron ang mga team makaduwa lang sa ilang kaugalingong sandbox.

Mahimo nimong makab-ot ang imong gusto pinaagi sa pag-assign sa usa ka user sa usa ka grupo nga adunay RoleBinding sa espesipiko Namespace ΠΈ ClusterRole nga adunay mga katungod sa pag-edit. Ang representasyon sa YAML mahimong sama niini:

---
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.yamlsa hilaw)

Paghimo sa ingon RoleBinding mahimo nimo kini nga mano-mano, apan sa higayon nga makakuha ka og kapin sa usa ka gatos nga mga namespaces, kini mahimong usa ka kapoy nga buluhaton. Dinhi magamit ang mga operator sa Kubernetes - gitugotan ka nila nga awtomatiko ang paghimo sa mga kapanguhaan sa Kubernetes base sa mga pagbag-o sa mga kapanguhaan. Sa among kaso, gusto namon nga maghimo RoleBinding samtang nagmugna Namespace.

Una sa tanan, atong ipasabut ang function main, nga naghimo sa gikinahanglan nga pag-setup aron sa pagpadagan sa pahayag ug dayon gisangpit ang aksyon nga pahayag:

(Nota. transl.: pagkahuman, ang mga komento sa code gihubad sa Russian. Dugang pa, ang indentasyon gitul-id alang sa mga luna imbes sa [girekomenda sa Go] nga mga tab para lamang sa katuyoan nga mas daling mabasa sulod sa gambalay sa layout ni Habr. Pagkahuman sa matag lista, adunay mga link sa orihinal sa GitHub, diin ang mga komentaryo ug mga tab sa English nga pinulongan gitipigan.)

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.gosa hilaw)

Atong buhaton ang mosunod:

  1. Nagbutang kami usa ka handler alang sa piho nga mga signal sa operating system aron mahimo’g mogawas ang operator.
  2. Gigamit namo WaitGroupsa maayong pagpahunong sa tanang goroutine sa dili pa matapos ang aplikasyon.
  3. Naghatag kami og access sa cluster pinaagi sa paghimo clientset.
  4. Paglusad NamespaceController, diin mahimutang ang tanan natong lohika.

Karon kinahanglan namon ang usa ka basehan alang sa lohika, ug sa among kaso kini ang gihisgutan 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.gosa hilaw)

Dinhi kita nagpahimutang SharedIndexInformer, nga episyente (gamit ang cache) maghulat alang sa mga pagbag-o sa namespace (basaha ang dugang bahin sa mga informer sa artikulo "Sa unsang paagi nga ang Kubernetes scheduler aktuwal nga nagtrabaho?"- gibanabana. transl.). Human niana nagkonektar kami EventHandler sa tigpahibalo, salamat niini, kung magdugang og namespace (Namespace) ang function gitawag createRoleBinding.

Ang sunod nga lakang mao ang paghubit niini nga function 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.gosa hilaw)

Atong makuha ang namespace ingon obj ug i-convert kini ngadto sa usa ka butang Namespace. Unya atong gipasabot RoleBinding, base sa YAML file nga gihisgotan sa sinugdanan, gamit ang gihatag nga butang Namespace ug paghimo RoleBinding. Sa katapusan, among gi-log kung ang paglalang nagmalampuson.

Ang katapusan nga function nga ipasabut mao ang - 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.gosa hilaw)

Dinhi kita nag-istoryahanay WaitGroupnga sugdan namo ang goroutine ug dayon tawagan namespaceInformernga gihubit na kaniadto. Sa diha nga ang usa ka stop signal moabut sa, kini motapos sa function, ipahibalo WaitGroup, nga dili na ipatuman, ug kini nga function mogawas.

Ang impormasyon bahin sa pagtukod ug pagpadagan niini nga pahayag sa usa ka Kubernetes cluster makita sa mga repositoryo sa GitHub.

Sa kini nga pahayag, nga nagmugna RoleBinding kanus-a Namespace sa usa ka Kubernetes cluster, andam na.

Source: www.habr.com

Idugang sa usa ka comment