krew: Install kubectl Plugins in CI
kubectl krew install <plugin> downloads a kubectl plugin from the krew index and puts it on PATH as a kubectl subcommand.
krew is to kubectl plugins what apt is to packages. In CI it bootstraps tools like kubectl-neat or kubectx as kubectl subcommands without manual downloads.
What it does
krew is itself a kubectl plugin that manages other plugins. install fetches a plugin and its manifest from the index, upgrade updates them, list shows what is installed, and search queries the index. Installed plugins live under ~/.krew/bin, invoked as kubectl <plugin>.
Common usage
kubectl krew update # refresh the plugin index
kubectl krew install neat ctx ns # install several plugins
kubectl krew list
kubectl krew upgradeOptions
| Subcommand | What it does |
|---|---|
| krew update | Refresh the local copy of the plugin index |
| krew install <name> | Install one or more plugins |
| krew search <term> | Search the index for plugins |
| krew list | List installed plugins |
| krew upgrade | Upgrade all installed plugins |
| krew uninstall <name> | Remove a plugin |
In CI
Run kubectl krew update before install, and export PATH="$HOME/.krew/bin:$PATH" so the runner finds the plugins afterward. Cache ~/.krew between jobs to avoid re-downloading. Always pin nothing surprising: krew install pulls the latest unless the index is pinned.
Common errors in CI
kubectl: krew is not a kubectl command means krew itself is not installed or not on PATH. kubectl: neat is not a kubectl command after install means ~/.krew/bin is missing from PATH. could not find plugin "<name>" in the index means a typo or a stale index; run krew update first.
Using this in CI
A runner has no kubeconfig, no cached context, and no interactive auth. Every kubectl invocation in CI needs the context supplied explicitly, and most confusing CI failures here are the command running against the wrong cluster or no cluster at all.
# never rely on the ambient context on a runner
kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" get pods
# confirm what you are actually connected to before mutating anything
kubectl config current-context
kubectl cluster-info
# fail fast instead of hanging on an unreachable API server
kubectl --request-timeout=30s get nodes