[K8S Seri] Triển khai Kubernet từ A- Z (Phần 1)

I.  HƯỚNG DẪN CÀI ĐẶT K8S- KUBERNET TRÊN MÔI TRƯỜNG ON PREMISE

1.      Tổng quan:

Việc lựa chọn mô hình phụ thuộc vào nhu cầu về tài nguyên, tính sẵn sàng cao và mục đích sử dụng (phát triển, thử nghiệm hay sản xuất).

  • Mô hình chuẩn (1 Control Plane, 2 Worker Nodes): Đây là kiến trúc phổ biến cho môi trường sản xuất. Control Plane (master) chuyên trách quản lý cụm, trong khi các Worker Node chịu trách nhiệm chạy các ứng dụng (pods). Mô hình này đảm bảo hiệu suất và sự ổn định, vì tài nguyên của control plane không bị ảnh hưởng bởi các ứng dụng.

Cấu hình chi tiết

Thông tin các máy chủ được sử dụng trong hướng dẫn này:

HostnameHệ điều hànhĐịa chỉ IPRAM (tối thiểu)CPU (tối thiểu)
k8s-node01Ubuntu 22.04192.168.9.213 GB2
k8s-node02Ubuntu 22.04192.168.9.223 GB2
k8s-node03Ubuntu 22.04192.168.9.233 GB2
K8s-rancherUbuntu 22.04192.168.9.243 GB2

2.      Sơ Đồ Chi tiết

Mô hình đa chức năng:

Tận dụng tài nguyên để chạy luôn cả control plane và worker để tối ưu tài nguyên. thường dùng cho các môi trường dev hoặc quy mô nhỏ cần tận dụng tối đa tài nguyên.

3.      Thực hiện: Bước này cấu hình trên cả 3 node.

Lưu ý quan trọng, nếu bạn coppy lệnh, hãy coppy từng lệnh thôi tránh lỗi nhen.

  1. Cấu hình host file trên cả 3 host

    sudo vi /ect/hosts

Nội dung cần thêm vào host

k8s-node01 192.168.9.21

k8s-node02 192.168.9.22

k8s-node03 192.168.9.23

k8s-rancher 192.168.9.24

  • Cập nhật hệ thống

sudo apt update -y && sudo apt upgrade -y

Tắt swap: hệ thống k8s yêu cầu tắt swap, nếu không thì không thể kết nối đến api của cụm

– Để kiểm tra thông tin swap ta dùng lệnh

    cat /etc/fstab

– Và ta chèn # vào để vô hiệu hóa swap.

sudo swapoff -a
sudo sed -i '/swap.img/s/^/#/' /etc/fstab

– Cấu hình module kernel /etc/modules-load.d/containerd.conf với nội dung sau:

Ta đùng lệnh sau để đưa overlay br_netfilte vào file /etc/modules-load.d/containerd.conf

sudo tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF
  • Tải module kernel
sudo modprobe overlay
sudo modprobe br_netfilter

– Cấu hình hệ thống mạng

echo "net.bridge.bridge-nf-call-ip6tables = 1" | sudo tee -a /etc/sysctl.d/kubernetes.conf
echo "net.bridge.bridge-nf-call-iptables = 1" | sudo tee -a /etc/sysctl.d/kubernetes.conf
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.d/kubernetes.conf

– Áp dụng cấu hình sysctl

sudo sysctl --system

-Cài đặt các gói cần thiết và thêm kho Docker

sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

– Cài đặt containerd

sudo apt update -y
sudo apt install -y containerd.io

– Cấu hình containerd

containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml

– Khởi động containerd

sudo systemctl restart containerd
sudo systemctl enable containerd

– Thêm kho lưu trữ Kubernetes

echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

– Cài đặt các gói Kubernetes

sudo apt update -y
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl 
// Sử dụng lệnh này để hold version lại tránh trường hợp update lên bị lỗi

– Khối lệnh reset cụm khi đã khởi tạo cụm

sudo kubeadm reset -f
sudo rm -rf /var/lib/etcd
sudo rm -rf /etc/kubernetes/manifests/*

4.      Mô hình đầu tiên:  1 master 2 worker

– Thực hiện trên server k8s-master-1

sudo kubeadm init
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml

– Thực hiện trên server k8s-master-2 và k8s master-3

sudo kubeadm join 192.168.9.21:6443 --token your_token --discovery-token-ca-cert-hash your_sha

Token và ca sẽ hiện tra trong lúc chạy lên init ở node master.

✅ Ý nghĩa:

Lệnh này xóa taint mặc định khỏi node k8s-master-1 để cho phép node master có thể chạy Pod bình thường (dành cho các môi trường lab hoặc single-node cluster).

  • Dấu - ở cuối là để xóa taint NoSchedule.
  • node-role.kubernetes.io/control-plane:NoSchedule là taint mặc định để ngăn Pod (không thuộc control plane) được schedule lên node master.

Sau khi chạy lệnh, minh có thể kiểm tra lại bằng:

kubectl describe node k8s-master-1 | grep Taint

    II. HƯỚNG DẪN CÀI ĐẶT RANCHER TRÊN MÔI TRƯỜNG ON PRIMSE VÀ QUẢN LÝ K8S

1. Cài đặt Rancher và Nginx Load Balancer

a.       Cài đặt Docker và Docker Compose

§  Cài đặt Docker

sudo apt update
sudo apt install docker.io -y
sudo systemctl start docker
sudo systemctl enable docker
docker --version

b.      Cài đặt Docker Compose

sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version

c.       Gán ổ đĩa data

sudo mkfs.ext4 -m 0 /dev/sdb

mkdir /data

echo “/dev/sdb  /data  ext4  defaults  0  0” | sudo tee -a /etc/fstab

mount -a

sudo df -h

File docker-compose.yml tạo Ran

2.       Cấu hình mạng Macvlan

Tạo một mạng ảo để các container có thể giao tiếp trong cùng lớp mạng vật lý.

docker network create -d macvlan \
--subnet=192.168.9.0/24 \
--ip-range=192.168.9.0/24 \
--gateway=192.168.9.254 \
-o macvlan_mode=bridge \
-o parent=ens160 VLAN88

3.       Tạo file docker-compose.yml

services:
nginx-proxy-manager:
image: ‘jc21/nginx-proxy-manager:latest’
container_name: nginx-proxy-manager
restart: always
ports:
– ’80:80′ # Cổng HTTP chính
– ’81:81′ # Cổng giao diện quản lý Web UI
– ‘443:443’ # Cổng HTTPS chính
environment:
DB_MYSQL_HOST: “192.168.9.26”
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: “npm”
DB_MYSQL_PASSWORD: “npm_password”
DB_MYSQL_NAME: “npm_db_1”
volumes:
– ./data/nginx/data:/data
– ./data/nginx/letsencrypt:/etc/letsencrypt
networks:
VLAN88:
ipv4_address: 192.168.9.25
npm-db-1:
image: ‘mariadb:10.5’
container_name: npm-db-1
restart: always
environment:
MYSQL_ROOT_PASSWORD: ‘npm_rootpass’
MYSQL_DATABASE: ‘npm_db_1’
MYSQL_USER: ‘npm’
MYSQL_PASSWORD: ‘npm_password’
volumes:
– ./data/mysql:/var/lib/mysql
networks:
VLAN88:
ipv4_address: 192.168.9.26
nginx-lb:
image: nginx:stable-alpine
container_name: nginx-lb
restart: always
# Xóa port mapping để tránh xung đột. Nginx Proxy Manager sẽ trỏ tới IP 192.168.9.27
# ports:
# – “80:80”
volumes:
– ./nginx-lb/nginx.conf:/etc/nginx/nginx.conf:ro
– ./nginx-lb/conf.d:/etc/nginx/conf.d:ro
networks:
VLAN88:
ipv4_address: 192.168.9.27
rancher:
image: rancher/rancher:latest
container_name: rancher
restart: always
privileged: true
environment:
CATTLE_BOOTSTRAP_PASSWORD: “Tonytechlab@2025”
volumes:
– /data/rancher/data:/var/lib/rancher
networks:
VLAN88:
ipv4_address: 192.168.9.28
# Xóa port mapping để tránh xung đột. Nginx Proxy Manager sẽ trỏ tới IP 192.168.9.28:443
# ports:
# – “443:443”
networks:
VLAN88:
external: true

Tạo file docker-compose.yml với nội dung sau để triển khai Rancher, Nginx Proxy Manager và cơ sở dữ liệu.

Lưu ý: Chạy docker-compose up -d. Có thể sẽ phát sinh lỗi ban đầu, hãy tạm bỏ qua và tiếp tục bước tiếp theo.

  III. Cấu hình Rancher và thêm Node K8s

  • Truy cập giao diện Rancher.
  • Tạo Project, Namespace, Deployment, Service (ClusterIP, NodePort).
  • Thêm cụm K8s đã tạo vào Rancher để quản lý.
  • (Chi tiết xem trong video hướng dẫn).

Join K8s thành công.


Cấu hình Ingress và Load Balancer

1.       Cài đặt Helm và Ingress-Nginx

Thực hiện trên Master node

# Tải và cài đặt Helm
wget https://get.helm.sh/helm-v3.14.4-linux-amd64.tar.gz
tar -zxvf helm-v3.14.4-linux-amd64.tar.gz
sudo mv linux-amd64/helm /usr/local/bin/helm
# Thêm kho lưu trữ của Ingress NGINX
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
# Tải chart về để chỉnh sửa
helm pull ingress-nginx/ingress-nginx
# Giải nén chart
tar -zxvf ingress-nginx-*.tgz
# Chỉnh sửa file values.yaml
Mở file: ingress-nginx/values.yaml
# Tìm và sửa:
controller.service.type: LoadBalancer -> type: NodePort
controller.service.nodePorts.http: 30080
controller.service.nodePorts.https: 30443
# Tạo namespace và cài đặt Ingress Controller bằng Helm
kubectl create namespace ingress-nginx
helm install ingress-nginx ingress-nginx/ \

-n ingress-nginx \

-f ingress-nginx/values.yaml

2.       Cấu hình Nginx Load Balancer (nginx-lb)

Cài đặt trên rancher server

a. Cập nhật nginx.conf

Tạo file tại ./nginx-lb/nginx.conf với nội dung:

worker_processes auto;
events { worker_connections 4096; }
http {
  include       mime.types;
  default_type  application/octet-stream;
  sendfile      on;
access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;
  include /etc/nginx/conf.d/*.conf;
}

b. Cập nhật ingress-lb.conf

Tạo file tại ./nginx-lb/conf.d/ingress-lb.conf để điều phối traffic đến các worker node.

upstream my_servers {
  least_conn;
  server 172.200.10.11:30080 max_fails=3 fail_timeout=10s;
  server 172.200.10.12:30080 max_fails=3 fail_timeout=10s;
  keepalive 32;
}
map $http_upgrade $connection_upgrade {
  default upgrade;
  ""      close;
}
server {
  listen 80;
  client_max_body_size 50m;
  location / {
    proxy_pass http://my_servers;
    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    # Headers
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    # Timeouts
    proxy_connect_timeout 5s;
    proxy_send_timeout    60s;
    proxy_read_timeout    60s;
    # Failover
    proxy_next_upstream error timeout http_502 http_503 http_504;
    proxy_next_upstream_tries 2;
    proxy_buffering on;
  }
}

Sau khi cấu hình, khởi động lại container nginx-lb

docker restart nginx-lb

 IV.            Triển khai dự án Fullstack

  1. Bạn với vai trò là Devops, bạn được công ty giao host website tự án full stack.

Link tải: – Download dự án về k8s – Google Drive

–  Edit config file thay thế tonytechlab.com bằng domain của bạn bằng notepad ++

–  Trong notepad ++ ta chọn File àOpen Folder as Workspace sau đó mở tới  folder dự án và bấm Control + F sau đó chọn File in file

–  Rồi bạn tiến hành gõ tonyteclab vào ô tìm kiếm và thay thế bằng domain của bạn

Trong Fullstack-Ecommerce-Web\01-starter-files_db-scripts/my.cnf  sửa.

bind-adress= 127.0.0.1 sang 0.0.0.0

Trong  \Fullstack-Ecommerce-Web\02-backend_spring-boot-rest-api\src\main\resources sửa

File à application.properties à đường dẫn Maria db

  • Coppy resource vào Racher server à build font end, back end và đưa lên docker hub.
  • Đóng gọi Font end & backup và chép lên docker hub
    • Sử dụng lệnh docker build và docker push.
    • Lệnh gồm
-cd 02-backend…..
-sudo docker build -t hoatrancntt/shop-backend:v1 .
-cd 03-fontend….
-sudo docker build -t hoatrancntt/shop-fontend:v1 .

Kiểm tra images đã build

Sudo docker images




Login docker hub & push lên docker hub

docker login -u hoatrancntt@gmail.com // sau đó gõ password
docker push hoatrancntt/shop-backend:v1
docker push hoatrancntt/shop-fontend:v1

Kiểm tra trên docker hub

  • Kết nối vào Mariadb
  • Sao chép dữ liệu vào Mariadb
mysql -u root -p // sau đó gõ password root của mysql          
source /var/lib/mysql/01-starter-files_db-scripts/01-create-user.sql
source /var/lib/mysql/01-starter-files_db-scripts/02-create-products.sql
source /var/lib/mysql/01-starter-files_db-scripts/03-refresh-database-with-100-products.sql
source /var/lib/mysql/01-starter-files_db-scripts/04-countries-and-states.sql
source /var/lib/mysql/01-starter-files_db-scripts/05-create-order-tables.sql
  • Chỉnh sửa và cập nhật file Fontend.yaml và Backend.yaml

Fontend.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: ecommerce-frontend-selector
  name: ecommerce-frontend-deployment
  namespace: hoatrancntt-ecommerce
spec:
  progressDeadlineSeconds: 600
  replicas: 2
  revisionHistoryLimit: 11
  selector:
    matchLabels:
      app: ecommerce-frontend-selector
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: ecommerce-frontend-selector
      namespace: hoatrancntt-ecommerce
    spec:
      containers:
        - image: hoatrancntt/shop-frontend:v1
          imagePullPolicy: Always
          name: ecommerce-frontend
          ports:
            - containerPort: 80
              name: tcp
              protocol: TCP
 
---
apiVersion: v1
kind: Service
metadata:
  name: ecommerce-frontend-clusterip
  namespace: hoatrancntt-ecommerce
  internalTrafficPolicy: Cluster
  ipFamilies:
    - IPv4
  ipFamilyPolicy: SingleStack
  ports:
    - name: tcp
      port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: ecommerce-frontend-selector
  sessionAffinity: None
  type: ClusterIP
 
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ecommerce-frontend-ingress
  namespace: hoatrancntt-ecommerce
spec:
  ingressClassName: nginx
  rules:
    - host: ecommerce.shop.htg.id.vn
      http:
        paths:
          - backend:
              service:
                name: ecommerce-frontend-clusterip
                port:
                  number: 80
            path: /
            pathType: Prefix

   Backend.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: ecommerce-backend-selector
  name: ecommerce-backend-deployment
  namespace: hoatrancntt-ecommerce
spec:
  progressDeadlineSeconds: 600
  replicas: 2
  revisionHistoryLimit: 11
  selector:
    matchLabels:
      app: ecommerce-backend-selector
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: ecommerce-backend-selector
      namespace: hoatrancntt-ecommerce
    spec:
      containers:
        - image: hoatrancntt/shope-backend:v1
          imagePullPolicy: Always
          name: ecommerce-backend
          ports:
            - containerPort: 8080
              name: tcp
              protocol: TCP
 
---
apiVersion: v1
kind: Service
metadata:
  name: ecommerce-backend-clusterip
  namespace: hoatrancntt-ecommerce
spec:
  internalTrafficPolicy: Cluster
  ipFamilies:
    - IPv4
  ipFamilyPolicy: SingleStack
  ports:
    - name: tcp
      port: 8080
      protocol: TCP
      targetPort: 8080
  selector:
    app: ecommerce-backend-selector
  sessionAffinity: None
  type: ClusterIP
 
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ecommerce-backend-ingress
  namespace: hoatrancntt-ecommerce
spec:
  ingressClassName: nginx
  rules:
    - host: api-ecommerce.shop.htg.id.vn
      http:
        paths:
          - backend:
              service:
                name: ecommerce-backend-clusterip
                port:
                  number: 8080
            path: /
            pathType: Prefix
  • Vào rancher tạo Project và Name Space

Upload file Backend và Fontend

– Sau đó ta tiến hành vào hostfile trong máy client truy cập tới lần lượt add

192.168.9.27 ecommerce.shop.htg.id.vn
192.168.9.27 api-ecommerce.shop.htg.id.vn

            Vào C:\Windows\System32\drivers\etc\hosts sửa file
Login vào web kiểm tra.