GolangでKubernetesの演算子を作成する

ご注意 perev。 :オペレーターは、特定のイベントのクラスターオブジェクトでのルーチン操作を自動化するように設計されたKubernetesサポートソフトウェアです。 この記事では、演算子についてすでに書いています 。そこでは、演算子の基本的なアイデアと原理について話しました。 しかし、その資料がKubernetes向けの既製のコンポーネントの操作から見ていた場合、現在提案されている新しい記事の翻訳は、開発​​者/ DevOpsエンジニアのビジョンであり、新しいオペレーターの実装に困惑しています。







コードスタディを経たKubernetesの演算子の作成に関するドキュメントを見つけようと試みた後、実際の例を使用してこの投稿を書くことにしました。



説明する例は次のとおりです。Kubernetesクラスターでは、各Namespace



スペースはあるチームのサンドボックス環境を表し、チームがサンドボックスでのみプレイできるように、それらへのアクセスを制限したいと考えました。



特定のNamespace



と編集権限を持つClusterRole



へのRoleBinding



を持つグループにユーザーを割り当てることで、目的を達成できます。 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
      
      





rawのrolebinding.yaml



このようなRoleBinding



手動で作成することもできますが、100個の名前空間のマークを克服した後は、退屈なタスクになります。 これは、Kubernetesオペレーターが支援する場所です。彼らは、リソースの変更に基づいてKubernetesリソースの作成を自動化します。 この場合、 Namespace



作成するときにRoleBinding



を作成します。



まず、関数main



を定義します。これは、オペレーターを開始するために必要な設定を実行してから、オペレーターを呼び出します。



注の翻訳 :以降、コード内のコメントはロシア語に翻訳されます。さらに、Habrのフレームワーク内で読みやすくするために、[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



    を使用して、アプリケーションをシャットダウンする前に、すべてのWaitGroup



    を正しく停止します。
  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



をセットアップしSharedIndexInformer



。これは、効率的に(キャッシュを使用して)名前空間の変更を期待します(インフォーマーの詳細については、記事「 Kubernetes Schedulerの実際の動作方法 」- 約Transl。を参照してください 。 その後、 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



オブジェクトに変換します。 次に、最初に説明したYAMLファイルに基づいて、提供されたNamespace



オブジェクトを使用してRoleBinding



を作成する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



を実行してから、以前に定義されたnamespaceInformer



を呼び出すことをWaitGroup



に伝えnamespaceInformer



。 停止信号が到着すると、関数を終了し、 WaitGroup



実行されていないことを伝え、この関数は作業を完了します。



Kubernetesクラスターでのこのステートメントの構築と実行に関する情報は、GitHubリポジトリにあります



これで、 Namespace



RoleBinding



がKubernetesクラスターに表示されるときにRoleBinding



が作成するステートメントの準備ができました。



All Articles