Анхаарна уу. орчуулга.: Операторууд нь 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