Nulis operator kanggo Kubernetes ing Golang

Cathetan. nerjemahake.: Operator minangka piranti lunak tambahan kanggo Kubernetes, dirancang kanggo ngotomatisasi eksekusi tumindak rutin ing obyek kluster nalika kedadeyan tartamtu. Kita wis nulis babagan operator ing artikel iki, ing ngendi dheweke ngomong babagan gagasan lan prinsip dhasar karyane. Nanging yen materi kasebut luwih katon saka sisih ngoperasikake komponen sing wis siap kanggo Kubernetes, mula terjemahan artikel anyar sing saiki diusulake wis dadi visi pangembang / insinyur DevOps sing bingung karo implementasine operator anyar.

Nulis operator kanggo Kubernetes ing Golang

Aku mutusake kanggo nulis kiriman iki kanthi conto nyata sawise nyoba golek dokumentasi babagan nggawe operator kanggo Kubernetes, sing sinau kode kasebut.

Conto sing bakal diterangake yaiku: ing kluster Kubernetes, saben Namespace makili lingkungan kothak wedhi tim, lan kita wanted kanggo matesi akses kanggo wong-wong mau supaya tim mung bisa muter ing kothak wedhi dhewe.

Sampeyan bisa entuk apa sing dikarepake kanthi menehi pangguna klompok sing duwe RoleBinding kanggo tartamtu Namespace ΠΈ ClusterRole karo hak editing. Perwakilan YAML bakal katon kaya iki:

---
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.yamling mentah)

Nggawe siji RoleBinding Sampeyan bisa nindakake kanthi manual, nanging sawise nyabrang tandha atus spasi jeneng, dadi tugas sing mboseni. Iki ngendi operator Kubernetes migunani-sing ngidini sampeyan ngotomatisasi nggawe sumber daya Kubernetes adhedhasar owah-owahan sumber daya. Ing kasus kita pengin nggawe RoleBinding nalika nggawe Namespace.

Kaping pisanan, ayo nemtokake fungsi kasebut mainsing nindakake persiyapan sing dibutuhake kanggo mbukak statement banjur nelpon tumindak statement:

(Cathetan. nerjemahake.: kene lan ngisor komentar ing kode diterjemahake menyang Rusian. Kajaba iku, indentasi wis didandani menyang spasi tinimbang tab [disaranake ing Go] mung kanggo tujuan supaya luwih gampang diwaca ing tata letak Habr. Sawise saben dhaptar ana pranala menyang asli ing GitHub, ing ngendi komentar lan tab ing basa Inggris disimpen.)

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

(utama.going mentah)

Kita nindakake ing ngisor iki:

  1. Kita ngatur handler kanggo sinyal sistem operasi tartamtu kanggo nimbulakΓ© mandap anggun saka operator.
  2. Kita nggunakake WaitGroupkanggo mungkasi kabeh goroutine kanthi apik sadurunge mungkasi aplikasi kasebut.
  3. We nyedhiyani akses kanggo kluster dening nggawe clientset.
  4. Bukak NamespaceController, ing ngendi kabeh logika kita bakal ana.

Saiki kita butuh basis kanggo logika, lan ing kasus kita iki sing kasebut 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
}

(pengontrol.going mentah)

Kene kita ngatur SharedIndexInformer, sing bakal kanthi efektif (nggunakake cache) ngenteni owah-owahan ing ruang jeneng (waca liyane babagan informan ing artikel "Kepiye cara kerja panjadwal Kubernetes?"- kira-kira. ngartekne). Sawise iki kita nyambung EventHandler marang informan, supaya nalika nambah spasi jeneng (Namespace) diarani fungsi createRoleBinding.

Langkah sabanjure kanggo nemtokake fungsi iki 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))
  }
}

(pengontrol.going mentah)

We njaluk namespace minangka obj lan ngowahi dadi obyek Namespace. Banjur kita nemtokake RoleBinding, adhedhasar file YAML sing kasebut ing wiwitan, nggunakake obyek sing kasedhiya Namespace lan nggawe RoleBinding. Pungkasan, kita log apa nggawe sukses.

Fungsi pungkasan sing ditetepake yaiku 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
}

(pengontrol.going mentah)

Kene kita ngomong WaitGroupsing kita miwiti goroutine banjur nelpon namespaceInformer, sing wis ditetepake sadurunge. Nalika sinyal mandeg teka, bakal mungkasi fungsi, ngandhani WaitGroup, sing ora dieksekusi maneh, lan fungsi iki bakal metu.

Informasi babagan mbangun lan nglakokake statement iki ing kluster Kubernetes bisa ditemokake ing repositori ing GitHub.

Iku kanggo operator sing nggawe RoleBinding nalika Namespace ing kluster Kubernetes, siap.

Source: www.habr.com

Add a comment