【Kubernetes】集群环境下的应用部署案例

最近将一个应用部署到 K8s 集群,并进行了详细记录,希望能对大家有所帮助该应用主要功能是简化加载地图的 WMTS 和 WMS,其架构采用 MySQL 作为后端数据库,后端使用 NestJS 来连接数据库,而前端则基于 Vue 实现用户界面展示。

GitHub 地址:https://gitee.com/geogy/wmts_wms_tools

  • 数据库:Mysql 8.0
  • 后端:Nestjs 10.0.0
  • 前端:Vue 3.5.13

1、制作 Docker 镜像

1.1、Mysql 数据库

bash 复制代码
###  Dockerfile ###
# 使用官方 MySQL 镜像
FROM mysql:8.0

# 设置环境变量
ENV MYSQL_DATABASE=mytool

# 将 SQL 脚本复制到 Docker 镜像中进行初始化
COPY *.sql /docker-entrypoint-initdb.d/

# 暴露 MySQL 默认端口
EXPOSE 3306

### 构建镜像 ###
docker build . -t mytool-db:v1

1.2、Nest 后端

bash 复制代码
### Dockerfile ###
# 使用官方的 Node.js 镜像作为基础镜像
FROM node:20.17.0-slim
 
# 设置工作目录
WORKDIR /data

# 复制项目打包文件到工作目录
COPY package*.json ./
COPY dist ./dist

# 安装依赖
RUN npm install

# 暴露端口
EXPOSE 3000

# 定义容器启动时执行命令运行项目
CMD ["npm","run","start:prod"]

### 构建镜像 ###
docker build . -t mytool-server:v1

1.3、vue 前端

bash 复制代码
###  Dockerfile ###
# Tomcat 基础镜像
FROM tomcat:10.1-jdk17

# 设置工作目录
WORKDIR /usr/local/tomcat/bin

# 删除默认的 webapps 内容
RUN rm -rf /usr/local/tomcat/webapps/*

# 复制项目文件到工作目录
COPY ./mytool /usr/local/tomcat/webapps/mytool
COPY ./ROOT  /usr/local/tomcat/webapps/ROOT

# 暴露端口(默认)
EXPOSE 8080

# 启动 Tomcat
CMD ["catalina.sh", "run"]

### 构建镜像 ###
docker build . -t mytool-ui:v1

2、编写 YAML

2.1、创建命名空间

bash 复制代码
# 命令:kubectl create ns mytool
apiVersion: v1
kind: Namespace
metadata:
  labels:
    kubernetes.io/metadata.name: mytool
  name: mytool

2.2、Secret / ConfigMap 配置

bash 复制代码
# 加密内容(如账号密码)使用 Secret 存储
# 非加密配置用 ConfigMap 存储

# 存储数据库 root 用户密码(base64 加密)
kind: Secret
apiVersion: v1
metadata:
  name: mytool-db-secret
  namespace: mytool
  labels:
    app: mytool-db
data:
  mysql.password: MTIzNDU2
  mysql.root.password: MTIzNDU2
  mysql.username: cm9vdA==
type: Opaque

# 后端 mytool-server 配置(配置前端跨域连接)
apiVersion: v1
kind: ConfigMap
metadata:
  name: mytool-server-conf
  namespace: mytool
data:
  .env: |
    SERVER_TITLE = WMTS/WMS-Tools Service
    # 运行端口
    SERVER_PORT = 3000
    # JWT配置
    JWT_SECRET = zheshimiyao
    JWT_EXP = 24h
    # 跨域白名单
    THITE_LIST = ['http://localhost:6060', 'http://127.0.0.1:6060'] 

# 前端 mytool-ui 配置(用于连接后端)
apiVersion: v1
kind: ConfigMap
metadata:
  name: mytool-ui-conf
  namespace: mytool
data:
  config.js: |
    window.serviceConfig = {
     dev: {
      url: 'http://localhost:3000/api'
     },
     test: {
      url: 'http://localhost:3000/api'
     },
     prod: {
      url: 'http://localhost:3000/api'
     }
    }

2.3、pv / pvc 挂载

bash 复制代码
# 实现数据库持久化
# 此处使用 hostPath 挂载(可结合 nfs 使用)
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-mytool
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /home/mytool
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-mytool-db
  namespace: mytool
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi
  volumeName: pv-mytool

2.4、为 Pod 绑定 Service

bash 复制代码
# 数据库 mytool-db -> Service
kind: Service
apiVersion: v1
metadata:
  name: mytool-db
  namespace: mytool
  labels:
    app: mytool-db
spec:
  ports:
  - protocol: TCP
    port: 3306
    targetPort: 3306
  selector:
    app: mytool-db
  type: ClusterIP

# 后端 mytool-server -> service
# NodePort 端口可结合实际修改(需同步修改 ConfigMap 中的地址)
kind: Service
apiVersion: v1
metadata:
  name: mytool-server
  namespace: mytool
  labels:
    app: mytool-server
spec:
  ports:
  - protocol: TCP
    port: 3000
    targetPort: 3000
    nodePort: 31111
  selector:
    app: mytool-server
  type: NodePort

# 前端 mytool-ui -> service
# NodePort 端口可结合实际修改(需同步修改 ConfigMap 中的地址)
kind: Service
apiVersion: v1
metadata:
  name: mytool-ui
  namespace: mytool
  labels:
    app: mytool-ui
spec:
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080
    nodePort: 32222
  selector:
    app: mytool-ui
  type: NodePort

2.5、Deployment 部署应用

2.5.1、数据库 mytool-db

bash 复制代码
# 数据库 mytool-db
# 使用 secret 挂载 env 环境变量(root 用户密码)
# pv / pvc 持久化存储数据库数据
kind: Deployment
apiVersion: apps/v1
metadata:
  name: mytool-db
  namespace: mytool
  labels:
    app: mytool-db
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mytool-db
  template:
    metadata:
      labels:
        app: mytool-db
    spec:
      volumes:
        - name: mytool-db-volume
          persistentVolumeClaim:
            claimName: pvc-mytool-db
        - name: timezone
          hostPath:
            path: /etc/localtime
            type: ''
      containers:
        - name: mytool-db
          image: mytool-db:v1
          ports:
            - containerPort: 3306
              protocol: TCP
          env:
            - name: MYSQL_DATABASE
              value: mytool
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mytool-db-secret
                  key: mysql.root.password
          resources:
            limits:
              cpu: '1'
              memory: 1Gi
            requests:
              cpu: 200m
              memory: 200Mi
          volumeMounts:
            - name: timezone
              mountPath: /etc/localtime
            - name: timezone
              mountPath: /etc/timezone
            - name: mytool-db-volume
              mountPath: /var/lib/mysql
              subPath: mytool-db
          imagePullPolicy: IfNotPresent
          livenessProbe:
            exec:
              command:
                - /bin/sh
                - '-c'
                - mysql -u root -p$MYSQL_ROOT_PASSWORD -e 'SELECT 1'
            initialDelaySeconds: 15
            timeoutSeconds: 20
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 5
          readinessProbe:
            exec:
              command:
                - /bin/sh
                - '-c'
                - mysql -u root -p$MYSQL_ROOT_PASSWORD -e 'SELECT 1'
            initialDelaySeconds: 15
            timeoutSeconds: 20
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 5
      restartPolicy: Always    

2.5.2、后端 mytool-server

bash 复制代码
# 后端 mytool-server
# initContainers 等待数据库可用后再启动后端
# configMap 挂载后端连接信息配置
kind: Deployment
apiVersion: apps/v1
metadata:
  name: mytool-server
  namespace: mytool
  labels:
    app: mytool-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mytool-server
  template:
    metadata:
      labels:
        app: mytool-server
    spec:
      volumes:
        - name: timezone
          hostPath:
            path: /etc/localtime
            type: ''
        - name: mytool-server-env
          configMap:
            name: mytool-server-conf
      initContainers:
        - name: wait-for-mysql
          image: mytool-db:v1
          command: ['/bin/sh', '-c', 'until mysql -h$MYTOOL_DB_SERVICE_HOST -u root -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 5; echo "等待 MySQL 启动..."; done; echo "MySQL 已启动...";']
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mytool-db-secret
                  key: mysql.root.password
          resources: {}
          imagePullPolicy: IfNotPresent
      containers:
        - name: mytool-server
          image: mytool-server:v1
          ports:
            - containerPort: 3000
              protocol: TCP
          command: ['/bin/sh', '-c', 'cp /tmp/env/.env /data/dist/env/.env; npm run start:prod']
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mytool-db-secret
                  key: mysql.root.password
          resources:
            limits:
              cpu: '1'
              memory: 1Gi
            requests:
              cpu: 200m
              memory: 200Mi
          livenessProbe:
            tcpSocket:
              port: 3000
            initialDelaySeconds: 50
            timeoutSeconds: 20
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 5
          readinessProbe:
            tcpSocket:
              port: 3000
            initialDelaySeconds: 50
            timeoutSeconds: 20
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 5
          volumeMounts:
            - name: timezone
              mountPath: /etc/localtime
            - name: timezone
              mountPath: /etc/timezone
            - name: mytool-server-env
              mountPath: /tmp/env
      restartPolicy: Always

2.5.3、前端 mytool-ui

bash 复制代码
# 前端 mytool-ui
# configMap 挂载后端连接配置
# startupProbe 探针检测后端服务是否可用
kind: Deployment
apiVersion: apps/v1
metadata:
  name: mytool-ui
  namespace: mytool
  labels:
    app: mytool-ui
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mytool-ui
  template:
    metadata:
      labels:
        app: mytool-ui
    spec:
      volumes:
        - name: timezone
          hostPath:
            path: /etc/localtime
            type: ''
        - name: mytool-ui-env
          configMap:
            name: mytool-ui-conf
      containers:
        - name: mytool-ui
          image: mytool-ui:v1
          command: ['/bin/sh', '-c', 'cp /tmp/config/config.js /usr/local/tomcat/webapps/mytool/config/config.js; catalina.sh run;']
          resources:
            limits:
              cpu: '1'
              memory: 1Gi
            requests:
              cpu: 200m
              memory: 200Mi
          ports:
            - containerPort: 8080
              protocol: TCP
          startupProbe:
            exec:
              command:
              - sh
              - -c
              - "curl -sSf $MYTOOL_SERVER_SERVICE_HOST:3000/api/code >/dev/null || exit 1"
            initialDelaySeconds: 50
            timeoutSeconds: 20
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 5
          livenessProbe:
            httpGet:
              path: /
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 50
            timeoutSeconds: 20
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 5
          readinessProbe:
            httpGet:
              path: /
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 50
            timeoutSeconds: 20
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 5
          volumeMounts:
            - name: timezone
              mountPath: /etc/localtime
            - name: timezone
              mountPath: /etc/timezone
            - name: mytool-ui-env
              mountPath: /tmp/config
      restartPolicy: Always
相关推荐
荣光波比2 小时前
K8S(一)—— 云原生与Kubernetes(K8S)从入门到实践:基础概念与操作全解析
云原生·容器·kubernetes
hello_2504 小时前
k8s基础监控promql
云原生·容器·kubernetes
静谧之心6 小时前
在 K8s 上可靠运行 PD 分离推理:RBG 的设计与实现
云原生·容器·golang·kubernetes·开源·pd分离
1024find11 小时前
Spark on k8s部署
大数据·运维·容器·spark·kubernetes
能不能别报错1 天前
K8s学习笔记(十六) 探针(Probe)
笔记·学习·kubernetes
能不能别报错1 天前
K8s学习笔记(十四) DaemonSet
笔记·学习·kubernetes
火星MARK1 天前
k8s面试题
容器·面试·kubernetes
赵渝强老师1 天前
【赵渝强老师】Docker容器的资源管理机制
linux·docker·容器·kubernetes
能不能别报错1 天前
K8s学习笔记(十五) pause容器与init容器
笔记·学习·kubernetes
稚辉君.MCA_P8_Java1 天前
kafka解决了什么问题?mmap 和sendfile
java·spring boot·分布式·kafka·kubernetes