Xây dựng hệ thống Microservices đơn giản bằng Kubernetes (K8S)
Trong bài viết này, tôi sẽ trình bày cách để xây dựng một hệ thống microservices đơn giản, sử dụng Kubernetes (K8S).
Nội Dung:
- Tổng quan về hệ thống.
- Dùng Docker để build các service
- Deploy sử dụng Kubernetes.
- Tổng kết.
- Tài liêu & code tham khảo
Tổng quan về hệ thống.
Đây là một hệ thống đơn giản cho phép thêm, sửa, xóa người dùng. Hệ thống bao gồm hai service chính: back-end và user-service được xây dựng dựa trên framework NestJS. Rest API sẽ được sử dụng để kết nối giữa các services này.
Dùng Docker để build các service
1. Khởi Tạo User Service.
Tôi dùng NestJS trong bài viết này để build các services.
$ npm i -g @nestjs/cli
$ nest new user-service
Chúng ta bắt đầu xây dựng một bộ API để có thể: thêm, sửa, xóa và đọc thông tin của user. Dưới đây là cách bạn có thể khai báo biến để lưu trữ dữ liệu người dùng trong tệp app.service.ts. Vì để đơn giản nhất có thể, tôi sẽ không sử dụng cơ sở dữ liệu, toàn bộ dữ liệu sẽ được lưu trữ trong một biến trong bộ nhớ:
Trong app.service.ts files: Khai báo 1 biến users để lưu toàn bộ data.
import { Injectable } from "@nestjs/common";
import { UserDto } from "./dto/create-user.dto";
import { ConfigService } from "@nestjs/config";
@Injectable()
export class AppService {
users = [];
constructor(private readonly configService: ConfigService) {}
async createUser(createUserDto: UserDto) {
this.users.push(createUserDto);
return createUserDto;
}
async getUser() {
return this.users;
}
async getUserById(id: string) {
return this.users.find((item) => item.id === id) || null;
}
async deleteByUserId(id: string) {
const index = this.users.findIndex((item) => item.id === id);
if (index < 0) {
return {
count: 0,
};
}
this.users.splice(index, 1);
return {
count: 1,
};
}
}
2. Khởi Tạo Back-End Service.
Tiếp theo, chúng ta build Back-End, đây là nơi nhận các yêu cầu từ Front-End và sau đó gọi đến các dịch vụ khác để lấy thông tin nếu cần để xử lý. Các bước thực hiện tương tự như User Service ở trên.
$ npm i -g @nestjs/cli
$ nest new back-end
Chúng ta build một bộ endpoints (CRUD) và gọi sang user-service để thao tác với dữ liêu.
import { Injectable } from "@nestjs/common";
import { UserDto } from "./dto/create-user.dto";
import { Axios } from "axios";
import axios from "axios";
import { ConfigService } from "@nestjs/config";
@Injectable()
export class AppService {
private axiosInstance: Axios;
constructor(private readonly configService: ConfigService) {
this.axiosInstance = axios.create({
baseURL: this.configService.get("ENDPOINT_USER_SERVICE"),
});
}
async createUser(createUserDto: UserDto) {
const result = await this.axiosInstance.post("user", createUserDto);
return result;
}
async getUser() {
const result = await this.axiosInstance.get("user");
return result;
}
async getUserById(id: string) {
const result = await this.axiosInstance.get(`user/:${id}`);
return result;
}
async deleteUserById(id: string) {
const result = await this.axiosInstance.get(`user/:${id}`);
return result;
}
}
3. Build Docker Images And Push To DockerHub.
Để triển khai với Kubernetes, chúng ta cần build cả back-end service và user-service thành các Docker image và đẩy chúng lên DockerHub. Đăng ký tài khoản DockerHub tại đây. Đăng nhập vào Docker CLI và nhập tên người dùng cùng mật khẩu.
$ docker login
Để build images, lần lượt cd vào thư mục back-end và user-service, và sau đó gõ các lệnh sau:
## Go back-end directory
$ docker build -t back-end:latest .
## Go to user-service
$ docker build -t user-service:latest .
Tag docker image.
## Go to back-end
$ docker tag back-end:latest <dockerhub-username>/back-end:latest
## Go to user-service
$ docker tag user-service:latest <dockerhub-username>/user-service:latest
Push it to docker hub.
## Go to back-end
$ docker push <dockerhub-username>/back-end:latest
## Go to user-service
$ docker push <dockerhub-username>/user-service:latest
Deploy Using Kubernetes
Để tạo một cụm K8S (Kubernetes) trên máy tính cục bộ, Minikube là một lựa chọn tốt.
1. Install MiniKube
Theo dõi tại đây here.
2. Store Environment Variables
Để lưu trữ environment variables tương tự như khi chạy ứng dụng trên máy tính (sử dụng .env file), Chúng ta dùng config map API object của K8S. Chi tiết tại đây
Tạo một folder tên là K8S, và sau đó tạo file back-end.config-map.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: back-end-config-map
data:
ENDPOINT_USER_SERVICE: http://user-service:3001
Dùng kubectl command để apply file này..
$ kubectl apply -f ./k8s/back-end.config-map.yml
3. Deploy Back End Service
Tạo deployment và service cho back-end service
back-end.deployment.yml file:
apiVersion: apps/v1
kind: Deployment
metadata:
name: back-end
labels:
app: back-end
spec:
replicas: 2
selector:
matchLabels:
app: back-end
template:
metadata:
labels:
app: back-end
spec:
containers:
- name: back-end
image: <dockerhub-username>/back-end:latest # Tên image Docker của bạn
ports:
- containerPort: 3000 # Cổng mà container sẽ nghe
envFrom:
- configMapRef:
name: back-end-config-map
back-end.service.yml file:
apiVersion: v1
kind: Service
metadata:
name: back-end-service
spec:
selector:
app: back-end # Matches the labels of the backend pods
ports:
- protocol: TCP
port: 3000 # Service port
targetPort: 3000 # Pod containerPort
type: ClusterIP
Apply deployment và service
$ kubectl apply -f ./k8s/back-end.deployment.yml
$ kubectl apply -f ./k8s/back-end.service.yml
4. Deploy User Service
Tạo deployment và service cho User Service
user-service.deployment.yml file:
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
labels:
app: user-service
spec:
replicas: 2
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: <dockerhub-username>/user-service:latest # Tên image Docker của bạn
ports:
- containerPort: 3001 # Cổng mà container sẽ nghe
user-service.service.yml file:
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service # Matches the labels of the backend pods
ports:
- protocol: TCP
port: 3001 # Service port
targetPort: 3001 # Pod containerPort
type: ClusterIP
Apply deployment and service
$ kubectl apply -f ./k8s/user-service.deployment.yml
$ kubectl apply -f ./k8s/user-service.service.yml
5. Forward ports
Để truy cập back-end (trong cụm Kubernetes), chúng ta cần chuyển tiếp cổng từ cụm K8S ra bên ngoài bằng cách sử dụng lệnh sau:
$ kubectl port-forward deployment/back-end 3000:3000
Sau khi chạy lệnh port-foward, thì back-end có thể được truy cập thông qua http://localhost:3000. Mở trình duyệt và truy cập http://localhost:3000/user để xem kết quả.
Trên cloud, chúng ta có thể sử dụng Load Balancer, NodePort, v.v.
6. Test Hệ Thống.
Tạo 1 user
curl --location 'http://localhost:3000/user' \
--header 'Content-Type: application/json' \
--data '{
"name": "Nguyen Van A"
}'
Danh sách users
curl --location 'http://localhost:3000/user'
Tổng Kết
Chúc mừng bạn đã hoàn thành hệ thống microservices đơn giản bằng cách sử dụng Kubernetes. Chúng ta đã bắt đầu viết mã cho back-end và user service bằng NestJS, dockerize chúng thành các Docker image và đẩy lên DockerHub. Ngoài ra, chúng ta cũng đã viết các file yaml cho K8S và các lệnh để triển khai hệ thống Kubernetes. Cảm ơn bạn đã đọc bài viết này. Nếu bạn có bất kỳ phản hồi nào, vui lòng comment nhé.
Tài Liệu & Code Tham Khảo
Code Example: https://github.com/ThanhPhanV/kubernetes-example
All rights reserved