Install kubectl on Linux and Configure kubeconfig

Install kubectl on Rocky Linux, RHEL, Ubuntu, or Debian, then configure kubeconfig, contexts, and remote access to a Kubernetes cluster.

Published

Updated

Read time 14 min read

Reviewed byDeepak Prasad

Install kubectl on Linux and configure kubeconfig for a remote Kubernetes cluster
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:

bash
command -v kubectl

Sample output when kubectl is present:

output
/usr/bin/kubectl

When 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:

bash
KUBECTL_VERSION=v1.36.3

If 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:

bash
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY

Confirm CPU architecture before you download. Use amd64 in the URL when uname -m prints x86_64, or arm64 on AArch64 hosts:

bash
uname -m

Sample output on the lab workstation:

output
x86_64

Download the binary with curl. The -f flag stops on HTTP errors and -SLO saves the file under its original name:

bash
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:

bash
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:

bash
echo "$(cat kubectl.sha256)  kubectl" | sha256sum --check

Sample output:

output
kubectl: OK

A 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:

bash
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

When you cannot use sudo, install under your home directory instead. Create a private bin directory first:

bash
mkdir -p "$HOME/.local/bin"

Copy the binary with executable permissions:

bash
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:

bash
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:

bash
command -v kubectl

Sample output for a user-local install:

output
/home/user/.local/bin/kubectl

A path under /usr/local/bin means the system-wide install succeeded.

Confirm the client reports the version you intended:

bash
kubectl version --client

Sample output:

output
Client Version: v1.36.3
Kustomize Version: v5.8.1

When 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:

bash
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
EOF

Install only the client package. Installing only the kubectl package does not install kubeadm or kubelet:

bash
sudo dnf install -y kubectl

On the lab control-plane node the RPM reports:

output
kubectl-1.36.3-150500.1.1.x86_64

The 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:

bash
sudo apt-get update

Install tools needed to fetch and verify the Kubernetes APT repository key:

bash
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

Create the keyring directory APT expects for third-party keys:

bash
sudo install -m 0755 -d /etc/apt/keyrings

Download the v1.36 repository signing key and store it in the keyring:

bash
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

Set permissions so every user can read the key but only root can write it:

bash
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg

Register the Kubernetes APT source for the v1.36 channel:

bash
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.list

Set the list file readable by APT but not writable by other users:

bash
sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list

Reload the index so APT sees the new repository:

bash
sudo apt-get update

Install the kubectl client package:

bash
sudo apt-get install -y kubectl

Run 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:

bash
kubectl version --client

Sample output from the lab:

output
Client Version: v1.36.3
Kustomize Version: v5.8.1

The 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 Version line, and the command exits with an error
bash
kubectl version

Sample output from worker01 in the lab after temporarily moving ~/.kube/config aside:

output
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/config in 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.

IMPORTANT
Accept kubeconfig files only from trusted sources. A malicious kubeconfig can point kubectl at a hostile API server or run arbitrary helper commands during exec-based authentication. The kubeadm 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:

bash
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):

bash
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:

bash
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:

bash
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 KUBECONFIG on the same line as the command
  • Applies to that single command only and takes precedence over ~/.kube/config
  • Leaves the next kubectl command 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:

bash
KUBECONFIG=/etc/kubernetes/admin.conf kubectl get nodes

If 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.

bash
kubectl --kubeconfig "$HOME/lab.conf" get nodes

Method 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.

bash
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.

bash
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:

bash
( umask 077; KUBECONFIG="$HOME/.kube/config:$HOME/.kube/lab.conf" kubectl config view --raw --flatten > "$HOME/.kube/merged-config" )

The command does four things:

  1. umask 077 — New files created in this subshell get mode 600 (read/write for your user only). The merged file contains cluster credentials, so it should not be world-readable.
  2. 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.
  3. kubectl config view --raw --flatten — Prints one kubeconfig YAML with credentials included (--raw). --flatten embeds referenced certificate and key files to produce a self-contained, portable kubeconfig.
  4. > "$HOME/.kube/merged-config" — Saves that YAML to a single file you can copy or point KUBECONFIG at 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.

IMPORTANT
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
bash
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:

bash
kubectl version

Sample output:

output
Client Version: v1.36.3
Kustomize Version: v5.8.1
Server Version: v1.36.3

The 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:

bash
kubectl get nodes

Sample output:

output
NAME       STATUS   ROLES           AGE   VERSION
k8s-cp     Ready    control-plane   21h   v1.36.3
worker01   Ready    <none>          21h   v1.36.3

For 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


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.


Frequently Asked Questions

1. Can I use a newer kubectl client than the Kubernetes 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 versions do not have to match exactly. Installing the newest kubectl binary without checking the cluster version can produce avoidable compatibility warnings.

2. Is copying admin.conf the right kubeconfig for every user?

No. The kubeadm admin.conf grants cluster-admin privileges. Use it only for controlled lab administration on the control-plane node or a trusted workstation. Generate separate RBAC-scoped credentials for normal users in production.

3. Why does kubectl try localhost:8080 when no kubeconfig exists?

kubectl falls back to http://localhost:8080 when it cannot find a valid kubeconfig and no KUBECONFIG path is set. Create $HOME/.kube/config or export KUBECONFIG to point at your cluster credentials.

4. Why does kubectl work for my user but fail with sudo?

sudo runs kubectl as root, so kubectl looks for /root/.kube/config instead of your user kubeconfig. Run kubectl as the account that owns the file, or copy credentials into root only when you deliberately need root-level cluster access.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)