Nodyn. traws.: Mae gweithredwyr yn feddalwedd ategol ar gyfer Kubernetes, sydd wedi'u cynllunio i awtomeiddio gweithredu gweithredoedd arferol ar wrthrychau clwstwr pan fydd digwyddiadau penodol yn digwydd. Rydym eisoes wedi ysgrifennu am weithredwyr yn
Penderfynais ysgrifennu'r swydd hon gydag enghraifft bywyd go iawn ar ôl fy ymdrechion i ddod o hyd i ddogfennaeth ar greu gweithredwr ar gyfer Kubernetes, a aeth trwy astudio'r cod.
Yr enghraifft a fydd yn cael ei disgrifio yw hyn: yn ein clwstwr Kubernetes, bob un Namespace
cynrychioli amgylchedd blwch tywod tîm, ac roeddem am gyfyngu mynediad iddynt fel mai dim ond yn eu blychau tywod eu hunain y gallai timau chwarae.
Gallwch chi gyflawni'r hyn rydych chi ei eisiau trwy aseinio grŵp defnyddiwr sydd wedi RoleBinding
i benodol Namespace
и ClusterRole
gyda hawliau golygu. Bydd cynrychiolaeth YAML yn edrych fel hyn:
---
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
(
Creu un RoleBinding
Gallwch chi ei wneud â llaw, ond ar ôl croesi'r marc can gofod enwau, mae'n dod yn dasg ddiflas. Dyma lle mae gweithredwyr Kubernetes yn ddefnyddiol - maen nhw'n caniatáu ichi awtomeiddio'r broses o greu adnoddau Kubernetes yn seiliedig ar newidiadau i adnoddau. Yn ein hachos ni rydym am greu RoleBinding
wrth greu Namespace
.
Yn gyntaf oll, gadewch i ni ddiffinio'r swyddogaeth main
sy'n gwneud y gosodiad gofynnol i redeg y datganiad ac yna'n galw'r datganiad yn weithred:
(Nodyn. traws.: yma ac isod mae'r sylwadau yn y cod yn cael eu cyfieithu i Rwsieg. Yn ogystal, mae'r mewnoliad wedi'i gywiro i fylchau yn lle tabiau [a argymhellir yn Go] yn unig er mwyn gwella darllenadwyedd o fewn cynllun Habr. Ar ôl pob rhestriad mae dolenni i'r gwreiddiol ar GitHub, lle mae sylwadau a thabiau Saesneg yn cael eu storio.)
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() // Ожидаем, что все остановлено
}
Rydym yn gwneud y canlynol:
- Rydym yn ffurfweddu triniwr ar gyfer signalau system weithredu penodol i achosi terfynu gosgeiddig y gweithredwr.
- Rydym yn defnyddio
WaitGroup
i atal pob goroutines yn osgeiddig cyn terfynu'r cais. - Rydym yn darparu mynediad i'r clwstwr trwy greu
clientset
. - Lansio
NamespaceController
, yn yr hwn y bydd ein holl resymeg wedi ei lleoli.
Nawr mae angen sail ar gyfer rhesymeg, ac yn ein hachos ni dyma'r un a grybwyllir 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
}
(
Yma rydym yn ffurfweddu SharedIndexInformer
, a fydd i bob pwrpas (gan ddefnyddio storfa) yn aros am newidiadau mewn gofodau enwau (darllenwch fwy am hysbyswyr yn yr erthygl “EventHandler
i'r hysbyswr, fel wrth ychwanegu gofod enw (Namespace
) swyddogaeth yn cael ei alw createRoleBinding
.
Y cam nesaf yw diffinio'r swyddogaeth hon 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))
}
}
(
Cawn y gofod enw fel obj
a'i drawsnewid yn wrthrych Namespace
. Yna rydym yn diffinio RoleBinding
, yn seiliedig ar y ffeil YAML a grybwyllir ar y dechrau, gan ddefnyddio'r gwrthrych a ddarperir Namespace
a chreu RoleBinding
. Yn olaf, rydym yn cofnodi a oedd y greadigaeth yn llwyddiannus.
Y swyddogaeth olaf i'w diffinio yw 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
}
(
Dyma ni yn siarad WaitGroup
ein bod yn lansio'r goroutine ac yna'n galw namespaceInformer
, sydd wedi'i ddiffinio'n flaenorol. Pan fydd y signal stopio yn cyrraedd, bydd yn dod â'r swyddogaeth i ben, hysbysu WaitGroup
, nad yw bellach yn cael ei weithredu, a bydd y swyddogaeth hon yn gadael.
Gellir dod o hyd i wybodaeth am adeiladu a rhedeg y datganiad hwn ar glwstwr Kubernetes yn
Dyna ni ar gyfer y gweithredwr sy'n creu RoleBinding
pryd Namespace
yn y clwstwr Kubernetes, yn barod.
Ffynhonnell: hab.com