Remak. trad.: Operatè yo se lojisyèl oksilyè pou Kubernetes, ki fèt pou otomatize ekzekisyon aksyon woutin sou objè gwoup lè sèten evènman rive. Nou te deja ekri sou operatè yo nan
Mwen deside ekri pòs sa a ak yon egzanp lavi reyèl apre tantativ mwen jwenn dokiman sou kreye yon operatè pou Kubernetes, ki te ale nan etidye kòd la.
Egzanp ki pral dekri a se sa a: nan gwoup Kubernetes nou an, chak Namespace
reprezante anviwònman sandbox yon ekip, e nou te vle limite aksè a yo pou ekip yo te kapab jwe sèlman nan pwòp sandbox yo.
Ou ka reyalize sa ou vle lè w bay yon itilizatè yon gwoup ki genyen RoleBinding
a espesifik Namespace
и ClusterRole
ak dwa koreksyon. Reprezantasyon YAML a pral sanble tankou sa a:
---
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
(
Kreye youn RoleBinding
Ou ka fè li manyèlman, men apre yo fin travèse make la san espas non, li vin tounen yon travay fatigan. Sa a se kote operatè Kubernetes yo vin an sou la men—yo pèmèt ou otomatize kreyasyon an nan resous Kubernetes ki baze sou chanjman nan resous yo. Nan ka nou an nou vle kreye RoleBinding
pandan y ap kreye Namespace
.
Premye a tout, se pou yo defini fonksyon an main
ki fè konfigirasyon ki nesesè pou kouri deklarasyon an epi li rele aksyon deklarasyon an:
(Remak. trad.: isit la ak anba kòmantè yo nan kòd la yo tradui nan Ris. Anplis de sa, yo te korije endentasyon an nan espas olye pou yo [rekòmande nan Go] onglet sèlman nan bi pou yo ka pi byen lizibilite nan layout Habr la. Apre chak lis, gen lyen ki mennen nan orijinal la sou GitHub, kote yo estoke kòmantè ak onglè ann angle.)
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() // Ожидаем, что все остановлено
}
(
Nou fè bagay sa yo:
- Nou konfigirasyon yon moun kap okipe siyal sistèm operasyon espesifik yo lakòz revokasyon grasyeuz nan operatè a.
- Nou itilize
WaitGroup
pou sispann tout goroutines yo anvan ou mete fen nan aplikasyon an. - Nou bay aksè nan gwoup la pa kreye
clientset
. - Lanse
NamespaceController
, nan ki tout lojik nou yo pral lokalize.
Koulye a, nou bezwen yon baz pou lojik, ak nan ka nou an sa a se youn nan mansyone 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
}
(
Isit la nou konfigirasyon SharedIndexInformer
, ki pral efektivman (lè l sèvi avèk yon kachèt) tann pou chanjman nan espas non yo (li plis sou enfomatè nan atik la "EventHandler
bay enfòmatè a, pou lè w ajoute yon espas non (Namespace
) yo rele fonksyon createRoleBinding
.
Pwochen etap la se defini fonksyon sa a 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))
}
}
(
Nou jwenn namespace la kòm obj
epi konvèti li an yon objè Namespace
. Lè sa a, nou defini RoleBinding
, ki baze sou dosye YAML mansyone nan kòmansman an, lè l sèvi avèk objè yo bay la Namespace
ak kreye RoleBinding
. Finalman, nou konekte si kreyasyon an te reyisi.
Dènye fonksyon yo dwe defini se 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
}
(
Men nap pale WaitGroup
ke nou lanse goroutine a ak Lè sa a, rele namespaceInformer
, ki te deja defini. Lè siyal la sispann rive, li pral fini fonksyon an, enfòme WaitGroup
, ki pa egzekite ankò, epi fonksyon sa a pral sòti.
Ou ka jwenn enfòmasyon sou bati ak kouri deklarasyon sa a sou yon gwoup Kubernetes nan
Sa a se li pou operatè a ki kreye RoleBinding
Kilè Namespace
nan gwoup Kubernetes, pare.
Sous: www.habr.com