K8s 集群部署微服务 - DevOps(一)

K8s 集群部署微服务 - DevOps(一)


K8s 集群环境搭建 - yaml 版本(一)
K8s 集群部署中间件 - yaml 版本(二)
K8s 集群部署微服务 - yaml 版本(三)
K8s 集群部署微服务 - DevOps(一)

文章目录

  • [K8s 集群部署微服务 - DevOps(一)](#K8s 集群部署微服务 - DevOps(一))
  • 前言
  • [一、 Helm](#一、 Helm)
    • [1. 安装 Helm](#1. 安装 Helm)
    • [2. Helm 常用命令:](#2. Helm 常用命令:)
  • [二、 kubeSphere](#二、 kubeSphere)
    • [1. 安装 kubeSphere](#1. 安装 kubeSphere)
    • [2. 激活 kubeSphere 社区版](#2. 激活 kubeSphere 社区版)
    • [3. 设置 Harbor 为应用仓库](#3. 设置 Harbor 为应用仓库)
  • 三、部署中间件
    • [1. 部署 mysql](#1. 部署 mysql)
    • [2. 部署 nacos](#2. 部署 nacos)
  • 四、疑问与总结

前言

  • 在前面我们手动搭建了 k8s 集群,并手动使用命令行部署了 中间件、微服务项目。部署的过程中深刻体会到了过程繁琐、yaml 文件难以管理的痛点。
  • 接下来我们使用 kubeSphere 和 helm 来解决这个痛点,实现 CI/CD,从代码提交后,后续流程通过配置的流水线自动化更新部署。

一、 Helm

  • Helm 是 Kubernetes 的包管理工具,可以方便的发现、共享和构建 kubernetes 应用。可以解决每次部署中间件或微服务众多yaml 文件难以管理、已经多集群环境下的yaml 文件无法重用的问题。我们可以可以通过 Helm 构建 chart,使用chart 来构建应用。Helm 组件如下:

    • Chart:包含部署 k8s 一个应用所有的yaml (比如 deployment,services,ingress,configMap)文件以及其他申明文件(比如版本,变量信息),一起整合后的 chart 包。Helm 同步部署该 chart 包来部署应用,解决了之前我们部署应用yaml文件难以管理的问题。
    • Helm 客户端:负责和 k8s apiserver 通信。
    • Release:使用 chart 包部署生成的一个实例就是 Release。部署多次就生成多个 Release。
    • Repository:用于发布和存储 chart 的仓库,类似于 docker 仓库,我后面使用的是 harbor 作为 仓库。
  • chart 目录结构如下:

    java 复制代码
    mysql-chart/
    ├── charts                      # 存放当前Chart依赖的子Chart(子图表),无依赖时为空
    ├── Chart.yaml                  # Chart元数据文件,存储名称、版本、描述等核心信息
    ├── templates                   # Kubernetes资源模板目录,Helm会渲染生成最终YAML
    │   ├── deployment.yaml         # 定义Deployment资源,管理MySQL Pod的创建、扩容和自愈
    │   ├── _helpers.tpl            # 模板辅助函数库,存放可复用的模板片段(如名称、标签定义)
    │   ├── hpa.yaml                # 定义HPA(水平自动扩缩容),根据资源使用率调整Pod数量
    │   ├── httproute.yaml          # 定义Gateway API的HTTPRoute,用于流量路由(替代传统Ingress)
    │   ├── ingress.yaml            # 定义Ingress资源,暴露服务到集群外(MySQL常用NodePort/LoadBalancer)
    │   ├── NOTES.txt               # 部署成功后的提示信息,指导用户使用应用(如连接方式)
    │   ├── serviceaccount.yaml     # 定义ServiceAccount,为Pod提供Kubernetes API访问权限
    │   ├── service.yaml            # 定义Service资源,为MySQL Pod提供固定访问地址和端口
    │   └── tests                   # 测试用例目录,验证应用部署是否成功
    │       └── test-connection.yaml # Helm测试钩子,部署后测试MySQL连接可用性
    └── values.yaml                 # Chart配置文件,存储所有可配置参数(如镜像、资源、密码等)
  • Helm 常用内置对象:

    类别 核心对象 作用
    Release .Release 包含当前 Release(部署实例)的元信息(名称、版本、命名空间等)
    Chart .Chart 包含当前 Chart 的元数据(名称、版本、描述等,来自 Chart.yaml)
    Values .Values 包含用户配置的参数(来自 values.yaml 或 --set 参数),属性由用户自定义
    Files .Files 读取 Chart 内的非模板文件(如配置文件、证书)
    Capabilities .Capabilities 描述 K8s 集群的能力(版本、支持的 API 资源等)
    Template .Template 包含当前模板文件的元信息(名称、路径)
    • .Release:

      子属性 说明 示例值
      .Release.Name Release 名称(helm install 指定的名称) my-mysql
      .Release.Namespace Release 部署的命名空间(未指定时为 default) mysql-prod
      .Release.Revision Release 的版本号(首次安装为 1,每次升级 / 回滚递增) 2
      .Release.IsInstall 布尔值,是否为首次安装(helm install) true/false
      .Release.IsUpgrade 布尔值,是否为升级操作(helm upgrade) true/false
      .Release.IsRollback 布尔值,是否为回滚操作(helm rollback) true/false
      .Release.Service 部署服务名称(通常为 Helm) Helm
      .Release.Time Release 操作的时间戳(RFC3339 格式) 2024-05-20T10:00:00Z
    • .Chart:

      子属性 说明 示例值
      .Chart.Name Chart 名称(Chart.yaml 中 name 字段) my-mysql-chart
      .Chart.Version Chart 版本(Chart.yaml 中 version 字段,SemVer 格式) 1.0.0
      .Chart.AppVersion 应用版本(Chart.yaml 中 appVersion 字段,如 MySQL 版本) 8.0.36
      .Chart.Description Chart 描述(Chart.yaml 中 description 字段) 自定义 MySQL Chart
      .Chart.Maintainers 维护者信息(数组,包含 name/email 等) [{name: "张三", email: "zhangsan@example.com"}]
      .Chart.Dependencies Chart 依赖(数组,来自 Chart.yaml 中 dependencies) [{name: "redis", version: "17.3.12"}]
    • .Files:

      方法 说明 示例
      .Files.Get "path" 读取文件内容(路径为 Chart 内相对路径) .Files.Get "config/my.cnf"
      .Files.Glob "pattern" 按通配符匹配文件(返回文件列表) .Files.Glob "config/*.yaml"
      .Files.AsConfig 将文件内容转为 ConfigMap 格式(自动处理键值对) `.Files.Get "config/application.properties"
      .Files.AsSecrets 将文件内容转为 Secret 格式(Base64 编码) `.Files.Get "certs/tls.key"
    • .Capabilities:

      子属性 说明 示例
      .Capabilities.KubeVersion K8s 版本信息(包含 Major/Minor/GitVersion) {Major: "1", Minor: "25", GitVersion: "v1.25.0"}
      .Capabilities.APIVersions.Has "group/version" 检查集群是否支持某个 API 版本(如 apps/v1) .Capabilities.APIVersions.Has "apps/v1"
      .Capabilities.APIVersions.AvailableVersions "group" 获取某个 API 组的所有可用版本 .Capabilities.APIVersions.AvailableVersions "apps"
    • .Template

      子属性 说明 示例
      .Template.Name 当前模板文件的名称(相对路径) templates/deployment.yaml
      .Template.BasePath Chart 中模板目录的路径(通常为 templates/) templates/

1. 安装 Helm

  • 一键安装 Helm :

    java 复制代码
    curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
  • 安装后查看 Helm 版本:helm version

2. Helm 常用命令:

  • 仓库管理(Repository):

    • helm repo add [仓库名] [仓库地址]:添加远程仓库。 helm repo add bitnami https://charts.bitnami.com/bitnami。
    • helm repo update [仓库名]:更新仓库索引(拉取最新 Chart 列表)。helm repo update(更新所有仓库),helm repo update bitnami(仅更新 bitnami 仓库)。
    • helm repo list: 查看已添加的仓库。
    • helm repo remove [仓库名]:移除仓库。helm repo remove bitnami。
  • Chart 操作(Chart):

    • helm create [chart 名]:创建标准化 Chart 骨架(自动生成目录结构)。helm create my-springboot-chart。
    • helm search repo [仓库名/chart名]: 搜索仓库中的 Chart。 helm search repo bitnami/mysql(搜索 bitnami 仓库的 MySQL Chart)
      helm search repo nginx --versions(查看所有版本)
    • helm show [values、模板、说明] [仓库名/chart名]:查看 Chart 详细信息(values、模板、说明)。helm show values bitnami/mysql(查看默认配置);helm show chart bitnami/mysql(查看 Chart 元数据);helm show readme bitnami/mysql(查看说明文档)。
    • helm pull [仓库名/chart名]:拉取 Chart 到本地(不安装)。 helm pull bitnami/mysql --version 9.10.1(指定版本拉取)。
  • Release 生命周期管理(核心):

    • helm install [release名] [仓库名/chart名]:安装 Chart 为 Release 。helm install my-mysql bitnami/mysql(默认配置安装);helm install my-mysql bitnami/mysql --set auth.rootPassword=123456 -n mysql --create-namespace(自定义参数 + 指定命名空间);helm install my-app ./my-chart -f custom-values.yaml(用自定义 values 文件安装)
    • helm upgrade 升级已安装的 Release(更新 Chart 版本或配置)。helm upgrade my-mysql bitnami/mysql --set replicaCount=3(更新配置);helm upgrade my-mysql bitnami/mysql --version 9.10.2(升级 Chart 版本)
    • helm rollback:回滚 Release 到历史版本。 helm rollback my-mysql 1(回滚到版本 1);helm rollback my-mysql(默认回滚到上一版本)
    • helm uninstall: 卸载 Release(删除应用及相关资源)。 helm uninstall my-mysql -n mysql
    • helm list:查看已安装的 Release。 helm list(默认显示当前命名空间);helm list -A(显示所有命名空间);helm list -n mysql(指定命名空间)
  • 调试与模板渲染:

    • helm template [release名] [仓库名/chart名]: 渲染 Chart 模板(不部署,仅输出 YAML)。 helm template my-mysql bitnami/mysql --set auth.rootPassword=123456。
    • helm install [release名] [仓库名/chart名] --dry-run:模拟安装(检查配置和依赖,不实际部署)。 helm install my-mysql bitnami/mysql --dry-run --debug(--debug 显示详细日志)
    • helm get [release名] :获取 Release 的已渲染模板、values 或 hooks。 helm get values my-mysql(查看当前使用的 values 配置);helm get manifest my-mysql(查看已部署的 YAML 清单)
  • 其他常用命令:

    • helm version:查看 Helm 版本 helm version
    • helm help:查看命令帮助(万能调试) helm help install(查看 install 命令详情)。helm install --help
    • helm test :运行 Release 的测试用例(验证应用可用性) helm test my-mysql -n mysql
    • helm plugin :管理 Helm 插件(扩展功能)。 helm plugin install https://github.com/chartmuseum/helm-push(安装推送插件)。

二、 kubeSphere

  • kubeSphere 简介:一款基于 Kubernetes 构建的开源容器平台,简化 Kubernetes 集群的部署、运维和应用管理流程,降低云原生技术的使用门槛。可视化运维:KubeSphere 对 Helm 部署的应用提供监控、日志、伸缩等一体化运维;
  • kubeSphere 的核心定位
    • 为 Kubernetes 提供可视化的操作界面,替代复杂的 kubectl 命令行操作;
    • 集成丰富的云原生组件(如 DevOps、监控、日志、服务网格等),实现一站式集群管理;
    • 支持多集群统一管理,适配公有云、私有云、混合云等多种部署环境。
  • KubeSphere 的核心功能模块
    • 集群与节点管理:可视化管理 Kubernetes 集群的节点、命名空间、资源配额、存储卷等核心资源;支持集群的扩缩容、节点状态监控、污点和容忍度配置,简化集群运维。
    • 应用生命周期管理:提供应用商店(App Store),支持 Helm Chart 一键部署主流云原生应用(如 MySQL、Redis、Elasticsearch 等);支持应用的发布、回滚、扩缩容和版本管理,支持无状态 / 有状态应用部署。
    • DevOps 平台:内置 CI/CD 流水线,兼容 Jenkins 核心能力,支持代码仓库(GitLab/GitHub)、镜像仓库(Harbor)无缝集成;提供代码检查、自动化构建、测试、部署的全流程支持,适配 DevOps 实践落地。
    • 监控与可观测性:集成 Prometheus 和 Grafana,实现集群、节点、Pod、应用的多维度指标监控和可视化;支持日志收集(ELK/Loki)、链路追踪(Jaeger/Zipkin),快速定位系统故障。
    • 服务网格(ServiceMesh):基于 Istio 实现服务网格的可视化管理,支持流量治理(熔断、限流、路由)、服务监控、分布式追踪;无需修改业务代码,即可实现微服务的高可用和可观测性。
    • 多租户与权限管理:基于 Kubernetes RBAC 实现细粒度的权限控制,支持企业级的租户(工作空间)、角色、项目管理;适配多团队协作的资源隔离和权限分配需求。
    • 存储与网络管理:支持主流存储插件(如 CSI、NFS、Ceph)和网络插件(Calico、Flannel)的可视化配置;提供存储类(StorageClass)、负载均衡(Service/Ingress)的便捷管理。

1. 安装 kubeSphere

  • kubeSphere 的部署有以下三种:

    • All-in-One 单节点部署:适用于测试和开发环境,一键部署 KubeSphere 和 Kubernetes 所有组件。
    • Multi-Node 多节点部署:适用于生产环境,支持高可用集群部署,可指定主节点和工作节点。
    • Kubernetes 集群上部署:在已有的 Kubernetes 集群(如 EKS、ACK、自建集群)上安装 KubeSphere,仅部署平台组件,复用现有集群资源。我们之前已经部署过了 k8s 集群,这里便直接通过如下方式进行部署。所有的部署、使用方式参考自官网。
  • 安装 helm 3:helm 官网安装教程

    java 复制代码
    curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
    chmod 700 get_helm.sh
    ./get_helm.sh
  • 验证 helm,查看版本:

    java 复制代码
    helm version
  • 添加 Helm 国内仓库:

    java 复制代码
    # 华为云 Helm 仓库
    helm repo add huawei https://mirrors.huaweicloud.com/kubernetes-charts/
    # 阿里云 Helm 仓库
    helm repo add aliyun	https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
    
    # 更新仓库索引(关键步骤,确保获取最新 Chart 列表)
    helm repo update
    
    # 验证查看已添加的仓库
    helm repo list
  • 安装 KubeSphere 的核心组件:KubeSphere Core (ks-core) 。KubeSphere Core 安装完成后,即可访问 KubeSphere Web 控制台。

    java 复制代码
    chart=oci://hub.kubesphere.com.cn/kse/ks-core
    version=1.2.3
    helm upgrade --install -n kubesphere-system --create-namespace ks-core $chart --debug --wait --version $version --reset-values --set extension.imageRegistry=swr.cn-north-9.myhuaweicloud.com/ks
  • 如下提示标识安装成功:首次登录需要提示中的用户名和密码,并且第一次登录成功后会让我们修改密码。

  • 访问提示中的 30880 端口进行访问:安装完成。

2. 激活 kubeSphere 社区版

  • 登录 kubeSphere 之后,我们需要激活kubeSphere社区办,不然部分功能不可用,步骤如下:
    • 登录 KubeSphere Web 控制台,点击组件坞 > 平台设置 > 许可证,进入许可证页面,获取当前集群的集群 ID:

    • 申请 KubeSphere 社区版的免费许可。填入个人信息和集群 ID,提交申请。

    • 提交申请之后会收到邮件,将邮件中的 license 复制到KubeSphere Web 控制台的许可证页面,点击添加许可证。

3. 设置 Harbor 为应用仓库

  • 我的 harbor 版本如下:v2.11.1

  • 该版本的 harbor 需要注意以下几点:

    • Harbor 2.8 版本及之后移除 ChartMuseum,全面转向 OCI 管理 Helm Chart,这是 2.8 最核心的变化,彻底删除了 Helm Chart 仓库的传统实现 ChartMuseum,所有 Helm Chart 必须以 OCI 制品形式存储和分发,与容器镜像共用存储和权限体系,不再支持--with-chartmuseum启动参。
    • Harbor 2.8 及以后版本(包括 v2.11)在创建 Charts 仓库时,无需单独创建 "Helm Charts 仓库",而是与 Docker 镜像仓库统一合并为OCI 制品仓库,即不再区分 "镜像仓
    • 库" 和 "Charts 仓库"。
  • 所以我们添加 harbor 为应用仓库时,需要设置 OIC://,而不是 http:// 或 https://。如下:

  • 其中的域名 mortal.harbor.com 需要配置在coredns 中,不然会报:no such host

    java 复制代码
    kubectl edit configmap coredns -n kube-system
  • 添加如下配置:

  • 保存退出后,重启 CoreDNS 生效:

    java 复制代码
    kubectl rollout restart deployment coredns -n kube-system
  • 还需要给 kubeSphere 配置 harbor 的证书,添加授权,不然验证无法通过,会报 401:unauthorized。

  • 添加 harbor 为应用仓库,具体交互流程如下:

    java 复制代码
    用户点击"添加仓库"
        ↓
    ks-apiserver 接收请求
        ↓
    ks-apiserver 尝试连接 Harbor (验证证书) ← 需要证书信任
        ↓
    返回"连接成功"给用户界面
        ↓
    ks-controller-manager 检测到新仓库需要同步
        ↓
    ks-controller-manager 开始拉取 Helm Chart 索引 ← 需要证书信任
        ↓
    同步状态更新为"成功"
  • 获取 Harbor CA 证书:

    java 复制代码
    echo | openssl s_client -connect mortal.harbor.com:443 -showcerts 2>/dev/null | sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' > /tmp/harbor-ca.crt
  • 创建 CA 证书 ConfigMap,用于给 ks-apiserver 和 ks-controller-manager 进行挂载:

    java 复制代码
    kubectl create configmap harbor-ca-cert \
      --from-file=harbor-ca.crt=/tmp/harbor-ca.crt \
      -n kubesphere-system
  • 为 ks-apiserver 添加证书挂载:

    java 复制代码
    # 编辑 ks-apiserver 部署
    kubectl edit deployment ks-apiserver -n kubesphere-system
    java 复制代码
    # 1. 在 spec.template.spec.containers 中找到 ks-apiserver 容器
    #    在 containers 下的 volumeMounts 部分添加:
    volumeMounts:
    - mountPath: /etc/ssl/certs/harbor-ca.crt  # 挂载路径
      name: harbor-ca-volume                   # 卷名称
      subPath: harbor-ca.crt                   # 引用 ConfigMap 中的文件名
      readOnly: true
    
    # 2. 在 spec.template.spec.volumes 部分添加:
    volumes:
    - name: harbor-ca-volume                   # 卷名称,与上面匹配
      configMap:
        name: harbor-ca-cert                   # ConfigMap 名称
        defaultMode: 420                       # 权限 0644
  • 为 ks-controller-manager 添加证书挂载:

    java 复制代码
    # 编辑 ks-controller-manager 部署
    kubectl edit deployment ks-controller-manager -n kubesphere-system
    java 复制代码
    # 在 ks-controller-manager 容器的 volumeMounts 部分添加:
    volumeMounts:
    - mountPath: /etc/ssl/certs/harbor-ca.crt
      name: harbor-ca-volume
      subPath: harbor-ca.crt
      readOnly: true
    
    # 在 volumes 部分添加:
    volumes:
    - name: harbor-ca-volume
      configMap:
        name: harbor-ca-cert
        defaultMode: 420
  • 保存后,pod 会重启,等待重启后验证:

    java 复制代码
    # 验证证书文件
    kubectl exec deployment/ks-controller-manager -n kubesphere-system -- cat /etc/ssl/certs/harbor-ca.crt | head -3
    # 应显示:-----BEGIN CERTIFICATE-----
  • 配置完之后,添加 Harbor 应用仓库便可以验证通过了,并且能成功同步。

  • 如果还是401,由于 kubeSphere 是社区版,只能有一个应用仓库,并且 UI 界面无法配置 用户密码,可通过控制台手动修改已有的该仓库地址和添加用户密码:

    • 编辑现有仓库:

      java 复制代码
      kubectl edit repo builtin-stable -n kubesphere-system
    • 修改信息如下:spec.url:替换为 https://mortal.harbor.com/chartrepo/charts-repo;`spec.credential`:添加认证信息(如果该字段不存在,则添加;如果存在,则更新)

      java 复制代码
      # Please edit the object below. Lines beginning with a '#' will be ignored,
      # and an empty file will abort the edit. If an error occurs while saving this file will be
      # reopened with the relevant failures.
      #
      apiVersion: application.kubesphere.io/v2
      kind: Repo
      metadata:
        annotations:
          kubesphere.io/alias-name: built-stable
          kubesphere.io/sync-timestamp: "1764660162"
        creationTimestamp: "2025-12-02T01:17:35Z"
        generation: 2
        labels:
          app.kubernetes.io/managed-by: Helm
          application.kubesphere.io/sync-app-store: "true"
          kubesphere.io/workspace: system-workspace
        name: builtin-stable
        resourceVersion: "11196151"
        uid: 1a4cffaf-39ab-43d3-8a0e-2f0e9b6ff978
      spec:
        credential:
          password: Harbor131413
          username: admin
        description: Harbor Helm Repository
        syncPeriod: 300
        url: oci://mortal.harbor.com/charts-repo
      status:
        lastUpdateTime: "2025-12-02T12:56:39Z"
        state: successful

三、部署中间件

1. 部署 mysql

  • 创建 mysql-chart

    java 复制代码
    helm create mysql-chart
  • 调整文件后结构如下:

    java 复制代码
    mysql-chart
    ├── Chart.yaml
    ├── templates
    │   ├── configmap.yaml
    │   ├── secret.yaml
    │   ├── service.yaml
    │   └── statefulset.yaml
    └── values.yaml
  • 编写 Chart.yaml

    java 复制代码
    apiVersion: v2
    name: mysql-chart
    description: A Helm chart for Kubernetes
    
    # A chart can be either an 'application' or a 'library' chart.
    #
    # Application charts are a collection of templates that can be packaged into versioned archives
    # to be deployed.
    #
    # Library charts provide useful utilities or functions for the chart developer. They're included as
    # a dependency of application charts to inject those utilities and functions into the rendering
    # pipeline. Library charts do not define any templates and therefore cannot be deployed.
    type: application
    
    # This is the chart version. This version number should be incremented each time you make changes
    # to the chart and its templates, including the app version.
    # Versions are expected to follow Semantic Versioning (https://semver.org/)
    version: 0.1.0
    
    # This is the version number of the application being deployed. This version number should be
    # incremented each time you make changes to the application. Versions are not expected to
    # follow Semantic Versioning. They should reflect the version the application is using.
    # It is recommended to use it with quotes.
    appVersion: "8.3.0"
  • 编写 values.yaml

    java 复制代码
    # 镜像配置
    image:
      repository: mortal.harbor.com/mortal/mysql
      tag: 8.3.0
      pullPolicy: IfNotPresent
      pullSecrets: harbor-creds
    
    # 服务配置
    service:
      headless:
        name: mysql-headless
      nodePort:
        name: mysql-service
        nodePort: 30306
    
    # 存储配置
    persistence:
      enabled: true
      storageClass: nfs-sc
      size: 10Gi
    
    # MySQL 配置
    mysql:
      rootPassword: "root"  # 实际使用时建议通过 --set 覆盖
      timezone: "Asia/Shanghai"
      maxConnections: 1000
      serverId: 1
  • 编写 configMap.yaml:

    java 复制代码
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: mysql-config
      namespace: {{ .Release.Namespace }}
    data:
      my.cnf: |
        [client]
        default-character-set=utf8mb4
        
        [mysql]
        default-character-set=utf8mb4
        
        [mysqld]
        server-id = {{ .Values.mysql.serverId }}
        log-bin=mysql-bin
        binlog_expire_logs_seconds = 2592000
        sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
        max_connections={{ .Values.mysql.maxConnections }}
        symbolic-links=0
        default-time_zone = '+8:00'
        character-set-server=utf8mb4
        collation-server=utf8mb4_unicode_ci
  • 编写 secret.yaml:

    java 复制代码
    apiVersion: v1
    kind: Secret
    metadata:
      name: mysql-secret
      namespace: {{ .Release.Namespace }}
    type: Opaque
    data:
      root-password: {{ .Values.mysql.rootPassword | b64enc }}
  • 编写 service.yaml:

    java 复制代码
    apiVersion: v1
    kind: Service
    metadata:
      name: {{ .Values.service.headless.name }}
      namespace: {{ .Release.Namespace }}
    spec:
      clusterIP: None
      selector:
        app: mysql
        release: {{ .Release.Name }}
      ports:
      - port: 3306
        targetPort: 3306
      type: ClusterIP
    
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: {{ .Values.service.nodePort.name }}
      namespace: {{ .Release.Namespace }}
    spec:
      type: NodePort
      ports:
      - port: 3306
        targetPort: 3306
        nodePort: {{ .Values.service.nodePort.nodePort }}
      selector:
        app: mysql
        release: {{ .Release.Name }}
  • 编写 statefulset.yaml:

    java 复制代码
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: {{ .Release.Name }}-mysql
      namespace: {{ .Release.Namespace }}
    spec:
      serviceName: {{ .Values.service.headless.name }}
      replicas: 3
      selector:
        matchLabels:
          app: mysql
          release: {{ .Release.Name }}
      template:
        metadata:
          labels:
            app: mysql
            release: {{ .Release.Name }}
        spec:
          imagePullSecrets:
          - name: {{ .Values.image.pullSecrets }}
          containers:
          - name: mysql
            image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
            ports:
            - containerPort: 3306
            env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: root-password
            - name: TZ
              value: {{ .Values.mysql.timezone }}
            volumeMounts:
            - name: mysql-config
              mountPath: /etc/mysql/conf.d/my.cnf
              subPath: my.cnf
            - name: mysql-data
              mountPath: /var/lib/mysql
            livenessProbe:
              exec:
                command: ["mysqladmin", "ping", "-uroot", "-p$(MYSQL_ROOT_PASSWORD)"]
              initialDelaySeconds: 30
              periodSeconds: 10
            readinessProbe:
              exec:
                command: ["mysqladmin", "ping", "-uroot", "-p$(MYSQL_ROOT_PASSWORD)"]
              initialDelaySeconds: 5
              periodSeconds: 5
          volumes:
          - name: mysql-config
            configMap:
              name: mysql-config
      volumeClaimTemplates:
      - metadata:
          name: mysql-data
        spec:
          accessModes: [ "ReadWriteOnce" ]
          resources:
            requests:
              storage: {{ .Values.persistence.size }}
          storageClassName: {{ .Values.persistence.storageClass }}
  • 结构如下:

    java 复制代码
    mysql-chart
    ├── Chart.yaml
    ├── templates
    │   ├── configmap.yaml
    │   ├── secret.yaml
    │   ├── service.yaml
    │   └── statefulset.yaml
    └── values.yaml
  • 将 chart 进行打包:

    java 复制代码
    helm package nysql-chart
  • 打完包后推送至 harbor 仓库:

    java 复制代码
    helm push mysql-chart-0.1.0.tgz oci://mortal.harbor.com/charts-repo --insecure-skip-tls-verify
  • 登录 kubeSphere,点击 [ 企业空间管理 ] -> [ 选择我们要安装的集群 ] -> [ 应用负载 ] -> [ 应用 ] -> [ 创建 ],选择从应用模板创建,选择我们前面创建的 harbor 应用仓库。

  • 选择 mysql-chart 安装,安装之后,集群中就可以使用该应用了。

  • 并且可以直观的看到部署详情,以及可以直接点击控制扩容或缩容,而不用依赖命令行了。

2. 部署 nacos

  • 创建 nacos-chart

    java 复制代码
    helm create nacos-chart
  • 需要对文件进行下调整,结构如下:

    java 复制代码
    nacos-chart/
    ├── Chart.yaml
    ├── templates
    │   ├── configmap.yaml
    │   ├── headless-svc.yaml
    │   ├── mysql-init-job.yaml
    │   ├── service.yaml
    │   └── statefulset.yaml
    └── values.yaml
  • Chart.yaml:

    java 复制代码
    apiVersion: v2
    name: nacos
    description: A simple Nacos Helm Chart without _helpers.tpl
    type: application
    version: 0.1.0
    appVersion: "2.1.1"
  • values.yaml:

    java 复制代码
    # 固定配置(无需动态调整)
    namespace: mortal-system
    replicaCount: 3
    image:
      repository: mortal.harbor.com/mortal/nacos
      tag: 2.1.1
      pullPolicy: IfNotPresent
    
    # MySQL 配置
    mysql:
      serviceName: mysql-headless
      rootPassword: root
      dbName: nacos_config
      port: 3306
    
    # 存储配置
    storage:
      className: nfs-sc
      size: 5Gi
    
    # 服务配置
    service:
      external:
        type: NodePort
        port: 8848
        nodePort: 30848
      headless:
        ports:
          http: 8848
          clientRpc: 9848
          serverRpc: 9849
    
    # Nacos 配置
    nacos:
      auth:
        enabled: false
      cluster:
        name: mortal-cluster
      raft:
        dataDir: /home/nacos/data/raft
  • configmap.yaml:

    java 复制代码
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: nacos-config
      namespace: {{ .Values.namespace }}
    data:
      application.properties: |
        spring.datasource.platform=mysql
        db.num=1
        db.url.0=jdbc:mysql://{{ .Values.mysql.serviceName }}:{{ .Values.mysql.port }}/{{ .Values.mysql.dbName }}?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
        db.user=root
        db.password={{ .Values.mysql.rootPassword }}
        nacos.core.auth.enabled={{ .Values.nacos.auth.enabled }}
        nacos.server.ip=0.0.0.0
        nacos.naming.data.warmup=true
        nacos.core.singleton=false
        nacos.raft.dataDir={{ .Values.nacos.raft.dataDir }}
        nacos.naming.cluster.name={{ .Values.nacos.cluster.name }}
        nacos.server.rpc.port={{ .Values.service.headless.ports.serverRpc }}
        nacos.inetutils.prefer-hostname-over-ip=true
        # 直接生成集群地址(替代 helpers)
        nacos.naming.serverAddr={{- $replicas := int .Values.replicaCount -}}
                              {{- $namespace := .Values.namespace -}}
                              {{- $httpPort := .Values.service.headless.ports.http -}}
                              {{- range $i := until $replicas -}}
                              nacos-{{ $i }}.nacos-headless.{{ $namespace }}.svc.cluster.local:{{ $httpPort }}{{- if ne $i (sub $replicas 1) }},{{ end -}}
                              {{- end -}}
  • headless-svc.yaml:

    java 复制代码
    apiVersion: v1
    kind: Service
    metadata:
      name: nacos-headless
      namespace: {{ .Values.namespace }}
    spec:
      clusterIP: None
      ports:
      - port: {{ .Values.service.headless.ports.http }}
        targetPort: {{ .Values.service.headless.ports.http }}
        name: http
      - port: {{ .Values.service.headless.ports.clientRpc }}
        targetPort: {{ .Values.service.headless.ports.clientRpc }}
        name: client-rpc
      - port: {{ .Values.service.headless.ports.serverRpc }}
        targetPort: {{ .Values.service.headless.ports.serverRpc }}
        name: server-rpc
      selector:
        app: nacos
  • service.yaml:

    java 复制代码
    apiVersion: v1
    kind: Service
    metadata:
      name: nacos-service
      namespace: {{ .Values.namespace }}
    spec:
      type: {{ .Values.service.external.type }}
      ports:
      - port: {{ .Values.service.external.port }}
        targetPort: {{ .Values.service.external.port }}
        nodePort: {{ .Values.service.external.nodePort }}
      selector:
        app: nacos
  • 我希望部署nacos的时候,同时完成 nacos 相关表的初始化工作。mysql-init-job.yaml:

    java 复制代码
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: nacos-mysql-init-job
      namespace: {{ .Values.namespace }}
      labels:
        app: nacos
        component: mysql-init
        env: {{ .Values.env | default "prod" }}  # 用 Values 定义环境标签
        job-type: init  # 自定义标签
    spec:
      backoffLimit: 3
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: mysql-init
            image: mortal.harbor.com/mortal/mysql:8.3.0
            env:
            - name: MYSQL_ROOT_PASSWORD
              value: "{{ .Values.mysql.rootPassword }}"
            - name: MYSQL_SERVICE_NAME
              value: "{{ .Values.mysql.serviceName }}"
            - name: NACOS_DB_NAME
              value: "{{ .Values.mysql.dbName }}"
            command: ["/bin/sh", "-c"]
            args:
            - |
              until mysql -h $MYSQL_SERVICE_NAME -u root -p$MYSQL_ROOT_PASSWORD --default-auth=mysql_native_password -e "SELECT 1"; do
                echo "等待 MySQL 服务启动中..."
                sleep 3
              done
    
              mysql -h $MYSQL_SERVICE_NAME -u root -p$MYSQL_ROOT_PASSWORD --default-auth=mysql_native_password <<'EOF'
              CREATE DATABASE IF NOT EXISTS `nacos_config` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
              USE `nacos_config`;
    
              -- 1. config_info
              CREATE TABLE IF NOT EXISTS `config_info` (
                `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
                `data_id` varchar(255) NOT NULL COMMENT 'data_id',
                `group_id` varchar(255) DEFAULT NULL COMMENT 'group_id',
                `content` longtext NOT NULL COMMENT 'content',
                `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
                `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
                `src_user` text COMMENT 'source user',
                `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
                `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
                `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
                `c_desc` varchar(256) DEFAULT NULL COMMENT 'configuration description',
                `c_use` varchar(64) DEFAULT NULL COMMENT 'configuration usage',
                `effect` varchar(64) DEFAULT NULL COMMENT 'configuration effect',
                `type` varchar(64) DEFAULT NULL COMMENT 'configuration type',
                `c_schema` text COMMENT 'configuration schema',
                PRIMARY KEY (`id`),
                UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='config_info';
    
              -- 2. config_info_aggr
              CREATE TABLE `config_info_aggr`  (
              `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT 'id',
              `data_id` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'data_id',
              `group_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'group_id',
              `datum_id` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'datum_id',
              `content` longtext CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT '内容',
              `gmt_modified` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
              `app_name` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL,
              `tenant_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT '' COMMENT '租户字段',
              PRIMARY KEY (`id`) USING BTREE,
              UNIQUE INDEX `uk_configinfoaggr_datagrouptenantdatum`(`data_id`, `group_id`, `tenant_id`, `datum_id`) USING BTREE
              ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_bin COMMENT = '增加租户字段' ROW_FORMAT = Dynamic;
    
              -- 3. config_info_beta
              CREATE TABLE IF NOT EXISTS `config_info_beta` (
                `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
                `data_id` varchar(255) NOT NULL COMMENT 'data_id',
                `group_id` varchar(128) NOT NULL COMMENT 'group_id',
                `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
                `content` longtext NOT NULL COMMENT 'content',
                `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
                `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
                `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
                `src_user` text COMMENT 'source user',
                `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
                `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
                PRIMARY KEY (`id`),
                UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='config_info_beta';
    
              -- 4. config_info_tag
              CREATE TABLE IF NOT EXISTS `config_info_tag` (
                `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
                `data_id` varchar(255) NOT NULL COMMENT 'data_id',
                `group_id` varchar(128) NOT NULL COMMENT 'group_id',
                `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
                `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
                `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
                `content` longtext NOT NULL COMMENT 'content',
                `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
                `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
                `src_user` text COMMENT 'source user',
                `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
                PRIMARY KEY (`id`),
                UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='config_info_tag';
    
              -- 5. config_tags_relation
              CREATE TABLE IF NOT EXISTS `config_tags_relation` (
                `id` bigint(20) NOT NULL COMMENT 'id',
                `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
                `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
                `data_id` varchar(255) NOT NULL COMMENT 'data_id',
                `group_id` varchar(128) NOT NULL COMMENT 'group_id',
                `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
                `nid` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'nid,自增标识',
                PRIMARY KEY (`nid`),
                UNIQUE KEY `uk_configtagrelation_configtag` (`data_id`,`group_id`,`tenant_id`,`tag_name`,`tag_type`),
                KEY `idx_tag_name` (`tag_name`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='config_tag_relation';
    
              -- 6. group_capacity
              CREATE TABLE IF NOT EXISTS `group_capacity` (
                `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
                `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
                `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
                `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '已使用量',
                `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置最大大小,0表示使用默认值',
                `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,0表示使用默认值',
                `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大总大小,0表示使用默认值',
                `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大历史配置个数,0表示使用默认值',
                `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
                PRIMARY KEY (`id`),
                UNIQUE KEY `uk_group_id` (`group_id`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='集群、Group 容量信息表';
    
              -- 7. his_config_info
              CREATE TABLE IF NOT EXISTS `his_config_info` (
                `id` bigint(64) unsigned NOT NULL COMMENT 'id',
                `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '历史记录ID',
                `data_id` varchar(255) NOT NULL COMMENT 'data_id',
                `group_id` varchar(128) NOT NULL COMMENT 'group_id',
                `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
                `content` longtext NOT NULL COMMENT 'content',
                `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
                `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
                `src_user` text COMMENT 'source user',
                `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
                `op_type` char(10) DEFAULT NULL COMMENT 'operation type',
                `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
                PRIMARY KEY (`nid`),
                KEY `idx_gmt_create` (`gmt_create`),
                KEY `idx_gmt_modified` (`gmt_modified`),
                KEY `idx_did` (`data_id`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='多租户改造';
    
              -- 8. tenant_capacity
              CREATE TABLE IF NOT EXISTS `tenant_capacity` (
                `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
                `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
                `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
                `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '已使用量',
                `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置最大大小,0表示使用默认值',
                `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,0表示使用默认值',
                `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大总大小,0表示使用默认值',
                `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大历史配置个数,0表示使用默认值',
                `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
                PRIMARY KEY (`id`),
                UNIQUE KEY `uk_tenant_id` (`tenant_id`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户容量信息表';
    
              -- 9. tenant_info
              CREATE TABLE IF NOT EXISTS `tenant_info` (
                `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
                `kp` varchar(128) NOT NULL COMMENT 'kp',
                `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
                `tenant_name` varchar(128) DEFAULT '' COMMENT 'tenant_name',
                `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
                `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
                `gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
                `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
                PRIMARY KEY (`id`),
                UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
                KEY `idx_tenant_id` (`tenant_id`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='tenant_info';
    
              -- 10. users
              CREATE TABLE IF NOT EXISTS `users` (
                `username` varchar(50) NOT NULL PRIMARY KEY COMMENT 'username',
                `password` varchar(500) NOT NULL COMMENT 'password',
                `enabled` boolean NOT NULL COMMENT 'enabled'
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='users';
    
              -- 11. roles
              CREATE TABLE IF NOT EXISTS `roles` (
                `username` varchar(50) NOT NULL COMMENT 'username',
                `role` varchar(50) NOT NULL COMMENT 'role',
                UNIQUE KEY `uk_username_role` (`username`,`role`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='roles';
    
              -- 12. permissions
              CREATE TABLE IF NOT EXISTS `permissions` (
                `role` varchar(50) NOT NULL COMMENT 'role',
                `resource` varchar(255) NOT NULL COMMENT 'resource',
                `action` varchar(8) NOT NULL COMMENT 'action',
                UNIQUE KEY `uk_role_permission` (`role`,`resource`,`action`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='permissions';
    
              -- 13. config_blacklist
              CREATE TABLE IF NOT EXISTS `config_blacklist` (
                `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
                `data_id` varchar(255) NOT NULL COMMENT 'data_id',
                `group_id` varchar(255) NOT NULL COMMENT 'group_id',
                `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
                `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                PRIMARY KEY (`id`),
                UNIQUE KEY `uk_configblacklist_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置黑名单';
    
              -- 14. external_storage_config
              CREATE TABLE IF NOT EXISTS `external_storage_config` (
                `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
                `storage_type` varchar(32) NOT NULL COMMENT '存储类型',
                `config_key` varchar(128) NOT NULL COMMENT '配置key',
                `config_value` varchar(2048) NOT NULL COMMENT '配置value',
                `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
                PRIMARY KEY (`id`),
                UNIQUE KEY `uk_externalstorageconfig_storagetype_configkey` (`storage_type`,`config_key`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='外部存储配置';
    
              -- 初始化 Nacos 管理员账号(密码:nacos)
              INSERT INTO `users` (`username`, `password`, `enabled`) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
              INSERT INTO `roles` (`username`, `role`) VALUES ('nacos', 'ROLE_ADMIN');
              INSERT INTO `permissions` (`role`, `resource`, `action`) VALUES ('ROLE_ADMIN', '*', 'all');
              EOF
    
              echo "Nacos 数据库全量表初始化完成!共创建 14 张表 + 管理员账号"
  • statefulset.yaml :

    java 复制代码
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: nacos
      namespace: {{ .Values.namespace }}
    spec:
      serviceName: nacos-headless
      replicas: {{ .Values.replicaCount }}
      selector:
        matchLabels:
          app: nacos
      template:
        metadata:
          labels:
            app: nacos
        spec:
          containers:
          - name: nacos
            image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
            imagePullPolicy: {{ .Values.image.pullPolicy }}
            ports:
            - containerPort: {{ .Values.service.headless.ports.http }}
              name: http
            - containerPort: {{ .Values.service.headless.ports.clientRpc }}
              name: client-rpc
            - containerPort: {{ .Values.service.headless.ports.serverRpc }}
              name: server-rpc
            env:
            - name: NACOS_REPLICAS
              value: "{{ .Values.replicaCount }}"
            - name: NACOS_SERVERS
              # 直接生成集群地址
              value: "{{- $replicas := int .Values.replicaCount -}}
                      {{- $namespace := .Values.namespace -}}
                      {{- $httpPort := .Values.service.headless.ports.http -}}
                      {{- range $i := until $replicas -}}
                      nacos-{{ $i }}.nacos-headless.{{ $namespace }}.svc.cluster.local:{{ $httpPort }}{{- if ne $i (sub $replicas 1) }} {{ end -}}
                      {{- end -}}"
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: NACOS_SERVER_PORT
              value: "{{ .Values.service.headless.ports.http }}"
            volumeMounts:
            - name: nacos-config
              mountPath: /home/nacos/conf/application.properties
              subPath: application.properties
            - name: nacos-data
              mountPath: /home/nacos/data
          volumes:
          - name: nacos-config
            configMap:
              name: nacos-config
      volumeClaimTemplates:
      - metadata:
          name: nacos-data
        spec:
          accessModes: [ "ReadWriteMany" ]
          storageClassName: "{{ .Values.storage.className }}"
          resources:
            requests:
              storage: "{{ .Values.storage.size }}"
  • 打包并上传至 harbor:

    java 复制代码
    helm package nacos-chart
    helm push nacos-0.1.0.tgz  oci://mortal.harbor.com/charts-repo --insecure-skip-tls-verify
  • 同步下仓库:

  • 部署nacos:

  • 验证:成功创建了 nacos-config 及其 14 张表;成功访问 nacos 控制台。


...其他中间件后续再补充,不过都是这样的流程。

四、疑问与总结

  • 通过 helm 和 kubeSphere,解决了部署应用的过程中 yaml 文件难以管理,以及 多套集群环境原先需要多套yaml文件的问题。
    • yaml 文件交于了 helm 进行管理,以及使用helm 上传应用之后,只需要再部署时选择对应的集群即可,实现多套环境一次部署。
    • 同时 kubeSphere 提供了可视化平台,直接可查看日志,缩容,扩容,无需在通过繁琐的命令行进行查看。
  • 在部署应用的时候发现,服务(或资源)名称后的后缀格式存在差异,比如一些资源启动后,会接后缀 -0,-1,有些事借 -sdf3j,这样的随机字母,这是为什么呢?
    • 有状态资源用有序数字后缀:资源类型为 StatefulSet Pod,保证有状态应用的顺序和唯一性,便于实现持久化存储绑定、集群节点身份识别(如主从选举)。
    • 无状态资源用随机字符串后缀:资源类型为 Deployment/Job Pod,避免名称冲突,支持无状态部署。
相关推荐
axihaihai1 小时前
jenkins下微服务的cicd流程
运维·微服务·jenkins
拾忆,想起2 小时前
Dubbo延迟加载全解:从延迟暴露到延迟连接的深度优化
前端·微服务·架构·dubbo·safari
深思慎考2 小时前
微服务即时通讯系统(服务端)——网关服务设计与实现(7)
linux·c++·微服务·云原生·架构
gugugu.2 小时前
从单机到微服务:分布式架构演进全景解析
分布式·微服务·架构
阿拉斯攀登11 小时前
SpringCloudAlibaba之Nacos
微服务·服务发现·springcloud
seeyoutlb11 小时前
微服务全局日志处理
java·python·微服务
哈里谢顿12 小时前
Kubernetes 节点污点(Taints)操作验证手册
kubernetes
菜萝卜子12 小时前
k8s 启动一个redis
redis·容器·kubernetes
音视频牛哥12 小时前
AI时代底层技术链:GPU、云原生与大模型的协同进化全解析
大数据·云原生·kubernetes·音视频·transformer·gpu算力·云原生cloud native