跳到主要内容

ONES Helm 集群部署说明(内置组件)

本文将引导您在 Kubernetes 集群中使用 Helm 部署 ONES,并使用 ONES 内置中间件。

本部署方式适用于 v7.25.0 或更高版本的 ONES。

必要条件

  • Kubernetes 版本为 v1.22 或更高版本。
  • ONES 采用集群多副本部署。
  • 使用 ONES 内置 MySQL、Kafka、Redis、TiKV 和 ClickHouse。
  • Kubernetes 已提供满足访问模式和回收策略要求的 StorageClass。
  • Helm 安装账号可以创建集群级 CRD,以及目标 Namespace 内的 RBAC、PVC 和应用资源。

功能特性

  • 单 Namespace 部署:所有 ONES 资源统一部署在同一个 Namespace 中。默认 Namespace 为 ones,也支持自定义,详见使用其他 Namespace
  • 内置中间件:MySQL、Kafka、Redis、TiKV 和 ClickHouse 随 ONES 一起部署。
  • 自动创建安装资源:Helm 自动创建 ONES 和内置 MySQL 所需的 CRD、Namespace Scope RBAC 和 PVC,无需分别应用 CRD、RBAC、PVC 清单。
  • Namespace Scope 运行权限:ONES 组件运行时仅使用 Namespace Scope 权限,不需要 Cluster Scope 权限。
  • 声明式交付与 GitOps:安装、升级和配置变更可以通过代码及 YAML 纳入 GitOps 和 CI/CD 流程。非敏感配置通过 values.yaml 管理;密码、Token 等敏感配置通过 Secret/ones-secret-config 管理。
  • 节点调度范围:支持通过节点 Label 或节点名称限定 ONES 工作负载可调度的节点范围, 默认不限制。
  • ResourceQuota 支持:支持在启用了 Namespace ResourceQuota 的 Kubernetes 集群中部署。

默认资源与容量

Helm 集群部署开箱默认配置一般仅能满足 200 人以下的中小型团队约一年的使用需求。以下为 默认容量基础信息:

  • ONES 工作负载:默认运行约 110 个 Pod。由于容器数量较多,CPU Limit 总和约为 160 核、内存 Limit 总和约为 170 GiB(不同版本略有差异)。
  • 内置 MySQL:默认运行 3 个 MySQL 实例,每个实例的 CPU Limit 为 4 核、内存 Limit 为 8 GiB,合计 CPU Limit 为 12 核、内存 Limit 为 24 GiB
  • PVC:默认约 29 个,总容量约为 2206 Gi(不同版本略有差异)。主要的大容量 PVC 包括:
    • 内置 MySQL:7 个 PVC,其中 3 个每个 200 Gi、4 个每个 1 Gi,容量合计约为 604 Gi
    • 附件存储:1 个 PVC,容量为 300 Gi
    • ClickHouse:2 个 PVC,每个容量为 100 Gi
    • TiKV:3 个 PVC,每个容量为 100 Gi
    • Kafka:3 个 PVC,每个容量为 200 Gi

补充说明

  • 内置 MySQL 默认的单实例 4C/8GiB 配置仅支持导入少量数据进行测试。如果需要导入大量 数据,或进行性能测试、压力测试,需要提高 MySQL 的 CPU 和内存上限,并同步调整 MySQL 配置参数。
  • CPU Limit 和内存 Limit 是各容器对应资源上限的累加值,实际运行时各容器通常不会同时 达到上限。200 人以下的中小型团队正常使用时,加上内置 MySQL 后,容器总体资源消耗通常 约为 28 核 CPU 和 100 GiB 内存。
  • ONES 工作负载与内置 MySQL 的 CPU Limit 总和约为 172 核,内存 Limit 总和约为 194 GiB(不同版本略有差异)。如需使用 ResourceQuota 对 Namespace 进行资源限制, 建议默认将 limits.cpu 配置为 200limits.memory 配置为 250Gi
  • 仅用于短期、少量且数据量极少的测试时,可以将 pvcOnesFileVolumeSizepvcMysqlDataVolumeSizeclickhouseDataVolumeSizepvcTidbTikvolumeSizepvcKafkaDataVolumeSize 统一调整为 20Gi。调整后,ONES 其他 PVC 总容量约为 382 Gi, 内置 MySQL 数据 PVC 总容量约为 60 Gi,规划时可按约 450 Gi 评估。
  • 如果需要支持更大的团队规模、数据量或并发量,请在部署前联系 ONES 技术支持进行容量评估, 并调整 Pod 的 CPU、内存上限、PVC 容量及其他相关配置项。

操作步骤

  1. 导入 ONES 和内置 MySQL 镜像。
  2. 配置集群私有化配置。
  3. 创建 Namespace。
  4. 创建敏感配置 Secret。
  5. 安装 ONES。
  6. 观察部署进度并验收。
  7. 网关对接。

准备部署参数

先在终端执行以下命令,根据实际环境准备部署参数。本文后续命令均复用这些参数,请在同一 终端会话中执行:

ONES_VERSION="v7.25.0"
NAMESPACE="ones"
RELEASE_NAME="ones"

HELM_REPO_URL="https://packages.ones.cn/release/helm"

mkdir -p ~/ones
cd ~/ones
  • 全球区域将 HELM_REPO_URL 设置为 https://packages.ones.com/release/helm
  • 使用其他 Namespace 时,只需修改 NAMESPACE;YAML 清单中的 Namespace 也需要保持一致。
  • 标准化工作目录便于统一保存安装配置、资源清单和操作记录,也便于后续排障、备份和升级。

第 1 步:导入 ONES 和内置 MySQL 镜像

  • 生产环境:使用客户私有镜像仓,并在安装前导入目标 ONES 版本的主体镜像和内置 MySQL 镜像。
  • 临时测试:可以直接使用 ONES 公网镜像仓,并跳过本步骤。

注意:ONES 不保证公网镜像仓的可用性,请勿将其用于生产环境。

按照 ONES 镜像导入私有镜像仓中的步骤,根据 Kubernetes 节点 架构导入业务镜像和内置 MySQL 镜像。可以使用预制离线包导入,也可以选择附录中的 Docker 在线导入方式。

镜像导入完成后,返回 ONES 操作目录:

cd ~/ones

第 2 步:配置集群私有化配置

确认当前目录并创建 values.yaml

cd ~/ones
vi ~/ones/values.yaml

写入以下配置:

# Use the multi-replica deployment mode.
onesSystemScale: "common-ha"

# Target Kubernetes node architecture. Supported values: amd64 and arm64.
systemArchitecture: "amd64"

# Deploy and initialize the built-in MySQL automatically.
internalComponentMysqlEnable: true
mysqlManualInitDBEnable: false

# Built-in MySQL resource limits for each MySQL instance.
mysqlCPULimit: "4000m"
mysqlMemoryLimit: "8Gi"

# Optional CPU and memory overrides for containers generated by mysql-operator.
# Empty values preserve the mysql-operator defaults.
mysqlContainerInitCPURequest: "0"
mysqlContainerInitCPULimit: "4000m"
mysqlContainerInitMemoryRequest: "0"
mysqlContainerInitMemoryLimit: "8Gi"
mysqlContainerInitOnlyCPURequest: "0"
mysqlContainerInitOnlyCPULimit: "4000m"
mysqlContainerInitOnlyMemoryRequest: "0"
mysqlContainerInitOnlyMemoryLimit: "8Gi"
mysqlContainerIncrementalRestoreCPURequest: "0"
mysqlContainerIncrementalRestoreCPULimit: "4000m"
mysqlContainerIncrementalRestoreMemoryRequest: "0"
mysqlContainerIncrementalRestoreMemoryLimit: "8Gi"
mysqlContainerCPURequest: "0"
mysqlContainerCPULimit: "4000m"
mysqlContainerMemoryRequest: "0"
mysqlContainerMemoryLimit: "8Gi"
mysqlContainerSidecarCPURequest: "0"
mysqlContainerSidecarCPULimit: "2000m"
mysqlContainerSidecarMemoryRequest: "0"
mysqlContainerSidecarMemoryLimit: "2Gi"
mysqlContainerXbackupServerCPURequest: "0"
mysqlContainerXbackupServerCPULimit: "2000m"
mysqlContainerXbackupServerMemoryRequest: "0"
mysqlContainerXbackupServerMemoryLimit: "2Gi"
mysqlContainerMetricsExporterCPURequest: "0"
mysqlContainerMetricsExporterCPULimit: "100m"
mysqlContainerMetricsExporterMemoryRequest: "0"
mysqlContainerMetricsExporterMemoryLimit: "512Mi"
mysqlContainerPtHeartbeatCPURequest: "0"
mysqlContainerPtHeartbeatCPULimit: "100m"
mysqlContainerPtHeartbeatMemoryRequest: "0"
mysqlContainerPtHeartbeatMemoryLimit: "256Mi"
mysqlContainerFluentdCPURequest: "0"
mysqlContainerFluentdCPULimit: "500m"
mysqlContainerFluentdMemoryRequest: "0"
mysqlContainerFluentdMemoryLimit: "256Mi"
mysqlContainerMasterTakeoverCPURequest: "0"
mysqlContainerMasterTakeoverCPULimit: "200m"
mysqlContainerMasterTakeoverMemoryRequest: "0"
mysqlContainerMasterTakeoverMemoryLimit: "256Mi"
mysqlContainerPtKillCPURequest: "0"
mysqlContainerPtKillCPULimit: "100m"
mysqlContainerPtKillMemoryRequest: "0"
mysqlContainerPtKillMemoryLimit: "256Mi"

# Optional securityContext overrides for containers generated by mysql-operator.
# fsGroup and fsGroupChangePolicy are Pod-level Kubernetes fields.
mysqlContainerInitRunAsUser: "1000"
mysqlContainerInitRunAsGroup: "1000"
mysqlContainerInitOnlyRunAsUser: "1000"
mysqlContainerInitOnlyRunAsGroup: "1000"
mysqlContainerIncrementalRestoreRunAsUser: "1000"
mysqlContainerIncrementalRestoreRunAsGroup: "1000"
mysqlContainerRunAsUser: "1000"
mysqlContainerRunAsGroup: "1000"
mysqlContainerSidecarRunAsUser: "1000"
mysqlContainerSidecarRunAsGroup: "1000"
mysqlContainerXbackupServerRunAsUser: "1000"
mysqlContainerXbackupServerRunAsGroup: "1000"
mysqlContainerMetricsExporterRunAsUser: "1000"
mysqlContainerMetricsExporterRunAsGroup: "1000"
mysqlContainerPtHeartbeatRunAsUser: "1000"
mysqlContainerPtHeartbeatRunAsGroup: "1000"
mysqlContainerFluentdRunAsUser: "1000"
mysqlContainerFluentdRunAsGroup: "1000"
mysqlContainerMasterTakeoverRunAsUser: "1000"
mysqlContainerMasterTakeoverRunAsGroup: "1000"
mysqlContainerPtKillRunAsUser: "1000"
mysqlContainerPtKillRunAsGroup: "1000"
mysqlPodRunAsUser: "1000"
mysqlPodRunAsGroup: "1000"
mysqlPodFSGroup: "1000"
mysqlPodFSGroupChangePolicy: "OnRootMismatch"

# Legacy mysql container ownership settings.
mysqlContainerFsgroup: 1000
# mysqlContainerRunasuser sets the legacy/root-compatible user ID used by the MySQL container.
# When podSecurityContextNonRootEnabled=true, built-in MySQL follows podSecurityContextRunAsUser instead.
mysqlContainerRunasuser: 1000

# Default resource requests and limits for containers without precise rules.
workloadResourceOverrides: |
default.containers.resources.requests.cpu=0
default.containers.resources.limits.cpu=1000m
default.containers.resources.requests.memory=0
default.containers.resources.limits.memory=512Mi
default.initContainers.resources.requests.cpu=0
default.initContainers.resources.limits.cpu=500m
default.initContainers.resources.requests.memory=0
default.initContainers.resources.limits.memory=256Mi

# Database migration resources required when ResourceQuota enforces requests and limits.
migrationContainerCPURequest: "0"
migrationContainerCPULimit: "4000m"
migrationContainerMemoryRequest: "0"
migrationContainerMemoryLimit: "10Gi"
migrationInitContainerCPURequest: "0"
migrationInitContainerCPULimit: "500m"
migrationInitContainerMemoryRequest: "0"
migrationInitContainerMemoryLimit: "128Mi"

# Language and time zone.
defaultLanguage: "zh"
clickhouseTimeZone: "Asia/Shanghai"
projectAPITimezone: "Asia/Shanghai"
timezone: "Asia/Shanghai"

# Optional NodePort for temporary test access. Do not use it as the production gateway.
# accessNodePort: "30011"

# StorageClass used by ONES and built-in middleware PVCs.
storageClassNameForReadWriteMany: "<REPLACE_WITH_RWX_STORAGECLASS>"
storageClassNameForReadWriteManyWithRetain: "<REPLACE_WITH_RWX_RETAIN_STORAGECLASS>"
storageClassNameForReadWriteOnce: "<REPLACE_WITH_RWO_STORAGECLASS>"
storageClassNameForReadWriteOnceWithRetain: "<REPLACE_WITH_RWO_RETAIN_STORAGECLASS>"

# Capacity of each large data PVC.
pvcOnesFileVolumeSize: "300Gi"
pvcMysqlDataVolumeSize: "200Gi"
clickhouseDataVolumeSize: "100Gi"
pvcTidbTikvolumeSize: "100Gi"
pvcKafkaDataVolumeSize: "200Gi"

# Helm creates CRDs, Namespace Scope RBAC, and PVCs.
enableNamespaceAutoCreate: false
enableCRDAutoCreate: true
enableRBACAutoCreate: true
enablePVCAutoReconcile: true
enableLocalStorageAutoCreate: false

需要根据实际环境调整以下配置:

配置项说明
systemArchitectureKubernetes 节点架构,可选 amd64arm64
defaultLanguageONES 默认语言:zhenjadezh-Hant-HK
clickhouseTimeZoneprojectAPITimezonetimezoneONES 服务使用的 IANA 时区,三项填写相同的值
storageClassNameForReadWriteMany支持 ReadWriteMany 的 StorageClass
storageClassNameForReadWriteManyWithRetain支持 ReadWriteMany 且回收策略为 Retain 的 StorageClass
storageClassNameForReadWriteOnce支持 ReadWriteOnce、底层存储介质为 SSD 的 StorageClass
storageClassNameForReadWriteOnceWithRetain支持 ReadWriteOnce、底层存储介质为 SSD,且回收策略为 Retain 的 StorageClass

StorageClass 要求

  • Retain 可以避免误删 PVC 时底层数据被一并清理。
  • storageClassNameForReadWriteOncestorageClassNameForReadWriteOnceWithRetain 必须使用 SSD 介质存储。不建议使用 NFS 代替 ReadWriteOnce StorageClass,否则可能明显影响 I/O 性能。
  • 请确认所选 StorageClass 的访问模式、回收策略、容量和动态制备能力。
  • 存储驱动应支持 fsGroupfsGroupChangePolicy,确保 UID/GID 1000/1000 的容器可以 读写数据卷。
  • 如不明确,请联系 Kubernetes 管理员或存储供应商确认。
  • 执行 kubectl get storageclass 查看集群中的 StorageClass。

当 ResourceQuota 要求每个容器必须配置 CPU、内存 request 和 limit 时,请保留上述迁移容器 资源配置。配置缺失会导致版本升级时 Migration Job 无法创建 Pod。

第 3 步:创建 Namespace

kubectl create namespace "${NAMESPACE}"

如需使用 ResourceQuota,请在安装 ONES 前完成 Namespace 配额配置。

第 4 步:创建敏感配置 Secret

创建 ones-secret-config.yaml

cd ~/ones
vi ~/ones/ones-secret-config.yaml

写入初始团队和镜像仓配置。内置 MySQL 的数据库账号和密码由 ONES 初始化流程自动生成, 无需客户手工创建数据库或执行初始化 SQL。

apiVersion: v1
kind: Secret
metadata:
name: ones-secret-config
namespace: "<填写 ONES Namespace,例如 ones>"
type: Opaque
stringData:
secret.yaml: |
# Initial team configuration.
teamName: "<初始团队名称>"
ownerName: "<初始管理员名称>"
ownerEmail: "<初始管理员邮箱>"
ownerPassword: "<初始管理员密码>"

# Private image registry configuration.
dockerRegistryHost: "registry.example.com"
dockerRegistryUserName: "<私有镜像仓用户名>"
dockerRegistryToken: "<私有镜像仓密码或 Token>"
dockerRegistryBasepathForOnesImage: "/ones/"

配置说明:

  • 初始管理员密码ownerPassword 长度为 8~32 个字符,必须同时包含大写字母、小写字母 和数字,不能包含空格或全角字符。部署完成后可在 ONES 中修改。
  • 镜像路径dockerRegistryBasepathForOnesImage 是私有镜像仓中存放 ONES 镜像的 URL 子路径,必须以 / 开头和结尾,并与第 1 步导入镜像时的 REGISTRY_BASE_PATH 保持一致。

应用 Secret:

kubectl -n "${NAMESPACE}" apply -f ~/ones/ones-secret-config.yaml
kubectl -n "${NAMESPACE}" get secret ones-secret-config

不要将 ones-secret-config.yaml 提交到 Git 仓库或发送到不受控的日志系统。

第 5 步:安装 ONES

5.1 检查客户端、集群和安装权限

kubectl cluster-info
helm version
kubectl auth can-i create customresourcedefinitions.apiextensions.k8s.io
kubectl auth can-i create roles.rbac.authorization.k8s.io --namespace "${NAMESPACE}"
kubectl auth can-i create persistentvolumeclaims --namespace "${NAMESPACE}"

确认命令指向目标生产集群,三个权限检查均返回 yes。Helm 自动创建的 CRD 属于集群级 资源,因此安装账号必须具备 CRD 创建权限。

5.2 添加 Helm 仓库

使用准备部署参数时设置的 Helm 仓库:

helm repo add ones \
"${HELM_REPO_URL}" \
--force-update

helm repo update
helm search repo ones/ones-cluster --versions

确认列表中存在需要安装的 ONES 版本。

5.3 安装指定 ONES 版本

确认安装文件存在:

cd ~/ones
ls -l ~/ones/values.yaml ~/ones/ones-secret-config.yaml
helm install "${RELEASE_NAME}" ones/ones-cluster \
--version "${ONES_VERSION}" \
--namespace "${NAMESPACE}" \
-f ~/ones/values.yaml \
--atomic \
--timeout 30m

本次 Helm 安装会自动创建:

  • ONES 和内置 MySQL 所需的 CRD。
  • ONES、installer-operator 和内置中间件所需的 ServiceAccount、Role、RoleBinding。
  • ONES 和内置中间件所需的 PVC。
  • installer-operator 及其配置、Service 和初始化资源。

无需手工执行 CRD、RBAC 或 PVC Manifest。

第 6 步:观察部署进度并验收

6.1 观察 installer-operator 调度进度

kubectl -n "${NAMESPACE}" logs -f deployment/installer-operator

日志以 [当前步骤/总步骤] 显示 Bootstrap 进度。如果调度失败,查看汇总错误:

kubectl -n "${NAMESPACE}" logs installer-operator-error

修复镜像、StorageClass、PVC 或配额问题后,installer-operator 会重新调度 Bootstrap。

6.2 检查部署结果

helm -n "${NAMESPACE}" status "${RELEASE_NAME}"
kubectl -n "${NAMESPACE}" get pods
kubectl -n "${NAMESPACE}" get pvc

确认 Helm Release 状态正常,PVC 均可被工作负载正常挂载,ONES 工作负载 Pod 均已就绪, 且不存在持续的 CrashLoopBackOffImagePullBackOffPending 状态。随后使用 ownerEmailownerPassword 登录 ONES。

第 7 步:网关对接

7.1 生产环境

access-service:8080 是 ONES 系统的统一访问入口网关。生产环境可以通过 Ingress NGINX、 Istio 等 Kubernetes 网关与该 Service 对接,为 ONES 提供外部访问入口:

access-service:8080

确认 Service:

kubectl -n "${NAMESPACE}" get service access-service

Ingress NGINX 和 Istio 的配置示例见现有 ONES Helm 集群部署说明

7.2 测试环境

临时测试需要从集群外直接访问时,可以向 values.yaml 添加:

accessNodePort: "30011"

安装后添加该配置时,执行:

helm upgrade "${RELEASE_NAME}" ones/ones-cluster \
--version "${ONES_VERSION}" \
--namespace "${NAMESPACE}" \
-f ~/ones/values.yaml \
--atomic \
--timeout 30m

配置生效后,可以通过任一 Kubernetes 节点的 IP 和 30011 端口访问。NodePort 仅用于临时 测试,不作为生产网关。

常见问题

Helm 没有权限创建 CRD

出现 customresourcedefinitions.apiextensions.k8s.io is forbidden 时,说明 Helm 安装账号没有 CRD 创建权限。请由 Kubernetes 集群管理员补充权限后重新安装。

PVC 长时间处于 Pending

检查 PVC、StorageClass 和 CSI 控制器:

PVC_NAME="ones-file-volume-pvc"

kubectl -n "${NAMESPACE}" get pvc
kubectl -n "${NAMESPACE}" describe pvc "${PVC_NAME}"
kubectl get storageclass

常见原因包括 StorageClass 不存在、不支持对应访问模式、动态制备失败或存储容量不足。

Pod 因 ResourceQuota 无法创建

如果 Pod 事件中出现 exceeded quota 或缺少 CPU、内存 limit,检查当前配额和事件:

RESOURCE_QUOTA_NAME="ones-compute-quota"

kubectl -n "${NAMESPACE}" describe resourcequota "${RESOURCE_QUOTA_NAME}"
kubectl -n "${NAMESPACE}" get events --sort-by='.lastTimestamp'

找不到指定 Chart 版本

helm repo update
helm search repo ones/ones-cluster --versions

Helm 提示 Release 名称已存在

helm -n "${NAMESPACE}" status "${RELEASE_NAME}"

已有 Release 需要更新时,不要重复执行 helm install,应使用目标版本对应的 Chart 执行 helm upgrade

附加说明

使用其他 Namespace

准备部署参数时,NAMESPACE 默认设置为 ones。如需改用其他 Namespace,请确保 Namespace、 ResourceQuota、ones-secret-config、Helm --namespace 参数及后续 kubectl 命令均使用相同的 Namespace。

Helm 会自动将 ONES 应用、installer-operatorones-cluster-operator 的 Namespace 配置同步为 Helm Release Namespace,无需在 values.yaml 中重复配置。

Helm 自动创建的 CRD

内置组件模式默认创建以下 CRD:

  • migrations.ones.ai
  • onesclusters.ones.ai
  • mysqlbackups.mysql.presslabs.org
  • mysqlclusters.mysql.presslabs.org

这些 CRD 使用 helm.sh/resource-policy: keep,执行 helm uninstall 时不会自动删除。如需彻底 清理测试环境,请确认 CRD 中没有其他环境正在使用的自定义资源,再由 Kubernetes 管理员处理。