コードスタディを経た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 、 生 )
次のことを行います。
- オペレーティングシステムの特定の信号のプロセッサを構成して、オペレーターを正しく(正常に)終了させます。
-
WaitGroup
を使用して、アプリケーションをシャットダウンする前に、すべてのWaitGroup
を正しく停止します。 -
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 }
( 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
が作成するステートメントの準備ができました。