Kuandika opereta kwa Kubernetes katika Golang

Kumbuka. tafsiri.: Waendeshaji ni programu saidizi ya Kubernetes, iliyoundwa ili kufanyia kazi vitendo vya kawaida kwenye vipengee vya kundi wakati matukio fulani yanapotokea. Tayari tumeandika kuhusu waendeshaji katika Makala hii, ambapo walizungumza kuhusu mawazo na kanuni za msingi za kazi zao. Lakini ikiwa nyenzo hiyo ilikuwa ya mtazamo zaidi kutoka kwa upande wa uendeshaji wa vipengele vilivyotengenezwa tayari kwa Kubernetes, basi tafsiri ya makala mpya inayopendekezwa sasa ni maono ya msanidi programu/DevOps aliyeshangazwa na utekelezaji wa mwendeshaji mpya.

Kuandika opereta kwa Kubernetes katika Golang

Niliamua kuandika chapisho hili na mfano wa maisha halisi baada ya majaribio yangu ya kupata hati juu ya kuunda opereta kwa Kubernetes, ambayo ilipitia kusoma msimbo.

Mfano ambao utaelezewa ni huu: katika nguzo yetu ya Kubernetes, kila moja Namespace inawakilisha mazingira ya kisanduku cha mchanga cha timu, na tulitaka kupunguza ufikiaji wao ili timu zicheze tu katika visanduku vyao vya mchanga.

Unaweza kufikia kile unachotaka kwa kumkabidhi mtumiaji kundi ambalo lina RoleBinding kwa maalum Namespace ΠΈ ClusterRole na haki za uhariri. Uwakilishi wa YAML utaonekana kama hii:

---
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

(wajibu.yamlndani ghafi)

Unda moja RoleBinding Unaweza kuifanya kwa mikono, lakini baada ya kuvuka alama ya nafasi za majina, inakuwa kazi ngumu. Hapa ndipo waendeshaji wa Kubernetes huja kwa manufaaβ€”wanakuruhusu kuhariri uundaji wa rasilimali za Kubernetes kulingana na mabadiliko ya rasilimali. Kwa upande wetu tunataka kuunda RoleBinding wakati wa kuunda Namespace.

Kwanza kabisa, hebu tufafanue kazi mainambayo hufanya usanidi unaohitajika kuendesha taarifa hiyo na kisha kuita hatua ya taarifa:

(Kumbuka. tafsiri.: hapa na chini ya maoni katika kanuni hutafsiriwa kwa Kirusi. Zaidi ya hayo, ujongezaji umesahihishwa kwa nafasi badala ya vichupo vya [vilivyopendekezwa katika Go] kwa madhumuni ya kusomeka vyema ndani ya mpangilio wa Habr. Baada ya kila tangazo kuna viungo vya asili kwenye GitHub, ambapo maoni na vichupo vya lugha ya Kiingereza huhifadhiwa.)

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()   // ОТидаСм, Ρ‡Ρ‚ΠΎ всС остановлСно
}

(kuu.kwendandani ghafi)

Tunafanya yafuatayo:

  1. Tunasanidi kidhibiti kwa mawimbi mahususi ya mfumo wa uendeshaji ili kusababisha kusitishwa kwa njia ya kifahari kwa opereta.
  2. Tunatumia WaitGroupili kusimamisha kwa uzuri taratibu zote kabla ya kusitisha programu.
  3. Tunatoa ufikiaji wa nguzo kwa kuunda clientset.
  4. Uzinduzi NamespaceController, ambayo mantiki yetu yote itakuwa iko.

Sasa tunahitaji msingi wa mantiki, na kwa upande wetu hii ndiyo iliyotajwa 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
}

(kidhibiti.gondani ghafi)

Hapa tunasanidi SharedIndexInformer, ambayo kwa ufanisi (kwa kutumia kache) itasubiri mabadiliko katika nafasi za majina (soma zaidi kuhusu watoa habari katika makala "Je, kipanga ratiba cha Kubernetes hufanyaje kazi kweli?"- takriban. tafsiri). Baada ya hayo tunaunganisha EventHandler kwa mtoaji habari, ili wakati wa kuongeza nafasi ya jina (Namespace) kazi inaitwa createRoleBinding.

Hatua inayofuata ni kufafanua kazi hii 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))
  }
}

(kidhibiti.gondani ghafi)

Tunapata nafasi ya majina kama obj na kuibadilisha kuwa kitu Namespace. Kisha tunafafanua RoleBinding, kulingana na faili ya YAML iliyotajwa mwanzoni, kwa kutumia kitu kilichotolewa Namespace na kuunda RoleBinding. Hatimaye, tunaandika kama uumbaji ulifanikiwa.

Kazi ya mwisho itakayofafanuliwa ni 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
}

(kidhibiti.gondani ghafi)

Hapa tunazungumza WaitGroupkwamba tunazindua goroutine na kisha kupiga simu namespaceInformer, ambayo imefafanuliwa hapo awali. Wakati ishara ya kuacha inakuja, itamaliza kazi, taarifa WaitGroup, ambayo haijatekelezwa tena, na chaguo hili la kukokotoa litatoka.

Taarifa kuhusu kujenga na kuendesha taarifa hii kwenye nguzo ya Kubernetes inaweza kupatikana ndani hazina kwenye GitHub.

Hiyo ni kwa mwendeshaji anayeunda RoleBinding juu ya kuonekana Namespace katika kundi la Kubernetes, tayari.

Chanzo: mapenzi.com

Kuongeza maoni