Skip to main content

DevOps essential tools

Mac install (with Homebrew):

brew install git kubernetes-cli kustomize fluxcd/tap/flux sops age jq yq yamllint kubeconform yamlfmt crane tree
brew install cloudflared # optional, convenient for local auth/tunnel ops
# Optional: a newer curl than macOS ships with
# brew install curl

What they’re for & how to check:

  • git – source control. git --version
  • kubectl – talks to your cluster. kubectl version --client
  • kustomize – local manifests testing. kustomize version
  • flux – CLI to kick reconciles, inspect resources. flux version
  • sops – encrypt/decrypt K8s secrets. sops --version
  • age – key management for SOPS. age --version
  • jq – JSON CLI parsing. jq --version
  • yq – YAML CLI parsing. yq --version
  • yamllint – YAML linter (style + basic correctness). yamllint --version
  • kubeconform – Kubernetes schema validator (catches invalid manifests). kubeconform -version
  • yamlfmt – YAML formatter/normalizer. yamlfmt -version
  • crane – container registry utility (tags, copy, digest). crane version
  • tree – show directory trees (great for repo layout). tree -v
  • cloudflared – local tunnel commands (optional). cloudflared --version
  • curl – HTTP client for validation. curl --version

Heads-up: crane prints version with crane version (no --version).

Tool description

  • git – Source control for all your GitOps repos (flux-config, app repos, runbooks).
    Typical: commit, push; branch & PR/MR flows.

  • kubectl – Inspect/apply/debug Kubernetes.
    Typical: kubectl diff -f …, kubectl get events -A --sort-by=.lastTimestamp, kubectl -n flux-system get kustomizations.

  • kustomize – Templating/overlays (also used by Flux under the hood).
    Typical: kustomize build ./clusters/my-cluster for local dry-runs.

  • flux – GitOps CLI to reconcile and inspect controllers.
    Typical: flux get kustomizations -A, flux tree kustomization flux-system -n flux-system,
    flux reconcile kustomization <name> -n flux-system --with-source.

  • sops + age – Encrypt secrets you store in Git (Flux decrypts in-cluster via your sops-age secret).
    Typical:

    • Generate key: age-keygen -o ~/.sops/age.key
    • Encrypt in place: sops --encrypt --in-place k8s/prod/secret.enc.yaml
    • View decrypted (locally): sops -d k8s/prod/secret.enc.yaml
  • jq / yq – JSON/YAML processors for scripting and quick patches.
    Typical: kubectl get secret x -o json | jq .data, yq -i '.spec.interval="30m"' file.yaml.

  • yamllint – Lints YAML for style and common mistakes. Great for CI and pre-commit.
    Typical:

    # Lint the current repo (respects .yamllint if present)
    yamllint .

    # Ad‑hoc relaxed config (120‑char lines, allow long unbreakables)
    yamllint -d "{extends: default, rules: {line-length: {max: 120, allow-non-breakable-words: true}}}" k8s/
    # Or use a file:
    yamllint -c .yamllint k8s/
  • kubeconform – Validates Kubernetes manifests against the official schemas.
    Typical:

    # Quick validate (strict mode): fails on unknown/extra fields
    kubeconform -summary -strict k8s/prod/*.yaml

    # Recursively (skipping CRDs with unknown schemas)
    find k8s -name '*.yaml' -o -name '*.yml' -print0 \
    | xargs -0 -n1 kubeconform -summary -strict --ignore-missing-schemas

    Notes: For custom resources, either provide schema locations or use --ignore-missing-schemas. If files are SOPS‑encrypted, validate the decrypted content or exclude them from schema checks.

  • yamlfmt – Formats YAML consistently; useful before committing or during auto‑fix flows.
    Typical:

    # Preview changes (does not modify file):
    yamlfmt -in < file.yaml | diff -u file.yaml - || true

    # Write back safely using a temp file:
    tmp="$(mktemp)"; yamlfmt -in < file.yaml > "$tmp" && mv "$tmp" file.yaml

    # CI/style check without changing files:
    yamlfmt -lint path/to/**/*.yaml || echo "Formatting differences detected"

    Notes: yamlfmt focuses on formatting—use yamllint for policy/style rules and kubeconform for schema validity.

  • crane – Query/pin container images by tag/digest.
    Typical:

    crane ls cloudflare/cloudflared | sort -V | tail -n1
    crane digest cloudflare/cloudflared:2025.9.1

    Then pin image refs to immutable digests in Deployments.

  • tree - Show repo layout (from root of repo):

    tree -a -I '.git|.DS_Store'
  • cloudflared – Local Cloudflare Tunnel client; great for testing DNS routes or creating tunnels.
    Typical: cloudflared tunnel route dns <tunnel> <host>, cloudflared --version.

  • curl – HTTP(S) testing; useful for SNI + Origin CA validation to ingress.
    Typical:

    SVC_IP=$(kubectl -n ingress-nginx get svc ingress-nginx-controller -o jsonpath='{.spec.clusterIP}')
    curl -sv --resolve muppit.au:443:$SVC_IP https://muppit.au/ --cacert /tmp/origin_ca.pem

Optional nice-to-haves:

  • tmux (persistent sessions/multi-panes)
  • fzf (fuzzy finder for history/files)

Verify tool version

printf "\n== Versions ==\n"
printf "%-14s %s\n" "git" "$(git --version)"
printf "%-14s %s\n" "kubectl" "$(kubectl version --client --short 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "kustomize" "$(kustomize version 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "flux" "$(flux --version 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "sops" "$(sops --version 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "age" "$(age --version 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "jq" "$(jq --version 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "yq" "$(yq --version 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "yamllint" "$(yamllint --version 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "kubeconform" "$(kubeconform -version 2>/dev/null || kubeconform --version 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "yamlfmt" "$(yamlfmt -version 2>/dev/null || yamlfmt --version 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "crane" "$(crane version 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "cloudflared" "$(cloudflared --version 2>/dev/null || echo 'not found')"
printf "%-14s %s\n" "curl" "$(curl --version 2>/dev/null | head -n1 || echo 'not found')"

Tip: If any row says “not found”, re-check PATH or reinstall that formula.

Check YAML script

A helper script is detailed here: check YAML script.


Linux install

Option A: Homebrew

# Install Homebrew on Linux (once)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> ~/.bashrc
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"

# Then install the same tools
brew install git kubernetes-cli kustomize fluxcd/tap/flux sops age jq yq yamllint kubeconform yamlfmt crane tree
brew install cloudflared # optional
# Optional: newer curl than distro defaults
# brew install curl

Option B: Debian/Ubuntu (mixed sources)

# Core packages
sudo apt update
sudo apt install -y git curl jq tree python3-pip

# kubectl (official repo)
sudo apt-get install -y apt-transport-https ca-certificates gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /usr/share/keyrings/kubernetes-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update && sudo apt install -y kubectl

# Flux (official installer)
curl -s https://fluxcd.io/install.sh | sudo bash

# yamllint via pip, yq via official binary
python3 -m pip install --user --upgrade yamllint
sudo wget -O /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64"
sudo chmod +x /usr/local/bin/yq

# sops, age, kustomize, kubeconform, yamlfmt, crane, cloudflared:
# Easiest is Homebrew on Linux (Option A). Otherwise install each from its GitHub releases page.

Verification commands are identical to macOS.


Windows install

Option A: WSL + Ubuntu

Use Windows Subsystem for Linux, then follow the Linux steps above inside Ubuntu.

wsl --install -d Ubuntu
# Open Ubuntu terminal, then follow “Linux equivalents”.

Option B: Native Windows with winget (PowerShell)

# Install core tools
winget install --id Git.Git -e
winget install --id Kubernetes.kubectl -e
winget install --id Kubernetes.kustomize -e
winget install --id FluxCD.Flux -e
winget install --id Mozilla.SOPS -e
winget install --id FiloSottile.Age -e
winget install --id jqlang.jq -e
winget install --id MikeFarah.yq -e
# yamllint via Python pip
winget install --id Python.Python.3.12 -e
py -m pip install --user --upgrade yamllint
# Extras, if available in winget:
winget install --id yannh.kubeconform -e # kubeconform
winget install --id Google.Yamlfmt -e # yamlfmt
winget install --id Cloudflare.cloudflared -e # cloudflared
# For crane, install from releases if not found in winget.

Verification (PowerShell or Windows Terminal):

git --version
kubectl version --client
kustomize version
flux --version
sops --version
age --version
jq --version
yq --version
yamllint --version
kubeconform -version
yamlfmt -version
crane version
cloudflared --version
curl --version

Notes.

  • Where a tool is not available in winget, use the official release binaries or install under WSL and call it from Windows Terminal.
  • On Linux without Homebrew, prefer official repos or vendor installers to avoid stale distro packages.
  • Keep your PATH updated so newly installed CLIs are available in shells.