נאטיץ. טראַנסל.: אָפּערייטערז זענען אַגזיליערי ווייכווארג פֿאַר 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
אין די קובערנעטעס קנויל, גרייט.
מקור: www.habr.com