跳到主要内容

ONES Helm 集群部署说明

本文将引导您在 Kubernetes 集群中使用 Helm 完成 ONES 集群部署。

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

当前对外提供的 Helm 安装方式要求如下。

必要条件

  • Kubernetes 版本为 v1.22 或更高版本。
  • ONES 采用集群多副本部署。
  • MySQL 由客户外置提供。

功能特性

  • 单 Namespace 部署:所有 ONES 资源统一部署在同一个 Namespace 中。默认 Namespace 为 ones,也支持自定义,详见使用其他 Namespace
  • Namespace Scope 权限:ONES 组件仅需 Namespace Scope 权限,不需要 Cluster Scope 权限。
  • 资源与权限审批:Namespace、CRD、RBAC 和 PVC 由客户的 Kubernetes 集群管理员创建, 便于纳入客户内部的资源申请和权限审批流程。
  • 数据库变更审批:数据库初始化 SQL 可在执行前由客户 DBA 审核,并纳入客户现有的 数据库变更审批流程。
  • 声明式交付与 GitOps:安装、升级和配置变更均可通过代码及 YAML 声明纳入 GitOps 和 CI/CD 流程。非敏感配置通过 values.yaml 管理;密码、Token 等敏感配置通过 Secret/ones-secret-config 独立管理。
  • 节点调度范围:支持通过节点 Label 或节点名称,限定 ONES 工作负载可调度的节点范围; 默认不限制节点范围。
  • ResourceQuota 支持:支持在启用了 Namespace ResourceQuota 的 Kubernetes 集群中部署。

默认资源与容量

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

  • 外置 MySQL:至少需要 4 vCPU8 GiB 内存和 200 GB 存储空间。
  • ONES 工作负载:默认运行约 110 个 Pod。由于容器数量较多,CPU Limit 总和约为 160 核、内存 Limit 总和约为 170 GiB(不同版本略有差异)。
  • PVC:默认申请约 22 个,总容量约为 1602 Gi(不同版本略有差异)。其中,容量 大于等于 100 Gi 的 PVC 共 9 个,合计约 1400 Gi
    • 附件存储:1 个 PVC,容量为 300 Gi
    • ClickHouse:2 个 PVC,每个容量为 100 Gi
    • TiKV:3 个 PVC,每个容量为 100 Gi
    • Kafka:3 个 PVC,每个容量为 200 Gi

补充说明

  • CPU Limit 和内存 Limit 是各容器对应资源上限的累加值,实际运行时各容器通常不会同时 达到上限。200 人以下的中小型团队正常使用时,容器总体资源消耗通常约为 20 核 CPU 和 80 GiB 内存。
  • 仅用于短期、少量且数据量极少的测试时,可以在创建 PVC 前,将附件存储、ClickHouse、 TiKV 和 Kafka 的单个 PVC 容量调整为 20Gi。调整后,PVC 总容量约为 382Gi,规划时 可按约 400Gi 评估。该配置不适用于生产环境。
  • 外置 MySQL 可用内存较小时,需要由 DBA 根据实际内存调整 MySQL 内存相关参数,避免 MySQL 进程因内存使用超限触发 OOM。
  • 如需使用 ResourceQuota 对 Namespace 进行资源限制,建议默认将 limits.cpu 配置为 200limits.memory 配置为 200Gi

如果需要支持更大的团队规模、数据量或并发量,可以在部署前联系 ONES 技术支持进行容量 评估,并调整 Pod 的 CPU、内存上限、PVC 容量及其他相关配置项;也可以先使用默认配置, 后续遇到资源瓶颈时再进行扩容。

操作步骤

  1. ONES 镜像导入私有仓。
  2. 配置集群私有化配置。
  3. 创建 Namespace。
  4. 创建 ONES CRD 和 RBAC。
  5. 创建 PVC。
  6. 配置并初始化外置数据库。
  7. 安装 ONES。
  8. 观察部署进度并验收。
  9. 网关对接。

准备部署参数

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

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 镜像导入私有仓

  • 生产环境:建议使用客户私有镜像仓。安装前,请按照 ONES 镜像导入私有镜像仓导入所选 ONES 版本需要的全部镜像。
  • 临时测试:可以直接使用 ONES 公网镜像仓,并跳过本步骤。

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

镜像导入完成后,返回 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"

# Disable the built-in MySQL and use a customer-provided database.
internalComponentMysqlEnable: false
mysqlManualInitDBEnable: true

# Keep the configuration supplied by Helm and only generate missing secrets.
initConfigDone: "true"

# 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 PVCs.
storageClassNameForReadWriteMany: "<REPLACE_WITH_RWX_STORAGECLASS>"
storageClassNameForReadWriteManyWithRetain: "<REPLACE_WITH_RWX_RETAIN_STORAGECLASS>"
storageClassNameForReadWriteOnce: "<REPLACE_WITH_RWO_STORAGECLASS>"
storageClassNameForReadWriteOnceWithRetain: "<REPLACE_WITH_RWO_RETAIN_STORAGECLASS>"

# Namespace, CRD, RBAC, and PVC are prepared by the customer administrator.
enableNamespaceAutoCreate: false
enableCRDAutoCreate: false
enableRBACAutoCreate: false
enablePVCAutoReconcile: false

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

配置项说明
systemArchitectureKubernetes 节点架构,可选 amd64arm64
defaultLanguageONES 默认语言:zh(简体中文)、en(English)、ja(日本語)、de(Deutsch)、zh-Hant-HK(繁體中文)
clickhouseTimeZoneprojectAPITimezonetimezoneONES 服务使用的 IANA 时区,三项填写相同的值。例如:Asia/ShanghaiAmerica/New_YorkAsia/TokyoEurope/BerlinAsia/Hong_Kong
storageClassNameForReadWriteMany支持 ReadWriteMany 的 StorageClass
storageClassNameForReadWriteManyWithRetain支持 ReadWriteMany 且回收策略为 Retain 的 StorageClass
storageClassNameForReadWriteOnce支持 ReadWriteOnce、底层存储介质为 SSD 的 StorageClass
storageClassNameForReadWriteOnceWithRetain支持 ReadWriteOnce、底层存储介质为 SSD,且回收策略为 Retain 的 StorageClass

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

补充说明

  • Retain 可以避免误删 PVC 时底层数据被一并清理。

  • storageClassNameForReadWriteOncestorageClassNameForReadWriteOnceWithRetain 必须使用 SSD 介质存储。不建议使用 NFS 代替 ReadWriteOnce StorageClass,否则可能明显影响 I/O 性能。

  • 请确认所选 StorageClass 的访问模式和回收策略;如不明确,请联系 Kubernetes 管理员或 存储供应商。

  • 执行以下命令查看集群中的 StorageClass:

    kubectl get storageclass

第 3 步:创建 Namespace

kubectl create namespace "${NAMESPACE}"

Namespace 资源说明

  • 工作负载规模:默认运行约 110 个 Pod。由于容器数量较多,CPU Limit 总和约为 160 核、内存 Limit 总和约为 170 GiB(不同版本略有差异)。
  • 实际资源消耗:CPU Limit 和内存 Limit 是各容器对应资源上限的累加值,各容器通常不会 同时达到上限。200 人以下的中小型团队正常使用时,总体资源消耗通常约为 20 核 CPU 和 80 GiB 内存。
  • ResourceQuota 建议:如需使用 ResourceQuota 对 Namespace 进行资源限制,建议将 limits.cpu 配置为 200limits.memory 配置为 200Gi

第 4 步:创建 ONES CRD 和 RBAC

创建 ONES CRD 和 Namespace Scope 最小权限 RBAC:

kubectl apply --server-side \
-f "https://packages.ones.cn/release/kubernetes-mainfest/${ONES_VERSION}/ones/common/ones-cluster-crd.yaml"

kubectl -n "${NAMESPACE}" apply \
-f "https://packages.ones.cn/release/kubernetes-mainfest/${ONES_VERSION}/ones/common/ones-cluster-rbac-mini.yaml"

CRD 使用 Server-Side Apply,避免大型 CRD 写入 kubectl.kubernetes.io/last-applied-configuration 注解后超过 Kubernetes 注解大小限制。

确认资源已创建:

kubectl get crd migrations.ones.ai onesclusters.ones.ai
kubectl -n "${NAMESPACE}" get serviceaccount,role,rolebinding

第 5 步:创建 PVC

返回 ONES 操作目录,确保 PVC 清单保存在固定位置:

cd ~/ones

5.1 获取 PVC 清单

curl -fL \
"https://packages.ones.cn/release/kubernetes-mainfest/${ONES_VERSION}/ones/cluster/ones-cluster-pvc.yaml" \
-o ~/ones/ones-cluster-pvc.yaml

查看 PVC 清单:

cat ~/ones/ones-cluster-pvc.yaml

清单开头的 PVC LIST 注释信息列出了 PVC 名称、访问模式、回收策略和容量。如果需要走 内部资源申请流程,可根据该清单申请所需的存储资源。

5.2 替换 StorageClass

编辑 ones-cluster-pvc.yaml

vi ~/ones/ones-cluster-pvc.yaml

使用第 2 步“配置集群私有化配置”中 values.yaml 填写的 StorageClass,替换清单中的 对应占位符:

PVC 清单占位符values.yaml 配置项
__storageClassNameForReadWriteMany__storageClassNameForReadWriteMany
__storageClassNameForReadWriteManyWithRetain__storageClassNameForReadWriteManyWithRetain
__storageClassNameForReadWriteOnce__storageClassNameForReadWriteOnce
__storageClassNameForReadWriteOnceWithRetain__storageClassNameForReadWriteOnceWithRetain

执行以下命令检查。命令无输出表示所有 StorageClass 占位符均已替换:

grep -n '__storageClassName' ~/ones/ones-cluster-pvc.yaml

5.3 创建 PVC

PVC 权限要求

ONES 容器使用 UID/GID 1000/1000 读写数据卷。应用 PVC 清单前,请确认:

  1. 数据卷权限:满足以下任一条件:
    • 数据卷的用户和用户组为 1000:1000,目录权限为 0755
    • 数据卷目录权限为 0777
  2. 存储驱动:支持 Kubernetes 的 fsGroupfsGroupChangePolicy

如果存储驱动不支持上述能力,请联系 Kubernetes 管理员或存储供应商协助配置数据卷权限。

创建 PVC:

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

第 6 步:配置并初始化外置数据库

返回 ONES 操作目录,确保数据库说明、SQL 包和 Secret 配置保存在固定位置:

cd ~/ones

6.1 获取数据库初始化说明

curl -fsSL \
"https://packages.ones.cn/release/${ONES_VERSION}/database/init-database.md" \
-o ~/ones/init-database.md

cat ~/ones/init-database.md

默认获取英文版说明。如需中文版,请将上述 URL 和文件名中的 init-database.md 替换为 init-database-cn.md

init-database.md 包含以下说明:

  1. 下载并审核数据库初始化 SQL 包。
  2. 创建 ones-secret-config.yaml,填写外置数据库连接和账号信息。
  3. 使用配置的密码替换 SQL 密码占位符。
  4. 创建数据库账号、数据库和表,并完成账号授权。

请按照 init-database.md 中的操作说明,完成 ones-secret-config.yaml 的创建和数据库初始化。

6.2 补充初始团队配置和镜像仓配置

编辑上一步创建的 ones-secret-config.yaml

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

stringData.secret.yaml 下追加初始团队配置;使用客户私有镜像仓时,同时追加镜像仓配置:

apiVersion: v1
kind: Secret
metadata:
name: ones-secret-config
namespace: "<填写 ONES Namespace,例如 ones>"
type: Opaque
stringData:
secret.yaml: |
# 此处省略上一步已经填写的 MySQL 配置

# 初始团队配置
teamName: "<初始团队名称>"
ownerName: "<初始管理员名称>"
ownerEmail: "<初始管理员邮箱>"
ownerPassword: "<初始管理员密码>"

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

配置说明:

  • 初始管理员密码ownerPassword 长度为 8~32 个字符,必须同时包含大写字母、 小写字母和数字,不能包含空格或全角字符。部署完成后可在 ONES 中修改。

  • 镜像路径dockerRegistryBasepathForOnesImage 用于指定私有镜像仓中存放 ONES 镜像的 URL 子路径,必须以 / 开头和结尾。

  • 临时测试场景,可使用公网镜像仓:ONES 不保证公网镜像仓的可用性,请勿将其用于生产环境。

    中国区:

        dockerRegistryHost: "registry.ones.cn"
    dockerRegistryUserName: ""
    dockerRegistryToken: ""
    dockerRegistryBasepathForOnesImage: "/ones/"

    全球:

        dockerRegistryHost: "public.ecr.aws"
    dockerRegistryUserName: ""
    dockerRegistryToken: ""
    dockerRegistryBasepathForOnesImage: "/registry.ones.com/"

完成配置后,应用 Secret:

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

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

第 7 步:安装 ONES

数据库初始化完成后,返回 ONES 操作目录,并确认安装所需配置文件存在:

cd ~/ones
ls -l ~/ones/values.yaml ~/ones/ones-secret-config.yaml

7.1 检查客户端和集群

安装机需要能够访问目标 Kubernetes 集群,并已安装 kubectl 和 Helm:

kubectl cluster-info
helm version

执行后确认命令指向目标生产集群。

7.2 添加 Helm 仓库

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

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

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

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

7.3 安装指定 ONES 版本

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

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

8.1 观察 installer-operator 调度进度

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

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

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

修复外部依赖或配置问题后,installer-operator 会重新调度 Bootstrap。

8.2 检查部署结果

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

确认 Helm Release 状态正常,ONES 工作负载 Pod 均已就绪,且不存在持续的 CrashLoopBackOffImagePullBackOffPending 状态。随后使用 ownerEmailownerPassword 登录 ONES,完成许可证和访问入口等后续配置。

第 9 步:网关对接

9.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 的配置示例见附加说明

9.2 测试环境

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

accessNodePort: "30011"

安装前完成配置时,后续执行 helm install 即可生效。ONES 已经安装时,编辑 ~/ones/values.yaml 后执行 helm upgrade

cd ~/ones

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

配置生效后,通过任一 Kubernetes 节点的 IP 和 NodePort 访问:

http://<Kubernetes 节点 IP>:30011

使用前请确认端口 30011 未被占用,并已在防火墙或安全组中放行。NodePort 仅用于临时 测试,不作为生产环境的网关接入方式。

常见问题

Deployment 显示 FailedCreate,但没有创建 Pod

kubectl describe deployment 通常只能看到 ReplicaFailureFailedCreate 等失败摘要, 不会展示 ReplicaSet 创建 Pod 时的完整错误。读取 Deployment Condition 的完整信息:

DEPLOYMENT_NAME="installer-api"
APP_NAME="installer-api"

kubectl -n "${NAMESPACE}" get deployment "${DEPLOYMENT_NAME}" \
-o jsonpath='{range .status.conditions[*]}{.type}{"\t"}{.reason}{"\t"}{.message}{"\n"}{end}'

创建 Pod 是 ReplicaSet 的职责。继续查看 ReplicaSet 事件,可以获得 ResourceQuota、RBAC、 Pod 配置校验等具体错误:

kubectl -n "${NAMESPACE}" describe replicaset -l "app=${APP_NAME}"

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'

确认是否提高了副本数或组件资源上限。资源配置合理但剩余配额不足时,由 Kubernetes 管理员提高 ResourceQuota 后,控制器会重新创建 Pod。

找不到指定 Chart 版本

重新拉取仓库索引并确认需要安装的 ONES_VERSION

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

PVC 长时间处于 Pending

检查 PVC 事件、StorageClass 和 CSI 控制器状态:

PVC_NAME="ones-file-volume-pvc"

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

Helm 提示 Release 名称已存在

先检查已有 Release,不要直接重复执行 helm install

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

已有 Release 需要更新时,使用与目标 ONES 版本配套的 Chart 执行 helm upgrade

附加说明

使用其他 Namespace

本文示例默认使用 ones。如需改用其他 Namespace,请确保 Namespace、ResourceQuota、RBAC、 PVC、ones-secret-config、Helm --namespace 参数及后续 kubectl 命令均使用相同的 Namespace。

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

网关对接示例

以下示例仅说明网关到 access-service:8080 的转发关系。请根据实际环境调整域名、IngressClass、 网关标签及 TLS 证书配置。

使用 Ingress NGINX 对接

在 ONES Namespace 中创建 Ingress,并将后端指向 access-service:8080

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ones
namespace: ones
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "<MAX_UPLOAD_SIZE>"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
spec:
ingressClassName: nginx
tls:
- hosts:
- ones.example.com
secretName: ones-ingress-tls
rules:
- host: ones.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: access-service
port:
number: 8080

ones.example.com 解析到 Ingress Controller 的外部地址,并根据附件上传需求设置 <MAX_UPLOAD_SIZE>。使用其他 Namespace 或 IngressClass 时,修改对应配置。

配置细节见 Ingress NGINX Annotations

使用 Istio 对接

使用 Istio GatewayVirtualService 将请求转发到 access-service:8080

apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: ones-gateway
namespace: ones
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- ones.example.com
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: ones
namespace: ones
spec:
hosts:
- ones.example.com
gateways:
- ones-gateway
http:
- route:
- destination:
host: access-service.ones.svc.cluster.local
port:
number: 8080

ones.example.com 解析到 Istio Ingress Gateway 的外部地址。selector 必须与实际 Istio Ingress Gateway Pod 标签一致;使用其他 Namespace 时,同时修改资源 Namespace 和 Service 完整域名。生产环境还需要按客户的 Istio 网关规范配置 HTTPS 和证书。

配置细节见 Istio Ingress GatewayIstio Secure Gateways