Märge. tõlge: operaatorid on Kubernetese abitarkvara, mis on loodud teatud sündmuste korral klastri objektidel rutiinsete toimingute täitmise automatiseerimiseks. Oleme juba kirjutanud operaatoritest aastal
Otsustasin kirjutada selle postituse päriselust pärit näitega pärast seda, kui püüdsin leida Kubernetese operaatori loomise dokumentatsiooni, mis läbis koodi uurimise.
Kirjeldatav näide on järgmine: meie Kubernetese klastris igaüks Namespace
esindab meeskonna liivakastikeskkonda ja soovisime neile juurdepääsu piirata, et meeskonnad saaksid mängida ainult oma liivakastides.
Saate saavutada selle, mida soovite, määrates kasutajale rühma, millel on olemas RoleBinding
konkreetseks Namespace
и ClusterRole
toimetamisõigusega. YAML-i esitus näeb välja selline:
---
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
(
Looge üks RoleBinding
Saate seda teha käsitsi, kuid pärast saja nimeruumi piiri ületamist muutub see tüütuks ülesandeks. Siin tulevad appi Kubernetese operaatorid – need võimaldavad automatiseerida Kubernetese ressursside loomist ressursside muudatuste põhjal. Meie puhul tahame luua RoleBinding
loomise ajal Namespace
.
Kõigepealt määratleme funktsiooni main
mis teeb avalduse käitamiseks vajaliku seadistuse ja kutsub seejärel välja avalduse toimingu:
(Märge. tõlge: siin ja allpool on koodi kommentaarid tõlgitud vene keelde. Lisaks on taane muudetud vahekaartide [soovitatud Go] asemel tühikuteks ainult Habri paigutuse parema loetavuse huvides. Pärast iga kirjet on GitHubis lingid originaalile, kuhu salvestatakse ingliskeelsed kommentaarid ja vahelehed.)
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() // Ожидаем, что все остановлено
}
Teeme järgmist:
- Konfigureerime käitleja konkreetsete operatsioonisüsteemi signaalide jaoks, et põhjustada operaatori graatsilist lõpetamist.
- Me kasutame
WaitGroup
et peatada graatsiliselt kõik gorutiinid enne rakenduse lõpetamist. - Luues pakume juurdepääsu klastrile
clientset
. - Käivitamine
NamespaceController
, milles asub kogu meie loogika.
Nüüd vajame loogika alust ja meie puhul on see mainitud 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
}
(
Siin me konfigureerime SharedIndexInformer
, mis jääb tõhusalt (vahemälu kasutades) ootama muudatusi nimeruumides (loe informaatorite kohta lähemalt artiklist “EventHandler
informaatorile, nii et nimeruumi lisamisel (Namespace
) kutsutakse funktsioon createRoleBinding
.
Järgmine samm on selle funktsiooni määratlemine 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))
}
}
(
Nimeruumi saame kui obj
ja teisendada see objektiks Namespace
. Seejärel määratleme RoleBinding
, põhinedes alguses mainitud YAML-failil, kasutades antud objekti Namespace
ja loomine RoleBinding
. Lõpuks logime, kas loomine õnnestus.
Viimane määratletav funktsioon on 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
}
(
Siin me räägime WaitGroup
et käivitame gorutiini ja siis helistame namespaceInformer
, mis on eelnevalt määratletud. Kui stoppsignaal saabub, lõpetab see funktsiooni, teavita WaitGroup
, mida enam ei käivitata, ja see funktsioon sulgub.
Teavet selle avalduse loomise ja käitamise kohta Kubernetese klastris leiate aadressilt
See on see operaatori jaoks, kes loob RoleBinding
millal Namespace
Kubernetese klastris, valmis.
Allikas: www.habr.com