เช—เซ‹เชฒเชพเช‚เช—เชฎเชพเช‚ เช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เชฎเชพเชŸเซ‡ เช“เชชเชฐเซ‡เชŸเชฐ เชฒเช–เชตเซเช‚

เชจเซ‰เซ…เชง. เช…เชจเซเชตเชพเชฆ: เช“เชชเชฐเซ‡เชŸเชฐเซเชธ เช เช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เชฎเชพเชŸเซ‡ เชธเชนเชพเชฏเช• เชธเซ‹เชซเซเชŸเชตเซ‡เชฐ เช›เซ‡, เชœเซเชฏเชพเชฐเซ‡ เช…เชฎเซเช• เช˜เชŸเชจเชพเช“ เชฌเชจเซ‡ เชคเซเชฏเชพเชฐเซ‡ เช•เซเชฒเชธเซเชŸเชฐ เช‘เชฌเซเชœเซ‡เช•เซเชŸเซเชธ เชชเชฐ เชจเชฟเชฏเชฎเชฟเชค เช•เซเชฐเชฟเชฏเชพเช“เชจเชพ เช…เชฎเชฒเชจเซ‡ เชธเซเชตเชšเชพเชฒเชฟเชค เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชฐเชšเชพเชฏเซ‡เชฒ เช›เซ‡. เชฎเชพเช‚ เช“เชชเชฐเซ‡เชŸเชฐเซ‹ เชตเชฟเชถเซ‡ เช…เชฎเซ‡ เชชเชนเซ‡เชฒเซ‡เชฅเซ€ เชœ เชฒเช–เซเชฏเซเช‚ เช›เซ‡ เช† เชฒเซ‡เช–, เชœเซเชฏเชพเช‚ เชคเซ‡เช“เช เชคเซ‡เชฎเชจเชพ เช•เชพเชฐเซเชฏเชจเชพ เชฎเซ‚เชณเชญเซ‚เชค เชตเชฟเชšเชพเชฐเซ‹ เช…เชจเซ‡ เชธเชฟเชฆเซเชงเชพเช‚เชคเซ‹ เชตเชฟเชถเซ‡ เชตเชพเชค เช•เชฐเซ€. เชชเชฐเช‚เชคเซ เชœเซ‹ เชคเซ‡ เชธเชพเชฎเช—เซเชฐเซ€ เช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เชฎเชพเชŸเซ‡ เชคเซˆเชฏเชพเชฐ เช˜เชŸเช•เซ‹เชจเชพ เชธเช‚เชšเชพเชฒเชจเชจเซ€ เชฌเชพเชœเซเชฅเซ€ เชตเชงเซ เชฆเซƒเชทเซเชŸเชฟเช•เซ‹เชฃ เชงเชฐเชพเชตเชคเซ€ เชนเชคเซ€, เชคเซ‹ เชนเชตเซ‡ เชชเซเชฐเชธเซเชคเชพเชตเชฟเชค เชจเชตเชพ เชฒเซ‡เช–เชจเซ‹ เช…เชจเซเชตเชพเชฆ เชชเชนเซ‡เชฒเชพเชฅเซ€ เชœ เชจเชตเชพ เช“เชชเชฐเซ‡เชŸเชฐเชจเชพ เช…เชฎเชฒเซ€เช•เชฐเชฃเชฅเซ€ เชฎเซ‚เช‚เชเชพเชฏเซ‡เชฒเชพ เชตเชฟเช•เชพเชธเช•เชฐเซเชคเชพ/DevOps เชเชจเซเชœเชฟเชจเชฟเชฏเชฐเชจเซ€ เชฆเซเชฐเชทเซเชŸเชฟ เช›เซ‡.

เช—เซ‹เชฒเชพเช‚เช—เชฎเชพเช‚ เช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เชฎเชพเชŸเซ‡ เช“เชชเชฐเซ‡เชŸเชฐ เชฒเช–เชตเซเช‚

เช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เชฎเชพเชŸเซ‡ เช“เชชเชฐเซ‡เชŸเชฐ เชฌเชจเชพเชตเชตเชพ เชฎเชพเชŸเซ‡เชจเชพ เชฆเชธเซเชคเชพเชตเซ‡เชœเซ‹ เชถเซ‹เชงเชตเชพเชจเชพ เชฎเชพเชฐเชพ เชชเซเชฐเชฏเชพเชธเซ‹ เชชเช›เซ€ เชฎเซ‡เช‚ เช† เชชเซ‹เชธเซเชŸเชจเซ‡ เชตเชพเชธเซเชคเชตเชฟเช• เชœเซ€เชตเชจเชจเชพ เช‰เชฆเชพเชนเชฐเชฃ เชธเชพเชฅเซ‡ เชฒเช–เชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซเชฏเซเช‚, เชœเซ‡ เช•เซ‹เชกเชจเซ‹ เช…เชญเซเชฏเชพเชธ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ เชนเชคเซ‹.

เชœเซ‡ เช‰เชฆเชพเชนเชฐเชฃเชจเซเช‚ เชตเชฐเซเชฃเชจ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡ เชคเซ‡ เช† เช›เซ‡: เช…เชฎเชพเชฐเชพ เช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เช•เซเชฒเชธเซเชŸเชฐเชฎเชพเช‚, เชฆเชฐเซ‡เช• 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 เชคเชฎเซ‡ เชคเซ‡ เชœเชพเชคเซ‡ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹, เชชเชฐเช‚เชคเซ เชธเซ‹ เชจเซ‡เชฎเชธเซเชชเซ‡เชธ เชšเชฟเชนเซเชจเชจเซ‡ เชชเชพเชฐ เช•เชฐเซเชฏเชพ เชชเช›เซ€, เชคเซ‡ เชเช• เช•เช‚เชŸเชพเชณเชพเชœเชจเช• เช•เชพเชฐเซเชฏ เชฌเชจเซ€ เชœเชพเชฏ เช›เซ‡. เช† เชคเซ‡ เช›เซ‡ เชœเซเชฏเชพเช‚ เช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เช“เชชเชฐเซ‡เชŸเชฐเซ‹ เช•เชพเชฎเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡-เชคเซ‡เช“ เชคเชฎเชจเซ‡ เชธเช‚เชธเชพเชงเชจเซ‹เชฎเชพเช‚ เชซเซ‡เชฐเชซเชพเชฐเชจเชพ เช†เชงเชพเชฐเซ‡ เช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เชธเช‚เชธเชพเชงเชจเซ‹เชจเซ€ เชฐเชšเชจเชพเชจเซ‡ เชธเซเชตเชšเชพเชฒเชฟเชค เช•เชฐเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡. เช…เชฎเชพเชฐเชพ เช•เชฟเชธเซเชธเชพเชฎเชพเช‚ เช…เชฎเซ‡ เชฌเชจเชพเชตเชตเชพ เชฎเชพเช‚เช—เซ€เช เช›เซ€เช RoleBinding เชฌเชจเชพเชตเชคเซ€ เชตเช–เชคเซ‡ Namespace.

เชธเซŒ เชชเซเชฐเชฅเชฎ, เชšเชพเชฒเซ‹ เชซเช‚เช•เซเชถเชจเชจเซ‡ เชตเซเชฏเชพเช–เซเชฏเชพเชฏเชฟเชค เช•เชฐเซ€เช mainเชœเซ‡ เชธเซเชŸเซ‡เชŸเชฎเซ‡เชจเซเชŸ เชšเชฒเชพเชตเชตเชพ เชฎเชพเชŸเซ‡ เชœเชฐเซ‚เชฐเซ€ เชธเซ‡เชŸเช…เชช เช•เชฐเซ‡ เช›เซ‡ เช…เชจเซ‡ เชชเช›เซ€ เชธเซเชŸเซ‡เชŸเชฎเซ‡เชจเซเชŸ เชเช•เซเชถเชจเชจเซ‡ เช•เซ‰เชฒ เช•เชฐเซ‡ เช›เซ‡:

(เชจเซ‰เซ…เชง. เช…เชจเซเชตเชพเชฆ: เช•เซ‹เชกเชฎเชพเช‚เชจเซ€ เชŸเชฟเชชเซเชชเชฃเซ€เช“ เช…เชนเซ€เช‚ เช…เชจเซ‡ เชจเซ€เชšเซ‡ เชฐเชถเชฟเชฏเชจเชฎเชพเช‚ เช…เชจเซเชตเชพเชฆเชฟเชค เช›เซ‡. เชตเชงเซเชฎเชพเช‚, เชฎเชพเชคเซเชฐ Habr เชฒเซ‡เช†เช‰เชŸเชจเซ€ เช…เช‚เชฆเชฐ เชตเชงเซ เชธเชพเชฐเซ€ เชฐเซ€เชคเซ‡ เชตเชพเช‚เชšเซ€ เชถเช•เชพเชฏ เชคเซ‡ เชนเซ‡เชคเซเชฅเซ€ เช‡เชจเซเชกเซ‡เชจเซเชŸเซ‡เชถเชจเชจเซ‡ [Go เชฎเชพเช‚ เชญเชฒเชพเชฎเชฃ เช•เชฐเซ‡เชฒ] เชŸเซ‡เชฌเชจเซ‡ เชฌเชฆเชฒเซ‡ เช–เชพเชฒเซ€ เชœเช—เซเชฏเชพเช“ เชชเชฐ เชธเซเชงเชพเชฐเซ‡เชฒ เช›เซ‡. เชฆเชฐเซ‡เช• เชธเซ‚เชšเชฟ เชชเช›เซ€ 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()   // ะžะถะธะดะฐะตะผ, ั‡ั‚ะพ ะฒัะต ะพัั‚ะฐะฝะพะฒะปะตะฝะพ
}

(เชฎเซเช–เซเชฏ.เช—เซ‹เชฎเชพเช‚ เช•เชพเชšเชพ)

เช…เชฎเซ‡ เชจเซ€เชšเซ‡ เชฎเซเชœเชฌ เช•เชฐเซ€เช เช›เซ€เช:

  1. เช“เชชเชฐเซ‡เชŸเชฐเชจเซ€ เช†เช•เชฐเซเชทเช• เชธเชฎเชพเชชเซเชคเชฟเชจเซเช‚ เช•เชพเชฐเชฃ เชฌเชจเซ‡ เชคเซ‡ เชฎเชพเชŸเซ‡ เช…เชฎเซ‡ เชšเซ‹เช•เซเช•เชธ เช“เชชเชฐเซ‡เชŸเชฟเช‚เช— เชธเชฟเชธเซเชŸเชฎ เชธเชฟเช—เซเชจเชฒเซ‹ เชฎเชพเชŸเซ‡ เชนเซ‡เชจเซเชกเชฒเชฐเชจเซ‡ เช—เซ‹เช เชตเซ€เช เช›เซ€เช.
  2. เช…เชฎเซ‡ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เช เช›เซ€เช WaitGroupเชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชจเซ‡ เชธเชฎเชพเชชเซเชค เช•เชฐเชคเชพ เชชเชนเซ‡เชฒเชพ เชคเชฎเชพเชฎ เช—เซ‹เชฐเซ‹เชŸเซ€เชจเชจเซ‡ เช†เช•เชฐเซเชทเช• เชฐเซ€เชคเซ‡ เชฌเช‚เชง เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡.
  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, เชœเซ‡ เช…เชธเชฐเช•เชพเชฐเช• เชฐเซ€เชคเซ‡ (เช•เซ‡เชถเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡) เชจเซ‡เชฎเชธเซเชชเซ‡เชธเชฎเชพเช‚ เชซเซ‡เชฐเชซเชพเชฐเซ‹เชจเซ€ เชฐเชพเชน เชœเซ‹เชถเซ‡ (เชฒเซ‡เช–เชฎเชพเช‚ เชฌเชพเชคเชฎเซ€เชฆเชพเชฐเซ‹ เชตเชฟเชถเซ‡ เชตเชงเซ เชตเชพเช‚เชšเซ‹ โ€œเช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เชถเซ‡เชกเซเชฏเซ‚เชฒเชฐ เช–เชฐเซ‡เช–เชฐ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช•เชพเชฎ เช•เชฐเซ‡ เช›เซ‡?"- เช†เชถเชฐเซ‡ เช…เชจเซเชตเชพเชฆ). เช† เชชเช›เซ€ เช…เชฎเซ‡ เช•เชจเซ‡เช•เซเชŸ เช•เชฐเซ€เช เช›เซ€เช EventHandler เชฎเชพเชนเชฟเชคเซ€ เช†เชชเชจเชพเชฐเชจเซ‡, เชœเซ‡เชฅเซ€ เชœเซเชฏเชพเชฐเซ‡ เชจเซ‡เชฎเชธเซเชชเซ‡เชธ เช‰เชฎเซ‡เชฐเชคเซ€ เชตเช–เชคเซ‡ (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เช•เซ‡ เช…เชฎเซ‡ เช—เซ‹เชฐเซ‹เชŸเซ€เชจ เชฒเซ‹เชจเซเชš เช•เชฐเซ€เช เช›เซ€เช เช…เชจเซ‡ เชชเช›เซ€ เช•เซ‰เชฒ เช•เชฐเซ€เช เช›เซ€เช namespaceInformer, เชœเซ‡ เช…เช—เชพเช‰ เชตเซเชฏเชพเช–เซเชฏเชพเชฏเชฟเชค เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ€ เช›เซ‡. เชœเซเชฏเชพเชฐเซ‡ เชธเซเชŸเซ‹เชช เชธเชฟเช—เซเชจเชฒ เช†เชตเซ‡ เช›เซ‡, เชคเซเชฏเชพเชฐเซ‡ เชคเซ‡ เช•เชพเชฐเซเชฏเชจเซ‡ เชธเชฎเชพเชชเซเชค เช•เชฐเชถเซ‡, เชœเชพเชฃ เช•เชฐเซ‹ WaitGroup, เชœเซ‡ เชฒเชพเช‚เชฌเชพ เชธเชฎเชฏ เชธเซเชงเซ€ เชเช•เซเชเชฟเช•เซเชฏเซเชŸ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡ เชจเชนเซ€เช‚, เช…เชจเซ‡ เช† เชซเช‚เช•เซเชถเชจ เชฌเชนเชพเชฐ เชจเซ€เช•เชณเซ€ เชœเชถเซ‡.

เช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เช•เซเชฒเชธเซเชŸเชฐ เชชเชฐ เช† เชจเชฟเชตเซ‡เชฆเชจ เชฌเชจเชพเชตเชตเชพ เช…เชจเซ‡ เชšเชฒเชพเชตเชตเชพ เชตเชฟเชถเซ‡เชจเซ€ เชฎเชพเชนเชฟเชคเซ€ เช†เชฎเชพเช‚ เชฎเชณเซ€ เชถเช•เซ‡ เช›เซ‡ GitHub เชชเชฐ เชฐเซ€เชชเซ‹เชเซ€เชŸเชฐเซ€เช.

เชคเซ‡ เช“เชชเชฐเซ‡เชŸเชฐ เชฎเชพเชŸเซ‡ เช›เซ‡ เชœเซ‡ เชฌเชจเชพเชตเซ‡ เช›เซ‡ RoleBinding เช•เซเชฏเชพเชฐเซ‡ Namespace เช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เช•เซเชฒเชธเซเชŸเชฐเชฎเชพเช‚, เชคเซˆเชฏเชพเชฐ.

เชธเซ‹เชฐเซเชธ: www.habr.com

เชเช• เชŸเชฟเชชเซเชชเชฃเซ€ เช‰เชฎเซ‡เชฐเซ‹