Auctor scribens pro Kubernetes in Golang

Nota. transl.: Operatores programmatis auxiliares sunt Kubernetes, qui automate constituunt executionem actionum usuum in glomeris obiectis cum certae res eveniunt. Iam de operariis in hoc articulumibi loquebantur de notionibus ac principiis sui operis fundamentalibus. Sed si materia illa plus spectaculi ex parte operandi paratae factae partes Kubernetes erat, translatio novi articuli iam propositi iam visio elit/DevOps architecti in exsequendo novi operantis perplexus erat.

Auctor scribens pro Kubernetes in Golang

Hanc epistulam scribere decrevi exemplo verae vitae, postquam conatus meos invenire documentum in creando operante Kubernetes, qui per studium codicis accessit.

Exemplum quod describendum est hoc est: in nostro botro Kubernetes Namespace environment sandbox team repraesentat, et accessum ad eos limitare voluimus ut iugis in suis sandboxes tantum ludere posset.

Potes consequi quod vis, assignando usorem coetui qui habet RoleBinding ad specifica Namespace и ClusterRole cum iura emendo. YAML repraesentatio sic erit:

---
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.yamlapud crudam)

Crea unum RoleBinding Manually facere potes, sed post centum spatiorum nomina transmisso, longum fit negotium. Haec ubi operarii Kubernetes in promptu veniunt - te permittunt creandi Kubernetes facultates quae in mutationibus facultatum sunt. In casu nostro volumus creare RoleBinding dum creando Namespace.

Primum munus definiamus mainquae facit requiritur setup ut run enuntiatio et inde vocat actionem enuntiationis:

(Nota. transl.commenta in codice Russico translata hic et infra. Praeterea incisum correctum est ad spatia pro tabs unice ad melioris promptitudinis causa intra Habr layout. Post singulas enumeratas nexus sunt cum originali in GitHub, ubi in lingua Anglica commenta et tabs reponuntur.

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.goapud crudam)

Facimus quae sequuntur;

  1. Nos tracto configuramus pro certis significationibus operandi rationi, ut jucundam efficiat operantis terminationem.
  2. Utimur WaitGrouput lepide desinas omnes goroutines ante applicationem terminandi.
  3. Botrus creando aditum praebemus clientset.
  4. Launch NamespaceControllerin quo omnis nostra logica collocabitur.

Nunc logicae fundamento indigemus, et in casu nostro haec est mentio 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.goapud crudam)

Hic configuramus SharedIndexInformerquae efficaciter (cache utendo) mutationes in spatiis nominalibus exspectant (Lege de indicibus in articulum "Quomodo Kubernetes schedulae actu laborant?"- proxime. translation). Post haec coniungimus EventHandler delatori, ut cum spatio addito (Namespace) Munus dicitur createRoleBinding.

Proximus gradus est definire hoc munus 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.goapud crudam)

Nos adepto in spatio nominali ut obj et convertam ad objectum Namespace. Deinde definimus RoleBinding, fundatur in YAML fasciculus, de quo in principio, utens objecto provisum Namespace et creando RoleBinding. Denique inspicimus utrum creatio felix fuerit.

Munus extremum definiendum est 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.goapud crudam)

Hic loquimur WaitGroupquod deducunt goroutine et vocamus namespaceInformerquod prius definitum est. Cum signum statur advenit, munus finiet, certiorem facit WaitGroupquod iam non est, et hoc munus exibit.

Informationes de aedificatione et currendo hanc propositionem in botro Kubernetes inveniri possunt repositoria in GitHub.

Id enim auctor creat RoleBinding quod Namespace in Kubernetes botrum, paratum.

Source: www.habr.com

Add a comment