Introduction to kind

by Gautham Pai

Image inclusion

Install Docker

Follow the Docker installation here.

Install kubectl

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
# Install GPG key
# Note that the commands ends with a link (apt-key.gpg)
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# Add k8s repository
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
# Install kubeadm, kubelet and kubectl
sudo apt-get update
sudo apt-get install -y kubectl
sudo apt-mark hold kubectl

Install kind in Linux

[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin
$ kind --version
kind version 0.23.0

For other platforms, refer to the documentation.

Creating a Cluster with kind

We don't have any clusters to begin with

$ kind get clusters
No kind clusters found.

Let us create one

$ kind create cluster
Creating cluster "kind" ...
 βœ“ Ensuring node image (kindest/node:v1.30.0) πŸ–Ό
 βœ“ Preparing nodes πŸ“¦  
 βœ“ Writing configuration πŸ“œ 
 βœ“ Starting control-plane πŸ•ΉοΈ 
 βœ“ Installing CNI πŸ”Œ 
 βœ“ Installing StorageClass πŸ’Ύ 
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind
...

Verify if your current kubectl context is referring to the Kind cluster

$ kubectl config get-contexts
CURRENT   NAME                                     CLUSTER                AUTHINFO                         NAMESPACE
*         kind-kind                                kind-kind              kind-kind    
$ kubectl config current-context
kind-kind

Check if a Docker control-plane container and a network has been created

$ docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED         STATUS         PORTS                       NAMES
bc1bfd181bf1   kindest/node:v1.30.0   "/usr/local/bin/entr…"   4 minutes ago   Up 3 minutes   127.0.0.1:38517->6443/tcp   kind-control-plane
$ docker network ls
NETWORK ID     NAME                    DRIVER    SCOPE
8551fcaf3051   bridge                  bridge    local
92dd22005631   host                    host      local
619dfddb526e   kind                    bridge    local
2424ce287606   none                    null      local
$ docker network inspect kind
[
    {
        "Name": "kind",
        "Id": "619dfddb526edf1527bebc012455e251283eed05393524fe45b1e82acbf0006b",
        "Created": "2024-08-04T19:13:19.149472365+05:30",
        "Scope": "local",
        "Driver": "bridge",
...
$ docker exec -it kind-control-plane /bin/bash
root@kind-control-plane:/# ip addr show
# Kubernetes Basics
kubectl get pods
kubectl run --image nginx webserver1
# Almost equivalent to: docker run -d --name webserver1 nginx
kubectl get pods
kubectl describe pod webserver1
# Make a note of the IP address of the pod
curl <pod-ip> # Example: curl 10.244.0.5
# The equivalent of "docker0"
ip addr show
# We should see 2 network interfaces flannel.1 and cni0
kubectl logs webserver1
kubectl exec -it webserver1 -- /bin/bash
# Inside the pod
echo "Hello" > /usr/share/nginx/html/index.html
^D
curl <pod-ip> # Example: curl 10.244.0.4
# Equivalent of -p 8080:80
kubectl port-forward pod/webserver1 8080:80 --address 0.0.0.0
# Go to the following location in your laptop's browser: http://<public-vm-ip>:8080/
# Kill the port-forward using ^C once done
# Once killed, we can't connect to the service anymore

Deploying with Manifest

cat > my-first-deployment.yaml <<"DELIM"
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webserver
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.22
        name: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
DELIM
kubectl apply -f my-first-deployment.yaml
curl http://172.21.0.2:30592/

Install the Cloud Provider (for LB support)

wget "https://github.com/kubernetes-sigs/cloud-provider-kind/releases/download/v0.3.0/cloud-provider-kind_0.3.0_linux_amd64.tar.gz"
tar -xzf cloud-provider-kind_0.3.0_linux_amd64.tar.gz
sudo mv cloud-provider-kind /usr/local/bin
/usr/local/bin/cloud-provider-kind

Delete using Manifest

kubectl delete -f my-first-deployment.yaml

Delete your Cluster

kind delete cluster --name kind

Working with a 3-node Cluster

cat > three-node-cluster.yaml <<"DELIM"
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
DELIM
kind create cluster --name multinode-kind --config three-node-cluster.yaml
kubectl config current-context
kubectl get nodes
kubectl describe nodes | grep -P "^Name|^Taint"
docker ps

sudo cloud-provider-kind
kubectl apply -f my-first-deployment.yaml 
kubectl get services
kubectl get pods -o wide
# Observe how some pods are scheduled to run in worker and some in worker2
# Accessing via NodePort
docker inspect multinode-kind-worker2 | grep IP
curl 172.21.0.3:31110
curl 172.21.0.4:31110
# Accessing via External IP (must be accessible even from the laptop's browser)
curl <external-ip>
# Delete the Cluster
kind delete cluster --name multinode-kind   

Test Your Knowledge

No quiz available

Tags