Kubebuilder でカスタム ポッドを作成する方法
12534 ワード
この投稿では、 kubebuilder を使用して単純な Kubernetes コントローラーを実装します.
Kubebuilder には book がありますが、初心者には複雑すぎると思います.もっと簡単にできるようにしようと思います.ポッドを管理する単純なオペレーターを実装します.
Kubebuilder は Go 1.17 をサポートしていないため、Go 1.16 をインストールする必要があります. Go のバージョンを管理するために goenv を使用することにしました.
以前の Go バージョン を削除 インストール goenv: Install goenv: https://github.com/syndbg/goenv/blob/master/INSTALL.md
インストール Go 1.16: このバージョンを使用: Kubebuilder をインストールします.
1 つのカスタム リソースを使用して新しいホワイト プロジェクトを作成するには、3 つの手順に従う必要があります.
これで、プロジェクトに必要なすべての足場が揃いました.
ここで
わかりました、「simplepod」リソースを作成できますが、何も実行せず、ロジックもありません.
リソースの構造を変更するたびに、make install を実行してマニフェストを再生成する必要があります.
次に、オペレーターのロジックを実装します. Pod オブジェクトを作成し、simplepod オブジェクトで指定されたコマンドを実行します.
リソースの構造を変更するたびに、make install を実行してマニフェストを再生成する必要があります.
次に、オペレーターのロジックを実装します. Pod オブジェクトを作成し、simplepod オブジェクトで指定されたコマンドを実行します.
次に、変更をインストールしてオペレーターを実行します.
最終コード全体: https://github.com/jilgue/medium-kubebuilder-pod
Kubebuilder には book がありますが、初心者には複雑すぎると思います.もっと簡単にできるようにしようと思います.ポッドを管理する単純なオペレーターを実装します.
Kubebuilder をインストールする
Kubebuilder は Go 1.17 をサポートしていないため、Go 1.16 をインストールする必要があります. Go のバージョンを管理するために goenv を使用することにしました.
$ goenv install 1.16.8
$ goenv global 1.16.8
$ curl -L -o ~/.local/bin/kubebuilder https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)
$ chmod a+x ~/.local/bin/kubebuilder
プロジェクトを初期化し、新しい API を作成する
1 つのカスタム リソースを使用して新しいホワイト プロジェクトを作成するには、3 つの手順に従う必要があります.
$ mkdir medium-kubebuilder-pod
$ cd !$
$ git init
$ go mod init simplepod
$ kubebuilder init --domain callepuzzle.com
$ git add .
$ git commit -m "init"
$ kubebuilder create api --group medium --version v1alpha1 --kind SimplePod
$ git add .
$ git commit -m "create api"
これで、プロジェクトに必要なすべての足場が揃いました.
ここで
make install
を実行すると、kubebuilder は config/crd/bases
の下にベース CRD と他のいくつかのファイルを生成するはずです. make run
を実行すると、オペレーターをローカルで起動できるようになります.$ make install
/home/cesar/projects/k8s-operator/medium-kubebuilder-pod/bin/controller-gen "crd:trivialVersions=true,preserveUnknownFields=false" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
go: creating new go.mod: module tmp
Downloading sigs.k8s.io/kustomize/kustomize/[email protected]
go get: added sigs.k8s.io/kustomize/kustomize/v3 v3.8.7
/home/cesar/projects/k8s-operator/medium-kubebuilder-pod/bin/kustomize build config/crd | kubectl apply -f -
customresourcedefinition.apiextensions.k8s.io/simplepods.medium.callepuzzle.com created$ kubectl get customresourcedefinitions.apiextensions.k8s.io simplepods.medium.callepuzzle.com
NAME CREATED AT
simplepods.medium.callepuzzle.com 2021-10-13T15:47:52Z$ kubectl apply -f config/samples/medium_v1alpha1_simplepod.yaml$ kubectl get simplepods.medium.callepuzzle.com
NAME AGE
simplepod-sample 9s
わかりました、「simplepod」リソースを作成できますが、何も実行せず、ロジックもありません.
カスタム リソースを作成する
api/v1alpha1/simplepod_types.go
には、リソースの構造体が定義されています.$ git diff api/v1alpha1/simplepod_types.go config/samples/medium_v1alpha1_simplepod.yaml
diff --git a/api/v1alpha1/simplepod_types.go b/api/v1alpha1/simplepod_types.go
index f5f3fde..e4f0630 100644
--- a/api/v1alpha1/simplepod_types.go
+++ b/api/v1alpha1/simplepod_types.go
@@ -29,7 +29,7 @@ type SimplePodSpec struct {
// Important: Run "make" to regenerate code after modifying this file
// Foo is an example field of SimplePod. Edit simplepod_types.go to remove/update
- Foo string `json:"foo,omitempty"`
+ Command string `json:"command,omitempty"`
}
// SimplePodStatus defines the observed state of SimplePod
diff --git a/config/samples/medium_v1alpha1_simplepod.yaml b/config/samples/medium_v1alpha1_simplepod.yaml
index 671c617..dd8cda0 100644
--- a/config/samples/medium_v1alpha1_simplepod.yaml
+++ b/config/samples/medium_v1alpha1_simplepod.yaml
@@ -4,4 +4,4 @@ metadata:
name: simplepod-sample
spec:
# Add fields here
- foo: bar
+ command: ls
リソースの構造を変更するたびに、make install を実行してマニフェストを再生成する必要があります.
次に、オペレーターのロジックを実装します. Pod オブジェクトを作成し、simplepod オブジェクトで指定されたコマンドを実行します.
$ git diff controllers/simplepod_controller.go
diff --git a/controllers/simplepod_controller.go b/controllers/simplepod_controller.go
index 2f13668..89b63d0 100644
--- a/controllers/simplepod_controller.go
+++ b/controllers/simplepod_controller.go
@@ -18,7 +18,10 @@ package controllers
import (
"context"
+ "strings"
+ corev1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -36,6 +39,7 @@ type SimplePodReconciler struct {
//+kubebuilder:rbac:groups=medium.callepuzzle.com,resources=simplepods,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=medium.callepuzzle.com,resources=simplepods/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=medium.callepuzzle.com,resources=simplepods/finalizers,verbs=update
+//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;create;update;patch;delete
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
@@ -47,16 +51,62 @@ type SimplePodReconciler struct {
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile
func (r *SimplePodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
- _ = log.FromContext(ctx)
+ log := log.FromContext(ctx)
- // your logic here
+ var instance mediumv1alpha1.SimplePod
+ errGet := r.Get(ctx, req.NamespacedName, &instance)
+ if errGet != nil {
+ log.Error(errGet, "Error getting instance")
+ return ctrl.Result{}, client.IgnoreNotFound(errGet)
+ }
+
+ pod := NewPod(&instance)
+
+ _, errCreate := ctrl.CreateOrUpdate(ctx, r.Client, pod, func() error {
+ return ctrl.SetControllerReference(&instance, pod, r.Scheme)
+ })
+
+ if errCreate != nil {
+ log.Error(errCreate, "Error creating pod")
+ return ctrl.Result{}, nil
+ }
+
+ err := r.Status().Update(context.TODO(), &instance)
+ if err != nil {
+ return ctrl.Result{}, err
+ }
return ctrl.Result{}, nil
}
+func NewPod(pod *mediumv1alpha1.SimplePod) *corev1.Pod {
+ labels := map[string]string{
+ "app": pod.Name,
+ }
+
+ return &corev1.Pod{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: pod.Name,
+ Namespace: pod.Namespace,
+ Labels: labels,
+ },
+ Spec: corev1.PodSpec{
+ Containers: []corev1.Container{
+ {
+ Name: "busybox",
+ Image: "busybox",
+ Command: strings.Split(pod.Spec.Command, " "),
+ },
+ },
+ RestartPolicy: corev1.RestartPolicyOnFailure,
+ },
+ }
+}
+
// SetupWithManager sets up the controller with the Manager.
func (r *SimplePodReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&mediumv1alpha1.SimplePod{}).
+ Owns(&corev1.Pod{}).
Complete(r)
}
リソースの構造を変更するたびに、make install を実行してマニフェストを再生成する必要があります.
次に、オペレーターのロジックを実装します. Pod オブジェクトを作成し、simplepod オブジェクトで指定されたコマンドを実行します.
$ git diff controllers/simplepod_controller.go
diff --git a/controllers/simplepod_controller.go b/controllers/simplepod_controller.go
index 2f13668..89b63d0 100644
--- a/controllers/simplepod_controller.go
+++ b/controllers/simplepod_controller.go
@@ -18,7 +18,10 @@ package controllers
import (
"context"
+ "strings"
+ corev1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -36,6 +39,7 @@ type SimplePodReconciler struct {
//+kubebuilder:rbac:groups=medium.callepuzzle.com,resources=simplepods,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=medium.callepuzzle.com,resources=simplepods/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=medium.callepuzzle.com,resources=simplepods/finalizers,verbs=update
+//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;create;update;patch;delete
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
@@ -47,16 +51,62 @@ type SimplePodReconciler struct {
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile
func (r *SimplePodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
- _ = log.FromContext(ctx)
+ log := log.FromContext(ctx)
- // your logic here
+ var instance mediumv1alpha1.SimplePod
+ errGet := r.Get(ctx, req.NamespacedName, &instance)
+ if errGet != nil {
+ log.Error(errGet, "Error getting instance")
+ return ctrl.Result{}, client.IgnoreNotFound(errGet)
+ }
+
+ pod := NewPod(&instance)
+
+ _, errCreate := ctrl.CreateOrUpdate(ctx, r.Client, pod, func() error {
+ return ctrl.SetControllerReference(&instance, pod, r.Scheme)
+ })
+
+ if errCreate != nil {
+ log.Error(errCreate, "Error creating pod")
+ return ctrl.Result{}, nil
+ }
+
+ err := r.Status().Update(context.TODO(), &instance)
+ if err != nil {
+ return ctrl.Result{}, err
+ }
return ctrl.Result{}, nil
}
+func NewPod(pod *mediumv1alpha1.SimplePod) *corev1.Pod {
+ labels := map[string]string{
+ "app": pod.Name,
+ }
+
+ return &corev1.Pod{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: pod.Name,
+ Namespace: pod.Namespace,
+ Labels: labels,
+ },
+ Spec: corev1.PodSpec{
+ Containers: []corev1.Container{
+ {
+ Name: "busybox",
+ Image: "busybox",
+ Command: strings.Split(pod.Spec.Command, " "),
+ },
+ },
+ RestartPolicy: corev1.RestartPolicyOnFailure,
+ },
+ }
+}
+
// SetupWithManager sets up the controller with the Manager.
func (r *SimplePodReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&mediumv1alpha1.SimplePod{}).
+ Owns(&corev1.Pod{}).
Complete(r)
}
次に、変更をインストールしてオペレーターを実行します.
$ go get k8s.io/api/core/[email protected]
$ make install
$ kubectl delete -f config/samples/medium_v1alpha1_simplepod.yaml
$ kubectl apply -f config/samples/medium_v1alpha1_simplepod.yaml
$ make run
(in another terminal)
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
simplepod-sample 0/1 Completed 0 3s
$ kubectl logs simplepod-sample
bin
dev
etc
home
proc
root
sys
tmp
usr
var
最終コード全体: https://github.com/jilgue/medium-kubebuilder-pod
Reference
この問題について(Kubebuilder でカスタム ポッドを作成する方法), 我々は、より多くの情報をここで見つけました https://dev.to/callepuzzle/how-to-create-custom-pod-with-kubebuilder-bd7テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol