My setup:
Ensure SSH is enabled in the VMs (disabled by default on Multipass VM):
# Enable in /etc/ssh/sshd_config PasswordAuthentication yes PubkeyAuthentication yes # Generate RSA key on client machines # Add ~/.ssh/id_rsa.pub from each client machine to ~/.ssh/authorized_keys on each VM
# Define the Kubernetes version and used CRI-O stream export KUBERNETES_VERSION=v1.31 export CRIO_VERSION=v1.31 # Add the Kubernetes repository sudo curl -fsSL https://pkgs.k8s.io/core:/stable:/$KUBERNETES_VERSION/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/$KUBERNETES_VERSION/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list # Add the CRI-O repository sudo curl -fsSL https://pkgs.k8s.io/addons:/cri-o:/stable:/$CRIO_VERSION/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/cri-o-apt-keyring.gpg echo "deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://pkgs.k8s.io/addons:/cri-o:/stable:/$CRIO_VERSION/deb/ /" | sudo tee /etc/apt/sources.list.d/cri-o.list # Install packages sudo apt-get update sudo apt-get install -y cri-o kubelet kubeadm sudo apt-mark hold kubelet kubeadm cri-o # Set swap off, start br_netfilter, and set ipv4 forwarding sudo swapoff -a sudo modprobe br_netfilter echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/k8s.conf sudo sysctl --system # Start CRI-O sudo systemctl start crio.service # Initialize control-plane node export CIDR=10.85.0.0/16 sudo kubeadm init
# Install kubectl sudo apt install kubectl # Create .kube directory mkdir ~/.kube # Copy necessary files from control plane node # /etc/kubernetes/pki/apiserver-kubelet-client.crt # /etc/kubernetes/pki/apiserver-kubelet-client.key # /etc/kubernetes/pki/ca.crt # Create local Kubeconfig file (~/.kube/config) apiVersion: v1 clusters: - cluster: certificate-authority: ./ca.crt server: https://<control-plane-ip>:6443 name: kubernetes contexts: - context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes current-context: kubernetes-admin@kubernetes kind: Config preferences: {} users: - name: kubernetes-admin user: client-certificate: ./apiserver-kubelet-client.crt client-key: ./apiserver-kubelet-client.key # Test kubectl kubectl config use-context kubernetes-admin@kubernetes kubectl get nodes
Follow the same steps as the control-plane node, except for the initialization. Then join the cluster:
sudo kubeadm join <cluster-ip>:6443 --token e7dfct.uh6ojtum3vmswbx7 --discovery-token-ca-cert-hash sha256:e012626
Create deployment and service files on the client machine:
# hello-world-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: hello-world spec: replicas: 3 selector: matchLabels: app: hello-world template: metadata: labels: app: hello-world spec: containers: - name: hello-world image: hashicorp/http-echo args: - "-text=Hello, World!" ports: - containerPort: 5678 # hello-world-service.yaml apiVersion: v1 kind: Service metadata: name: hello-world spec: type: NodePort selector: app: hello-world ports: - port: 5678 targetPort: 5678 nodePort: 30007 # Apply the configurations kubectl apply -f hello-world-deployment.yaml kubectl apply -f hello-world-service.yaml # View pods and nodes kubectl get pods -o wide kubectl get nodes -o wide # Access the hello-world app curl http://<any-one-node-internal-ip>:30007 # Scale the deployment kubectl get deployments kubectl scale deployment--replicas=2 # To know on which node the pod is running kubectl get pods -o wide