Apache Solr Operator CRD 详解与调谐实测

SolrCloud CRD 核心字段详解(基于 0.9.1 实测 schema)、0→1 部署 SolrCloud 的调谐产物实录、扩容缩容实测,以及 zookeeperRef 新旧 API 迁移与字段校验坑

Apache Solr OperatorSolr OperatorSolrKubernetes2026/10/15

Apache Solr Operator CRD 详解与调谐实测

目标:以 Solr Operator 0.9.1 实测 schema 为准,详解 SolrCloud CRD 的核心字段;给出 0→1 部署一套 SolrCloud(含托管 ZooKeeper)的完整调谐产物;实测扩容调谐行为;并澄清 0.9 线 zookeeperRef API 重构带来的迁移坑。本文所有字段清单均直接取自集群内 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']

常用字段说明(结合实测行为):

字段作用实测默认/备注
replicasSolr 节点数本文实测 2→3 扩容
zookeeperRefZK 连接声明二选一:provided(托管)或 connectionInfo(外接)
solrImageSolr 镜像默认 library/solr:8.11(实测 pod spec)
busyBoxImageinit 容器镜像默认 library/busybox:1.28.0-glibc(实测 pod spec)
dataStorage数据盘(PVC/临时盘)默认临时盘(Kind 环境 PVC 需 local-path)
solrModules启用 Solr 模块(如 extraction/analyzers-icu)加载进镜像路径并注入 SOLR_MODULES
solrSecurityBasic Auth / TLS 认证配置开启后自动创建 Secret 并注入客户端 TLS
backupRepositories备份仓库定义(volume/GCS/S3)供 SolrBackup CR 引用
updateStrategy滚动升级策略method/restartSchedule
solrAddressabilityService 形态(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/1busybox init 镜像缺失预注入 library/busybox:1.28.0-glibc 或改 spec.busyBoxImage
想用 Solr 9默认镜像是 8.11spec.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),旧字段在严格校验下一律拒绝。