Qeyd. tərcümə.Operatorlar müəyyən hadisələr baş verdikdə klaster obyektlərində gündəlik hərəkətləri avtomatlaşdırmaq üçün nəzərdə tutulmuş Kubernetes üçün köməkçi proqramdır. Biz artıq operatorlar haqqında yazmışıq əsas ideyaları və fəaliyyət prinsiplərini müzakirə edən . Lakin bu material hazır Kubernetes komponentlərinin istismarı baxımından daha çox perspektiv olsa da, bu yeni məqalənin təklif olunan tərcüməsi yeni operatorun tətbiqi ilə çaşqın qalan bir inkişaf etdiricinin/DevOps mühəndisinin perspektividir.

Kubernetes üçün operator yaratmaq üçün sənədləri tapmaq cəhdlərimdən sonra bu yazını real dünya nümunəsi ilə yazmaq qərarına gəldim və bu, kodu öyrənməyimə səbəb oldu.
Təsvir ediləcək nümunə belədir: Kubernetes klasterimizdə hər biri Namespace komandanın sandbox mühitini təmsil edir və biz onlara girişi məhdudlaşdırmaq istədik ki, komandalar yalnız öz qum qutularında oynaya bilsinlər.
İstənilən nəticə istifadəçini olan qrupa təyin etməklə əldə edilə bilər RoleBinding konkretə Namespace и ClusterRole redaktə hüququ ilə. YAML təqdimatı belə görünəcək:
---
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(, in )
Belə yaratmaq RoleBinding Bunu əl ilə edə bilərsiniz, lakin 100 ad sahəsi nişanını keçdikdən sonra bu, yorucu olur. Burada Kubernetes operatorları kömək edir – onlar sizə resurs dəyişiklikləri əsasında Kubernetes resurslarının yaradılmasını avtomatlaşdırmağa imkan verir. Bizim vəziyyətimizdə biz yaratmaq istəyirik RoleBinding yaratarkən Namespace.
Əvvəlcə funksiyanı təyin edək mainoperatoru işə salmaq üçün tələb olunan quraşdırmanı yerinə yetirir və sonra operatorun hərəkətini çağırır:
(Qeyd. tərcümə.: Bundan sonra koddakı şərhlər rus dilinə tərcümə edilmişdir. Əlavə olaraq, abzaslar yalnız Habr tərtibatında oxunaqlılığı yaxşılaşdırmaq məqsədilə [Get-də tövsiyə olunur] nişanlar əvəzinə boşluqlara dəyişdirilib. Hər bir siyahıdan sonra ingiliscə şərhlər və nişanlar qorunub saxlanılan orijinal GitHub koduna keçidlər var.
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() // Ожидаем, что все остановлено
}(, in )
Biz aşağıdakıları edirik:
- Operatorun zərif şəkildə dayandırılmasına səbəb olmaq üçün xüsusi əməliyyat sistemi siqnalları üçün işləyicini konfiqurasiya edirik.
- Biz istifadə edirik
WaitGroupproqram bitməzdən əvvəl bütün goroutinləri zərif şəkildə dayandırmaq. - Yaratmaqla klasterə girişi təmin edirik
clientset. - Başlat
NamespaceController, bütün məntiqimizin yerləşəcəyi.
İndi məntiq üçün əsas lazımdır və bizim vəziyyətimizdə qeyd olunandır 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
}(, in )
Burada qurduq SharedIndexInformer, bu, səmərəli şəkildə (keşdən istifadə etməklə) ad boşluqlarında dəyişiklikləri gözləyəcək (məqalədə məlumat verənlər haqqında daha çox oxuyun- təqribən. tərcümə.)Bundan sonra bağlanırıq EventHandler məlumat verənə, belə ki, ad sahəsi əlavə edərkən (Namespace) funksiyası çağırılır createRoleBinding.
Növbəti addım bu funksiyanı təyin etməkdir 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))
}
}(, in )
Biz ad sahəsini alırıq obj və onu obyektə çevirmək Namespace. Sonra müəyyən edirik RoleBinding, təqdim olunan obyektdən istifadə edərək, əvvəlində qeyd olunan YAML faylı əsasında Namespace və yaratmaq RoleBindingNəhayət, yaradılışın uğurlu olub olmadığını qeyd edirik.
Müəyyən edilməli olan son funksiyadır 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
}(, in )
Burada danışırıq WaitGroup, biz goroutine başlamaq və sonra zəng ki, namespaceInformerəvvəllər müəyyən edilmişdi. Dayanma siqnalı qəbul edildikdə, o, funksiyanı, hesabatı dayandıracaq WaitGroup, artıq işləmir və bu funksiya dayandırılacaq.
Bu operatoru Kubernetes klasterində qurmaq və idarə etmək haqqında məlumatı burada tapa bilərsiniz .
Yaradan bu operatorda RoleBinding görünüşünə görə Namespace Kubernetes klasterində hazırdır.
Mənbə: www.habr.com
