Back to blog
Sep 13, 2024
4 min read

Writing Your Own Kubernetes Operators

and save some dosh in the cloud

If you’re running stateful apps or dealing with cloud costs that make your CFO sweat, you should probably look into writing your own Kubernetes Operators.

What’s an Operator Again?

Operators are basically Kubernetes’ brain extension. They’re custom controllers that let you automate not just deployments but also the full lifecycle management of any app. Think of it as building your own automated DevOps team in Kubernetes.

Why Build Your Own Operator?

Because sometimes, the off-the-shelf Operators don’t cut it. Maybe your cloud bill is ballooning because…

  • no one’s shutting down the beefy instances on Fridays
  • you’ve got custom apps with special handling needs that existing Operators just don’t get
  • you’re getting stooged by your cloud provider.

This is where you write your own Operator to automate these bespoke tasks, including evaluating and managing cloud costs.

Evaluating Cloud Costs with Custom Operators

Imagine an Operator that monitors your workloads and takes action based on real-time costs. It could scale down unused resources, shift workloads to cheaper nodes, or even send daily cost reports directly to Slack. Basically, your custom Operator could pay for itself in savings.

Building Your Own Operator (Quick and Dirty)

If you find yourself in Operator territory, chances are your problem space is niche. So let’s start simple. Let’s walk through the basics of writing a Kubernetes Operator using Go and the Operator SDK.

  1. Install Operator SDK:

    brew install operator-sdk
    
  2. Initialize Your Operator:

    operator-sdk init --domain=olibyte.io --repo=github.com/olibyte/cost-optimizer-operator
    
  3. Create an API and Controller:

    operator-sdk create api --group costs --version v1 --kind CostOptimizer --resource --controller
    

    This sets up your custom resource definition (CRD) and the controller that does all the heavy lifting.

  4. Define Your CRD: Let’s add some custom fields to track resources and actions.

    apiVersion: costs.olibyte.io/v1
    kind: CostOptimizer
    metadata:
      name: my-cost-optimizer
    spec:
      targetNamespaces:
        - default
      maxCostThreshold: 100  # dollars per day, don't get greedy
      actions:
        - scaleDown
        - shiftToSpotInstances
    
  5. Write the Controller Logic: This is where the magic happens. Your controller will watch for cloud costs, compare them against the defined thresholds, and take action. Here’s a quick snippet to get an idea:

    if currentCost > costThreshold {
        log.Println("Cost threshold exceeded. Initiating cost-saving actions.")
        scaleDownUnnecessaryPods()
        moveToCheaperInstances()
    }
    

    You can use cloud APIs to pull in real-time cost data and use Kubernetes API to adjust your resources accordingly.

Real-World Use Case: Scaling Down Non-Prod Environments on Weekends

Your Operator would know if it’s the weekend and scale down all non-production environments. Or maybe it checks for instances that haven’t been touched in days and shuts them down. We’re talking real-time cost management, and it’s fully automated.

func scaleDownUnnecessaryPods() {
    // Implement logic to find and scale down unnecessary pods
    kubectl scale deployment my-deployment --replicas=0
}

You’re already paying for cloud resources. Unfortunately, there’s little room for negotiation when signing up for managed services. Writing your own Kubernetes Operator gives you the ultimate flexibility to automate cost management, handle weird custom requirements, and make Kubernetes work the way you need it to. You’re not just saving time; you’re saving money, and that’s the kind of automation we can all get behind.