نوٹ. ترجمہ: آپریٹرز 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 میں تجویز کردہ] ٹیبز کے بجائے انڈینٹیشن کو خالی جگہوں پر درست کیا گیا ہے۔ ہر فہرست کے بعد 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