ノート。 翻訳。: Operator は 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
(
一つ作る RoleBinding
手動で行うこともできますが、名前空間の数が XNUMX を超えると、面倒な作業になります。 ここで Kubernetes オペレーターが役に立ちます。Kubernetes オペレーターを使用すると、リソースへの変更に基づいて Kubernetes リソースの作成を自動化できます。 私たちの場合、作成したいのは RoleBinding
作成中 Namespace
.
まずは関数を定義しましょう 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() // Ожидаем, что все остановлено
}
次のことを行います。
- オペレーターを正常に終了させるために、特定のオペレーティング システム信号のハンドラーを構成します。
- を使用しております
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
}
(
ここで設定します SharedIndexInformer
、これは事実上 (キャッシュを使用して) 名前空間の変更を待ちます。 (情報提供者について詳しくは、記事「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))
}
}
(
名前空間を次のように取得します。 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
}
(
ここで話しています WaitGroup
goroutine を起動してから呼び出すこと namespaceInformer
、これは以前に定義されています。 停止信号が到着すると機能を終了し、通知します。 WaitGroup
、実行されなくなり、この関数は終了します。
Kubernetes クラスター上でのこのステートメントの構築と実行に関する情報は、次の場所にあります。
作成するオペレーターはこれで終わりです RoleBinding
いつ Namespace
Kubernetes クラスター内で準備完了です。
出所: habr.com