Apache Solr Operator CRD 详解与调谐实测
SolrCloud CRD 核心字段详解(基于 0.9.1 实测 schema)、0→1 部署 SolrCloud 的调谐产物实录、扩容缩容实测,以及 zookeeperRef 新旧 API 迁移与字段校验坑
Apache Solr Operator CRD 详解与调谐实测
目标:以 Solr Operator 0.9.1 实测 schema 为准,详解 SolrCloud CRD 的核心字段;给出 0→1 部署一套 SolrCloud(含托管 ZooKeeper)的完整调谐产物;实测扩容调谐行为;并澄清 0.9 线
zookeeperRefAPI 重构带来的迁移坑。本文所有字段清单均直接取自集群内 CRD schema(kubectl get crd ... -o json),所有操作与回显均实际执行。
一、环境与前置
- Kubernetes:Kind v1.32.0 单节点(部署过程见《Ubuntu 22.04 部署 Apache Solr Operator(Kind 集群)安装指南》)
- Solr Operator 0.9.1 + ZooKeeper Operator 0.2.15,4 个 CRD 已注册:
solrbackups.solr.apache.org
solrclouds.solr.apache.org
solrprometheusexporters.solr.apache.org
zookeeperclusters.zookeeper.pravega.io
- CRD 版本:
v1beta1(Solr 系)与v1beta1(ZooKeeper 系)
二、SolrCloud CRD 核心字段速查(实测 schema)
获取 spec 字段清单:
kubectl get crd solrclouds.solr.apache.org -o json | \
python3 -c "import json,sys; print(sorted(json.load(sys.stdin)['spec']['versions'][0]['schema']['openAPIV3Schema']['properties']['spec']['properties'].keys()))"
实测输出(spec 全部顶层字段):
['additionalLibs', 'availability', 'backupRepositories', 'busyBoxImage',
'customSolrKubeOptions', 'dataStorage', 'replicas', 'scaling',
'solrAddressability', 'solrClientTLS', 'solrGCTune', 'solrImage',
'solrJavaMem', 'solrLogLevel', 'solrModules', 'solrOpts', 'solrSecurity',
'solrTLS', 'solrZkOpts', 'updateStrategy', 'zookeeperRef']
常用字段说明(结合实测行为):
| 字段 | 作用 | 实测默认/备注 |
|---|---|---|
replicas | Solr 节点数 | 本文实测 2→3 扩容 |
zookeeperRef | ZK 连接声明 | 二选一:provided(托管)或 connectionInfo(外接) |
solrImage | Solr 镜像 | 默认 library/solr:8.11(实测 pod spec) |
busyBoxImage | init 容器镜像 | 默认 library/busybox:1.28.0-glibc(实测 pod spec) |
dataStorage | 数据盘(PVC/临时盘) | 默认临时盘(Kind 环境 PVC 需 local-path) |
solrModules | 启用 Solr 模块(如 extraction/analyzers-icu) | 加载进镜像路径并注入 SOLR_MODULES |
solrSecurity | Basic Auth / TLS 认证配置 | 开启后自动创建 Secret 并注入客户端 TLS |
backupRepositories | 备份仓库定义(volume/GCS/S3) | 供 SolrBackup CR 引用 |
updateStrategy | 滚动升级策略 | method/restartSchedule |
solrAddressability | Service 形态(common/headless/external) | 默认 common + headless(实测两者均创建) |
additionalLibs | 额外 jar 挂载 |
2.1 zookeeperRef:0.9 线 API 实测(重要变更)
zookeeperRef 在 0.9.1 中只有两个子字段(实测 schema dump):
zookeeperRef keys: ['connectionInfo', 'provided']
connectionInfo : A zookeeper ensemble that is run independently of the solr operator ...
provided : Create a new Zookeeper Ensemble with the following spec ...
(Requires the zookeeperOperator flag ...)
provided:把 ZK 交给内嵌 ZooKeeper Operator 托管,子字段包括replicas(默认 3)、image、persistence、chroot等(实测 schema keys:['acl','adminServerService','chroot','clientService','config','containers','ephemeral','headlessService','image','initContainers','labels','maxUnavailableReplicas','persistence','probes','readOnlyAcl','replicas','volumeMounts','volumes','zookeeperPodPolicy']);connectionInfo:外接 ZK,填internalConnectionString(集群内可达)/externalConnectionString;- 迁移坑:旧版(0.8 前)的
provisionZookeeperCR、externalConnectionString在 0.9 严格校验下直接报错(实测):
SolrCloud in version "v1beta1" cannot be handled as a SolrCloud:
strict decoding error: unknown field "spec.zookeeperRef.provisionZookeeperCR"
provided的镜像字段是image.repository(ZooKeeper Operator 的 Image 类型),写成image.repo同样报 unknown field(实测踩坑)。
三、0→1 部署 SolrCloud(托管 ZK 模式)
3.1 最小 CR
CR 文件 solrcloud-demo.yaml:
apiVersion: solr.apache.org/v1beta1
kind: SolrCloud
metadata:
name: demo
labels:
app: demo-solrcloud
spec:
replicas: 2
zookeeperRef:
provided:
replicas: 1
image:
repository: pravega/zookeeper
tag: 0.2.15
persistence:
reclaimPolicy: Delete
托管 ZK 的
replicas生产建议 3(默认),演示环境取 1 省资源;persistence.reclaimPolicy: Delete让 PVC 随删除回收。
3.2 apply 与调谐时序
kubectl apply -f solrcloud-demo.yaml
solrcloud.solr.apache.org/demo created
operator 立即执行一系列创建动作(kubectl logs deploy/solr-operator 实测节选,同一秒内):
2026-10-15T05:18:20Z INFO Setting default settings for SolrCloud {"SolrCloud": {"name":"demo",...}}
2026-10-15T05:18:20Z INFO Creating Zookeeer Cluster {"SolrCloud": {"name":"demo",...}}
2026-10-15T05:18:20Z INFO Creating Common Service {"SolrCloud": {"name":"demo",...}}
2026-10-15T05:18:20Z INFO Creating Headless Service {"SolrCloud": {"name":"demo",...}}
2026-10-15T05:18:20Z INFO Creating ConfigMap {"SolrCloud": {"name":"demo",...}}
2026-10-15T05:18:20Z INFO Creating StatefulSet {"SolrCloud": {"name":"demo",...}}
调谐链路(实测归纳):
SolrCloud/demo
├── ZookeeperCluster/demo-solrcloud-zookeeper (zookeeper-operator 接管 → StatefulSet + 3 个 Service)
├── StatefulSet/demo-solrcloud (replicas 个 Solr pod,init 容器复制配置)
├── Service/demo-solrcloud-common (统一读写入口)
├── Service/demo-solrcloud-headless (节点点对点,StatefulSet 域名)
└── ConfigMap/demo-solrcloud-<hash> (solr.xml 等配置)
3.3 就绪验证
$ kubectl get solrcloud demo
NAME VERSION TARGETVERSION DESIREDNODES NODES READYNODES UPTODATENODES
demo 8.11 2 2 2 2
$ kubectl get pods | grep demo
demo-solrcloud-0 1/1 Running 0
demo-solrcloud-1 1/1 Running 0
demo-solrcloud-zookeeper-0 1/1 Running 0
VERSION 8.11:默认 Solr 版本(可用spec.solrImage覆盖);READYNODES:实际就绪节点;UPTODATENODES:与当前 spec 一致的节点(滚动升级时两者会出现差值)。
四、扩容实测:2 → 3
一条 patch 完成(无需改文件重 apply):
kubectl patch solrcloud demo --type=merge -p '{"spec":{"replicas":3}}'
solrcloud.solr.apache.org/demo patched
operator 行为(实测时间线):
$ kubectl get solrcloud demo # patch 3 秒后
NAME VERSION TARGETVERSION DESIREDNODES NODES READYNODES UPTODATENODES
demo 8.11 3 3 2 3
$ kubectl wait --for=condition=Ready pod/demo-solrcloud-2 --timeout=600s
pod/demo-solrcloud-2 condition met
$ kubectl get solrcloud demo
NAME VERSION TARGETVERSION DESIREDNODES NODES READYNODES UPTODATENODES
demo 8.11 3 3 3 3
- 新 pod
demo-solrcloud-2由 StatefulSet 控制器按序创建、operator 注入同样的配置与启动参数,Ready 后自动注册进 ZK 的集群拓扑; - 全程无数据丢失、无手动 join 步骤——这就是 Operator 相对手工 StatefulSet 的核心价值;
- 缩容同理(
replicas改回 2,operator 会先搬移数据再删 pod,生产环境建议配合availability字段控制最低可用节点)。
五、SolrCloud 的 Service 与访问端点
实测创建的 5 个 Service:
service/demo-solrcloud-common ClusterIP 10.96.232.131 # 推荐入口
service/demo-solrcloud-headless ClusterIP None # <pod>.demo-solrcloud-headless.default.svc
service/demo-solrcloud-zookeeper-client ClusterIP 10.96.71.74 # ZK 客户端 :2181
service/demo-solrcloud-zookeeper-headless ClusterIP None
service/demo-solrcloud-zookeeper-admin-server ClusterIP 10.96.212.101
集群内应用连 http://demo-solrcloud-common.default:80;集群外用 kubectl port-forward svc/demo-solrcloud-common 8983:80(数据操作实测见《Apache Solr Operator 数据操作与验证指南》)。
六、字段校验类踩坑速查
| 报错 | 原因 | 解法 |
|---|---|---|
unknown field "spec.zookeeperRef.provisionZookeeperCR" | 0.9 线 API 重构,旧字段删除 | provided(托管)或 connectionInfo(外接) |
unknown field "spec.zookeeperRef.provided.zookeeper" | provided 下字段是平铺的 | 直接写 provided.image/provided.replicas |
operator 反复重启 no matches for kind "ZookeeperCluster" | zk CRD 未注册 | 安装时 --set zookeeper-operator.crd.create=true |
pods 卡 Init:0/1 | busybox init 镜像缺失 | 预注入 library/busybox:1.28.0-glibc 或改 spec.busyBoxImage |
| 想用 Solr 9 | 默认镜像是 8.11 | spec.solrImage: {repository: library/solr, tag: "9.8.1"} |
七、小结
- SolrCloud CRD 的 spec 共 21 个顶层字段,覆盖镜像/存储/网络/安全/升级/备份六大域,本文全部经实测 schema 验证;
- 一个 CR 的调谐产物:ZookeeperCluster + 2 个 StatefulSet + 5 个 Service + ConfigMap,命名前缀统一;
- 扩容实测证明调谐闭环:
kubectl patch一个数字,operator 自动补节点并入集群(DESIREDNODES=READYNODES=3); - 0.9 线务必使用新 zookeeperRef API(provided/connectionInfo),旧字段在严格校验下一律拒绝。