ملحوظة. ترجمة.: المشغلون عبارة عن برامج مساعدة لـ 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
، والذي يقوم بالإعداد المطلوب لتشغيل العبارة ثم استدعاء إجراء العبارة:
(ملحوظة. ترجمة.: فيما بعد ، تتم ترجمة التعليقات الواردة في الكود إلى اللغة الروسية. بالإضافة إلى ذلك ، يتم تصحيح المسافة البادئة للمسافات بدلاً من علامات التبويب [موصى بها في Go] فقط لغرض قراءة أفضل في إطار تخطيط 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
لإيقاف جميع goroutines بأمان قبل إنهاء التطبيق. - نحن نوفر الوصول إلى الكتلة عن طريق إنشاء
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
أن نبدأ goroutine ثم ندعو namespaceInformer
التي تم تعريفها مسبقًا. عندما تأتي إشارة التوقف ، فإنها ستنهي الوظيفة ، وتبلغ WaitGroup
، والتي لم تعد قيد التنفيذ ، وسيتم إنهاء هذه الوظيفة.
يمكن العثور على معلومات حول إنشاء هذا البيان وتشغيله على مجموعة Kubernetes على
على هذا البيان الذي يخلق RoleBinding
متى Namespace
في مجموعة Kubernetes ، جاهزة.
المصدر: www.habr.com