Tandaan. transl.Ang mga operator ay pantulong na software para sa Kubernetes na idinisenyo upang i-automate ang mga nakagawiang pagkilos sa mga cluster object kapag nangyari ang ilang partikular na kaganapan. Nagsulat na kami tungkol sa mga operator sa , na tinalakay ang mga pangunahing ideya at prinsipyo ng pagpapatakbo. Ngunit habang ang materyal na iyon ay higit pa sa isang pananaw mula sa pananaw ng pagpapatakbo ng mga handa na bahagi ng Kubernetes, ang iminungkahing pagsasalin ng bagong artikulong ito ay ang pananaw ng isang developer/DevOps engineer, na nalilito sa pagpapatupad ng bagong operator.

Nagpasya akong isulat ang post na ito gamit ang isang real-world na halimbawa pagkatapos ng aking mga pagtatangka na maghanap ng dokumentasyon sa paglikha ng isang operator para sa Kubernetes, na humantong sa aking pag-aaral ng code.
Ang halimbawang ilalarawan ay ito: sa aming Kubernetes cluster, bawat isa Namespace kumakatawan sa kapaligiran ng sandbox ng isang koponan, at gusto naming paghigpitan ang pag-access sa kanila upang ang mga koponan ay makapaglaro lamang sa sarili nilang mga sandbox.
Ang ninanais na resulta ay maaaring makamit sa pamamagitan ng pagtatalaga ng user sa isang pangkat na mayroon RoleBinding sa tiyak Namespace ΠΈ ClusterRole na may mga karapatan sa pag-edit. Ang representasyon ng YAML ay magiging ganito:
---
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
(sa )
Upang lumikha ng ganoon RoleBinding Magagawa mo ito nang manu-mano, ngunit pagkatapos mong tumawid sa marka ng 100 namespace, ito ay nagiging nakakapagod. Dito nagagamit ang mga operator ng Kubernetesβpinapayagan ka nilang i-automate ang paggawa ng mga mapagkukunan ng Kubernetes batay sa mga pagbabago sa mapagkukunan. Sa aming kaso, gusto naming lumikha RoleBinding kapag lumilikha Namespace.
Una sa lahat, tukuyin natin ang function main, na nagsasagawa ng kinakailangang pag-setup upang patakbuhin ang operator at pagkatapos ay hinihimok ang pagkilos ng operator:
(Tandaan. transl.: Mula dito, ang mga komento sa code ay isinalin na sa Russian. Bilang karagdagan, ang mga indentasyon ay ginawang mga puwang sa halip na mga tab [inirerekomenda sa Go] para lamang sa layunin ng pagpapabuti ng pagiging madaling mabasa sa loob ng layout ng Habr. Ang pagsunod sa bawat listahan ay mga link sa orihinal na GitHub code, kung saan pinapanatili ang mga komento at tab sa English.
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() // ΠΠΆΠΈΠ΄Π°Π΅ΠΌ, ΡΡΠΎ Π²ΡΠ΅ ΠΎΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΎ
}
(sa )
Ginagawa namin ang sumusunod:
- Nag-configure kami ng handler para sa mga partikular na signal ng operating system upang maging sanhi ng magandang pagwawakas ng operator.
- Gumamit
WaitGroupupang maayos na ihinto ang lahat ng goroutine bago matapos ang aplikasyon. - Nagbibigay kami ng access sa cluster sa pamamagitan ng paggawa
clientset. - Ilunsad
NamespaceController, kung saan matatagpuan ang lahat ng ating lohika.
Ngayon kailangan namin ng isang batayan para sa lohika, at sa aming kaso ito ang nabanggit 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
}
(sa )
Dito kami nag-set up SharedIndexInformer, na mahusay na maghihintay (gamit ang cache) para sa mga pagbabago sa mga namespace (magbasa nang higit pa tungkol sa mga impormante sa artikulong ""- tinatayang pagsasalin)Pagkatapos ay kumonekta kami EventHandler sa tagapagbigay-alam, upang kapag nagdadagdag ng namespace (Namespace) ang function ay tinatawag createRoleBinding.
Ang susunod na hakbang ay upang tukuyin ang function na ito 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))
}
}
(sa )
Nakukuha namin ang namespace bilang obj at ibahin ito sa isang bagay Namespace. Pagkatapos ay tinutukoy namin RoleBinding, batay sa YAML file na binanggit sa simula, gamit ang ibinigay na bagay Namespace at paglikha RoleBindingSa wakas, nag-log kami kung matagumpay ang paglikha.
Ang huling function na kailangang tukuyin ay 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
}
(sa )
Dito tayo nagsasalita WaitGroup, na simulan namin ang goroutine at pagkatapos ay tumawag namespaceInformer, na dating tinukoy. Kapag ang isang stop signal ay natanggap, ito ay wakasan ang function, ulat WaitGroup, na hindi na tumatakbo, at ang function na ito ay magwawakas.
Ang impormasyon sa pagbuo at pagpapatakbo ng operator na ito sa isang Kubernetes cluster ay matatagpuan sa .
Sa operator na ito, na lumilikha RoleBinding sa hitsura Namespace sa Kubernetes cluster, handa na.
Pinagmulan: www.habr.com
