阶段四:微服务项目运维实践基础

项目部署到k8s中的流程

1. 集群服务对外提供访问,需要通过Ingress代理发布域名。 2. 搭建私有镜像仓库,用于存储自己构建的项目镜像。 3. 集群中容器数据持久化,通过PV、PVC、StorageClass实现后端数据存储。 4. 部署项目所需的数据库,并配置好项目连接数据库的信息。 5. 项目运行在什么环境中,需要将运行环境打包到镜像中。 6. 在k8s中部署项目,并通过Ingress发布项目

需要掌握的技能

微服务与容器化架构基础

Kubernetes 核心概念与组件

微服务应用部署与运行机制

系统监控与日志管理

CI/CD 与自动化运维

高可用与故障处理

微服务项目部署

传统项目简介

image

传统项目是一个进程包含了所有的业务功能,功能越多项目就复杂。随着代码的增多,构建和部署的时间也会增加,每次功能的变更或Bug的修复,甚至添加一个简单的功能,都需要重新打包整个项目代码。某个功能出现问题可能影响整个应用

微服务项目概述

image

一个微服务只关注一个特定的业务功能,所以它业务清晰、代码量较少,易于维护,启动更快。 传统项目只要有修改,就得重新部署整个应用,微服务解决了这样的问题。一般来说,对某个微服务进行修改,只需要重新部署这个服务即可。

War包与Jar包的区别:

微服务架构图

https://www.processon.com/view/5ec290195653bb6f2a18504e

image

微服务项目介绍

文档地址:http://doc.ruoyi.vip/ruoyi-cloud/

代码下载:https://gitee.com/y_project/RuoYi-Cloud

微服务组件介绍

部署Nacos注册中心

image
image

YAML 保存位置: ~/k8s-manifests/ruoyi/mysql-svc.yaml

先在 Kubernetes 管理节点执行:

mkdir -p ~/k8s-manifests/ruoyi
cd ~/k8s-manifests/ruoyi
vi mysql-svc.yaml

把下方 YAML 全部复制进去;红色字段按当前环境修改;按 Esc 后输入 :wq 保存退出。

apiVersion: v1
kind: Service
metadata:
  name: mysql-svc
  namespace: ruoyi
spec:
  clusterIP: None
  selector:
    app: mysql
  ports:
    - port: 3306
      targetPort: 3306
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  namespace: ruoyi
spec:
  serviceName: "mysql-svc"
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/mysql:8.4.6
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123456"
            - name: MYSQL_DATABASE
              value: "ry-config"
            - name: TZ
              value: "Asia/Shanghai"
          ports:
            - containerPort: 3306
          volumeMounts:
            - name: data
              mountPath: /var/lib/mysql
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        storageClassName: "alicloud-disk-topology-alltype"
        resources:
          requests:
            storage: 20Gi

配置详解:

需要改的项为什么改
namespace: ruoyi与实际命名空间一致;使用默认命名空间时可不写。
port: 3306对外暴露的 Service 端口;调用方按此端口访问。
targetPort: 3306必须与容器实际监听端口一致。
replicas: 1按可用性和资源容量设置副本数。
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/mysql:8.4.6替换为实际可拉取的镜像地址和版本。
MYSQL_ROOT_PASSWORD: 123456按当前环境的实际值确认。

注意事项:

#克隆项目代码并进入到sql目录
git clone https://gitee.com/y_project/RuoYi-Cloud.git
git checkout v3.6.7
cd /root/RuoYi-Cloud/sql
#数据库复制到容器内部
kubectl cp ry_config_20250902.sql ruoyi/mysql-0:/root
kubectl cp ry_20250523.sql ruoyi/mysql-0:/root

#登录mysql-0数据库
kubectl exec -it mysql-0 -n ruoyi -- /bin/bash
mysql -u root -p
mysql> use ry-config
mysql> source /root/ry_config_20250902.sql;
mysql> create database ruoyi;
mysql> use ruoyi
mysql> source /root/ry_20250523.sql;

注意事项:

YAML 保存位置: ~/k8s-manifests/ruoyi/nacos-cm.yaml

先在 Kubernetes 管理节点执行:

mkdir -p ~/k8s-manifests/ruoyi
cd ~/k8s-manifests/ruoyi
vi nacos-cm.yaml

把下方 YAML 全部复制进去;红色字段按当前环境修改;按 Esc 后输入 :wq 保存退出。

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: ruoyi
  name: nacos-cm
data:
  mysql.host: "mysql-svc"
  mysql.db.name: "ry-config"
  mysql.port: "3306"
  mysql.user: "root"
  mysql.password: "123456"
---
#headless service
apiVersion: v1
kind: Service
metadata:
  name: nacos-svc
  namespace: ruoyi
spec:
  clusterIP: None
  selector:
    app: nacos
  ports:
  #8848是Nacos服务的默认端口,用于处理客户端的请求
  - name: server
    port: 8848
    targetPort: 8848
  #9848端口在Nacos集群模式下用于节点间的心跳检测
  - name: client-rpc
    port: 9848
    targetPort: 9848
  #9849端口主要用于Nacos集群模式下内部节点间进行数据复制等操作
  - name: raft-rpc
    port: 9849
    targetPort: 9849
  #兼容1.4.x版本的选举端口
  - name: old-raft-rpc
    port: 7848
    targetPort: 7848
---
#Nacos作为服务注册与配置中心,必须要有一个稳定的地址,通过StatefulSet进行部署最佳
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nacos
  namespace: ruoyi
spec:
  serviceName: "nacos-svc"
  replicas: 3              #Nacos集群数量
  selector:
    matchLabels:
      app: nacos
  template:
    metadata:
      labels:
        app: nacos
    spec:
      affinity:
          podAntiAffinity:
            # 设置为“尽量不要在同一节点上”,而不是强制分开
            preferredDuringSchedulingIgnoredDuringExecution:
              - weight: 100  # 优先级权重(1-100,越大优先级越高)
                podAffinityTerm:
                  labelSelector:
                    matchExpressions:
                      - key: app
                        operator: In
                        values: ["nacos"]
                  topologyKey: "kubernetes.io/hostname"
      initContainers:
      - name: peer-finder-plugin-install
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nacos/nacos-peer-finder-plugin:1.1
        imagePullPolicy: Always
        volumeMounts:
          - name: data
            mountPath: /home/nacos/plugins/peer-finder
            subPath: peer-finder
      containers:
      - name: nacos
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nacos/nacos-server:v2.1.1
        resources:
          requests:
            memory: "100Mi"
            cpu: "500m"
        ports:
        - name: client-port
          containerPort: 8848
        - name: client-rpc
          containerPort: 9848
        - name: raft-rpc
          containerPort: 9849
        - name: old-raft-rpc
          containerPort: 7848
        env:
        #设置Nacos的运行模式,"cluster"表示Nacos在集群模式下运行
        - name: MODE
          value: "cluster"
        #表示Nacos的版本号
        - name: NACOS_VERSION
          value: 2.1.1
        #表示Nacos集群的副本数量
        - name: NACOS_REPLICAS
          value: "3"
        #表示Nacos的service名称
        - name: SERVICE_NAME 
          value: "nacos-svc"
        #DNS前缀域名
        - name: DOMAIN_NAME 
          value: "cluster.local"
        #表示Nacos服务的端口号
        - name: NACOS_SERVER_PORT   
          value: "8848"
        #表示Nacos应用的端口号
        - name: NACOS_APPLICATION_PORT
          value: "8848"
        #表示Nacos集群中的节点通信使用主机名而非IP地址
        - name: PREFER_HOST_MODE
          value: "hostname"
        #POD_NAMESPACE环境变量用于设置为当前Pod所在的名称空间
        - name: POD_NAMESPACE      
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
        #使用MySQL作为数据源
        - name: SPRING_DATASOURCE_PLATFORM
          value: "mysql"
        #JDBC连接数据库后面的参数
        - name: MYSQL_SERVICE_DB_PARAM
          value: characterEncoding=utf8&connectTimeout=10000&socketTimeout=30000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
        #MySQL主机地址从configMap的key中获取
        - name: MYSQL_SERVICE_HOST
          valueFrom:
            configMapKeyRef:
              name: nacos-cm
              key: mysql.host
        #MySQL的库名称从configMap的key中获取
        - name: MYSQL_SERVICE_DB_NAME
          valueFrom:
            configMapKeyRef:
              name: nacos-cm
              key: mysql.db.name
        #MySQL的端口从configMap的key中获取
        - name: MYSQL_SERVICE_PORT
          valueFrom:
            configMapKeyRef:
              name: nacos-cm
              key: mysql.port
        #MySQL的用户名从configMap的key中获取
        - name: MYSQL_SERVICE_USER
          valueFrom:
            configMapKeyRef:
              name: nacos-cm
              key: mysql.user
        #MySQL的用户密码从configMap的key中获取
        - name: MYSQL_SERVICE_PASSWORD
          valueFrom:
            configMapKeyRef:
              name: nacos-cm
              key: mysql.password
        volumeMounts:
        - name: data
          mountPath: /home/nacos/plugins/peer-finder
          subPath: peer-finder
        - name: data
          mountPath: /home/nacos/data
          subPath: data
        - name: data
          mountPath: /home/nacos/logs
          subPath: logs
  #在pvc模板中按照实际情况指定动态存储的名称
  volumeClaimTemplates:
    - metadata:
        name: data
        namespace: ruoyi
      spec:
        storageClassName: "alicloud-disk-topology-alltype"
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 20Gi

配置详解:

需要改的项为什么改
namespace: ruoyi与实际命名空间一致;使用默认命名空间时可不写。
port: 8848对外暴露的 Service 端口;调用方按此端口访问。
targetPort: 8848必须与容器实际监听端口一致。
port: 9848对外暴露的 Service 端口;调用方按此端口访问。
targetPort: 9848必须与容器实际监听端口一致。
port: 9849对外暴露的 Service 端口;调用方按此端口访问。

注意事项:

部署redis缓存服务

---

可复制 YAML:

YAML 保存位置: ~/k8s-manifests/ruoyi/redis-config.yaml

先在 Kubernetes 管理节点执行:

mkdir -p ~/k8s-manifests/ruoyi
cd ~/k8s-manifests/ruoyi
vi redis-config.yaml

把下方 YAML 全部复制进去;红色字段按当前环境修改;按 Esc 后输入 :wq 保存退出。

apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-config
  namespace: ruoyi
data:
  redis.conf: |
    bind 0.0.0.0
    protected-mode no
    appendonly yes
    requirepass 123456
---
apiVersion: v1
kind: Service
metadata:
  name: ry-redis-svc
  namespace: ruoyi
spec:
  # StatefulSet 必须使用 headless service 才能给每个 Pod 分配 DNS 名称
  clusterIP: None
  selector:
    app: ry-redis
  ports:
  - port: 6379
    targetPort: 6379
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: ry-redis
  namespace: ruoyi
spec:
  serviceName: ry-redis-svc   # 必须和上面的 Service 名一致
  replicas: 1
  selector:
    matchLabels:
      app: ry-redis
  template:
    metadata:
      labels:
        app: ry-redis
    spec:
      containers:
      - name: redis
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/redis:7.2.9
        ports:
        - containerPort: 6379
        env:
        - name: TZ
          value: "Asia/Shanghai"
        volumeMounts:
        - name: data
          mountPath: /data
        - name: redis-config
          mountPath: /usr/local/etc/redis/redis.conf
          subPath: redis.conf
        command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
      volumes:
      - name: redis-config
        configMap:
          name: redis-config
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "alicloud-disk-topology-alltype"
      resources:
        requests:
          storage: 20Gi

配置详解:

需要改的项为什么改
namespace: ruoyi与实际命名空间一致;使用默认命名空间时可不写。
port: 6379对外暴露的 Service 端口;调用方按此端口访问。
targetPort: 6379必须与容器实际监听端口一致。
replicas: 1按可用性和资源容量设置副本数。
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/redis:7.2.9替换为实际可拉取的镜像地址和版本。
accessModes: ["ReadWriteOnce"]按存储类型与读写需求确认。

注意事项:

同步说明

本文由飞书云文档同步生成。涉及命令、SQL、配置示例时,请以飞书源文档和实际环境执行结果为准。