Cách dựng 1 cluster Kubernetes phục vụ mục đích phát triển trong 2 phút

Thi thoảng có vài bạn hỏi mình là: “Có cách nào để dựng 1 cluster K8s thật nhanh không?”

Câu trả lời là có: Bạn có thể sử dụng minikube, nhưng nhược điểm của minikube là tốn bộ nhớ máy cực kỳ, do minikube sẽ dựng sẵn cho bạn 1 multi-nodes cluster. Mình nhớ có lần mình dùng cloud9 với instance là một con t2.micro, dung lượng 8GB mặc định, chạy minikube start nó chửi ầm ĩ là không đủ bộ nhớ. Chưa kể có vài câu lệnh tương tác với cluster cũng sẽ phải nhớ.

Mình muốn giới thiệu một công cụ đơn giản hơn, nhẹ nhàng hơn (cloud9 8GB bộ nhớ mình vẫn chạy phà phà), tương tác với cluster bằng kubectl thông thường, bạn có thể dựng xong 1 cluster chỉ trong vài câu lệnh (chắc là không tốn tới tận 2 phút gõ lệnh luôn), đó là Kind:

https://kind.sigs.k8s.io/

Cách làm:

Chuẩn bị sẵn một máy ảo chạy linux, tốt nhất thì dùng distro là Ubuntu, x86_64. Tuy nhiên bạn thích dùng dòng arm thì cũng được. Lưu ý là cài kubectl vào nhé!

Cài đặt kind:

# Nếu dùng AMD64 / x86_64
[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64

# Nếu dùng ARM64
[ $(uname -m) = aarch64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-arm64

và chạy tiếp:
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

Sau khi đã cài đặt kind thành công, bạn chỉ cần:

kind create cluster --name <tên cluster>

Done, lúc này bạn đã có thể tương tác với cluster của bạn bằng câu lệnh kubectl bình thường, ví dụ:

kubectl cluster-info –context kind-kind

Để xem list các cluster mà kind tạo ra:

kind get clusters

Xóa cluster do kind tạo ra:

kind delete cluster

Nếu bạn thích thử tạo 1 cluster K8s sử dụng Kind, thì đọc tiếp phần sau.

Create a K8s Cluster

Install kubectl:

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

kubectl version --client
# If you do not have root access on the target system, you can still install kubectl to the ~/.local/bin directory:

chmod +x kubectl
mkdir -p ~/.local/bin
mv ./kubectl ~/.local/bin/kubectl
# and then append (or prepend) ~/.local/bin to $PATH

Cài đặt container engine (Docker):

sudo yum update
sudo yum install docker -y
sudo usermod -aG docker $USER

(optional) cài đặt docker compose:

sudo yum install python3-pip -y

sudo pip3 install docker-compose # with root access

# OR #
pip3 install --user docker-compose # without root access for security reasons

Tạo cluster bằng kind:

kind create cluster

Deploy 1 app:

kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1

kubectl get deployments

kubectl proxy # open in a new terminal

curl http://localhost:8001/version

export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
echo Name of the Pod: $POD_NAME

curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME:8080/proxy/

Kiểm tra pods và nodes:

kubectl get pods
kubectl describe pods

Hãy nhớ rằng các Pod đang chạy trong một mạng riêng được cô lập – vì vậy chúng ta cần ủy quyền (proxy) quyền truy cập vào chúng để có thể gỡ lỗi và tương tác với chúng. Để làm điều này, chúng ta sẽ sử dụng lệnh kubectl proxy để chạy một proxy trong một terminal thứ hai. Mở một cửa sổ terminal mới và trong terminal mới đó, hãy chạy:

kubectl proxy

export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"
echo Name of the Pod: $POD_NAME

curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME:8080/proxy/

kubectl logs "$POD_NAME"

Chạy command trên container:

kubectl exec "$POD_NAME" -- env
kubectl exec -ti $POD_NAME -- bash
cat server.js
curl http://localhost:8080
exit

Sử dụng service để expose app:

kubectl get pods
kubectl get services
kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
kubectl get services
kubectl describe services/kubernetes-bootcamp

export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
echo "NODE_PORT=$NODE_PORT"

Get kind node IP:

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' kind-control-plane
curl http://$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' kind-control-plane):$NODE_PORT

Sử dụng label:

kubectl describe deployment
kubectl get pods -l app=kubernetes-bootcamp
kubectl get services -l app=kubernetes-bootcamp
export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"
echo "Name of the Pod: $POD_NAME"
kubectl label pods "$POD_NAME" version=v1
kubectl describe pods "$POD_NAME"
kubectl get pods -l version=v1

Xóa service:

kubectl delete service -l app=kubernetes-bootcamp
kubectl get services
curl http://$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' kind-control-plane):$NODE_PORT
kubectl exec -ti $POD_NAME -- curl http://localhost:8080

Scale app:

Vì đã xóa ở bên trên nên cần expose lại:

kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
kubectl get deployments
kubectl get rs
kubectl scale deployments/kubernetes-bootcamp --replicas=4
kubectl get deployments
kubectl get pods -o wide
kubectl describe deployments/kubernetes-bootcamp

Load balancing:

kubectl describe services/kubernetes-bootcamp
export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"

echo NODE_PORT=$NODE_PORT

curl http://$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' kind-control-plane):$NODE_PORT

Scale down:

kubectl scale deployments/kubernetes-bootcamp --replicas=2
kubectl get deployments
kubectl get pods -o wide

Thực hiện rolling update:

kubectl get pods
kubectl describe pods

kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=docker.io/jocatalin/kubernetes-bootcamp:v2
kubectl get pods
kubectl describe services/kubernetes-bootcamp
export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
echo "NODE_PORT=$NODE_PORT"

curl http://$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' kind-control-plane):$NODE_PORT

kubectl rollout status deployments/kubernetes-bootcamp
kubectl describe pods

Rollback update:

kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10
kubectl get deployments
kubectl get pods
kubectl describe pods
kubectl rollout undo deployments/kubernetes-bootcamp
kubectl get pods
kubectl describe pods

Clean up:

kubectl delete deployments/kubernetes-bootcamp services/kubernetes-bootcamp