| Tested on | Rocky Linux 10.2 (Red Quartz) workstation |
|---|---|
| Package | kubectl 1.36.3 (binary and RPM) |
| Applies to | Rocky Linux, RHEL, AlmaLinux, Oracle Linux, CentOS Stream, Fedora, Ubuntu, Debian |
| Cert prep | CKAD · CKA · CKS |
| Lab environment | Multi-node kubeadm cluster with containerd — install Kubernetes with kubeadm |
| Privilege | Normal user; sudo for system-wide kubectl install |
| Scope | Linux workstation kubectl install (binary and package managers), kubeconfig setup, context management, remote API access, and common connection errors. Does not install a cluster. |
| Related guides | kubectl commands and YAML examples |
What Is kubectl?
kubectl is the official command-line client for the Kubernetes API server. It sends HTTPS requests to the API. It does not install a cluster, and it does not talk to kubelet or etcd directly for routine commands such as kubectl get pods.
You run kubectl on a Linux host of your choice:
- Control-plane node
- Worker node
- Separate machine such as a laptop or jump host
The next sections cover installing the client, checking versions, and pointing kubectl at your cluster through a kubeconfig file.
Install kubectl on Linux
Check if kubectl is installed
Connect to the Linux host where you plan to run kubectl before you use any method in this section.
Check whether kubectl is already on PATH:
command -v kubectlSample output when kubectl is present:
/usr/bin/kubectlWhen this prints a path, kubectl is already installed. Skip the install methods below and continue to Check kubectl and cluster versions.
When the command prints nothing, install kubectl on this host.
| Host | kubectl on this host |
|---|---|
Control-plane (k8s-cp, 192.168.56.108 in the lab) |
Installed during install Kubernetes with kubeadm |
Worker (worker01, 192.168.56.109 in the lab) |
Installed during install Kubernetes with kubeadm |
| Another Linux machine (laptop, jump host) | Install kubectl on this host |
Pick one install method from the table below.
Choose an install method
| Method | Applies to | When to choose |
|---|---|---|
| Official binary | Any Linux distribution | Default choice. Works on every distro when you can reach dl.k8s.io. Use this on laptops, jump hosts, or when you do not want a package repository. |
dnf repository |
Rocky Linux, RHEL, AlmaLinux, Oracle Linux, CentOS Stream, Fedora | You prefer RPM packages and dnf install kubectl on a RHEL-family host. |
RPM package steps on RHEL-family nodes follow dnf syntax.
| apt repository | Ubuntu, Debian | You prefer DEB packages and apt install kubectl on a Debian-family host. |
For dnf and apt, the repository URL selects the minor channel (v1.36 in the examples below). The package manager installs the latest patch release available from that channel. The next major section shows how to confirm client and server compatibility.
Install from the official binary
Use this method when you chose Official binary in the table above. It works on any Linux distribution.
Set the client version to match your cluster minor release before you download:
KUBECTL_VERSION=v1.36.3If your shell has an HTTP proxy and curl fails against dl.k8s.io, unset proxy variables for the download or add dl.k8s.io to NO_PROXY:
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXYConfirm CPU architecture before you download. Use amd64 in the URL when uname -m prints x86_64, or arm64 on AArch64 hosts:
uname -mSample output on the lab workstation:
x86_64Download the binary with curl. The -f flag stops on HTTP errors and -SLO saves the file under its original name:
curl -fsSLO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl"On ARM64 workstations, replace amd64 with arm64 in the URL.
Verify the download with the published SHA-256 checksum file before you install the binary:
curl -fsSLO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl.sha256"On ARM64 workstations, replace amd64 with arm64 in this URL as well so the checksum matches the binary you downloaded.
Pipe the checksum and filename into sha256sum --check:
echo "$(cat kubectl.sha256) kubectl" | sha256sum --checkSample output:
kubectl: OKA failed check means the download was corrupted or incomplete. Delete both files and download again. Do not install the binary until the check prints kubectl: OK.
Install the verified file system-wide under /usr/local/bin, which is already on PATH for most Linux distributions:
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectlWhen you cannot use sudo, install under your home directory instead. Create a private bin directory first:
mkdir -p "$HOME/.local/bin"Copy the binary with executable permissions:
install -m 0755 kubectl "$HOME/.local/bin/kubectl"Mode 0755 grants execute permission to the owner, group, and others.
Prepend that directory to PATH for the current shell session:
export PATH="$HOME/.local/bin:$PATH"Add the export PATH=... line to ~/.bashrc or ~/.profile so the path persists after you sign out.
Confirm the shell resolves kubectl to the path you expect:
command -v kubectlSample output for a user-local install:
/home/user/.local/bin/kubectlA path under /usr/local/bin means the system-wide install succeeded.
Confirm the client reports the version you intended:
kubectl version --clientSample output:
Client Version: v1.36.3
Kustomize Version: v5.8.1When the Client Version matches KUBECTL_VERSION, the install step is complete.
To pin an exact patch within a minor release, change only the patch number in KUBECTL_VERSION and download again with the same URL pattern above.
Install from the dnf repository
Use this method when you chose dnf repository in the table above. It applies to Rocky Linux, RHEL, AlmaLinux, Oracle Linux, CentOS Stream, and Fedora.
Write a repository file that points dnf at the Kubernetes v1.36 package repository:
cat <<'EOF' | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.36/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.36/rpm/repodata/repomd.xml.key
EOFInstall only the client package. Installing only the kubectl package does not install kubeadm or kubelet:
sudo dnf install -y kubectlOn the lab control-plane node the RPM reports:
kubectl-1.36.3-150500.1.1.x86_64The NEVRA confirms the v1.36.3 client from pkgs.k8s.io. This repository definition has no exclude= line, so you do not need --setopt=disable_excludes=kubernetes.
Run kubectl version --client after the install to confirm the minor release.
Install from the apt repository
Use this method when you chose apt repository in the table above. It applies to Ubuntu and Debian.
Refresh the package index before you add a new signing key:
sudo apt-get updateInstall tools needed to fetch and verify the Kubernetes APT repository key:
sudo apt-get install -y apt-transport-https ca-certificates curl gpgCreate the keyring directory APT expects for third-party keys:
sudo install -m 0755 -d /etc/apt/keyringsDownload the v1.36 repository signing key and store it in the keyring:
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpgSet permissions so every user can read the key but only root can write it:
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpgRegister the Kubernetes APT source for the v1.36 channel:
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.listSet the list file readable by APT but not writable by other users:
sudo chmod 644 /etc/apt/sources.list.d/kubernetes.listReload the index so APT sees the new repository:
sudo apt-get updateInstall the kubectl client package:
sudo apt-get install -y kubectlRun kubectl version --client after any package-manager install to confirm the minor release.
Check kubectl and cluster versions
After kubectl is on PATH, confirm the client release and whether it matches your API server.
kubectl is supported within one minor version of the kube-apiserver. A v1.36 client works with v1.35, v1.36, and v1.37 API servers. Patch releases do not need to match exactly. Install a client that matches your cluster minor version instead of always grabbing the newest release binary. For a full client/server skew walkthrough, see check Kubernetes cluster version.
Read the client version alone. This works even before kubeconfig is configured:
kubectl version --clientSample output from the lab:
Client Version: v1.36.3
Kustomize Version: v5.8.1The Client Version line is the release you installed. Match its minor version to the API server when you pick a download or repository channel.
kubectl version without flags also tries to reach the API server. When kubeconfig is not configured yet:
- kubectl falls back to
http://localhost:8080 - The client lines still print
- There is no
Server Versionline, and the command exits with an error
kubectl versionSample output from worker01 in the lab after temporarily moving ~/.kube/config aside:
Client Version: v1.36.3
Kustomize Version: v5.8.1
The connection to the server localhost:8080 was refused - did you specify the right host or port?That error is expected before ~/.kube/config exists. It does not mean kubectl is broken. Configure kubeconfig in the next section, then run kubectl version again to read the Server Version line and compare its minor version with the client.
Configure kubeconfig
A kubeconfig file tells kubectl:
- Which API server to call
- Which CA certificate to trust
- Which credentials to present
On Linux, kubectl reads $HOME/.kube/config by default when you install credentials with Method 1.
When more than one source is in play, kubectl uses the highest-precedence source that is set:
| Precedence | Source | Scope | Article method |
|---|---|---|---|
| 1 (highest) | --kubeconfig <path> |
Single command only | Method 3 |
| 2 | KUBECONFIG |
One command (inline) or current shell session (export) |
Methods 2, 4, 5 |
| 3 (default) | $HOME/.kube/config |
Used when no flag or variable is set | Method 1 |
Setting KUBECONFIG:
- Does not add to the default file automatically
- Limits kubectl to the paths you list
- Needs
$HOME/.kube/configin the colon-separated list when you still want Method 1 contexts alongside another file (Method 5)
A kubeconfig ties clusters, users, and contexts together:
| Key | Purpose |
|---|---|
clusters |
API server URL and trusted CA certificate |
users |
Client certificate, token, or exec-based authentication |
contexts |
Named combination of cluster + user (+ optional default namespace) |
current-context |
Which context kubectl uses by default |
A context does not grant permissions by itself. RBAC on the API server still decides whether a request is allowed after authentication succeeds.
admin.conf grants cluster-admin privileges. Use it only for controlled lab administration. In production, create RBAC-scoped credentials instead of distributing the administrator file.
This article does not cover authentication architecture or RBAC policy design. For that depth, see Kubernetes authentication and authorization and Kubernetes RBAC.
Method 1: Copy admin.conf to ~/.kube/config
Use this for everyday cluster access. Get /etc/kubernetes/admin.conf from the control-plane node and install it as ~/.kube/config on the host where you run kubectl:
mkdir -p "$HOME/.kube"On the control-plane, use /etc/kubernetes/admin.conf as <path-to-admin.conf>.
On a remote workstation, copy admin.conf from the control-plane first. From the workstation in the lab (k8s-cp is 192.168.56.108):
scp [email protected]:/etc/kubernetes/admin.conf "$HOME/admin.conf"Install the copied file as your default kubeconfig with your user as owner and mode 600:
sudo install -o "$USER" -g "$(id -gn)" -m 0600 "$HOME/admin.conf" "$HOME/.kube/config"On the control-plane node, install directly from /etc/kubernetes/admin.conf:
sudo install -o "$USER" -g "$(id -gn)" -m 0600 /etc/kubernetes/admin.conf "$HOME/.kube/config"Method 2: Set KUBECONFIG for one command
Use this as a one-time, temporary way to point kubectl at a kubeconfig file:
- Set
KUBECONFIGon the same line as the command - Applies to that single command only and takes precedence over
~/.kube/config - Leaves the next
kubectlcommand to use the default file (or fail if it does not exist yet) - Writes nothing to
~/.kube/config
When ~/.kube/config does not exist yet, kubectl has no cluster credentials and commands such as kubectl get nodes fail.
On the control-plane node, admin.conf is already at /etc/kubernetes/admin.conf. Use that path for a one-time test before you run Method 1:
KUBECONFIG=/etc/kubernetes/admin.conf kubectl get nodesIf the command lists your nodes, the kubeconfig file is valid. This was a one-time check only.
Method 3: Pass --kubeconfig to one command
Use this in scripts or for a one-off command that must read a specific file without changing ~/.kube/config. The flag overrides both KUBECONFIG and the default ~/.kube/config for that command.
kubectl --kubeconfig "$HOME/lab.conf" get nodesMethod 4: Export KUBECONFIG for the shell session
Use this when another cluster should be active for every command in the current terminal. The export lasts until you close the shell or run unset KUBECONFIG. While KUBECONFIG is set, kubectl ignores ~/.kube/config unless you include that path in the variable.
export KUBECONFIG="$HOME/lab.conf"Add the same export line to ~/.bashrc or ~/.profile when you want that path on every login.
Method 5: Load multiple kubeconfig files in one shell
Use this when you switch between several clusters from one workstation. List paths separated by colons on Linux. KUBECONFIG replaces the default file for the session, so include $HOME/.kube/config in the list when you still need contexts from Method 1. The first file wins when context or cluster names overlap.
export KUBECONFIG="$HOME/.kube/config:$HOME/.kube/lab.conf"List merged contexts with kubectl config get-contexts. To write one portable file from several sources, run:
( umask 077; KUBECONFIG="$HOME/.kube/config:$HOME/.kube/lab.conf" kubectl config view --raw --flatten > "$HOME/.kube/merged-config" )The command does four things:
umask 077— New files created in this subshell get mode600(read/write for your user only). The merged file contains cluster credentials, so it should not be world-readable.KUBECONFIG=...— Same colon-separated list as above. kubectl merges those files in memory for this one command. When cluster, user, or context names overlap, the first file in the list wins.kubectl config view --raw --flatten— Prints one kubeconfig YAML with credentials included (--raw).--flattenembeds referenced certificate and key files to produce a self-contained, portable kubeconfig.> "$HOME/.kube/merged-config"— Saves that YAML to a single file you can copy or pointKUBECONFIGat later.
The parentheses run umask and kubectl in a subshell so the stricter umask does not change file permissions for the rest of your terminal session.
kubectl config view --raw writes credentials into the output. Treat merged kubeconfig files as secrets.
Method 6: Switch context in the loaded kubeconfig
Use this after kubeconfig is already loaded when you need a different default from the same file:
- Cluster
- User
- Namespace
kubectl config use-context <context-name>Pin a default namespace with kubectl config set-context --current --namespace=kube-system. Override the context for one command with kubectl --context <name> get nodes.
Verify cluster access
Confirm cluster access after Method 1:
kubectl versionSample output:
Client Version: v1.36.3
Kustomize Version: v5.8.1
Server Version: v1.36.3The Server Version line confirms that kubectl reached the API server. Compare its minor version with the client version to confirm that they are within the supported one-minor-version skew.
List cluster nodes to confirm API access:
kubectl get nodesSample output:
NAME STATUS ROLES AGE VERSION
k8s-cp Ready control-plane 21h v1.36.3
worker01 Ready <none> 21h v1.36.3For namespace concepts and kubectl -n, see Kubernetes namespaces.
Troubleshoot kubectl and kubeconfig
| Symptom | Likely cause | Fix |
|---|---|---|
kubectl: command not found |
Binary missing or not on PATH |
Confirm the file at /usr/local/bin/kubectl or $HOME/.local/bin/kubectl; check echo "$PATH"; run hash -r or open a new shell; run type -a kubectl for an older binary earlier in PATH |
localhost:8080 in the connection error |
No kubeconfig loaded | Create $HOME/.kube/config (Method 1) or set KUBECONFIG |
Connection error on port 6443 from the workstation |
API server down, wrong server: URL, or firewall |
Verify API server health, the server: URL in kubeconfig, and network reachability to port 6443 |
Port 6443 still unreachable on the control-plane |
kubelet active but kube-apiserver static Pod unhealthy | systemctl status kubelet is not enough; run crictl ps -a | grep kube-apiserver (or kubectl get pods -n kube-system when API access works) and inspect kube-apiserver logs |
Most commands fail; no current-context |
Kubeconfig has no active context | kubectl config get-contexts; kubectl config use-context <name> (name must match exactly) |
| Commands hit the wrong cluster | Typo in context name or stale KUBECONFIG |
kubectl config current-context; fix the context name or run unset KUBECONFIG and export the correct path |
x509: certificate signed by unknown authority |
Kubeconfig CA does not match the API server certificate | Obtain a corrected kubeconfig from the cluster administrator |
x509: certificate is valid for ... |
Hostname or IP is not in the API server certificate SAN | Connect with a name or IP from the certificate, or ask the administrator to reissue the server certificate |
Unauthorized or You must be logged in to the server |
API server rejected your credentials | Refresh expired client certificates or tokens from the administrator |
kubectl works without sudo, fails with sudo |
sudo uses /root/.kube/config |
Run kubectl as the user who owns the kubeconfig |
| Permission denied reading kubeconfig | Wrong owner or insufficient permissions | chown to your user; chmod 600 |
| Client/server version skew warnings | kubectl outside the supported one-minor skew window | Install a client within one minor version of the server (for example v1.35–v1.37 against a v1.36 API server) |
| Wrong cluster or namespace | Active context points elsewhere | kubectl config current-context; kubectl config get-contexts; kubectl config use-context <name> |
References
- Install and set up kubectl on Linux
- Organize cluster access using kubeconfig files
- kubectl config
- Version skew policy
Summary
Install kubectl on the Linux host where you plan to run it, confirm client and server versions match within the supported skew, then configure kubeconfig so kubectl get nodes reaches your cluster. Use contexts and KUBECONFIG when you manage more than one cluster. The kubeadm admin.conf file is appropriate for controlled lab administration only; create RBAC-scoped credentials for normal users in production.

