+6

Kubernetes Example - Xây dựng hệ thống microservices đơn giản.

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).

Quick Start

Để run hệ thống, truy cập vào repository Code Example và dùng các lệnh sau:

$ kubectl apply -f ./k8s/back-end.config-map.yml
$ kubectl apply -f ./k8s/back-end.deployment.yml
$ kubectl apply -f ./k8s/user-service.deployment.yml
$ kubectl apply -f ./k8s/back-end.service.yml
$ kubectl apply -f ./k8s/user-service.service.yml
$ kubectl port-forward deployment/back-end 3000:3000

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 và 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. Để đơn giản nhất có thể, tôi sẽ không sử dụng cơ sở dữ liệu và 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?.data;
  }

  async getUser() {
    const result = await this.axiosInstance.get("user");
    return result?.data;
  }

  async getUserById(id: string) {
    const result = await this.axiosInstance.get(`user/:${id}`);
    return result?.data;
  }

  async deleteUserById(id: string) {
    const result = await this.axiosInstance.get(`user/:${id}`);
    return result?.data;
  }
}

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 có bất kỳ phản hồi nào, xin vui lòng comment.

Tài Liệu & Code Tham Khảo

Code Example: https://github.com/ThanhPhanV/kubernetes-example


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí