Ескерту. аударма: Операторлар - белгілі бір оқиғалар орын алған кезде кластер нысандарындағы әдеттегі әрекеттерді орындауды автоматтандыруға арналған Kubernetes үшін көмекші бағдарламалық құрал. Біз операторлар туралы бұрын жазғанбыз
Мен бұл жазбаны кодты зерттеген Kubernetes операторын құру бойынша құжаттаманы табуға тырысқаннан кейін нақты өмірлік мысалмен жазуды шештім.
Сипатталған мысал мынада: біздің Kubernetes кластерінде әрқайсысы 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
Мұны қолмен жасауға болады, бірақ жүз аттар кеңістігінің белгісін кесіп өткеннен кейін бұл жалықтыратын тапсырмаға айналады. Бұл жерде Kubernetes операторлары көмекке келеді — олар ресурстардағы өзгерістер негізінде Kubernetes ресурстарын жасауды автоматтандыруға мүмкіндік береді. Біздің жағдайда біз жасағымыз келеді RoleBinding
құру кезінде Namespace
.
Ең алдымен функцияны анықтайық main
ол мәлімдемені іске қосу үшін қажетті орнатуды жасайды, содан кейін мәлімдеме әрекетін шақырады:
(Ескерту. аударма: мұнда және төменде кодтағы түсініктемелер орыс тіліне аударылған. Сонымен қатар, шегініс тек Habr орналасуында жақсырақ оқылу мақсатында [Өтуде ұсынылған] қойындыларының орнына бос орындарға түзетілді. Әрбір листингтен кейін ағылшын тіліндегі түсініктемелер мен қойындылар сақталған 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() // Ожидаем, что все остановлено
}
Біз келесі әрекеттерді орындаймыз:
- Операторды керемет түрде тоқтату үшін арнайы операциялық жүйе сигналдары үшін өңдегішті конфигурациялаймыз.
- Біз қолданамыз
WaitGroup
қолданбаны аяқтамас бұрын барлық горутиндерді мұқият тоқтату үшін. - Біз кластерге қол жеткізуді жасау арқылы қамтамасыз етеміз
clientset
. - Іске қосу
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
}
(
Мұнда біз конфигурациялаймыз 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))
}
}
(
Біз аттар кеңістігін аламыз 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
}
(
Міне, біз сөйлесеміз WaitGroup
біз горутинді іске қосамыз, содан кейін қоңырау шаламыз namespaceInformer
, ол бұрын анықталған. Тоқтау сигналы келгенде, ол функцияны аяқтайды, хабарлаңыз WaitGroup
, ол енді орындалмайды және бұл функция шығады.
Бұл мәлімдемені Kubernetes кластерінде құру және іске қосу туралы ақпаратты мына жерден табуға болады
Бұл жасаушы оператор үшін RoleBinding
қашан Namespace
Kubernetes кластерінде дайын.
Ақпарат көзі: www.habr.com