Text size
On My Radar6 min read

Should DevOps engineers learn Go?

Kubernetes is written in Go, and so is almost every tool around it. Where to start.

Should DevOps engineers learn Go?
AI-generated editorial illustration

Look at the tools you use every day: Kubernetes, Docker, containerd, Terraform, OpenTofu, Helm, Prometheus, Grafana's backend, Argo CD, Flux, etcd, Vault, Trivy, k9s. Almost all of them are written in Go.

That’s not a coincidence. It’s a good reason for DevOps engineers to think about learning it.

Why Go took over infrastructure

Go was created at Google and released in 2009, designed for building reliable networked services and tools. A few properties made it the language of cloud-native infrastructure:

  • Single static binaries. A Go program compiles into one file with no runtime to install. Copy it anywhere and it runs. Perfect for CLIs and containers.
  • Easy cross-compilation. Build for Linux, macOS, Windows, ARM and x86 from one machine.
  • Built-in concurrency with goroutines and channels, ideal for programs that do many things at once, like controllers watching many resources.
  • Simple language. Deliberately small, easy to read, with one standard formatting style (gofmt). You can read someone else's Go code without decoding their personal style.
  • Fast compilation and good performance.
  • Strong standard library for HTTP, JSON, cryptography and more.

What you can do with it

As a DevOps engineer, Go opens a few doors:

  • Read the source of the tools you use. When Kubernetes or Terraform behaves strangely, reading the code is often the fastest way to understand why.
  • Build CLI tools that colleagues can install as a single binary.
  • Write Kubernetes operators and controllers to automate your platform.
  • Write Terraform providers for internal systems.
  • Contribute to open-source cloud-native projects.
  • Build small services: webhooks, exporters, admission controllers.

My first CLI

A tiny but real example: a CLI that checks when TLS certificates expire.

package main

import (
    "crypto/tls"
    "fmt"
    "os"
    "time"
)

func main() {
    if len(os.Args) < 2 {
        fmt.Fprintln(os.Stderr, "usage: certcheck <host> [host...]")
        os.Exit(1)
    }

    exitCode := 0
    for _, host := range os.Args[1:] {
        conn, err := tls.Dial("tcp", host+":443", &tls.Config{ServerName: host})
        if err != nil {
            fmt.Printf("%-30s ERROR %v\n", host, err)
            exitCode = 1
            continue
        }
        cert := conn.ConnectionState().PeerCertificates[0]
        conn.Close()

        days := int(time.Until(cert.NotAfter).Hours() / 24)
        status := "OK"
        if days < 14 {
            status = "EXPIRING"
            exitCode = 1
        }
        fmt.Printf("%-30s %-8s %d days left\n", host, status, days)
    }
    os.Exit(exitCode)
}
go build -o certcheck .
./certcheck example.com deslypeter.com
GOOS=linux GOARCH=arm64 go build -o certcheck-linux-arm64 .   # cross-compile

No dependencies beyond the standard library, one binary, works anywhere. For bigger CLIs, libraries like Cobra (used by kubectl, Helm and many others) add subcommands and flags.

Learning Go is like getting a key to the engine room of cloud-native infrastructure.

A tiny Kubernetes operator

Operators are where Go really shines for platform work. An operator watches Kubernetes resources and makes reality match what they describe.

Kubebuilder (and the Operator SDK, which builds on it) generates most of the boilerplate:

kubebuilder init --domain acme.com --repo github.com/acme/app-operator
kubebuilder create api --group platform --version v1alpha1 --kind App

You then define your custom resource's fields in Go structs and write a Reconcile function: "given this App resource, make sure the right Deployment, Service and HTTPRoute exist". The framework handles watching, caching, retries and leader election.

It's not a weekend project to build a production-quality operator, but building a toy one is the best way to understand how Kubernetes itself works. Every built-in controller follows the same pattern.

Go vs Python for DevOps

They're complementary:

  • Python: faster for quick scripts, data processing, glue code, and anything where a huge library ecosystem helps. Great for one-off automation.
  • Go: better for tools you distribute, long-running services, operators, and anything that needs to be fast, concurrent, or a single binary.

Many DevOps engineers use Python for scripts and Go for tools.

Where to start

  • A Tour of Go (go.dev/tour): the official interactive introduction. A few hours.
  • Go by Example: short, practical examples for every common task.
  • "Learning Go" by Jon Bodner, or "Let's Go" by Alex Edwards for web services.
  • The Kubebuilder Book for operators.
  • Then build something small you'll actually use: a CLI, an exporter for an internal system, a webhook.

So, should you learn it?

If you work with Kubernetes and want to go beyond using tools to understanding and extending them, yes. You don't need to become a Go expert. Being able to read Go code and write small tools already makes you noticeably more effective.

My take: you don't have to speak Go to work in cloud-native. But it's the language the whole neighbourhood speaks, and it helps to understand the conversation.

— Desly