Rubuta ma'aikaci don Kubernetes a Golang

Lura. fassara: Masu aiki software ne na taimako don Kubernetes, waɗanda aka tsara don sarrafa aiwatar da ayyukan yau da kullun akan abubuwan tari lokacin da wasu abubuwan suka faru. Mun riga mun rubuta game da masu aiki a ciki wannan labarin, inda suka yi magana game da mahimman ra'ayoyi da ka'idodin aikinsu. Amma idan wannan kayan ya kasance mafi ra'ayi daga gefen aiki na kayan aikin da aka shirya don Kubernetes, to, fassarar sabon labarin da aka tsara yanzu ya rigaya ya kasance hangen nesa na injiniya mai haɓakawa / DevOps ya damu da aiwatar da sabon mai aiki.

Rubuta ma'aikaci don Kubernetes a Golang

Na yanke shawarar rubuta wannan sakon tare da misali na rayuwa na gaske bayan ƙoƙarina na nemo takaddun akan ƙirƙirar ma'aikaci don Kubernetes, wanda ya shiga nazarin lambar.

Misalin da za a kwatanta shi ne: a cikin gungu na Kubernetes, kowanne Namespace yana wakiltar muhallin akwatin sandbox na ƙungiyar, kuma muna so mu iyakance damar zuwa gare su ta yadda ƙungiyoyi za su iya yin wasa a cikin akwatin yashi kawai.

Kuna iya cimma abin da kuke so ta hanyar sanya mai amfani ƙungiyar da ke da ita RoleBinding zuwa takamaiman Namespace и ClusterRole tare da hakkin gyarawa. Wakilin YAML zai yi kama da haka:

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

(rawar aiki.yaml, in raw)

Ƙirƙiri ɗaya RoleBinding Kuna iya yin shi da hannu, amma bayan haye alamar wuraren suna ɗari, ya zama aiki mai wahala. Wannan shine inda ma'aikatan Kubernetes suka zo da hannu-suna ba ku damar sarrafa sarrafa albarkatun Kubernetes bisa canje-canje ga albarkatun. A cikin yanayinmu muna son ƙirƙirar RoleBinding yayin ƙirƙirar Namespace.

Da farko, bari mu ayyana aikin mainwanda ke yin saitin da ake buƙata don gudanar da bayanin sannan ya kira aikin bayanin:

(Lura. fassara: nan da ƙasa an fassara sharhin da ke cikin lambar zuwa Rashanci. Bugu da kari, an gyara indentation zuwa sarari maimakon [an ba da shawarar a Go] shafuka kawai don manufar ingantaccen karatu a cikin shimfidar Habr. Bayan kowane jeri akwai hanyoyin haɗi zuwa na asali akan GitHub, inda ake adana sharhi da shafuka na harshen Ingilishi.)

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, in raw)

Muna yin haka:

  1. Muna saita mai sarrafa don takamaiman siginar tsarin aiki don haifar da kyakkyawan ƙarewar mai aiki.
  2. Muna amfani WaitGroupdon dakatar da duk goroutines cikin alheri kafin ƙare aikace-aikacen.
  3. Muna ba da dama ga gungu ta hanyar ƙirƙira clientset.
  4. Kaddamarwa NamespaceController, wanda duk tunaninmu zai kasance.

Yanzu muna buƙatar tushe don tunani, kuma a cikin yanayinmu wannan shine wanda aka ambata 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
}

(mai sarrafawa.go, in raw)

Anan mun daidaita SharedIndexInformer, wanda zai dace (ta amfani da cache) yana jira canje-canje a cikin wuraren suna (kara karantawa game da masu ba da labari a cikin labarin "Ta yaya mai tsara tsarin Kubernetes yake aiki a zahiri?"- - kusan fassara). Bayan wannan mun haɗa EventHandler zuwa ga mai ba da labari, ta yadda lokacin ƙara sunan wuri (Namespace) ana kiran aikin createRoleBinding.

Mataki na gaba shine ayyana wannan aikin 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))
  }
}

(mai sarrafawa.go, in raw)

Muna samun filin suna kamar obj kuma canza shi zuwa wani abu Namespace. Sai mu ayyana RoleBinding, dangane da fayil ɗin YAML da aka ambata a farkon, ta amfani da abin da aka bayar Namespace da halitta RoleBinding. A ƙarshe, mun shiga ko halittar ta yi nasara.

Aikin ƙarshe da za a ayyana shi ne 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
}

(mai sarrafawa.go, in raw)

Anan muna magana WaitGroupcewa mu kaddamar da goroutine sannan mu kira namespaceInformer, wanda aka bayyana a baya. Lokacin da siginar tsayawa ya zo, zai ƙare aikin, sanar WaitGroup, wanda ba a sake aiwatarwa, kuma wannan aikin zai fita.

Ana iya samun bayanai game da ginawa da gudanar da wannan sanarwa akan gungu na Kubernetes a ciki wuraren ajiya akan GitHub.

Shi ke nan ga ma'aikacin da ke ƙirƙira RoleBinding yaushe Namespace a cikin gungun Kubernetes, shirye.

source: www.habr.com

Add a comment