Start your free 14-day ContainIQ trial

Kubectl Config Set-Context | Tutorial and Best Practices

June 27, 2022

Kubernetes comes with many tools to help you manage your clusters, including kubectl set-context. In this guide, you’ll learn how to use this command to manipulate contexts in your kubeconfig file, as well as best practices for doing so.

Ketan Singh
Backend Engineer

The first time you configure kubectl, you need to place kubeconfig in the correct location before you’re able to issue commands to your Kubernetes cluster. There are three ways to do this.

One option is to place the kubeconfig file in <terminal inline>$HOME/.kube/config<terminal inline>, which is the default path kubectl looks for.

Another option is to use the flag <terminal inline>--kubeconfig<terminal inline>. If your kubeconfig is located somewhere other than the default path, you can specify it with this flag and issue commands:


$ kubectl --kubeconfig path1 get pods

The final option is to use the <terminal inline>KUBECONFIG<terminal inline> environment variable. This environment variable allows you to specify multiple kubeconfig files by setting the value to the paths of the files, delimited by colons:


$ export KUBECONFIG=path1:path2:path3
$ kubectl get pods

If you are working with multiple Kubernetes clusters, it can quickly become cumbersome to manage configuration files like this as you are switching from one cluster to the other.

If your clusters have multiple namespaces, another pain point appears: the need to specify <terminal inline>--namespace<terminal inline> or <terminal inline>-n<terminal inline> every time you use <terminal inline>kubectl<terminal inline>. Combined with multiple clusters, every <terminal inline>kubectl<terminal inline> command is going to look something like <terminal inline>kubectl --namespace <NAMESPACE_NAME> --kubeconfig <PATH_TO_KUBECONFIG> …<terminal inline>, which is both time consuming and an easy place for errors to slip in.

This is where Kubernetes contexts come into the picture. You can think of Kubernetes contexts as a kind of shortcut that allows you to access cluster, user, and namespace parameters conveniently.

This allows you to define multiple contexts in your configuration file, which you can then use to target multiple Kubernetes clusters, or the same cluster with a different set of users or namespaces. You can quickly switch between clusters by using the <terminal inline>kubectl config use-context<terminal inline> command. To use that command, though, you need to configure contexts in your kubeconfig. This can be done with the <terminal inline>kubectl config set-context<terminal inline> command. In this article, you’ll take a closer look at how kubeconfig is structured, how to define contexts in kubeconfig, and how to effectively use <terminal inline>set-context<terminal inline> to manipulate different contexts.

What is Kubernetes Context?

In Kubernetes, a <terminal inline>context<terminal inline> is an entity defined inside kubeconfig to alias cluster parameters with a human-readable name. It’s important to understand that a Kubernetes context only applies to the client side. The Kubernetes API server itself doesn’t recognize <terminal inline>context<terminal inline> the way it does other objects such as pods, deployments, or namespaces.

Let’s take a look at a cross section of a typical kubeconfig structure to see how cluster, user, and context tie up together.


---
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: ...
    server: ...
  name: k3d-k3s
contexts:
- context:
    cluster: k3d-k3s
    user: admin@k3d-k3s
  name: k3d-k3s-default
current-context: k3d-k3
kind: Config
preferences: {}
users:
- name: admin@k3d-k3s
  user:
    client-certificate-data: ...
    client-key-data: ...

Typically there are three parts to a kubeconfig:

  • Clusters: This section lists all the clusters that you have access to. Each <terminal inline>cluster<terminal inline> contains details about the URL for the Kubernetes API server (where the cluster accepts commands from kubectl), certificate authority, and a name to identify the cluster.
  • Contexts: This is the most relevant section to this tutorial, since it lists the available contexts. Each <terminal inline>context<terminal inline> consists of the cluster name, user, and namespace that you can access when you invoke it. Note that in the example, the namespace information is omitted because it’s using the <terminal inline>default<terminal inline> namespace.
  • Users: The users section identifies each user by a unique name and includes the relevant authentication information, which could be client certificates (as is the case here), bearer tokens, or an authenticating proxy.

In this example, the kubeconfig contains only one cluster, user, and context. Interestingly, it also contains <terminal inline>current-context<terminal inline> which means all of the <terminal inline>kubectl<terminal inline> commands are going to run in that context unless that is changed.

Which brings us to <terminal inline>kubectl set-context<terminal inline>, which is used to set a context entry in kubeconfig.

K8s Metrics, Logging, and Tracing
Monitor the health of your cluster and troubleshoot issues faster with pre-built dashboards that just work.
Start Free Trial Book a Demo

Using kubectl config set-context

To follow this tutorial, you need to have access from your local machine to a Kubernetes deployment via the <terminal inline>kubectl<terminal inline> command-line tool.

  • For instructions on how to install <terminal inline>kubectl<terminal inline> on your workstation, you can read official documentation.
  • The easiest way to install Kubernetes is using minikube, Rancher Desktop, Docker Desktop, or a similar tool. All of these tools install Kubernetes locally and preconfigure kubectl to give you access to the deployment.

After setting up Kubernetes and kubectl, you can look at the <terminal inline>set-context<terminal inline> help using the following command:


kubectl config set-context --help

You’ll get the following output:


$ kubectl config set-context --help
Set a context entry in kubeconfig.

Specifying a name that already exists will merge new fields on top of existing values for those fields.

Examples:
  # Set the user field on the gce context entry without touching other values
  kubectl config set-context gce --user=cluster-admin

Options:
    --current=false: Modify the current context

Usage:
  kubectl config set-context [NAME | --current] [--cluster=cluster_nickname] [--user=user_nickname]
[--namespace=namespace] [options]

What this says is that you can create or modify contexts in your kubeconfig file with the command <terminal inline>kubectl config set-context<terminal inline>. This command also accepts the name of the context to be changed (or <terminal inline>--current<terminal inline> if you want to change the current context), as well as <terminal inline>--user<terminal inline>, <terminal inline>--cluster<terminal inline>, and <terminal inline>--namespace<terminal inline> options. If the specified context already exists in the kubeconfig, this command is going to modify that entry with the parameters that are passed.

Basic Usage of kubectl config set-context

Before you start modifying your kubeconfig, it’s helpful to know how to display its content. To do this, you can to use the following command:


kubectl config view

The result will vary depending on the tool you use, since each tool names the users and clusters differently, but basically maintains the structure discussed earlier.


apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://kubernetes.docker.internal:6443
  name: docker-desktop
contexts:
- context:
    cluster: docker-desktop
    user: docker-desktop
  name: docker-desktop
current-context: docker-desktop
kind: Config
preferences: {}
users:
- name: docker-desktop
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

Say you want to create a new context for development called “dev-context”, which points to the namespace “dev-namespace”, and the user “dev-user”. For simplicity, let’s also assume that you’re using the same cluster you’re currently in.

The command to add a new context with the data described above is as follows:


kubectl config set-context \
dev-context \
--namespace=dev-namespace \
--cluster=docker-desktop \
--user=dev-user

If you run the <terminal inline>kubectl config view<terminal inline> command again, you’ll notice that the new context has been added:


apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://kubernetes.docker.internal:6443
  name: docker-desktop
contexts:
- context:
    cluster: docker-desktop
    namespace: dev-namespace
    user: dev-user
  name: dev-context
- context:
    cluster: docker-desktop
    user: docker-desktop
  name: docker-desktop
current-context: docker-desktop
kind: Config
preferences: {}
users:
- name: docker-desktop
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

You’ll also notice that the user was only added to the context section, which you’ll look at in more detail shortly. Now that you’ve learned how to add contexts to your kubeconfig, it’s time to learn how to modify an existing context.

Suppose you want to change the <terminal inline>dev-namespace<terminal inline> name to “development”. To do this, you can use the following command:


kubectl config set-context \
dev-context \
--namespace=development \
--cluster=docker-desktop \
--user=dev-user

This will return the message “Context “dev-context” modified”, indicating that the change was successful.

The template to create or modify a context is as follows:


kubectl config set-context \
<CONTEXT_NAME> \
--namespace=<NAMESPACE_NAME> \
--cluster=<CLUSTER_NAME> \
--user=<USER_NAME>

Since the point of creating contexts is to be able to switch to any of them as needed, you’ll want to familiarize yourself with the following commands:


# Shows which is the active context
kubectl config current-context

# Allows you to switch between contexts using their name
kubectl config use-context <CONTEXT_NAME>

Advanced Usage of kubectl config set-context

In this section, you’ll look at how to configure access to other clusters in a more complex situation. There are scenarios where you can leverage the <terminal inline>kubectl config set-context<terminal inline> command to simplify your workflow.

As you may have already noticed, <terminal inline>kubectl config set-context<terminal inline> is only one of many commands that help you work with the kubeconfig file. Specifically, <terminal inline>kubectl config set-context<terminal inline> only modifies the section of kubeconfig corresponding to the context.

The following commands are the commands that allow you to add or modify cluster access and user credentials in your kubeconfig. You might notice some similarity to <terminal inline>kubectl config set-context<terminal inline> in its structure.

To add or modify a cluster, you can use the following template:


# Add or modify a cluster
kubectl config set-cluster \
<CLUSTER_NAME> \
--server=<SERVER_ADDRESS> \
--certificate-authority=<CLUSTER_CERTIFICATE>

Similarly, you can use the following template to add or modify the user’s credentials:


# Add or modify user credentials
kubectl config set-credentials \
<USER_NAME> \
--client-certificate=<USER_CERTIFICATE> \
--client-key=<USER_KEY>

Please note that for the purposes of this tutorial, client certificates are used to authenticate the user, and a certificate authority (CA) is used to authenticate to Kubernetes. For more information about other authentication methods, you can read the Kubernetes authentication overview.

Using the commands described above, you can now add a new cluster, a new context, and a new user to the kubeconfig.

Suppose you want to access a new cluster called “prod” with a specific IP address and credentials. To add it to kubeconfig, you can use a command like this:


kubectl config set-cluster \
prod \
--server=https://1.2.3.4 \
--certificate-authority=xTsofu101...

To add a new context called “prod”, with a namespace called “production” and a user called “admin”, you can use the following command:


kubectl config set-context \
prod \
--namespace=production \
--cluster=prod \
--user=admin

To complete this exercise, add the imaginary credentials for the user “admin”:


kubectl config set-credentials \
admin \
--client-certificate=<CERTIFICATE> \
--client-key=<KEY>

To review the changes, use the <terminal inline>kubectl config view<terminal inline> command. The output should be similar to the following:


apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://kubernetes.docker.internal:6443
  name: docker-desktop
- cluster:
    certificate-authority: <CERTIFICATE>
    server: https://1.2.3.4
  name: prod
contexts:
- context:
    cluster: docker-desktop
    namespace: development
    user: dev-user
  name: dev-context
- context:
    cluster: docker-desktop
    user: docker-desktop
  name: docker-desktop
- context:
    cluster: prod
    namespace: production
    user: admin
  name: prod
current-context: docker-desktop
kind: Config
preferences: {}
users:
- name: admin
  user:
    client-certificate: <CERTIFICATE>
    client-key: <KEY>
- name: docker-desktop
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

Now, whenever you want to access the <terminal inline>prod<terminal inline> cluster in the production namespace as the user admin, all you have to do is use the command:


kubectl config use-context prod

The use case shown is just an example of what you can achieve using the <terminal inline>kubectl config set-<terminal inline> commands. You can create any conceivable combination of contexts with different users, namespaces, and clusters.

Best Practices When Using kubectl config set-context

A common challenge IT departments face is agreeing on an appropriate naming convention. When you use the <terminal inline>kubectl config set-<terminal inline> context command, you’re actually creating an alias, a kind of shortcut that allows you to avoid the need to enter multiple flags on the command line. While this can speed up your workflow, it could become a problem if your team doesn’t follow a naming guideline.

Consider the example from the previous section. If you only work with a single cluster, the name “production” may be appropriate. But what if you need access to dozens of Kubernetes deployments? What if each of those clusters has several namespaces (production, testing, stage), and multiple users with different access permissions?

If your organization isn’t careful, each developer may end up using different names to refer to the same object, cluster, or namespace. In fact, even if you work alone, you can forget how to access a given cluster if you use a different naming convention every time.

To avoid situations like the one described above, the best practice is to plan a naming strategy for your organization in advance.

It’s also important to remember that your kubeconfig file is a kind of private key. Anyone who has access to this file will be able to authenticate to your Kubernetes deployment. It’s crucial that you take every precaution to keep your kubeconfig secure and private.

Final Thoughts

In this article, you’ve learned what Kubernetes config contexts are, how they’re used, and how you can manipulate contexts in your kubeconfig file by using <terminal inline>set-context<terminal inline> to make your life easier when using <terminal inline>kubectl<terminal inline> commands.

If you liked this post and are running Kubernetes in production, you might be interested in ContainIQ. It uses eBPF to instrument the applications deployed in your Kubernetes clusters. It offers an easily readable, visually friendly dashboard for keeping an eye on metrics, events, logs, and traces, which help keep services healthy and allows you to zero in quickly on any production issues.

Start your free 14-day ContainIQ trial
Start Free TrialBook a Demo
No card required
Ketan Singh
Backend Engineer

Ketan is a Backend Engineer with experience in fintech. His favorite programming languages are Go and Rust, and he has substantial experience running workloads on Kubernetes.

READ MORE