Golang හි Kubernetes සඳහා ක්රියාකරු ලිවීම

සටහන. පරිවර්තනය.: ක්‍රියාකරුවන් යනු Kubernetes සඳහා සහායක මෘදුකාංග වේ, ඇතැම් සිදුවීම් සිදු වූ විට පොකුරු වස්තු මත සාමාන්‍ය ක්‍රියාවන් ක්‍රියාත්මක කිරීම ස්වයංක්‍රීය කිරීමට නිර්මාණය කර ඇත. හි ක්‍රියාකරුවන් ගැන අපි දැනටමත් ලියා ඇත මේ ලිපිය කියවන්න, එහිදී ඔවුන් ඔවුන්ගේ කාර්යයේ මූලික අදහස් සහ මූලධර්ම ගැන කතා කළහ. නමුත් එම ද්‍රව්‍යය Kubernetes සඳහා සූදානම් කළ සංරචක ක්‍රියාත්මක කිරීමේ පැත්තෙන් බලන විට, දැන් යෝජිත නව ලිපියේ පරිවර්තනය දැනටමත් නව ක්‍රියාකරුවෙකු ක්‍රියාත්මක කිරීම මගින් ව්‍යාකූල වූ සංවර්ධක/DevOps ඉංජිනේරුවෙකුගේ දැක්මයි.

Golang හි 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

(භූමිකාව බැඳීම.yamlඇතුළත අමු)

එකක් නිර්මාණය 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()   // Ожидаем, что все остановлено
}

(main.goඇතුළත අමු)

අපි පහත සඳහන් දේ කරන්නෙමු:

  1. අපි විශේෂිත මෙහෙයුම් පද්ධති සංඥා සඳහා හසුරුවන්නක් වින්‍යාස කරන්නෙමු.
  2. අපි පාවිච්චි කරන්නේ WaitGroupයෙදුම අවසන් කිරීමට පෙර සියලුම goroutines අලංකාර ලෙස නතර කිරීමට.
  3. අපි නිර්මාණය කිරීමෙන් පොකුරට ප්රවේශය ලබා දෙන්නෙමු clientset.
  4. අපි දියත් කරනවා 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
}

(controller.goඇතුළත අමු)

මෙන්න අපි මානකරනවා SharedIndexInformer, එය ඵලදායි ලෙස (හැඹිලියක් භාවිතා කරමින්) නාම අවකාශයේ වෙනස්කම් සඳහා රැඳී සිටිනු ඇත (ලිපියේ තොරතුරු සපයන්නන් ගැන වැඩිදුර කියවන්න "Kubernetes උපලේඛකයා සැබවින්ම ක්‍රියා කරන්නේ කෙසේද?"- ආසන්න වශයෙන් පරිවර්තනය). මෙයින් පසු අපි සම්බන්ධ කරමු 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))
  }
}

(controller.goඇතුළත අමු)

අපට නාම අවකාශය ලැබෙන්නේ මෙසේය 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
}

(controller.goඇතුළත අමු)

මෙන්න අපි කතා කරනවා WaitGroupඅපි goroutine දියත් කර පසුව අමතන්න කියා namespaceInformer, කලින් නිර්වචනය කර ඇත. නැවතුම් සංඥාව පැමිණි විට, එය කාර්යය අවසන් කරනු ඇත, දැනුම් දෙන්න WaitGroup, එය තවදුරටත් ක්‍රියාත්මක නොවන අතර, මෙම ශ්‍රිතය පිටවේ.

Kubernetes පොකුරක් මත මෙම ප්රකාශය ගොඩනැගීම සහ ක්රියාත්මක කිරීම පිළිබඳ තොරතුරු සොයාගත හැකිය GitHub මත ගබඩා.

නිර්මාණය කරන ක්‍රියාකරුට එයයි RoleBinding කවදා ද Namespace Kubernetes පොකුරේ, සූදානම්.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න