Generate kubeconfig files
Where you are
A kubeconfig file bundles two things: an identity and the address of the API server to reach. You make one kubeconfig per component now so that each component can prove who it is when the runtimes start. Nothing runs yet. You are still assembling credentials, this time by packaging the certificates you signed in the last step into files each component can read.
Generate the kubeconfig files
A kubeconfig file is a Kubernetes client configuration file. It tells a client how to connect to a Kubernetes API server and how to authenticate to it. In this step you generate one for the kubelet on each worker node, one for each control plane service, and one for the admin user.
The kubelet kubeconfig file
The kubelet runs on each worker node and manages the containers there. When you generate a kubeconfig for a kubelet, you must use the client certificate that matches the kubelet’s node name. This lets the Node Authorizer, the part of the API server that decides what each node is allowed to do, recognize the node and grant the correct permissions.
Run the following commands in the same directory you used to generate the certificates in the previous step.
Generate a kubeconfig file for the node-0 and node-1 worker nodes:
for host in node-0 node-1; do
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=https://server.kubernetes.local:6443 \
--kubeconfig=${host}.kubeconfig
kubectl config set-credentials system:node:${host} \
--client-certificate=${host}.crt \
--client-key=${host}.key \
--embed-certs=true \
--kubeconfig=${host}.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:node:${host} \
--kubeconfig=${host}.kubeconfig
kubectl config use-context default \
--kubeconfig=${host}.kubeconfig
done
Each pass runs four commands. The first names the cluster and records the API server address and CA certificate. The second records the identity, the node’s client certificate and key. The third joins that cluster and that identity into a context. The fourth makes that context the active one. The --embed-certs=true flag copies the certificate contents into the file, so the kubeconfig is self contained and does not point at separate certificate files.
Results:
node-0.kubeconfig
node-1.kubeconfig
The kube-proxy kubeconfig file
The kube-proxy service runs on each worker node and keeps network rules in sync. Generate a kubeconfig file for the kube-proxy service:
{
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=https://server.kubernetes.local:6443 \
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-credentials system:kube-proxy \
--client-certificate=kube-proxy.crt \
--client-key=kube-proxy.key \
--embed-certs=true \
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:kube-proxy \
--kubeconfig=kube-proxy.kubeconfig
kubectl config use-context default \
--kubeconfig=kube-proxy.kubeconfig
}
Results:
kube-proxy.kubeconfig
The kube-controller-manager kubeconfig file
The kube-controller-manager runs on the control plane and drives the cluster toward its desired state. Generate a kubeconfig file for the kube-controller-manager service:
{
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=https://server.kubernetes.local:6443 \
--kubeconfig=kube-controller-manager.kubeconfig
kubectl config set-credentials system:kube-controller-manager \
--client-certificate=kube-controller-manager.crt \
--client-key=kube-controller-manager.key \
--embed-certs=true \
--kubeconfig=kube-controller-manager.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:kube-controller-manager \
--kubeconfig=kube-controller-manager.kubeconfig
kubectl config use-context default \
--kubeconfig=kube-controller-manager.kubeconfig
}
Results:
kube-controller-manager.kubeconfig
The kube-scheduler kubeconfig file
The kube-scheduler runs on the control plane and assigns pods to nodes. Generate a kubeconfig file for the kube-scheduler service:
{
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=https://server.kubernetes.local:6443 \
--kubeconfig=kube-scheduler.kubeconfig
kubectl config set-credentials system:kube-scheduler \
--client-certificate=kube-scheduler.crt \
--client-key=kube-scheduler.key \
--embed-certs=true \
--kubeconfig=kube-scheduler.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:kube-scheduler \
--kubeconfig=kube-scheduler.kubeconfig
kubectl config use-context default \
--kubeconfig=kube-scheduler.kubeconfig
}
Results:
kube-scheduler.kubeconfig
The admin kubeconfig file
The admin user is the identity you use to run commands against the cluster yourself. Its kubeconfig points at https://127.0.0.1:6443 because you will run these commands on the server machine itself, so the API server is reachable on the local loopback address. Generate a kubeconfig file for the admin user:
{
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=https://127.0.0.1:6443 \
--kubeconfig=admin.kubeconfig
kubectl config set-credentials admin \
--client-certificate=admin.crt \
--client-key=admin.key \
--embed-certs=true \
--kubeconfig=admin.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=admin \
--kubeconfig=admin.kubeconfig
kubectl config use-context default \
--kubeconfig=admin.kubeconfig
}
Results:
admin.kubeconfig
Distribute the kubeconfig files
Each kubeconfig has to live on the machine that will read it. Copy the kubelet and kube-proxy kubeconfig files to the node-0 and node-1 machines:
for host in node-0 node-1; do
ssh root@${host} "mkdir -p /var/lib/{kube-proxy,kubelet}"
scp kube-proxy.kubeconfig \
root@${host}:/var/lib/kube-proxy/kubeconfig \
scp ${host}.kubeconfig \
root@${host}:/var/lib/kubelet/kubeconfig
done
Copy the kube-controller-manager and kube-scheduler kubeconfig files to the server machine:
scp admin.kubeconfig \
kube-controller-manager.kubeconfig \
kube-scheduler.kubeconfig \
root@server:~/
Each component now holds a file that proves its identity and tells it where to find the API server. When the runtimes start in a later step, they read these files to authenticate.
Key terms
kubeconfig: A file that tells a Kubernetes client how to reach an API server and how to authenticate to it. It holds three kinds of entries: clusters, users, and contexts.
cluster (in a kubeconfig): An entry that records an API server address and the CA certificate used to verify that server. In these files it is named kubernetes-the-hard-way.
user (in a kubeconfig): An entry that records an identity, made up of a client certificate and key. Examples here include system:node:node-0, system:kube-proxy, and admin.
context: An entry that pairs one cluster with one user. The active context decides which cluster the client talks to and which identity it presents. Each file here defines a single context named default and makes it active.
Reflect
Each kubeconfig embeds both an identity and the API server address. If you later move the API server to a new address, what would you have to do to every kubeconfig you generated here, and why does embedding the certificate contents not save you from that work?