αž€αžΆαžšαžŸαžšαžŸαŸαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Kubernetes αž“αŸ…αž€αŸ’αž“αž»αž„ Golang

αž…αŸ†αžŽαžΆαŸ†αŸ” αž”αž€αž”αŸ’αžšαŸ‚αŸ– αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžšαž‚αžΊαž‡αžΆαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‡αŸ†αž“αž½αž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Kubernetes αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαž…αž“αžΆαž‘αžΎαž„αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αž€αž˜αŸ’αž˜αž€αžΆαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž“αŸƒαžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αž‡αžΆαž”αŸ’αžšαž…αžΆαŸ†αž“αŸ…αž›αžΎαžœαžαŸ’αžαž»αž…αž„αŸ’αž€αŸ„αž˜ αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž–αŸ’αžšαžΉαžαŸ’αžαž·αž€αžΆαžšαžŽαŸαž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αž€αžΎαžαž‘αžΎαž„αŸ” αž™αžΎαž„αž”αžΆαž“αžŸαžšαžŸαŸαžšαžšαž½αž…αž αžΎαž™αž’αŸ†αž–αžΈαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžšαž“αŸ…αž€αŸ’αž“αž»αž„ αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αžŠαŸ‚αž›αž‡αžΆαž€αž“αŸ’αž›αŸ‚αž„αžŠαŸ‚αž›αž–αž½αž€αž‚αŸαž”αžΆαž“αž“αž·αž™αžΆαž™αž’αŸ†αž–αžΈαž‚αŸ†αž“αž·αžαž‡αžΆαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“ αž“αž·αž„αž‚αŸ„αž›αž€αžΆαžšαžŽαŸαž“αŸƒαž€αžΆαžšαž„αžΆαžšαžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸαŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž”αŸ’αžšαžŸαž·αž“αž”αžΎαžŸαž˜αŸ’αž—αžΆαžšαŸˆαž“αŸ„αŸ‡αž˜αžΆαž“αž‘αžŸαŸ’αžŸαž“αŸˆαž…αŸ’αžšαžΎαž“αž–αžΈαž•αŸ’αž“αŸ‚αž€αž“αŸƒαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαžŠαŸ‚αž›αžαŸ’αžšαŸ€αž˜αžšαž½αž…αž‡αžΆαžŸαŸ’αžšαŸαž…αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Kubernetes αž“αŸ„αŸ‡αž€αžΆαžšαž”αž€αž”αŸ’αžšαŸ‚αž’αžαŸ’αžαž”αž‘αžαŸ’αž˜αžΈαžŠαŸ‚αž›αž”αžΆαž“αžŸαŸ’αž“αžΎαž‘αžΎαž„αž₯αž‘αžΌαžœαž“αŸαŸ‡αž‚αžΊαž‡αžΆαž…αž€αŸ’αžαž»αžœαž·αžŸαŸαž™αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž’αž—αž·αžœαžŒαŸ’αžαž“αŸ/αžœαž·αžŸαŸ’αžœαž€αžš DevOps αžŠαŸ‚αž›αž„αžΏαž„αž†αŸ’αž„αž›αŸ‹αžŠαŸ„αž™αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžšαžαŸ’αž˜αžΈαŸ”

αž€αžΆαžšαžŸαžšαžŸαŸαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Kubernetes αž“αŸ…αž€αŸ’αž“αž»αž„ Golang

αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αžŸαž˜αŸ’αžšαŸαž…αž…αž·αžαŸ’αžαžŸαžšαžŸαŸαžšαž”αŸ’αžšαž€αžΆαžŸαž“αŸαŸ‡αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž§αž‘αžΆαž αžšαžŽαŸαž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„αž˜αž½αž™ αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž€αžΆαžšαž–αŸ’αž™αžΆαž™αžΆαž˜αžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ†αž€αŸ’αž“αž»αž„αž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€αž―αž€αžŸαžΆαžšαžŸαŸ’αžαžΈαž–αžΈαž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Kubernetes αžŠαŸ‚αž›αž”αžΆαž“αž†αŸ’αž›αž„αž€αžΆαžαŸ‹αž€αžΆαžšαžŸαž·αž€αŸ’αžŸαžΆαž€αžΌαžŠαŸ”

αž§αž‘αžΆαž αžšαžŽαŸαžŠαŸ‚αž›αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž–αž·αž–αžŽαŸŒαž“αžΆαž‚αžΊαž“αŸαŸ‡αŸ– αž“αŸ…αž€αŸ’αž“αž»αž„αž…αž„αŸ’αž€αŸ„αž˜ Kubernetes αžšαž”αžŸαŸ‹αž™αžΎαž„αž“αžΈαž˜αž½αž™αŸ— Namespace αžαŸ†αžŽαžΆαž„αž±αŸ’αž™αž”αžšαž·αž™αžΆαž€αžΆαžŸαž”αŸ’αžšαž’αž”αŸ‹αžαŸ’αžŸαžΆαž…αŸ‹αžšαž”αžŸαŸ‹αž€αŸ’αžšαž»αž˜ αž αžΎαž™αž™αžΎαž„αž…αž„αŸ‹αž€αŸ†αžŽαžαŸ‹αž€αžΆαžšαž…αžΌαž›αž”αŸ’αžšαžΎαž–αž½αž€αžœαžΆ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž€αŸ’αžšαž»αž˜αž’αžΆαž…αž›αŸαž„αž”αžΆαž“αžαŸ‚αž“αŸ…αž€αŸ’αž“αž»αž„αž”αŸ’αžšαž’αž”αŸ‹αžαŸ’αžŸαžΆαž…αŸ‹αžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸαž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ”

αž’αŸ’αž“αž€αž’αžΆαž…αžŸαž˜αŸ’αžšαŸαž…αž”αžΆαž“αž“αžΌαžœαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž’αŸ’αž“αž€αž…αž„αŸ‹αž”αžΆαž“αžŠαŸ„αž™αž€αŸ†αžŽαžαŸ‹αž±αŸ’αž™αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž“αžΌαžœαž€αŸ’αžšαž»αž˜αžŠαŸ‚αž›αž˜αžΆαž“ RoleBinding αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹ Namespace ΠΈ ClusterRole αž‡αžΆαž˜αž½αž™αž“αžΉαž„αžŸαž·αž‘αŸ’αž’αž·αž€αŸ‚αžŸαž˜αŸ’αžšαž½αž›αŸ” αžαŸ†αžŽαžΆαž„ YAML αž“αžΉαž„αž˜αžΎαž›αž‘αŸ…αžŠαžΌαž…αž“αŸαŸ‡αŸ–

---
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.yamlαž“αŸ… αž‡αž½αžšαžŠαŸαž€)

αž”αž„αŸ’αž€αžΎαžαž˜αž½αž™αŸ” RoleBinding αž’αŸ’αž“αž€β€‹αž’αžΆαž…β€‹αž’αŸ’αžœαžΎβ€‹αžœαžΆβ€‹αžŠαŸ„αž™β€‹αžŠαŸƒ αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αž”αž“αŸ’αž‘αžΆαž”αŸ‹β€‹αž–αžΈβ€‹αž†αŸ’αž›αž„αž€αžΆαžαŸ‹β€‹αžŸαž‰αŸ’αž‰αžΆβ€‹αžŠαž€β€‹αžˆαŸ’αž˜αŸ„αŸ‡β€‹αž˜αž½αž™β€‹αžšαž™ αžœαžΆβ€‹αž€αŸ’αž›αžΆαž™β€‹αž‡αžΆβ€‹αž€αž·αž…αŸ’αž…αž€αžΆαžšβ€‹αžŠαŸβ€‹αž’αž»αž‰αž‘αŸ’αžšαžΆαž“αŸ‹αŸ” αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž€αž“αŸ’αž›αŸ‚αž„αžŠαŸ‚αž›αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžš Kubernetes αž„αžΆαž™αžŸαŸ’αžšαž½αž› - αž–αž½αž€αž‚αŸαž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž’αŸ’αž“αž€αž”αž„αŸ’αž€αžΎαžαž’αž“αž’αžΆαž“ Kubernetes αžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αžŠαŸ„αž™αž•αŸ’αž’αŸ‚αž€αž›αžΎαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž’αž“αž’αžΆαž“αŸ” αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαžšαž”αžŸαŸ‹αž™αžΎαž„αž™αžΎαž„αž…αž„αŸ‹αž”αž„αŸ’αž€αžΎαž RoleBinding αžαžŽαŸˆαž–αŸαž›αž€αŸ†αž–αž»αž„αž”αž„αŸ’αž€αžΎαž Namespace.

αžŠαŸ†αž”αžΌαž„αž™αžΎαž„αž€αŸ†αžŽαžαŸ‹αž˜αž»αžαž„αžΆαžš mainαžŠαŸ‚αž›αž’αŸ’αžœαžΎαž€αžΆαžšαžŠαŸ†αž‘αžΎαž„αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž€αžΆαžšαžŠαžΎαž˜αŸ’αž”αžΈαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαŸαž…αž€αŸ’αžαžΈαžαŸ’αž›αŸ‚αž„αž€αžΆαžšαžŽαŸ αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž αŸ…αžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αžŸαŸαž…αž€αŸ’αžαžΈαžαŸ’αž›αŸ‚αž„αž€αžΆαžšαžŽαŸαŸ–

(αž…αŸ†αžŽαžΆαŸ†αŸ” αž”αž€αž”αŸ’αžšαŸ‚αŸ– αž“αŸ…αž‘αžΈαž“αŸαŸ‡ αž“αž·αž„αžαžΆαž„αž€αŸ’αžšαŸ„αž˜ αž˜αžαž·αž™αŸ„αž”αž›αŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αž€αžΌαžŠαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž€αž”αŸ’αžšαŸ‚αž‡αžΆαž—αžΆαžŸαžΆαžšαž»αžŸαŸ’αžŸαžΈαŸ” αž›αžΎαžŸαž–αžΈαž“αŸαŸ‡ αž€αžΆαžšαž…αžΌαž›αž”αž“αŸ’αž‘αžΆαžαŸ‹αžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ‚αž‘αŸ…αžŠαž€αžƒαŸ’αž›αžΆαž‡αŸ†αž“αž½αžŸαž±αŸ’αž™αž•αŸ’αž‘αžΆαŸ†αž„ [αž”αžΆαž“αžŽαŸ‚αž“αžΆαŸ†αž€αŸ’αž“αž»αž„ Go] αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‚αŸ„αž›αž”αŸ†αžŽαž„αž“αŸƒαž€αžΆαžšαž’αžΆαž“αž€αžΆαž“αŸ‹αžαŸ‚αž›αŸ’αž’αž“αŸ…αž€αŸ’αž“αž»αž„αž”αŸ’αž›αž„αŸ‹ Habr αŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž€αžΆαžšαž…αž»αŸ‡αž”αž‰αŸ’αž‡αžΈαž“αžΈαž˜αž½αž™αŸ— αž˜αžΆαž“αžαŸ†αžŽαž—αŸ’αž‡αžΆαž”αŸ‹αž‘αŸ…αž€αžΆαž“αŸ‹αžŠαžΎαž˜αž“αŸ…αž›αžΎ GitHub αžŠαŸ‚αž›αž˜αžαž·αž™αŸ„αž”αž›αŸ‹ αž“αž·αž„αž•αŸ’αž‘αžΆαŸ†αž„αž‡αžΆαž—αžΆαžŸαžΆαž’αž„αŸ‹αž‚αŸ’αž›αŸαžŸαžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αŸ”)

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αž“αŸ… αž‡αž½αžšαžŠαŸαž€)

αž™αžΎαž„αž’αŸ’αžœαžΎαžŠαžΌαž…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αŸˆ

  1. αž™αžΎαž„αž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž§αž”αž€αžšαžŽαŸαžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŸαž‰αŸ’αž‰αžΆαž”αŸ’αžšαž–αŸαž“αŸ’αž’αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αžŠαžΎαž˜αŸ’αž”αžΈαž”αž„αŸ’αž€αž±αŸ’αž™αž˜αžΆαž“αž€αžΆαžšαž”αž‰αŸ’αž…αž”αŸ‹αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžšαž”αŸ’αžšαž€αž”αžŠαŸ„αž™αž‚αž»αžŽαž’αž˜αŸŒαŸ”
  2. αž™αžΎαž„β€‹αž”αŸ’αžšαžΎ WaitGroupαžŠαžΎαž˜αŸ’αž”αžΈαž”αž‰αŸ’αžˆαž”αŸ‹ goroutines αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž™αŸ‰αžΆαž„αžšαž›αžΌαž“ αž˜αž»αž“αž–αŸαž›αž”αž‰αŸ’αž…αž”αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαŸ”
  3. αž™αžΎαž„αž•αŸ’αžαž›αŸ‹αžŸαž·αž‘αŸ’αž’αž·αž…αžΌαž›αž”αŸ’αžšαžΎαž…αž„αŸ’αž€αŸ„αž˜αžŠαŸ„αž™αž”αž„αŸ’αž€αžΎαž clientset.
  4. αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš NamespaceControllerαžŠαŸ‚αž›αž€αŸ’αž“αž»αž„αž“αŸ„αŸ‡αžαž€αŸ’αž€αžœαž·αž‡αŸ’αž‡αžΆαžšαž”αžŸαŸ‹αž™αžΎαž„αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αžΉαž„αž˜αžΆαž“αž‘αžΈαžαžΆαŸ†αž„αž“αŸ…αŸ”

αž₯αž‘αžΌαžœαž“αŸαŸ‡αž™αžΎαž„αžαŸ’αžšαžΌαžœαž€αžΆαžšαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžαž€αŸ’αž€αžœαž·αž‡αŸ’αž‡αžΆαž αžΎαž™αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαžšαž”αžŸαŸ‹αž™αžΎαž„αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž”αžΆαž“αž›αžΎαž€αž‘αžΎαž„ 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.goαž“αŸ… αž‡αž½αžšαžŠαŸαž€)

αž“αŸ…αž‘αžΈαž“αŸαŸ‡αž™αžΎαž„αž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’ SharedIndexInformerαžŠαŸ‚αž›αž“αžΉαž„αž˜αžΆαž“αž”αŸ’αžšαžŸαž·αž‘αŸ’αž’αž·αž—αžΆαž– (αžŠαŸ„αž™αž”αŸ’αžšαžΎαžƒαŸ’αž›αžΆαŸ†αž„αžŸαž˜αŸ’αž„αžΆαžαŸ‹) αžšαž„αŸ‹αž…αžΆαŸ†αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž“αŸ…αž€αŸ’αž“αž»αž„ namespaces (αž’αžΆαž“αž”αž“αŸ’αžαŸ‚αž˜αž’αŸ†αž–αžΈαž’αŸ’αž“αž€αž•αŸ’αžαž›αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘ "αžαžΎαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž€αŸ†αžŽαžαŸ‹αž–αŸαž› Kubernetes αž–αž·αžαž‡αžΆαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž™αŸ‰αžΆαž„αžŠαžΌαž…αž˜αŸ’αžαŸαž…?"- αž”αŸ’αžšαž αŸ‚αž› αž€αžΆαžšαž”αž€αž”αŸ’αžšαŸ‚). αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž“αŸαŸ‡αž™αžΎαž„αž—αŸ’αž‡αžΆαž”αŸ‹ EventHandler αž‘αŸ…αž€αžΆαž“αŸ‹αž’αŸ’αž“αž€αž•αŸ’αžαž›αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž“αŸ…αž–αŸαž›αž”αž“αŸ’αžαŸ‚αž˜ namespace (Namespace) αž˜αž»αžαž„αžΆαžšαžαŸ’αžšαžΌαžœαž”αžΆαž“αž‚αŸαž αŸ…αžαžΆ createRoleBinding.

αž‡αŸ†αž αžΆαž“αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž‚αžΊαž€αŸ†αžŽαžαŸ‹αž˜αž»αžαž„αžΆαžšαž“αŸαŸ‡αŸ” 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.goαž“αŸ… αž‡αž½αžšαžŠαŸαž€)

αž™αžΎαž„αž‘αž‘αž½αž›αž”αžΆαž“αž…αž“αŸ’αž›αŸ„αŸ‡αžˆαŸ’αž˜αŸ„αŸ‡αž‡αžΆ obj αž αžΎαž™αž”αŸ†αž”αŸ’αž›αŸ‚αž„αžœαžΆαž‘αŸ…αž‡αžΆαžœαžαŸ’αžαž»αž˜αž½αž™αŸ” Namespace. αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž™αžΎαž„αž€αŸ†αžŽαžαŸ‹ RoleBindingαžŠαŸ„αž™αž•αŸ’αž’αŸ‚αž€αž›αžΎαž―αž€αžŸαžΆαžš YAML αžŠαŸ‚αž›αž”αžΆαž“αžšαŸ€αž”αžšαžΆαž”αŸ‹αž“αŸ…αžŠαžΎαž˜ αžŠαŸ„αž™αž”αŸ’αžšαžΎαžœαžαŸ’αžαž»αžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αžαž›αŸ‹ Namespace αž“αž·αž„αž€αžΆαžšαž”αž„αŸ’αž€αžΎαž RoleBinding. αž‡αžΆαž…αž»αž„αž€αŸ’αžšαŸ„αž™ αž™αžΎαž„αž€αžαŸ‹αžαŸ’αžšαžΆαžαžΆαžαžΎαž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž“αŸαŸ‡αž”αžΆαž“αž‡αŸ„αž‚αž‡αŸαž™αžŠαŸ‚αžšαž¬αž‘αŸαŸ”

αž˜αž»αžαž„αžΆαžšαž…αž»αž„αž€αŸ’αžšαŸ„αž™αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž€αŸ†αžŽαžαŸ‹αž‚αžΊ 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.goαž“αŸ… αž‡αž½αžšαžŠαŸαž€)

αž“αŸ…αž‘αžΈαž“αŸαŸ‡αž™αžΎαž„αž€αŸ†αž–αž»αž„αž“αž·αž™αžΆαž™ WaitGroupαžαžΆαž™αžΎαž„αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš goroutine αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž αŸ… namespaceInformerαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ†αžŽαžαŸ‹αž–αžΈαž˜αž»αž“αŸ” αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αžŸαž‰αŸ’αž‰αžΆαžˆαž”αŸ‹αž˜αž€αžŠαž›αŸ‹ αžœαžΆαž“αžΉαž„αž”αž‰αŸ’αž…αž”αŸ‹αž˜αž»αžαž„αžΆαžš αž‡αžΌαž“αžŠαŸ†αžŽαžΉαž„ WaitGroupαžŠαŸ‚αž›αž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαž‘αŸ€αžαž‘αŸ αž αžΎαž™αž˜αž»αžαž„αžΆαžšαž“αŸαŸ‡αž“αžΉαž„αž…αŸαž‰αŸ”

αž–αŸαžαŸŒαž˜αžΆαž“αž’αŸ†αž–αžΈαž€αžΆαžšαž€αžŸαžΆαž„ αž“αž·αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαŸαž…αž€αŸ’αžαžΈαžαŸ’αž›αŸ‚αž„αž€αžΆαžšαžŽαŸαž“αŸαŸ‡αž“αŸ…αž›αžΎαž…αž„αŸ’αž€αŸ„αž˜ Kubernetes αž’αžΆαž…αžšαž€αž”αžΆαž“αž“αŸ…αž€αŸ’αž“αž»αž„ αžƒαŸ’αž›αžΆαŸ†αž„αž“αŸ…αž›αžΎ GitHub.

αž“αŸ„αŸ‡αž αžΎαž™αž‡αžΆαžœαžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžšαžŠαŸ‚αž›αž”αž„αŸ’αž€αžΎαž RoleBinding αž–αŸαž›αžŽαžΆβ€‹ Namespace αž“αŸ…αž€αŸ’αž“αž»αž„αž…αž„αŸ’αž€αŸ„αž˜ Kubernetes αžšαž½αž…αžšαžΆαž›αŸ‹αŸ”

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹