Run Kubernetes API server locally
Overview
In this post, I’ll share how to run Kube API server in your local. If you are not familiar with Kubernetes components in the control plane, it’d be great to start with playing with API server.
What is Kube API server?
Kube API server is a component in the control plane of Kubernetes, which is responsible for managing Kubernetes objects that are stored in etcd (another component for datastore). For more details, you can check the official document: https://kubernetes.io/docs/concepts/overview/components/.
Every time we use kubectl
, it sends a request to API server to create/get/update/delete Kubernetes resources.
Kubernetes controllers/operators are also a client of Kube API server, which send requests to API server to get the status of its target objects and make changes via API server.
Kube API server is the central component that interacts with other components.
To gain deeper understanding of Kubernetes components, we can’t skip Kube API server.
Prerequisite
- bash:
brew install bash
- openssl:
brew install openssl
- etcd:
brew install etcd
If you’re using Mac you can install them via brew
Steps
Run etcd
Running Kube API server locally is helpful to get more familiar with it.
Kube API server uses etcd as a backend datastore, we need etcd to run API server.
You can start etcd
by the command etcd
:
etcd
...
{"level":"info","ts":"2023-03-26T07:07:29.803+0900","caller":"api/capability.go:75","msg":"enabled capabilities for version","cluster-version":"3.5"}
{"level":"info","ts":"2023-03-26T07:07:29.803+0900","caller":"etcdserver/server.go:2595","msg":"cluster version is updated","cluster-version":"3.5"}
Build Kubernetes
You can build Kubernetes with the following steps:
git clone https://github.com/kubernetes/kubernetes && kubernetes
git checkout release-1.26 # you can choose any version
make
Prepare certificates
Prepare the following shell script to create certificate for service account and api-server
# service account
openssl genrsa -out service-account-key.pem 4096
openssl req -new -x509 -days 365 -key service-account-key.pem -subj "/CN=test" -sha256 -out service-account.pem
# api-server
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=test" -days 10000 -out ca.crt
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -config csr.conf
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt -days 10000 \
-extensions v3_ext -extfile csr.conf
# kubeconfig
kubectl config set-cluster local-apiserver \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=https://127.0.0.1:6443 \
--kubeconfig=kubeconfig
kubectl config set-credentials admin \
--client-certificate=server.crt \
--client-key=server.key \
--embed-certs=true \
--kubeconfig=kubeconfig
kubectl config set-context default \
--cluster=local-apiserver \
--user=admin \
--kubeconfig=kubeconfig
kubectl config use-context default --kubeconfig=kubeconfig
In this post, we don’t see how those commands works in details. For more details about certificates, you can check Generate Certificates Manually.
Run API server
Now we are going to run API server that is built in the above step:
PATH_TO_KUBERNETES_DIR=~/repos/kubernetes/kubernetes # the path to your cloned kubernetes repo
You can check the API server’s version:
${PATH_TO_KUBERNETES_DIR}/_output/bin/kube-apiserver --version
Kubernetes v1.26.3-11+9043dd888deae0
Start the API server
${PATH_TO_KUBERNETES_DIR}/_output/bin/kube-apiserver --etcd-servers http://localhost:2379 \
--service-account-key-file=service-account-key.pem \
--service-account-signing-key-file=service-account-key.pem \
--service-account-issuer=api \
--tls-cert-file=server.crt \
--tls-private-key-file=server.key \
--client-ca-file=ca.crt
Check the component status with the following command:
kubectl get componentstatuses --kubeconfig kubeconfig
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Unhealthy Get "https://127.0.0.1:10259/healthz": dial tcp 127.0.0.1:10259: connect: connection refused
controller-manager Unhealthy Get "https://127.0.0.1:10257/healthz": dial tcp 127.0.0.1:10257: connect: connection refused
etcd-0 Healthy {"health":"true","reason":""}
Only etcd is healthy as we don’t run scheduler and controller manager.
Try using the API server
We need to create default/default
service account with the following command:
kubectl create sa default --kubeconfig kubeconfig
Now you can create a nginx Pod with the following command:
kubectl run nginx --image nginx --kubeconfig kubeconfig
You can list Pods with kubectl get pods
:
kubectl get pod --kubeconfig kubeconfig
NAME READY STATUS RESTARTS AGE
nginx 0/1 Pending 0 41s
(The Pod will remain Pending status as there’s no kubelet, which is a component to start a container for Pod)
Clean up the Pod
kubectl delete pod nginx --kubeconfig kubeconfig
Summary
In this post, I shared how to run Kube API server locally (with the dependent component etcd
) and created a Pod object using kubectl
.
We run API server with different configuration: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/