Nota. transl.: L-operaturi huma softwer awżiljarju għal Kubernetes, iddisinjat biex awtomat l-eżekuzzjoni ta 'azzjonijiet ta' rutina fuq oġġetti cluster meta jseħħu ċerti avvenimenti. Diġà ktibna dwar l-operaturi fil
Iddeċidejt li nikteb din il-kariga b'eżempju tal-ħajja reali wara t-tentattivi tiegħi biex insib dokumentazzjoni dwar il-ħolqien ta 'operatur għal Kubernetes, li għadda mill-istudju tal-kodiċi.
L-eżempju li se jiġi deskritt huwa dan: fil-cluster Kubernetes tagħna, kull wieħed Namespace
jirrappreżenta l-ambjent ta 'sandbox ta' tim, u ridna nillimitaw l-aċċess għalihom sabiex it-timijiet ikunu jistgħu jilagħbu biss fis-sandboxes tagħhom stess.
Tista 'tikseb dak li trid billi tassenja utent grupp li għandu RoleBinding
għal speċifiċi Namespace
и ClusterRole
bi drittijiet ta’ editjar. Ir-rappreżentazzjoni YAML se tidher bħal din:
---
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
(
Oħloq wieħed RoleBinding
Tista 'tagħmel dan manwalment, iżda wara li taqsam il-marka tal-mitt namespaces, issir kompitu tedious. Dan huwa fejn l-operaturi Kubernetes jiġu utli—jippermettulek awtomatizza l-ħolqien tar-riżorsi Kubernetes ibbażat fuq bidliet fir-riżorsi. Fil-każ tagħna rridu noħolqu RoleBinding
waqt li toħloq Namespace
.
L-ewwelnett, ejja niddefinixxu l-funzjoni main
li jagħmel is-setup meħtieġ biex iħaddem id-dikjarazzjoni u mbagħad isejjaħ l-azzjoni tad-dikjarazzjoni:
(Nota. transl.: hawn u taħt il-kummenti fil-kodiċi huma tradotti għar-Russu. Barra minn hekk, l-indentazzjoni ġiet ikkoreġuta għal spazji minflok [rakkomandat f'Go] tabs biss għall-iskop ta' leġibilità aħjar fit-tqassim tal-Habr. Wara kull lista hemm links għall-oriġinal fuq GitHub, fejn jinħażnu kummenti u tabs bil-lingwa Ingliża.)
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() // Ожидаем, что все остановлено
}
Aħna nagħmlu dan li ġej:
- Aħna kkonfigurat handler għal sinjali speċifiċi tas-sistema operattiva biex tikkawża t-terminazzjoni graceful tal-operatur.
- Aħna nużaw
WaitGroup
biex twaqqaf bil-grazzja l-goroutines kollha qabel ittemm l-applikazzjoni. - Aħna nipprovdu aċċess għall-cluster billi noħolqu
clientset
. - Tnedija
NamespaceController
, li fiha se tkun tinsab il-loġika tagħna kollha.
Issa neħtieġu bażi għal-loġika, u fil-każ tagħna din hija dik li tissemma 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
}
(
Hawnhekk aħna kkonfigurat SharedIndexInformer
, li effettivament (bl-użu ta' cache) tistenna għal bidliet fl-ispazji tal-isem (aqra aktar dwar informaturi fl-artiklu “EventHandler
lill-informatur, sabiex meta żżid spazju tal-isem (Namespace
) tissejjaħ funzjoni createRoleBinding
.
Il-pass li jmiss huwa li tiddefinixxi din il-funzjoni 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))
}
}
(
Nirċievu l-ispazju tal-isem bħala obj
u jaqilbuh għal oġġett Namespace
. Imbagħad niddefinixxu RoleBinding
, ibbażat fuq il-fajl YAML imsemmi fil-bidu, bl-użu tal-oġġett ipprovdut Namespace
u l-ħolqien RoleBinding
. Fl-aħħarnett, nilloggjaw jekk il-ħolqien kienx ta 'suċċess.
L-aħħar funzjoni li għandha tiġi definita hija 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
}
(
Hawnhekk qed nitkellmu WaitGroup
li nniedu l-goroutine u mbagħad insejħu namespaceInformer
, li ġie definit qabel. Meta jasal is-sinjal ta 'waqfien, se jispiċċa l-funzjoni, informa WaitGroup
, li m'għadux esegwit, u din il-funzjoni se toħroġ.
Informazzjoni dwar il-bini u t-tħaddim ta' din id-dikjarazzjoni fuq cluster Kubernetes tista' tinstab fi
Dak hu għall-operatur li joħloq RoleBinding
meta Namespace
fil-cluster Kubernetes, lest.
Sors: www.habr.com