Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

161
Views
Create k8s resource and wait until it finish to proceed to the next

I need to create a k8s resource which take some time until it will be available, for this I use the following

https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller/controllerutil#example-CreateOrUpdate

op, err := controllerutil.CreateOrUpdate(context.TODO(), c, deploy, func() error {

})

func2()

now I need to call to func2 right after the creation of the object was done (it may take 2-3 min until finish), How should I do it right?

I found this but not sure how to combine them ...

https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg#hdr-Watching_and_EventHandling

im using kubebuilder

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

The above approach is more for cli usage.

When you are using kubebuilder or the operator sdk then you need to deal with it in your reconcile function.

Usually you have a custom resource that triggers your controllers reconcile function. When the custom resource is being created you then create the deployment and instead of returning an empty reconcile.Result (which marks it as done) you can return the reconcile.Result with the Requeue attribute.

reconcile.Result{Requeue: true}

So during the next run you check if the deployment is ready. If not then you requeue again. Once it is ready you return an empty reconcile.Result struct.

Also keep in mind that the reconcile function always needs to be idempotent as it will be run again for every custom resource during a restart of the controller and also every 10 hours by default.

Alternatively you could also use an owner reference on the created deployment and then setup the controller to reconcile the owner resource (your custom resource) whenever an update happens on the owned resource (the deployment). With operator sdk this can be configured in the SetupWithManager function, which by default only uses the For option function. Here you need to add the Owns option function.

// SetupWithManager sets up the controller with the Manager.
func (r *YourReconciler) SetupWithManager(mgr ctrl.Manager) error {
    return ctrl.NewControllerManagedBy(mgr).
        For(&yourapigroup.YourCustomResource{}).
        Owns(&appv1.Deployment{}).
        Complete(r)
}

I never used that approach though therefore it might be required to add more code for this to work.

Using the owner reference can also come in handy if you do not require any finalizer code, because kubernetes will delete your owned resource (the deployment) automatically when the custom resource is being deleted.

over 4 years ago · Santiago Trujillo Report

0

Here is an example how to create a deployment and check if it has at least 1 ready replica. Maybe it would be even better to check the conditions in the status and look for the condition of type Available and status of "True".

package main

import (
    "context"
    "fmt"
    v1 "k8s.io/api/apps/v1"
    podv1 "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/fields"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/cache"
    "sigs.k8s.io/controller-runtime/pkg/client"
    "sigs.k8s.io/controller-runtime/pkg/client/config"
    "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
    "time"
)

const (
    namespace      = "default"
    deploymentName = "nginx"
)

func main() {
    cfg, err := config.GetConfig()
    if err != nil {
        panic(err)
    }

    clientset, err := kubernetes.NewForConfig(cfg)
    if err != nil {
        panic(err)
    }

    client, err := client.New(cfg, client.Options{})
    if err != nil {
        panic(err)
    }

    d := &v1.Deployment{
        ObjectMeta: metav1.ObjectMeta{
            Name:      deploymentName,
            Namespace: namespace,
        },
        Spec: v1.DeploymentSpec{
            Replicas: toInt32Ptr(2),
            Selector: &metav1.LabelSelector{
                MatchLabels: map[string]string{
                    "app": "nginx",
                },
            },
            Template: podv1.PodTemplateSpec{
                ObjectMeta: metav1.ObjectMeta{
                    Labels: map[string]string{
                        "app": "nginx",
                    },
                },
                Spec: podv1.PodSpec{
                    Containers: []podv1.Container{
                        {
                            Name:  "nginx",
                            Image: "nginx",
                        },
                    },
                },
            },
        },
    }

    fmt.Println("Deploying")
    _, err = controllerutil.CreateOrUpdate(context.TODO(), client, d, func() error {
        return nil
    })

    if err != nil {
        panic(err)
    }

    stop := make(chan struct{})

    watchList := cache.NewListWatchFromClient(clientset.AppsV1().RESTClient(), "deployments", namespace, fields.Everything())
    _, ctrl := cache.NewInformer(watchList, &v1.Deployment{}, time.Second, cache.ResourceEventHandlerFuncs{
        UpdateFunc: func(o, n interface{}) {
            newDeployment := n.(*v1.Deployment)
            if newDeployment.Name != deploymentName {
                return
            }

            if newDeployment.Status.ReadyReplicas > 0 {
                close(stop)
                return
            }

            return
        },
    })

    ctrl.Run(stop)
    fmt.Println("Deployment has at least 1 ready replica")
}

func toInt32Ptr(i int32) *int32 {
    return &i
}

over 4 years ago · Santiago Trujillo Report

0

This example, from operator-sdk documentation, might help: https://sdk.operatorframework.io/docs/building-operators/golang/references/client/#example-usage. It is based on Create() and Update() functions, which might lead to a simpler algorithm.

This one, from kubebuilder documentation, also provides an interesting track, although it is deprecated: https://book-v1.book.kubebuilder.io/basics/simple_controller.html

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!