From 1a06136bd5ea6fd166d92fdaba26f413034fe1a1 Mon Sep 17 00:00:00 2001 From: Houston Putman Date: Mon, 8 Jun 2026 13:01:49 -0700 Subject: [PATCH 1/7] Set up Antora build for the operator documentation First step toward publishing the operator docs as a component of the Apache Solr Reference Guide: make the docs buildable as an Antora component that contributors can preview locally. - docs/antora.template.yml + generated docs/antora.yml define the 'operator' component. hack/docs/generate_antora_yaml.sh derives the Antora component version from version/version.go so it stays in sync with the operator version without requiring Gradle. - docs/modules/ROOT provides an initial landing page and navigation. - docs/local-playbook.yml plus the new `make docs` target render a local preview using the stock antora/antora image and the Solr Reference Guide UI bundle. - `make check-docs` validates the build (no broken references) and is wired into `make lint`. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitignore | 3 ++ Makefile | 27 +++++++++++- docs/antora.template.yml | 36 ++++++++++++++++ docs/antora.yml | 36 ++++++++++++++++ docs/local-playbook.yml | 56 ++++++++++++++++++++++++ docs/modules/ROOT/nav.adoc | 18 ++++++++ docs/modules/ROOT/pages/index.adoc | 38 ++++++++++++++++ hack/docs/generate_antora_yaml.sh | 69 ++++++++++++++++++++++++++++++ 8 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 docs/antora.template.yml create mode 100644 docs/antora.yml create mode 100644 docs/local-playbook.yml create mode 100644 docs/modules/ROOT/nav.adoc create mode 100644 docs/modules/ROOT/pages/index.adoc create mode 100755 hack/docs/generate_antora_yaml.sh diff --git a/.gitignore b/.gitignore index 54bb6039..212e7122 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,9 @@ generated-check # Integration test outputs tests/**/output +# Locally-built Antora documentation site +docs/build + # Python for the release wizard venv __pycache__ diff --git a/Makefile b/Makefile index c9a1044f..23a3b0bd 100644 --- a/Makefile +++ b/Makefile @@ -228,7 +228,7 @@ smoke-test: build-release-artifacts ## Run a full smoke test on a set of local r check: lint test ## Do all checks, lints and tests for the Solr Operator .PHONY: lint -lint: check-zk-op-version check-mod vet check-format check-licenses check-manifests check-generated check-helm ## Lint the codebase to check for formatting and correctness +lint: check-zk-op-version check-mod vet check-format check-licenses check-manifests check-generated check-helm check-docs ## Lint the codebase to check for formatting and correctness .PHONY: check-format check-format: ## Check the codebase to make sure it adheres to golang standards @@ -329,6 +329,31 @@ helm-deploy-operator: helm-dependency-build docker-build ## Deploy the current v helm install solr-operator helm/solr-operator --set image.version=$(TAG) --set image.repository=$(IMG) --set image.pullPolicy=Never +##@ Documentation + +# Antora image used to build the docs site locally. Pinned to the Antora +# version used by the Apache Solr Reference Guide build (apache/solr). This is +# for local previewing only; the official site is published as an additional +# component of the Reference Guide from the apache/solr repo. +ANTORA_IMAGE ?= antora/antora:3.1.12 + +.PHONY: generate-antora-yaml +generate-antora-yaml: ## Generate docs/antora.yml from version/version.go + ./hack/docs/generate_antora_yaml.sh + +.PHONY: docs +docs: generate-antora-yaml ## Build the operator Antora docs site locally for previewing (requires Docker) + docker run --rm -v "$(PROJECT_DIR):/antora" -w /antora/docs $(ANTORA_IMAGE) --fetch --to-dir build/site local-playbook.yml + @echo "Docs built. Open docs/build/site/index.html in a browser to preview." + +.PHONY: docs-clean +docs-clean: ## Remove the locally-generated documentation site + rm -rf docs/build + +.PHONY: check-docs +check-docs: generate-antora-yaml ## Validate the operator docs build with no broken references (requires Docker) + docker run --rm -v "$(PROJECT_DIR):/antora" -w /antora/docs $(ANTORA_IMAGE) --fetch --log-failure-level=warn --to-dir build/site local-playbook.yml + ##@ Dependencies LOCALBIN ?= $(PROJECT_DIR)/bin $(LOCALBIN): diff --git a/docs/antora.template.yml b/docs/antora.template.yml new file mode 100644 index 00000000..c1b81aea --- /dev/null +++ b/docs/antora.template.yml @@ -0,0 +1,36 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# DO NOT EDIT docs/antora.yml directly -- it is GENERATED from this template +# (docs/antora.template.yml) by `make generate-antora-yaml` +# (hack/docs/generate_antora_yaml.sh), which fills the @...@ tokens below from +# version/version.go. Make documentation/version changes in this template. +name: operator +title: Apache Solr Operator +version: '@ANTORA_VERSION@' +display_version: '@DISPLAY_VERSION@' +@PRERELEASE_LINE@ +start_page: ROOT:index.adoc +nav: + - modules/ROOT/nav.adoc +asciidoc: + attributes: + idseparator: '-' + idprefix: '' + # Full operator version (no leading 'v'), e.g. used in install snippets. + operator-version: '@OPERATOR_VERSION@' + # Link target for the Solr Reference Guide (absolute so it resolves in + # both the local operator-only preview and the combined official site). + solr-ref-guide: 'https://solr.apache.org/guide/solr/latest/' diff --git a/docs/antora.yml b/docs/antora.yml new file mode 100644 index 00000000..9203bee2 --- /dev/null +++ b/docs/antora.yml @@ -0,0 +1,36 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# DO NOT EDIT docs/antora.yml directly -- it is GENERATED from this template +# (docs/antora.template.yml) by `make generate-antora-yaml` +# (hack/docs/generate_antora_yaml.sh), which fills the @...@ tokens below from +# version/version.go. Make documentation/version changes in this template. +name: operator +title: Apache Solr Operator +version: '0_10' +display_version: '0.10-prerelease' +prerelease: -prerelease +start_page: ROOT:index.adoc +nav: + - modules/ROOT/nav.adoc +asciidoc: + attributes: + idseparator: '-' + idprefix: '' + # Full operator version (no leading 'v'), e.g. used in install snippets. + operator-version: '0.10.0' + # Link target for the Solr Reference Guide (absolute so it resolves in + # both the local operator-only preview and the combined official site). + solr-ref-guide: 'https://solr.apache.org/guide/solr/latest/' diff --git a/docs/local-playbook.yml b/docs/local-playbook.yml new file mode 100644 index 00000000..cc07b7de --- /dev/null +++ b/docs/local-playbook.yml @@ -0,0 +1,56 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Local-only Antora playbook for previewing the operator docs component. +# +# This is NOT the official publishing playbook -- the operator is published as +# an additional component of the Apache Solr Reference Guide, whose playbook +# lives in the apache/solr repo (solr/solr-ref-guide). This file just lets a +# contributor render the operator component on its own to preview changes. +# +# Build with: make docs +# +# `make docs` runs the antora/antora image with its working directory set to +# this folder (docs/), so both the current working directory and this +# playbook's directory are the same. Relative paths below are therefore +# resolved against docs/: `url: ..` is the repository git root (where .git +# lives) and the site is written to docs/build/site. Always build via +# `make docs` so the working directory is correct. +site: + title: Apache Solr Operator (local preview) + start_page: operator::index.adoc + +content: + sources: + - url: .. + # HEAD builds the current worktree, including uncommitted changes. + branches: HEAD + start_path: docs + # No "edit this page" links in local preview. + edit_url: false + +ui: + # Reuse the published Solr Reference Guide UI bundle so the local preview + # looks like the real site. Requires network access on first build. + bundle: + url: 'https://nightlies.apache.org/solr/solr-reference-guide-ui-bundle/ui-bundle.zip' + snapshot: true + +output: + clean: true + dir: ./build/site + +runtime: + fetch: true diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc new file mode 100644 index 00000000..e8fa80c4 --- /dev/null +++ b/docs/modules/ROOT/nav.adoc @@ -0,0 +1,18 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +* xref:index.adoc[Introduction] diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc new file mode 100644 index 00000000..6e3bc3fd --- /dev/null +++ b/docs/modules/ROOT/pages/index.adoc @@ -0,0 +1,38 @@ += Apache Solr Operator +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +The Apache Solr Operator is a https://kubernetes.io/docs/concepts/extend-kubernetes/operator/[Kubernetes Operator] that makes it easy to deploy, manage, and scale Apache Solr in a cloud-native environment. + +[NOTE] +==== +This guide is being migrated to Antora. +As pages are migrated they will appear in the navigation menu on the left. +==== + +== What the Operator manages + +The operator provides several Kubernetes Custom Resources (CRDs) for running Solr: + +* *SolrCloud* -- run and manage a complete SolrCloud cluster, including ZooKeeper dependencies, autoscaling, and rolling updates. +* *SolrBackup* -- schedule and manage backups of Solr collections. +* *SolrPrometheusExporter* -- expose Solr metrics to Prometheus for monitoring. + +== Getting started + +To install the operator and run your first SolrCloud, follow the tutorials and operational guides linked from the navigation menu. +For the broader Apache Solr documentation, see the {solr-ref-guide}[Solr Reference Guide]. diff --git a/hack/docs/generate_antora_yaml.sh b/hack/docs/generate_antora_yaml.sh new file mode 100755 index 00000000..27ec6154 --- /dev/null +++ b/hack/docs/generate_antora_yaml.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Generates docs/antora.yml from docs/antora.template.yml, deriving the Antora +# component version from version/version.go. This keeps the Antora version in +# lock-step with the operator version without requiring Gradle (unlike Solr). +# +# v0.10.0 (suffix "") -> version '0_10', display_version '0.10' +# v0.10.0 (suffix "prerelease") -> version '0_10', display_version '0.10-prerelease', prerelease: -prerelease + +set -eu +set -o pipefail + +# Resolve the project root (this script lives in hack/docs/). +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)" + +VERSION_GO="${PROJECT_DIR}/version/version.go" +TEMPLATE="${PROJECT_DIR}/docs/antora.template.yml" +OUTPUT="${PROJECT_DIR}/docs/antora.yml" + +# Parse Version (e.g. v0.10.0) and VersionSuffix (e.g. prerelease) from version.go. +RAW_VERSION="$(grep -E 'Version([[:space:]]+)=' "${VERSION_GO}" | head -1 | sed -E 's/.*["'"'"']([^"'"'"']*)["'"'"'].*/\1/')" +SUFFIX="$(grep -E 'VersionSuffix([[:space:]]+)=' "${VERSION_GO}" | sed -E 's/.*["'"'"']([^"'"'"']*)["'"'"'].*/\1/')" + +# Strip leading 'v' and split into semver parts. +SEMVER="${RAW_VERSION#v}" +IFS='.' read -r MAJOR MINOR PATCH <<< "${SEMVER}" + +ANTORA_VERSION="${MAJOR}_${MINOR}" +DISPLAY_VERSION="${MAJOR}.${MINOR}" +OPERATOR_VERSION="${SEMVER}" + +if [[ -n "${SUFFIX}" ]]; then + DISPLAY_VERSION="${DISPLAY_VERSION}-${SUFFIX}" + PRERELEASE_LINE="prerelease: -${SUFFIX}" +else + PRERELEASE_LINE="" +fi + +# Substitute tokens. Use '|' as the sed delimiter; values contain no '|'. +sed \ + -e "s|@ANTORA_VERSION@|${ANTORA_VERSION}|g" \ + -e "s|@DISPLAY_VERSION@|${DISPLAY_VERSION}|g" \ + -e "s|@OPERATOR_VERSION@|${OPERATOR_VERSION}|g" \ + "${TEMPLATE}" > "${OUTPUT}.tmp" + +# Replace the prerelease placeholder line, or delete it entirely when released. +if [[ -n "${PRERELEASE_LINE}" ]]; then + sed -e "s|@PRERELEASE_LINE@|${PRERELEASE_LINE}|g" "${OUTPUT}.tmp" > "${OUTPUT}" +else + sed -e "/@PRERELEASE_LINE@/d" "${OUTPUT}.tmp" > "${OUTPUT}" +fi +rm -f "${OUTPUT}.tmp" + +echo "Generated ${OUTPUT}: version '${ANTORA_VERSION}' (display '${DISPLAY_VERSION}')" From 99df6ef8f5626f3a7e12e56007fdb401a6b28c3b Mon Sep 17 00:00:00 2001 From: Houston Putman Date: Mon, 8 Jun 2026 13:56:52 -0700 Subject: [PATCH 2/7] Migrate operator docs from Markdown to Antora AsciiDoc Convert the 16 user-facing Markdown docs into the 'operator' Antora component, grouped into modules (getting-started, solr-cloud, solr-backup, solr-prometheus-exporter, upgrade-notes, development), so they can be published alongside the Solr Reference Guide. - All pages converted to AsciiDoc with per-module nav files and the component nav list in antora.template.yml; landing page links to each section via xref. - Inbound links updated from apache.github.io/solr-operator/docs/* to solr.apache.org/guide/operator/latest/* in the top-level README, both helm chart READMEs, and helm/solr/values.yaml. - Release tooling repointed at the new docs: propagate_version.sh now updates the .adoc install snippets and regenerates docs/antora.yml, and the zookeeper-operator version check reads development.adoc. Verified locally with `make check-docs` (no broken references or AsciiDoc warnings). Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 18 +- docs/README.md | 30 - docs/antora.template.yml | 6 + docs/antora.yml | 6 + docs/development.md | 152 ---- docs/known-issues.md | 35 - docs/modules/ROOT/pages/index.adoc | 23 +- docs/modules/development/nav.adoc | 21 + .../development/pages/development.adoc | 164 ++++ .../pages/release-instructions.adoc | 44 + .../pages/upgrading-to-apache.adoc | 177 ++++ docs/modules/getting-started/nav.adoc | 20 + .../pages/local-tutorial.adoc} | 163 ++-- .../pages/running-the-operator.adoc} | 151 ++-- docs/modules/solr-backup/nav.adoc | 19 + .../solr-backup/pages/index.adoc} | 178 ++-- docs/modules/solr-cloud/nav.adoc | 24 + .../solr-cloud/pages/cluster-operations.adoc} | 92 +- .../solr-cloud/pages/dependencies.adoc} | 40 +- .../solr-cloud/pages/index.adoc} | 108 +-- .../solr-cloud/pages/managed-updates.adoc | 118 +++ .../solr-cloud/pages/scaling.adoc} | 96 +- .../solr-cloud/pages/solr-cloud-crd.adoc} | 839 ++++++++++-------- .../modules/solr-prometheus-exporter/nav.adoc | 19 + .../pages/index.adoc} | 218 +++-- docs/modules/upgrade-notes/nav.adoc | 20 + .../upgrade-notes/pages/known-issues.adoc | 36 + .../upgrade-notes/pages/upgrade-notes.adoc | 376 ++++++++ docs/release-instructions.md | 44 - docs/solr-cloud/managed-updates.md | 116 --- docs/upgrade-notes.md | 344 ------- docs/upgrading-to-apache.md | 152 ---- hack/release/version/propagate_version.sh | 15 +- hack/zk-operator/check-version.sh | 4 +- helm/solr-operator/README.md | 2 +- helm/solr/README.md | 18 +- helm/solr/values.yaml | 12 +- 37 files changed, 2149 insertions(+), 1751 deletions(-) delete mode 100644 docs/README.md delete mode 100644 docs/development.md delete mode 100644 docs/known-issues.md create mode 100644 docs/modules/development/nav.adoc create mode 100644 docs/modules/development/pages/development.adoc create mode 100644 docs/modules/development/pages/release-instructions.adoc create mode 100644 docs/modules/development/pages/upgrading-to-apache.adoc create mode 100644 docs/modules/getting-started/nav.adoc rename docs/{local_tutorial.md => modules/getting-started/pages/local-tutorial.adoc} (70%) rename docs/{running-the-operator.md => modules/getting-started/pages/running-the-operator.adoc} (68%) create mode 100644 docs/modules/solr-backup/nav.adoc rename docs/{solr-backup/README.md => modules/solr-backup/pages/index.adoc} (77%) create mode 100644 docs/modules/solr-cloud/nav.adoc rename docs/{solr-cloud/cluster-operations.md => modules/solr-cloud/pages/cluster-operations.adoc} (64%) rename docs/{solr-cloud/dependencies.md => modules/solr-cloud/pages/dependencies.adoc} (79%) rename docs/{solr-cloud/README.md => modules/solr-cloud/pages/index.adoc} (55%) create mode 100644 docs/modules/solr-cloud/pages/managed-updates.adoc rename docs/{solr-cloud/scaling.md => modules/solr-cloud/pages/scaling.adoc} (60%) rename docs/{solr-cloud/solr-cloud-crd.md => modules/solr-cloud/pages/solr-cloud-crd.adoc} (67%) create mode 100644 docs/modules/solr-prometheus-exporter/nav.adoc rename docs/{solr-prometheus-exporter/README.md => modules/solr-prometheus-exporter/pages/index.adoc} (79%) create mode 100644 docs/modules/upgrade-notes/nav.adoc create mode 100644 docs/modules/upgrade-notes/pages/known-issues.adoc create mode 100644 docs/modules/upgrade-notes/pages/upgrade-notes.adoc delete mode 100644 docs/release-instructions.md delete mode 100644 docs/solr-cloud/managed-updates.md delete mode 100644 docs/upgrade-notes.md delete mode 100644 docs/upgrading-to-apache.md diff --git a/README.md b/README.md index e7d6103e..d3a0f36e 100644 --- a/README.md +++ b/README.md @@ -53,17 +53,17 @@ Join us on the [#solr-operator](https://kubernetes.slack.com/messages/solr-opera Please visit the following pages for documentation on using and developing the Solr Operator: -- [Local Tutorial](https://apache.github.io/solr-operator/docs/local_tutorial) +- [Local Tutorial](https://solr.apache.org/guide/operator/latest/getting-started/local-tutorial.html) - [Helm Instructions via Artifact Hub](https://artifacthub.io/packages/helm/apache-solr/solr-operator) - The released helm charts and their instructions should be used for all safe and stable deployments. The charts found in `helm/` are not guaranteed to be compatible with the last stable release, and should only be used for development purposes. -- [Running the Solr Operator](https://apache.github.io/solr-operator/docs/running-the-operator) -- [Known Issues](https://apache.github.io/solr-operator/docs/known-issues) +- [Running the Solr Operator](https://solr.apache.org/guide/operator/latest/getting-started/running-the-operator.html) +- [Known Issues](https://solr.apache.org/guide/operator/latest/upgrade-notes/known-issues.html) - Available Solr Resources - - [Solr Clouds](https://apache.github.io/solr-operator/docs/solr-cloud) - - [Solr Backups](https://apache.github.io/solr-operator/docs/solr-backup) - - [Solr Metrics](https://apache.github.io/solr-operator/docs/solr-prometheus-exporter) -- [Development](https://apache.github.io/solr-operator/docs/development) + - [Solr Clouds](https://solr.apache.org/guide/operator/latest/solr-cloud/index.html) + - [Solr Backups](https://solr.apache.org/guide/operator/latest/solr-backup/index.html) + - [Solr Metrics](https://solr.apache.org/guide/operator/latest/solr-prometheus-exporter/index.html) +- [Development](https://solr.apache.org/guide/operator/latest/development/development.html) ### Examples @@ -71,9 +71,9 @@ Example uses of each CRD have been [provided](https://apache.github.io/solr-oper ## Version Compatibility & Upgrade Notes -Make sure to check the [Solr Operator Upgrade notes](docs/upgrade-notes.md), before upgrading the Solr Operator or CRDs in your Kubernetes cluster. +Make sure to check the [Solr Operator Upgrade notes](https://solr.apache.org/guide/operator/latest/upgrade-notes/upgrade-notes.html), before upgrading the Solr Operator or CRDs in your Kubernetes cluster. -This page also contains [Version Compatibility Matrixes](docs/upgrade-notes.md#version-compatibility-matrixes), which detail the compatible Solr versions and Kubernetes versions for each release of the Solr Operator. +This page also contains [Version Compatibility Matrixes](https://solr.apache.org/guide/operator/latest/upgrade-notes/upgrade-notes.html#version-compatibility-matrixes), which detail the compatible Solr versions and Kubernetes versions for each release of the Solr Operator. ## Contributions diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 980fca11..00000000 --- a/docs/README.md +++ /dev/null @@ -1,30 +0,0 @@ - - -# Documentation - -Please visit the following pages for documentation on using and developing the Solr Operator: - -- [Local Tutorial](local_tutorial.md) -- [Upgrade Notes](upgrade-notes.md) -- [Known Issues](known-issues.md) -- [Running the Solr Operator](running-the-operator.md) -- Available Solr Resources - - [Solr Clouds](solr-cloud) - - [Solr Backups](solr-backup) - - [Solr Metrics](solr-prometheus-exporter) -- [Development](development.md) \ No newline at end of file diff --git a/docs/antora.template.yml b/docs/antora.template.yml index c1b81aea..74bb7278 100644 --- a/docs/antora.template.yml +++ b/docs/antora.template.yml @@ -25,6 +25,12 @@ display_version: '@DISPLAY_VERSION@' start_page: ROOT:index.adoc nav: - modules/ROOT/nav.adoc + - modules/getting-started/nav.adoc + - modules/solr-cloud/nav.adoc + - modules/solr-backup/nav.adoc + - modules/solr-prometheus-exporter/nav.adoc + - modules/upgrade-notes/nav.adoc + - modules/development/nav.adoc asciidoc: attributes: idseparator: '-' diff --git a/docs/antora.yml b/docs/antora.yml index 9203bee2..a3b28649 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -25,6 +25,12 @@ prerelease: -prerelease start_page: ROOT:index.adoc nav: - modules/ROOT/nav.adoc + - modules/getting-started/nav.adoc + - modules/solr-cloud/nav.adoc + - modules/solr-backup/nav.adoc + - modules/solr-prometheus-exporter/nav.adoc + - modules/upgrade-notes/nav.adoc + - modules/development/nav.adoc asciidoc: attributes: idseparator: '-' diff --git a/docs/development.md b/docs/development.md deleted file mode 100644 index cf9907c1..00000000 --- a/docs/development.md +++ /dev/null @@ -1,152 +0,0 @@ - - -# Developing the Solr Operator - -This page details the steps for developing the Solr Operator, and all necessary steps to follow before creating a PR to the repo. - - - [Setup](#setup) - - [Setup Docker for Mac with K8S](#setup-docker-for-mac-with-k8s-with-an-ingress-controller) - - [Install the necessary Dependencies](#install-the-necessary-dependencies) - - [Build the Solr CRDs](#build-the-solr-crds) - - [Build and Run the Solr Operator](#build-and-run-local-versions) - - [Build the Solr Operator](#building-the-solr-operator) - - [Running the Solr Operator](#running-the-solr-operator) - - [Steps to take before creating a PR](#before-you-create-a-pr) - -## Setup - -### Install a newer version of Bash - -If you are running on a Mac, you need to download a newer version of bash and have it used as your default version of bash. -An easy way to do this is via Homebrew. - -### Setup Docker for Mac with K8S with an Ingress Controller - -Please follow the instructions from the [local tutorial](local_tutorial.md#setup-docker-for-mac-with-k8s). - -### Install the necessary dependencies - -Install the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator), which this operator depends on by default. -It is optional, however, as described in the [Zookeeper Reference](solr-cloud/solr-cloud-crd.md#zookeeper-reference) section in the CRD docs. - -```bash -helm repo add pravega https://charts.pravega.io -helm install zookeeper-operator pravega/zookeeper-operator --version 0.2.15 -``` - -Install necessary dependencies for building and deploying the operator. -```bash -export PATH="$PATH:$GOPATH/bin" # You likely want to add this line to your ~/.bashrc or ~/.bash_aliases -make install-dependencies -``` - -Note: if you have previously installed/older versions of dependencies, you can first clear these dependencies with: -```bash -make clean -``` - -## Build the Solr CRDs - -If you have changed anything in the [APIs directory](/api/v1beta1), you will need to run the following command to regenerate all Solr CRDs. - -```bash -make manifests -``` - -In order to apply these CRDs to your kube cluster, merely run the following: - -```bash -make install -``` - -## Build and Run local versions - -It is very useful to build and run your local version of the operator to test functionality. - -### Building the Solr Operator - -#### Building a Go binary - -Building the Go binary files is quite straightforward: - -```bash -make build -``` - -This is useful for testing that your code builds correctly, as well as using the `make run` command detailed below. - -#### Building the Docker image - -Building and releasing a test operator image with a custom Docker namespace. - -```bash -REPOSITORY=your-repository make docker-build docker-push -``` - -You can control the repository and version for your solr-operator docker image via the ENV variables: -- `REPOSITORY` - defaults to `apache`. This can also include the docker repository information for private repos. -- `NAME` - defaults to `solr-operator`. -- `TAG` - defaults to the full branch version (e.g. `v0.3.0-prerelease`). For github tags, this value will be the release version. -You can check what version you are using by running `make tag`, you can check your version with `make version`. - -The image will be created under the tag `$(REPOSITORY)/$(NAME):$(TAG)` as well as `$(REPOSITORY)/$(NAME):latest`. - - -### Running the Solr Operator - -There are a few options for running the Solr Operator version you are developing. - -- You can deploy the Solr Operator by using our provided [Helm Chart](/helm/solr-operator/README.md). -You will need to [build a docker image](#building-the-docker-image) for your version of the operator. -Then update the values for the helm chart to use the version that you have built. -- There are two useful `make` commands provided to help with running development versions of the operator: - - `make run` - This command will start the solr-operator process locally (not within kubernetes). - This does not require building a docker image. - - `make deploy` - This command will apply the docker image with your local version to your kubernetes cluster. - This requires [building a docker image](#building-the-docker-image). - -**Warning**: If you are running kubernetes locally and do not want to push your image to docker hub or a private repository, you will need to set the `imagePullPolicy: Never` on your Solr Operator Deployment. -That way Kubernetes does not try to pull your image from whatever repo it is listed under (or docker hub by default). - -## Testing - -If you are creating new functionality for the operator, please include that functionality in an existing test or a new test before creating a PR. -Most tests can be found in the [controller](/controllers) directory, with names that end in `_test.go`. - -PRs will automatically run the unit tests, and will block merging if the tests fail. - -You can run these tests locally via the following make command: - -```bash -make test -``` - -## Before you create a PR - -The github actions will auto-check that linting is successful on your PR. -To make sure that the linting will succeed, run the following command before committing. - -```bash -make prepare -``` - -Make sure that you have updated the go.mod file: - -```bash -make mod-tidy -``` diff --git a/docs/known-issues.md b/docs/known-issues.md deleted file mode 100644 index 3fc527c3..00000000 --- a/docs/known-issues.md +++ /dev/null @@ -1,35 +0,0 @@ - - -# Known Issues - -## Solr Cloud - -- You may be seeing timeouts in your Solr logs after a rolling update. - This can be caused by DNS caching in CoreDNS (the default DNS for Kubernetes). - This can be fixed by reducing the kubernetes cache TTL to 5-10 seconds. - Please refer to this ticket for more information: https://github.com/kubernetes/kubernetes/issues/92559 - \ - Fix: In the `kube-system` namespace, there will be a `ConfigMap` with name `coredns`. It will contain a section: - ``` - kubernetes cluster.local in-addr.arpa ip6.arpa { - ... - ttl 30 - ... - } - ``` - Edit the `ttl` value to be `5`, CoreDNS will automatically see a change in the configMap and reload it. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 6e3bc3fd..8169bafb 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -18,21 +18,22 @@ The Apache Solr Operator is a https://kubernetes.io/docs/concepts/extend-kubernetes/operator/[Kubernetes Operator] that makes it easy to deploy, manage, and scale Apache Solr in a cloud-native environment. -[NOTE] -==== -This guide is being migrated to Antora. -As pages are migrated they will appear in the navigation menu on the left. -==== +== Getting started + +* xref:getting-started:local-tutorial.adoc[] -- run Solr on Kubernetes locally, end to end. +* xref:getting-started:running-the-operator.adoc[] -- install and configure the operator. -== What the Operator manages +== Managing Solr The operator provides several Kubernetes Custom Resources (CRDs) for running Solr: -* *SolrCloud* -- run and manage a complete SolrCloud cluster, including ZooKeeper dependencies, autoscaling, and rolling updates. -* *SolrBackup* -- schedule and manage backups of Solr collections. -* *SolrPrometheusExporter* -- expose Solr metrics to Prometheus for monitoring. +* xref:solr-cloud:index.adoc[Solr Clouds] -- run and manage a complete SolrCloud cluster, including ZooKeeper dependencies, autoscaling, and rolling updates. +* xref:solr-backup:index.adoc[Solr Backups] -- schedule and manage backups of Solr collections. +* xref:solr-prometheus-exporter:index.adoc[Solr Metrics] -- expose Solr metrics to Prometheus for monitoring. -== Getting started +== Reference + +* xref:upgrade-notes:upgrade-notes.adoc[] and xref:upgrade-notes:known-issues.adoc[]. +* xref:development:development.adoc[] -- build, test, and contribute to the operator. -To install the operator and run your first SolrCloud, follow the tutorials and operational guides linked from the navigation menu. For the broader Apache Solr documentation, see the {solr-ref-guide}[Solr Reference Guide]. diff --git a/docs/modules/development/nav.adoc b/docs/modules/development/nav.adoc new file mode 100644 index 00000000..bd7492db --- /dev/null +++ b/docs/modules/development/nav.adoc @@ -0,0 +1,21 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +.Development +* xref:development.adoc[] +* xref:release-instructions.adoc[] +* xref:upgrading-to-apache.adoc[] diff --git a/docs/modules/development/pages/development.adoc b/docs/modules/development/pages/development.adoc new file mode 100644 index 00000000..8f8cd7c7 --- /dev/null +++ b/docs/modules/development/pages/development.adoc @@ -0,0 +1,164 @@ += Developing the Solr Operator +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +This page details the steps for developing the Solr Operator, and all necessary steps to follow before creating a PR to the repo. + +* <> +** <> +** <> +* <> +* <> +** <> +** <> +* <> + +== Setup + +=== Install a newer version of Bash + +If you are running on a Mac, you need to download a newer version of bash and have it used as your default version of bash. +An easy way to do this is via Homebrew. + +=== Setup Docker for Mac with K8S with an Ingress Controller + +Please follow the instructions from the xref:getting-started:local-tutorial.adoc#setup-docker-for-mac-with-k8s[local tutorial]. + +=== Install the necessary dependencies + +Install the https://github.com/pravega/zookeeper-operator[Zookeeper Operator], which this operator depends on by default. +It is optional, however, as described in the xref:solr-cloud:solr-cloud-crd.adoc#zookeeper-reference[Zookeeper Reference] section in the CRD docs. + +[source,bash] +---- +helm repo add pravega https://charts.pravega.io +helm install zookeeper-operator pravega/zookeeper-operator --version 0.2.15 +---- + +Install necessary dependencies for building and deploying the operator. + +[source,bash] +---- +export PATH="$PATH:$GOPATH/bin" # You likely want to add this line to your ~/.bashrc or ~/.bash_aliases +make install-dependencies +---- + +Note: if you have previously installed/older versions of dependencies, you can first clear these dependencies with: + +[source,bash] +---- +make clean +---- + +== Build the Solr CRDs + +If you have changed anything in the https://github.com/apache/solr-operator/blob/main/api/v1beta1[APIs directory], you will need to run the following command to regenerate all Solr CRDs. + +[source,bash] +---- +make manifests +---- + +In order to apply these CRDs to your kube cluster, merely run the following: + +[source,bash] +---- +make install +---- + +== Build and Run local versions + +It is very useful to build and run your local version of the operator to test functionality. + +=== Building the Solr Operator + +==== Building a Go binary + +Building the Go binary files is quite straightforward: + +[source,bash] +---- +make build +---- + +This is useful for testing that your code builds correctly, as well as using the `make run` command detailed below. + +==== Building the Docker image + +Building and releasing a test operator image with a custom Docker namespace. + +[source,bash] +---- +REPOSITORY=your-repository make docker-build docker-push +---- + +You can control the repository and version for your solr-operator docker image via the ENV variables: + +* `REPOSITORY` - defaults to `apache`. This can also include the docker repository information for private repos. +* `NAME` - defaults to `solr-operator`. +* `TAG` - defaults to the full branch version (e.g. `v0.3.0-prerelease`). For github tags, this value will be the release version. + +You can check what version you are using by running `make tag`, you can check your version with `make version`. + +The image will be created under the tag `$(REPOSITORY)/$(NAME):$(TAG)` as well as `$(REPOSITORY)/$(NAME):latest`. + +=== Running the Solr Operator + +There are a few options for running the Solr Operator version you are developing. + +* You can deploy the Solr Operator by using our provided https://github.com/apache/solr-operator/blob/main/helm/solr-operator/README.md[Helm Chart]. +You will need to <> for your version of the operator. +Then update the values for the helm chart to use the version that you have built. +* There are two useful `make` commands provided to help with running development versions of the operator: +** `make run` - This command will start the solr-operator process locally (not within kubernetes). +This does not require building a docker image. +** `make deploy` - This command will apply the docker image with your local version to your kubernetes cluster. +This requires <>. + +WARNING: If you are running kubernetes locally and do not want to push your image to docker hub or a private repository, you will need to set the `imagePullPolicy: Never` on your Solr Operator Deployment. +That way Kubernetes does not try to pull your image from whatever repo it is listed under (or docker hub by default). + +== Testing + +If you are creating new functionality for the operator, please include that functionality in an existing test or a new test before creating a PR. +Most tests can be found in the https://github.com/apache/solr-operator/blob/main/controllers[controller] directory, with names that end in `_test.go`. + +PRs will automatically run the unit tests, and will block merging if the tests fail. + +You can run these tests locally via the following make command: + +[source,bash] +---- +make test +---- + +== Before you create a PR + +The github actions will auto-check that linting is successful on your PR. +To make sure that the linting will succeed, run the following command before committing. + +[source,bash] +---- +make prepare +---- + +Make sure that you have updated the go.mod file: + +[source,bash] +---- +make mod-tidy +---- diff --git a/docs/modules/development/pages/release-instructions.adoc b/docs/modules/development/pages/release-instructions.adoc new file mode 100644 index 00000000..3ef5d1a4 --- /dev/null +++ b/docs/modules/development/pages/release-instructions.adoc @@ -0,0 +1,44 @@ += Releasing a New Version of the Solr Operator +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +This page details the steps for releasing new versions of the Solr Operator. + +* <> +* <> + +== Versioning + +The Solr Operator follows kubernetes conventions with versioning with is: + +`v..` + +For example `v0.2.5` or `v1.3.4`. +Certain systems except versions that do not start with `v`, such as Helm. +However the tooling has been created to automatically make these changes when necessary, so always include the prefixed `v` when following these instructions. + +== Release Wizard + +Run the release wizard from the root of the repo on the branch that you want to make the release from. + +[source,bash] +---- +./hack/release/wizard/releaseWizard.py +---- + +Make sure to install all necessary programs and follow all steps. +If there is any confusion, it is best to reach out on slack or the mailing lists before continuing. diff --git a/docs/modules/development/pages/upgrading-to-apache.adoc b/docs/modules/development/pages/upgrading-to-apache.adoc new file mode 100644 index 00000000..b1a82eaa --- /dev/null +++ b/docs/modules/development/pages/upgrading-to-apache.adoc @@ -0,0 +1,177 @@ += Upgrading the Solr Operator from Bloomberg to Apache +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +Please read the guide fully before attempting to upgrade your system. + +== Guide + +There are many ways of managing what runs in your Kubernetes cluster. +Therefore, we cannot give one definitive way of upgrading the Solr Operator and the Solr resources in your Cluster. + +Below are guides based on how to upgrade, depending on the type of management that you use. +Please look through all the instructions to see what will work best for your setup. + +== If you manage your cluster declaratively + +If you have an external system managing your cluster (e.g. Ansible, Helm, etc), then the steps you take to upgrade the Solr Operator may be very different. + +. Make sure your system is installing the `v0.3.0` version of the Solr Operator, through the https://artifacthub.io/packages/helm/apache-solr/solr-operator[Helm chart], or other means. +. Make sure your system is <>. +. Make sure the Solr resources you are installing are using the new `solr.apache.org` group and not `solr.bloomberg.com`. +. Check if the Solr resources you are managing use any fields deprecated in `v0.2.x` versions, you can check for these in the xref:upgrade-notes:upgrade-notes.adoc#upgrade-warnings-and-notes[Upgrade Notes]. ++ +-- +If your resources contain these fields, replace them with their new locations. +Otherwise, your `kubectl apply` commands will fail when using the `solr.apache.org` CRDs. +-- + +Once you have made sure that your declarative system is checked for the above points, you can run it to install the new version of the Solr Operator and all of your new CRDs. + +Now you need to delete all the old `solr.bloomberg.com` resources & operator. + +. Remove the `v0.2.x` version of the Solr Operator that is running, unless you merely upgraded your existing deployment to `v0.3.0`. +. <> that the Solr Resources may contain, in all namespaces that you run Solr resources in. +. <>, as they are no longer needed when running the `v0.3.0` version of the Solr Operator. + +== If you manually manage your cluster + +If you manually manage your cluster, then the instructions below will allow you to upgrade in-place. + +. Make sure you have the latest Apache Solr Operator helm charts (If you use helm to deploy the Solr Operator) ++ +[source,bash] +---- +helm repo add apache-solr https://solr.apache.org/charts +helm repo update +---- +. Upgrade to `v0.2.8`, if you are running a version lower. ++ +-- +If your Solr Operator deployment is managed with a Helm chart, merely upgrade your helm chart to version `0.2.8` +-- +. Install the v0.2.8 Solr Operator CRDs ++ +[source,bash] +---- +kubectl replace -f "https://solr.apache.org/operator/downloads/crds/v0.2.8/all.yaml" +---- ++ +_The Upgrade Notes page says to always upgrade CRDs before upgrading the operator, however for this single upgrade case this order is safer._ +. _If you are using the ZK Operator_ ++ +<>. +. Install the Apache Solr CRDs ++ +[source,bash] +---- +kubectl create -f "https://solr.apache.org/operator/downloads/crds/v0.3.0/all.yaml" +---- ++ +_If you are using the ZK Operator_ ++ +[source,bash] +---- +kubectl create -f "https://solr.apache.org/operator/downloads/crds/v0.3.0/all-with-dependencies.yaml" || \ + kubectl replace -f "https://solr.apache.org/operator/downloads/crds/v0.3.0/all-with-dependencies.yaml" +---- +. Install the Apache Solr Operator ++ +[source,bash] +---- +helm install apache apache-solr/solr-operator --version 0.3.0 +---- +. Convert `solr.bloomberg.com` resources into `solr.apache.org` resources: ++ +[source,bash] +---- +# First make sure that "yq" is installed +kubectl get solrclouds.solr.bloomberg.com --all-namespaces -o yaml | \ + sed "s#solr.bloomberg.com#solr.apache.org#g" | \ + yq eval 'del(.items.[].metadata.annotations."kubectl.kubernetes.io/last-applied-configuration", .items.[].metadata.managedFields, .items.[].metadata.resourceVersion, .items.[].metadata.creationTimestamp, .items.[].metadata.generation, .items.[].metadata.selfLink, .items.[].metadata.uid, .items.[].spec.solrPodPolicy, .items.[].spec.zookeeperRef.provided.image.tag, .items.[].status)' - \ + | kubectl apply -f - +kubectl get solrprometheusexporters.solr.bloomberg.com --all-namespaces -o yaml | \ + sed "s#solr.bloomberg.com#solr.apache.org#g" | \ + yq eval 'del(.items.[].metadata.annotations."kubectl.kubernetes.io/last-applied-configuration", .items.[].metadata.managedFields, .items.[].metadata.resourceVersion, .items.[].metadata.creationTimestamp, .items.[].metadata.generation, .items.[].metadata.selfLink, .items.[].metadata.uid, .items.[].spec.podPolicy, .items.[].status)' - \ + | kubectl apply -f - +kubectl get solrbackups.solr.bloomberg.com --all-namespaces -o yaml | \ + sed "s#solr.bloomberg.com#solr.apache.org#g" | \ + yq eval 'del(.items.[].metadata.annotations."kubectl.kubernetes.io/last-applied-configuration", .items.[].metadata.managedFields, .items.[].metadata.resourceVersion, .items.[].metadata.creationTimestamp, .items.[].metadata.generation, .items.[].metadata.selfLink, .items.[].metadata.uid, .items.[].status)' - \ + | kubectl apply -f - +---- +. Delete the `v0.2.8` Solr Operator deployment: ++ +[source,bash] +---- +# If solr-operator is the name of your v0.2.8 Solr Operator deployment +helm delete solr-operator +---- +. <> that the Solr Resources may contain, in all namespaces that you run Solr resources in. +. <>, as they are no longer needed when running the `v0.3.0` version of the Solr Operator. +. Test to make sure that your Solr resources exist as apache resources now and your `StatefulSets`/`Deployments` are still running correctly. + +== Other Considerations + +=== Zookeeper Operator Upgrade + +The https://github.com/pravega/zookeeper-operator[Zookeeper Operator] version that the Solr Operator requires has changed between `v0.2.6` and `v0.3.0`. +Therefore, the Zookeeper Operator needs to be upgraded to `v0.2.9` when the Solr Operator is upgraded to `v0.3.0`. + +==== Removing the old Zookeeper Operator resources + +If you use the Solr Operator https://artifacthub.io/packages/helm/apache-solr/solr-operator[Helm chart], then the correct version of the Zookeeper Operator will be deployed when upgrading. +However, you will need to pre-emptively delete some Kubernetes resources so that they can be managed by Helm. + +_Only use the below `kubectl` commands if you installed the Zookeeper Operator using the URL provided in the Solr Operator repository._ +If you already have a `v0.2.9` Zookeeper Operator running, ignore this and pass the following options when installing the Solr Operator: +`--set zookeeper-operator.install=false --set zookeeper-operator.use=true` + +[source,bash] +---- +kubectl delete deployment zk-operator +kubectl delete clusterrolebinding zookeeper-operator-cluster-role-binding +kubectl delete clusterrole zookeeper-operator +kubectl delete serviceaccount zookeeper-operator +---- + +You will then be able to install the Solr Operator & dependency CRDs, and the Solr Operator Helm Chart. + +=== Remove Solr Resource Finalizers + +It is necessary to remove any finalizers that the old `solr.bloomberg.com` resources may have, otherwise they will not be able to be deleted. +You should do this for all namespaces that you are running solr resources in. + +IMPORTANT: Only run these after stopping any `v0.2.x` Solr Operator that may be running in the Kubernetes cluster. + +[source,bash] +---- +kubectl get solrcollections.solr.bloomberg.com -o name | sed -e 's/.*\///g' | xargs -I {} kubectl patch solrcollections.solr.bloomberg.com {} --type='json' -p='[{"op": "remove", "path": "/metadata/finalizers/0"}]' +kubectl get solrcollectionaliases.solr.bloomberg.com -o name | sed -e 's/.*\///g' | xargs -I {} kubectl patch solrcollectionaliases.solr.bloomberg.com {} --type='json' -p='[{"op": "remove", "path": "/metadata/finalizers/0"}]' +kubectl get solrclouds.solr.bloomberg.com -o name | sed -e 's/.*\///g' | xargs -I {} kubectl patch solrclouds.solr.bloomberg.com {} --type='json' -p='[{"op": "remove", "path": "/metadata/finalizers/0"}]' +---- + +=== Remove Bloomberg Solr CRDs + +After you have <>, you can remove all `solr.bloomberg.com` CRDs. + +If you don't want to disrupt any Solr service that is running, make sure that all Solr resources have been upgraded from `solr.bloomberg.com` CRDs to `solr.apache.org` CRDs. +This command will delete all `solr.bloomberg.com` resources, which means that only resources that exist as `solr.apache.org` will continue to run afterwards. + +[source,bash] +---- +kubectl delete crd solrclouds.solr.bloomberg.com solrprometheusexporters.solr.bloomberg.com solrbackups.solr.bloomberg.com solrcollections.solr.bloomberg.com solrcollectionaliases.solr.bloomberg.com +---- diff --git a/docs/modules/getting-started/nav.adoc b/docs/modules/getting-started/nav.adoc new file mode 100644 index 00000000..b654570d --- /dev/null +++ b/docs/modules/getting-started/nav.adoc @@ -0,0 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +.Getting Started +* xref:local-tutorial.adoc[] +* xref:running-the-operator.adoc[] diff --git a/docs/local_tutorial.md b/docs/modules/getting-started/pages/local-tutorial.adoc similarity index 70% rename from docs/local_tutorial.md rename to docs/modules/getting-started/pages/local-tutorial.adoc index ba1743d1..172f998a 100644 --- a/docs/local_tutorial.md +++ b/docs/modules/getting-started/pages/local-tutorial.adoc @@ -1,41 +1,41 @@ - - -# Solr on Kubernetes on local Mac += Solr on Kubernetes on local Mac +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. This tutorial shows how to setup Solr under Kubernetes on your local mac. The plan is as follows: - 1. [Setup Kubernetes and Dependencies](#setup-kubernetes-and-dependencies) - 1. [Setup Docker for Mac with K8S](#setup-docker-for-mac-with-k8s) - 2. [Install an Ingress Controller to reach the cluster on localhost](#install-an-ingress-controller) - 3. [Install Solr Operator](#install-the-solr-operator) - 4. [Start your Solr cluster](#start-an-example-solr-cloud-cluster) - 5. [Create a collection and index some documents](#create-a-collection-and-index-some-documents) - 6. [Scale from 3 to 5 nodes](#scale-from-3-to-5-nodes) - 1. [Using the Horizontal Pod Autoscaler](#horizontal-pod-autoscaler-hpa) - 7. [Upgrade to newer Solr version](#upgrade-to-newer-version) - 8. [Install Kubernetes Dashboard (optional)](#install-kubernetes-dashboard-optional) - 9. [Delete the solrCloud cluster named 'example'](#delete-the-solrcloud-cluster-named-example) +. xref:getting-started:local-tutorial.adoc#setup-kubernetes-and-dependencies[Setup Kubernetes and Dependencies] +.. xref:getting-started:local-tutorial.adoc#setup-docker-for-mac-with-k8s[Setup Docker for Mac with K8S] +.. xref:getting-started:local-tutorial.adoc#install-an-ingress-controller[Install an Ingress Controller to reach the cluster on localhost] +. xref:getting-started:local-tutorial.adoc#install-the-solr-operator[Install Solr Operator] +. xref:getting-started:local-tutorial.adoc#start-an-example-solr-cloud-cluster[Start your Solr cluster] +. xref:getting-started:local-tutorial.adoc#create-a-collection-and-index-some-documents[Create a collection and index some documents] +. xref:getting-started:local-tutorial.adoc#scale-from-3-to-5-nodes[Scale from 3 to 5 nodes] +.. xref:getting-started:local-tutorial.adoc#horizontal-pod-autoscaler-hpa[Using the Horizontal Pod Autoscaler] +. xref:getting-started:local-tutorial.adoc#upgrade-to-newer-version[Upgrade to newer Solr version] +. xref:getting-started:local-tutorial.adoc#install-kubernetes-dashboard-optional[Install Kubernetes Dashboard (optional)] +. xref:getting-started:local-tutorial.adoc#delete-the-solrcloud-cluster-named-example[Delete the solrCloud cluster named 'example'] -## Setup Kubernetes and Dependencies +== Setup Kubernetes and Dependencies -### Setup Docker for Mac with K8s +=== Setup Docker for Mac with K8s -```bash +[source,bash] +---- # Install Homebrew, if you don't have it already /bin/bash -c "$(curl -fsSL \ https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" @@ -52,54 +52,58 @@ open /Applications/Docker.app # Install Helm, which we'll use to install the operator, and 'watch' brew install helm watch -``` +---- -### Install an Ingress Controller +=== Install an Ingress Controller Kubernetes services are by default only accessible from within the k8s cluster. To make them adressable from our laptop, we'll add an ingress controller -```bash +[source,bash] +---- # Install the nginx ingress controller kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud/deploy.yaml -# Inspect that the ingress controller is running by visiting the Kubernetes dashboard +# Inspect that the ingress controller is running by visiting the Kubernetes dashboard # and selecting namespace `ingress-nginx`, or running this command: kubectl get all --namespace ingress-nginx # Edit your /etc/hosts file (`sudo vi /etc/hosts`) and replace the 127.0.0.1 line with: 127.0.0.1 localhost default-example-solrcloud.ing.local.domain ing.local.domain default-example-solrcloud-0.ing.local.domain default-example-solrcloud-1.ing.local.domain default-example-solrcloud-2.ing.local.domain dinghy-ping.localhost -``` +---- Once we have installed Solr to our k8s, this will allow us to address the nodes locally. -## Install the Solr Operator +== Install the Solr Operator -You can follow along here, or follow the instructions in the [Official Helm release](https://artifacthub.io/packages/helm/apache-solr/solr-operator). +You can follow along here, or follow the instructions in the https://artifacthub.io/packages/helm/apache-solr/solr-operator[Official Helm release]. Now that we have the prerequisites setup, let us install Solr Operator which will let us easily manage a large Solr cluster: Now add the Solr Operator Helm repository. (You should only need to do this once) -```bash +[source,bash] +---- $ helm repo add apache-solr https://solr.apache.org/charts $ helm repo update -``` +---- -Next, install the Solr Operator chart. Note this is using Helm v3, in order to use Helm v2 please consult the [Helm Chart documentation](https://hub.helm.sh/charts/solr-operator/solr-operator). -This will install the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator) by default. +Next, install the Solr Operator chart. Note this is using Helm v3, in order to use Helm v2 please consult the https://hub.helm.sh/charts/solr-operator/solr-operator[Helm Chart documentation]. +This will install the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] by default. -```bash +[source,bash] +---- # Install the Solr & Zookeeper CRDs $ kubectl create -f https://solr.apache.org/operator/downloads/crds/v0.10.0-prerelease/all-with-dependencies.yaml # Install the Solr operator and Zookeeper Operator $ helm install solr-operator apache-solr/solr-operator --version 0.10.0-prerelease -``` +---- _Note that the Helm chart version does not contain a `v` prefix, which the downloads version does. The Helm chart version is the only part of the Solr Operator release that does not use the `v` prefix._ - After installing, you can check to see what lives in the cluster to make sure that the Solr and ZooKeeper operators have started correctly. -```bash + +[source,bash] +---- $ kubectl get all NAME READY STATUS RESTARTS AGE @@ -113,15 +117,16 @@ deployment.apps/solr-operator-zookeeper-operator 1/1 1 1 NAME DESIRED CURRENT READY AGE replicaset.apps/solr-operator-8449d4d96f 1 1 1 2d1h replicaset.apps/solr-operator-zookeeper-operator-674676769c 1 1 1 49d -``` +---- After inspecting the status of you Kube cluster, you should see a deployment for the Solr Operator as well as the Zookeeper Operator. -## Start an example Solr Cloud cluster +== Start an example Solr Cloud cluster To start a Solr Cloud cluster, we will create a yaml that will tell the Solr Operator what version of Solr Cloud to run, and how many nodes, with how much memory etc. -```bash +[source,bash] +---- # Create a 3-node cluster v9.10.0 with 300m Heap each: helm install example-solr apache-solr/solr --version 0.10.0-prerelease \ --set image.tag=9.10.0 \ @@ -138,51 +143,58 @@ kubectl get solrclouds -w # Open a web browser to see a solr node: # Note that this is the service level, so will round-robin between the nodes open "http://default-example-solrcloud.ing.local.domain/solr/#/~cloud?view=nodes" -``` +---- -## Create a collection and index some documents +== Create a collection and index some documents -Create a collection via the [Collections API](https://solr.apache.org/guide/8_8/collection-management.html#create). +Create a collection via the https://solr.apache.org/guide/8_8/collection-management.html#create[Collections API]. -```bash +[source,bash] +---- # Execute the Collections API command curl "http://default-example-solrcloud.ing.local.domain/solr/admin/collections?action=CREATE&name=mycoll&numShards=1&replicationFactor=3&maxShardsPerNode=2&collection.configName=_default" # Check in Admin UI that collection is created open "http://default-example-solrcloud.ing.local.domain/solr/#/~cloud?view=graph" -``` +---- Now index some documents into the empty collection. -```bash + +[source,bash] +---- curl -XPOST -H "Content-Type: application/json" \ -d '[{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}, {id: 7}, {id: 8}]' \ "http://default-example-solrcloud.ing.local.domain/solr/mycoll/update/" -``` +---- -## Scale from 3 to 5 nodes +== Scale from 3 to 5 nodes So we wish to add more capacity. Scaling the cluster is a breeze. -```bash +[source,bash] +---- # Issue the scale command kubectl scale --replicas=5 solrcloud/example -``` +---- After issuing the scale command, start hitting the "Refresh" button in the Admin UI. You will see how the new Solr nodes are added. You can also watch the status via the `kubectl get solrclouds` command: -```bash +[source,bash] +---- kubectl get solrclouds -w # Hit Control-C when done -``` +---- -### Horizontal Pod Autoscaler (HPA) +=== Horizontal Pod Autoscaler (HPA) The SolrCloud CRD is setup so that it is able to run with the HPA. Merely use the following when creating an HPA object: -```yaml + +[source,yaml] +---- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: @@ -196,17 +208,18 @@ spec: name: example metrics: .... - ``` +---- Make sure that you are not overwriting the `SolrCloud.Spec.replicas` field when doing `kubectl apply`, otherwise you will be undoing the autoscaler's work. By default, the helm chart does not set the `replicas` field, so it is safe to use with the HPA. -## Upgrade to newer version +== Upgrade to newer version So we wish to upgrade to a newer Solr version: -```bash +[source,bash] +---- # Take note of the current version curl -s http://default-example-solrcloud.ing.local.domain/solr/admin/info/system | grep solr-i @@ -221,13 +234,14 @@ helm upgrade example-solr apache-solr/solr --version 0.10.0-prerelease \ kubectl get solrclouds -w # Hit Control-C when done -``` +---- -## Install Kubernetes Dashboard (optional) +== Install Kubernetes Dashboard (optional) Kubernetes Dashboard is a web interface that gives a better overview of your k8s cluster than only running command-line commands. This step is optional, you don't need it if you're comfortable with the cli. -```bash +[source,bash] +---- # Install the Dashboard kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/recommended.yaml @@ -243,10 +257,11 @@ kubectl proxy & open "http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/overview?namespace=default" # Select 'Token' in the UI and paste the token from last step (starting with 'ey...') -``` +---- -## Delete the solrCloud cluster named 'example' +== Delete the solrCloud cluster named 'example' -```bash +[source,bash] +---- kubectl delete solrcloud example -``` +---- diff --git a/docs/running-the-operator.md b/docs/modules/getting-started/pages/running-the-operator.adoc similarity index 68% rename from docs/running-the-operator.md rename to docs/modules/getting-started/pages/running-the-operator.adoc index 16dd6c3b..6fdd47a9 100644 --- a/docs/running-the-operator.md +++ b/docs/modules/getting-started/pages/running-the-operator.adoc @@ -1,52 +1,54 @@ - - -# Running the Solr Operator - -## Using the Solr Operator Helm Chart - -The easiest way to run the Solr Operator is via the [provided Helm Chart](https://artifacthub.io/packages/helm/apache-solr/solr-operator). += Running the Solr Operator +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +== Using the Solr Operator Helm Chart + +The easiest way to run the Solr Operator is via the https://artifacthub.io/packages/helm/apache-solr/solr-operator[provided Helm Chart]. The helm chart provides abstractions over the Input Arguments described below, and should work with any official images in docker hub. -### How to install via Helm +=== How to install via Helm -The official documentation for installing the Solr Operator Helm chart can be found on [Artifact Hub](https://artifacthub.io/packages/helm/apache-solr/solr-operator). +The official documentation for installing the Solr Operator Helm chart can be found on https://artifacthub.io/packages/helm/apache-solr/solr-operator[Artifact Hub]. The first step is to add the Solr Operator helm repository. -```bash +[source,bash] +---- $ helm repo add apache-solr https://solr.apache.org/charts $ helm repo update -``` +---- Next, install the Solr Operator chart. Note this is using Helm v3, use the official Helm chart documentation linked to above. -This will install the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator) by default. +This will install the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] by default. -```bash +[source,bash] +---- $ kubectl create -f https://solr.apache.org/operator/downloads/crds/v0.10.0-prerelease/all-with-dependencies.yaml $ helm install solr-operator apache-solr/solr-operator --version 0.10.0-prerelease -``` +---- _Note that the Helm chart version does not contain a `v` prefix, which the downloads version does. The Helm chart version is the only part of the Solr Operator release that does not use the `v` prefix._ - After installing, you can check to see what lives in the cluster to make sure that the Solr and ZooKeeper operators have started correctly. -```bash + +[source,bash] +---- $ kubectl get all NAME READY STATUS RESTARTS AGE @@ -60,107 +62,113 @@ deployment.apps/solr-operator-zookeeper-operator 1/1 1 1 NAME DESIRED CURRENT READY AGE replicaset.apps/solr-operator-8449d4d96f 1 1 1 2d1h replicaset.apps/solr-operator-zookeeper-operator-674676769c 1 1 1 49d -``` +---- After inspecting the status of you Kube cluster, you should see a deployment for the Solr Operator as well as the Zookeeper Operator. -### Managing CRDs +=== Managing CRDs Helm 3 automatically installs the Solr CRDs in the /crds directory, so no further action is needed when first installing the Operator. If you have solr operator installations in multiple namespaces that are managed separately, you will likely want to skip installing CRDs when installing the chart. This can be done with the `--skip-crds` helm option. -```bash +[source,bash] +---- helm install solr-operator apache-solr/solr-operator --skip-crds --namespace solr -``` +---- -**Helm will not upgrade CRDs once they have been installed. -Therefore, if you are upgrading from a previous Solr Operator version, be sure to install the most recent CRDs first.** +*Helm will not upgrade CRDs once they have been installed. +Therefore, if you are upgrading from a previous Solr Operator version, be sure to install the most recent CRDs first.* You can update the released Solr CRDs with the following URL: -```bash + +[source,bash] +---- kubectl replace -f "https://solr.apache.org/operator/downloads/crds//.yaml" -``` +---- Examples: -- `https://solr.apache.org/operator/downloads/crds/v0.3.0/all.yaml` + +* `https://solr.apache.org/operator/downloads/crds/v0.3.0/all.yaml` + Includes all Solr CRDs in the `v0.3.0` release -- `https://solr.apache.org/operator/downloads/crds/v0.2.7/all-with-dependencies.yaml` +* `https://solr.apache.org/operator/downloads/crds/v0.2.7/all-with-dependencies.yaml` + Includes all Solr CRDs and dependency CRDs in the `v0.2.7` release -- `https://solr.apache.org/operator/downloads/crds/v0.2.8/solrclouds.yaml` +* `https://solr.apache.org/operator/downloads/crds/v0.2.8/solrclouds.yaml` + Just the SolrCloud CRD in the `v0.2.8` release -#### The ZookeeperCluster CRD +==== The ZookeeperCluster CRD If you use the provided Zookeeper Cluster in the SolrCloud Spec, it is important to make sure you have the correct `ZookeeperCluster` CRD installed as well. The Zookeeper Operator Helm chart includes its CRDs when installing, however the way the CRDs are managed can be considered risky. -If we let the Zookeeper Operator Helm chart manage the Zookeeper CRDs, then users could see outages when [uninstalling the chart](#uninstalling-the-chart). +If we let the Zookeeper Operator Helm chart manage the Zookeeper CRDs, then users could see outages when uninstalling the chart. Therefore, by default, we tell the Zookeeper Operator to not install the Zookeeper CRDs. You can override this, assuming the risks, by setting `zookeeper-operator.crd.create: true`. -For manual installation of the ZookeeperCluster CRD, you can find the file in the [zookeeper-operator repo](https://github.com/pravega/zookeeper-operator/blob/master/deploy/crds/zookeeper.pravega.io_zookeeperclusters_crd.yaml), for the correct release, +For manual installation of the ZookeeperCluster CRD, you can find the file in the https://github.com/pravega/zookeeper-operator/blob/master/deploy/crds/zookeeper.pravega.io_zookeeperclusters_crd.yaml[zookeeper-operator repo], for the correct release, or use the convenience download locations provided below. The Solr CRD releases have bundled the ZookeeperCluster CRD required in each version. -```bash +[source,bash] +---- # Install all Solr CRDs as well as the dependency CRDS (ZookeeperCluster) for the given version of the Solr Operator kubectl create -f "https://solr.apache.org/operator/downloads/crds//all-with-dependencies.yaml" # Install just the ZookeeperCluster CRD used in the given version of the Solr Operator kubectl create -f "https://solr.apache.org/operator/downloads/crds//zookeeperclusters.yaml" -``` +---- Examples: -- `https://solr.apache.org/operator/downloads/crds/v0.3.0/all-with-dependencies.yaml` + +* `https://solr.apache.org/operator/downloads/crds/v0.3.0/all-with-dependencies.yaml` + Includes all Solr CRDs and dependency CRDs, including `ZookeeperCluster`, in the `v0.3.0` Solr Operator release -- `https://solr.apache.org/operator/downloads/crds/v0.2.8/zookeeperclusters.yaml` +* `https://solr.apache.org/operator/downloads/crds/v0.2.8/zookeeperclusters.yaml` + Just the ZookeeperCluster CRD required in the `v0.2.8` Solr Operator release -## Solr Operator Docker Images +== Solr Operator Docker Images -The Solr Operator Docker image is published to Dockerhub at [apache/solr-operator](https://hub.docker.com/r/apache/solr-operator). -The [Dockerfile](/build/Dockerfile) builds from scratch source, and copies all necessary information to a very limited image. +The Solr Operator Docker image is published to Dockerhub at https://hub.docker.com/r/apache/solr-operator[apache/solr-operator]. +The https://github.com/apache/solr-operator/blob/main/build/Dockerfile[Dockerfile] builds from scratch source, and copies all necessary information to a very limited image. The final image will only contain the solr-operator binary and necessary License information. -## Solr Operator Input Args +== Solr Operator Input Args -* **--zookeeper-operator** Whether or not to use the Zookeeper Operator to create dependency Zookeeepers. +* *--zookeeper-operator* Whether or not to use the Zookeeper Operator to create dependency Zookeeepers. Required to use the `spec.zookeeperRef.provided` option. If _true_, then a Zookeeper Operator must be running for the cluster. (_true_ | _false_ , defaults to _false_) -* **--watch-namespaces** Watch certain namespaces in the Kubernetes cluster. +* *--watch-namespaces* Watch certain namespaces in the Kubernetes cluster. If flag is omitted, or given an empty string, then the whole cluster will be watched. If the operator should watch multiple namespaces, provide them all separated by commas. (_string_ , defaults to _empty_) -* **--leader-elect** Whether or not to use leader election for the Solr Operator. +* *--leader-elect* Whether or not to use leader election for the Solr Operator. If set to true, then only one operator pod will be functional for the namespaces given through `--watch-namespaces`. If multiple namespaces are provided, leader election will use the first namespace sorted alphabetically. (_true_ | _false_ , defaults to _true_) -* **--metrics-bind-address** The address to bind the metrics servlet on. +* *--metrics-bind-address* The address to bind the metrics servlet on. If only a port is provided (e.g. `:8080`), then the metrics server will respond to requests with any Host header. (defaults to _:8080_) -* **--health-probe-bind-address=** The address to bind the health probe servlet on. +* *--health-probe-bind-address=* The address to bind the health probe servlet on. If only a port is provided (e.g. `:8081`), then the metrics server will respond to requests with any Host header. (defaults to _:8081_) -* **--zap-devel** Enables development mode. +* *--zap-devel* Enables development mode. Changes logging to `console` encoder and `debug` level. (_true_ | _false_, defaults to _false_) -* **--zap-log-level** Overrides the log level. +* *--zap-log-level* Overrides the log level. Can be one of `debug`, `info`, `error`, or any integer value > 0 for custom verbosity. (_string_, defaults to _empty_) -* **--zap-encoder** Overrides the log format. +* *--zap-encoder* Overrides the log format. Use `console` or `json`. (_string_, defaults to _empty_) -* **--zap-stacktrace-level** Overrides the level for stack trace logging. (_string_, defaults to _empty_) +* *--zap-stacktrace-level* Overrides the level for stack trace logging. (_string_, defaults to _empty_) -## Client Auth for mTLS-enabled Solr clusters +== Client Auth for mTLS-enabled Solr clusters For SolrCloud instances that run with mTLS enabled (see `spec.solrTLS.clientAuth`), the operator needs to supply a trusted certificate when making API calls to the Solr pods it is managing. @@ -168,25 +176,28 @@ This means that the client certificate used by the operator must be added to the Alternatively, the certificate for the Certificate Authority (CA) that signed the client certificate can be trusted by adding the CA's certificate to the Solr truststore. In the latter case, any client certificates issued by the trusted CA will be accepted by Solr, so make sure this is appropriate for your environment. -The client certificate used by the operator should be stored in a [TLS secret](https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets); you must create this secret before deploying the Solr operator. +The client certificate used by the operator should be stored in a https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets[TLS secret]; you must create this secret before deploying the Solr operator. When deploying the operator, supply the client certificate using the `mTLS.clientCertSecret` Helm chart variable, such as: -``` + +---- --set mTLS.clientCertSecret=my-client-cert \ -``` +---- + The specified secret must exist in the same namespace where the operator is deployed. -In addition, if the CA used to sign the server certificate used by Solr is not built into the operator's Docker image, +In addition, if the CA used to sign the server certificate used by Solr is not built into the operator's Docker image, then you'll need to add the CA's certificate to the operator so its HTTP client will trust the server certificates during the TLS handshake. The CA certificate needs to be stored in Kubernetes secret in PEM format and provided via the following Helm chart variables: -``` + +---- --set mTLS.caCertSecret=my-client-ca-cert \ --set mTLS.caCertSecretKey=ca-cert-pem -``` +---- In most cases, you'll also want to configure the operator with `mTLS.insecureSkipVerify=true` (the default) as you'll want the operator to skip hostname verification for Solr pods. Setting `mTLS.insecureSkipVerify` to `false` means the operator will enforce hostname verification for the certificate provided by Solr pods. By default, the operator watches for updates to the mTLS client certificate (mounted from the `mTLS.clientCertSecret` secret) and then refreshes the HTTP client to use the updated certificate. -To disable this behavior, configure the operator using: `--set mTLS.watchForUpdates=false`. \ No newline at end of file +To disable this behavior, configure the operator using: `--set mTLS.watchForUpdates=false`. diff --git a/docs/modules/solr-backup/nav.adoc b/docs/modules/solr-backup/nav.adoc new file mode 100644 index 00000000..84634517 --- /dev/null +++ b/docs/modules/solr-backup/nav.adoc @@ -0,0 +1,19 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +.Solr Backups +* xref:index.adoc[] diff --git a/docs/solr-backup/README.md b/docs/modules/solr-backup/pages/index.adoc similarity index 77% rename from docs/solr-backup/README.md rename to docs/modules/solr-backup/pages/index.adoc index e842466b..eba39d72 100644 --- a/docs/solr-backup/README.md +++ b/docs/modules/solr-backup/pages/index.adoc @@ -1,21 +1,20 @@ - - -# Solr Backups += Solr Backups +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. The Solr Operator supports triggering the backup of arbitrary Solr collections. @@ -27,25 +26,26 @@ For detailed information on how to best configure backups for your use case, ple This page outlines how to create and delete a Kubernetes SolrBackup. -- [Creation](#creating-an-example-solrbackup) -- [Recurring/Scheduled Backups](#recurring-backups) -- [Deletion](#deleting-an-example-solrbackup) -- [Repository Types](#supported-repository-types) - - [GCS](#gcs-backup-repositories) - - [S3](#s3-backup-repositories) - - [Volume](#volume-backup-repositories) +* <> +* <> +* <> +* <> +** <> +** <> +** <> -## Creating an example SolrBackup +== Creating an example SolrBackup A prerequisite for taking a backup is having something to take a backup _of_. -SolrCloud creation generally is covered in more detail [here](../solr-cloud/README.md), so if you don't have one already, create a SolrCloud instance as per those instructions. +SolrCloud creation generally is covered in more detail xref:solr-cloud:index.adoc[here], so if you don't have one already, create a SolrCloud instance as per those instructions. Now that you have a Solr cluster to backup data from, you need a place to store the backup data. In this example, we'll create a Kubernetes persistent volume to mount on each Solr node. A volume for this purpose can be created as below: -```yaml +[source,yaml] +---- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -55,10 +55,10 @@ spec: - ReadWriteMany resources: requests: - storage: 1Gi + storage: 1Gi storageClassName: hostpath volumeMode: Filesystem -``` +---- Note that this PVC specifies `ReadWriteMany` access, which is required for Solr clusters with more than one node. Note also that it uses a `storageClassName` of `hostpath`. @@ -67,7 +67,8 @@ Not all Kubernetes clusters support this `storageClassName` value - you may need Next, modify your existing SolrCloud instance by adding a backup repository definition that uses the recently created volume. To do this, run `kubectl edit solrcloud example`, adding the following YAML nested under the `spec` property: -```yaml +[source,yaml] +---- spec: backupRepositories: - name: "local-collection-backups-1" @@ -75,14 +76,15 @@ spec: source: persistentVolumeClaim: claimName: "collection-backup-pvc" -``` +---- This defines a backup repository called "local-collection-backups-1" which is setup to store backup data on the volume we've just created. The operator will notice this change and create new Solr pods that have the 'collection-backup-pvc' volume mounted. Now that there's a backup repository available to use, a backup can be triggered anytime by creating a new SolrBackup instance. -```yaml +[source,yaml] +---- apiVersion: solr.apache.org/v1beta1 kind: SolrBackup metadata: @@ -94,19 +96,20 @@ spec: collections: - techproducts - books -``` +---- This will create a backup of both the 'techproducts' and 'books' collections, storing the data on the 'collection-backup-pvc' volume. If you don't specify the collections field, every available SolrCloud collection will be backed up. The status of our triggered backup can be checked with the command below. -```bash +[source,bash] +---- $ kubectl get solrbackups NAME CLOUD STARTED FINISHED SUCCESSFUL NEXTBACKUP AGE test example 123m true false 161m -``` +---- -## Recurring Backups +== Recurring Backups _Since v0.5.0_ The Solr Operator enables taking recurring updates, at a set interval. @@ -114,9 +117,10 @@ Note that this feature requires a SolrCloud running Solr >= `8.9.0`, because it By default the Solr Operator will save a maximum of **5** backups at a time, however users can override this using `SolrBackup.spec.recurrence.maxSaved`. When using `recurrence`, users must provide a Cron-style `schedule` for the interval at which backups should be taken. -Please refer to the [GoLang cron-spec](https://pkg.go.dev/github.com/robfig/cron/v3?utm_source=godoc#hdr-CRON_Expression_Format) for more information on allowed syntax. +Please refer to the https://pkg.go.dev/github.com/robfig/cron/v3?utm_source=godoc#hdr-CRON_Expression_Format[GoLang cron-spec] for more information on allowed syntax. -```yaml +[source,yaml] +---- apiVersion: solr.apache.org/v1beta1 kind: SolrBackup metadata: @@ -131,15 +135,16 @@ spec: recurrence: # Store one backup daily, and keep a week at a time. schedule: "@daily" maxSaved: 7 -``` +---- If using `kubectl`, the standard `get` command will return the time the backup was last started and when the next backup will occur. -```bash +[source,bash] +---- $ kubectl get solrbackups NAME CLOUD STARTED FINISHED SUCCESSFUL NEXTBACKUP AGE test example 123m true true 2021-11-09T00:00:00Z 161m -``` +---- Much like when not taking a recurring backup, `SolrBackup.status` will contain the information from the latest, or currently running, backup. The results of previous backup attempts are stored under `SolrBackup.status.history` (sorted from most recent to oldest). @@ -149,7 +154,7 @@ If you add recurrence, then a new backup will be scheduled based on the `startTi If you remove recurrence, then the `nextBackupTime` will be removed. However, if the recurrent backup is already underway, it will not be stopped. -### Backup Scheduling +=== Backup Scheduling Backups are scheduled based on the `startTimestamp` of the last backup. Therefore, if an interval schedule such as `@every 1h` is used, and a backup starts on `2021-11-09T03:10:00Z` and ends on `2021-11-09T05:30:00Z`, then the next backup will be started at `2021-11-09T04:10:00Z`. @@ -159,7 +164,7 @@ So there is a possibility of skew overtime if backups take longer than the allot If a guaranteed schedule is important, it is recommended to use intervals that are guaranteed to be longer than the time it takes to complete a backup. -### Temporarily Disabling Recurring Backups +=== Temporarily Disabling Recurring Backups It is also easy to temporarily disable backups for a time. Merely add `disabled: true` under the `recurrence` section of the `SolrBackup` resource. @@ -167,7 +172,8 @@ And set `disabled: false`, or just remove the property to re-enable backups. Since backups are scheduled based on the `startTimestamp` of the last backup, a new backup may start immediately after you re-enable the recurrence. -```yaml +[source,yaml] +---- apiVersion: solr.apache.org/v1beta1 kind: SolrBackup metadata: @@ -183,36 +189,39 @@ spec: schedule: "@daily" maxSaved: 7 disabled: true -``` +---- -**Note: this will not stop any backups running at the time that `disabled: true` is set, it will only affect scheduling future backups.** +NOTE: this will not stop any backups running at the time that `disabled: true` is set, it will only affect scheduling future backups. -## Deleting an example SolrBackup +== Deleting an example SolrBackup Once the operator completes a backup, the SolrBackup instance can be safely deleted. -```bash +[source,bash] +---- $ kubectl delete solrbackup local-backup -``` +---- Note that deleting SolrBackup instances doesn't delete the backed up data, which the operator views as already persisted and outside its control. In our example this data can still be found on the volume we created earlier -```bash +[source,bash] +---- $ kubectl exec example-solrcloud-0 -- ls -lh /var/solr/data/backup-restore/local-collection-backups-1/backups/ total 8K drwxr-xr-x 3 solr solr 4.0K Sep 16 11:48 local-backup-books drwxr-xr-x 3 solr solr 4.0K Sep 16 11:48 local-backup-techproducts -``` +---- Volume backup data, as in our example, can always be deleted using standard shell commands if desired: -```bash +[source,bash] +---- kubectl exec example-solrcloud-0 -- rm -r /var/solr/data/backup-restore/local-collection-backups-1/backups/local-backup-books kubectl exec example-solrcloud-0 -- rm -r /var/solr/data/backup-restore/local-collection-backups-1/backups/local-backup-techproducts -``` +---- -## Supported Repository Types +== Supported Repository Types _Since v0.5.0_ Note all repositories are defined in the `SolrCloud` specification. @@ -228,7 +237,8 @@ Repository-type specific options are found under the object named with the repos Examples can be found below under each repository-type section below. Feel free to mix and match multiple backup repository types to fit your use case (or multiple repositories of the same type): -```yaml +[source,yaml] +---- spec: backupRepositories: - name: "local-collection-backups-1" @@ -243,49 +253,52 @@ spec: - name: "s3-collection-backups-2" s3: ... -``` +---- -### GCS Backup Repositories +=== GCS Backup Repositories _Since v0.5.0_ GCS Repositories store backup data remotely in Google Cloud Storage. This repository type is only supported in deployments that use a Solr version >= `8.9.0`. Each repository must specify the GCS bucket to store data in (the `bucket` property), and (usually) the name of a Kubernetes secret containing credentials for accessing GCS (the `gcsCredentialSecret` property). -This secret must have a key `service-account-key.json` whose value is a JSON service account key as described [here](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) +This secret must have a key `service-account-key.json` whose value is a JSON service account key as described https://cloud.google.com/iam/docs/creating-managing-service-account-keys[here] If you already have your service account key, this secret can be created using a command like the one below. -```bash +[source,bash] +---- kubectl create secret generic --from-file=service-account-key.json= -``` +---- -In some rare cases (e.g. when deploying in GKE and relying on its [Workload Identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity) feature) explicit credentials are not required to talk to GCS. In these cases, the `gcsCredentialSecret` property may be omitted. +In some rare cases (e.g. when deploying in GKE and relying on its https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity[Workload Identity] feature) explicit credentials are not required to talk to GCS. In these cases, the `gcsCredentialSecret` property may be omitted. An example of a SolrCloud spec with only one backup repository, with type GCS: -```yaml +[source,yaml] +---- spec: backupRepositories: - name: "gcs-backups-1" gcs: bucket: "backup-bucket" # Required - gcsCredentialSecret: + gcsCredentialSecret: name: "secretName" key: "service-account-key.json" baseLocation: "/store/here" # Optional -``` +---- -### S3 Backup Repositories +=== S3 Backup Repositories _Since v0.5.0_ S3 Repositories store backup data remotely in AWS S3 (or a supported S3 compatible interface). This repository type is only supported in deployments that use a Solr version >= `8.10.0`. Each repository must specify an S3 bucket and region to store data in (the `bucket` and `region` properties). -Users will want to setup credentials so that the SolrCloud can connect to the S3 bucket and region, more information can be found in the [credentials section](#s3-credentials). +Users will want to setup credentials so that the SolrCloud can connect to the S3 bucket and region, more information can be found in the <>. -```yaml +[source,yaml] +---- spec: backupRepositories: - name: "s3-backups-1" @@ -295,20 +308,21 @@ spec: credentials: {} # Optional proxyUrl: "https://proxy-url-for-s3:3242" # Optional endpoint: "https://custom-s3-endpoint:3242" # Optional -``` +---- Users can also optionally set a `proxyUrl` or `endpoint` for the S3Repository. -More information on these settings can be found in the [Ref Guide](https://solr.apache.org/guide/8_10/making-and-restoring-backups.html#s3backuprepository). +More information on these settings can be found in the https://solr.apache.org/guide/8_10/making-and-restoring-backups.html#s3backuprepository[Ref Guide]. -#### S3 Credentials +==== S3 Credentials -The Solr `S3Repository` module uses the [default credential chain for AWS](https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/credentials.html#credentials-chain). +The Solr `S3Repository` module uses the https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/credentials.html#credentials-chain[default credential chain for AWS]. All of the options below are designed to be utilized by this credential chain. There are a few options for giving a SolrCloud the credentials for connecting to S3. The two most straightforward ways can be used via the `spec.backupRepositories.s3.credentials` property. -```yaml +[source,yaml] +---- spec: backupRepositories: - name: "s3-backups-1" @@ -328,10 +342,10 @@ spec: credentialsFileSecret: # Optional name: aws-credentials key: credentials -``` +---- All options in the `credentials` property are optional, as users can pick and choose which ones to use. -If you have all of your credentials setup in an [AWS Credentials File](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html#file-format-creds), +If you have all of your credentials setup in an https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html#file-format-creds[AWS Credentials File], then `credentialsFileSecret` will be the only property you need to set. However, if you don't have a credentials file, you will likely need to set at least the `accessKeyIdSecret` and `secretAccessKeySecret` properties. All of these options require the referenced Kuberentes secrets to already exist before creating the SolrCloud resource. @@ -340,19 +354,19 @@ _(If desired, all options can be combined. e.g. Use `accessKeyIdSecret` and `cre The options in the credentials file above merely set environment variables on the pod, or in the case of `credentialsFileSecret` use an environment variable and a volume mount. Users can decide to not use the `credentials` section of the s3 repository config, and instead set these environment variables themselves via `spec.customSolrKubeOptions.podOptions.env`. -Lastly, if running in EKS, it is possible to add [IAM information to Kubernetes serviceAccounts](https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/). +Lastly, if running in EKS, it is possible to add https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/[IAM information to Kubernetes serviceAccounts]. If this is done correctly, you will only need to specify the serviceAccount for the SolrCloud pods via `spec.customSolrKubeOptions.podOptions.serviceAccount`. -_NOTE: Because the Solr S3 Repository is using system-wide settings for AWS credentials, you cannot specify different credentials for different S3 repositories. -This may be addressed in future Solr versions, but for now use the same credentials for all s3 repos._ +NOTE: Because the Solr S3 Repository is using system-wide settings for AWS credentials, you cannot specify different credentials for different S3 repositories. This may be addressed in future Solr versions, but for now use the same credentials for all s3 repos. -### Volume Backup Repositories +=== Volume Backup Repositories _Since v0.5.0_ Volume repositories store backup data "locally" on a Kubernetes volume mounted to each Solr pod. An example of a SolrCloud spec with only one backup repository, with type Volume: -```yaml +[source,yaml] +---- spec: backupRepositories: - name: "local-collection-backups-1" @@ -361,6 +375,6 @@ spec: persistentVolumeClaim: claimName: "collection-backup-pvc" directory: "store/here" # Optional -``` +---- -**NOTE: All persistent volumes used with Volume Repositories must have `accessMode: ReadWriteMany` set, otherwise the backups will not succeed.** +IMPORTANT: All persistent volumes used with Volume Repositories must have `accessMode: ReadWriteMany` set, otherwise the backups will not succeed. diff --git a/docs/modules/solr-cloud/nav.adoc b/docs/modules/solr-cloud/nav.adoc new file mode 100644 index 00000000..02f324bd --- /dev/null +++ b/docs/modules/solr-cloud/nav.adoc @@ -0,0 +1,24 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +.Solr Clouds +* xref:index.adoc[Overview] +* xref:solr-cloud-crd.adoc[] +* xref:cluster-operations.adoc[] +* xref:managed-updates.adoc[] +* xref:scaling.adoc[] +* xref:dependencies.adoc[] diff --git a/docs/solr-cloud/cluster-operations.md b/docs/modules/solr-cloud/pages/cluster-operations.adoc similarity index 64% rename from docs/solr-cloud/cluster-operations.md rename to docs/modules/solr-cloud/pages/cluster-operations.adoc index aa915de7..a7392a59 100644 --- a/docs/solr-cloud/cluster-operations.md +++ b/docs/modules/solr-cloud/pages/cluster-operations.adoc @@ -1,85 +1,86 @@ - - -# Cluster Operations += Cluster Operations +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + _Since v0.8.0_ Solr Clouds are complex distributed systems, and thus any operations that deal with data availability should be handled with care. -## Cluster Operation Locks +== Cluster Operation Locks Since cluster operations deal with Solr's index data (either the availability of it, or moving it), its safest to only allow one operation to take place at a time. That is why these operations must first obtain a lock on the SolrCloud before execution can be started. -### Lockable Operations +=== Lockable Operations -- [Managed Rolling Updates](managed-updates.md) -- [Scaling Down with Replica Migrations](scaling.md#solr-pod-scale-down) -- [Scaling Up with Replica Migrations](scaling.md#solr-pod-scale-up) -- Balancing Replicas Across Pods - - This is started after a Rolling Update with Ephemeral Data or after a ScaleUp operation. +* xref:solr-cloud:managed-updates.adoc[Managed Rolling Updates] +* xref:solr-cloud:scaling.adoc#solr-pod-scale-down[Scaling Down with Replica Migrations] +* xref:solr-cloud:scaling.adoc#solr-pod-scale-up[Scaling Up with Replica Migrations] +* Balancing Replicas Across Pods +** This is started after a Rolling Update with Ephemeral Data or after a ScaleUp operation. -### How is the Lock Implemented? +=== How is the Lock Implemented? The lock is implemented as an annotation on the SolrCloud's `StatefulSet`. The cluster operation retry queue is also implemented as an annotation. These locks can be viewed at the following annotation keys: -- `solr.apache.org/clusterOpsLock` - The cluster operation that currently holds a lock on the SolrCloud and is executing. -- `solr.apache.org/clusterOpsRetryQueue` - The queue of cluster operations that timed out and will be retried in order after the `clusterOpsLock` is given up. +* `solr.apache.org/clusterOpsLock` - The cluster operation that currently holds a lock on the SolrCloud and is executing. +* `solr.apache.org/clusterOpsRetryQueue` - The queue of cluster operations that timed out and will be retried in order after the `clusterOpsLock` is given up. -### Avoiding Deadlocks +=== Avoiding Deadlocks If all cluster operations executed without any issues, there would be no need to worry about deadlocks. Cluster operations give up the lock when the operation is complete, and then other operations that have been waiting can proceed. Unfortunately, these cluster operations can and will fail for a number of reasons: -- Replicas have no other pod to be placed when moving off of a node. (Due to the [Replica Placement Plugin](https://solr.apache.org/guide/solr/latest/configuration-guide/replica-placement-plugins.html) used) -- There are insufficient resources to create new Solr Pods. -- The Solr Pod Template has an error and new Solr Pods cannot be started successfully. +* Replicas have no other pod to be placed when moving off of a node. (Due to the https://solr.apache.org/guide/solr/latest/configuration-guide/replica-placement-plugins.html[Replica Placement Plugin] used) +* There are insufficient resources to create new Solr Pods. +* The Solr Pod Template has an error and new Solr Pods cannot be started successfully. If this is the case, then we need to be able to stop the locked cluster operation if it hasn't succeeded in a certain time period. The cluster operation can only be stopped if there is no background task (async request) being executed in the Solr Cluster. Once cluster operation reaches a point at which it can stop, and the locking-timeout has been exceeded or an error was found, the cluster operation is _paused_, and added to a queue to retry later. The _timeout_ is different per-operation: -- Scaling (Up or Down): **1 minute** -- Rolling restarts: **10 minutes** + +* Scaling (Up or Down): *1 minute* +* Rolling restarts: *10 minutes* Immediately afterwards, the Solr Operator sees if there are any other operations that need to take place while before the queued cluster operation is re-started. This allows for users to make changes to fix the reason why the cluster operation was failing. Examples: -- **If there are insufficient resources to create new Solr Pods** \ - The user can decrease the resource requirements in the Pod Template. \ - This will create a `Rolling Update` cluster operation that will run once the `Scale Up` is paused. \ +* *If there are insufficient resources to create new Solr Pods* + + The user can decrease the resource requirements in the Pod Template. + + This will create a `Rolling Update` cluster operation that will run once the `Scale Up` is paused. + The `Scale Up` will be dequeued when the `Rolling Update` is complete, and can now complete because there are more available resources in the Kubernetes Cluster. -- **Scale Down is failing because a replica from the scaled-down pod has nowhere to be moved to** \ - The user can see this error in the logs, and know that the scale down won't work for their use case. \ - Instead they will have to scale the SolrCloud to the number of pods that the `StatefulSet` is currently running. \ - Once the `Scale Down` is paused, it will be replaced by a `Scale Up` operation to current number of running pods. \ +* *Scale Down is failing because a replica from the scaled-down pod has nowhere to be moved to* + + The user can see this error in the logs, and know that the scale down won't work for their use case. + + Instead they will have to scale the SolrCloud to the number of pods that the `StatefulSet` is currently running. + + Once the `Scale Down` is paused, it will be replaced by a `Scale Up` operation to current number of running pods. + This doesn't actually increase the number of pods, but it will issue a command to Solr to balance replicas across all pods, to make sure the cluster is well-balanced after the failed `ScaleDown`. If a queued operation is going to be retried, the Solr Operator first makes sure that its values are still valid. For the `Scale Down` example above, when the Solr Operator tries to restart the queued `Scale Down` operation, it sees that the `SolrCloud.Spec.Replicas` is no longer lower than the current number of Solr Pods. Therefore, the `Scale Down` does not need to be retried, and a "fake" `Scale Up` needs to take place. -### In the case of an emergency +=== In the case of an emergency When all else fails, and you need to stop a cluster operation, you can remove the lock annotation from the `StatefulSet` manually. @@ -87,11 +88,12 @@ Edit the StatefulSet (e.g. `kubectl edit statefulset `) and remove the clu This can be done via the following command: -```bash +[source,bash] +---- $ kubectl annotate statefulset ${statefulSetName} solr.apache.org/clusterOpsLock- -``` +---- This will only remove the current running cluster operation, if other cluster operations have been queued, they will be retried once the lock annotation is removed. Also if the operation still needs to occur to put the SolrCloud in its expected state, then the operation will be retried once a lock can be acquired. The only way to have the cluster operation not run again is to put the SolrCloud back to its previous state (for scaling, set `SolrCloud.Spec.replicas` to the value found in `StatefulSet.Spec.replicas`). -If the SolrCloud requires a rolling restart, it cannot be "put back to its previous state". The only way to move forward is to either delete the `StatefulSet` (a very dangerous operation), or find a way to allow the `RollingUpdate` operation to succeed. \ No newline at end of file +If the SolrCloud requires a rolling restart, it cannot be "put back to its previous state". The only way to move forward is to either delete the `StatefulSet` (a very dangerous operation), or find a way to allow the `RollingUpdate` operation to succeed. diff --git a/docs/solr-cloud/dependencies.md b/docs/modules/solr-cloud/pages/dependencies.adoc similarity index 79% rename from docs/solr-cloud/dependencies.md rename to docs/modules/solr-cloud/pages/dependencies.adoc index c162048f..b874445e 100644 --- a/docs/solr-cloud/dependencies.md +++ b/docs/modules/solr-cloud/pages/dependencies.adoc @@ -1,25 +1,25 @@ - - -## Dependent Kubernetes Resources += Dependent Kubernetes Resources +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. What actually gets created when the Solr Cloud is spun up? -```bash +[source,bash] +---- $ kubectl get all NAME READY STATUS RESTARTS AGE @@ -62,4 +62,4 @@ ingress.extensions/example-solrcloud-common default-example-solrcloud.test.dom NAME VERSION DESIREDNODES NODES READYNODES AGE solrcloud.solr.apache.org/example 8.1.1 4 4 4 47h -``` \ No newline at end of file +---- diff --git a/docs/solr-cloud/README.md b/docs/modules/solr-cloud/pages/index.adoc similarity index 55% rename from docs/solr-cloud/README.md rename to docs/modules/solr-cloud/pages/index.adoc index d8478836..c36bf55c 100644 --- a/docs/solr-cloud/README.md +++ b/docs/modules/solr-cloud/pages/index.adoc @@ -1,46 +1,47 @@ - - -# Solr Clouds += Solr Clouds +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. Child Pages: -- [All SolrCloud CRD Options](solr-cloud-crd.md) - Please refer here when trying to find new SolrCloud options/features. -- [Managed Updates](managed-updates.md) -- [Scaling](scaling.md) + +* xref:solr-cloud:solr-cloud-crd.adoc[All SolrCloud CRD Options] - Please refer here when trying to find new SolrCloud options/features. +* xref:solr-cloud:managed-updates.adoc[Managed Updates] +* xref:solr-cloud:scaling.adoc[Scaling] The Solr Operator supports creating and managing Solr Clouds clusters via its 'solrcloud' resource. (Note: running Solr in "standalone" mode is not supported.) This page outlines how to create, update and delete a SolrCloud in Kubernetes. -- [Creation](#creating-an-example-solrcloud) -- [Scaling](#scaling-a-solrcloud) -- [Deletion](#deleting-the-example-solrcloud) -- [Solr Images](#solr-images) - - [Official Images](#official-solr-images) - - [Custom Images](#build-your-own-private-solr-images) +* <> +* <> +* <> +* <> +** <> +** <> -## Creating an example SolrCloud +== Creating an example SolrCloud Make sure that the Solr Operator and a Zookeeper Operator are running. Create an example Solr cloud, with the following configuration. -```bash +[source,bash] +---- $ cat example/test_solrcloud.yaml apiVersion: solr.apache.org/v1beta1 @@ -51,11 +52,12 @@ spec: replicas: 4 solrImage: tag: 8.1.1 -``` +---- Apply it to your Kubernetes cluster. -```bash +[source,bash] +---- $ kubectl apply -f example/test_solrcloud.yaml $ kubectl get solrclouds @@ -66,62 +68,64 @@ $ kubectl get solrclouds NAME VERSION DESIREDNODES NODES READYNODES AGE example 8.1.1 4 4 4 8m -``` +---- What actually gets created when you start a Solr Cloud though? -Refer to the [dependencies outline](dependencies.md) to see what dependent Kuberenetes resources are created in order to run a Solr Cloud. +Refer to the xref:solr-cloud:dependencies.adoc[dependencies outline] to see what dependent Kuberenetes resources are created in order to run a Solr Cloud. -## Scaling a SolrCloud +== Scaling a SolrCloud The SolrCloud CRD support the Kubernetes `scale` operation, to increase and decrease the number of Solr Nodes that are running within the cloud. -``` +---- # Issue the scale command kubectl scale --replicas=5 solrcloud/example -``` +---- -For more information on SolrCloud scaling, refer to the [scaling page](scaling.md). +For more information on SolrCloud scaling, refer to the xref:solr-cloud:scaling.adoc[scaling page]. After issuing the scale command, start hitting the "Refresh" button in the Admin UI. You will see how the new Solr nodes are added. You can also watch the status via the `kubectl get solrclouds` command: -```bash +[source,bash] +---- watch -dc kubectl get solrclouds # Hit Control-C when done -``` +---- -### Deleting the example SolrCloud +=== Deleting the example SolrCloud Delete the example SolrCloud -```bash +[source,bash] +---- $ kubectl delete solrcloud example -``` - -## Solr Images +---- + +== Solr Images -### Official Solr Images +=== Official Solr Images -The Solr Operator is only guaranteed to work with [official Solr images](https://hub.docker.com/_/solr). +The Solr Operator is only guaranteed to work with https://hub.docker.com/_/solr[official Solr images]. However, as long as your custom image is built to be compatible with the official image, things should go smoothly. This is especially true starting with Solr 9, where the docker image creation is bundled within Solr. Run `./gradlew docker` in the Solr repository, and your custom Solr additions will be packaged into an officially compliant Solr Docker image. -Please refer to the [Version Compatibility Matrix](../upgrade-notes.md#solr-versions) for more information on what Solr Versions are compatible with the Solr Operator. +Please refer to the xref:upgrade-notes:upgrade-notes.adoc#solr-versions[Version Compatibility Matrix] for more information on what Solr Versions are compatible with the Solr Operator. Also note that certain features available within the Solr Operator are only supported in newer Solr Versions. -The version compatibility matrix shows the minimum Solr version supported for **most** options. +The version compatibility matrix shows the minimum Solr version supported for *most* options. Please refer to the Solr Reference guide to see what features are enabled for the Solr version you are running. -### Build Your Own Private Solr Images +=== Build Your Own Private Solr Images -The Solr Operator supports private Docker repo access for Solr images you may want to store in a private Docker repo. It is recommended to source your image from the official Solr images. +The Solr Operator supports private Docker repo access for Solr images you may want to store in a private Docker repo. It is recommended to source your image from the official Solr images. Using a private image requires you have a K8s secret preconfigured with appropriate access to the image. (type: kubernetes.io/dockerconfigjson) -``` +---- apiVersion: solr.apache.org/v1beta1 kind: SolrCloud metadata: @@ -132,4 +136,4 @@ spec: repository: myprivate-repo.jfrog.io/solr tag: 8.2.0 imagePullSecret: "k8s-docker-registry-secret" -``` +---- diff --git a/docs/modules/solr-cloud/pages/managed-updates.adoc b/docs/modules/solr-cloud/pages/managed-updates.adoc new file mode 100644 index 00000000..9695c604 --- /dev/null +++ b/docs/modules/solr-cloud/pages/managed-updates.adoc @@ -0,0 +1,118 @@ += Managed SolrCloud Rolling Updates +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +_Since v0.2.7_ + +Solr Clouds are complex distributed systems, and thus require a more delicate and informed approach to rolling updates. + +If the xref:solr-cloud:solr-cloud-crd.adoc#update-strategy[`Managed` update strategy] is specified in the Solr Cloud CRD, then the Solr Operator will take control over deleting SolrCloud pods when they need to be updated. + +The operator will find all pods that have not been updated yet and choose the next set of pods to delete for an update, given the following workflow. + +Note: Managed Updates are a executed via xref:solr-cloud:cluster-operations.adoc[Cluster Operation Locks], please refer to the documentation for more information about how these operations are executed. + +== Pod Update Workflow + +The logic goes as follows: + +. Find the pods that are out-of-date +. Update all out-of-date pods that do not have a started Solr container. + * This allows for updating a pod that cannot start, even if other pods are not available. + * This step does not respect the `maxPodsUnavailable` option, because these pods have not even started the Solr process. +. Retrieve the cluster state of the SolrCloud if there are any `ready` pods. + * If no pods are ready, then there is no endpoint to retrieve the cluster state from. +. Sort the pods in order of safety for being restarted. <> +. Iterate through the sorted pods, greedily choosing which pods to update. <> + * The maximum number of pods that can be updated are determined by starting with `maxPodsUnavailable`, +then subtracting the number of updated pods that are unavailable as well as the number of not-yet-started, out-of-date pods that were updated in a previous step. +This check makes sure that any pods taken down during this step do not violate the `maxPodsUnavailable` constraint. + + +=== Pod Update Sorting Order + +The pods are sorted by the following criteria, in the given order. +If any two pods on a criterion, then the next criteria (in the following order) is used to sort them. + +In this context the pods sorted highest are the first chosen to be updated, the pods sorted lowest will be selected last. + +. If the pod is the overseer, it will be sorted lowest. +. If the pod is not represented in the clusterState, it will be sorted highest. + * A pod is not in the clusterstate if it does not host any replicas and is not the overseer. +. Number of leader replicas hosted in the pod, sorted low -> high +. Number of active or recovering replicas hosted in the pod, sorted low -> high +. Number of total replicas hosted in the pod, sorted low -> high +. If the pod is not a liveNode, then it will be sorted lower. +. Any pods that are equal on the above criteria will be sorted lexicographically. + +=== Pod Update Selection Logic + +Loop over the sorted pods, until the number of pods selected to be updated has reached the maximum. +This maximum is calculated by taking the given, or default, xref:solr-cloud:solr-cloud-crd.adoc#update-strategy[`maxPodsUnavailable`] and subtracting the number of updated pods that are unavailable or have yet to be re-created. + +* If the pod is the overseer, then all other pods must be updated and available. + Otherwise, the overseer pod cannot be updated. +* If the pod contains no replicas, the pod is chosen to be updated. + + *WARNING*: If you use Solr worker nodes for streaming expressions, you will likely want to set xref:solr-cloud:solr-cloud-crd.adoc#update-strategy[`maxPodsUnavailable`] to a value you are comfortable with. +* If Solr Node of the pod is not *`live`*, the pod is chosen to be updated. +* If all replicas in the pod are in a *`down`* or *`recovery_failed`* state, the pod is chosen to be updated. +* If the taking down the replicas hosted in the pod would not violate the given xref:solr-cloud:solr-cloud-crd.adoc#update-strategy[`maxShardReplicasUnavailable`], then the pod can be updated. + Once a pod with replicas has been chosen to be updated, the replicas hosted in that pod are then considered unavailable for the rest of the selection logic. +** Some replicas in the shard may already be in a non-active state, or may reside on Solr Nodes that are not "live". + The `maxShardReplicasUnavailable` calculation will take these replicas into account, as a starting point. +** If a pod contains non-active replicas, and the pod is chosen to be updated, then the pods that are already non-active will not be double counted for the `maxShardReplicasUnavailable` calculation. + +== Triggering a Manual Rolling Restart + +Given these complex requirements, `kubectl rollout restart statefulset` will generally not work on a SolrCloud. + +One option to trigger a manual restart is to change one of the podOptions annotations. For example you could set this to the date and time of the manual restart. + +[source,yaml] +---- +apiVersion: solr.apache.org/v1beta1 +kind: SolrCloud +spec: + customSolrKubeOptions: + podOptions: + annotations: + manualrestart: "2021-10-20T08:37:00Z" +---- + +== Pod Readiness during updates + +The Solr Operator sets up at least two Services for every SolrCloud. + +* Always +** A clusterIP service for all solr nodes (What we call the "common service") +* Either +** A https://kubernetes.io/docs/concepts/services-networking/service/#headless-services[Headless Service] for individual Solr Node endpoints that are not exposed via an Ingress. +** Individual clusterIP services for Solr Nodes that are exposed via an Ingress + +Only the common service uses the `publishNotReadyAddresses: false` option, since the common service should load balance between all available nodes. +The other services have individual endpoints for each node, so there is no reason to de-list pods that are not available. + +When doing a rolling upgrade, or taking down a pod for any reason, we want to first stop all requests to this pod. +Solr will do this while stopping by first taking itself out of the cluster's set of `liveNodes` , so that other Solr nodes and clients think it is not running. +However, for ephemeral clusters we are also evicting data before the pod is deleted. So we want to stop requests to this node since the data will soon no-longer live there. + +Kubernetes allows the Solr Operator to control whether a pod is considered `ready`, or available for requests, via https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-gate[readinessConditions/readinessGates]. +When the Solr Operator begins the shut-down procedure for a pod, it will first set a `readinessCondition` to `false`, so that no loadBalanced requests (through the common service) go to the pod. +This readinessCondition will stay set to `false` until the pod is deleted and a new pod is created in its place. + +*For this reason, it's a good idea to avoid very aggressive xref:solr-cloud:solr-cloud-crd.adoc#update-strategy[Update Strategies]. +During a rolling restart with a high `maxPodsUnavailable`, requests that go through the common service might be routed to a very small number of pods.* diff --git a/docs/solr-cloud/scaling.md b/docs/modules/solr-cloud/pages/scaling.adoc similarity index 60% rename from docs/solr-cloud/scaling.md rename to docs/modules/solr-cloud/pages/scaling.adoc index 491cbba4..135764b3 100644 --- a/docs/solr-cloud/scaling.md +++ b/docs/modules/solr-cloud/pages/scaling.adoc @@ -1,52 +1,54 @@ - - -# SolrCloud Scaling += SolrCloud Scaling +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + _Since v0.8.0_ Solr Clouds are complex distributed systems, and thus require additional help when trying to scale up or down. Scaling/Autoscaling can mean different things in different situations, and this is true even within the `SolrCloud.spec.scaling` section. -- Replicas can be moved when new nodes are added or when nodes need to be taken down -- Nodes can be added/removed if more or less resources are desired. + +* Replicas can be moved when new nodes are added or when nodes need to be taken down +* Nodes can be added/removed if more or less resources are desired. The following sections describes all the features that the Solr Operator currently supports to aid in scaling & autoscaling SolrClouds. -## Configuration +== Configuration The `scaling` section in the SolrCloud CRD can be configured in the following ways -```yaml +[source,yaml] +---- spec: scaling: vacatePodsOnScaleDown: true # Default: true populatePodsOnScaleUp: true # Default: true -``` +---- -## Replica Movement +== Replica Movement Solr can be scaled up & down either manually or by `HorizontalPodAutoscaler`'s, however no matter how the `SolrCloud.Spec.Replicas` value changes, the Solr Operator must implement this change the same way. For now Replicas are not scaled up and down themselves, they are just moved to utilize new Solr pods or vacate soon-to-be-deleted Solr pods. -Note: Scaling actions with replica movements are a executed via [Cluster Operation Locks](cluster-operations.md), please refer to the documentation for more information about how these operations are executed. +Note: Scaling actions with replica movements are a executed via xref:solr-cloud:cluster-operations.adoc[Cluster Operation Locks], please refer to the documentation for more information about how these operations are executed. -### Solr Pod Scale-Down +=== Solr Pod Scale-Down When the desired number of Solr Pods that should be run `SolrCloud.Spec.Replicas` is decreased, the `SolrCloud.spec.scaling.vacatePodsOnScaleDown` option determines whether the Solr Operator should move replicas @@ -66,28 +68,29 @@ that change will be reflected in the StatefulSet immediately. Pods will be deleted even if replicas live on those pods. If `scaling.vacatePodsOnScaleDown` option is enabled, which it is by default, then the following steps occur: -1. Acquire a cluster-ops lock on the SolrCloud. (This means other cluster operations, such as a rolling restart and scale up, cannot occur during the scale down operation) -1. Scale down the last pod. - 1. Mark the pod as "notReady" so that traffic is diverted away from this pod (for requests to the common endpoint, requests that target that node directly will not be affected). - 1. Check to see if the last pod has any replicas. - 1. If so, start an asynchronous command to remove replicas from this pod. - 1. Check if the async command completed, if not then loop back until the command is finished. - 1. If the command succeeded, continue, if not go back to step #2.3. - 1. Scale down the StatefulSet by 1. This will delete the pod that was just vacated. -1. If the StatefulSet size == the desired SolrCloud size, continue, otherwise go back to step #2. -1. Give up the cluster-ops lock on the SolrCloud. The scale-down operation is complete. + +. Acquire a cluster-ops lock on the SolrCloud. (This means other cluster operations, such as a rolling restart and scale up, cannot occur during the scale down operation) +. Scale down the last pod. + . Mark the pod as "notReady" so that traffic is diverted away from this pod (for requests to the common endpoint, requests that target that node directly will not be affected). + . Check to see if the last pod has any replicas. + . If so, start an asynchronous command to remove replicas from this pod. + . Check if the async command completed, if not then loop back until the command is finished. + . If the command succeeded, continue, if not go back to step #2.3. + . Scale down the StatefulSet by 1. This will delete the pod that was just vacated. +. If the StatefulSet size == the desired SolrCloud size, continue, otherwise go back to step #2. +. Give up the cluster-ops lock on the SolrCloud. The scale-down operation is complete. Because of the available Solr APIs, the statefulSet can only be scaled down 1 pod at-a-time, this is why the Scale down step is repeated until the statefulSet size reaches the desired size. -#### Scale to Zero +==== Scale to Zero If the `SolrCloud.spec.replicas` is set to 0, then the SolrCloud will set the statefulSet replicas to 0 without moving or deleting replicas. The data will be saved in PVCs if the SolrCloud is set to use persistent storage, and `dataStorage.persistent.reclaimPolicy` is set to `Retain`. If the `reclaimPolicy` is set to `Delete`, these PVCs will be deleted when the pods are scaled down. -### Solr Pod Scale-Up +=== Solr Pod Scale-Up When the desired number of Solr Pods that should be run `SolrCloud.Spec.Replicas` is increased, the `SolrCloud.spec.scaling.populatePodsOnScaleUp` option determines whether the Solr Operator should move replicas @@ -99,17 +102,18 @@ This means that the new pods that are created will likely remain empty until the This could be creating collections, migrating replicas or scaling up existing shards/collections. If `scaling.populatePodsOnScaleUp` option is enabled, which it is by default, then the following steps occur: -1. Acquire a cluster-ops lock on the SolrCloud. (This means other cluster operations, such as a rolling restart and scale down, cannot occur during the scale up operation) -1. Scale up to the StatefulSet to the desired `spec.replicas` (number of pods). -1. Wait for all pods in the cluster to become healthy. + +. Acquire a cluster-ops lock on the SolrCloud. (This means other cluster operations, such as a rolling restart and scale down, cannot occur during the scale up operation) +. Scale up to the StatefulSet to the desired `spec.replicas` (number of pods). +. Wait for all pods in the cluster to become healthy. * Rolling restarts cannot occur at the same time, so most likely every existing pod will be ready, and we will just be waiting for the newly created pods. -1. Start an asynchronous command to balance replicas across all pods. (This does not just target the newly created pods) -1. Check if the async command completed, if not then loop back until the command is finished. -1. If the command succeeded, continue, if not go back to step #4. -1. Give up the cluster-ops lock on the SolrCloud. The scale-up operation is complete. +. Start an asynchronous command to balance replicas across all pods. (This does not just target the newly created pods) +. Check if the async command completed, if not then loop back until the command is finished. +. If the command succeeded, continue, if not go back to step #4. +. Give up the cluster-ops lock on the SolrCloud. The scale-up operation is complete. -#### Solr Version Compatibility +==== Solr Version Compatibility The managed scale-up option relies on the BalanceReplicas API in Solr, which was added in Solr 9.3. Therefore, this option cannot be used with Solr versions < 9.3. diff --git a/docs/solr-cloud/solr-cloud-crd.md b/docs/modules/solr-cloud/pages/solr-cloud-crd.adoc similarity index 67% rename from docs/solr-cloud/solr-cloud-crd.md rename to docs/modules/solr-cloud/pages/solr-cloud-crd.adoc index 03051881..dcbb1c19 100644 --- a/docs/solr-cloud/solr-cloud-crd.md +++ b/docs/modules/solr-cloud/pages/solr-cloud-crd.adoc @@ -1,35 +1,34 @@ - - -# The SolrCloud CRD += The SolrCloud CRD +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. The SolrCloud CRD allows users to spin up a Solr cloud in a very configurable way. Those configuration options are laid out on this page. -## Solr Options +== Solr Options The SolrCloud CRD gives users the ability to customize how Solr is run. Please note that the options described below are shown using the base SolrCloud resource, not the helm chart. Most options will have the same name and path, however there are differences such as `customSolrKubeOptions`. -If using Helm, refer to the [Helm Chart documentation](https://artifacthub.io/packages/helm/apache-solr/solr#chart-values) to see the names for the options you are looking to use. +If using Helm, refer to the https://artifacthub.io/packages/helm/apache-solr/solr#chart-values[Helm Chart documentation] to see the names for the options you are looking to use. This document should still be used to see how the SolrCloud options can be used. -### Solr Modules and Additional Libraries +=== Solr Modules and Additional Libraries _Since v0.5.0_ Solr comes packaged with modules that can be loaded optionally, known as either Solr Modules or Solr Contrib Modules. @@ -39,44 +38,44 @@ Use the **`SolrCloud.spec.solrModules`** property to add a list of module names, However, users might want to include custom code that is not an official Solr Module. In order to facilitate this, the **`SolrCloud.spec.additionalLibs`** property takes a list of paths to folders, containing jars to load in the classpath of the SolrCloud. -## Data Storage +== Data Storage The SolrCloud CRD gives the option for users to use either -persistent storage, through [PVCs](https://kubernetes.io/docs/concepts/storage/persistent-volumes/), -or ephemeral storage, through [emptyDir volumes](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir), +persistent storage, through https://kubernetes.io/docs/concepts/storage/persistent-volumes/[PVCs], +or ephemeral storage, through https://kubernetes.io/docs/concepts/storage/volumes/#emptydir[emptyDir volumes], to store Solr data. Ephemeral and persistent storage cannot be used together, if both are provided, the `persistent` options take precedence. If neither is provided, ephemeral storage will be used by default. These options can be found in `SolrCloud.spec.dataStorage` -- **`persistent`** - - **`reclaimPolicy`** - - _Since v0.2.7_ - - Either `Retain`, the default, or `Delete`. - This describes the lifecycle of PVCs that are deleted after the SolrCloud is deleted, or the SolrCloud is scaled down and the pods that the PVCs map to no longer exist. - `Retain` is used by default, as that is the default Kubernetes policy, to leave PVCs in case pods, or StatefulSets are deleted accidentally. - - Note: If reclaimPolicy is set to `Delete`, PVCs will not be deleted if pods are merely deleted. They will only be deleted once the `SolrCloud.spec.replicas` is scaled down or deleted. - - **`pvcTemplate`** - The template of the PVC to use for the solr data PVCs. By default the name will be "data". - Only the `pvcTemplate.spec` field is required, metadata is optional. - - Note: Currently, [Kubernetes does not support PVC resizing (expanding) in StatefulSets](https://github.com/kubernetes/enhancements/issues/661). - However, the Solr Operator will manage the PVC expansion for users until this is supported by default in Kubernetes. - Therefore the `pvcTemplate.spec` can have an update to `pvcTemplate.spec.resources.requests`, but all other fields should be considered immutable. - - The storage size can only be increased (PVCs cannot be shrunk), and the backing [`StorageClass` must allow volume expansion](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#expanding-persistent-volumes-claims) (`allowVolumeExpansion: true`). - When the size is increased, the operator resizes the data PVCs and then performs a rolling restart of the SolrCloud so the new capacity is picked up on each node. - If the storage class does not allow expansion, or the request would shrink the PVCs, the operator emits a warning event on the SolrCloud and leaves the storage unchanged. -- **`ephemeral`** - - There are two types of ephemeral volumes that can be specified. - Both are optional, and if none are specified then an empty `emptyDir` volume source is used. - If both are specified then the `hostPath` volume source will take precedence. - - **`emptyDir`** - An [`emptyDir` volume source](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) that describes the desired emptyDir volume to use in each SolrCloud pod to store data. - - **`hostPath`** - A [`hostPath` volume source](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) that describes the desired hostPath volume to use in each SolrCloud pod to store data. - -## Update Strategy +* **`persistent`** +** **`reclaimPolicy`** - +_Since v0.2.7_ - +Either `Retain`, the default, or `Delete`. +This describes the lifecycle of PVCs that are deleted after the SolrCloud is deleted, or the SolrCloud is scaled down and the pods that the PVCs map to no longer exist. +`Retain` is used by default, as that is the default Kubernetes policy, to leave PVCs in case pods, or StatefulSets are deleted accidentally. ++ +NOTE: If reclaimPolicy is set to `Delete`, PVCs will not be deleted if pods are merely deleted. They will only be deleted once the `SolrCloud.spec.replicas` is scaled down or deleted. +** **`pvcTemplate`** - The template of the PVC to use for the solr data PVCs. By default the name will be "data". +Only the `pvcTemplate.spec` field is required, metadata is optional. ++ +NOTE: Currently, https://github.com/kubernetes/enhancements/issues/661[Kubernetes does not support PVC resizing (expanding) in StatefulSets]. +However, the Solr Operator will manage the PVC expansion for users until this is supported by default in Kubernetes. +Therefore the `pvcTemplate.spec` can have an update to `pvcTemplate.spec.resources.requests`, but all other fields should be considered immutable. ++ +The storage size can only be increased (PVCs cannot be shrunk), and the backing https://kubernetes.io/docs/concepts/storage/persistent-volumes/#expanding-persistent-volumes-claims[`StorageClass` must allow volume expansion] (`allowVolumeExpansion: true`). +When the size is increased, the operator resizes the data PVCs and then performs a rolling restart of the SolrCloud so the new capacity is picked up on each node. +If the storage class does not allow expansion, or the request would shrink the PVCs, the operator emits a warning event on the SolrCloud and leaves the storage unchanged. +* **`ephemeral`** ++ +There are two types of ephemeral volumes that can be specified. +Both are optional, and if none are specified then an empty `emptyDir` volume source is used. +If both are specified then the `hostPath` volume source will take precedence. +** **`emptyDir`** - An https://kubernetes.io/docs/concepts/storage/volumes/#emptydir[`emptyDir` volume source] that describes the desired emptyDir volume to use in each SolrCloud pod to store data. +** **`hostPath`** - A https://kubernetes.io/docs/concepts/storage/volumes/#hostpath[`hostPath` volume source] that describes the desired hostPath volume to use in each SolrCloud pod to store data. + +== Update Strategy _Since v0.2.7_ The SolrCloud CRD provides users the ability to define how Pod updates should be managed, through `SolrCloud.Spec.updateStrategy`. @@ -84,35 +83,37 @@ This provides the following options: Under `SolrCloud.Spec.updateStrategy`: -- **`method`** - The method in which Solr pods should be updated. Enum options are as follows: - - `Managed` - (Default) The Solr Operator will take control over deleting pods for updates. This process is [documented here](managed-updates.md). - - `StatefulSet` - Use the default StatefulSet rolling update logic, one pod at a time waiting for all pods to be "ready". - - `Manual` - Neither the StatefulSet or the Solr Operator will delete pods in need of an update. The user will take responsibility over this. -- **`managed`** - Options for rolling updates managed by the Solr Operator. - - **`maxPodsUnavailable`** - (Defaults to `"25%"`) The number of Solr pods in a Solr Cloud that are allowed to be unavailable during the rolling restart. - More pods may become unavailable during the restart, however the Solr Operator will not kill pods if the limit has already been reached. - - **`maxShardReplicasUnavailable`** - (Defaults to `1`) The number of replicas for each shard allowed to be unavailable during the restart. -- **`restartSchedule`** - A [CRON](https://en.wikipedia.org/wiki/Cron) schedule for automatically restarting the Solr Cloud. - [Multiple CRON syntaxes](https://pkg.go.dev/github.com/robfig/cron/v3?utm_source=godoc#hdr-CRON_Expression_Format) are supported, such as intervals (e.g. `@every 10h`) or predefined schedules (e.g. `@yearly`, `@weekly`, etc.). - -**Note:** Both `maxPodsUnavailable` and `maxShardReplicasUnavailable` are intOrString fields. So either an int or string can be provided for the field. -- **int** - The parameter is treated as an absolute value, unless the value is <= 0 which is interpreted as unlimited. -- **string** - Only percentage string values (`"0%"` - `"100%"`) are accepted, all other values will be ignored. - - **`maxPodsUnavailable`** - The `maximumPodsUnavailable` is calculated as the percentage of the total pods configured for that Solr Cloud. - - **`maxShardReplicasUnavailable`** - The `maxShardReplicasUnavailable` is calculated independently for each shard, as the percentage of the number of replicas for that shard. - -### Pod Disruption Budgets +* **`method`** - The method in which Solr pods should be updated. Enum options are as follows: +** `Managed` - (Default) The Solr Operator will take control over deleting pods for updates. This process is xref:solr-cloud:managed-updates.adoc[documented here]. +** `StatefulSet` - Use the default StatefulSet rolling update logic, one pod at a time waiting for all pods to be "ready". +** `Manual` - Neither the StatefulSet or the Solr Operator will delete pods in need of an update. The user will take responsibility over this. +* **`managed`** - Options for rolling updates managed by the Solr Operator. +** **`maxPodsUnavailable`** - (Defaults to `"25%"`) The number of Solr pods in a Solr Cloud that are allowed to be unavailable during the rolling restart. +More pods may become unavailable during the restart, however the Solr Operator will not kill pods if the limit has already been reached. +** **`maxShardReplicasUnavailable`** - (Defaults to `1`) The number of replicas for each shard allowed to be unavailable during the restart. +* **`restartSchedule`** - A https://en.wikipedia.org/wiki/Cron[CRON] schedule for automatically restarting the Solr Cloud. +https://pkg.go.dev/github.com/robfig/cron/v3?utm_source=godoc#hdr-CRON_Expression_Format[Multiple CRON syntaxes] are supported, such as intervals (e.g. `@every 10h`) or predefined schedules (e.g. `@yearly`, `@weekly`, etc.). + +NOTE: Both `maxPodsUnavailable` and `maxShardReplicasUnavailable` are intOrString fields. So either an int or string can be provided for the field. + +* **int** - The parameter is treated as an absolute value, unless the value is <= 0 which is interpreted as unlimited. +* **string** - Only percentage string values (`"0%"` - `"100%"`) are accepted, all other values will be ignored. +** **`maxPodsUnavailable`** - The `maximumPodsUnavailable` is calculated as the percentage of the total pods configured for that Solr Cloud. +** **`maxShardReplicasUnavailable`** - The `maxShardReplicasUnavailable` is calculated independently for each shard, as the percentage of the number of replicas for that shard. + +=== Pod Disruption Budgets _Since v0.7.0_ -The Solr Operator can optionally create a [`PodDisruptionBudget`](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#pod-disruption-budgets) to ensure that Kubernetes does not take down more than an acceptable amount of SolrCloud nodes at a time. +The Solr Operator can optionally create a https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#pod-disruption-budgets[`PodDisruptionBudget`] to ensure that Kubernetes does not take down more than an acceptable amount of SolrCloud nodes at a time. This behavior is controlled by the `.spec.availability.podDisruptionBudget.enabled` setting, which defaults to "true" but can be disabled if desired as in the snippet below: -```yaml +[source,yaml] +---- spec: availability: podDisruptionBudget: enabled: false -``` +---- When not disabled, the PDB's `maxUnavailable` setting is populated from the `maxPodsUnavailable` setting in `SolrCloud.Spec.updateStrategy.managed`. If this option is not set, it will use the default value (`25%`). @@ -120,115 +121,120 @@ If this option is not set, it will use the default value (`25%`). Currently, the implementation does not take shard/replica topology into account, like the update strategy does. So although Kubernetes might just take down 25% of a Cloud's nodes, that might represent all nodes that host a shard's replicas. This is ongoing work, and hopefully something the Solr Operator can protect against in the future. -See [this discussion](https://github.com/apache/solr-operator/issues/471) for more information. +See https://github.com/apache/solr-operator/issues/471[this discussion] for more information. -## Addressability +== Addressability _Since v0.2.6_ The SolrCloud CRD provides users the ability to define how it is addressed, through the following options: Under `SolrCloud.Spec.solrAddressability`: -- **`podPort`** - The port on which the pod is listening. This is also that the port that the Solr Jetty service will listen on. (Defaults to `8983`) -- **`commonServicePort`** - The port on which the common service is exposed. (Defaults to `80`) -- **`kubeDomain`** - Specifies an override of the default Kubernetes cluster domain name, `cluster.local`. This option should only be used if the Kubernetes cluster has been setup with a custom domain name. -- **`external`** - Expose the cloud externally, outside of the kubernetes cluster in which it is running. - - **`method`** - (Required) The method by which your cloud will be exposed externally. - Currently available options are [`Ingress`](https://kubernetes.io/docs/concepts/services-networking/ingress/) and [`ExternalDNS`](https://github.com/kubernetes-sigs/external-dns). - The goal is to support more methods in the future, such as LoadBalanced Services. - - **`domainName`** - (Required) The primary domain name to open your cloud endpoints on. If `useExternalAddress` is set to `true`, then this is the domain that will be used in Solr Node names. - - **`additionalDomainNames`** - You can choose to listen on additional domains for each endpoint, however Solr will not register itself under these names. - - **`useExternalAddress`** - Use the external address to advertise the SolrNode. If a domain name is required for the chosen external `method`, then the one provided in `domainName` will be used. \ - This can not be set to `true` when **`hideNodes`** is set to `true` or **`ingressTLSTermination`** is used. - - **`hideCommon`** - Do not externally expose the common service (one endpoint for all solr nodes). - - **`hideNodes`** - Do not externally expose each node. (This cannot be set to `true` if the cloud is running across multiple kubernetes clusters) - - **`nodePortOverride`** - Make the Node Service(s) override the podPort. This is only available for the `Ingress` external method. If `hideNodes` is set to `true`, then this option is ignored. If provided, this port will be used to advertise the Solr Node. \ - If `method: Ingress` and `hideNodes: false`, then this value defaults to `80` since that is the default port that ingress controllers listen on. - - **`ingressTLSTermination`** - Terminate TLS for the SolrCloud at the `Ingress`, if using the `Ingress` **method**. This will leave the inter-node communication within the cluster to use HTTP. \ - This option may not be used with **`useExternalAddress`**. Only one sub-option can be provided. - - **`useDefaultTLSSecret`** - Use the default TLS Secret set by your Ingress controller, if your Ingress controller supports this feature. Cannot be used when `tlsSecret` is used. \ - For example, using nginx: https://kubernetes.github.io/ingress-nginx/user-guide/tls/#default-ssl-certificate - - **`tlsSecret`** - Name a of Kubernetes TLS Secret to terminate TLS when using the `Ingress` method. Cannot be used when `useDefaultTlsSecret` is used. - -**Note:** Unless both `external.method=Ingress` and `external.hideNodes=false`, a headless service will be used to make each Solr Node in the statefulSet addressable. +* **`podPort`** - The port on which the pod is listening. This is also that the port that the Solr Jetty service will listen on. (Defaults to `8983`) +* **`commonServicePort`** - The port on which the common service is exposed. (Defaults to `80`) +* **`kubeDomain`** - Specifies an override of the default Kubernetes cluster domain name, `cluster.local`. This option should only be used if the Kubernetes cluster has been setup with a custom domain name. +* **`external`** - Expose the cloud externally, outside of the kubernetes cluster in which it is running. +** **`method`** - (Required) The method by which your cloud will be exposed externally. +Currently available options are https://kubernetes.io/docs/concepts/services-networking/ingress/[`Ingress`] and https://github.com/kubernetes-sigs/external-dns[`ExternalDNS`]. +The goal is to support more methods in the future, such as LoadBalanced Services. +** **`domainName`** - (Required) The primary domain name to open your cloud endpoints on. If `useExternalAddress` is set to `true`, then this is the domain that will be used in Solr Node names. +** **`additionalDomainNames`** - You can choose to listen on additional domains for each endpoint, however Solr will not register itself under these names. +** **`useExternalAddress`** - Use the external address to advertise the SolrNode. If a domain name is required for the chosen external `method`, then the one provided in `domainName` will be used. +This can not be set to `true` when **`hideNodes`** is set to `true` or **`ingressTLSTermination`** is used. +** **`hideCommon`** - Do not externally expose the common service (one endpoint for all solr nodes). +** **`hideNodes`** - Do not externally expose each node. (This cannot be set to `true` if the cloud is running across multiple kubernetes clusters) +** **`nodePortOverride`** - Make the Node Service(s) override the podPort. This is only available for the `Ingress` external method. If `hideNodes` is set to `true`, then this option is ignored. If provided, this port will be used to advertise the Solr Node. +If `method: Ingress` and `hideNodes: false`, then this value defaults to `80` since that is the default port that ingress controllers listen on. +** **`ingressTLSTermination`** - Terminate TLS for the SolrCloud at the `Ingress`, if using the `Ingress` **method**. This will leave the inter-node communication within the cluster to use HTTP. +This option may not be used with **`useExternalAddress`**. Only one sub-option can be provided. +*** **`useDefaultTLSSecret`** - Use the default TLS Secret set by your Ingress controller, if your Ingress controller supports this feature. Cannot be used when `tlsSecret` is used. +For example, using nginx: https://kubernetes.github.io/ingress-nginx/user-guide/tls/#default-ssl-certificate +*** **`tlsSecret`** - Name a of Kubernetes TLS Secret to terminate TLS when using the `Ingress` method. Cannot be used when `useDefaultTlsSecret` is used. + +NOTE: Unless both `external.method=Ingress` and `external.hideNodes=false`, a headless service will be used to make each Solr Node in the statefulSet addressable. If both of those criteria are met, then an individual ClusterIP Service will be created for each Solr Node/Pod. If you are using an `Ingress` for external addressability, you can customize the created `Ingress` through `SolrCloud.spec.customSolrKubeOptions.ingressOptions`. Under this property, you can set custom `annotations`, `labels` and an `ingressClassName`. -**Note:** If you have no need for an `Ingress` or a specific hostname to address your SolrCloud cluster you can create a simple loadbalancer that can be addressed from outside the kubernetes cluster. To achieve this you can add annotations to `SolrCloud.spec.customSolrKubeOptions.commonServiceOptions.annotations`. Exposing the headlessService is an option as well through `SolrCloud.spec.customSolrKubeOptions.headlessServiceOptions.annotations`, mind that using the headless service requires a load balancing implementation in the client calling the SolrCloud api. +NOTE: If you have no need for an `Ingress` or a specific hostname to address your SolrCloud cluster you can create a simple loadbalancer that can be addressed from outside the kubernetes cluster. To achieve this you can add annotations to `SolrCloud.spec.customSolrKubeOptions.commonServiceOptions.annotations`. Exposing the headlessService is an option as well through `SolrCloud.spec.customSolrKubeOptions.headlessServiceOptions.annotations`, mind that using the headless service requires a load balancing implementation in the client calling the SolrCloud api. Snippet below shows you can create an NLB on AWS: -```yaml +[source,yaml] +---- spec: customSolrKubeOptions: commonServiceOptions: - annotations: + annotations: service.beta.kubernetes.io/aws-load-balancer-type: external service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip - service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing -``` + service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing +---- -## Backups +== Backups Solr Backups are enabled via the Solr Operator. -Please refer to the [SolrBackup documentation](../solr-backup) for more information on setting up a SolrCloud with backups enabled. +Please refer to the xref:solr-backup:index.adoc[SolrBackup documentation] for more information on setting up a SolrCloud with backups enabled. -## Zookeeper Reference +== Zookeeper Reference All SolrCloud resources run Solr in "cloud" mode, and require access to an Apache ZooKeeper cluster for state-management. The Solr operator gives a few options for ZooKeeper access: -- Connecting to an already running zookeeper ensemble via [connection strings](#zk-connection-info) -- [Spinning up a provided](#provided-instance) Zookeeper Ensemble in the same namespace via the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator) +* Connecting to an already running zookeeper ensemble via <> +* <> Zookeeper Ensemble in the same namespace via the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] These options are configured under `spec.zookeeperRef` -#### Chroot +[#chroot] +=== Chroot Both options below come with options to specify a `chroot`, or a ZNode path for solr to use as it's base "directory" in Zookeeper. Before the operator creates or updates a StatefulSet with a given `chroot`, it will first ensure that the given ZNode path exists and if it doesn't the operator will create all necessary ZNodes in the path. If no chroot is given, a default of `/` will be used, which doesn't require the existence check previously mentioned. If a chroot is provided without a prefix of `/`, the operator will add the prefix, as it is required by Zookeeper. -### ZK Connection Info +[#zk-connection-info] +=== ZK Connection Info This is an external/internal connection string as well as an optional chRoot to an already running Zookeeeper ensemble. If you provide an external connection string, you do not _have_ to provide an internal one as well. Under `spec.zookeeperRef`: -- **`connectionInfo`** - - **`externalConnectionString`** - The ZK connection string to the external Zookeeper cluster, e.g. `zoo1:2181` - - **`chroot`** - The chroot to use for the cluster +* **`connectionInfo`** +** **`externalConnectionString`** - The ZK connection string to the external Zookeeper cluster, e.g. `zoo1:2181` +** **`chroot`** - The chroot to use for the cluster External ZooKeeper clusters are often configured to use ZooKeeper features (e.g. securePort) which require corresponding configuration on the client side. To support these use-cases, users may provide arbitrary system properties under `spec.solrZkOpts` which will be passed down to all ZooKeeper clients (Solr, zkcli.sh, etc.) managed by the operator. -#### ACLs +==== ACLs _Since v0.2.7_ The Solr Operator allows for users to specify ZK ACL references in their Solr Cloud CRDs. The user must specify the name of a secret that resides in the same namespace as the cloud, that contains an ACL username value and an ACL password value. -This ACL must have admin permissions for the [chroot](#chroot) given. +This ACL must have admin permissions for the <> given. + +The ACL information can be provided through an ADMIN acl and a READ ONLY acl. -The ACL information can be provided through an ADMIN acl and a READ ONLY acl. -- Admin: `SolrCloud.spec.zookeeperRef.connectionInfo.acl` -- Read Only: `SolrCloud.spec.zookeeperRef.connectionInfo.readOnlyAcl` +* Admin: `SolrCloud.spec.zookeeperRef.connectionInfo.acl` +* Read Only: `SolrCloud.spec.zookeeperRef.connectionInfo.readOnlyAcl` All ACL fields are **required** if an ACL is used. -- **`secret`** - The name of the secret, in the same namespace as the SolrCloud, that contains the admin ACL username and password. -- **`usernameKey`** - The name of the key in the provided secret that stores the admin ACL username. -- **`passwordKey`** - The name of the key in the provided secret that stores the admin ACL password. +* **`secret`** - The name of the secret, in the same namespace as the SolrCloud, that contains the admin ACL username and password. +* **`usernameKey`** - The name of the key in the provided secret that stores the admin ACL username. +* **`passwordKey`** - The name of the key in the provided secret that stores the admin ACL password. -### Provided Instance +[#provided-instance] +=== Provided Instance If you do not require the Solr cloud to run cross-kube cluster, and do not want to manage your own Zookeeper ensemble, the solr-operator can manage Zookeeper ensemble(s) for you. -Using the [zookeeper-operator](https://github.com/pravega/zookeeper-operator), a new Zookeeper ensemble can be spun up for +Using the https://github.com/pravega/zookeeper-operator[zookeeper-operator], a new Zookeeper ensemble can be spun up for each solrCloud that has this option specified. The startup parameter `zookeeper-operator` must be provided on startup of the solr-operator for this parameter to be available. @@ -238,12 +244,13 @@ Zookeeper Conf and PodOptions provided in the linked Zookeeper Operator version However, this is a manual task, so not all options might be available. If there is an option available in the ZookeeperCluster CRD that is not exposed via the SolrCloud CRD, please create a Github Issue. -#### Zookeeper Storage Options +==== Zookeeper Storage Options _Since v0.4.0_ The Zookeeper Operator allows for both ephemeral and persistent storage, and the Solr Operator supports both as of `v0.4.0`. -```yaml +[source,yaml] +---- spec: zookeeperRef: provided: @@ -252,85 +259,96 @@ spec: persistence: reclaimPolicy: "Retain" # Either Retain or Delete spec: {} # PVC Spec for the Zookeeper volumes -``` +---- By default, if you do not provide either `ephemeral` or `persistence`, the Solr Operator will default to the type of storage you are using for your Solr pods. However, if you provide either object above, even if the object is empty, that storage type will be used for the created Zookeeper pods. If both `ephemeral` and `persistence` is provided, then `persistence` is preferred. -#### ACLs for Provided Ensembles +==== ACLs for Provided Ensembles _Since v0.3.0_ -If you want Solr to set ZK ACLs for znodes it creates in the `provided` ensemble, you can supply ACL credentials for an ADMIN and optionally a READ ONLY user using the following config settings: -- Admin: `SolrCloud.spec.zookeeperRef.provided.acl` -- Read Only: `SolrCloud.spec.zookeeperRef.provided.readOnlyAcl` +If you want Solr to set ZK ACLs for znodes it creates in the `provided` ensemble, you can supply ACL credentials for an ADMIN and optionally a READ ONLY user using the following config settings: + +* Admin: `SolrCloud.spec.zookeeperRef.provided.acl` +* Read Only: `SolrCloud.spec.zookeeperRef.provided.readOnlyAcl` All ACL fields are **required** if an ACL is used. -- **`secret`** - The name of the secret, in the same namespace as the SolrCloud, that contains the ACL username and password. -- **`usernameKey`** - The name of the key in the provided secret that stores the admin ACL username. -- **`passwordKey`** - The name of the key in the provided secret that stores the admin ACL password. +* **`secret`** - The name of the secret, in the same namespace as the SolrCloud, that contains the ACL username and password. +* **`usernameKey`** - The name of the key in the provided secret that stores the admin ACL username. +* **`passwordKey`** - The name of the key in the provided secret that stores the admin ACL password. -**Warning**: There is a known issue with the Zookeeper operator where it deploys pods with `skipACL=yes`, see: https://github.com/pravega/zookeeper-operator/issues/316. -This means that even if Solr sets the ACLs on znodes, they will not be enforced by Zookeeper. If your organization requires Solr to use ZK ACLs, then you'll need to -deploy Zookeeper to Kubernetes using another approach, such as using a Helm chart. +WARNING: There is a known issue with the Zookeeper operator where it deploys pods with `skipACL=yes`, see: https://github.com/pravega/zookeeper-operator/issues/316. +This means that even if Solr sets the ACLs on znodes, they will not be enforced by Zookeeper. If your organization requires Solr to use ZK ACLs, then you'll need to +deploy Zookeeper to Kubernetes using another approach, such as using a Helm chart. -## Scaling +== Scaling _Since v0.8.0_ -```yaml +[source,yaml] +---- spec: scaling: vacatePodsOnScaleDown: true populatePodsOnScaleUp: true -``` +---- -Please refer to the [Scaling page](scaling.md) for more information. +Please refer to the xref:solr-cloud:scaling.adoc[Scaling page] for more information. -## Override Built-in Solr Configuration Files +== Override Built-in Solr Configuration Files _Since v0.2.7_ -The Solr operator deploys well-configured SolrCloud instances with minimal input required from human operators. -As such, the operator installs various configuration files automatically, including `solr.xml` for node-level settings and `log4j2.xml` for logging. +The Solr operator deploys well-configured SolrCloud instances with minimal input required from human operators. +As such, the operator installs various configuration files automatically, including `solr.xml` for node-level settings and `log4j2.xml` for logging. However, there may come a time when you need to override the built-in configuration files with custom settings. -In general, users can provide custom config files by providing a ConfigMap in the same namespace as the SolrCloud instance; +In general, users can provide custom config files by providing a ConfigMap in the same namespace as the SolrCloud instance; all custom config files should be stored in the same user-provided ConfigMap under different keys. Point your SolrCloud definition to a user-provided ConfigMap using the following structure: -```yaml + +[source,yaml] +---- spec: ... customSolrKubeOptions: configMapOptions: providedConfigMap: -``` +---- -### Custom solr.xml +=== Custom solr.xml -Solr pods load node-level configuration settings from `/var/solr/data/solr.xml`. +Solr pods load node-level configuration settings from `/var/solr/data/solr.xml`. This important configuration file gets created by the `cp-solr-xml` initContainer which bootstraps the `solr.home` directory on each pod before starting the main container. The default `solr.xml` is mounted into the `cp-solr-xml` initContainer from a ConfigMap named `-solrcloud-configmap` (where `` is the name of your SolrCloud instance) created by the Solr operator. -_Note: The data in the default ConfigMap is not editable! Any changes to the `solr.xml` in the default ConfigMap created by the operator will be overwritten during the next reconcile cycle._ +NOTE: The data in the default ConfigMap is not editable! Any changes to the `solr.xml` in the default ConfigMap created by the operator will be overwritten during the next reconcile cycle. Many of the specific values in `solr.xml` can be set using Java system properties; for instance, the following setting controls the read timeout for the HTTP client used by Solr's `HttpShardHandlerFactory`: -```xml + +---- ${socketTimeout:600000} -``` +---- + The `${socketTimeout:600000}` syntax means pull the value from a Java system property named `socketTimeout` with default `600000` if not set. You can set Java system properties using the `solrOpts` string in your SolrCloud definition, such as: -```yaml + +[source,yaml] +---- spec: solrOpts: -DsocketTimeout=300000 -``` +---- + This same approach works for a number of settings in `solrconfig.xml` as well. -However, if you need to customize `solr.xml` beyond what can be accomplished with Java system properties, +However, if you need to customize `solr.xml` beyond what can be accomplished with Java system properties, then you need to supply your own `solr.xml` in a ConfigMap in the same namespace where you deploy your SolrCloud instance. Provide your custom XML in the ConfigMap using `solr.xml` as the key as shown in the example below: -```yaml + +[source,yaml] +---- --- kind: ConfigMap apiVersion: v1 @@ -342,50 +360,62 @@ data: ... CUSTOM CONFIG HERE ... -``` -**Important: Your custom `solr.xml` must include `${solr.port.advertise:0}` as the operator relies on this element to set the port Solr pods advertise to ZooKeeper. If this element is missing, then your Solr pods will not be created.** +---- + +IMPORTANT: Your custom `solr.xml` must include `${solr.port.advertise:0}` as the operator relies on this element to set the port Solr pods advertise to ZooKeeper. If this element is missing, then your Solr pods will not be created. You can get the default `solr.xml` from a Solr pod as a starting point for creating a custom config using `kubectl cp` as shown in the example below: -```bash + +[source,bash] +---- SOLR_POD_ID=$(kubectl get pod -l technology=solr-cloud --no-headers -o custom-columns=":metadata.name" | head -1) kubectl cp $SOLR_POD_ID:/var/solr/data/solr.xml ./custom-solr.xml -``` -This copies the default config from the first Solr pod found in the namespace and names it `custom-solr.xml`. Customize the settings in `custom-solr.xml` as needed and then create a ConfigMap using YAML. +---- -_Note: Using `kubectl create configmap --from-file` scrambles the XML formatting, so we recommend defining the configmap YAML as shown above to keep the XML formatted properly._ +This copies the default config from the first Solr pod found in the namespace and names it `custom-solr.xml`. Customize the settings in `custom-solr.xml` as needed and then create a ConfigMap using YAML. + +NOTE: Using `kubectl create configmap --from-file` scrambles the XML formatting, so we recommend defining the configmap YAML as shown above to keep the XML formatted properly. Point your SolrCloud instance at the custom ConfigMap using: -```yaml + +[source,yaml] +---- spec: customSolrKubeOptions: configMapOptions: providedConfigMap: custom-solr-xml -``` -_Note: If you set `providedConfigMap`, then the ConfigMap must include the `solr.xml` or `log4j2.xml` key, otherwise the SolrCloud will fail to reconcile._ +---- -#### Changes to Custom Config Trigger Rolling Restarts +NOTE: If you set `providedConfigMap`, then the ConfigMap must include the `solr.xml` or `log4j2.xml` key, otherwise the SolrCloud will fail to reconcile. + +==== Changes to Custom Config Trigger Rolling Restarts The Solr operator stores the MD5 hash of your custom XML in the StatefulSet's pod spec annotations (`spec.template.metadata.annotations`). To see the current annotations for your Solr pods, you can do: -```bash + +[source,bash] +---- kubectl annotate pod -l technology=solr-cloud --list=true -``` +---- + If the custom `solr.xml` changes in the user-provided ConfigMap, then the operator triggers a rolling restart of Solr pods to apply the updated configuration settings automatically. To summarize, if you need to customize `solr.xml`, provide your own version in a ConfigMap and changes made to the XML in the ConfigMap are automatically applied to your Solr pods. -### Custom Log Configuration +=== Custom Log Configuration _Since v0.3.0_ -By default, the Solr Docker image configures Solr to load its log configuration from `/var/solr/log4j2.xml`. +By default, the Solr Docker image configures Solr to load its log configuration from `/var/solr/log4j2.xml`. If you need to fine-tune the log configuration, then you can provide a custom `log4j2.xml` in a ConfigMap using the same basic process as described in the previous section for customizing `solr.xml`. If supplied, the operator overrides the log config using the `LOG4J_PROPS` env var. -As with custom `solr.xml`, the operator can track the MD5 hash of your `log4j2.xml` in the pod spec annotations to trigger a rolling restart if the log config changes. -However, Log4j2 supports hot reloading of log configuration using the `monitorInterval` attribute on the root `` element. For more information on this, see: [Log4j Automatic Reconfiguration](https://logging.apache.org/log4j/2.x/manual/configuration.html#AutomaticReconfiguration). -If your custom log config has a `monitorInterval` set, then the operator does not watch for changes to the log config and will not trigger a rolling restart if the config changes. +As with custom `solr.xml`, the operator can track the MD5 hash of your `log4j2.xml` in the pod spec annotations to trigger a rolling restart if the log config changes. +However, Log4j2 supports hot reloading of log configuration using the `monitorInterval` attribute on the root `` element. For more information on this, see: https://logging.apache.org/log4j/2.x/manual/configuration.html#AutomaticReconfiguration[Log4j Automatic Reconfiguration]. +If your custom log config has a `monitorInterval` set, then the operator does not watch for changes to the log config and will not trigger a rolling restart if the config changes. Kubernetes will automatically update the file on each pod's filesystem when the data in the ConfigMap changes. Once Kubernetes updates the file, Log4j will pick up the changes and apply them without restarting the Solr pod. If you need to customize both `solr.xml` and `log4j2.xml` then you need to supply both in the same ConfigMap using multiple keys as shown below: -```yaml + +[source,yaml] +---- --- kind: ConfigMap apiVersion: v1 @@ -404,47 +434,54 @@ data: ... YOUR CUSTOM SOLR XML CONFIG HERE ... -``` +---- -## Enable TLS Between Solr Pods +[#enable-tls-between-solr-pods] +== Enable TLS Between Solr Pods _Since v0.3.0_ -A common approach to securing traffic to your Solr cluster is to perform [**TLS termination** at the Ingress](#enable-ingress-tls-termination) and leave all traffic between Solr pods un-encrypted. +A common approach to securing traffic to your Solr cluster is to perform <> and leave all traffic between Solr pods un-encrypted. However, depending on how you expose Solr on your network, you may also want to encrypt traffic between Solr pods. The Solr operator provides **optional** configuration settings to enable TLS for encrypting traffic between Solr pods. -Enabling TLS for Solr is a straight-forward process once you have a [**PKCS12 keystore**]((https://en.wikipedia.org/wiki/PKCS_12)) containing an [X.509](https://en.wikipedia.org/wiki/X.509) certificate and private key; as of Java 8, PKCS12 is the default keystore format supported by the JVM. +Enabling TLS for Solr is a straight-forward process once you have a https://en.wikipedia.org/wiki/PKCS_12[**PKCS12 keystore**] containing an https://en.wikipedia.org/wiki/X.509[X.509] certificate and private key; as of Java 8, PKCS12 is the default keystore format supported by the JVM. -There are three basic use cases supported by the Solr operator. First, you can use cert-manager to issue a certificate and store the resulting PKCS12 keystore in a Kubernetes TLS secret. +There are three basic use cases supported by the Solr operator. First, you can use cert-manager to issue a certificate and store the resulting PKCS12 keystore in a Kubernetes TLS secret. Alternatively, you can create the TLS secret manually from a certificate obtained by some other means. In both cases, you simply point your SolrCloud CRD to the resulting TLS secret and corresponding keystore password secret. -Lastly, as of **v0.4.0**, you can supply the path to a directory containing TLS files that are mounted by some external agent or CSI driver. +Lastly, as of **v0.4.0**, you can supply the path to a directory containing TLS files that are mounted by some external agent or CSI driver. -### Use cert-manager to issue the certificate +=== Use cert-manager to issue the certificate -[cert-manager](https://cert-manager.io/docs/) is a popular Kubernetes controller for managing TLS certificates, including renewing certificates prior to expiration. -One of the primary benefits of cert-manager is it supports pluggable certificate `Issuer` implementations, including a self-signed Issuer for local development and an [ACME compliant](https://tools.ietf.org/html/rfc8555) Issuer for working with services like [Let’s Encrypt](https://letsencrypt.org/). +https://cert-manager.io/docs/[cert-manager] is a popular Kubernetes controller for managing TLS certificates, including renewing certificates prior to expiration. +One of the primary benefits of cert-manager is it supports pluggable certificate `Issuer` implementations, including a self-signed Issuer for local development and an https://tools.ietf.org/html/rfc8555[ACME compliant] Issuer for working with services like https://letsencrypt.org/[Let's Encrypt]. -If you already have a TLS certificate you want to use for Solr, then you don't need cert-manager and can skip down to [I already have a TLS Certificate](#i-already-have-a-tls-certificate) later in this section. +If you already have a TLS certificate you want to use for Solr, then you don't need cert-manager and can skip down to <> later in this section. If you do not have a TLS certificate, then we recommend installing **cert-manager** as it makes working with TLS in Kubernetes much easier. -#### Install cert-manager +==== Install cert-manager Given its popularity, cert-manager may already be installed in your Kubernetes cluster. To check if `cert-manager` is already installed, do: -```bash + +[source,bash] +---- kubectl get crds -l app.kubernetes.io/instance=cert-manager -``` +---- + If installed, you should see the following cert-manager related CRDs: -``` + +---- certificaterequests.cert-manager.io certificates.cert-manager.io challenges.acme.cert-manager.io clusterissuers.cert-manager.io issuers.cert-manager.io orders.acme.cert-manager.io -``` +---- If not installed, use Helm to install it into the `cert-manager` namespace: -```bash + +[source,bash] +---- if ! helm repo list | grep -q "https://charts.jetstack.io"; then helm repo add jetstack https://charts.jetstack.io helm repo update @@ -455,26 +492,32 @@ helm upgrade --install cert-manager jetstack/cert-manager \ --namespace cert-manager \ --version v1.1.0 \ --set installCRDs=true -``` -You’ll need admin privileges to install the CRDs in a shared K8s cluster, so work with your friendly Kubernetes admin to install if needed (most likely cert-manager will already be installed). -Refer to the [cert-manager Installation](https://cert-manager.io/docs/installation/kubernetes/) instructions for more information. +---- -#### Create cert-manager Certificate +You'll need admin privileges to install the CRDs in a shared K8s cluster, so work with your friendly Kubernetes admin to install if needed (most likely cert-manager will already be installed). +Refer to the https://cert-manager.io/docs/installation/kubernetes/[cert-manager Installation] instructions for more information. -Once cert-manager is installed, you need to create an `Issuer` or `ClusterIssuer` CRD and then request a certificate using a [Certificate CRD](https://cert-manager.io/docs/usage/certificate/). -Refer to the [cert-manager docs](https://cert-manager.io/docs/) on how to define a certificate. +==== Create cert-manager Certificate -Certificate Issuers are typically platform specific. For instance, on GKE, to create a Let’s Encrypt Issuer you need a service account with various cloud DNS permissions granted for DNS01 challenges to work, see: https://cert-manager.io/docs/configuration/acme/dns01/google/. +Once cert-manager is installed, you need to create an `Issuer` or `ClusterIssuer` CRD and then request a certificate using a https://cert-manager.io/docs/usage/certificate/[Certificate CRD]. +Refer to the https://cert-manager.io/docs/[cert-manager docs] on how to define a certificate. + +Certificate Issuers are typically platform specific. For instance, on GKE, to create a Let's Encrypt Issuer you need a service account with various cloud DNS permissions granted for DNS01 challenges to work, see: https://cert-manager.io/docs/configuration/acme/dns01/google/. The DNS names in your certificate should match the Solr addressability settings in your SolrCloud CRD. For instance, if your SolrCloud CRD uses the following settings: -```yaml + +[source,yaml] +---- spec: solrAddressability: external: domainName: k8s.solr.cloud -``` +---- + Then your certificate needs the following domains specified: -```yaml + +[source,yaml] +---- apiVersion: cert-manager.io/v1 kind: Certificate metadata: @@ -483,39 +526,47 @@ spec: dnsNames: - '*.k8s.solr.cloud' - k8s.solr.cloud -``` +---- + The wildcard DNS name will cover all SolrCloud nodes such as `-solrcloud-1.k8s.solr.cloud`. -Also, when requesting your certificate, keep in mind that internal DNS names in Kubernetes are not valid for public certificates. -For instance `..svc.cluster.local` is internal to Kubernetes and certificate issuer services like LetsEncrypt +Also, when requesting your certificate, keep in mind that internal DNS names in Kubernetes are not valid for public certificates. +For instance `..svc.cluster.local` is internal to Kubernetes and certificate issuer services like LetsEncrypt will not generate a certificate for K8s internal DNS names (you'll get errors during certificate issuing). -Another benefit is cert-manager can create a [PKCS12](https://cert-manager.io/docs/release-notes/release-notes-0.15/#general-availability-of-jks-and-pkcs-12-keystores) keystore automatically when issuing a `Certificate`, +Another benefit is cert-manager can create a https://cert-manager.io/docs/release-notes/release-notes-0.15/#general-availability-of-jks-and-pkcs-12-keystores[PKCS12] keystore automatically when issuing a `Certificate`, which allows the Solr operator to mount the keystore directly on our Solr pods. Ensure your certificate instance requests **pkcs12 keystore** gets created using config similar to the following: -```yaml + +[source,yaml] +---- keystores: pkcs12: create: true passwordSecretRef: key: password-key name: pkcs12-password-secret -``` -_Note: the example structure above goes in your certificate CRD YAML, not SolrCloud._ +---- + +NOTE: the example structure above goes in your certificate CRD YAML, not SolrCloud. You need to create the keystore secret (e.g. `pkcs12-password-secret`) in the same namespace before requesting the certificate, see: https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.PKCS12Keystore. Although a keystore password is not required for PKCS12, **cert-manager** requires a password when requesting a `pkcs12` keystore for your certificate. Moreover, most JVMs require a password for pkcs12 keystores, not supplying a password typically results in errors like the following: -``` + +---- Caused by: java.security.UnrecoverableKeyException: Get Key failed: null at java.base/sun.security.pkcs12.PKCS12KeyStore.engineGetKey(Unknown Source) at java.base/sun.security.util.KeyStoreDelegator.engineGetKey(Unknown Source) at java.base/java.security.KeyStore.getKey(Unknown Source) at java.base/sun.security.ssl.SunX509KeyManagerImpl.(Unknown Source) -``` -Consequently, the Solr operator requires you to use a non-null password for your keystore. +---- + +Consequently, the Solr operator requires you to use a non-null password for your keystore. Here's an example of how to use cert-manager to generate a self-signed certificate: -```yaml + +[source,yaml] +---- --- apiVersion: v1 kind: Secret @@ -553,10 +604,12 @@ spec: passwordSecretRef: key: password-key name: pkcs12-password-secret -``` +---- Once created, simply point the SolrCloud deployment at the TLS and keystore password secrets, e.g. -```yaml + +[source,yaml] +---- spec: ... other SolrCloud CRD settings ... @@ -567,25 +620,32 @@ spec: pkcs12Secret: name: selfsigned-cert key: keystore.p12 -``` -_Note: when using self-signed certificates, you'll have to configure HTTP client libraries to skip hostname and CA verification._ +---- -### I already have a TLS Certificate +NOTE: when using self-signed certificates, you'll have to configure HTTP client libraries to skip hostname and CA verification. -Users may bring their own cert stored in a `kubernetes.io/tls` secret; for this use case, cert-manager is not required. -There are many ways to get a certificate, such as from the GKE managed certificate process or from a CA directly. -Regardless of how you obtain a Certificate, it needs to be stored in a [Kubernetes TLS secret](https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets) +[#i-already-have-a-tls-certificate] +=== I already have a TLS Certificate + +Users may bring their own cert stored in a `kubernetes.io/tls` secret; for this use case, cert-manager is not required. +There are many ways to get a certificate, such as from the GKE managed certificate process or from a CA directly. +Regardless of how you obtain a Certificate, it needs to be stored in a https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets[Kubernetes TLS secret] that contains a `tls.crt` file (x.509 certificate with a public key and info about the issuer) and a `tls.key` file (the private key). -Ideally, the TLS secret will also have a `pkcs12` keystore. +Ideally, the TLS secret will also have a `pkcs12` keystore. If the supplied TLS secret does not contain a `keystore.p12` key, then the Solr operator creates an `initContainer` on the StatefulSet to generate the keystore from the TLS secret using the following command: -```bash + +[source,bash] +---- openssl pkcs12 -export -in tls.crt -inkey tls.key -out keystore.p12 -passout pass:${SOLR_SSL_KEY_STORE_PASSWORD}" -``` +---- + _The `initContainer` uses the main Solr image as it has `openssl` installed._ Configure the SolrCloud deployment to point to the user-provided keystore and TLS secrets: -```yaml + +[source,yaml] +---- spec: ... other SolrCloud CRD settings ... @@ -596,13 +656,15 @@ spec: pkcs12Secret: name: pkcs12-keystore-manual key: keystore.p12 -``` +---- -### Separate TrustStore +=== Separate TrustStore A truststore holds public keys for certificates you trust. By default, Solr pods are configured to use the keystore as the truststore. However, you may have a separate truststore you want to use for Solr TLS. As with the keystore, you need to provide a PKCS12 truststore in a secret and then configure your SolrCloud TLS settings as shown below: -```yaml + +[source,yaml] +---- spec: ... other SolrCloud CRD settings ... @@ -619,17 +681,20 @@ spec: trustStoreSecret: name: pkcs12-truststore key: truststore.p12 -``` -_Tip: if your truststore is not in PKCS12 format, use `openssl` to convert it._ +---- -### Mounted TLS Directory +TIP: if your truststore is not in PKCS12 format, use `openssl` to convert it. + +=== Mounted TLS Directory _Since v0.4.0_ The options discussed to this point require that all Solr pods share the same certificate and truststore. An emerging pattern in the Kubernetes ecosystem is to issue a unique certificate for each pod. Typically this operation is performed by an external agent, such as a cert-manager extension, that uses mutating webhooks to mount a unique certificate and supporting files on each pod dynamically. How the pod-specific certificates get issued is beyond the scope of the Solr operator. Under this scheme, you can use `spec.solrTLS.mountedTLSDir.path` to specify the path where the TLS files are mounted on the main pod. The following example illustrates how to configure a keystore and truststore in PKCS12 format using the `mountedTLSDir` option: -```yaml + +[source,yaml] +---- spec: ... other SolrCloud CRD settings ... @@ -642,10 +707,10 @@ spec: keystoreFile: keystore.p12 keystorePasswordFile: keystore-password truststoreFile: truststore.p12 -``` +---- When using the mounted TLS directory option, you need to ensure each Solr pod gets restarted before the certificate expires. Solr does not support hot reloading of the keystore or truststore. -Consequently, we recommend using the `spec.updateStrategy.restartSchedule` to restart pods before the certificate expires. +Consequently, we recommend using the `spec.updateStrategy.restartSchedule` to restart pods before the certificate expires. Typically, with this scheme, a new certificate is issued whenever a pod is restarted. When using the Cert Manager CSI Driver, a file is not generated for the keystore password. @@ -654,17 +719,19 @@ For this use case, the `solrTLS.mountedTLSDir.keystorePassword` and `solrTLS.mou These take strings that are plain-text passwords for the keystore or truststore. They will be ignored when `keystorePasswordFile` and `truststorePasswordFile` are provided. -### Client TLS +=== Client TLS _Since v0.4.0_ Solr supports using separate client and server TLS certificates. Solr uses the client certificate in mutual TLS (mTLS) scenarios to make requests to other Solr pods. -Use the `spec.solrClientTLS` configuration options to configure a separate client certificate. +Use the `spec.solrClientTLS` configuration options to configure a separate client certificate. As this is an advanced option, the supplied client certificate keystore and truststore must already be in PKCS12 format. -As with the server certificate loaded from `spec.solrTLS.pkcs12Secret`, +As with the server certificate loaded from `spec.solrTLS.pkcs12Secret`, you can have the operator restart Solr pods after the client TLS secret updates by setting `spec.solrClientTLS.restartOnTLSSecretUpdate` to `true`. -You may need to increase the timeout for the liveness / readiness probes when using mTLS with a separate client certificate, such as: -```yaml +You may need to increase the timeout for the liveness / readiness probes when using mTLS with a separate client certificate, such as: + +[source,yaml] +---- spec: ... other SolrCloud CRD settings ... @@ -674,14 +741,16 @@ spec: timeoutSeconds: 10 readinessProbe: timeoutSeconds: 10 -``` +---- -You may also use the `spec.solrClientTLS.mountedTLSDir` option to load a pod specific client certificate from a directory mounted by an external agent or CSI driver. +You may also use the `spec.solrClientTLS.mountedTLSDir` option to load a pod specific client certificate from a directory mounted by an external agent or CSI driver. -### Ingress with TLS protected Solr +=== Ingress with TLS protected Solr The Solr operator may create an Ingress for exposing Solr pods externally. When TLS is enabled, the operator adds the following annotation and TLS settings to the Ingress manifest, such as: -```yaml + +[source,yaml] +---- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -692,25 +761,28 @@ spec: ... tls: - secretName: my-selfsigned-cert-tls -``` +---- If using the mounted TLS Directory option with an Ingress, you will need to inject the ingress with TLS information as well. -The [Ingress TLS Termination section below](#enable-ingress-tls-termination) shows how this can be done when using cert-manager. - +The <> shows how this can be done when using cert-manager. -### Certificate Renewal and Rolling Restarts +=== Certificate Renewal and Rolling Restarts cert-manager automatically handles certificate renewal. From the docs: -> The default duration for all certificates is 90 days and the default renewal windows is 30 days. This means that certificates are considered valid for 3 months and renewal will be attempted within 1 month of expiration. -> https://docs.cert-manager.io/en/release-0.8/reference/certificates.html +____ +The default duration for all certificates is 90 days and the default renewal windows is 30 days. This means that certificates are considered valid for 3 months and renewal will be attempted within 1 month of expiration. + https://docs.cert-manager.io/en/release-0.8/reference/certificates.html +____ -However, this only covers updating the underlying TLS secret and mounted secrets in each Solr pod do get updated on the filesystem, see: https://kubernetes.io/docs/concepts/configuration/secret/#mounted-secrets-are-updated-automatically. +However, this only covers updating the underlying TLS secret and mounted secrets in each Solr pod do get updated on the filesystem, see: https://kubernetes.io/docs/concepts/configuration/secret/#mounted-secrets-are-updated-automatically. However, the JVM only reads key and trust stores once during initialization and does not reload them if they change. Thus, we need to recycle the Solr container in each pod to pick up the updated keystore. The operator tracks the MD5 hash of the `tls.crt` from the TLS secret in an annotation on the StatefulSet pod spec so that when the TLS secret changes, it will trigger a rolling restart of the affected Solr pods. The operator guards this behavior with an **opt-in** flag `restartOnTLSSecretUpdate` as some users may not want to restart Solr pods when the TLS secret holding the cert changes and may instead choose to restart the pods during a maintenance window (presumably before the certs expire). -```yaml + +[source,yaml] +---- spec: ... other SolrCloud CRD settings ... @@ -718,12 +790,14 @@ spec: restartOnTLSSecretUpdate: true ... -``` +---- + +=== Misc Config Settings for TLS Enabled Solr -### Misc Config Settings for TLS Enabled Solr +Although not required, we recommend setting the `commonServicePort` and `nodePortOverride` to `443` instead of the default port `80` under `solrAddressability` to avoid confusion when working with `https`. -Although not required, we recommend setting the `commonServicePort` and `nodePortOverride` to `443` instead of the default port `80` under `solrAddressability` to avoid confusion when working with `https`. -```yaml +[source,yaml] +---- spec: ... other SolrCloud CRD settings ... @@ -732,13 +806,15 @@ spec: external: nodePortOverride: 443 -``` +---- -#### Prometheus Exporter +==== Prometheus Exporter -If you're relying on a self-signed certificate (or any certificate that requires importing the CA into the Java trust store) for Solr pods, then the Prometheus Exporter will not be able to make requests for metrics. +If you're relying on a self-signed certificate (or any certificate that requires importing the CA into the Java trust store) for Solr pods, then the Prometheus Exporter will not be able to make requests for metrics. You'll need to duplicate your TLS config from your SolrCloud CRD definition to your Prometheus exporter CRD definition as shown in the example below: -```yaml + +[source,yaml] +---- solrReference: cloud: name: "dev" @@ -750,70 +826,80 @@ You'll need to duplicate your TLS config from your SolrCloud CRD definition to y pkcs12Secret: name: dev-selfsigned-cert-tls key: keystore.p12 -``` +---- + _This only applies to the SolrJ client the exporter uses to make requests to your TLS-enabled Solr pods and does not enable HTTPS for the exporter service._ -#### Public / Private Domain Names +==== Public / Private Domain Names -If your Solr pods use Kubernetes internal domain names, such as `-solrcloud-.` or -`-solrcloud-..svc.cluster.local` then you **cannot** request a certificate from a service like LetsEncrypt. +If your Solr pods use Kubernetes internal domain names, such as `-solrcloud-.` or +`-solrcloud-..svc.cluster.local` then you **cannot** request a certificate from a service like LetsEncrypt. You'll receive an error like (from the cert-manager controller pod logs): -``` + +---- Cannot issue for \"*..svc.cluster.local\": Domain name does not end with a valid public suffix (TLD)" -``` +---- + This is policy enforced by trusted certificate authorities, see: https://www.digicert.com/kb/advisories/internal-names.htm. -Intuitively, this makes sense because services like LetsEncrypt cannot determine if you own a private domain because they cannot reach it from the Internet. +Intuitively, this makes sense because services like LetsEncrypt cannot determine if you own a private domain because they cannot reach it from the Internet. Some CA's provide TLS certificates for private domains but that topic is beyond the scope of the Solr operator. You may want to use a self-signed certificate for internal traffic and then a public certificate for your Ingress. Alternatively, you can choose to expose Solr pods with an external name using SolrCloud `solrAddressability` settings: -```yaml + +[source,yaml] +---- kind: SolrCloud metadata: name: search spec: ... other SolrCloud CRD settings ... - solrAddressability: + solrAddressability: commonServicePort: 443 external: nodePortOverride: 443 domainName: k8s.solr.cloud method: Ingress useExternalAddress: true -``` -The example settings above will result in your Solr pods getting names like: `-search-solrcloud-0.k8s.solr.cloud` +---- + +The example settings above will result in your Solr pods getting names like: `-search-solrcloud-0.k8s.solr.cloud` which you can request TLS certificates from LetsEncrypt assuming you own the `k8s.solr.cloud` domain. -#### mTLS +==== mTLS Mutual TLS (mTLS) provides an additional layer of security by ensuring the client applications sending requests to Solr are trusted. To enable mTLS, simply set `spec.solrTLS.clientAuth` to either `Want` or `Need`. When mTLS is enabled, the Solr operator needs to -supply a client certificate that is trusted by Solr; the operator makes API calls to Solr to get cluster status. -To configure the client certificate for the operator, see [Running the Operator > mTLS](../running-the-operator.md#client-auth-for-mtls-enabled-solr-clusters) +supply a client certificate that is trusted by Solr; the operator makes API calls to Solr to get cluster status. +To configure the client certificate for the operator, see xref:getting-started:running-the-operator.adoc#client-auth-for-mtls-enabled-solr-clusters[Running the Operator > mTLS] When mTLS is enabled, the liveness and readiness probes are configured to execute a local command on each Solr pod instead of the default HTTP Get request. Using a command is required so that we can use the correct TLS certificate when making an HTTPs call to the probe endpoints. To help with debugging the TLS handshake between client and server, -you can add the `-Djavax.net.debug=SSL,keymanager,trustmanager,ssl:handshake` Java system property to the `spec.solrOpts` for your SolrCloud instance. +you can add the `-Djavax.net.debug=SSL,keymanager,trustmanager,ssl:handshake` Java system property to the `spec.solrOpts` for your SolrCloud instance. To verify mTLS is working for your Solr pods, you can supply the client certificate (and CA cert if needed) via curl after opening a port-forward to one of your Solr pods: -``` + +---- curl "https://localhost:8983/solr/admin/info/system" -v \ --key client/private_key.pem \ --cert client/client.pem \ --cacert root-ca/root-ca.pem -``` +---- + The `--cacert` option supplies the CA's certificate needed to trust the server certificate provided by the Solr pods during TLS handshake. -## Enable Ingress TLS Termination +[#enable-ingress-tls-termination] +== Enable Ingress TLS Termination _Since v0.4.0_ A common approach to securing traffic to your Solr cluster is to perform **TLS termination** at the Ingress and either leave all traffic between Solr pods un-encrypted or use private CAs for inter-pod communication. The operator supports this paradigm, to ensure all external traffic is encrypted. -```yaml +[source,yaml] +---- kind: SolrCloud metadata: name: search @@ -828,19 +914,21 @@ spec: useExternalAddress: false ingressTLSTermination: tlsSecret: my-selfsigned-cert-tls -``` +---- The only additional settings required here are: -- Making sure that you are not using the external TLS address for Solr to communicate internally via `useExternalAddress: false`. - This will be ignored, even if it is set to `true`. -- Adding a TLS secret through `ingressTLSTermination.tlsSecret`, this is passed to the Kubernetes Ingress to handle the TLS termination. - _This ensures that the only way to communicate with your Solr cluster externally is through the TLS protected common-endpoint._ -To generate a TLS secret, follow the [instructions above](#use-cert-manager-to-issue-the-certificate) and use the templated Hostname: `--solrcloud.` +* Making sure that you are not using the external TLS address for Solr to communicate internally via `useExternalAddress: false`. +This will be ignored, even if it is set to `true`. +* Adding a TLS secret through `ingressTLSTermination.tlsSecret`, this is passed to the Kubernetes Ingress to handle the TLS termination. +_This ensures that the only way to communicate with your Solr cluster externally is through the TLS protected common-endpoint._ + +To generate a TLS secret, follow the <> and use the templated Hostname: `--solrcloud.` If you configure your SolrCloud correctly, cert-manager can auto-inject the TLS secrets for you as well: -```yaml +[source,yaml] +---- kind: SolrCloud metadata: name: search @@ -861,11 +949,11 @@ spec: useExternalAddress: false ingressTLSTermination: tlsSecret: myingress-cert -``` +---- -For more information on the Ingress TLS Termination options for cert-manager, [refer to the documentation](https://cert-manager.io/docs/usage/ingress/). +For more information on the Ingress TLS Termination options for cert-manager, https://cert-manager.io/docs/usage/ingress/[refer to the documentation]. -## Authentication and Authorization +== Authentication and Authorization _Since v0.3.0_ All well-configured Solr clusters should enforce users to authenticate, even for read-only operations. Even if you want @@ -875,71 +963,84 @@ use case. The Solr operator can bootstrap a default security configuration for y there is no reason to deploy an unsecured SolrCloud cluster when using the Solr operator. In most cases, you'll want to combine basic authentication with TLS to ensure credentials are never passed in clear text. -For background on Solr security, please refer to the [Reference Guide](https://solr.apache.org/guide) for your version of Solr. +For background on Solr security, please refer to the https://solr.apache.org/guide[Reference Guide] for your version of Solr. The Solr operator only supports the `Basic` authentication scheme. In general, you have two primary options for configuring authentication with the Solr operator: -1. Let the Solr operator bootstrap the `security.json` to configure *basic authentication* for Solr. -2. Supply your own `security.json` to Solr, which must define a user account that the operator can use to make API requests to secured Solr pods. -If you choose option 2, then you need to provide the credentials the Solr operator should use to make requests to Solr via a Kubernetes secret. +. Let the Solr operator bootstrap the `security.json` to configure *basic authentication* for Solr. +. Supply your own `security.json` to Solr, which must define a user account that the operator can use to make API requests to secured Solr pods. + +If you choose option 2, then you need to provide the credentials the Solr operator should use to make requests to Solr via a Kubernetes secret. With option 1, the operator creates a Basic Authentication Secret for you, which contains the username and password for the `k8s-oper` user. -### Option 1: Bootstrap Security +=== Option 1: Bootstrap Security The easiest way to get started with Solr security is to have the operator bootstrap a `security.json` (stored in ZK) as part of the initial deployment process. To activate this feature, add the following configuration to your SolrCloud CRD definition YAML: -```yaml + +[source,yaml] +---- spec: ... solrSecurity: authenticationType: Basic -``` +---- Once the cluster is up, you'll need the `admin` user password to login to the Solr Admin UI. The `admin` user will have a random password generated by the operator during `security.json` bootstrapping. Use the following command to retrieve the password from the bootstrap secret created by the operator: -```bash + +[source,bash] +---- kubectl get secret -solrcloud-security-bootstrap -o jsonpath='{.data.admin}' | base64 --decode -``` +---- + _where `` is the name of your SolrCloud_ Once `security.json` is bootstrapped, the operator will not update it! You're expected to use the `admin` user to access the Security API to make further changes. In addition to the `admin` user, the operator defines a `solr` user, which has basic read access to Solr resources. You can retrieve the `solr` user password using: -```bash + +[source,bash] +---- kubectl get secret -solrcloud-security-bootstrap -o jsonpath='{.data.solr}' | base64 --decode -``` +---- You can safely delete the bootstrap secret, provided you've captured the `admin` password, after your SolrCloud deploys with the bootstrapped `security.json`. However, this will trigger a rolling restart across all pods as the `setup-zk` initContainer definition changes. -#### k8s-oper user +==== k8s-oper user The operator makes requests to secured Solr endpoints as the `k8s-oper` user; credentials for the `k8s-oper` user are stored in a separate secret of type `kubernetes.io/basic-auth` with name `-solrcloud-basic-auth`. The `k8s-oper` user is configured with read-only access to a minimal set of endpoints, see details in the **Authorization** sub-section below. Remember, if you change the `k8s-oper` password using the Solr security API, then you **must** update the secret with the new password or the operator will be locked out. Also, changing the password for the `k8s-oper` user in the K8s secret after bootstrapping will not update Solr! You're responsible for changing the password in both places. -#### Liveness and Readiness Probes +==== Liveness and Readiness Probes -We recommend configuring Solr to allow un-authenticated access over HTTP to the probe endpoint(s) and the bootstrapped `security.json` does this for you automatically (see next sub-section). +We recommend configuring Solr to allow un-authenticated access over HTTP to the probe endpoint(s) and the bootstrapped `security.json` does this for you automatically (see next sub-section). However, if you want to secure the probe endpoints, then you need to set `probesRequireAuth: true` as shown below: -```yaml + +[source,yaml] +---- spec: ... solrSecurity: authenticationType: Basic probesRequireAuth: true -``` -When `probesRequireAuth` is set to `true`, the liveness and readiness probes execute a command instead of using HTTP. -The operator configures a command instead of setting the `Authorization` header for the HTTP probes, as that would require a restart of all pods if the password changes. -With a command, we can load the username and password from a secret; Kubernetes will -[update the mounted secret files](https://kubernetes.io/docs/concepts/configuration/secret/#mounted-secrets-are-updated-automatically) when the secret changes automatically. +---- + +When `probesRequireAuth` is set to `true`, the liveness and readiness probes execute a command instead of using HTTP. +The operator configures a command instead of setting the `Authorization` header for the HTTP probes, as that would require a restart of all pods if the password changes. +With a command, we can load the username and password from a secret; Kubernetes will +https://kubernetes.io/docs/concepts/configuration/secret/#mounted-secrets-are-updated-automatically[update the mounted secret files] when the secret changes automatically. By default, the operator will use Solr's `/admin/info/system` endpoint for startup and liveness probes, and the `/admin/info/health` endpoint for readiness probes. This default can be customized by changing the HTTP path for any probes (under `spec.customSolrKubeOptions.podOptions`), however this also requires users to set `probesRequireAuth=false` as the operator does not reconfigure custom HTTP probes to use the command needed to support `probesRequireAuth=true`. Custom readiness and liveness probes can be specified using configuration like the following: -```yaml + +[source,yaml] +---- spec: ... customSolrKubeOptions: @@ -954,10 +1055,12 @@ spec: scheme: HTTP path: /solr/admin/customreadiness port: 8983 -``` +---- Consequently, the bootstrapped `security.json` will include additional rules to allow access to the endpoints used by the startup, liveness, and readiness probes: -```json + +[source,json] +---- { "name": "k8s-probe-1", "role": null, @@ -970,17 +1073,19 @@ Consequently, the bootstrapped `security.json` will include additional rules to "collection": null, "path": "/admin/customreadiness" } -``` +---- Note, if you change the probes after creating your solrcloud, then the new probe paths will not be added to the security.json. The security file is bootstrapped just once, so if your probes need to change you must add it to the allowed paths via the Solr Security API using the admin credentials. -#### Authorization +==== Authorization The default `security.json` created by the operator during initialization is shown below; the passwords for each user are randomized for every SolrCloud you create. In addition to configuring the `solr.BasicAuthPlugin`, the operator initializes a set of authorization rules for the default user accounts: `admin`, `solr`, and `k8s-oper`. Take a moment to review these authorization rules so that you're aware of the roles and access granted to each user in your cluster. -```json + +[source,json] +---- { "authentication": { "blockUnknown": false, @@ -1025,11 +1130,11 @@ Take a moment to review these authorization rules so that you're aware of the ro "collection": null, "path": "/admin/metrics" }, - { - "name": "k8s-zk", - "role":"k8s", - "collection": null, - "path":"/admin/zookeeper/status" + { + "name": "k8s-zk", + "role":"k8s", + "collection": null, + "path":"/admin/zookeeper/status" }, { "name": "k8s-ping", @@ -1070,34 +1175,43 @@ Take a moment to review these authorization rules so that you're aware of the ro ] } } -``` -A few aspects of the default `security.json` configuration warrant a closer look. First, the `probesRequireAuth` setting +---- + +A few aspects of the default `security.json` configuration warrant a closer look. First, the `probesRequireAuth` setting (defaults to `false`) governs the value for `blockUnknown` (under `authentication`) and whether the probe endpoint(s) require authentication: -```json + +[source,json] +---- { "name": "k8s-probe-0", "role": null, "collection": null, "path": "/admin/info/system" } -``` -In this case, the `"role":null` indicates this endpoint allows anonymous access by unknown users. +---- + +In this case, the `"role":null` indicates this endpoint allows anonymous access by unknown users. The `"collection":null` value indicates the path is not associated with any collection, i.e. it is a top-level system path. The operator sends GET requests to the `/admin/collections` endpoint to get cluster status to determine the rolling restart order: -```json + +[source,json] +---- { "name": "k8s-status", "role": "k8s", "collection": null, "path": "/admin/collections" }, -``` +---- + In this case, the `"role":"k8s"` indicates the requesting user must be in the `k8s` role; notice that all default users have the `k8s` role. -The Prometheus exporter sends GET requests to the `/admin/metrics` endpoint to collect metrics from each pod. +The Prometheus exporter sends GET requests to the `/admin/metrics` endpoint to collect metrics from each pod. The exporter also hits the `/admin/ping` endpoint for every collection, which requires the following authorization rules: -```json + +[source,json] +---- { "name": "k8s-metrics", "role": "k8s", @@ -1110,30 +1224,32 @@ The exporter also hits the `/admin/ping` endpoint for every collection, which re "collection": "*", "path": "/admin/ping" }, - { - "name": "k8s-zk", - "role":"k8s", - "collection": null, - "path":"/admin/zookeeper/status" + { + "name": "k8s-zk", + "role":"k8s", + "collection": null, + "path":"/admin/zookeeper/status" }, -``` +---- + The `"collection":"*"` setting indicates this path applies to all collections, which maps to endpoint `/collections//admin/ping` at runtime. The initial authorization config grants the `read` permission to the `users` role, which allows `users` to send query requests but cannot add / update / delete documents. -For instance, the `solr` user is mapped to the `users` role, so the `solr` user can send query requests only. +For instance, the `solr` user is mapped to the `users` role, so the `solr` user can send query requests only. In general, please verify the initial authorization rules for each role before sharing user credentials. -### Option 2: User-provided `security.json` and credentials secret +=== Option 2: User-provided `security.json` and credentials secret If users want full control over their cluster's security config, then they can provide the Solr `security.json` via a Secret and the credentials the operator should use to make requests to Solr in a Secret. -#### Custom `security.json` Secret +==== Custom `security.json` Secret _Since v0.5.0_ For full control over the Solr security configuration, supply a `security.json` in a Secret. The following example illustrates how to point the operator to a Secret containing a custom `security.json`: -```yaml +[source,yaml] +---- spec: ... solrSecurity: @@ -1141,25 +1257,29 @@ spec: bootstrapSecurityJson: name: my-custom-security-json key: security.json -``` +---- + For `Basic` authentication, if you don't supply a `security.json` Secret, then the operator assumes you are bootstrapping the security configuration via some other means. -Refer to the example `security.json` shown in the Authorization section above to help you get started crafting your own custom configuration. +Refer to the example `security.json` shown in the Authorization section above to help you get started crafting your own custom configuration. + +==== Basic Authentication -#### Basic Authentication +For `Basic` authentication, the supplied secret must be of type https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret[Basic Authentication Secret] and define both a `username` and `password`. -For `Basic` authentication, the supplied secret must be of type [Basic Authentication Secret](https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret) and define both a `username` and `password`. - -```yaml +[source,yaml] +---- spec: ... solrSecurity: authenticationType: Basic basicAuthSecret: user-provided-secret -``` +---- Here is an example of how to define a basic auth secret using YAML: -```yaml + +[source,yaml] +---- apiVersion: v1 kind: Secret metadata: @@ -1168,12 +1288,14 @@ type: kubernetes.io/basic-auth stringData: username: k8s-oper password: Test1234 -``` -With this config, the operator will make API requests to secured Solr pods as the `k8s-oper` user. -_Note: be sure to use a stronger password for real deployments_ +---- + +With this config, the operator will make API requests to secured Solr pods as the `k8s-oper` user. +NOTE: be sure to use a stronger password for real deployments Users need to ensure their `security.json` contains the user supplied in the `basicAuthSecret` has read access to the following endpoints: -``` + +---- /admin/info/system /admin/info/health /admin/collections @@ -1181,29 +1303,31 @@ Users need to ensure their `security.json` contains the user supplied in the `ba /admin/ping (for collection="*") /admin/zookeeper/status /____v2/cluster/replicas/balance -``` +---- And the following named permissions: -```aiignore + +---- collection-admin-edit -``` -_Tip: see the authorization rules defined by the default `security.json` as a guide for configuring access for the operator user_ +---- + +TIP: see the authorization rules defined by the default `security.json` as a guide for configuring access for the operator user -##### Changing the Password +===== Changing the Password If you change the password for the user configured in your `basicAuthSecret` using the Solr security API, then you **must** update the secret with the new password or the operator will be locked out. Also, changing the password for this user in the K8s secret will not update Solr! You're responsible for changing the password in both places. -##### Prometheus Exporter with Basic Auth +===== Prometheus Exporter with Basic Auth -If you enable basic auth for your SolrCloud cluster, then you need to point the Prometheus exporter at the basic auth secret; -refer to [Prometheus Exporter with Basic Auth](../solr-prometheus-exporter/README.md#prometheus-exporter-with-basic-auth) for more details. +If you enable basic auth for your SolrCloud cluster, then you need to point the Prometheus exporter at the basic auth secret; +refer to xref:solr-prometheus-exporter:index.adoc#prometheus-exporter-with-basic-auth[Prometheus Exporter with Basic Auth] for more details. -## Various Runtime Parameters +== Various Runtime Parameters There are various runtime parameters that allow you to customize the running of your Solr Cloud via the Solr Operator. -### Time to wait for Solr to be killed gracefully +=== Time to wait for Solr to be killed gracefully _Since v0.3.0_ The Solr Operator manages the Solr StatefulSet in a way that when a Solr pod needs to be stopped, or deleted, Kubernetes and Solr are on the same page for how long to wait for the process to die gracefully. @@ -1211,10 +1335,11 @@ The Solr Operator manages the Solr StatefulSet in a way that when a Solr pod nee The default time given is 60 seconds, before Solr or Kubernetes tries to forcefully stop the Solr process. You can override this default with the field: -```yaml +[source,yaml] +---- spec: ... customSolrKubeOptions: podOptions: terminationGracePeriodSeconds: 120 -``` +---- diff --git a/docs/modules/solr-prometheus-exporter/nav.adoc b/docs/modules/solr-prometheus-exporter/nav.adoc new file mode 100644 index 00000000..ba645e84 --- /dev/null +++ b/docs/modules/solr-prometheus-exporter/nav.adoc @@ -0,0 +1,19 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +.Solr Metrics +* xref:index.adoc[] diff --git a/docs/solr-prometheus-exporter/README.md b/docs/modules/solr-prometheus-exporter/pages/index.adoc similarity index 79% rename from docs/solr-prometheus-exporter/README.md rename to docs/modules/solr-prometheus-exporter/pages/index.adoc index 0f033e18..8efd2b48 100644 --- a/docs/solr-prometheus-exporter/README.md +++ b/docs/modules/solr-prometheus-exporter/pages/index.adoc @@ -1,68 +1,69 @@ - - -# Solr Prometheus Exporter += Solr Prometheus Exporter +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. Solr metrics can be collected from solr clouds/standalone solr both residing within the kubernetes cluster and outside. To use the Prometheus exporter, the easiest thing to do is just provide a reference to a Solr instance. That can be any of the following: -- The name and namespace of the Solr Cloud CRD -- The Zookeeper connection information of the Solr Cloud -- The address of the standalone Solr instance + +* The name and namespace of the Solr Cloud CRD +* The Zookeeper connection information of the Solr Cloud +* The address of the standalone Solr instance You can also provide a custom Prometheus Exporter config, Solr version, and exporter options as described in the -[Solr ref-guide](https://solr.apache.org/guide/monitoring-solr-with-prometheus-and-grafana.html#command-line-parameters). +https://solr.apache.org/guide/monitoring-solr-with-prometheus-and-grafana.html#command-line-parameters[Solr ref-guide]. -## Finding the Solr Cluster to monitor +== Finding the Solr Cluster to monitor The Prometheus Exporter supports metrics for both standalone solr as well as Solr Cloud. -### Cloud +=== Cloud You have two options for the prometheus exporter to find the zookeeper connection information that your Solr Cloud uses. -- Provide the name of a `SolrCloud` object in the same Kubernetes cluster, and optional namespace. -The Solr Operator will keep the ZK Connection info up to date from the SolrCloud object. +* Provide the name of a `SolrCloud` object in the same Kubernetes cluster, and optional namespace. +The Solr Operator will keep the ZK Connection info up to date from the SolrCloud object. This name can be provided at: `SolrPrometheusExporter.spec.solrRef.cloud.name` -- Provide explicit Zookeeper Connection info for the prometheus exporter to use. +* Provide explicit Zookeeper Connection info for the prometheus exporter to use. This info can be provided at: `SolrPrometheusExporter.spec.solrRef.cloud.zkConnectionInfo`, with keys `internalConnectionString` and `chroot` If `SolrPrometheusExporter.spec.solrRef.cloud.name` is used and no image information is passed via `SolrPrometheusExporter.spec.image.*` options, then the Prometheus Exporter will use the same image as the SolrCloud it is listening to. If any `SolrPrometheusExporter.spec.image.*` option is provided, then the Prometheus Exporter will use its own image. -#### ACLs +==== ACLs _Since v0.2.7_ The Prometheus Exporter can be set up to use ZK ACLs when connecting to Zookeeper. -If the prometheus exporter has been provided the name of a solr cloud, through `cloud.name`, then the solr operator will load up the ZK ACL Secret information found in the [SolrCloud spec](../solr-cloud/solr-cloud-crd.md#acls). +If the prometheus exporter has been provided the name of a solr cloud, through `cloud.name`, then the solr operator will load up the ZK ACL Secret information found in the xref:solr-cloud:solr-cloud-crd.adoc#acls[SolrCloud spec]. In order for the prometheus exporter to have visibility to these secrets, it must be deployed to the same namespace as the referenced SolrCloud or the same exact secrets must exist in both namespaces. If explicit Zookeeper connection information has been provided, through `cloud.zkConnectionInfo`, then ACL information must be provided in the same section. -The ACL information can be provided through an ADMIN acl and a READ ONLY acl. -- Admin: `SolrPrometheusExporter.spec.solrRef.cloud.zkConnectionInfo.acl` -- Read Only: `SolrPrometheusExporter.spec.solrRef.cloud.zkConnectionInfo.readOnlyAcl` +The ACL information can be provided through an ADMIN acl and a READ ONLY acl. + +* Admin: `SolrPrometheusExporter.spec.solrRef.cloud.zkConnectionInfo.acl` +* Read Only: `SolrPrometheusExporter.spec.solrRef.cloud.zkConnectionInfo.readOnlyAcl` All ACL fields are **required** if an ACL is used. -- **`secret`** - The name of the secret, in the same namespace as the SolrCloud, that contains the admin ACL username and password. -- **`usernameKey`** - The name of the key in the provided secret that stores the admin ACL username. -- **`passwordKey`** - The name of the key in the provided secret that stores the admin ACL password. +* **`secret`** - The name of the secret, in the same namespace as the SolrCloud, that contains the admin ACL username and password. +* **`usernameKey`** - The name of the key in the provided secret that stores the admin ACL username. +* **`passwordKey`** - The name of the key in the provided secret that stores the admin ACL password. -### Standalone +=== Standalone The Prometheus Exporter can be setup to scrape a standalone Solr instance. In order to use this functionality, use the following spec field: @@ -70,13 +71,14 @@ In order to use this functionality, use the following spec field: `SolrPrometheusExporter.spec.solrRef.standalone.address` -### Solr TLS +=== Solr TLS _Since v0.3.0_ If you're relying on a self-signed certificate (or any certificate that requires importing the CA into the Java trust store) for Solr pods, then the Prometheus Exporter will not be able to make requests for metrics. You'll need to duplicate your TLS config from your SolrCloud CRD definition to your Prometheus exporter CRD definition as shown in the example below: -```yaml +[source,yaml] +---- spec: solrReference: cloud: @@ -89,30 +91,33 @@ spec: pkcs12Secret: name: dev-selfsigned-cert-tls key: keystore.p12 -``` +---- **This only applies to the SolrJ client the exporter uses to make requests to your TLS-enabled Solr pods and does not enable HTTPS for the exporter service.** -#### Mounted TLS Directory +==== Mounted TLS Directory _Since v0.4.0_ You can use the `spec.solrReference.solrTLS.mountedTLSDir.path` to point to a directory containing certificate files mounted by an external agent or CSI driver. -### Prometheus Exporter with Basic Auth +=== Prometheus Exporter with Basic Auth _Since v0.3.0_ If you enable basic auth for your SolrCloud cluster, then you need to point the Prometheus exporter at the basic auth secret containing the credentials for making API requests to `/admin/metrics` and `/admin/ping` for all collections. -```yaml +[source,yaml] +---- spec: solrReference: basicAuthSecret: user-provided-secret -``` +---- + If you chose option #1 to have the operator bootstrap `security.json` for you, then the name of the secret will be: `-solrcloud-basic-auth`. If you chose option #2, then pass the same name that you used for your SolrCloud CRD instance. This user account will need access to the following endpoints in Solr: -```json + +---- { "name": "k8s-metrics", "role": "k8s", @@ -125,20 +130,22 @@ This user account will need access to the following endpoints in Solr: "collection": "*", "path": "/admin/ping" }, -``` +---- -For more details on configuring Solr security with the operator, see [Authentication and Authorization](../solr-cloud/solr-cloud-crd.md#authentication-and-authorization) +For more details on configuring Solr security with the operator, see xref:solr-cloud:solr-cloud-crd.adoc#authentication-and-authorization[Authentication and Authorization] -## Prometheus Stack +== Prometheus Stack -In this section, we'll walk through how to use the Prometheus exporter with the [Prometheus Stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack). +In this section, we'll walk through how to use the Prometheus exporter with the https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack[Prometheus Stack]. The Prometheus Stack provides all the services you need for monitoring Kubernetes applications like Solr and is the recommended way of deploying Prometheus and Grafana. -### Install Prometheus Stack +=== Install Prometheus Stack Begin by installing the Prometheus Stack in the `monitoring` namespace with Helm release name `mon`: -```bash + +[source,bash] +---- MONITOR_NS=monitoring PROM_OPER_REL=mon @@ -156,19 +163,24 @@ helm upgrade --install ${PROM_OPER_REL} prometheus-community/kube-prometheus-sta --namespace ${MONITOR_NS} \ --set kubeStateMetrics.enabled=false \ --set nodeExporter.enabled=false -``` +---- + _Refer to the Prometheus stack documentation for detailed instructions._ Verify you have Prometheus / Grafana pods running in the `monitoring` namespace: -```bash + +[source,bash] +---- kubectl get pods -n monitoring -``` +---- -### Deploy Prometheus Exporter for Solr Metrics +=== Deploy Prometheus Exporter for Solr Metrics -Next, deploy a Solr Prometheus exporter for the SolrCloud you want to capture metrics from in the namespace where you're running SolrCloud, not in the `monitoring` namespace. +Next, deploy a Solr Prometheus exporter for the SolrCloud you want to capture metrics from in the namespace where you're running SolrCloud, not in the `monitoring` namespace. For instance, the following example creates a Prometheus exporter named `dev-prom-exporter` for a SolrCloud named `dev` deployed in the `dev` namespace: -```yaml + +[source,yaml] +---- apiVersion: solr.apache.org/v1beta1 kind: SolrPrometheusExporter metadata: @@ -184,44 +196,55 @@ spec: cloud: name: "dev" numThreads: 6 -``` +---- Look at the logs for your exporter pod to ensure it is running properly (notice we're using a label filter vs. addressing the pod by name): -```bash + +[source,bash] +---- kubectl logs -l solr-prometheus-exporter=dev-prom-exporter -``` +---- + You should see some log messages that look similar to: -``` + +---- INFO - ; org.apache.solr.prometheus.collector.SchedulerMetricsCollector; Beginning metrics collection INFO - ; org.apache.solr.prometheus.collector.SchedulerMetricsCollector; Completed metrics collection -``` +---- You can also see the metrics that are exported by the pod by opening a port-forward to the exporter pod and hitting port 8080 with cURL: -```bash + +[source,bash] +---- kubectl port-forward $(kubectl get pod -l solr-prometheus-exporter=dev-prom-exporter --no-headers -o custom-columns=":metadata.name") 8080 curl http://localhost:8080/metrics -``` +---- -#### Customize Prometheus Exporter Config +==== Customize Prometheus Exporter Config _Since v0.3.0_ Each Solr pod exposes metrics as JSON from the `/solr/admin/metrics` endpoint. To see this in action, open a port-forward to a Solr pod and send a request to `http://localhost:8983/solr/admin/metrics`. -The Prometheus exporter requests metrics from each pod and then extracts the desired metrics using a series of [jq](https://stedolan.github.io/jq/) queries against the JSON returned by each pod. +The Prometheus exporter requests metrics from each pod and then extracts the desired metrics using a series of https://stedolan.github.io/jq/[jq] queries against the JSON returned by each pod. By default, the Solr operator configures the exporter to use the config from `/opt/solr/contrib/prometheus-exporter/conf/solr-exporter-config.xml`. If you need to customize the metrics exposed to Prometheus, you'll need to provide a custom config XML via a ConfigMap and then configure the exporter CRD to point to it. For instance, let's imagine you need to expose a new metric to Prometheus. Start by pulling the default config from the exporter pod using: -```bash + +[source,bash] +---- EXPORTER_POD_ID=$(kubectl get pod -l solr-prometheus-exporter=dev-prom-exporter --no-headers -o custom-columns=":metadata.name"`) kubectl cp $EXPORTER_POD_ID:/opt/solr/contrib/prometheus-exporter/conf/solr-exporter-config.xml ./solr-exporter-config.xml -``` +---- + Create a ConfigMap with your customized XML config under the `solr-prometheus-exporter.xml` key. -```yaml + +[source,yaml] +---- apiVersion: v1 data: solr-prometheus-exporter.xml: | @@ -232,44 +255,57 @@ data: kind: ConfigMap metadata: name: custom-exporter-xml -``` +---- + _Note: Using `kubectl create configmap --from-file` scrambles the XML formatting, so we recommend defining the configmap YAML as shown above to keep the XML formatted properly._ Point to the custom ConfigMap in your Prometheus exporter definition using: -```yaml + +[source,yaml] +---- spec: customKubeOptions: configMapOptions: providedConfigMap: custom-exporter-xml -``` +---- + The ConfigMap needs to be defined in the same namespace where you're running the exporter. The Solr operator automatically triggers a restart of the exporter pods whenever the exporter config XML changes in the ConfigMap. -#### Solr Prometheus Exporter Service +==== Solr Prometheus Exporter Service + The Solr operator creates a K8s `ClusterIP` service for load-balancing across exporter pods; there will typically only be one active exporter pod per SolrCloud managed by a K8s deployment. For our example `dev-prom-exporter`, the service name is: `dev-prom-exporter-solr-metrics` Take a quick look at the labels on the service as you'll need them to define a service monitor in the next step. -```bash + +[source,bash] +---- kubectl get svc dev-prom-exporter-solr-metrics --show-labels -``` +---- Also notice the ports that are exposed for this service: -```bash + +[source,bash] +---- kubectl get svc dev-prom-exporter-solr-metrics --output jsonpath="{@.spec.ports}" -``` +---- + You should see output similar to: -```json + +---- [{"name":"solr-metrics","port":80,"protocol":"TCP","targetPort":8080}] -``` +---- + +=== Create a Service Monitor -### Create a Service Monitor The Prometheus operator (deployed with the Prometheus stack) uses service monitors to find which services to scrape metrics from. Thus, we need to define a service monitor for our exporter service `dev-prom-exporter-solr-metrics`. -If you're not using the Prometheus operator, then you do not need a service monitor as Prometheus will scrape metrics using the `prometheus.io/*` pod annotations on the exporter service; see [Prometheus Configuration](https://prometheus.io/docs/prometheus/latest/configuration/configuration/). +If you're not using the Prometheus operator, then you do not need a service monitor as Prometheus will scrape metrics using the `prometheus.io/*` pod annotations on the exporter service; see https://prometheus.io/docs/prometheus/latest/configuration/configuration/[Prometheus Configuration]. -```yaml +[source,yaml] +---- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: @@ -286,28 +322,34 @@ spec: endpoints: - port: solr-metrics interval: 20s -``` +---- There are a few important aspects of this service monitor definition: + * The `release: mon` label associates this service monitor with the Prometheus operator; recall that we used `mon` as the Helm release when installing our Prometheus stack * The Prometheus operator uses the `solr-prometheus-exporter: dev-prom-exporter` label selector to find the service to scrape metrics from, which of course is the `dev-prom-exporter-solr-metrics` service created by the Solr operator. * The Prometheus operator uses `dev` to match the namespace (`namespaceSelector.matchNames`) where our SolrCloud and Prometheus exporter services are deployed -* The `endpoints` section identifies the port to scrape metrics from and the scrape interval; recall our service exposes the port as `solr-metrics` +* The `endpoints` section identifies the port to scrape metrics from and the scrape interval; recall our service exposes the port as `solr-metrics` Save the service monitor YAML to a file, such as `dev-prom-service-monitor.yaml` and apply to the `monitoring` namespace: -```bash + +[source,bash] +---- kubectl apply -f dev-prom-service-monitor.yaml -n monitoring -``` +---- Prometheus is now configured to scrape metrics from the exporter service. -### Load Solr Dashboard in Grafana +=== Load Solr Dashboard in Grafana You can expose Grafana via a LoadBalancer (or Ingress) but for now, we'll just open a port-forward to port 3000 to access Grafana: -```bash + +[source,bash] +---- GRAFANA_POD_ID=$(kubectl get pod -l app.kubernetes.io/name=grafana --no-headers -o custom-columns=":metadata.name" -n monitoring) kubectl port-forward -n monitoring $GRAFANA_POD_ID 3000 -``` +---- + Open Grafana using `localhost:3000` and login with username `admin` and password `prom-operator`. Once logged into Grafana, import the Solr dashboard JSON corresponding to the version of Solr you're running. diff --git a/docs/modules/upgrade-notes/nav.adoc b/docs/modules/upgrade-notes/nav.adoc new file mode 100644 index 00000000..5c1fbbbb --- /dev/null +++ b/docs/modules/upgrade-notes/nav.adoc @@ -0,0 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +.Upgrade Notes +* xref:upgrade-notes.adoc[] +* xref:known-issues.adoc[] diff --git a/docs/modules/upgrade-notes/pages/known-issues.adoc b/docs/modules/upgrade-notes/pages/known-issues.adoc new file mode 100644 index 00000000..2cb37ffa --- /dev/null +++ b/docs/modules/upgrade-notes/pages/known-issues.adoc @@ -0,0 +1,36 @@ += Known Issues +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +== Solr Cloud + +* You may be seeing timeouts in your Solr logs after a rolling update. +This can be caused by DNS caching in CoreDNS (the default DNS for Kubernetes). +This can be fixed by reducing the kubernetes cache TTL to 5-10 seconds. +Please refer to this ticket for more information: https://github.com/kubernetes/kubernetes/issues/92559 ++ +Fix: In the `kube-system` namespace, there will be a `ConfigMap` with name `coredns`. It will contain a section: ++ +---- +kubernetes cluster.local in-addr.arpa ip6.arpa { + ... + ttl 30 +... +} +---- ++ +Edit the `ttl` value to be `5`, CoreDNS will automatically see a change in the configMap and reload it. diff --git a/docs/modules/upgrade-notes/pages/upgrade-notes.adoc b/docs/modules/upgrade-notes/pages/upgrade-notes.adoc new file mode 100644 index 00000000..d0d152ec --- /dev/null +++ b/docs/modules/upgrade-notes/pages/upgrade-notes.adoc @@ -0,0 +1,376 @@ += Solr Operator Upgrade Notes +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +Please carefully read the entries for all versions between the version you are running and the version you want to upgrade to. + +Ensure to read the <> for the version you are upgrading to as well as the versions you are skipping. + +If you want to skip versions when upgrading, be sure to check out the <> and <> sections. + +== Version Compatibility Matrixes + +=== Kubernetes Versions + +[cols="^,^,^,^,^,^",options="header"] +|=== +| Solr Operator Version | `1.15` | `1.16` - `1.18` | `1.19` - `1.20` | `1.21` | `1.22`+ + +| `v0.2.6` | YES | YES | YES | YES | NO +| `v0.2.7` | NO | YES | YES | YES | NO +| `v0.2.8` | NO | YES | YES | YES | NO +| `v0.3.x` | NO | YES | YES | YES | NO +| `v0.4.x` | NO | YES | YES | YES | NO +| `v0.5.x` | NO | NO | YES | YES | YES +| `v0.6.x` | NO | NO | YES | YES | YES +| `v0.7.x` | NO | NO | NO | YES | YES +| `v0.8.x` | NO | NO | NO | NO | YES +| `v0.9.x` | NO | NO | NO | NO | YES +| `v0.10.x` | NO | NO | NO | NO | YES +|=== + +=== Solr Versions + +[cols="^,^,^,^,^,^",options="header"] +|=== +| Solr Operator Version | `7.7` | `8.0` - `8.10` | `8.11` | `9.0` - `9.3` | `9.4`+ + +| `v0.2.7` | YES | YES | YES | NO | NO +| `v0.2.8` | YES | YES | YES | NO | NO +| `v0.3.x` | YES | YES | YES | NO | NO +| `v0.4.x` | YES | YES | YES | NO | NO +| `v0.5.x` | YES | YES | YES | NO | NO +| `v0.6.x` | YES | YES | YES | YES ^1^ | YES ^1^ +| `v0.7.x` | YES | YES | YES | YES ^1^ | YES ^1^ +| `v0.8.x` | NO | NO | YES | YES ^1^ | YES +| `v0.9.x` | NO | NO | YES | YES ^1^ | YES +| `v0.10.x` | NO | NO | YES | YES ^1^ | YES +|=== + +*Exceptions* + +* ^1^ `SolrTLS` and `SolrClientTLS` are not supported + +Please note that this represents basic compatibility with the Solr Operator. +There may be options and features that require newer versions of Solr. +(e.g. S3/GCS Backup Support) + +Please test to make sure the features you plan to use are compatible with the version of Solr you choose to run. + + +== Upgrade Instructions + +Please follow the instructions below when upgrading the Solr Operator. + +However, no matter the upgrade, always read the <> for every version between + +=== Upgrading minor versions (`vX.A._` -> `vX.B._`) + +In order to upgrade minor versions (e.g. `v0.2.5` -> `v0.3.0`), you must upgrade one minor version at a time (e.g. `v0.2.0` -> `v0.3.0` -> `v0.4.0`). +It is also necessary to upgrade to the latest patch version before upgrading to the next minor version. +Therefore if you are running `v0.2.5` and you want to upgrade to `v0.3.0`, you must first upgrade to `v0.2.8` before upgrading to `v0.3.0`. + +There when upgrading minor versions, there may be CRD options that have been deprecated. +The Solr Operator will automatically change the existing Solr resources to use the new format. +Therefore when upgrading to the next version, which may remove the deprecated option, the existing resources will behave correctly. +However, creating new resources with the deprecated options will fail. +Be sure to carefully read the <> to be sure you are not using deprecated options. + +=== Upgrading patch versions (`vX.Y.A` -> `vZ.Y.B`) + +You should be able to upgrade from a version to any patch version with the same minor and major versions. +It is always encouraged to upgrade to the latest patch version of the minor and major version you are running. +There is no need to upgrade one patch version at a time (e.g. `v0.2.5` -> `v0.2.6` -> `v0.2.7` -> `v0.2.8`), +instead you can leap to the latest patch version (e.g. `v0.2.5` -> `v0.2.8`). + +== Installing the Solr Operator vs Solr CRDs + +Installing the Solr Operator, especially via the https://artifacthub.io/packages/helm/apache-solr/solr-operator[Helm Chart], +does not necessarily mean that you are installing the required CRDs for that version of the Solr Operator. + +If the Solr CRDs already exist in your Kubernetes cluster, then Helm will not update them even if the CRDs have changed between the Helm chart versions. +Instead, you will need to manually install the CRDs whenever upgrading your Solr Operator. +*You should always upgrade your CRDs before upgrading the Operator* + +You can do this via the following command, replacing `` with the version of the Solr Operator you are installing: + +[source,bash] +---- +# Just replace the Solr CRDs +kubectl replace -f "http://solr.apache.org/operator/downloads/crds//all.yaml" +# Just replace the Solr CRDs and all CRDs it might depend on (e.g. ZookeeperCluster) +kubectl replace -f "http://solr.apache.org/operator/downloads/crds//all-with-dependencies.yaml" +---- + +It is *strongly recommended* to use `kubectl create` or `kubectl replace`, instead of `kubectl apply` when creating/updating CRDs. + +=== Upgrading the Zookeeper Operator + +When upgrading the Solr Operator, you may need to upgrade the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] at the same time. +If you are using the Solr Helm chart to deploy the Zookeeper operator, then you won't need to do anything besides installing the CRD's with dependencies, and upgrade the Solr Operator helm deployment. + +[source,bash] +---- +# Just replace the Solr CRDs and all CRDs it might depend on (e.g. ZookeeperCluster) +kubectl replace -f "http://solr.apache.org/operator/downloads/crds/v0.10.0-prerelease/all-with-dependencies.yaml" +helm upgrade solr-operator apache-solr/solr-operator --version 0.10.0-prerelease +---- + +_Note that the Helm chart version does not contain a `v` prefix, which the downloads version does. The Helm chart version is the only part of the Solr Operator release that does not use the `v` prefix._ + +== Upgrade Warnings and Notes + +=== v0.10.0 + +* *Logging now defaults to JSON format* ++ +The new default for CLI flag `--zap-devel` is now `false`, causing log encoding to be `json` and log level to be `info`. +There is a new helm value `development` that can be set to `true` to switch to `console` encoding and `debug` level +that was the default in previous versions. + +=== v0.8.0 + +* *The minimum supported Solr version is now 8.11* ++ +If you are unable to use a newer version of Solr, please install the `v0.7.1` version of the Solr Operator. +However, it is strongly suggested to upgrade to newer versions of Solr that are actively supported. +See the <> for more information. + +* *Kubernetes support is now limited to 1.22+.* ++ +If you are unable to use a newer version of Kubernetes, please install the `v0.7.1` version of the Solr Operator for use with Kubernetes `1.21`. +See the <> for more information. + +* The new `SolrCloud.spec.scaling.vacatePodsOnScaleDown` option is enabled by default. +This means that any SolrCloud that has its `spec.replicas` decreased will have the replicas migrated off of the soon-to-be-deleted pods by default. +Set this value to `false` to retain the previous functionality. +More information can be found in the xref:solr-cloud:scaling.adoc#solr-pod-scale-down[Solr Pod Scale-Down] documentation. + +* The `POD_HOSTNAME` envVar in SolrCloud Pods has been deprecated. Use `POD_NAME` instead. + +* Use of the `hostPort` system property placeholder in custom solr.xml files has been deprecated. +Use `${solr.port.advertise:80}`, the default value used by Solr, instead. + +* By default `solrcloud` resources will now use `/admin/info/system` and `/admin/info/health` for liveness and readiness checks, respectively. +Administrators that provide custom `security.json` files for their clusters should either exempt both of these endpoints from authentication entirely, or configure permissions ensuring the relevant Solr user account can access them without issue. + +=== v0.7.0 + +* *Kubernetes support is now limited to 1.21+.* ++ +If you are unable to use a newer version of Kubernetes, please install the `v0.6.0` version of the Solr Operator for use with Kubernetes `1.20` and below. +See the <> for more information. + +* The required version of the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] to use with this version has been upgraded from `v0.2.14` to `v0.2.15`. +If you use the Solr Operator helm chart, then by default the new version of the Zookeeper Operator will be installed as well. +Refer to the helm chart documentation if you want to manage the Zookeeper Operator installation yourself. +Please refer to the https://github.com/pravega/zookeeper-operator/releases[Zookeeper Operator release notes] before upgrading. +Make sure to install the correct version of the Zookeeper Operator CRDs, as <>. + +* `PodDisruptionBudgets` are now created by default alongside SolrCloud instances. +The maximum number of pods allowed down at any given time is aligned with the xref:solr-cloud:solr-cloud-crd.adoc#update-strategy[Managed Update settings] provided in the spec. +If this is not provided, the default setting (`25%`) is used. +`PodDisruptionBudget` creation can be disabled for a solrcloud resource, by setting `spec.availability.podDisruptionBudget.enabled` to false. + +* Provided Zookeeper pods use the `IfNotPresent` pullPolicy by default. Users that specify this field manually will not see a change. + +* The Solr Operator now tries to limit connectivity to pods before they are deleted, for rolling updates or other reasons. +Before the pod is killed, and evicted of replicas if ephemeral storage is used, a readinessCondition will be set to `false`. +The Headless Service does not use readiness, so internode traffic will not be affected, however the ClusterIP (common) service will no longer include these nodes until they have been restarted. +This change will improve request success rates during a rolling restart. +Refer to the xref:solr-cloud:managed-updates.adoc#pod-readiness-during-updates[Managed Updates documentation]. + +* The deprecated SolrCloud CRD field `Spec.solrAddressability.external.ingressTLSTerminationSecret` has been removed, please use `Spec.solrAddressability.external.ingressTLSTermination.tlsSecret` instead. +In order to have these fields changed automatically, upgrade to the `v0.6.0` version of the Solr operator before upgrading to the `v0.7.0` version. +However, all new SolrCloud resources will need to respect this field change. + +* The deprecated SolrCloud CRD field `Spec.solrAddressability.external.additionalDomains` has been removed, please use `Spec.solrAddressability.external.additionalDomainNames` instead. +In order to have these fields changed automatically, upgrade to the `v0.6.0` version of the Solr operator before upgrading to the `v0.7.0` version. +However, all new SolrCloud resources will need to respect this field change. + +=== v0.6.0 + +* The default Solr version for the `SolrCloud` and `SolrPrometheusExporter` resources has been upgraded from `8.9` to `8.11`. +This will not affect any existing resources, as default versions are hard-written to the resources immediately. +Only new resources created after the Solr Operator is upgraded to `v0.6.0` will be affected. + +* The required version of the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] to use with this version has been upgraded from `v0.2.12` to `v0.2.14`. +If you use the Solr Operator helm chart, then by default the new version of the Zookeeper Operator will be installed as well. +Refer to the helm chart documentation if you want to manage the Zookeeper Operator installation yourself. +Please refer to the https://github.com/pravega/zookeeper-operator/releases[Zookeeper Operator release notes] before upgrading. +Make sure to install the correct version of the Zookeeper Operator CRDS, as <>. + +* The SolrCloud CRD field `Spec.solrAddressability.external.additionalDomains` has been renamed to `additionalDomainNames`. +In this release `additionalDomains` is still accepted, but all values will automatically be added to `additionalDomainNames` and the field will be set to `nil` by the operator. +The `additionalDomains` option will be removed in a future version. + +* The SolrCloud CRD field `Spec.solrAddressability.external.ingressTLSTerminationSecret` has been moved to `Spec.solrAddressability.external.ingressTLSTermination.tlsSecret`. +In this release `ingressTLSTerminationSecret` is still accepted, but all values will automatically be changed to `ingressTLSTermination.tlsSecret` and the original field will be set to `nil` by the operator. +The `ingressTLSTerminationSecret` option will be removed in a future version. + +* `SolrPrometheusExporter` resources without any image specifications (`SolrPrometheusExporter.Spec.image.*`) will use the referenced `SolrCloud` image, if the reference is by `name`, not `zkConnectionString`. +If any `SolrPrometheusExporter.Spec.image.*` option is provided, then those values will be defaulted by the Solr Operator and the `SolrCloud` image will not be used. +When upgrading from `v0.5.*` to `v0.6.0`, only new `SolrPrometheusExporter` resources will use this new feature. +To enable it on existing resources, update the resources and remove the `SolrPrometheusExporter.Spec.image` section. + +* CRD options deprecated in `v0.5.0` have been removed. +This includes field `SolrCloud.spec.dataStorage.backupRestoreOptions`, `SolrBackup.spec.persistence` and `SolrBackup.status.persistenceStatus`. +Upgrading to `v0.5.*` will remove these options on existing and new SolrCloud and SolrBackup resources. +However, once the Solr CRDs are upgraded to `v0.6.0`, you will no longer be able to submit resources with the options listed above. +Please migrate your systems to use the new options while running `v0.5.*`, before upgrading to `v0.6.0`. + +=== v0.5.0 + +* Due to the deprecation and removal of `networking.k8s.io/v1beta1` in Kubernetes v1.22, `networking.k8s.io/v1` will be used for Ingresses. ++ +*This means that Kubernetes support is now limited to 1.19+.* ++ +If you are unable to use a newer version of Kubernetes, please install the `v0.4.0` version of the Solr Operator for use with Kubernetes 1.18 and below. +See the <> for more information. ++ +This also means that if you specify a custom `ingressClass` via an annotation, you should change to use the `SolrCloud.spec.customSolrKubeOptions.ingressOptions.ingressClassName` instead. +The ability to set the class through annotations is now deprecated in Kubernetes and will be removed in future versions. + +* The legacy way of specifying a backupRepository has been *DEPRECATED*. +Instead of using `SolrCloud.spec.dataStorage.backupRestoreOptions`, use `SolrCloud.spec.backupRepositories`. +The `SolrCloud.spec.dataStorage.backupRestoreOptions` option *will be removed in `v0.6.0`*. ++ +*Note*: Do not take backups while upgrading from the Solr Operator `v0.4.0` to `v0.5.0`. +Wait for the SolrClouds to be updated, after the Solr Operator is upgraded, and complete their rolling restarts before continuing to use the Backup functionality. + +* The location of Solr backup data as well as the name of the Solr backups have been changed, when using volume repositories. +Previously the name of the backup (in solr) was set to the name of the collection. +Now the name given to the backup in Solr will be set to `-`, without the `<` or `>` characters, where the `backup-resource-name` is the name of the SolrBackup resource. ++ +The directory in the Read-Write-Many Volume, required for volume repositories, that backups are written to is now `/cloud//backups` by default, instead of `/cloud//backups/`. +Because the backup name in Solr uses both the SolrBackup resource name and the collection name, there should be no collisions in this directory. +However, this can be overridden using the `SolrBackup.spec.location` option, which is appended to `/cloud/`. + +* The SolrBackup persistence option has been removed as of `v0.5.0`. +Users should plan to keep their backup data in the shared volume if using a Volume Backup repository. +If `SolrBackup.spec.persistence` is provided, it will be removed and written back to Kubernetes. ++ +Users using the S3 persistence option should try to use the xref:solr-backup:index.adoc#s3-backup-repositories[S3 backup repository] instead. This requires Solr 8.10 or higher. + +* Default ports when using TLS are now set to 443 instead of 80. +This affects `solrCloud.Spec.SolrAddressability.CommonServicePort` and `solrCloud.Spec.SolrAddressability.CommonServicePort` field defaulting. +Users already explicitly setting these values will not be affected. + +=== v0.4.0 + +* The required version of the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] to use with this version has been upgraded from `v0.2.9` to `v0.2.12`. +If you use the Solr Operator helm chart, then by default the new version of the Zookeeper Operator will be installed as well. +Refer to the helm chart documentation if you want to manage the Zookeeper Operator installation yourself. +Please refer to the https://github.com/pravega/zookeeper-operator/releases[Zookeeper Operator release notes] before upgrading. +Make sure to install the correct version of the Zookeeper Operator CRDS, as <>. + +* The deprecated Solr Operator Helm chart option `useZkOperator` has been removed, use `zookeeper-operator.use` instead. ++ +*Note*: The old option takes a _string_ `"true"`/`"false"`, while the new option takes a _boolean_ `true`/`false`. + +* The default Solr version for `SolrCloud` and `SolrPrometheusExporter` resources has been upgraded from `7.7.0` to `8.9`. +This will not affect any existing resources, as default versions are hard-written to the resources immediately. +Only new resources created after the Solr Operator is upgraded to `v0.4.0` will be affected. + +* In previous versions of the Solr Operator, the provided Zookeeper instances could only use Persistent Storage. +Now ephemeral storage is enabled, and used by default if Solr is using ephemeral storage. +The ZK storage type can be explicitly set via `Spec.zookeeperRef.provided.ephemeral` or `Spec.zookeeperRef.provided.persistence`, +however if neither is set, the Solr Operator will default to use the type of storage (persistent or ephemeral) that Solr is using. ++ +*This means that the default Zookeeper Storage type can change for users using ephemeral storage for Solr. +If you require ephemeral Solr storage and persistent Zookeeper Storage, be sure to explicitly set that starting in `v0.4.0`.* + +=== v0.3.0 + +* All deprecated CRD fields and Solr Operator options from `v0.2.*` have been removed. + +* The `SolrCollection` and `SolrCollectionAlias` have been removed. Please use the Solr APIs to manage these resources instead. +Discussion around the removal can be found in https://github.com/apache/solr-operator/issues/204[Issue #204]. + +* The required version of the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] to use with this version has been upgraded from `v0.2.6` to `v0.2.9`. +If you use the Solr Operator helm chart, then by default the new version of the Zookeeper Operator will be installed as well. +Refer to the helm chart documentation if you want to manage the Zookeeper Operator installation yourself. +Please refer to the https://github.com/pravega/zookeeper-operator/releases[Zookeeper Operator release notes] before upgrading. + +=== v0.2.7 + +* Due to the addition of possible sidecar/initContainers for SolrClouds, the version of CRDs used had to be upgraded to `apiextensions.k8s.io/v1`. ++ +*This means that Kubernetes support is now limited to 1.16+.* ++ +If you are unable to use a newer version of Kubernetes, please install the `v0.2.6` version of the Solr Operator for use with Kubernetes 1.15 and below. + +* The location of backup-restore volume mounts in Solr containers has changed from `/var/solr/solr-backup-restore` to `/var/solr/data/backup-restore`. +This change was made to ensure that there were no issues using the backup API with solr 8.6+, which restricts the locations that backup data can be saved to and read from. +This change should be transparent if you are merely using the SolrBackup CRD. +All files permissions issues with SolrBackups should now be addressed. + +* The default `PodManagementPolicy` for StatefulSets has been changed to `Parallel` from `OrderedReady`. +This change will not affect existing StatefulSets, as `PodManagementPolicy` cannot be updated. +In order to continue using `OrderedReady` on new SolrClouds, please use the following setting: +`SolrCloud.spec.customSolrKubeOptions.statefulSetOptions.podManagementPolicy` + +* The `SolrCloud` and `SolrPrometheusExporter` services' portNames have changed to `"solr-client"` and `"solr-metrics"` from `"ext-solr-client"` and `"ext-solr-metrics"`, respectively. +This is due to a bug in Kubernetes where `portName` and `targetPort` must match for services. + +* Support for `etcd`/`zetcd` deployments has been removed. +The section for a Zookeeper cluster Spec `SolrCloud.spec.zookeeperRef.provided.zookeeper` has been *DEPRECATED*. +The same fields (except for the deprecated `persistentVolumeClaimSpec` option) are now available under `SolrCloud.spec.zookeeperRef.provided`. + +* Data Storage options have been expanded, and moved from their old locations. +** `SolrCloud.spec.dataPvcSpec` has been *DEPRECATED*. +Please instead use the following instead: `SolrCloud.spec.dataStorage.persistent.pvcTemplate.spec=` +** `SolrCloud.spec.backupRestoreVolume` has been *DEPRECATED*. +Please instead use the following instead: `SolrCloud.spec.dataStorage.backupRestoreOptions.Volume=` + +=== v0.2.6 + +* The solr-operator argument `--ingressBaseDomain` has been *DEPRECATED*. +In order to set the external baseDomain of your clouds, please begin to use `SolrCloud.spec.solrAddressability.external.domainName` instead. +You will also need to set `SolrCloud.spec.solrAddressability.external.method` to `Ingress`. +The `--ingressBaseDomain` argument is backwards compatible, and all existing SolrCloud objects will be auto-updated once your operator is upgraded to `v0.2.6`. +The argument will be removed in a future version (`v0.3.0`). + +=== v0.2.4 + +* The default supported version of the Zookeeper Operator has been upgraded to `v0.2.6`. +If you are using the provided zookeeper option for your SolrClouds, then you will want to upgrade your zookeeper operator version as well as the version and image of the zookeeper that you are running. +You can find examples of the zookeeper operator as well as solrClouds that use provided zookeepers in the https://github.com/apache/solr-operator/blob/main/example[examples] directory. +Please refer to the https://github.com/pravega/zookeeper-operator/releases[Zookeeper Operator release notes] before upgrading. + +=== v0.2.3 + +* If you do not use an ingress with the Solr Operator, the Solr Hostname and Port will change when upgrading to this version. This is to fix an outstanding bug. Because of the headless service port change, you will likely see an outage for inter-node communication until all pods have been restarted. + +=== v0.2.2 + +* `SolrCloud.spec.solrPodPolicy` has been *DEPRECATED* in favor of the `SolrCloud.spec.customSolrKubeOptions.podOptions` option. +This option is backwards compatible, but will be removed in a future version (`v0.3.0`). + +* `SolrPrometheusExporter.spec.solrPodPolicy` has been *DEPRECATED* in favor of the `SolrPrometheusExporter.spec.customKubeOptions.podOptions` option. +This option is backwards compatible, but will be removed in a future version (`v0.3.0`). + +=== v0.2.1 + +* The zkConnectionString used for provided zookeepers changed from using the string provided in the `ZkCluster.Status`, which used an IP, to using the service name. This will cause a rolling restart of your solrs using the provided zookeeper option, but there will be no data loss. + +=== v0.2.0 + +* Uses `gomod` instead of `dep` +* `SolrCloud.spec.zookeeperRef.provided.zookeeper.persistentVolumeClaimSpec` has been *DEPRECATED* in favor of the `SolrCloud.zookeeperRef.provided.zookeeper.persistence` option. +This option is backwards compatible, but will be removed in a future version (`v0.3.0`). +* An upgrade to the ZKOperator version `0.2.4` is required. diff --git a/docs/release-instructions.md b/docs/release-instructions.md deleted file mode 100644 index 59c71614..00000000 --- a/docs/release-instructions.md +++ /dev/null @@ -1,44 +0,0 @@ - - -# Releasing a New Verson of the Solr Operator - -This page details the steps for releasing new versions of the Solr Operator. - -- [Versioning](#versioning) -- [Use the Release Wizard](#release-wizard) - -### Versioning - -The Solr Operator follows kubernetes conventions with versioning with is: - -`v..` - -For example `v0.2.5` or `v1.3.4`. -Certain systems except versions that do not start wth `v`, such as Helm. -However the tooling has been created to automatically make these changes when necessary, so always include the prefixed `v` when following these instructions. - -### Release Wizard - -Run the release wizard from the root of the repo on the branch that you want to make the release from. - -```bash -./hack/release/wizard/releaseWizard.py -``` - -Make sure to install all necessary programs and follow all steps. -If there is any confusion, it is best to reach out on slack or the mailing lists before continuing. \ No newline at end of file diff --git a/docs/solr-cloud/managed-updates.md b/docs/solr-cloud/managed-updates.md deleted file mode 100644 index b3b8c473..00000000 --- a/docs/solr-cloud/managed-updates.md +++ /dev/null @@ -1,116 +0,0 @@ - - -# Managed SolrCloud Rolling Updates -_Since v0.2.7_ - -Solr Clouds are complex distributed systems, and thus require a more delicate and informed approach to rolling updates. - -If the [`Managed` update strategy](solr-cloud-crd.md#update-strategy) is specified in the Solr Cloud CRD, then the Solr Operator will take control over deleting SolrCloud pods when they need to be updated. - -The operator will find all pods that have not been updated yet and choose the next set of pods to delete for an update, given the following workflow. - -Note: Managed Updates are a executed via [Cluster Operation Locks](cluster-operations.md), please refer to the documentation for more information about how these operations are executed. - -## Pod Update Workflow - -The logic goes as follows: - -1. Find the pods that are out-of-date -1. Update all out-of-date pods that do not have a started Solr container. - - This allows for updating a pod that cannot start, even if other pods are not available. - - This step does not respect the `maxPodsUnavailable` option, because these pods have not even started the Solr process. -1. Retrieve the cluster state of the SolrCloud if there are any `ready` pods. - - If no pods are ready, then there is no endpoint to retrieve the cluster state from. -1. Sort the pods in order of safety for being restarted. [Sorting order reference](#pod-update-sorting-order) -1. Iterate through the sorted pods, greedily choosing which pods to update. [Selection logic reference](#pod-update-selection-logic) - - The maximum number of pods that can be updated are determined by starting with `maxPodsUnavailable`, - then subtracting the number of updated pods that are unavailable as well as the number of not-yet-started, out-of-date pods that were updated in a previous step. - This check makes sure that any pods taken down during this step do not violate the `maxPodsUnavailable` constraint. - - -### Pod Update Sorting Order - -The pods are sorted by the following criteria, in the given order. -If any two pods on a criterion, then the next criteria (in the following order) is used to sort them. - -In this context the pods sorted highest are the first chosen to be updated, the pods sorted lowest will be selected last. - -1. If the pod is the overseer, it will be sorted lowest. -1. If the pod is not represented in the clusterState, it will be sorted highest. - - A pod is not in the clusterstate if it does not host any replicas and is not the overseer. -1. Number of leader replicas hosted in the pod, sorted low -> high -1. Number of active or recovering replicas hosted in the pod, sorted low -> high -1. Number of total replicas hosted in the pod, sorted low -> high -1. If the pod is not a liveNode, then it will be sorted lower. -1. Any pods that are equal on the above criteria will be sorted lexicographically. - -### Pod Update Selection Logic - -Loop over the sorted pods, until the number of pods selected to be updated has reached the maximum. -This maximum is calculated by taking the given, or default, [`maxPodsUnavailable`](solr-cloud-crd.md#update-strategy) and subtracting the number of updated pods that are unavailable or have yet to be re-created. - - If the pod is the overseer, then all other pods must be updated and available. - Otherwise, the overseer pod cannot be updated. - - If the pod contains no replicas, the pod is chosen to be updated. - **WARNING**: If you use Solr worker nodes for streaming expressions, you will likely want to set [`maxPodsUnavailable`](solr-cloud-crd.md#update-strategy) to a value you are comfortable with. - - If Solr Node of the pod is not **`live`**, the pod is chosen to be updated. - - If all replicas in the pod are in a **`down`** or **`recovery_failed`** state, the pod is chosen to be updated. - - If the taking down the replicas hosted in the pod would not violate the given [`maxShardReplicasUnavailable`](solr-cloud-crd.md#update-strategy), then the pod can be updated. - Once a pod with replicas has been chosen to be updated, the replicas hosted in that pod are then considered unavailable for the rest of the selection logic. - - Some replicas in the shard may already be in a non-active state, or may reside on Solr Nodes that are not "live". - The `maxShardReplicasUnavailable` calculation will take these replicas into account, as a starting point. - - If a pod contains non-active replicas, and the pod is chosen to be updated, then the pods that are already non-active will not be double counted for the `maxShardReplicasUnavailable` calculation. - -## Triggering a Manual Rolling Restart - -Given these complex requirements, `kubectl rollout restart statefulset` will generally not work on a SolrCloud. - -One option to trigger a manual restart is to change one of the podOptions annotations. For example you could set this to the date and time of the manual restart. - - -```yaml -apiVersion: solr.apache.org/v1beta1 -kind: SolrCloud -spec: - customSolrKubeOptions: - podOptions: - annotations: - manualrestart: "2021-10-20T08:37:00Z" -``` - -## Pod Readiness during updates - -The Solr Operator sets up at least two Services for every SolrCloud. -- Always - - A clusterIP service for all solr nodes (What we call the "common service") -- Either - - A [Headless Service](https://kubernetes.io/docs/concepts/services-networking/service/#headless-services) for individual Solr Node endpoints that are not exposed via an Ingress. - - Individual clusterIP services for Solr Nodes that are exposed via an Ingress - -Only the common service uses the `publishNotReadyAddresses: false` option, since the common service should load balance between all available nodes. -The other services have individual endpoints for each node, so there is no reason to de-list pods that are not available. - -When doing a rolling upgrade, or taking down a pod for any reason, we want to first stop all requests to this pod. -Solr will do this while stopping by first taking itself out of the cluster's set of `liveNodes` , so that other Solr nodes and clients think it is not running. -However, for ephemeral clusters we are also evicting data before the pod is deleted. So we want to stop requests to this node since the data will soon no-longer live there. - -Kubernetes allows the Solr Operator to control whether a pod is considered `ready`, or available for requests, via [readinessConditions/readinessGates](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-gate). -When the Solr Operator begins the shut-down procedure for a pod, it will first set a `readinessCondition` to `false`, so that no loadBalanced requests (through the common service) go to the pod. -This readinessCondition will stay set to `false` until the pod is deleted and a new pod is created in its place. - -**For this reason, it's a good idea to avoid very aggressive [Update Strategies](solr-cloud-crd.md#update-strategy). -During a rolling restart with a high `maxPodsUnavailable`, requests that go through the common service might be routed to a very small number of pods.** diff --git a/docs/upgrade-notes.md b/docs/upgrade-notes.md deleted file mode 100644 index 2a2eb176..00000000 --- a/docs/upgrade-notes.md +++ /dev/null @@ -1,344 +0,0 @@ - - -# Solr Operator Upgrade Notes - -Please carefully read the entries for all versions between the version you are running and the version you want to upgrade to. - -Ensure to read the [Upgrade Warnings and Notes](#upgrade-warnings-and-notes) for the version you are upgrading to as well as the versions you are skipping. - -If you want to skip versions when upgrading, be sure to check out the [upgrading minor versions](#upgrading-minor-versions-vxa---vxb) and [upgrading patch versions](#upgrading-patch-versions-vxya---vzyb) sections. - -## Version Compatibility Matrixes - -### Kubernetes Versions - -| Solr Operator Version | `1.15` | `1.16` - `1.18` | `1.19` - `1.20` | `1.21` | `1.22`+ | -|:---------------------:| :---: | :---: |:------------------:|:------------------:|:------------------:| -| `v0.2.6` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | -| `v0.2.7` | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | -| `v0.2.8` | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | -| `v0.3.x` | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | -| `v0.4.x` | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | -| `v0.5.x` | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| `v0.6.x` | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| `v0.7.x` | :x: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| `v0.8.x` | :x: | :x: | :x: | :x: | :heavy_check_mark: | -| `v0.9.x` | :x: | :x: | :x: | :x: | :heavy_check_mark: | -| `v0.10.x` | :x: | :x: | :x: | :x: | :heavy_check_mark: | - -### Solr Versions - -| Solr Operator Version | `7.7` | `8.0` - `8.10` | `8.11` | `9.0` - `9.3` | `9.4`+ | -|:---------------------:|:------------------:|:------------------:|:------------------:|:------------------------:|:------------------------:| -| `v0.2.7` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | -| `v0.2.8` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | -| `v0.3.x` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | -| `v0.4.x` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | -| `v0.5.x` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | -| `v0.6.x` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: :one: | :heavy_check_mark: :one: | -| `v0.7.x` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: :one: | :heavy_check_mark: :one: | -| `v0.8.x` | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: :one: | :heavy_check_mark: | -| `v0.9.x` | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: :one: | :heavy_check_mark: | -| `v0.10.x` | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: :one: | :heavy_check_mark: | - -**Exceptions** -* :one: `SolrTLS` and `SolrClientTLS` are not supported - -Please note that this represents basic compatibility with the Solr Operator. -There may be options and features that require newer versions of Solr. -(e.g. S3/GCS Backup Support) - -Please test to make sure the features you plan to use are compatible with the version of Solr you choose to run. - - -## Upgrade Instructions - -Please follow the instructions below when upgrading the Solr Operator. - -However, no matter the upgrade, always read the [Upgrade Notes](#upgrade-warnings-and-notes) for every version between - -### Upgrading minor versions (`vX.A._` -> `vX.B._`) - -In order to upgrade minor versions (e.g. `v0.2.5` -> `v0.3.0`), you must upgrade one minor version at a time (e.g. `v0.2.0` -> `v0.3.0` -> `v0.4.0`). -It is also necessary to upgrade to the latest patch version before upgrading to the next minor version. -Therefore if you are running `v0.2.5` and you want to upgrade to `v0.3.0`, you must first upgrade to `v0.2.8` before upgrading to `v0.3.0`. - -There when upgrading minor versions, there may be CRD options that have been deprecated. -The Solr Operator will automatically change the existing Solr resources to use the new format. -Therefore when upgrading to the next version, which may remove the deprecated option, the existing resources will behave correctly. -However, creating new resources with the deprecated options will fail. -Be sure to carefully read the [Upgrade Warnings](#upgrade-warnings-and-notes) to be sure you are not using deprecated options. - -### Upgrading patch versions (`vX.Y.A` -> `vZ.Y.B`) - -You should be able to upgrade from a version to any patch version with the same minor and major versions. -It is always encouraged to upgrade to the latest patch version of the minor and major version you are running. -There is no need to upgrade one patch version at a time (e.g. `v0.2.5` -> `v0.2.6` -> `v0.2.7` -> `v0.2.8`), -instead you can leap to the latest patch version (e.g. `v0.2.5` -> `v0.2.8`). - -## Installing the Solr Operator vs Solr CRDs - -Installing the Solr Operator, especially via the [Helm Chart](https://artifacthub.io/packages/helm/apache-solr/solr-operator), -does not necessarily mean that you are installing the required CRDs for that version of the Solr Operator. - -If the Solr CRDs already exist in your Kubernetes cluster, then Helm will not update them even if the CRDs have changed between the Helm chart versions. -Instead, you will need to manually install the CRDs whenever upgrading your Solr Operator. -**You should always upgrade your CRDs before upgrading the Operator** - -You can do this via the following command, replacing `` with the version of the Solr Operator you are installing: -```bash -# Just replace the Solr CRDs -kubectl replace -f "http://solr.apache.org/operator/downloads/crds//all.yaml" -# Just replace the Solr CRDs and all CRDs it might depend on (e.g. ZookeeperCluster) -kubectl replace -f "http://solr.apache.org/operator/downloads/crds//all-with-dependencies.yaml" -``` - -It is **strongly recommended** to use `kubectl create` or `kubectl replace`, instead of `kubectl apply` when creating/updating CRDs. - -### Upgrading the Zookeeper Operator - -When upgrading the Solr Operator, you may need to upgrade the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator) at the same time. -If you are using the Solr Helm chart to deploy the Zookeeper operator, then you won't need to do anything besides installing the CRD's with dependencies, and upgrade the Solr Operator helm deployment. - -```bash -# Just replace the Solr CRDs and all CRDs it might depend on (e.g. ZookeeperCluster) -kubectl replace -f "http://solr.apache.org/operator/downloads/crds/v0.10.0-prerelease/all-with-dependencies.yaml" -helm upgrade solr-operator apache-solr/solr-operator --version 0.10.0-prerelease -``` - -_Note that the Helm chart version does not contain a `v` prefix, which the downloads version does. The Helm chart version is the only part of the Solr Operator release that does not use the `v` prefix._ - -## Upgrade Warnings and Notes - -### v0.10.0 -- **Logging now defaults to JSON format** - The new default for CLI flag `--zap-devel` is now `false`, causing log encoding to be `json` and log level to be `info`. - There is a new helm value `development` that can be set to `true` to switch to `console` encoding and `debug` level - that was the default in previous versions. - -### v0.8.0 -- **The minimum supported Solr version is now 8.11** - If you are unable to use a newer version of Solr, please install the `v0.7.1` version of the Solr Operator. - However, it is strongly suggested to upgrade to newer versions of Solr that are actively supported. - See the [version compatibility matrix](#solr-versions) for more information. - -- **Kubernetes support is now limited to 1.22+.** - If you are unable to use a newer version of Kubernetes, please install the `v0.7.1` version of the Solr Operator for use with Kubernetes `1.21`. - See the [version compatibility matrix](#kubernetes-versions) for more information. - -- The new `SolrCloud.spec.scaling.vacatePodsOnScaleDown` option is enabled by default. - This means that any SolrCloud that has its `spec.replicas` decreased will have the replicas migrated off of the soon-to-be-deleted pods by default. - Set this value to `false` to retain the previous functionality. - More information can be found in the [Solr Pod Scale-Down](solr-cloud/scaling.md#solr-pod-scale-down) documentation. - -- The `POD_HOSTNAME` envVar in SolrCloud Pods has been deprecated. Use `POD_NAME` instead. - -- Use of the `hostPort` system property placeholder in custom solr.xml files has been deprecated. - Use `${solr.port.advertise:80}`, the default value used by Solr, instead. - -- By default `solrcloud` resources will now use `/admin/info/system` and `/admin/info/health` for liveness and readiness checks, respectively. - Administrators that provide custom `security.json` files for their clusters should either exempt both of these endpoints from authentication entirely, or configure permissions ensuring the relevant Solr user account can access them without issue. - -### v0.7.0 -- **Kubernetes support is now limited to 1.21+.** - If you are unable to use a newer version of Kubernetes, please install the `v0.6.0` version of the Solr Operator for use with Kubernetes `1.20` and below. - See the [version compatibility matrix](#kubernetes-versions) for more information. - -- The required version of the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator) to use with this version has been upgraded from `v0.2.14` to `v0.2.15`. - If you use the Solr Operator helm chart, then by default the new version of the Zookeeper Operator will be installed as well. - Refer to the helm chart documentation if you want to manage the Zookeeper Operator installation yourself. - Please refer to the [Zookeeper Operator release notes](https://github.com/pravega/zookeeper-operator/releases) before upgrading. - Make sure to install the correct version of the Zookeeper Operator CRDs, as [shown above](#upgrading-the-zookeeper-operator). - -- `PodDisruptionBudgets` are now created by default alongside SolrCloud instances. - The maximum number of pods allowed down at any given time is aligned with the [Managed Update settings](solr-cloud/solr-cloud-crd.md#update-strategy) provided in the spec. - If this is not provided, the default setting (`25%`) is used. - `PodDisruptionBudget` creation can be disabled for a solrcloud resource, by setting `spec.availability.podDisruptionBudget.enabled` to false. - -- Provided Zookeeper pods use the `IfNotPresent` pullPolicy by default. Users that specify this field manually will not see a change. - -- The Solr Operator now tries to limit connectivity to pods before they are deleted, for rolling updates or other reasons. - Before the pod is killed, and evicted of replicas if ephemeral storage is used, a readinessCondition will be set to `false`. - The Headless Service does not use readiness, so internode traffic will not be affected, however the ClusterIP (common) service will no longer include these nodes until they have been restarted. - This change will improve request success rates during a rolling restart. - Refer to the [Managed Updates documentation](solr-cloud/managed-updates.md#pod-readiness-during-updates). - -- The deprecated SolrCloud CRD field `Spec.solrAddressability.external.ingressTLSTerminationSecret` has been removed, please use `Spec.solrAddressability.external.ingressTLSTermination.tlsSecret` instead. - In order to have these fields changed automatically, upgrade to the `v0.6.0` version of the Solr operator before upgrading to the `v0.7.0` version. - However, all new SolrCloud resources will need to respect this field change. - -- The deprecated SolrCloud CRD field `Spec.solrAddressability.external.additionalDomains` has been removed, please use `Spec.solrAddressability.external.additionalDomainNames` instead. - In order to have these fields changed automatically, upgrade to the `v0.6.0` version of the Solr operator before upgrading to the `v0.7.0` version. - However, all new SolrCloud resources will need to respect this field change. - -### v0.6.0 -- The default Solr version for the `SolrCloud` and `SolrPrometheusExporter` resources has been upgraded from `8.9` to `8.11`. - This will not affect any existing resources, as default versions are hard-written to the resources immediately. - Only new resources created after the Solr Operator is upgraded to `v0.6.0` will be affected. - -- The required version of the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator) to use with this version has been upgraded from `v0.2.12` to `v0.2.14`. - If you use the Solr Operator helm chart, then by default the new version of the Zookeeper Operator will be installed as well. - Refer to the helm chart documentation if you want to manage the Zookeeper Operator installation yourself. - Please refer to the [Zookeeper Operator release notes](https://github.com/pravega/zookeeper-operator/releases) before upgrading. - Make sure to install the correct version of the Zookeeper Operator CRDS, as [shown above](#upgrading-the-zookeeper-operator). - -- The SolrCloud CRD field `Spec.solrAddressability.external.additionalDomains` has been renamed to `additionalDomainNames`. - In this release `additionalDomains` is still accepted, but all values will automatically be added to `additionalDomainNames` and the field will be set to `nil` by the operator. - The `additionalDomains` option will be removed in a future version. - -- The SolrCloud CRD field `Spec.solrAddressability.external.ingressTLSTerminationSecret` has been moved to `Spec.solrAddressability.external.ingressTLSTermination.tlsSecret`. - In this release `ingressTLSTerminationSecret` is still accepted, but all values will automatically be changed to `ingressTLSTermination.tlsSecret` and the original field will be set to `nil` by the operator. - The `ingressTLSTerminationSecret` option will be removed in a future version. - -- `SolrPrometheusExporter` resources without any image specifications (`SolrPrometheusExporter.Spec.image.*`) will use the referenced `SolrCloud` image, if the reference is by `name`, not `zkConnectionString`. - If any `SolrPrometheusExporter.Spec.image.*` option is provided, then those values will be defaulted by the Solr Operator and the `SolrCloud` image will not be used. - When upgrading from `v0.5.*` to `v0.6.0`, only new `SolrPrometheusExporter` resources will use this new feature. - To enable it on existing resources, update the resources and remove the `SolrPrometheusExporter.Spec.image` section. - -- CRD options deprecated in `v0.5.0` have been removed. - This includes field `SolrCloud.spec.dataStorage.backupRestoreOptions`, `SolrBackup.spec.persistence` and `SolrBackup.status.persistenceStatus`. - Upgrading to `v0.5.*` will remove these options on existing and new SolrCloud and SolrBackup resources. - However, once the Solr CRDs are upgraded to `v0.6.0`, you will no longer be able to submit resources with the options listed above. - Please migrate your systems to use the new options while running `v0.5.*`, before upgrading to `v0.6.0`. - -### v0.5.0 -- Due to the deprecation and removal of `networking.k8s.io/v1beta1` in Kubernetes v1.22, `networking.k8s.io/v1` will be used for Ingresses. - - **This means that Kubernetes support is now limited to 1.19+.** - If you are unable to use a newer version of Kubernetes, please install the `v0.4.0` version of the Solr Operator for use with Kubernetes 1.18 and below. - See the [version compatibility matrix](#kubernetes-versions) for more information. - - This also means that if you specify a custom `ingressClass` via an annotation, you should change to use the `SolrCloud.spec.customSolrKubeOptions.ingressOptions.ingressClassName` instead. - The ability to set the class through annotations is now deprecated in Kubernetes and will be removed in future versions. - -- The legacy way of specifying a backupRepository has been **DEPRECATED**. - Instead of using `SolrCloud.spec.dataStorage.backupRestoreOptions`, use `SolrCloud.spec.backupRepositories`. - The `SolrCloud.spec.dataStorage.backupRestoreOptions` option **will be removed in `v0.6.0`**. - **Note**: Do not take backups while upgrading from the Solr Operator `v0.4.0` to `v0.5.0`. - Wait for the SolrClouds to be updated, after the Solr Operator is upgraded, and complete their rolling restarts before continuing to use the Backup functionality. - -- The location of Solr backup data as well as the name of the Solr backups have been changed, when using volume repositories. - Previously the name of the backup (in solr) was set to the name of the collection. - Now the name given to the backup in Solr will be set to `-`, without the `<` or `>` characters, where the `backup-resource-name` is the name of the SolrBackup resource. - - The directory in the Read-Write-Many Volume, required for volume repositories, that backups are written to is now `/cloud//backups` by default, instead of `/cloud//backups/`. - Because the backup name in Solr uses both the SolrBackup resource name and the collection name, there should be no collisions in this directory. - However, this can be overridden using the `SolrBackup.spec.location` option, which is appended to `/cloud/`. - -- The SolrBackup persistence option has been removed as of `v0.5.0`. - Users should plan to keep their backup data in the shared volume if using a Volume Backup repository. - If `SolrBackup.spec.persistence` is provided, it will be removed and written back to Kubernetes. - - Users using the S3 persistence option should try to use the [S3 backup repository](solr-backup/README.md#s3-backup-repositories) instead. This requires Solr 8.10 or higher. - -- Default ports when using TLS are now set to 443 instead of 80. - This affects `solrCloud.Spec.SolrAddressability.CommonServicePort` and `solrCloud.Spec.SolrAddressability.CommonServicePort` field defaulting. - Users already explicitly setting these values will not be affected. - -### v0.4.0 -- The required version of the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator) to use with this version has been upgraded from `v0.2.9` to `v0.2.12`. - If you use the Solr Operator helm chart, then by default the new version of the Zookeeper Operator will be installed as well. - Refer to the helm chart documentation if you want to manage the Zookeeper Operator installation yourself. - Please refer to the [Zookeeper Operator release notes](https://github.com/pravega/zookeeper-operator/releases) before upgrading. - Make sure to install the correct version of the Zookeeper Operator CRDS, as [shown above](#upgrading-the-zookeeper-operator). - -- The deprecated Solr Operator Helm chart option `useZkOperator` has been removed, use `zookeeper-operator.use` instead. - **Note**: The old option takes a _string_ `"true"`/`"false"`, while the new option takes a _boolean_ `true`/`false`. - -- The default Solr version for `SolrCloud` and `SolrPrometheusExporter` resources has been upgraded from `7.7.0` to `8.9`. - This will not affect any existing resources, as default versions are hard-written to the resources immediately. - Only new resources created after the Solr Operator is upgraded to `v0.4.0` will be affected. - -- In previous versions of the Solr Operator, the provided Zookeeper instances could only use Persistent Storage. - Now ephemeral storage is enabled, and used by default if Solr is using ephemeral storage. - The ZK storage type can be explicitly set via `Spec.zookeeperRef.provided.ephemeral` or `Spec.zookeeperRef.provided.persistence`, - however if neither is set, the Solr Operator will default to use the type of storage (persistent or ephemeral) that Solr is using. - **This means that the default Zookeeper Storage type can change for users using ephemeral storage for Solr. - If you require ephemeral Solr storage and persistent Zookeeper Storage, be sure to explicitly set that starting in `v0.4.0`.** - -### v0.3.0 -- All deprecated CRD fields and Solr Operator options from `v0.2.*` have been removed. - -- The `SolrCollection` and `SolrCollectionAlias` have been removed. Please use the Solr APIs to manage these resources instead. - Discussion around the removal can be found in [Issue #204](https://github.com/apache/solr-operator/issues/204). - -- The required version of the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator) to use with this version has been upgraded from `v0.2.6` to `v0.2.9`. - If you use the Solr Operator helm chart, then by default the new version of the Zookeeper Operator will be installed as well. - Refer to the helm chart documentation if you want to manage the Zookeeper Operator installation yourself. - Please refer to the [Zookeeper Operator release notes](https://github.com/pravega/zookeeper-operator/releases) before upgrading. - -### v0.2.7 -- Due to the addition of possible sidecar/initContainers for SolrClouds, the version of CRDs used had to be upgraded to `apiextensions.k8s.io/v1`. - - **This means that Kubernetes support is now limited to 1.16+.** - If you are unable to use a newer version of Kubernetes, please install the `v0.2.6` version of the Solr Operator for use with Kubernetes 1.15 and below. - -- The location of backup-restore volume mounts in Solr containers has changed from `/var/solr/solr-backup-restore` to `/var/solr/data/backup-restore`. - This change was made to ensure that there were no issues using the backup API with solr 8.6+, which restricts the locations that backup data can be saved to and read from. - This change should be transparent if you are merely using the SolrBackup CRD. - All files permissions issues with SolrBackups should now be addressed. - -- The default `PodManagementPolicy` for StatefulSets has been changed to `Parallel` from `OrderedReady`. - This change will not affect existing StatefulSets, as `PodManagementPolicy` cannot be updated. - In order to continue using `OrderedReady` on new SolrClouds, please use the following setting: - `SolrCloud.spec.customSolrKubeOptions.statefulSetOptions.podManagementPolicy` - -- The `SolrCloud` and `SolrPrometheusExporter` services' portNames have changed to `"solr-client"` and `"solr-metrics"` from `"ext-solr-client"` and `"ext-solr-metrics"`, respectively. - This is due to a bug in Kubernetes where `portName` and `targetPort` must match for services. - -- Support for `etcd`/`zetcd` deployments has been removed. - The section for a Zookeeper cluster Spec `SolrCloud.spec.zookeeperRef.provided.zookeeper` has been **DEPRECATED**. - The same fields (except for the deprecated `persistentVolumeClaimSpec` option) are now available under `SolrCloud.spec.zookeeperRef.provided`. - -- Data Storage options have been expanded, and moved from their old locations. - - `SolrCloud.spec.dataPvcSpec` has been **DEPRECATED**. - Please instead use the following instead: `SolrCloud.spec.dataStorage.persistent.pvcTemplate.spec=` - - `SolrCloud.spec.backupRestoreVolume` has been **DEPRECATED**. - Please instead use the following instead: `SolrCloud.spec.dataStorage.backupRestoreOptions.Volume=` - -### v0.2.6 -- The solr-operator argument `--ingressBaseDomain` has been **DEPRECATED**. - In order to set the external baseDomain of your clouds, please begin to use `SolrCloud.spec.solrAddressability.external.domainName` instead. - You will also need to set `SolrCloud.spec.solrAddressability.external.method` to `Ingress`. - The `--ingressBaseDomain` argument is backwards compatible, and all existing SolrCloud objects will be auto-updated once your operator is upgraded to `v0.2.6`. - The argument will be removed in a future version (`v0.3.0`). - -### v0.2.4 -- The default supported version of the Zookeeper Operator has been upgraded to `v0.2.6`. - If you are using the provided zookeeper option for your SolrClouds, then you will want to upgrade your zookeeper operator version as well as the version and image of the zookeeper that you are running. - You can find examples of the zookeeper operator as well as solrClouds that use provided zookeepers in the [examples](/example) directory. - Please refer to the [Zookeeper Operator release notes](https://github.com/pravega/zookeeper-operator/releases) before upgrading. - -### v0.2.3 -- If you do not use an ingress with the Solr Operator, the Solr Hostname and Port will change when upgrading to this version. This is to fix an outstanding bug. Because of the headless service port change, you will likely see an outage for inter-node communication until all pods have been restarted. - -### v0.2.2 -- `SolrCloud.spec.solrPodPolicy` has been **DEPRECATED** in favor of the `SolrCloud.spec.customSolrKubeOptions.podOptions` option. - This option is backwards compatible, but will be removed in a future version (`v0.3.0`). - -- `SolrPrometheusExporter.spec.solrPodPolicy` has been **DEPRECATED** in favor of the `SolrPrometheusExporter.spec.customKubeOptions.podOptions` option. - This option is backwards compatible, but will be removed in a future version (`v0.3.0`). - -### v0.2.1 -- The zkConnectionString used for provided zookeepers changed from using the string provided in the `ZkCluster.Status`, which used an IP, to using the service name. This will cause a rolling restart of your solrs using the provided zookeeper option, but there will be no data loss. - -### v0.2.0 -- Uses `gomod` instead of `dep` -- `SolrCloud.spec.zookeeperRef.provided.zookeeper.persistentVolumeClaimSpec` has been **DEPRECATED** in favor of the `SolrCloud.zookeeperRef.provided.zookeeper.persistence` option. - This option is backwards compatible, but will be removed in a future version (`v0.3.0`). -- An upgrade to the ZKOperator version `0.2.4` is required. diff --git a/docs/upgrading-to-apache.md b/docs/upgrading-to-apache.md deleted file mode 100644 index 2e58db80..00000000 --- a/docs/upgrading-to-apache.md +++ /dev/null @@ -1,152 +0,0 @@ - - -# Upgrading the Solr Operator from Bloomberg to Apache - -Please read the guide fully before attempting to upgrade your system. - -## Guide - -There are many ways of managing what runs in your Kubernetes cluster. -Therefore, we cannot give one definitive way of upgrading the Solr Operator and the Solr resources in your Cluster. - -Below are guides based on how to upgrade, depending on the type of management that you use. -Please look through all the instructions to see what will work best for your setup. - -## If you manage your cluster declaratively - -If you have an external system managing your cluster (e.g. Ansible, Helm, etc), then the steps you take to upgrade the Solr Operator may be very different. - -1. Make sure your system is installing the `v0.3.0` version of the Solr Operator, through the [Helm chart](https://artifacthub.io/packages/helm/apache-solr/solr-operator), or other means. -1. Make sure your system is [installing the `v0.2.9` version of the Zookeeper Operator](#zookeeper-operator-upgrade). -1. Make sure the Solr resources you are installing are using the new `solr.apache.org` group and not `solr.bloomberg.com`. -1. Check if the Solr resources you are managing use any fields deprecated in `v0.2.x` versions, you can check for these in the [Upgrade Notes](upgrade-notes.md#upgrade-warnings-and-notes). - - If your resources contain these fields, replace them with their new locations. - Otherwise, your `kubectl apply` commands will fail when using the `solr.apache.org` CRDs. - -Once you have made sure that your declarative system is checked for the above points, you can run it to install the new version of the Solr Operator and all of your new CRDs. - -Now you need to delete all the old `solr.bloomberg.com` resources & operator. - -1. Remove the `v0.2.x` version of the Solr Operator that is running, unless you merely upgraded your existing deployment to `v0.3.0`. -1. [Remove any finalizers](#remove-solr-resource-finalizers) that the Solr Resources may contain, in all namespaces that you run Solr resources in. -1. [Remove the `solr.bloomberg.com` CRDs](#remove-bloomberg-solr-crds), as they are no longer needed when running the `v0.3.0` version of the Solr Operator. - -## If you manually manage your cluster - -If you manually manage your cluster, then the instructions below will allow you to upgrade in-place. - -1. Make sure you have the latest Apache Solr Operator helm charts (If you use helm to deploy the Solr Operator) - ```bash - helm repo add apache-solr https://solr.apache.org/charts - helm repo update - ``` -1. Upgrade to `v0.2.8`, if you are running a version lower. - - If your Solr Operator deployment is managed with a Helm chart, merely upgrade your helm chart to version `0.2.8` -1. Install the v0.2.8 Solr Operator CRDs - ```bash - kubectl replace -f "https://solr.apache.org/operator/downloads/crds/v0.2.8/all.yaml" - ``` - _The Upgrade Notes page says to always upgrade CRDs before upgrading the operator, however for this single upgrade case this order is safer._ -1. _If you are using the ZK Operator_ - [Remove the outdated Zookeeper Operator deployment and other resources](#removing-the-old-zookeeper-operator-resources). -1. Install the Apache Solr CRDs - ```bash - kubectl create -f "https://solr.apache.org/operator/downloads/crds/v0.3.0/all.yaml" - ``` - _If you are using the ZK Operator_ - ```bash - kubectl create -f "https://solr.apache.org/operator/downloads/crds/v0.3.0/all-with-dependencies.yaml" || \ - kubectl replace -f "https://solr.apache.org/operator/downloads/crds/v0.3.0/all-with-dependencies.yaml" - ``` -1. Install the Apache Solr Operator - ```bash - helm install apache apache-solr/solr-operator --version 0.3.0 - ``` -1. Convert `solr.bloomberg.com` resources into `solr.apache.org` resources: - ```bash - # First make sure that "yq" is installed - kubectl get solrclouds.solr.bloomberg.com --all-namespaces -o yaml | \ - sed "s#solr.bloomberg.com#solr.apache.org#g" | \ - yq eval 'del(.items.[].metadata.annotations."kubectl.kubernetes.io/last-applied-configuration", .items.[].metadata.managedFields, .items.[].metadata.resourceVersion, .items.[].metadata.creationTimestamp, .items.[].metadata.generation, .items.[].metadata.selfLink, .items.[].metadata.uid, .items.[].spec.solrPodPolicy, .items.[].spec.zookeeperRef.provided.image.tag, .items.[].status)' - \ - | kubectl apply -f - - kubectl get solrprometheusexporters.solr.bloomberg.com --all-namespaces -o yaml | \ - sed "s#solr.bloomberg.com#solr.apache.org#g" | \ - yq eval 'del(.items.[].metadata.annotations."kubectl.kubernetes.io/last-applied-configuration", .items.[].metadata.managedFields, .items.[].metadata.resourceVersion, .items.[].metadata.creationTimestamp, .items.[].metadata.generation, .items.[].metadata.selfLink, .items.[].metadata.uid, .items.[].spec.podPolicy, .items.[].status)' - \ - | kubectl apply -f - - kubectl get solrbackups.solr.bloomberg.com --all-namespaces -o yaml | \ - sed "s#solr.bloomberg.com#solr.apache.org#g" | \ - yq eval 'del(.items.[].metadata.annotations."kubectl.kubernetes.io/last-applied-configuration", .items.[].metadata.managedFields, .items.[].metadata.resourceVersion, .items.[].metadata.creationTimestamp, .items.[].metadata.generation, .items.[].metadata.selfLink, .items.[].metadata.uid, .items.[].status)' - \ - | kubectl apply -f - - ``` -1. Delete the `v0.2.8` Solr Operator deployment: - ```bash - # If solr-operator is the name of your v0.2.8 Solr Operator deployment - helm delete solr-operator - ``` -1. [Remove any finalizers](#remove-solr-resource-finalizers) that the Solr Resources may contain, in all namespaces that you run Solr resources in. -1. [Remove the `solr.bloomberg.com` CRDs](#remove-bloomberg-solr-crds), as they are no longer needed when running the `v0.3.0` version of the Solr Operator. -1. Test to make sure that your Solr resources exist as apache resources now and your `StatefulSets`/`Deployments` are still running correctly. - -## Other Considerations - -### Zookeeper Operator Upgrade - -The [Zookeeper Operator](https://github.com/pravega/zookeeper-operator) version that the Solr Operator requires has changed between `v0.2.6` and `v0.3.0`. -Therefore, the Zookeeper Operator needs to be upgraded to `v0.2.9` when the Solr Operator is upgraded to `v0.3.0`. - -#### Removing the old Zookeeper Operator resources -If you use the Solr Operator [Helm chart](https://artifacthub.io/packages/helm/apache-solr/solr-operator), then the correct version of the Zookeeper Operator will be deployed when upgrading. -However, you will need to pre-emptively delete some Kubernetes resources so that they can be managed by Helm. - -_Only use the below `kubectl` commands if you installed the Zookeeper Operator using the URL provided in the Solr Operator repository._ -If you already have a `v0.2.9` Zookeeper Operator running, ignore this and pass the following options when installing the Solr Operator: -`--set zookeeper-operator.install=false --set zookeeper-operator.use=true` - -```bash -kubectl delete deployment zk-operator -kubectl delete clusterrolebinding zookeeper-operator-cluster-role-binding -kubectl delete clusterrole zookeeper-operator -kubectl delete serviceaccount zookeeper-operator -``` - -You will then be able to install the Solr Operator & dependency CRDs, and the Solr Operator Helm Chart. - - -### Remove Solr Resource Finalizers - -It is necessary to remove any finalizers that the old `solr.bloomberg.com` resources may have, otherwise they will not be able to be deleted. -You should do this for all namespaces that you are running solr resources in. - -**Only run these after stopping any `v0.2.x` Solr Operator that may be running in the Kubernetes cluster.** - -```bash -kubectl get solrcollections.solr.bloomberg.com -o name | sed -e 's/.*\///g' | xargs -I {} kubectl patch solrcollections.solr.bloomberg.com {} --type='json' -p='[{"op": "remove", "path": "/metadata/finalizers/0"}]' -kubectl get solrcollectionaliases.solr.bloomberg.com -o name | sed -e 's/.*\///g' | xargs -I {} kubectl patch solrcollectionaliases.solr.bloomberg.com {} --type='json' -p='[{"op": "remove", "path": "/metadata/finalizers/0"}]' -kubectl get solrclouds.solr.bloomberg.com -o name | sed -e 's/.*\///g' | xargs -I {} kubectl patch solrclouds.solr.bloomberg.com {} --type='json' -p='[{"op": "remove", "path": "/metadata/finalizers/0"}]' -``` - -### Remove Bloomberg Solr CRDs - -After you have [removed all finalizers on Solr resources](#remove-solr-resource-finalizers), you can remove all `solr.bloomberg.com` CRDs. - -If you don't want to disrupt any Solr service that is running, make sure that all Solr resources have been upgraded from `solr.bloomberg.com` CRDs to `solr.apache.org` CRDs. -This command will delete all `solr.bloomberg.com` resources, which means that only resources that exist as `solr.apache.org` will continue to run afterwards. - -```bash -kubectl delete crd solrclouds.solr.bloomberg.com solrprometheusexporters.solr.bloomberg.com solrbackups.solr.bloomberg.com solrcollections.solr.bloomberg.com solrcollectionaliases.solr.bloomberg.com -``` diff --git a/hack/release/version/propagate_version.sh b/hack/release/version/propagate_version.sh index 32aaa67a..2715bd0d 100755 --- a/hack/release/version/propagate_version.sh +++ b/hack/release/version/propagate_version.sh @@ -100,19 +100,22 @@ fi # Update Docs (Remove this when docs are generated with versioning info) { - cat docs/local_tutorial.md | \ + cat docs/modules/getting-started/pages/local-tutorial.adoc | \ sed -E "s|(kubectl.+/crds/)[^/<]+|\1${VERSION}|g" | \ sed -E "s|(helm.+--version )[^ <]+|\1${VERSION#v}|g" -} > docs/local_tutorial.md.tmp && mv docs/local_tutorial.md.tmp docs/local_tutorial.md +} > docs/modules/getting-started/pages/local-tutorial.adoc.tmp && mv docs/modules/getting-started/pages/local-tutorial.adoc.tmp docs/modules/getting-started/pages/local-tutorial.adoc { - cat docs/upgrade-notes.md | \ + cat docs/modules/upgrade-notes/pages/upgrade-notes.adoc | \ sed -E "s|(kubectl.+/crds/)[^/<]+|\1${VERSION}|g" | \ sed -E "s|(helm.+--version )[^ <]+|\1${VERSION#v}|g" -} > docs/upgrade-notes.md.tmp && mv docs/upgrade-notes.md.tmp docs/upgrade-notes.md +} > docs/modules/upgrade-notes/pages/upgrade-notes.adoc.tmp && mv docs/modules/upgrade-notes/pages/upgrade-notes.adoc.tmp docs/modules/upgrade-notes/pages/upgrade-notes.adoc { - cat docs/running-the-operator.md | \ + cat docs/modules/getting-started/pages/running-the-operator.adoc | \ sed -E "s|(kubectl.+/crds/)[^/<]+|\1${VERSION}|g" | \ sed -E "s|(helm.+--version )[^ <]+|\1${VERSION#v}|g" -} > docs/running-the-operator.md.tmp && mv docs/running-the-operator.md.tmp docs/running-the-operator.md +} > docs/modules/getting-started/pages/running-the-operator.adoc.tmp && mv docs/modules/getting-started/pages/running-the-operator.adoc.tmp docs/modules/getting-started/pages/running-the-operator.adoc + +# Regenerate the operator Antora component descriptor (docs/antora.yml) from version/version.go +./hack/docs/generate_antora_yaml.sh make manifests diff --git a/hack/zk-operator/check-version.sh b/hack/zk-operator/check-version.sh index a82e34f9..6c3025a3 100755 --- a/hack/zk-operator/check-version.sh +++ b/hack/zk-operator/check-version.sh @@ -45,8 +45,8 @@ if (grep -E "https://raw.githubusercontent.com/pravega/zookeeper-operator/" hack printf "\nVersion not correct for all locations in file 'hack/release/artifacts/create_crds.sh' ^ \n" >&2 && exit 1 fi -if (grep -E "helm install zookeeper-operator" docs/development.md | grep -v -E "${ZK_OP_VERSION#v}"); then - printf "\nVersion not correct for all locations in file 'docs/development.md' ^ \nMake sure that this version does not contain a 'v'.\n" >&2 && exit 1 +if (grep -E "helm install zookeeper-operator" docs/modules/development/pages/development.adoc | grep -v -E "${ZK_OP_VERSION#v}"); then + printf "\nVersion not correct for all locations in file 'docs/modules/development/pages/development.adoc' ^ \nMake sure that this version does not contain a 'v'.\n" >&2 && exit 1 fi HELM_DEPENDENCY_VERSION="$(yq eval '.dependencies[] | select(.name = "zookeeper-operator") | .version' helm/solr-operator/Chart.yaml)" diff --git a/helm/solr-operator/README.md b/helm/solr-operator/README.md index 2e44b873..1a56ee97 100644 --- a/helm/solr-operator/README.md +++ b/helm/solr-operator/README.md @@ -9,7 +9,7 @@ Documentation around using the Solr Operator can be found at it's [official site ## Upgrade Notes -Before upgrading your Solr Operator to a newer version, **please refer to the [Upgrade Notes](https://apache.github.io/solr-operator/docs/upgrade-notes.html)**. +Before upgrading your Solr Operator to a newer version, **please refer to the [Upgrade Notes](https://solr.apache.org/guide/operator/latest/upgrade-notes/upgrade-notes.html)**. There may be breaking changes between the version you are running and the version you want to upgrade to. ## Using the Helm Chart diff --git a/helm/solr/README.md b/helm/solr/README.md index a2c29c93..24428788 100644 --- a/helm/solr/README.md +++ b/helm/solr/README.md @@ -26,7 +26,7 @@ The Solr version can be any supported version of Solr you wish to run, but the _ ## Upgrade Notes -Before upgrading your Solr Operator and Solr Helm chart version, **please refer to the [Upgrade Notes](https://apache.github.io/solr-operator/docs/upgrade-notes.html)**. +Before upgrading your Solr Operator and Solr Helm chart version, **please refer to the [Upgrade Notes](https://solr.apache.org/guide/operator/latest/upgrade-notes/upgrade-notes.html)**. There may be breaking changes between the version you are using and the version you want to upgrade to. ## Using the Helm Chart @@ -54,7 +54,7 @@ helm upgrade example apache-solr/solr --version 0.10.0-prerelease --reuse-values ``` The upgrade will be done according to the `upgradeStrategy.method` chosen in the values. -Be sure to select the [update strategy](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#update-strategy) that best fits your use case. +Be sure to select the [update strategy](https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#update-strategy) that best fits your use case. However, the `Managed` strategy is highly recommended. ### Uninstalling the Chart @@ -72,7 +72,7 @@ The command removes the SolrCloud resource, and then Kubernetes will garbage col Please note that there is not a 1-1 mapping from SolrCloud CRD options to Solr Helm options. All options should be supported, but they might be slightly renamed in some scenarios, such as `customSolrKubeOptions`. Please read below to see what the Helm chart values are for the options you need. -Descriptions on how to use these options can be found in the [SolrCloud documentation](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html). +Descriptions on how to use these options can be found in the [SolrCloud documentation](https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html). ### Running Solr @@ -101,7 +101,7 @@ Descriptions on how to use these options can be found in the [SolrCloud document | solrOptions.security.probesRequireAuth | boolean | | Whether the probes for the SolrCloud pod require auth | | solrOptions.security.bootstrapSecurityJson.name | string | | Name of a Secret in the same namespace that stores a user-provided `security.json` to bootstrap the Solr security config | | solrOptions.security.bootstrapSecurityJson.key | string | | Key holding the user-provided `security.json` in the bootstrap security Secret | -| updateStrategy.method | string | `"Managed"` | The method for conducting updates of Solr pods. Either `Managed`, `StatefulSet` or `Manual`. See the [docs](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#update-strategy) for more information | +| updateStrategy.method | string | `"Managed"` | The method for conducting updates of Solr pods. Either `Managed`, `StatefulSet` or `Manual`. See the [docs](https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#update-strategy) for more information | | updateStrategy.managedUpdate.maxPodsUnavailable | int-or-string | `"25%"` | The number of Solr pods in a Solr Cloud that are allowed to be unavailable during the rolling restart. Either a static number, or a percentage representing the percentage of total pods requested for the statefulSet. | | updateStrategy.managedUpdate.maxShardReplicasUnavailable | int-or-string | `1` | The number of replicas for each shard allowed to be unavailable during the restart. Either a static number, or a percentage representing the percentage of the number of replicas for a shard. | | updateStrategy.restartSchedule | [string (CRON)](https://pkg.go.dev/github.com/robfig/cron/v3?utm_source=godoc#hdr-CRON_Expression_Format) | | A CRON schedule for automatically restarting the Solr Cloud. [Refer here](https://pkg.go.dev/github.com/robfig/cron/v3?utm_source=godoc#hdr-CRON_Expression_Format) for all possible CRON syntaxes accepted. | @@ -109,13 +109,13 @@ Descriptions on how to use these options can be found in the [SolrCloud document | availability.podDisruptionBudget.method | string | `"ClusterWide"` | The method by which PodDisruptionBudgets should be created. The only option currently is `ClusterWide`. | | serviceAccount.create | boolean | `false` | Create a serviceAccount to be used for all pods being deployed (Solr & ZK). If `serviceAccount.name` is not specified, the full name of the deployment will be used. | | serviceAccount.name | string | | The optional default service account used for Solr and ZK unless overridden below. If `serviceAccount.create` is set to `false`, this serviceAccount must exist in the target namespace. | -| backupRepositories | []object | | A list of BackupRepositories to connect your SolrCloud to. Visit the [SolrBackup docs](https://apache.github.io/solr-operator/docs/solr-backup) or run `kubectl explain solrcloud.spec.backupRepositories` to see the available options. | +| backupRepositories | []object | | A list of BackupRepositories to connect your SolrCloud to. Visit the [SolrBackup docs](https://solr.apache.org/guide/operator/latest/solr-backup/index.html) or run `kubectl explain solrcloud.spec.backupRepositories` to see the available options. | | scaling.vacatePodsOnScaleDown | boolean | `true` | While scaling down the SolrCloud, move replicas off of Solr Pods before they are deleted. This only affects pods that will not exist after the scaleDown operation. | | scaling.populatePodsOnScaleUp | boolean | `true` | While scaling up the SolrCloud, migrate replicas onto the new Solr Pods after they are created. This uses the Balance Replicas API in Solr that is only available in Solr 9.3+. This option will be ignored if using an unsupported version of Solr. | ### Data Storage Options -See the [documentation](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#data-storage) for more information. +See the [documentation](https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#data-storage) for more information. | Key | Type | Default | Description | |-----|------|---------|-------------| @@ -131,7 +131,7 @@ See the [documentation](https://apache.github.io/solr-operator/docs/solr-cloud/s ### Addressability Options -See the [documentation](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#addressability) for more information. +See the [documentation](https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#addressability) for more information. If providing external addressability, then `method` and `domainName` must be provided. External addressability is disabled by default. @@ -210,7 +210,7 @@ Currently the Zookeeper Operator does not support ACLs, so do not use the provid ### TLS Options -See [documentation](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#enable-tls-between-solr-pods) for more information. +See [documentation](https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#enable-tls-between-solr-pods) for more information. Solr TLS is disabled by default. Provide any of the following to enable it. @@ -238,7 +238,7 @@ Solr TLS is disabled by default. Provide any of the following to enable it. #### Client TLS Options -See [documentation](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#enable-tls-between-solr-pods) for more information. +See [documentation](https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#enable-tls-between-solr-pods) for more information. Configure Solr to use a separate TLS certificate for client auth. diff --git a/helm/solr/values.yaml b/helm/solr/values.yaml index e6addba7..1713cb1b 100644 --- a/helm/solr/values.yaml +++ b/helm/solr/values.yaml @@ -63,7 +63,7 @@ solrOptions: # Enable authentication for the Solr Cloud # More information can be found at: - # https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#authentication-and-authorization + # https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#authentication-and-authorization security: {} # authenticationType: Basic # basicAuthSecret: secret-name @@ -74,7 +74,7 @@ solrOptions: # Specify how the SolrCloud should be addressable -# https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#addressability +# https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#addressability addressability: podPort: 8983 commonServicePort: null @@ -94,7 +94,7 @@ addressability: # useDefaultTLSSecret: false # Specify how rolling updates should be managed for the Solr StatefulSet -# https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#update-strategy +# https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#update-strategy updateStrategy: method: "Managed" # Options for the managed update method @@ -113,7 +113,7 @@ updateStrategy: restartSchedule: "" # More information can be found at: -# https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#data-storage +# https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#data-storage dataStorage: # Either persistent or ephemeral type: "ephemeral" @@ -150,7 +150,7 @@ scaling: # A list of BackupRepositories to connect your SolrCloud to # See either for more information: -# - https://apache.github.io/solr-operator/docs/solr-backup +# - https://solr.apache.org/guide/operator/latest/solr-backup/index.html # - kubectl explain solrcloud.spec.backupRepositories backupRepositories: [] # - name: example-repo # Required @@ -234,7 +234,7 @@ zk: # Enable TLS between your SolrCloud nodes # More information can be found at: -# https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#enable-tls-between-solr-pods +# https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#enable-tls-between-solr-pods solrTLS: {} # pkcs12Secret: # name: secret-name From a59eeb11f181c157174c27578fb0b4e5c760b2e7 Mon Sep 17 00:00:00 2001 From: Houston Putman Date: Mon, 8 Jun 2026 14:27:28 -0700 Subject: [PATCH 3/7] Split SolrCloud CRD/SolrBackup reference pages and drop Since markers The SolrCloud CRD and SolrBackup pages were large single documents. Now that the docs are a versioned Antora site, split them into focused pages and remove the per-feature "Since vX.Y.Z" annotations (version context is provided by the versioned site itself). - SolrCloud CRD overview keeps the common options and links out to its own pages: addressability, zookeeper, custom-solr-config, tls, and authentication-and-authorization (addressability is split out on its own to leave room for future expansion). - SolrBackup splits the repository-type reference into backup-repositories. - All cross-references updated: in-page <<>> links that crossed a new page boundary became xrefs, inbound xrefs from other pages were repointed to the new pages, and helm chart README/values.yaml links were updated to the new page URLs. - Removed 31 "_Since vX.Y.Z_" markers across 12 pages. Verified locally with `make check-docs`. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../development/pages/development.adoc | 2 +- docs/modules/solr-backup/nav.adoc | 1 + .../pages/backup-repositories.adoc | 169 +++ docs/modules/solr-backup/pages/index.adoc | 167 +-- docs/modules/solr-cloud/nav.adoc | 5 + .../solr-cloud/pages/addressability.adoc | 62 + .../authentication-and-authorization.adoc | 383 ++++++ .../solr-cloud/pages/cluster-operations.adoc | 2 - .../solr-cloud/pages/custom-solr-config.adoc | 152 +++ .../solr-cloud/pages/managed-updates.adoc | 2 - docs/modules/solr-cloud/pages/scaling.adoc | 2 - .../solr-cloud/pages/solr-cloud-crd.adoc | 1196 +---------------- docs/modules/solr-cloud/pages/tls.adoc | 530 ++++++++ docs/modules/solr-cloud/pages/zookeeper.adoc | 121 ++ .../solr-prometheus-exporter/pages/index.adoc | 9 +- .../upgrade-notes/pages/upgrade-notes.adoc | 2 +- helm/solr/README.md | 6 +- helm/solr/values.yaml | 6 +- 18 files changed, 1445 insertions(+), 1372 deletions(-) create mode 100644 docs/modules/solr-backup/pages/backup-repositories.adoc create mode 100644 docs/modules/solr-cloud/pages/addressability.adoc create mode 100644 docs/modules/solr-cloud/pages/authentication-and-authorization.adoc create mode 100644 docs/modules/solr-cloud/pages/custom-solr-config.adoc create mode 100644 docs/modules/solr-cloud/pages/tls.adoc create mode 100644 docs/modules/solr-cloud/pages/zookeeper.adoc diff --git a/docs/modules/development/pages/development.adoc b/docs/modules/development/pages/development.adoc index 8f8cd7c7..64dbe550 100644 --- a/docs/modules/development/pages/development.adoc +++ b/docs/modules/development/pages/development.adoc @@ -41,7 +41,7 @@ Please follow the instructions from the xref:getting-started:local-tutorial.adoc === Install the necessary dependencies Install the https://github.com/pravega/zookeeper-operator[Zookeeper Operator], which this operator depends on by default. -It is optional, however, as described in the xref:solr-cloud:solr-cloud-crd.adoc#zookeeper-reference[Zookeeper Reference] section in the CRD docs. +It is optional, however, as described in the xref:solr-cloud:zookeeper.adoc[Zookeeper Reference] section in the CRD docs. [source,bash] ---- diff --git a/docs/modules/solr-backup/nav.adoc b/docs/modules/solr-backup/nav.adoc index 84634517..29674ca5 100644 --- a/docs/modules/solr-backup/nav.adoc +++ b/docs/modules/solr-backup/nav.adoc @@ -17,3 +17,4 @@ .Solr Backups * xref:index.adoc[] +** xref:backup-repositories.adoc[] diff --git a/docs/modules/solr-backup/pages/backup-repositories.adoc b/docs/modules/solr-backup/pages/backup-repositories.adoc new file mode 100644 index 00000000..d5c51b06 --- /dev/null +++ b/docs/modules/solr-backup/pages/backup-repositories.adoc @@ -0,0 +1,169 @@ += Supported Repository Types +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +Note all repositories are defined in the `SolrCloud` specification. +In order to use a repository in the `SolrBackup` CRD, it must be defined in the `SolrCloud` spec. +All yaml examples below are `SolrCloud` resources, not `SolrBackup` resources. + +The Solr-operator currently supports three different backup repository types: Google Cloud Storage ("GCS"), AWS S3 ("S3"), and Volume ("local"). +The cloud backup solutions (GCS and S3) are strongly suggested as they are cloud-native backup solutions, however they require newer Solr versions. + +Multiple repositories can be defined under the `SolrCloud.spec.backupRepositories` field. +Specify a unique name and single repo type that you want to connect to. +Repository-type specific options are found under the object named with the repository-type. +Examples can be found below under each repository-type section below. +Feel free to mix and match multiple backup repository types to fit your use case (or multiple repositories of the same type): + +[source,yaml] +---- +spec: + backupRepositories: + - name: "local-collection-backups-1" + volume: + ... + - name: "gcs-collection-backups-1" + gcs: + ... + - name: "s3-collection-backups-1" + s3: + ... + - name: "s3-collection-backups-2" + s3: + ... +---- + +== GCS Backup Repositories + +GCS Repositories store backup data remotely in Google Cloud Storage. +This repository type is only supported in deployments that use a Solr version >= `8.9.0`. + +Each repository must specify the GCS bucket to store data in (the `bucket` property), and (usually) the name of a Kubernetes secret containing credentials for accessing GCS (the `gcsCredentialSecret` property). +This secret must have a key `service-account-key.json` whose value is a JSON service account key as described https://cloud.google.com/iam/docs/creating-managing-service-account-keys[here] +If you already have your service account key, this secret can be created using a command like the one below. + +[source,bash] +---- +kubectl create secret generic --from-file=service-account-key.json= +---- + +In some rare cases (e.g. when deploying in GKE and relying on its https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity[Workload Identity] feature) explicit credentials are not required to talk to GCS. In these cases, the `gcsCredentialSecret` property may be omitted. + +An example of a SolrCloud spec with only one backup repository, with type GCS: + +[source,yaml] +---- +spec: + backupRepositories: + - name: "gcs-backups-1" + gcs: + bucket: "backup-bucket" # Required + gcsCredentialSecret: + name: "secretName" + key: "service-account-key.json" + baseLocation: "/store/here" # Optional +---- + + +== S3 Backup Repositories + +S3 Repositories store backup data remotely in AWS S3 (or a supported S3 compatible interface). +This repository type is only supported in deployments that use a Solr version >= `8.10.0`. + +Each repository must specify an S3 bucket and region to store data in (the `bucket` and `region` properties). +Users will want to setup credentials so that the SolrCloud can connect to the S3 bucket and region, more information can be found in the <>. + +[source,yaml] +---- +spec: + backupRepositories: + - name: "s3-backups-1" + s3: + region: "us-west-2" # Required + bucket: "backup-bucket" # Required + credentials: {} # Optional + proxyUrl: "https://proxy-url-for-s3:3242" # Optional + endpoint: "https://custom-s3-endpoint:3242" # Optional +---- + +Users can also optionally set a `proxyUrl` or `endpoint` for the S3Repository. +More information on these settings can be found in the https://solr.apache.org/guide/8_10/making-and-restoring-backups.html#s3backuprepository[Ref Guide]. + +=== S3 Credentials + +The Solr `S3Repository` module uses the https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/credentials.html#credentials-chain[default credential chain for AWS]. +All of the options below are designed to be utilized by this credential chain. + +There are a few options for giving a SolrCloud the credentials for connecting to S3. +The two most straightforward ways can be used via the `spec.backupRepositories.s3.credentials` property. + +[source,yaml] +---- +spec: + backupRepositories: + - name: "s3-backups-1" + s3: + region: "us-west-2" + bucket: "backup-bucket" + credentials: + accessKeyIdSecret: # Optional + name: aws-secrets + key: access-key-id + secretAccessKeySecret: # Optional + name: aws-secrets + key: secret-access-key + sessionTokenSecret: # Optional + name: aws-secrets + key: session-token + credentialsFileSecret: # Optional + name: aws-credentials + key: credentials +---- + +All options in the `credentials` property are optional, as users can pick and choose which ones to use. +If you have all of your credentials setup in an https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html#file-format-creds[AWS Credentials File], +then `credentialsFileSecret` will be the only property you need to set. +However, if you don't have a credentials file, you will likely need to set at least the `accessKeyIdSecret` and `secretAccessKeySecret` properties. +All of these options require the referenced Kuberentes secrets to already exist before creating the SolrCloud resource. +_(If desired, all options can be combined. e.g. Use `accessKeyIdSecret` and `credentialsFileSecret` together. The ordering of the default credentials chain will determine which options are used.)_ + +The options in the credentials file above merely set environment variables on the pod, or in the case of `credentialsFileSecret` use an environment variable and a volume mount. +Users can decide to not use the `credentials` section of the s3 repository config, and instead set these environment variables themselves via `spec.customSolrKubeOptions.podOptions.env`. + +Lastly, if running in EKS, it is possible to add https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/[IAM information to Kubernetes serviceAccounts]. +If this is done correctly, you will only need to specify the serviceAccount for the SolrCloud pods via `spec.customSolrKubeOptions.podOptions.serviceAccount`. + +NOTE: Because the Solr S3 Repository is using system-wide settings for AWS credentials, you cannot specify different credentials for different S3 repositories. This may be addressed in future Solr versions, but for now use the same credentials for all s3 repos. + +== Volume Backup Repositories + +Volume repositories store backup data "locally" on a Kubernetes volume mounted to each Solr pod. +An example of a SolrCloud spec with only one backup repository, with type Volume: + +[source,yaml] +---- +spec: + backupRepositories: + - name: "local-collection-backups-1" + volume: + source: # Required + persistentVolumeClaim: + claimName: "collection-backup-pvc" + directory: "store/here" # Optional +---- + +IMPORTANT: All persistent volumes used with Volume Repositories must have `accessMode: ReadWriteMany` set, otherwise the backups will not succeed. diff --git a/docs/modules/solr-backup/pages/index.adoc b/docs/modules/solr-backup/pages/index.adoc index eba39d72..e0c431c4 100644 --- a/docs/modules/solr-backup/pages/index.adoc +++ b/docs/modules/solr-backup/pages/index.adoc @@ -29,10 +29,10 @@ This page outlines how to create and delete a Kubernetes SolrBackup. * <> * <> * <> -* <> -** <> -** <> -** <> +* xref:backup-repositories.adoc[Repository Types] +** xref:backup-repositories.adoc#gcs-backup-repositories[GCS] +** xref:backup-repositories.adoc#s3-backup-repositories[S3] +** xref:backup-repositories.adoc#volume-backup-repositories[Volume] == Creating an example SolrBackup @@ -110,7 +110,6 @@ test example 123m true false 161m ---- == Recurring Backups -_Since v0.5.0_ The Solr Operator enables taking recurring updates, at a set interval. Note that this feature requires a SolrCloud running Solr >= `8.9.0`, because it relies on `Incremental` backups. @@ -220,161 +219,3 @@ Volume backup data, as in our example, can always be deleted using standard shel kubectl exec example-solrcloud-0 -- rm -r /var/solr/data/backup-restore/local-collection-backups-1/backups/local-backup-books kubectl exec example-solrcloud-0 -- rm -r /var/solr/data/backup-restore/local-collection-backups-1/backups/local-backup-techproducts ---- - -== Supported Repository Types -_Since v0.5.0_ - -Note all repositories are defined in the `SolrCloud` specification. -In order to use a repository in the `SolrBackup` CRD, it must be defined in the `SolrCloud` spec. -All yaml examples below are `SolrCloud` resources, not `SolrBackup` resources. - -The Solr-operator currently supports three different backup repository types: Google Cloud Storage ("GCS"), AWS S3 ("S3"), and Volume ("local"). -The cloud backup solutions (GCS and S3) are strongly suggested as they are cloud-native backup solutions, however they require newer Solr versions. - -Multiple repositories can be defined under the `SolrCloud.spec.backupRepositories` field. -Specify a unique name and single repo type that you want to connect to. -Repository-type specific options are found under the object named with the repository-type. -Examples can be found below under each repository-type section below. -Feel free to mix and match multiple backup repository types to fit your use case (or multiple repositories of the same type): - -[source,yaml] ----- -spec: - backupRepositories: - - name: "local-collection-backups-1" - volume: - ... - - name: "gcs-collection-backups-1" - gcs: - ... - - name: "s3-collection-backups-1" - s3: - ... - - name: "s3-collection-backups-2" - s3: - ... ----- - -=== GCS Backup Repositories -_Since v0.5.0_ - -GCS Repositories store backup data remotely in Google Cloud Storage. -This repository type is only supported in deployments that use a Solr version >= `8.9.0`. - -Each repository must specify the GCS bucket to store data in (the `bucket` property), and (usually) the name of a Kubernetes secret containing credentials for accessing GCS (the `gcsCredentialSecret` property). -This secret must have a key `service-account-key.json` whose value is a JSON service account key as described https://cloud.google.com/iam/docs/creating-managing-service-account-keys[here] -If you already have your service account key, this secret can be created using a command like the one below. - -[source,bash] ----- -kubectl create secret generic --from-file=service-account-key.json= ----- - -In some rare cases (e.g. when deploying in GKE and relying on its https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity[Workload Identity] feature) explicit credentials are not required to talk to GCS. In these cases, the `gcsCredentialSecret` property may be omitted. - -An example of a SolrCloud spec with only one backup repository, with type GCS: - -[source,yaml] ----- -spec: - backupRepositories: - - name: "gcs-backups-1" - gcs: - bucket: "backup-bucket" # Required - gcsCredentialSecret: - name: "secretName" - key: "service-account-key.json" - baseLocation: "/store/here" # Optional ----- - - -=== S3 Backup Repositories -_Since v0.5.0_ - -S3 Repositories store backup data remotely in AWS S3 (or a supported S3 compatible interface). -This repository type is only supported in deployments that use a Solr version >= `8.10.0`. - -Each repository must specify an S3 bucket and region to store data in (the `bucket` and `region` properties). -Users will want to setup credentials so that the SolrCloud can connect to the S3 bucket and region, more information can be found in the <>. - -[source,yaml] ----- -spec: - backupRepositories: - - name: "s3-backups-1" - s3: - region: "us-west-2" # Required - bucket: "backup-bucket" # Required - credentials: {} # Optional - proxyUrl: "https://proxy-url-for-s3:3242" # Optional - endpoint: "https://custom-s3-endpoint:3242" # Optional ----- - -Users can also optionally set a `proxyUrl` or `endpoint` for the S3Repository. -More information on these settings can be found in the https://solr.apache.org/guide/8_10/making-and-restoring-backups.html#s3backuprepository[Ref Guide]. - -==== S3 Credentials - -The Solr `S3Repository` module uses the https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/credentials.html#credentials-chain[default credential chain for AWS]. -All of the options below are designed to be utilized by this credential chain. - -There are a few options for giving a SolrCloud the credentials for connecting to S3. -The two most straightforward ways can be used via the `spec.backupRepositories.s3.credentials` property. - -[source,yaml] ----- -spec: - backupRepositories: - - name: "s3-backups-1" - s3: - region: "us-west-2" - bucket: "backup-bucket" - credentials: - accessKeyIdSecret: # Optional - name: aws-secrets - key: access-key-id - secretAccessKeySecret: # Optional - name: aws-secrets - key: secret-access-key - sessionTokenSecret: # Optional - name: aws-secrets - key: session-token - credentialsFileSecret: # Optional - name: aws-credentials - key: credentials ----- - -All options in the `credentials` property are optional, as users can pick and choose which ones to use. -If you have all of your credentials setup in an https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html#file-format-creds[AWS Credentials File], -then `credentialsFileSecret` will be the only property you need to set. -However, if you don't have a credentials file, you will likely need to set at least the `accessKeyIdSecret` and `secretAccessKeySecret` properties. -All of these options require the referenced Kuberentes secrets to already exist before creating the SolrCloud resource. -_(If desired, all options can be combined. e.g. Use `accessKeyIdSecret` and `credentialsFileSecret` together. The ordering of the default credentials chain will determine which options are used.)_ - -The options in the credentials file above merely set environment variables on the pod, or in the case of `credentialsFileSecret` use an environment variable and a volume mount. -Users can decide to not use the `credentials` section of the s3 repository config, and instead set these environment variables themselves via `spec.customSolrKubeOptions.podOptions.env`. - -Lastly, if running in EKS, it is possible to add https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/[IAM information to Kubernetes serviceAccounts]. -If this is done correctly, you will only need to specify the serviceAccount for the SolrCloud pods via `spec.customSolrKubeOptions.podOptions.serviceAccount`. - -NOTE: Because the Solr S3 Repository is using system-wide settings for AWS credentials, you cannot specify different credentials for different S3 repositories. This may be addressed in future Solr versions, but for now use the same credentials for all s3 repos. - -=== Volume Backup Repositories -_Since v0.5.0_ - -Volume repositories store backup data "locally" on a Kubernetes volume mounted to each Solr pod. -An example of a SolrCloud spec with only one backup repository, with type Volume: - -[source,yaml] ----- -spec: - backupRepositories: - - name: "local-collection-backups-1" - volume: - source: # Required - persistentVolumeClaim: - claimName: "collection-backup-pvc" - directory: "store/here" # Optional ----- - -IMPORTANT: All persistent volumes used with Volume Repositories must have `accessMode: ReadWriteMany` set, otherwise the backups will not succeed. diff --git a/docs/modules/solr-cloud/nav.adoc b/docs/modules/solr-cloud/nav.adoc index 02f324bd..44ca7bf5 100644 --- a/docs/modules/solr-cloud/nav.adoc +++ b/docs/modules/solr-cloud/nav.adoc @@ -18,6 +18,11 @@ .Solr Clouds * xref:index.adoc[Overview] * xref:solr-cloud-crd.adoc[] +** xref:addressability.adoc[] +** xref:zookeeper.adoc[] +** xref:custom-solr-config.adoc[Custom Solr Configuration] +** xref:tls.adoc[] +** xref:authentication-and-authorization.adoc[] * xref:cluster-operations.adoc[] * xref:managed-updates.adoc[] * xref:scaling.adoc[] diff --git a/docs/modules/solr-cloud/pages/addressability.adoc b/docs/modules/solr-cloud/pages/addressability.adoc new file mode 100644 index 00000000..158a63de --- /dev/null +++ b/docs/modules/solr-cloud/pages/addressability.adoc @@ -0,0 +1,62 @@ += Addressability +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +The SolrCloud CRD provides users the ability to define how it is addressed, through the following options: + +Under `SolrCloud.Spec.solrAddressability`: + +* **`podPort`** - The port on which the pod is listening. This is also that the port that the Solr Jetty service will listen on. (Defaults to `8983`) +* **`commonServicePort`** - The port on which the common service is exposed. (Defaults to `80`) +* **`kubeDomain`** - Specifies an override of the default Kubernetes cluster domain name, `cluster.local`. This option should only be used if the Kubernetes cluster has been setup with a custom domain name. +* **`external`** - Expose the cloud externally, outside of the kubernetes cluster in which it is running. +** **`method`** - (Required) The method by which your cloud will be exposed externally. +Currently available options are https://kubernetes.io/docs/concepts/services-networking/ingress/[`Ingress`] and https://github.com/kubernetes-sigs/external-dns[`ExternalDNS`]. +The goal is to support more methods in the future, such as LoadBalanced Services. +** **`domainName`** - (Required) The primary domain name to open your cloud endpoints on. If `useExternalAddress` is set to `true`, then this is the domain that will be used in Solr Node names. +** **`additionalDomainNames`** - You can choose to listen on additional domains for each endpoint, however Solr will not register itself under these names. +** **`useExternalAddress`** - Use the external address to advertise the SolrNode. If a domain name is required for the chosen external `method`, then the one provided in `domainName` will be used. +This can not be set to `true` when **`hideNodes`** is set to `true` or **`ingressTLSTermination`** is used. +** **`hideCommon`** - Do not externally expose the common service (one endpoint for all solr nodes). +** **`hideNodes`** - Do not externally expose each node. (This cannot be set to `true` if the cloud is running across multiple kubernetes clusters) +** **`nodePortOverride`** - Make the Node Service(s) override the podPort. This is only available for the `Ingress` external method. If `hideNodes` is set to `true`, then this option is ignored. If provided, this port will be used to advertise the Solr Node. +If `method: Ingress` and `hideNodes: false`, then this value defaults to `80` since that is the default port that ingress controllers listen on. +** **`ingressTLSTermination`** - Terminate TLS for the SolrCloud at the `Ingress`, if using the `Ingress` **method**. This will leave the inter-node communication within the cluster to use HTTP. +This option may not be used with **`useExternalAddress`**. Only one sub-option can be provided. +*** **`useDefaultTLSSecret`** - Use the default TLS Secret set by your Ingress controller, if your Ingress controller supports this feature. Cannot be used when `tlsSecret` is used. +For example, using nginx: https://kubernetes.github.io/ingress-nginx/user-guide/tls/#default-ssl-certificate +*** **`tlsSecret`** - Name a of Kubernetes TLS Secret to terminate TLS when using the `Ingress` method. Cannot be used when `useDefaultTlsSecret` is used. + +NOTE: Unless both `external.method=Ingress` and `external.hideNodes=false`, a headless service will be used to make each Solr Node in the statefulSet addressable. +If both of those criteria are met, then an individual ClusterIP Service will be created for each Solr Node/Pod. + +If you are using an `Ingress` for external addressability, you can customize the created `Ingress` through `SolrCloud.spec.customSolrKubeOptions.ingressOptions`. +Under this property, you can set custom `annotations`, `labels` and an `ingressClassName`. + +NOTE: If you have no need for an `Ingress` or a specific hostname to address your SolrCloud cluster you can create a simple loadbalancer that can be addressed from outside the kubernetes cluster. To achieve this you can add annotations to `SolrCloud.spec.customSolrKubeOptions.commonServiceOptions.annotations`. Exposing the headlessService is an option as well through `SolrCloud.spec.customSolrKubeOptions.headlessServiceOptions.annotations`, mind that using the headless service requires a load balancing implementation in the client calling the SolrCloud api. +Snippet below shows you can create an NLB on AWS: + +[source,yaml] +---- +spec: + customSolrKubeOptions: + commonServiceOptions: + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: external + service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip + service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing +---- diff --git a/docs/modules/solr-cloud/pages/authentication-and-authorization.adoc b/docs/modules/solr-cloud/pages/authentication-and-authorization.adoc new file mode 100644 index 00000000..6c9c1a06 --- /dev/null +++ b/docs/modules/solr-cloud/pages/authentication-and-authorization.adoc @@ -0,0 +1,383 @@ += Authentication and Authorization +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +All well-configured Solr clusters should enforce users to authenticate, even for read-only operations. Even if you want +to allow anonymous query requests from unknown users, you should make this explicit using Solr's rule-based authorization +plugin. In other words, always enforce security and then relax constraints as needed for specific endpoints based on your +use case. The Solr operator can bootstrap a default security configuration for your SolrCloud during initialization. As such, +there is no reason to deploy an unsecured SolrCloud cluster when using the Solr operator. In most cases, you'll want to combine +basic authentication with TLS to ensure credentials are never passed in clear text. + +For background on Solr security, please refer to the https://solr.apache.org/guide[Reference Guide] for your version of Solr. + +The Solr operator only supports the `Basic` authentication scheme. In general, you have two primary options for configuring authentication with the Solr operator: + +. Let the Solr operator bootstrap the `security.json` to configure *basic authentication* for Solr. +. Supply your own `security.json` to Solr, which must define a user account that the operator can use to make API requests to secured Solr pods. + +If you choose option 2, then you need to provide the credentials the Solr operator should use to make requests to Solr via a Kubernetes secret. +With option 1, the operator creates a Basic Authentication Secret for you, which contains the username and password for the `k8s-oper` user. + +== Option 1: Bootstrap Security + +The easiest way to get started with Solr security is to have the operator bootstrap a `security.json` (stored in ZK) as part of the initial deployment process. +To activate this feature, add the following configuration to your SolrCloud CRD definition YAML: + +[source,yaml] +---- +spec: + ... + solrSecurity: + authenticationType: Basic +---- + +Once the cluster is up, you'll need the `admin` user password to login to the Solr Admin UI. +The `admin` user will have a random password generated by the operator during `security.json` bootstrapping. +Use the following command to retrieve the password from the bootstrap secret created by the operator: + +[source,bash] +---- +kubectl get secret -solrcloud-security-bootstrap -o jsonpath='{.data.admin}' | base64 --decode +---- + +_where `` is the name of your SolrCloud_ + +Once `security.json` is bootstrapped, the operator will not update it! You're expected to use the `admin` user to access the Security API to make further changes. +In addition to the `admin` user, the operator defines a `solr` user, which has basic read access to Solr resources. You can retrieve the `solr` user password using: + +[source,bash] +---- +kubectl get secret -solrcloud-security-bootstrap -o jsonpath='{.data.solr}' | base64 --decode +---- + +You can safely delete the bootstrap secret, provided you've captured the `admin` password, after your SolrCloud deploys with the bootstrapped `security.json`. +However, this will trigger a rolling restart across all pods as the `setup-zk` initContainer definition changes. + +=== k8s-oper user + +The operator makes requests to secured Solr endpoints as the `k8s-oper` user; credentials for the `k8s-oper` user are stored in a separate secret of type `kubernetes.io/basic-auth` +with name `-solrcloud-basic-auth`. The `k8s-oper` user is configured with read-only access to a minimal set of endpoints, see details in the **Authorization** sub-section below. +Remember, if you change the `k8s-oper` password using the Solr security API, then you **must** update the secret with the new password or the operator will be locked out. +Also, changing the password for the `k8s-oper` user in the K8s secret after bootstrapping will not update Solr! You're responsible for changing the password in both places. + +=== Liveness and Readiness Probes + +We recommend configuring Solr to allow un-authenticated access over HTTP to the probe endpoint(s) and the bootstrapped `security.json` does this for you automatically (see next sub-section). +However, if you want to secure the probe endpoints, then you need to set `probesRequireAuth: true` as shown below: + +[source,yaml] +---- +spec: + ... + solrSecurity: + authenticationType: Basic + probesRequireAuth: true +---- + +When `probesRequireAuth` is set to `true`, the liveness and readiness probes execute a command instead of using HTTP. +The operator configures a command instead of setting the `Authorization` header for the HTTP probes, as that would require a restart of all pods if the password changes. +With a command, we can load the username and password from a secret; Kubernetes will +https://kubernetes.io/docs/concepts/configuration/secret/#mounted-secrets-are-updated-automatically[update the mounted secret files] when the secret changes automatically. + +By default, the operator will use Solr's `/admin/info/system` endpoint for startup and liveness probes, and the `/admin/info/health` endpoint for readiness probes. +This default can be customized by changing the HTTP path for any probes (under `spec.customSolrKubeOptions.podOptions`), however this also requires users to set `probesRequireAuth=false` as the operator does not reconfigure custom HTTP probes to use the command needed to support `probesRequireAuth=true`. + +Custom readiness and liveness probes can be specified using configuration like the following: + +[source,yaml] +---- +spec: + ... + customSolrKubeOptions: + podOptions: + livenessProbe: + httpGet: + scheme: HTTP + path: /solr/admin/customliveness + port: 8983 + readinessProbe: + httpGet: + scheme: HTTP + path: /solr/admin/customreadiness + port: 8983 +---- + +Consequently, the bootstrapped `security.json` will include additional rules to allow access to the endpoints used by the startup, liveness, and readiness probes: + +[source,json] +---- + { + "name": "k8s-probe-1", + "role": null, + "collection": null, + "path": "/admin/customliveness" + }, + { + "name": "k8s-probe-2", + "role": null, + "collection": null, + "path": "/admin/customreadiness" + } +---- + +Note, if you change the probes after creating your solrcloud, then the new probe paths will not be added to the security.json. +The security file is bootstrapped just once, so if your probes need to change you must add it to the allowed paths via the Solr Security API using the admin credentials. + +=== Authorization + +The default `security.json` created by the operator during initialization is shown below; the passwords for each user are randomized for every SolrCloud you create. +In addition to configuring the `solr.BasicAuthPlugin`, the operator initializes a set of authorization rules for the default user accounts: `admin`, `solr`, and `k8s-oper`. +Take a moment to review these authorization rules so that you're aware of the roles and access granted to each user in your cluster. + +[source,json] +---- +{ + "authentication": { + "blockUnknown": false, + "class": "solr.BasicAuthPlugin", + "credentials": { + "admin": "...", + "k8s-oper": "...", + "solr": "..." + }, + "realm": "Solr Basic Auth", + "forwardCredentials": false + }, + "authorization": { + "class": "solr.RuleBasedAuthorizationPlugin", + "user-role": { + "admin": [ "admin", "k8s" ], + "k8s-oper": [ "k8s" ], + "solr": [ "users", "k8s" ] + }, + "permissions": [ + { + "name": "k8s-probe-0", + "role": null, + "collection": null, + "path": "/admin/info/system" + }, + { + "name": "k8s-probe-1", + "role": null, + "collection": null, + "path": "/admin/info/health" + }, + { + "name": "k8s-status", + "role": "k8s", + "collection": null, + "path": "/admin/collections" + }, + { + "name": "k8s-metrics", + "role": "k8s", + "collection": null, + "path": "/admin/metrics" + }, + { + "name": "k8s-zk", + "role":"k8s", + "collection": null, + "path":"/admin/zookeeper/status" + }, + { + "name": "k8s-ping", + "role": "k8s", + "collection": "*", + "path": "/admin/ping" + }, + { + "name": "k8s-replica-balancing", + "role": "k8s", + "collection": null, + "path": "/____v2/cluster/replicas/balance" + }, + { + "name": "collection-admin-edit", + "role": "k8s" + }, + { + "name": "read", + "role": [ "admin", "users" ] + }, + { + "name": "update", + "role": [ "admin" ] + }, + { + "name": "security-read", + "role": [ "admin" ] + }, + { + "name": "security-edit", + "role": [ "admin" ] + }, + { + "name": "all", + "role": [ "admin" ] + } + ] + } +} +---- + +A few aspects of the default `security.json` configuration warrant a closer look. First, the `probesRequireAuth` setting +(defaults to `false`) governs the value for `blockUnknown` (under `authentication`) and whether the probe endpoint(s) require authentication: + +[source,json] +---- + { + "name": "k8s-probe-0", + "role": null, + "collection": null, + "path": "/admin/info/system" + } +---- + +In this case, the `"role":null` indicates this endpoint allows anonymous access by unknown users. +The `"collection":null` value indicates the path is not associated with any collection, i.e. it is a top-level system path. + +The operator sends GET requests to the `/admin/collections` endpoint to get cluster status to determine the rolling restart order: + +[source,json] +---- + { + "name": "k8s-status", + "role": "k8s", + "collection": null, + "path": "/admin/collections" + }, +---- + +In this case, the `"role":"k8s"` indicates the requesting user must be in the `k8s` role; notice that all default users have the `k8s` role. + +The Prometheus exporter sends GET requests to the `/admin/metrics` endpoint to collect metrics from each pod. +The exporter also hits the `/admin/ping` endpoint for every collection, which requires the following authorization rules: + +[source,json] +---- + { + "name": "k8s-metrics", + "role": "k8s", + "collection": null, + "path": "/admin/metrics" + }, + { + "name": "k8s-ping", + "role": "k8s", + "collection": "*", + "path": "/admin/ping" + }, + { + "name": "k8s-zk", + "role":"k8s", + "collection": null, + "path":"/admin/zookeeper/status" + }, +---- + +The `"collection":"*"` setting indicates this path applies to all collections, which maps to endpoint `/collections//admin/ping` at runtime. + +The initial authorization config grants the `read` permission to the `users` role, which allows `users` to send query requests but cannot add / update / delete documents. +For instance, the `solr` user is mapped to the `users` role, so the `solr` user can send query requests only. +In general, please verify the initial authorization rules for each role before sharing user credentials. + +== Option 2: User-provided `security.json` and credentials secret + +If users want full control over their cluster's security config, then they can provide the Solr `security.json` via a Secret and the credentials the operator should use +to make requests to Solr in a Secret. + +=== Custom `security.json` Secret + +For full control over the Solr security configuration, supply a `security.json` in a Secret. The following example illustrates how to point the operator to a Secret containing a custom `security.json`: + +[source,yaml] +---- +spec: + ... + solrSecurity: + authenticationType: Basic + bootstrapSecurityJson: + name: my-custom-security-json + key: security.json +---- + +For `Basic` authentication, if you don't supply a `security.json` Secret, then the operator assumes you are bootstrapping the security configuration via some other means. + +Refer to the example `security.json` shown in the Authorization section above to help you get started crafting your own custom configuration. + +=== Basic Authentication + +For `Basic` authentication, the supplied secret must be of type https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret[Basic Authentication Secret] and define both a `username` and `password`. + +[source,yaml] +---- +spec: + ... + solrSecurity: + authenticationType: Basic + basicAuthSecret: user-provided-secret +---- + +Here is an example of how to define a basic auth secret using YAML: + +[source,yaml] +---- +apiVersion: v1 +kind: Secret +metadata: + name: my-basic-auth-secret +type: kubernetes.io/basic-auth +stringData: + username: k8s-oper + password: Test1234 +---- + +With this config, the operator will make API requests to secured Solr pods as the `k8s-oper` user. +NOTE: be sure to use a stronger password for real deployments + +Users need to ensure their `security.json` contains the user supplied in the `basicAuthSecret` has read access to the following endpoints: + +---- +/admin/info/system +/admin/info/health +/admin/collections +/admin/metrics +/admin/ping (for collection="*") +/admin/zookeeper/status +/____v2/cluster/replicas/balance +---- + +And the following named permissions: + +---- +collection-admin-edit +---- + +TIP: see the authorization rules defined by the default `security.json` as a guide for configuring access for the operator user + +==== Changing the Password + +If you change the password for the user configured in your `basicAuthSecret` using the Solr security API, then you **must** update the secret with the new password or the operator will be locked out. +Also, changing the password for this user in the K8s secret will not update Solr! You're responsible for changing the password in both places. + +==== Prometheus Exporter with Basic Auth + +If you enable basic auth for your SolrCloud cluster, then you need to point the Prometheus exporter at the basic auth secret; +refer to xref:solr-prometheus-exporter:index.adoc#prometheus-exporter-with-basic-auth[Prometheus Exporter with Basic Auth] for more details. diff --git a/docs/modules/solr-cloud/pages/cluster-operations.adoc b/docs/modules/solr-cloud/pages/cluster-operations.adoc index a7392a59..633364ff 100644 --- a/docs/modules/solr-cloud/pages/cluster-operations.adoc +++ b/docs/modules/solr-cloud/pages/cluster-operations.adoc @@ -16,8 +16,6 @@ // specific language governing permissions and limitations // under the License. -_Since v0.8.0_ - Solr Clouds are complex distributed systems, and thus any operations that deal with data availability should be handled with care. == Cluster Operation Locks diff --git a/docs/modules/solr-cloud/pages/custom-solr-config.adoc b/docs/modules/solr-cloud/pages/custom-solr-config.adoc new file mode 100644 index 00000000..ca733874 --- /dev/null +++ b/docs/modules/solr-cloud/pages/custom-solr-config.adoc @@ -0,0 +1,152 @@ += Override Built-in Solr Configuration Files +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +The Solr operator deploys well-configured SolrCloud instances with minimal input required from human operators. +As such, the operator installs various configuration files automatically, including `solr.xml` for node-level settings and `log4j2.xml` for logging. +However, there may come a time when you need to override the built-in configuration files with custom settings. + +In general, users can provide custom config files by providing a ConfigMap in the same namespace as the SolrCloud instance; +all custom config files should be stored in the same user-provided ConfigMap under different keys. +Point your SolrCloud definition to a user-provided ConfigMap using the following structure: + +[source,yaml] +---- +spec: + ... + customSolrKubeOptions: + configMapOptions: + providedConfigMap: +---- + +== Custom solr.xml + +Solr pods load node-level configuration settings from `/var/solr/data/solr.xml`. +This important configuration file gets created by the `cp-solr-xml` initContainer which bootstraps the `solr.home` directory on each pod before starting the main container. +The default `solr.xml` is mounted into the `cp-solr-xml` initContainer from a ConfigMap named `-solrcloud-configmap` (where `` is the name of your SolrCloud instance) created by the Solr operator. + +NOTE: The data in the default ConfigMap is not editable! Any changes to the `solr.xml` in the default ConfigMap created by the operator will be overwritten during the next reconcile cycle. + +Many of the specific values in `solr.xml` can be set using Java system properties; for instance, the following setting controls the read timeout for the HTTP client used by Solr's `HttpShardHandlerFactory`: + +---- +${socketTimeout:600000} +---- + +The `${socketTimeout:600000}` syntax means pull the value from a Java system property named `socketTimeout` with default `600000` if not set. + +You can set Java system properties using the `solrOpts` string in your SolrCloud definition, such as: + +[source,yaml] +---- +spec: + solrOpts: -DsocketTimeout=300000 +---- + +This same approach works for a number of settings in `solrconfig.xml` as well. + +However, if you need to customize `solr.xml` beyond what can be accomplished with Java system properties, +then you need to supply your own `solr.xml` in a ConfigMap in the same namespace where you deploy your SolrCloud instance. +Provide your custom XML in the ConfigMap using `solr.xml` as the key as shown in the example below: + +[source,yaml] +---- +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: custom-solr-xml +data: + solr.xml: | + + + ... CUSTOM CONFIG HERE ... + +---- + +IMPORTANT: Your custom `solr.xml` must include `${solr.port.advertise:0}` as the operator relies on this element to set the port Solr pods advertise to ZooKeeper. If this element is missing, then your Solr pods will not be created. + +You can get the default `solr.xml` from a Solr pod as a starting point for creating a custom config using `kubectl cp` as shown in the example below: + +[source,bash] +---- +SOLR_POD_ID=$(kubectl get pod -l technology=solr-cloud --no-headers -o custom-columns=":metadata.name" | head -1) +kubectl cp $SOLR_POD_ID:/var/solr/data/solr.xml ./custom-solr.xml +---- + +This copies the default config from the first Solr pod found in the namespace and names it `custom-solr.xml`. Customize the settings in `custom-solr.xml` as needed and then create a ConfigMap using YAML. + +NOTE: Using `kubectl create configmap --from-file` scrambles the XML formatting, so we recommend defining the configmap YAML as shown above to keep the XML formatted properly. + +Point your SolrCloud instance at the custom ConfigMap using: + +[source,yaml] +---- +spec: + customSolrKubeOptions: + configMapOptions: + providedConfigMap: custom-solr-xml +---- + +NOTE: If you set `providedConfigMap`, then the ConfigMap must include the `solr.xml` or `log4j2.xml` key, otherwise the SolrCloud will fail to reconcile. + +=== Changes to Custom Config Trigger Rolling Restarts + +The Solr operator stores the MD5 hash of your custom XML in the StatefulSet's pod spec annotations (`spec.template.metadata.annotations`). To see the current annotations for your Solr pods, you can do: + +[source,bash] +---- +kubectl annotate pod -l technology=solr-cloud --list=true +---- + +If the custom `solr.xml` changes in the user-provided ConfigMap, then the operator triggers a rolling restart of Solr pods to apply the updated configuration settings automatically. + +To summarize, if you need to customize `solr.xml`, provide your own version in a ConfigMap and changes made to the XML in the ConfigMap are automatically applied to your Solr pods. + +== Custom Log Configuration + +By default, the Solr Docker image configures Solr to load its log configuration from `/var/solr/log4j2.xml`. +If you need to fine-tune the log configuration, then you can provide a custom `log4j2.xml` in a ConfigMap using the same basic process as described in the previous section for customizing `solr.xml`. If supplied, the operator overrides the log config using the `LOG4J_PROPS` env var. + +As with custom `solr.xml`, the operator can track the MD5 hash of your `log4j2.xml` in the pod spec annotations to trigger a rolling restart if the log config changes. +However, Log4j2 supports hot reloading of log configuration using the `monitorInterval` attribute on the root `` element. For more information on this, see: https://logging.apache.org/log4j/2.x/manual/configuration.html#AutomaticReconfiguration[Log4j Automatic Reconfiguration]. +If your custom log config has a `monitorInterval` set, then the operator does not watch for changes to the log config and will not trigger a rolling restart if the config changes. +Kubernetes will automatically update the file on each pod's filesystem when the data in the ConfigMap changes. Once Kubernetes updates the file, Log4j will pick up the changes and apply them without restarting the Solr pod. + +If you need to customize both `solr.xml` and `log4j2.xml` then you need to supply both in the same ConfigMap using multiple keys as shown below: + +[source,yaml] +---- +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: custom-solr-xml +data: + log4j2.xml: | + + + ... YOUR CUSTOM LOG4J CONFIG HERE ... + + + + solr.xml: | + + + ... YOUR CUSTOM SOLR XML CONFIG HERE ... + +---- diff --git a/docs/modules/solr-cloud/pages/managed-updates.adoc b/docs/modules/solr-cloud/pages/managed-updates.adoc index 9695c604..ba6e3438 100644 --- a/docs/modules/solr-cloud/pages/managed-updates.adoc +++ b/docs/modules/solr-cloud/pages/managed-updates.adoc @@ -16,8 +16,6 @@ // specific language governing permissions and limitations // under the License. -_Since v0.2.7_ - Solr Clouds are complex distributed systems, and thus require a more delicate and informed approach to rolling updates. If the xref:solr-cloud:solr-cloud-crd.adoc#update-strategy[`Managed` update strategy] is specified in the Solr Cloud CRD, then the Solr Operator will take control over deleting SolrCloud pods when they need to be updated. diff --git a/docs/modules/solr-cloud/pages/scaling.adoc b/docs/modules/solr-cloud/pages/scaling.adoc index 135764b3..6dc879d1 100644 --- a/docs/modules/solr-cloud/pages/scaling.adoc +++ b/docs/modules/solr-cloud/pages/scaling.adoc @@ -16,8 +16,6 @@ // specific language governing permissions and limitations // under the License. -_Since v0.8.0_ - Solr Clouds are complex distributed systems, and thus require additional help when trying to scale up or down. Scaling/Autoscaling can mean different things in different situations, and this is true even within the `SolrCloud.spec.scaling` section. diff --git a/docs/modules/solr-cloud/pages/solr-cloud-crd.adoc b/docs/modules/solr-cloud/pages/solr-cloud-crd.adoc index dcbb1c19..a72ec09a 100644 --- a/docs/modules/solr-cloud/pages/solr-cloud-crd.adoc +++ b/docs/modules/solr-cloud/pages/solr-cloud-crd.adoc @@ -17,7 +17,14 @@ // under the License. The SolrCloud CRD allows users to spin up a Solr cloud in a very configurable way. -Those configuration options are laid out on this page. +The most common configuration options are described on this page. +The following topics are covered on their own pages: + +* xref:addressability.adoc[Addressability] +* xref:zookeeper.adoc[Zookeeper Reference] +* xref:custom-solr-config.adoc[Overriding built-in Solr configuration files] +* xref:tls.adoc[Enabling TLS between Solr pods] +* xref:authentication-and-authorization.adoc[Authentication and Authorization] == Solr Options @@ -29,7 +36,6 @@ If using Helm, refer to the https://artifacthub.io/packages/helm/apache-solr/sol This document should still be used to see how the SolrCloud options can be used. === Solr Modules and Additional Libraries -_Since v0.5.0_ Solr comes packaged with modules that can be loaded optionally, known as either Solr Modules or Solr Contrib Modules. By default they are not included in the classpath of Solr, so they have to be explicitly enabled. @@ -51,7 +57,6 @@ These options can be found in `SolrCloud.spec.dataStorage` * **`persistent`** ** **`reclaimPolicy`** - -_Since v0.2.7_ - Either `Retain`, the default, or `Delete`. This describes the lifecycle of PVCs that are deleted after the SolrCloud is deleted, or the SolrCloud is scaled down and the pods that the PVCs map to no longer exist. `Retain` is used by default, as that is the default Kubernetes policy, to leave PVCs in case pods, or StatefulSets are deleted accidentally. @@ -76,7 +81,6 @@ If both are specified then the `hostPath` volume source will take precedence. ** **`hostPath`** - A https://kubernetes.io/docs/concepts/storage/volumes/#hostpath[`hostPath` volume source] that describes the desired hostPath volume to use in each SolrCloud pod to store data. == Update Strategy -_Since v0.2.7_ The SolrCloud CRD provides users the ability to define how Pod updates should be managed, through `SolrCloud.Spec.updateStrategy`. This provides the following options: @@ -102,7 +106,6 @@ NOTE: Both `maxPodsUnavailable` and `maxShardReplicasUnavailable` are intOrStrin ** **`maxShardReplicasUnavailable`** - The `maxShardReplicasUnavailable` is calculated independently for each shard, as the percentage of the number of replicas for that shard. === Pod Disruption Budgets -_Since v0.7.0_ The Solr Operator can optionally create a https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#pod-disruption-budgets[`PodDisruptionBudget`] to ensure that Kubernetes does not take down more than an acceptable amount of SolrCloud nodes at a time. This behavior is controlled by the `.spec.availability.podDisruptionBudget.enabled` setting, which defaults to "true" but can be disabled if desired as in the snippet below: @@ -123,169 +126,13 @@ So although Kubernetes might just take down 25% of a Cloud's nodes, that might r This is ongoing work, and hopefully something the Solr Operator can protect against in the future. See https://github.com/apache/solr-operator/issues/471[this discussion] for more information. -== Addressability -_Since v0.2.6_ - -The SolrCloud CRD provides users the ability to define how it is addressed, through the following options: - -Under `SolrCloud.Spec.solrAddressability`: - -* **`podPort`** - The port on which the pod is listening. This is also that the port that the Solr Jetty service will listen on. (Defaults to `8983`) -* **`commonServicePort`** - The port on which the common service is exposed. (Defaults to `80`) -* **`kubeDomain`** - Specifies an override of the default Kubernetes cluster domain name, `cluster.local`. This option should only be used if the Kubernetes cluster has been setup with a custom domain name. -* **`external`** - Expose the cloud externally, outside of the kubernetes cluster in which it is running. -** **`method`** - (Required) The method by which your cloud will be exposed externally. -Currently available options are https://kubernetes.io/docs/concepts/services-networking/ingress/[`Ingress`] and https://github.com/kubernetes-sigs/external-dns[`ExternalDNS`]. -The goal is to support more methods in the future, such as LoadBalanced Services. -** **`domainName`** - (Required) The primary domain name to open your cloud endpoints on. If `useExternalAddress` is set to `true`, then this is the domain that will be used in Solr Node names. -** **`additionalDomainNames`** - You can choose to listen on additional domains for each endpoint, however Solr will not register itself under these names. -** **`useExternalAddress`** - Use the external address to advertise the SolrNode. If a domain name is required for the chosen external `method`, then the one provided in `domainName` will be used. -This can not be set to `true` when **`hideNodes`** is set to `true` or **`ingressTLSTermination`** is used. -** **`hideCommon`** - Do not externally expose the common service (one endpoint for all solr nodes). -** **`hideNodes`** - Do not externally expose each node. (This cannot be set to `true` if the cloud is running across multiple kubernetes clusters) -** **`nodePortOverride`** - Make the Node Service(s) override the podPort. This is only available for the `Ingress` external method. If `hideNodes` is set to `true`, then this option is ignored. If provided, this port will be used to advertise the Solr Node. -If `method: Ingress` and `hideNodes: false`, then this value defaults to `80` since that is the default port that ingress controllers listen on. -** **`ingressTLSTermination`** - Terminate TLS for the SolrCloud at the `Ingress`, if using the `Ingress` **method**. This will leave the inter-node communication within the cluster to use HTTP. -This option may not be used with **`useExternalAddress`**. Only one sub-option can be provided. -*** **`useDefaultTLSSecret`** - Use the default TLS Secret set by your Ingress controller, if your Ingress controller supports this feature. Cannot be used when `tlsSecret` is used. -For example, using nginx: https://kubernetes.github.io/ingress-nginx/user-guide/tls/#default-ssl-certificate -*** **`tlsSecret`** - Name a of Kubernetes TLS Secret to terminate TLS when using the `Ingress` method. Cannot be used when `useDefaultTlsSecret` is used. - -NOTE: Unless both `external.method=Ingress` and `external.hideNodes=false`, a headless service will be used to make each Solr Node in the statefulSet addressable. -If both of those criteria are met, then an individual ClusterIP Service will be created for each Solr Node/Pod. - -If you are using an `Ingress` for external addressability, you can customize the created `Ingress` through `SolrCloud.spec.customSolrKubeOptions.ingressOptions`. -Under this property, you can set custom `annotations`, `labels` and an `ingressClassName`. - -NOTE: If you have no need for an `Ingress` or a specific hostname to address your SolrCloud cluster you can create a simple loadbalancer that can be addressed from outside the kubernetes cluster. To achieve this you can add annotations to `SolrCloud.spec.customSolrKubeOptions.commonServiceOptions.annotations`. Exposing the headlessService is an option as well through `SolrCloud.spec.customSolrKubeOptions.headlessServiceOptions.annotations`, mind that using the headless service requires a load balancing implementation in the client calling the SolrCloud api. -Snippet below shows you can create an NLB on AWS: - -[source,yaml] ----- -spec: - customSolrKubeOptions: - commonServiceOptions: - annotations: - service.beta.kubernetes.io/aws-load-balancer-type: external - service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip - service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing ----- - == Backups Solr Backups are enabled via the Solr Operator. Please refer to the xref:solr-backup:index.adoc[SolrBackup documentation] for more information on setting up a SolrCloud with backups enabled. -== Zookeeper Reference - -All SolrCloud resources run Solr in "cloud" mode, and require access to an Apache ZooKeeper cluster for state-management. - -The Solr operator gives a few options for ZooKeeper access: - -* Connecting to an already running zookeeper ensemble via <> -* <> Zookeeper Ensemble in the same namespace via the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] - -These options are configured under `spec.zookeeperRef` - -[#chroot] -=== Chroot - -Both options below come with options to specify a `chroot`, or a ZNode path for solr to use as it's base "directory" in Zookeeper. -Before the operator creates or updates a StatefulSet with a given `chroot`, it will first ensure that the given ZNode path exists and if it doesn't the operator will create all necessary ZNodes in the path. -If no chroot is given, a default of `/` will be used, which doesn't require the existence check previously mentioned. -If a chroot is provided without a prefix of `/`, the operator will add the prefix, as it is required by Zookeeper. - -[#zk-connection-info] -=== ZK Connection Info - -This is an external/internal connection string as well as an optional chRoot to an already running Zookeeeper ensemble. -If you provide an external connection string, you do not _have_ to provide an internal one as well. - -Under `spec.zookeeperRef`: - -* **`connectionInfo`** -** **`externalConnectionString`** - The ZK connection string to the external Zookeeper cluster, e.g. `zoo1:2181` -** **`chroot`** - The chroot to use for the cluster - -External ZooKeeper clusters are often configured to use ZooKeeper features (e.g. securePort) which require corresponding configuration on the client side. -To support these use-cases, users may provide arbitrary system properties under `spec.solrZkOpts` which will be passed down to all ZooKeeper clients (Solr, zkcli.sh, etc.) managed by the operator. - -==== ACLs -_Since v0.2.7_ - -The Solr Operator allows for users to specify ZK ACL references in their Solr Cloud CRDs. -The user must specify the name of a secret that resides in the same namespace as the cloud, that contains an ACL username value and an ACL password value. -This ACL must have admin permissions for the <> given. - -The ACL information can be provided through an ADMIN acl and a READ ONLY acl. - -* Admin: `SolrCloud.spec.zookeeperRef.connectionInfo.acl` -* Read Only: `SolrCloud.spec.zookeeperRef.connectionInfo.readOnlyAcl` - -All ACL fields are **required** if an ACL is used. - -* **`secret`** - The name of the secret, in the same namespace as the SolrCloud, that contains the admin ACL username and password. -* **`usernameKey`** - The name of the key in the provided secret that stores the admin ACL username. -* **`passwordKey`** - The name of the key in the provided secret that stores the admin ACL password. - -[#provided-instance] -=== Provided Instance - -If you do not require the Solr cloud to run cross-kube cluster, and do not want to manage your own Zookeeper ensemble, -the solr-operator can manage Zookeeper ensemble(s) for you. - -Using the https://github.com/pravega/zookeeper-operator[zookeeper-operator], a new Zookeeper ensemble can be spun up for -each solrCloud that has this option specified. - -The startup parameter `zookeeper-operator` must be provided on startup of the solr-operator for this parameter to be available. - -To find all Provided zookeeper options, run `kubectl explain solrcloud.spec.zookeeperRef.provided`. -Zookeeper Conf and PodOptions provided in the linked Zookeeper Operator version should be supported in the SolrCloud CRD. -However, this is a manual task, so not all options might be available. -If there is an option available in the ZookeeperCluster CRD that is not exposed via the SolrCloud CRD, please create a Github Issue. - -==== Zookeeper Storage Options -_Since v0.4.0_ - -The Zookeeper Operator allows for both ephemeral and persistent storage, and the Solr Operator supports both as of `v0.4.0`. - -[source,yaml] ----- -spec: - zookeeperRef: - provided: - ephemeral: - emptydirvolumesource: {} - persistence: - reclaimPolicy: "Retain" # Either Retain or Delete - spec: {} # PVC Spec for the Zookeeper volumes ----- - -By default, if you do not provide either `ephemeral` or `persistence`, the Solr Operator will default to the type of storage you are using for your Solr pods. - -However, if you provide either object above, even if the object is empty, that storage type will be used for the created Zookeeper pods. -If both `ephemeral` and `persistence` is provided, then `persistence` is preferred. - -==== ACLs for Provided Ensembles -_Since v0.3.0_ - -If you want Solr to set ZK ACLs for znodes it creates in the `provided` ensemble, you can supply ACL credentials for an ADMIN and optionally a READ ONLY user using the following config settings: - -* Admin: `SolrCloud.spec.zookeeperRef.provided.acl` -* Read Only: `SolrCloud.spec.zookeeperRef.provided.readOnlyAcl` - -All ACL fields are **required** if an ACL is used. - -* **`secret`** - The name of the secret, in the same namespace as the SolrCloud, that contains the ACL username and password. -* **`usernameKey`** - The name of the key in the provided secret that stores the admin ACL username. -* **`passwordKey`** - The name of the key in the provided secret that stores the admin ACL password. - -WARNING: There is a known issue with the Zookeeper operator where it deploys pods with `skipACL=yes`, see: https://github.com/pravega/zookeeper-operator/issues/316. -This means that even if Solr sets the ACLs on znodes, they will not be enforced by Zookeeper. If your organization requires Solr to use ZK ACLs, then you'll need to -deploy Zookeeper to Kubernetes using another approach, such as using a Helm chart. == Scaling -_Since v0.8.0_ [source,yaml] ---- @@ -297,1038 +144,11 @@ spec: Please refer to the xref:solr-cloud:scaling.adoc[Scaling page] for more information. -== Override Built-in Solr Configuration Files -_Since v0.2.7_ - -The Solr operator deploys well-configured SolrCloud instances with minimal input required from human operators. -As such, the operator installs various configuration files automatically, including `solr.xml` for node-level settings and `log4j2.xml` for logging. -However, there may come a time when you need to override the built-in configuration files with custom settings. - -In general, users can provide custom config files by providing a ConfigMap in the same namespace as the SolrCloud instance; -all custom config files should be stored in the same user-provided ConfigMap under different keys. -Point your SolrCloud definition to a user-provided ConfigMap using the following structure: - -[source,yaml] ----- -spec: - ... - customSolrKubeOptions: - configMapOptions: - providedConfigMap: ----- - -=== Custom solr.xml - -Solr pods load node-level configuration settings from `/var/solr/data/solr.xml`. -This important configuration file gets created by the `cp-solr-xml` initContainer which bootstraps the `solr.home` directory on each pod before starting the main container. -The default `solr.xml` is mounted into the `cp-solr-xml` initContainer from a ConfigMap named `-solrcloud-configmap` (where `` is the name of your SolrCloud instance) created by the Solr operator. - -NOTE: The data in the default ConfigMap is not editable! Any changes to the `solr.xml` in the default ConfigMap created by the operator will be overwritten during the next reconcile cycle. - -Many of the specific values in `solr.xml` can be set using Java system properties; for instance, the following setting controls the read timeout for the HTTP client used by Solr's `HttpShardHandlerFactory`: - ----- -${socketTimeout:600000} ----- - -The `${socketTimeout:600000}` syntax means pull the value from a Java system property named `socketTimeout` with default `600000` if not set. - -You can set Java system properties using the `solrOpts` string in your SolrCloud definition, such as: - -[source,yaml] ----- -spec: - solrOpts: -DsocketTimeout=300000 ----- - -This same approach works for a number of settings in `solrconfig.xml` as well. - -However, if you need to customize `solr.xml` beyond what can be accomplished with Java system properties, -then you need to supply your own `solr.xml` in a ConfigMap in the same namespace where you deploy your SolrCloud instance. -Provide your custom XML in the ConfigMap using `solr.xml` as the key as shown in the example below: - -[source,yaml] ----- ---- -kind: ConfigMap -apiVersion: v1 -metadata: - name: custom-solr-xml -data: - solr.xml: | - - - ... CUSTOM CONFIG HERE ... - ----- - -IMPORTANT: Your custom `solr.xml` must include `${solr.port.advertise:0}` as the operator relies on this element to set the port Solr pods advertise to ZooKeeper. If this element is missing, then your Solr pods will not be created. - -You can get the default `solr.xml` from a Solr pod as a starting point for creating a custom config using `kubectl cp` as shown in the example below: - -[source,bash] ----- -SOLR_POD_ID=$(kubectl get pod -l technology=solr-cloud --no-headers -o custom-columns=":metadata.name" | head -1) -kubectl cp $SOLR_POD_ID:/var/solr/data/solr.xml ./custom-solr.xml ----- - -This copies the default config from the first Solr pod found in the namespace and names it `custom-solr.xml`. Customize the settings in `custom-solr.xml` as needed and then create a ConfigMap using YAML. - -NOTE: Using `kubectl create configmap --from-file` scrambles the XML formatting, so we recommend defining the configmap YAML as shown above to keep the XML formatted properly. - -Point your SolrCloud instance at the custom ConfigMap using: - -[source,yaml] ----- -spec: - customSolrKubeOptions: - configMapOptions: - providedConfigMap: custom-solr-xml ----- - -NOTE: If you set `providedConfigMap`, then the ConfigMap must include the `solr.xml` or `log4j2.xml` key, otherwise the SolrCloud will fail to reconcile. - -==== Changes to Custom Config Trigger Rolling Restarts - -The Solr operator stores the MD5 hash of your custom XML in the StatefulSet's pod spec annotations (`spec.template.metadata.annotations`). To see the current annotations for your Solr pods, you can do: - -[source,bash] ----- -kubectl annotate pod -l technology=solr-cloud --list=true ----- - -If the custom `solr.xml` changes in the user-provided ConfigMap, then the operator triggers a rolling restart of Solr pods to apply the updated configuration settings automatically. - -To summarize, if you need to customize `solr.xml`, provide your own version in a ConfigMap and changes made to the XML in the ConfigMap are automatically applied to your Solr pods. - -=== Custom Log Configuration -_Since v0.3.0_ - -By default, the Solr Docker image configures Solr to load its log configuration from `/var/solr/log4j2.xml`. -If you need to fine-tune the log configuration, then you can provide a custom `log4j2.xml` in a ConfigMap using the same basic process as described in the previous section for customizing `solr.xml`. If supplied, the operator overrides the log config using the `LOG4J_PROPS` env var. - -As with custom `solr.xml`, the operator can track the MD5 hash of your `log4j2.xml` in the pod spec annotations to trigger a rolling restart if the log config changes. -However, Log4j2 supports hot reloading of log configuration using the `monitorInterval` attribute on the root `` element. For more information on this, see: https://logging.apache.org/log4j/2.x/manual/configuration.html#AutomaticReconfiguration[Log4j Automatic Reconfiguration]. -If your custom log config has a `monitorInterval` set, then the operator does not watch for changes to the log config and will not trigger a rolling restart if the config changes. -Kubernetes will automatically update the file on each pod's filesystem when the data in the ConfigMap changes. Once Kubernetes updates the file, Log4j will pick up the changes and apply them without restarting the Solr pod. - -If you need to customize both `solr.xml` and `log4j2.xml` then you need to supply both in the same ConfigMap using multiple keys as shown below: - -[source,yaml] ----- ---- -kind: ConfigMap -apiVersion: v1 -metadata: - name: custom-solr-xml -data: - log4j2.xml: | - - - ... YOUR CUSTOM LOG4J CONFIG HERE ... - - - - solr.xml: | - - - ... YOUR CUSTOM SOLR XML CONFIG HERE ... - ----- - -[#enable-tls-between-solr-pods] -== Enable TLS Between Solr Pods -_Since v0.3.0_ - -A common approach to securing traffic to your Solr cluster is to perform <> and leave all traffic between Solr pods un-encrypted. -However, depending on how you expose Solr on your network, you may also want to encrypt traffic between Solr pods. -The Solr operator provides **optional** configuration settings to enable TLS for encrypting traffic between Solr pods. - -Enabling TLS for Solr is a straight-forward process once you have a https://en.wikipedia.org/wiki/PKCS_12[**PKCS12 keystore**] containing an https://en.wikipedia.org/wiki/X.509[X.509] certificate and private key; as of Java 8, PKCS12 is the default keystore format supported by the JVM. - -There are three basic use cases supported by the Solr operator. First, you can use cert-manager to issue a certificate and store the resulting PKCS12 keystore in a Kubernetes TLS secret. -Alternatively, you can create the TLS secret manually from a certificate obtained by some other means. In both cases, you simply point your SolrCloud CRD to the resulting TLS secret and corresponding keystore password secret. -Lastly, as of **v0.4.0**, you can supply the path to a directory containing TLS files that are mounted by some external agent or CSI driver. - -=== Use cert-manager to issue the certificate - -https://cert-manager.io/docs/[cert-manager] is a popular Kubernetes controller for managing TLS certificates, including renewing certificates prior to expiration. -One of the primary benefits of cert-manager is it supports pluggable certificate `Issuer` implementations, including a self-signed Issuer for local development and an https://tools.ietf.org/html/rfc8555[ACME compliant] Issuer for working with services like https://letsencrypt.org/[Let's Encrypt]. - -If you already have a TLS certificate you want to use for Solr, then you don't need cert-manager and can skip down to <> later in this section. -If you do not have a TLS certificate, then we recommend installing **cert-manager** as it makes working with TLS in Kubernetes much easier. - -==== Install cert-manager - -Given its popularity, cert-manager may already be installed in your Kubernetes cluster. To check if `cert-manager` is already installed, do: - -[source,bash] ----- -kubectl get crds -l app.kubernetes.io/instance=cert-manager ----- - -If installed, you should see the following cert-manager related CRDs: - ----- -certificaterequests.cert-manager.io -certificates.cert-manager.io -challenges.acme.cert-manager.io -clusterissuers.cert-manager.io -issuers.cert-manager.io -orders.acme.cert-manager.io ----- - -If not installed, use Helm to install it into the `cert-manager` namespace: - -[source,bash] ----- -if ! helm repo list | grep -q "https://charts.jetstack.io"; then - helm repo add jetstack https://charts.jetstack.io - helm repo update -fi - -kubectl create ns cert-manager -helm upgrade --install cert-manager jetstack/cert-manager \ - --namespace cert-manager \ - --version v1.1.0 \ - --set installCRDs=true ----- - -You'll need admin privileges to install the CRDs in a shared K8s cluster, so work with your friendly Kubernetes admin to install if needed (most likely cert-manager will already be installed). -Refer to the https://cert-manager.io/docs/installation/kubernetes/[cert-manager Installation] instructions for more information. - -==== Create cert-manager Certificate - -Once cert-manager is installed, you need to create an `Issuer` or `ClusterIssuer` CRD and then request a certificate using a https://cert-manager.io/docs/usage/certificate/[Certificate CRD]. -Refer to the https://cert-manager.io/docs/[cert-manager docs] on how to define a certificate. - -Certificate Issuers are typically platform specific. For instance, on GKE, to create a Let's Encrypt Issuer you need a service account with various cloud DNS permissions granted for DNS01 challenges to work, see: https://cert-manager.io/docs/configuration/acme/dns01/google/. - -The DNS names in your certificate should match the Solr addressability settings in your SolrCloud CRD. For instance, if your SolrCloud CRD uses the following settings: - -[source,yaml] ----- -spec: - solrAddressability: - external: - domainName: k8s.solr.cloud ----- - -Then your certificate needs the following domains specified: - -[source,yaml] ----- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - ... -spec: - dnsNames: - - '*.k8s.solr.cloud' - - k8s.solr.cloud ----- - -The wildcard DNS name will cover all SolrCloud nodes such as `-solrcloud-1.k8s.solr.cloud`. - -Also, when requesting your certificate, keep in mind that internal DNS names in Kubernetes are not valid for public certificates. -For instance `..svc.cluster.local` is internal to Kubernetes and certificate issuer services like LetsEncrypt -will not generate a certificate for K8s internal DNS names (you'll get errors during certificate issuing). - -Another benefit is cert-manager can create a https://cert-manager.io/docs/release-notes/release-notes-0.15/#general-availability-of-jks-and-pkcs-12-keystores[PKCS12] keystore automatically when issuing a `Certificate`, -which allows the Solr operator to mount the keystore directly on our Solr pods. Ensure your certificate instance requests **pkcs12 keystore** gets created using config similar to the following: - -[source,yaml] ----- - keystores: - pkcs12: - create: true - passwordSecretRef: - key: password-key - name: pkcs12-password-secret ----- - -NOTE: the example structure above goes in your certificate CRD YAML, not SolrCloud. - -You need to create the keystore secret (e.g. `pkcs12-password-secret`) in the same namespace before requesting the certificate, see: https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.PKCS12Keystore. -Although a keystore password is not required for PKCS12, **cert-manager** requires a password when requesting a `pkcs12` keystore for your certificate. -Moreover, most JVMs require a password for pkcs12 keystores, not supplying a password typically results in errors like the following: - ----- -Caused by: java.security.UnrecoverableKeyException: Get Key failed: null - at java.base/sun.security.pkcs12.PKCS12KeyStore.engineGetKey(Unknown Source) - at java.base/sun.security.util.KeyStoreDelegator.engineGetKey(Unknown Source) - at java.base/java.security.KeyStore.getKey(Unknown Source) - at java.base/sun.security.ssl.SunX509KeyManagerImpl.(Unknown Source) ----- - -Consequently, the Solr operator requires you to use a non-null password for your keystore. - -Here's an example of how to use cert-manager to generate a self-signed certificate: - -[source,yaml] ----- ---- -apiVersion: v1 -kind: Secret -metadata: - name: pkcs12-password-secret -data: - password-key: SOME_PASSWORD_HERE - ---- -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - name: selfsigned-issuer -spec: - selfSigned: {} - ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: selfsigned-cert -spec: - subject: - organizations: ["dev"] - dnsNames: - - localhost - - dev-dev-solrcloud.ing.local.domain - - "*.ing.local.domain" - secretName: dev-selfsigned-cert-tls - issuerRef: - name: selfsigned-issuer - keystores: - pkcs12: - create: true - passwordSecretRef: - key: password-key - name: pkcs12-password-secret ----- - -Once created, simply point the SolrCloud deployment at the TLS and keystore password secrets, e.g. - -[source,yaml] ----- -spec: - ... other SolrCloud CRD settings ... - - solrTLS: - keyStorePasswordSecret: - name: pkcs12-password-secret - key: password-key - pkcs12Secret: - name: selfsigned-cert - key: keystore.p12 ----- - -NOTE: when using self-signed certificates, you'll have to configure HTTP client libraries to skip hostname and CA verification. - -[#i-already-have-a-tls-certificate] -=== I already have a TLS Certificate - -Users may bring their own cert stored in a `kubernetes.io/tls` secret; for this use case, cert-manager is not required. -There are many ways to get a certificate, such as from the GKE managed certificate process or from a CA directly. -Regardless of how you obtain a Certificate, it needs to be stored in a https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets[Kubernetes TLS secret] -that contains a `tls.crt` file (x.509 certificate with a public key and info about the issuer) and a `tls.key` file (the private key). - -Ideally, the TLS secret will also have a `pkcs12` keystore. -If the supplied TLS secret does not contain a `keystore.p12` key, then the Solr operator creates an `initContainer` on the StatefulSet to generate the keystore from the TLS secret using the following command: - -[source,bash] ----- -openssl pkcs12 -export -in tls.crt -inkey tls.key -out keystore.p12 -passout pass:${SOLR_SSL_KEY_STORE_PASSWORD}" ----- - -_The `initContainer` uses the main Solr image as it has `openssl` installed._ - -Configure the SolrCloud deployment to point to the user-provided keystore and TLS secrets: - -[source,yaml] ----- -spec: - ... other SolrCloud CRD settings ... - - solrTLS: - keyStorePasswordSecret: - name: pkcs12-keystore-manual - key: password-key - pkcs12Secret: - name: pkcs12-keystore-manual - key: keystore.p12 ----- - -=== Separate TrustStore - -A truststore holds public keys for certificates you trust. By default, Solr pods are configured to use the keystore as the truststore. -However, you may have a separate truststore you want to use for Solr TLS. As with the keystore, you need to provide a PKCS12 truststore in a secret and then configure your SolrCloud TLS settings as shown below: - -[source,yaml] ----- -spec: - ... other SolrCloud CRD settings ... - - solrTLS: - keyStorePasswordSecret: - name: pkcs12-keystore-manual - key: password-key - pkcs12Secret: - name: pkcs12-keystore-manual - key: keystore.p12 - trustStorePasswordSecret: - name: pkcs12-truststore - key: password-key - trustStoreSecret: - name: pkcs12-truststore - key: truststore.p12 ----- - -TIP: if your truststore is not in PKCS12 format, use `openssl` to convert it. - -=== Mounted TLS Directory -_Since v0.4.0_ - -The options discussed to this point require that all Solr pods share the same certificate and truststore. An emerging pattern in the Kubernetes ecosystem is to issue a unique certificate for each pod. -Typically this operation is performed by an external agent, such as a cert-manager extension, that uses mutating webhooks to mount a unique certificate and supporting files on each pod dynamically. -How the pod-specific certificates get issued is beyond the scope of the Solr operator. Under this scheme, you can use `spec.solrTLS.mountedTLSDir.path` to specify the path where the TLS files are mounted on the main pod. -The following example illustrates how to configure a keystore and truststore in PKCS12 format using the `mountedTLSDir` option: - -[source,yaml] ----- -spec: - ... other SolrCloud CRD settings ... - - solrTLS: - clientAuth: Want - checkPeerName: true - verifyClientHostname: true - mountedTLSDir: - path: /pod-server-tls - keystoreFile: keystore.p12 - keystorePasswordFile: keystore-password - truststoreFile: truststore.p12 ----- - -When using the mounted TLS directory option, you need to ensure each Solr pod gets restarted before the certificate expires. Solr does not support hot reloading of the keystore or truststore. -Consequently, we recommend using the `spec.updateStrategy.restartSchedule` to restart pods before the certificate expires. -Typically, with this scheme, a new certificate is issued whenever a pod is restarted. - -When using the Cert Manager CSI Driver, a file is not generated for the keystore password. -Instead, users can provide an annotation to manually set the password. -For this use case, the `solrTLS.mountedTLSDir.keystorePassword` and `solrTLS.mountedTLSDir.truststorePassword` options are available. -These take strings that are plain-text passwords for the keystore or truststore. -They will be ignored when `keystorePasswordFile` and `truststorePasswordFile` are provided. - -=== Client TLS -_Since v0.4.0_ - -Solr supports using separate client and server TLS certificates. Solr uses the client certificate in mutual TLS (mTLS) scenarios to make requests to other Solr pods. -Use the `spec.solrClientTLS` configuration options to configure a separate client certificate. -As this is an advanced option, the supplied client certificate keystore and truststore must already be in PKCS12 format. -As with the server certificate loaded from `spec.solrTLS.pkcs12Secret`, -you can have the operator restart Solr pods after the client TLS secret updates by setting `spec.solrClientTLS.restartOnTLSSecretUpdate` to `true`. - -You may need to increase the timeout for the liveness / readiness probes when using mTLS with a separate client certificate, such as: - -[source,yaml] ----- -spec: - ... other SolrCloud CRD settings ... - - customSolrKubeOptions: - podOptions: - livenessProbe: - timeoutSeconds: 10 - readinessProbe: - timeoutSeconds: 10 ----- - -You may also use the `spec.solrClientTLS.mountedTLSDir` option to load a pod specific client certificate from a directory mounted by an external agent or CSI driver. - -=== Ingress with TLS protected Solr - -The Solr operator may create an Ingress for exposing Solr pods externally. When TLS is enabled, the operator adds the following annotation and TLS settings to the Ingress manifest, such as: - -[source,yaml] ----- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - annotations: - nginx.ingress.kubernetes.io/backend-protocol: HTTPS -spec: - rules: - ... - tls: - - secretName: my-selfsigned-cert-tls ----- - -If using the mounted TLS Directory option with an Ingress, you will need to inject the ingress with TLS information as well. -The <> shows how this can be done when using cert-manager. - -=== Certificate Renewal and Rolling Restarts - -cert-manager automatically handles certificate renewal. From the docs: - -____ -The default duration for all certificates is 90 days and the default renewal windows is 30 days. This means that certificates are considered valid for 3 months and renewal will be attempted within 1 month of expiration. - https://docs.cert-manager.io/en/release-0.8/reference/certificates.html -____ - -However, this only covers updating the underlying TLS secret and mounted secrets in each Solr pod do get updated on the filesystem, see: https://kubernetes.io/docs/concepts/configuration/secret/#mounted-secrets-are-updated-automatically. -However, the JVM only reads key and trust stores once during initialization and does not reload them if they change. Thus, we need to recycle the Solr container in each pod to pick up the updated keystore. - -The operator tracks the MD5 hash of the `tls.crt` from the TLS secret in an annotation on the StatefulSet pod spec so that when the TLS secret changes, it will trigger a rolling restart of the affected Solr pods. -The operator guards this behavior with an **opt-in** flag `restartOnTLSSecretUpdate` as some users may not want to restart Solr pods when the TLS secret holding the cert changes and may instead choose to restart the pods during a maintenance window (presumably before the certs expire). - -[source,yaml] ----- -spec: - ... other SolrCloud CRD settings ... - - solrTLS: - restartOnTLSSecretUpdate: true - ... - ----- - -=== Misc Config Settings for TLS Enabled Solr - -Although not required, we recommend setting the `commonServicePort` and `nodePortOverride` to `443` instead of the default port `80` under `solrAddressability` to avoid confusion when working with `https`. - -[source,yaml] ----- -spec: - ... other SolrCloud CRD settings ... - - solrAddressability: - commonServicePort: 443 - external: - nodePortOverride: 443 - ----- - -==== Prometheus Exporter - -If you're relying on a self-signed certificate (or any certificate that requires importing the CA into the Java trust store) for Solr pods, then the Prometheus Exporter will not be able to make requests for metrics. -You'll need to duplicate your TLS config from your SolrCloud CRD definition to your Prometheus exporter CRD definition as shown in the example below: - -[source,yaml] ----- - solrReference: - cloud: - name: "dev" - solrTLS: - restartOnTLSSecretUpdate: true - keyStorePasswordSecret: - name: pkcs12-password-secret - key: password-key - pkcs12Secret: - name: dev-selfsigned-cert-tls - key: keystore.p12 ----- - -_This only applies to the SolrJ client the exporter uses to make requests to your TLS-enabled Solr pods and does not enable HTTPS for the exporter service._ - -==== Public / Private Domain Names - -If your Solr pods use Kubernetes internal domain names, such as `-solrcloud-.` or -`-solrcloud-..svc.cluster.local` then you **cannot** request a certificate from a service like LetsEncrypt. -You'll receive an error like (from the cert-manager controller pod logs): - ----- - Cannot issue for \"*..svc.cluster.local\": Domain name does not end with a valid public suffix (TLD)" ----- - -This is policy enforced by trusted certificate authorities, see: https://www.digicert.com/kb/advisories/internal-names.htm. -Intuitively, this makes sense because services like LetsEncrypt cannot determine if you own a private domain because they cannot reach it from the Internet. - -Some CA's provide TLS certificates for private domains but that topic is beyond the scope of the Solr operator. -You may want to use a self-signed certificate for internal traffic and then a public certificate for your Ingress. -Alternatively, you can choose to expose Solr pods with an external name using SolrCloud `solrAddressability` settings: - -[source,yaml] ----- -kind: SolrCloud -metadata: - name: search -spec: - ... other SolrCloud CRD settings ... - - solrAddressability: - commonServicePort: 443 - external: - nodePortOverride: 443 - domainName: k8s.solr.cloud - method: Ingress - useExternalAddress: true ----- - -The example settings above will result in your Solr pods getting names like: `-search-solrcloud-0.k8s.solr.cloud` -which you can request TLS certificates from LetsEncrypt assuming you own the `k8s.solr.cloud` domain. - -==== mTLS - -Mutual TLS (mTLS) provides an additional layer of security by ensuring the client applications sending requests to Solr are trusted. -To enable mTLS, simply set `spec.solrTLS.clientAuth` to either `Want` or `Need`. When mTLS is enabled, the Solr operator needs to -supply a client certificate that is trusted by Solr; the operator makes API calls to Solr to get cluster status. -To configure the client certificate for the operator, see xref:getting-started:running-the-operator.adoc#client-auth-for-mtls-enabled-solr-clusters[Running the Operator > mTLS] - -When mTLS is enabled, the liveness and readiness probes are configured to execute a local command on each Solr pod instead of the default HTTP Get request. -Using a command is required so that we can use the correct TLS certificate when making an HTTPs call to the probe endpoints. - -To help with debugging the TLS handshake between client and server, -you can add the `-Djavax.net.debug=SSL,keymanager,trustmanager,ssl:handshake` Java system property to the `spec.solrOpts` for your SolrCloud instance. - -To verify mTLS is working for your Solr pods, you can supply the client certificate (and CA cert if needed) via curl after opening a port-forward to one of your Solr pods: - ----- -curl "https://localhost:8983/solr/admin/info/system" -v \ - --key client/private_key.pem \ - --cert client/client.pem \ - --cacert root-ca/root-ca.pem ----- - -The `--cacert` option supplies the CA's certificate needed to trust the server certificate provided by the Solr pods during TLS handshake. - -[#enable-ingress-tls-termination] -== Enable Ingress TLS Termination -_Since v0.4.0_ - -A common approach to securing traffic to your Solr cluster is to perform **TLS termination** at the Ingress and either leave all traffic between Solr pods un-encrypted or use private CAs for inter-pod communication. -The operator supports this paradigm, to ensure all external traffic is encrypted. - -[source,yaml] ----- -kind: SolrCloud -metadata: - name: search -spec: - ... other SolrCloud CRD settings ... - - solrAddressability: - external: - domainName: k8s.solr.cloud - method: Ingress - hideNodes: true - useExternalAddress: false - ingressTLSTermination: - tlsSecret: my-selfsigned-cert-tls ----- - -The only additional settings required here are: - -* Making sure that you are not using the external TLS address for Solr to communicate internally via `useExternalAddress: false`. -This will be ignored, even if it is set to `true`. -* Adding a TLS secret through `ingressTLSTermination.tlsSecret`, this is passed to the Kubernetes Ingress to handle the TLS termination. -_This ensures that the only way to communicate with your Solr cluster externally is through the TLS protected common-endpoint._ - -To generate a TLS secret, follow the <> and use the templated Hostname: `--solrcloud.` - -If you configure your SolrCloud correctly, cert-manager can auto-inject the TLS secrets for you as well: - -[source,yaml] ----- -kind: SolrCloud -metadata: - name: search - namespace: explore -spec: - ... other SolrCloud CRD settings ... - customSolrKubeOptions: - ingressOptions: - annotations: - kubernetes.io/ingress.class: "nginx" - cert-manager.io/issuer: "" - cert-manager.io/common-name: explore-search-solrcloud.apple.com - solrAddressability: - external: - domainName: k8s.solr.cloud - method: Ingress - hideNodes: true - useExternalAddress: false - ingressTLSTermination: - tlsSecret: myingress-cert ----- - -For more information on the Ingress TLS Termination options for cert-manager, https://cert-manager.io/docs/usage/ingress/[refer to the documentation]. - -== Authentication and Authorization -_Since v0.3.0_ - -All well-configured Solr clusters should enforce users to authenticate, even for read-only operations. Even if you want -to allow anonymous query requests from unknown users, you should make this explicit using Solr's rule-based authorization -plugin. In other words, always enforce security and then relax constraints as needed for specific endpoints based on your -use case. The Solr operator can bootstrap a default security configuration for your SolrCloud during initialization. As such, -there is no reason to deploy an unsecured SolrCloud cluster when using the Solr operator. In most cases, you'll want to combine -basic authentication with TLS to ensure credentials are never passed in clear text. - -For background on Solr security, please refer to the https://solr.apache.org/guide[Reference Guide] for your version of Solr. - -The Solr operator only supports the `Basic` authentication scheme. In general, you have two primary options for configuring authentication with the Solr operator: - -. Let the Solr operator bootstrap the `security.json` to configure *basic authentication* for Solr. -. Supply your own `security.json` to Solr, which must define a user account that the operator can use to make API requests to secured Solr pods. - -If you choose option 2, then you need to provide the credentials the Solr operator should use to make requests to Solr via a Kubernetes secret. -With option 1, the operator creates a Basic Authentication Secret for you, which contains the username and password for the `k8s-oper` user. - -=== Option 1: Bootstrap Security - -The easiest way to get started with Solr security is to have the operator bootstrap a `security.json` (stored in ZK) as part of the initial deployment process. -To activate this feature, add the following configuration to your SolrCloud CRD definition YAML: - -[source,yaml] ----- -spec: - ... - solrSecurity: - authenticationType: Basic ----- - -Once the cluster is up, you'll need the `admin` user password to login to the Solr Admin UI. -The `admin` user will have a random password generated by the operator during `security.json` bootstrapping. -Use the following command to retrieve the password from the bootstrap secret created by the operator: - -[source,bash] ----- -kubectl get secret -solrcloud-security-bootstrap -o jsonpath='{.data.admin}' | base64 --decode ----- - -_where `` is the name of your SolrCloud_ - -Once `security.json` is bootstrapped, the operator will not update it! You're expected to use the `admin` user to access the Security API to make further changes. -In addition to the `admin` user, the operator defines a `solr` user, which has basic read access to Solr resources. You can retrieve the `solr` user password using: - -[source,bash] ----- -kubectl get secret -solrcloud-security-bootstrap -o jsonpath='{.data.solr}' | base64 --decode ----- - -You can safely delete the bootstrap secret, provided you've captured the `admin` password, after your SolrCloud deploys with the bootstrapped `security.json`. -However, this will trigger a rolling restart across all pods as the `setup-zk` initContainer definition changes. - -==== k8s-oper user - -The operator makes requests to secured Solr endpoints as the `k8s-oper` user; credentials for the `k8s-oper` user are stored in a separate secret of type `kubernetes.io/basic-auth` -with name `-solrcloud-basic-auth`. The `k8s-oper` user is configured with read-only access to a minimal set of endpoints, see details in the **Authorization** sub-section below. -Remember, if you change the `k8s-oper` password using the Solr security API, then you **must** update the secret with the new password or the operator will be locked out. -Also, changing the password for the `k8s-oper` user in the K8s secret after bootstrapping will not update Solr! You're responsible for changing the password in both places. - -==== Liveness and Readiness Probes - -We recommend configuring Solr to allow un-authenticated access over HTTP to the probe endpoint(s) and the bootstrapped `security.json` does this for you automatically (see next sub-section). -However, if you want to secure the probe endpoints, then you need to set `probesRequireAuth: true` as shown below: - -[source,yaml] ----- -spec: - ... - solrSecurity: - authenticationType: Basic - probesRequireAuth: true ----- - -When `probesRequireAuth` is set to `true`, the liveness and readiness probes execute a command instead of using HTTP. -The operator configures a command instead of setting the `Authorization` header for the HTTP probes, as that would require a restart of all pods if the password changes. -With a command, we can load the username and password from a secret; Kubernetes will -https://kubernetes.io/docs/concepts/configuration/secret/#mounted-secrets-are-updated-automatically[update the mounted secret files] when the secret changes automatically. - -By default, the operator will use Solr's `/admin/info/system` endpoint for startup and liveness probes, and the `/admin/info/health` endpoint for readiness probes. -This default can be customized by changing the HTTP path for any probes (under `spec.customSolrKubeOptions.podOptions`), however this also requires users to set `probesRequireAuth=false` as the operator does not reconfigure custom HTTP probes to use the command needed to support `probesRequireAuth=true`. - -Custom readiness and liveness probes can be specified using configuration like the following: - -[source,yaml] ----- -spec: - ... - customSolrKubeOptions: - podOptions: - livenessProbe: - httpGet: - scheme: HTTP - path: /solr/admin/customliveness - port: 8983 - readinessProbe: - httpGet: - scheme: HTTP - path: /solr/admin/customreadiness - port: 8983 ----- - -Consequently, the bootstrapped `security.json` will include additional rules to allow access to the endpoints used by the startup, liveness, and readiness probes: - -[source,json] ----- - { - "name": "k8s-probe-1", - "role": null, - "collection": null, - "path": "/admin/customliveness" - }, - { - "name": "k8s-probe-2", - "role": null, - "collection": null, - "path": "/admin/customreadiness" - } ----- - -Note, if you change the probes after creating your solrcloud, then the new probe paths will not be added to the security.json. -The security file is bootstrapped just once, so if your probes need to change you must add it to the allowed paths via the Solr Security API using the admin credentials. - -==== Authorization - -The default `security.json` created by the operator during initialization is shown below; the passwords for each user are randomized for every SolrCloud you create. -In addition to configuring the `solr.BasicAuthPlugin`, the operator initializes a set of authorization rules for the default user accounts: `admin`, `solr`, and `k8s-oper`. -Take a moment to review these authorization rules so that you're aware of the roles and access granted to each user in your cluster. - -[source,json] ----- -{ - "authentication": { - "blockUnknown": false, - "class": "solr.BasicAuthPlugin", - "credentials": { - "admin": "...", - "k8s-oper": "...", - "solr": "..." - }, - "realm": "Solr Basic Auth", - "forwardCredentials": false - }, - "authorization": { - "class": "solr.RuleBasedAuthorizationPlugin", - "user-role": { - "admin": [ "admin", "k8s" ], - "k8s-oper": [ "k8s" ], - "solr": [ "users", "k8s" ] - }, - "permissions": [ - { - "name": "k8s-probe-0", - "role": null, - "collection": null, - "path": "/admin/info/system" - }, - { - "name": "k8s-probe-1", - "role": null, - "collection": null, - "path": "/admin/info/health" - }, - { - "name": "k8s-status", - "role": "k8s", - "collection": null, - "path": "/admin/collections" - }, - { - "name": "k8s-metrics", - "role": "k8s", - "collection": null, - "path": "/admin/metrics" - }, - { - "name": "k8s-zk", - "role":"k8s", - "collection": null, - "path":"/admin/zookeeper/status" - }, - { - "name": "k8s-ping", - "role": "k8s", - "collection": "*", - "path": "/admin/ping" - }, - { - "name": "k8s-replica-balancing", - "role": "k8s", - "collection": null, - "path": "/____v2/cluster/replicas/balance" - }, - { - "name": "collection-admin-edit", - "role": "k8s" - }, - { - "name": "read", - "role": [ "admin", "users" ] - }, - { - "name": "update", - "role": [ "admin" ] - }, - { - "name": "security-read", - "role": [ "admin" ] - }, - { - "name": "security-edit", - "role": [ "admin" ] - }, - { - "name": "all", - "role": [ "admin" ] - } - ] - } -} ----- - -A few aspects of the default `security.json` configuration warrant a closer look. First, the `probesRequireAuth` setting -(defaults to `false`) governs the value for `blockUnknown` (under `authentication`) and whether the probe endpoint(s) require authentication: - -[source,json] ----- - { - "name": "k8s-probe-0", - "role": null, - "collection": null, - "path": "/admin/info/system" - } ----- - -In this case, the `"role":null` indicates this endpoint allows anonymous access by unknown users. -The `"collection":null` value indicates the path is not associated with any collection, i.e. it is a top-level system path. - -The operator sends GET requests to the `/admin/collections` endpoint to get cluster status to determine the rolling restart order: - -[source,json] ----- - { - "name": "k8s-status", - "role": "k8s", - "collection": null, - "path": "/admin/collections" - }, ----- - -In this case, the `"role":"k8s"` indicates the requesting user must be in the `k8s` role; notice that all default users have the `k8s` role. - -The Prometheus exporter sends GET requests to the `/admin/metrics` endpoint to collect metrics from each pod. -The exporter also hits the `/admin/ping` endpoint for every collection, which requires the following authorization rules: - -[source,json] ----- - { - "name": "k8s-metrics", - "role": "k8s", - "collection": null, - "path": "/admin/metrics" - }, - { - "name": "k8s-ping", - "role": "k8s", - "collection": "*", - "path": "/admin/ping" - }, - { - "name": "k8s-zk", - "role":"k8s", - "collection": null, - "path":"/admin/zookeeper/status" - }, ----- - -The `"collection":"*"` setting indicates this path applies to all collections, which maps to endpoint `/collections//admin/ping` at runtime. - -The initial authorization config grants the `read` permission to the `users` role, which allows `users` to send query requests but cannot add / update / delete documents. -For instance, the `solr` user is mapped to the `users` role, so the `solr` user can send query requests only. -In general, please verify the initial authorization rules for each role before sharing user credentials. - -=== Option 2: User-provided `security.json` and credentials secret - -If users want full control over their cluster's security config, then they can provide the Solr `security.json` via a Secret and the credentials the operator should use -to make requests to Solr in a Secret. - -==== Custom `security.json` Secret -_Since v0.5.0_ - -For full control over the Solr security configuration, supply a `security.json` in a Secret. The following example illustrates how to point the operator to a Secret containing a custom `security.json`: - -[source,yaml] ----- -spec: - ... - solrSecurity: - authenticationType: Basic - bootstrapSecurityJson: - name: my-custom-security-json - key: security.json ----- - -For `Basic` authentication, if you don't supply a `security.json` Secret, then the operator assumes you are bootstrapping the security configuration via some other means. - -Refer to the example `security.json` shown in the Authorization section above to help you get started crafting your own custom configuration. - -==== Basic Authentication - -For `Basic` authentication, the supplied secret must be of type https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret[Basic Authentication Secret] and define both a `username` and `password`. - -[source,yaml] ----- -spec: - ... - solrSecurity: - authenticationType: Basic - basicAuthSecret: user-provided-secret ----- - -Here is an example of how to define a basic auth secret using YAML: - -[source,yaml] ----- -apiVersion: v1 -kind: Secret -metadata: - name: my-basic-auth-secret -type: kubernetes.io/basic-auth -stringData: - username: k8s-oper - password: Test1234 ----- - -With this config, the operator will make API requests to secured Solr pods as the `k8s-oper` user. -NOTE: be sure to use a stronger password for real deployments - -Users need to ensure their `security.json` contains the user supplied in the `basicAuthSecret` has read access to the following endpoints: - ----- -/admin/info/system -/admin/info/health -/admin/collections -/admin/metrics -/admin/ping (for collection="*") -/admin/zookeeper/status -/____v2/cluster/replicas/balance ----- - -And the following named permissions: - ----- -collection-admin-edit ----- - -TIP: see the authorization rules defined by the default `security.json` as a guide for configuring access for the operator user - -===== Changing the Password - -If you change the password for the user configured in your `basicAuthSecret` using the Solr security API, then you **must** update the secret with the new password or the operator will be locked out. -Also, changing the password for this user in the K8s secret will not update Solr! You're responsible for changing the password in both places. - -===== Prometheus Exporter with Basic Auth - -If you enable basic auth for your SolrCloud cluster, then you need to point the Prometheus exporter at the basic auth secret; -refer to xref:solr-prometheus-exporter:index.adoc#prometheus-exporter-with-basic-auth[Prometheus Exporter with Basic Auth] for more details. - == Various Runtime Parameters There are various runtime parameters that allow you to customize the running of your Solr Cloud via the Solr Operator. === Time to wait for Solr to be killed gracefully -_Since v0.3.0_ The Solr Operator manages the Solr StatefulSet in a way that when a Solr pod needs to be stopped, or deleted, Kubernetes and Solr are on the same page for how long to wait for the process to die gracefully. diff --git a/docs/modules/solr-cloud/pages/tls.adoc b/docs/modules/solr-cloud/pages/tls.adoc new file mode 100644 index 00000000..f8f1d605 --- /dev/null +++ b/docs/modules/solr-cloud/pages/tls.adoc @@ -0,0 +1,530 @@ += Solr TLS +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +[#enable-tls-between-solr-pods] +== Enable TLS Between Solr Pods + +A common approach to securing traffic to your Solr cluster is to perform <> and leave all traffic between Solr pods un-encrypted. +However, depending on how you expose Solr on your network, you may also want to encrypt traffic between Solr pods. +The Solr operator provides **optional** configuration settings to enable TLS for encrypting traffic between Solr pods. + +Enabling TLS for Solr is a straight-forward process once you have a https://en.wikipedia.org/wiki/PKCS_12[**PKCS12 keystore**] containing an https://en.wikipedia.org/wiki/X.509[X.509] certificate and private key; as of Java 8, PKCS12 is the default keystore format supported by the JVM. + +There are three basic use cases supported by the Solr operator. First, you can use cert-manager to issue a certificate and store the resulting PKCS12 keystore in a Kubernetes TLS secret. +Alternatively, you can create the TLS secret manually from a certificate obtained by some other means. In both cases, you simply point your SolrCloud CRD to the resulting TLS secret and corresponding keystore password secret. +Lastly, as of **v0.4.0**, you can supply the path to a directory containing TLS files that are mounted by some external agent or CSI driver. + +=== Use cert-manager to issue the certificate + +https://cert-manager.io/docs/[cert-manager] is a popular Kubernetes controller for managing TLS certificates, including renewing certificates prior to expiration. +One of the primary benefits of cert-manager is it supports pluggable certificate `Issuer` implementations, including a self-signed Issuer for local development and an https://tools.ietf.org/html/rfc8555[ACME compliant] Issuer for working with services like https://letsencrypt.org/[Let's Encrypt]. + +If you already have a TLS certificate you want to use for Solr, then you don't need cert-manager and can skip down to <> later in this section. +If you do not have a TLS certificate, then we recommend installing **cert-manager** as it makes working with TLS in Kubernetes much easier. + +==== Install cert-manager + +Given its popularity, cert-manager may already be installed in your Kubernetes cluster. To check if `cert-manager` is already installed, do: + +[source,bash] +---- +kubectl get crds -l app.kubernetes.io/instance=cert-manager +---- + +If installed, you should see the following cert-manager related CRDs: + +---- +certificaterequests.cert-manager.io +certificates.cert-manager.io +challenges.acme.cert-manager.io +clusterissuers.cert-manager.io +issuers.cert-manager.io +orders.acme.cert-manager.io +---- + +If not installed, use Helm to install it into the `cert-manager` namespace: + +[source,bash] +---- +if ! helm repo list | grep -q "https://charts.jetstack.io"; then + helm repo add jetstack https://charts.jetstack.io + helm repo update +fi + +kubectl create ns cert-manager +helm upgrade --install cert-manager jetstack/cert-manager \ + --namespace cert-manager \ + --version v1.1.0 \ + --set installCRDs=true +---- + +You'll need admin privileges to install the CRDs in a shared K8s cluster, so work with your friendly Kubernetes admin to install if needed (most likely cert-manager will already be installed). +Refer to the https://cert-manager.io/docs/installation/kubernetes/[cert-manager Installation] instructions for more information. + +==== Create cert-manager Certificate + +Once cert-manager is installed, you need to create an `Issuer` or `ClusterIssuer` CRD and then request a certificate using a https://cert-manager.io/docs/usage/certificate/[Certificate CRD]. +Refer to the https://cert-manager.io/docs/[cert-manager docs] on how to define a certificate. + +Certificate Issuers are typically platform specific. For instance, on GKE, to create a Let's Encrypt Issuer you need a service account with various cloud DNS permissions granted for DNS01 challenges to work, see: https://cert-manager.io/docs/configuration/acme/dns01/google/. + +The DNS names in your certificate should match the Solr addressability settings in your SolrCloud CRD. For instance, if your SolrCloud CRD uses the following settings: + +[source,yaml] +---- +spec: + solrAddressability: + external: + domainName: k8s.solr.cloud +---- + +Then your certificate needs the following domains specified: + +[source,yaml] +---- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + ... +spec: + dnsNames: + - '*.k8s.solr.cloud' + - k8s.solr.cloud +---- + +The wildcard DNS name will cover all SolrCloud nodes such as `-solrcloud-1.k8s.solr.cloud`. + +Also, when requesting your certificate, keep in mind that internal DNS names in Kubernetes are not valid for public certificates. +For instance `..svc.cluster.local` is internal to Kubernetes and certificate issuer services like LetsEncrypt +will not generate a certificate for K8s internal DNS names (you'll get errors during certificate issuing). + +Another benefit is cert-manager can create a https://cert-manager.io/docs/release-notes/release-notes-0.15/#general-availability-of-jks-and-pkcs-12-keystores[PKCS12] keystore automatically when issuing a `Certificate`, +which allows the Solr operator to mount the keystore directly on our Solr pods. Ensure your certificate instance requests **pkcs12 keystore** gets created using config similar to the following: + +[source,yaml] +---- + keystores: + pkcs12: + create: true + passwordSecretRef: + key: password-key + name: pkcs12-password-secret +---- + +NOTE: the example structure above goes in your certificate CRD YAML, not SolrCloud. + +You need to create the keystore secret (e.g. `pkcs12-password-secret`) in the same namespace before requesting the certificate, see: https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.PKCS12Keystore. +Although a keystore password is not required for PKCS12, **cert-manager** requires a password when requesting a `pkcs12` keystore for your certificate. +Moreover, most JVMs require a password for pkcs12 keystores, not supplying a password typically results in errors like the following: + +---- +Caused by: java.security.UnrecoverableKeyException: Get Key failed: null + at java.base/sun.security.pkcs12.PKCS12KeyStore.engineGetKey(Unknown Source) + at java.base/sun.security.util.KeyStoreDelegator.engineGetKey(Unknown Source) + at java.base/java.security.KeyStore.getKey(Unknown Source) + at java.base/sun.security.ssl.SunX509KeyManagerImpl.(Unknown Source) +---- + +Consequently, the Solr operator requires you to use a non-null password for your keystore. + +Here's an example of how to use cert-manager to generate a self-signed certificate: + +[source,yaml] +---- +--- +apiVersion: v1 +kind: Secret +metadata: + name: pkcs12-password-secret +data: + password-key: SOME_PASSWORD_HERE + +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: selfsigned-issuer +spec: + selfSigned: {} + +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: selfsigned-cert +spec: + subject: + organizations: ["dev"] + dnsNames: + - localhost + - dev-dev-solrcloud.ing.local.domain + - "*.ing.local.domain" + secretName: dev-selfsigned-cert-tls + issuerRef: + name: selfsigned-issuer + keystores: + pkcs12: + create: true + passwordSecretRef: + key: password-key + name: pkcs12-password-secret +---- + +Once created, simply point the SolrCloud deployment at the TLS and keystore password secrets, e.g. + +[source,yaml] +---- +spec: + ... other SolrCloud CRD settings ... + + solrTLS: + keyStorePasswordSecret: + name: pkcs12-password-secret + key: password-key + pkcs12Secret: + name: selfsigned-cert + key: keystore.p12 +---- + +NOTE: when using self-signed certificates, you'll have to configure HTTP client libraries to skip hostname and CA verification. + +[#i-already-have-a-tls-certificate] +=== I already have a TLS Certificate + +Users may bring their own cert stored in a `kubernetes.io/tls` secret; for this use case, cert-manager is not required. +There are many ways to get a certificate, such as from the GKE managed certificate process or from a CA directly. +Regardless of how you obtain a Certificate, it needs to be stored in a https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets[Kubernetes TLS secret] +that contains a `tls.crt` file (x.509 certificate with a public key and info about the issuer) and a `tls.key` file (the private key). + +Ideally, the TLS secret will also have a `pkcs12` keystore. +If the supplied TLS secret does not contain a `keystore.p12` key, then the Solr operator creates an `initContainer` on the StatefulSet to generate the keystore from the TLS secret using the following command: + +[source,bash] +---- +openssl pkcs12 -export -in tls.crt -inkey tls.key -out keystore.p12 -passout pass:${SOLR_SSL_KEY_STORE_PASSWORD}" +---- + +_The `initContainer` uses the main Solr image as it has `openssl` installed._ + +Configure the SolrCloud deployment to point to the user-provided keystore and TLS secrets: + +[source,yaml] +---- +spec: + ... other SolrCloud CRD settings ... + + solrTLS: + keyStorePasswordSecret: + name: pkcs12-keystore-manual + key: password-key + pkcs12Secret: + name: pkcs12-keystore-manual + key: keystore.p12 +---- + +=== Separate TrustStore + +A truststore holds public keys for certificates you trust. By default, Solr pods are configured to use the keystore as the truststore. +However, you may have a separate truststore you want to use for Solr TLS. As with the keystore, you need to provide a PKCS12 truststore in a secret and then configure your SolrCloud TLS settings as shown below: + +[source,yaml] +---- +spec: + ... other SolrCloud CRD settings ... + + solrTLS: + keyStorePasswordSecret: + name: pkcs12-keystore-manual + key: password-key + pkcs12Secret: + name: pkcs12-keystore-manual + key: keystore.p12 + trustStorePasswordSecret: + name: pkcs12-truststore + key: password-key + trustStoreSecret: + name: pkcs12-truststore + key: truststore.p12 +---- + +TIP: if your truststore is not in PKCS12 format, use `openssl` to convert it. + +=== Mounted TLS Directory + +The options discussed to this point require that all Solr pods share the same certificate and truststore. An emerging pattern in the Kubernetes ecosystem is to issue a unique certificate for each pod. +Typically this operation is performed by an external agent, such as a cert-manager extension, that uses mutating webhooks to mount a unique certificate and supporting files on each pod dynamically. +How the pod-specific certificates get issued is beyond the scope of the Solr operator. Under this scheme, you can use `spec.solrTLS.mountedTLSDir.path` to specify the path where the TLS files are mounted on the main pod. +The following example illustrates how to configure a keystore and truststore in PKCS12 format using the `mountedTLSDir` option: + +[source,yaml] +---- +spec: + ... other SolrCloud CRD settings ... + + solrTLS: + clientAuth: Want + checkPeerName: true + verifyClientHostname: true + mountedTLSDir: + path: /pod-server-tls + keystoreFile: keystore.p12 + keystorePasswordFile: keystore-password + truststoreFile: truststore.p12 +---- + +When using the mounted TLS directory option, you need to ensure each Solr pod gets restarted before the certificate expires. Solr does not support hot reloading of the keystore or truststore. +Consequently, we recommend using the `spec.updateStrategy.restartSchedule` to restart pods before the certificate expires. +Typically, with this scheme, a new certificate is issued whenever a pod is restarted. + +When using the Cert Manager CSI Driver, a file is not generated for the keystore password. +Instead, users can provide an annotation to manually set the password. +For this use case, the `solrTLS.mountedTLSDir.keystorePassword` and `solrTLS.mountedTLSDir.truststorePassword` options are available. +These take strings that are plain-text passwords for the keystore or truststore. +They will be ignored when `keystorePasswordFile` and `truststorePasswordFile` are provided. + +=== Client TLS + +Solr supports using separate client and server TLS certificates. Solr uses the client certificate in mutual TLS (mTLS) scenarios to make requests to other Solr pods. +Use the `spec.solrClientTLS` configuration options to configure a separate client certificate. +As this is an advanced option, the supplied client certificate keystore and truststore must already be in PKCS12 format. +As with the server certificate loaded from `spec.solrTLS.pkcs12Secret`, +you can have the operator restart Solr pods after the client TLS secret updates by setting `spec.solrClientTLS.restartOnTLSSecretUpdate` to `true`. + +You may need to increase the timeout for the liveness / readiness probes when using mTLS with a separate client certificate, such as: + +[source,yaml] +---- +spec: + ... other SolrCloud CRD settings ... + + customSolrKubeOptions: + podOptions: + livenessProbe: + timeoutSeconds: 10 + readinessProbe: + timeoutSeconds: 10 +---- + +You may also use the `spec.solrClientTLS.mountedTLSDir` option to load a pod specific client certificate from a directory mounted by an external agent or CSI driver. + +=== Ingress with TLS protected Solr + +The Solr operator may create an Ingress for exposing Solr pods externally. When TLS is enabled, the operator adds the following annotation and TLS settings to the Ingress manifest, such as: + +[source,yaml] +---- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + nginx.ingress.kubernetes.io/backend-protocol: HTTPS +spec: + rules: + ... + tls: + - secretName: my-selfsigned-cert-tls +---- + +If using the mounted TLS Directory option with an Ingress, you will need to inject the ingress with TLS information as well. +The <> shows how this can be done when using cert-manager. + +=== Certificate Renewal and Rolling Restarts + +cert-manager automatically handles certificate renewal. From the docs: + +____ +The default duration for all certificates is 90 days and the default renewal windows is 30 days. This means that certificates are considered valid for 3 months and renewal will be attempted within 1 month of expiration. + https://docs.cert-manager.io/en/release-0.8/reference/certificates.html +____ + +However, this only covers updating the underlying TLS secret and mounted secrets in each Solr pod do get updated on the filesystem, see: https://kubernetes.io/docs/concepts/configuration/secret/#mounted-secrets-are-updated-automatically. +However, the JVM only reads key and trust stores once during initialization and does not reload them if they change. Thus, we need to recycle the Solr container in each pod to pick up the updated keystore. + +The operator tracks the MD5 hash of the `tls.crt` from the TLS secret in an annotation on the StatefulSet pod spec so that when the TLS secret changes, it will trigger a rolling restart of the affected Solr pods. +The operator guards this behavior with an **opt-in** flag `restartOnTLSSecretUpdate` as some users may not want to restart Solr pods when the TLS secret holding the cert changes and may instead choose to restart the pods during a maintenance window (presumably before the certs expire). + +[source,yaml] +---- +spec: + ... other SolrCloud CRD settings ... + + solrTLS: + restartOnTLSSecretUpdate: true + ... + +---- + +=== Misc Config Settings for TLS Enabled Solr + +Although not required, we recommend setting the `commonServicePort` and `nodePortOverride` to `443` instead of the default port `80` under `solrAddressability` to avoid confusion when working with `https`. + +[source,yaml] +---- +spec: + ... other SolrCloud CRD settings ... + + solrAddressability: + commonServicePort: 443 + external: + nodePortOverride: 443 + +---- + +==== Prometheus Exporter + +If you're relying on a self-signed certificate (or any certificate that requires importing the CA into the Java trust store) for Solr pods, then the Prometheus Exporter will not be able to make requests for metrics. +You'll need to duplicate your TLS config from your SolrCloud CRD definition to your Prometheus exporter CRD definition as shown in the example below: + +[source,yaml] +---- + solrReference: + cloud: + name: "dev" + solrTLS: + restartOnTLSSecretUpdate: true + keyStorePasswordSecret: + name: pkcs12-password-secret + key: password-key + pkcs12Secret: + name: dev-selfsigned-cert-tls + key: keystore.p12 +---- + +_This only applies to the SolrJ client the exporter uses to make requests to your TLS-enabled Solr pods and does not enable HTTPS for the exporter service._ + +==== Public / Private Domain Names + +If your Solr pods use Kubernetes internal domain names, such as `-solrcloud-.` or +`-solrcloud-..svc.cluster.local` then you **cannot** request a certificate from a service like LetsEncrypt. +You'll receive an error like (from the cert-manager controller pod logs): + +---- + Cannot issue for \"*..svc.cluster.local\": Domain name does not end with a valid public suffix (TLD)" +---- + +This is policy enforced by trusted certificate authorities, see: https://www.digicert.com/kb/advisories/internal-names.htm. +Intuitively, this makes sense because services like LetsEncrypt cannot determine if you own a private domain because they cannot reach it from the Internet. + +Some CA's provide TLS certificates for private domains but that topic is beyond the scope of the Solr operator. +You may want to use a self-signed certificate for internal traffic and then a public certificate for your Ingress. +Alternatively, you can choose to expose Solr pods with an external name using SolrCloud `solrAddressability` settings: + +[source,yaml] +---- +kind: SolrCloud +metadata: + name: search +spec: + ... other SolrCloud CRD settings ... + + solrAddressability: + commonServicePort: 443 + external: + nodePortOverride: 443 + domainName: k8s.solr.cloud + method: Ingress + useExternalAddress: true +---- + +The example settings above will result in your Solr pods getting names like: `-search-solrcloud-0.k8s.solr.cloud` +which you can request TLS certificates from LetsEncrypt assuming you own the `k8s.solr.cloud` domain. + +==== mTLS + +Mutual TLS (mTLS) provides an additional layer of security by ensuring the client applications sending requests to Solr are trusted. +To enable mTLS, simply set `spec.solrTLS.clientAuth` to either `Want` or `Need`. When mTLS is enabled, the Solr operator needs to +supply a client certificate that is trusted by Solr; the operator makes API calls to Solr to get cluster status. +To configure the client certificate for the operator, see xref:getting-started:running-the-operator.adoc#client-auth-for-mtls-enabled-solr-clusters[Running the Operator > mTLS] + +When mTLS is enabled, the liveness and readiness probes are configured to execute a local command on each Solr pod instead of the default HTTP Get request. +Using a command is required so that we can use the correct TLS certificate when making an HTTPs call to the probe endpoints. + +To help with debugging the TLS handshake between client and server, +you can add the `-Djavax.net.debug=SSL,keymanager,trustmanager,ssl:handshake` Java system property to the `spec.solrOpts` for your SolrCloud instance. + +To verify mTLS is working for your Solr pods, you can supply the client certificate (and CA cert if needed) via curl after opening a port-forward to one of your Solr pods: + +---- +curl "https://localhost:8983/solr/admin/info/system" -v \ + --key client/private_key.pem \ + --cert client/client.pem \ + --cacert root-ca/root-ca.pem +---- + +The `--cacert` option supplies the CA's certificate needed to trust the server certificate provided by the Solr pods during TLS handshake. + +[#enable-ingress-tls-termination] +== Enable Ingress TLS Termination + +A common approach to securing traffic to your Solr cluster is to perform **TLS termination** at the Ingress and either leave all traffic between Solr pods un-encrypted or use private CAs for inter-pod communication. +The operator supports this paradigm, to ensure all external traffic is encrypted. + +[source,yaml] +---- +kind: SolrCloud +metadata: + name: search +spec: + ... other SolrCloud CRD settings ... + + solrAddressability: + external: + domainName: k8s.solr.cloud + method: Ingress + hideNodes: true + useExternalAddress: false + ingressTLSTermination: + tlsSecret: my-selfsigned-cert-tls +---- + +The only additional settings required here are: + +* Making sure that you are not using the external TLS address for Solr to communicate internally via `useExternalAddress: false`. +This will be ignored, even if it is set to `true`. +* Adding a TLS secret through `ingressTLSTermination.tlsSecret`, this is passed to the Kubernetes Ingress to handle the TLS termination. +_This ensures that the only way to communicate with your Solr cluster externally is through the TLS protected common-endpoint._ + +To generate a TLS secret, follow the <> and use the templated Hostname: `--solrcloud.` + +If you configure your SolrCloud correctly, cert-manager can auto-inject the TLS secrets for you as well: + +[source,yaml] +---- +kind: SolrCloud +metadata: + name: search + namespace: explore +spec: + ... other SolrCloud CRD settings ... + customSolrKubeOptions: + ingressOptions: + annotations: + kubernetes.io/ingress.class: "nginx" + cert-manager.io/issuer: "" + cert-manager.io/common-name: explore-search-solrcloud.apple.com + solrAddressability: + external: + domainName: k8s.solr.cloud + method: Ingress + hideNodes: true + useExternalAddress: false + ingressTLSTermination: + tlsSecret: myingress-cert +---- + +For more information on the Ingress TLS Termination options for cert-manager, https://cert-manager.io/docs/usage/ingress/[refer to the documentation]. diff --git a/docs/modules/solr-cloud/pages/zookeeper.adoc b/docs/modules/solr-cloud/pages/zookeeper.adoc new file mode 100644 index 00000000..e4074e12 --- /dev/null +++ b/docs/modules/solr-cloud/pages/zookeeper.adoc @@ -0,0 +1,121 @@ += Zookeeper Reference +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + +All SolrCloud resources run Solr in "cloud" mode, and require access to an Apache ZooKeeper cluster for state-management. + +The Solr operator gives a few options for ZooKeeper access: + +* Connecting to an already running zookeeper ensemble via <> +* <> Zookeeper Ensemble in the same namespace via the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] + +These options are configured under `spec.zookeeperRef` + +[#chroot] +== Chroot + +Both options below come with options to specify a `chroot`, or a ZNode path for solr to use as it's base "directory" in Zookeeper. +Before the operator creates or updates a StatefulSet with a given `chroot`, it will first ensure that the given ZNode path exists and if it doesn't the operator will create all necessary ZNodes in the path. +If no chroot is given, a default of `/` will be used, which doesn't require the existence check previously mentioned. +If a chroot is provided without a prefix of `/`, the operator will add the prefix, as it is required by Zookeeper. + +[#zk-connection-info] +== ZK Connection Info + +This is an external/internal connection string as well as an optional chRoot to an already running Zookeeeper ensemble. +If you provide an external connection string, you do not _have_ to provide an internal one as well. + +Under `spec.zookeeperRef`: + +* **`connectionInfo`** +** **`externalConnectionString`** - The ZK connection string to the external Zookeeper cluster, e.g. `zoo1:2181` +** **`chroot`** - The chroot to use for the cluster + +External ZooKeeper clusters are often configured to use ZooKeeper features (e.g. securePort) which require corresponding configuration on the client side. +To support these use-cases, users may provide arbitrary system properties under `spec.solrZkOpts` which will be passed down to all ZooKeeper clients (Solr, zkcli.sh, etc.) managed by the operator. + +=== ACLs + +The Solr Operator allows for users to specify ZK ACL references in their Solr Cloud CRDs. +The user must specify the name of a secret that resides in the same namespace as the cloud, that contains an ACL username value and an ACL password value. +This ACL must have admin permissions for the <> given. + +The ACL information can be provided through an ADMIN acl and a READ ONLY acl. + +* Admin: `SolrCloud.spec.zookeeperRef.connectionInfo.acl` +* Read Only: `SolrCloud.spec.zookeeperRef.connectionInfo.readOnlyAcl` + +All ACL fields are **required** if an ACL is used. + +* **`secret`** - The name of the secret, in the same namespace as the SolrCloud, that contains the admin ACL username and password. +* **`usernameKey`** - The name of the key in the provided secret that stores the admin ACL username. +* **`passwordKey`** - The name of the key in the provided secret that stores the admin ACL password. + +[#provided-instance] +== Provided Instance + +If you do not require the Solr cloud to run cross-kube cluster, and do not want to manage your own Zookeeper ensemble, +the solr-operator can manage Zookeeper ensemble(s) for you. + +Using the https://github.com/pravega/zookeeper-operator[zookeeper-operator], a new Zookeeper ensemble can be spun up for +each solrCloud that has this option specified. + +The startup parameter `zookeeper-operator` must be provided on startup of the solr-operator for this parameter to be available. + +To find all Provided zookeeper options, run `kubectl explain solrcloud.spec.zookeeperRef.provided`. +Zookeeper Conf and PodOptions provided in the linked Zookeeper Operator version should be supported in the SolrCloud CRD. +However, this is a manual task, so not all options might be available. +If there is an option available in the ZookeeperCluster CRD that is not exposed via the SolrCloud CRD, please create a Github Issue. + +=== Zookeeper Storage Options + +The Zookeeper Operator allows for both ephemeral and persistent storage, and the Solr Operator supports both as of `v0.4.0`. + +[source,yaml] +---- +spec: + zookeeperRef: + provided: + ephemeral: + emptydirvolumesource: {} + persistence: + reclaimPolicy: "Retain" # Either Retain or Delete + spec: {} # PVC Spec for the Zookeeper volumes +---- + +By default, if you do not provide either `ephemeral` or `persistence`, the Solr Operator will default to the type of storage you are using for your Solr pods. + +However, if you provide either object above, even if the object is empty, that storage type will be used for the created Zookeeper pods. +If both `ephemeral` and `persistence` is provided, then `persistence` is preferred. + +=== ACLs for Provided Ensembles + +If you want Solr to set ZK ACLs for znodes it creates in the `provided` ensemble, you can supply ACL credentials for an ADMIN and optionally a READ ONLY user using the following config settings: + +* Admin: `SolrCloud.spec.zookeeperRef.provided.acl` +* Read Only: `SolrCloud.spec.zookeeperRef.provided.readOnlyAcl` + +All ACL fields are **required** if an ACL is used. + +* **`secret`** - The name of the secret, in the same namespace as the SolrCloud, that contains the ACL username and password. +* **`usernameKey`** - The name of the key in the provided secret that stores the admin ACL username. +* **`passwordKey`** - The name of the key in the provided secret that stores the admin ACL password. + +WARNING: There is a known issue with the Zookeeper operator where it deploys pods with `skipACL=yes`, see: https://github.com/pravega/zookeeper-operator/issues/316. +This means that even if Solr sets the ACLs on znodes, they will not be enforced by Zookeeper. If your organization requires Solr to use ZK ACLs, then you'll need to +deploy Zookeeper to Kubernetes using another approach, such as using a Helm chart. diff --git a/docs/modules/solr-prometheus-exporter/pages/index.adoc b/docs/modules/solr-prometheus-exporter/pages/index.adoc index 8efd2b48..0979fddd 100644 --- a/docs/modules/solr-prometheus-exporter/pages/index.adoc +++ b/docs/modules/solr-prometheus-exporter/pages/index.adoc @@ -44,11 +44,10 @@ If `SolrPrometheusExporter.spec.solrRef.cloud.name` is used and no image informa If any `SolrPrometheusExporter.spec.image.*` option is provided, then the Prometheus Exporter will use its own image. ==== ACLs -_Since v0.2.7_ The Prometheus Exporter can be set up to use ZK ACLs when connecting to Zookeeper. -If the prometheus exporter has been provided the name of a solr cloud, through `cloud.name`, then the solr operator will load up the ZK ACL Secret information found in the xref:solr-cloud:solr-cloud-crd.adoc#acls[SolrCloud spec]. +If the prometheus exporter has been provided the name of a solr cloud, through `cloud.name`, then the solr operator will load up the ZK ACL Secret information found in the xref:solr-cloud:zookeeper.adoc#acls[SolrCloud spec]. In order for the prometheus exporter to have visibility to these secrets, it must be deployed to the same namespace as the referenced SolrCloud or the same exact secrets must exist in both namespaces. If explicit Zookeeper connection information has been provided, through `cloud.zkConnectionInfo`, then ACL information must be provided in the same section. @@ -72,7 +71,6 @@ In order to use this functionality, use the following spec field: === Solr TLS -_Since v0.3.0_ If you're relying on a self-signed certificate (or any certificate that requires importing the CA into the Java trust store) for Solr pods, then the Prometheus Exporter will not be able to make requests for metrics. You'll need to duplicate your TLS config from your SolrCloud CRD definition to your Prometheus exporter CRD definition as shown in the example below: @@ -96,12 +94,10 @@ spec: **This only applies to the SolrJ client the exporter uses to make requests to your TLS-enabled Solr pods and does not enable HTTPS for the exporter service.** ==== Mounted TLS Directory -_Since v0.4.0_ You can use the `spec.solrReference.solrTLS.mountedTLSDir.path` to point to a directory containing certificate files mounted by an external agent or CSI driver. === Prometheus Exporter with Basic Auth -_Since v0.3.0_ If you enable basic auth for your SolrCloud cluster, then you need to point the Prometheus exporter at the basic auth secret containing the credentials for making API requests to `/admin/metrics` and `/admin/ping` for all collections. @@ -132,7 +128,7 @@ This user account will need access to the following endpoints in Solr: }, ---- -For more details on configuring Solr security with the operator, see xref:solr-cloud:solr-cloud-crd.adoc#authentication-and-authorization[Authentication and Authorization] +For more details on configuring Solr security with the operator, see xref:solr-cloud:authentication-and-authorization.adoc[Authentication and Authorization] == Prometheus Stack @@ -222,7 +218,6 @@ curl http://localhost:8080/metrics ---- ==== Customize Prometheus Exporter Config -_Since v0.3.0_ Each Solr pod exposes metrics as JSON from the `/solr/admin/metrics` endpoint. To see this in action, open a port-forward to a Solr pod and send a request to `http://localhost:8983/solr/admin/metrics`. diff --git a/docs/modules/upgrade-notes/pages/upgrade-notes.adoc b/docs/modules/upgrade-notes/pages/upgrade-notes.adoc index d0d152ec..0a382da4 100644 --- a/docs/modules/upgrade-notes/pages/upgrade-notes.adoc +++ b/docs/modules/upgrade-notes/pages/upgrade-notes.adoc @@ -264,7 +264,7 @@ However, this can be overridden using the `SolrBackup.spec.location` option, whi Users should plan to keep their backup data in the shared volume if using a Volume Backup repository. If `SolrBackup.spec.persistence` is provided, it will be removed and written back to Kubernetes. + -Users using the S3 persistence option should try to use the xref:solr-backup:index.adoc#s3-backup-repositories[S3 backup repository] instead. This requires Solr 8.10 or higher. +Users using the S3 persistence option should try to use the xref:solr-backup:backup-repositories.adoc#s3-backup-repositories[S3 backup repository] instead. This requires Solr 8.10 or higher. * Default ports when using TLS are now set to 443 instead of 80. This affects `solrCloud.Spec.SolrAddressability.CommonServicePort` and `solrCloud.Spec.SolrAddressability.CommonServicePort` field defaulting. diff --git a/helm/solr/README.md b/helm/solr/README.md index 24428788..7c79c722 100644 --- a/helm/solr/README.md +++ b/helm/solr/README.md @@ -131,7 +131,7 @@ See the [documentation](https://solr.apache.org/guide/operator/latest/solr-cloud ### Addressability Options -See the [documentation](https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#addressability) for more information. +See the [documentation](https://solr.apache.org/guide/operator/latest/solr-cloud/addressability.html) for more information. If providing external addressability, then `method` and `domainName` must be provided. External addressability is disabled by default. @@ -210,7 +210,7 @@ Currently the Zookeeper Operator does not support ACLs, so do not use the provid ### TLS Options -See [documentation](https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#enable-tls-between-solr-pods) for more information. +See [documentation](https://solr.apache.org/guide/operator/latest/solr-cloud/tls.html#enable-tls-between-solr-pods) for more information. Solr TLS is disabled by default. Provide any of the following to enable it. @@ -238,7 +238,7 @@ Solr TLS is disabled by default. Provide any of the following to enable it. #### Client TLS Options -See [documentation](https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#enable-tls-between-solr-pods) for more information. +See [documentation](https://solr.apache.org/guide/operator/latest/solr-cloud/tls.html#enable-tls-between-solr-pods) for more information. Configure Solr to use a separate TLS certificate for client auth. diff --git a/helm/solr/values.yaml b/helm/solr/values.yaml index 1713cb1b..cbdb34fa 100644 --- a/helm/solr/values.yaml +++ b/helm/solr/values.yaml @@ -63,7 +63,7 @@ solrOptions: # Enable authentication for the Solr Cloud # More information can be found at: - # https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#authentication-and-authorization + # https://solr.apache.org/guide/operator/latest/solr-cloud/authentication-and-authorization.html security: {} # authenticationType: Basic # basicAuthSecret: secret-name @@ -74,7 +74,7 @@ solrOptions: # Specify how the SolrCloud should be addressable -# https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#addressability +# https://solr.apache.org/guide/operator/latest/solr-cloud/addressability.html addressability: podPort: 8983 commonServicePort: null @@ -234,7 +234,7 @@ zk: # Enable TLS between your SolrCloud nodes # More information can be found at: -# https://solr.apache.org/guide/operator/latest/solr-cloud/solr-cloud-crd.html#enable-tls-between-solr-pods +# https://solr.apache.org/guide/operator/latest/solr-cloud/tls.html#enable-tls-between-solr-pods solrTLS: {} # pkcs12Secret: # name: secret-name From a069983c9f93e6e87ad119acbc993d72f5720d15 Mon Sep 17 00:00:00 2001 From: Houston Putman Date: Mon, 8 Jun 2026 14:30:47 -0700 Subject: [PATCH 4/7] Rename SolrBackup doc pages and flatten backup nav Retitle the SolrBackup pages ("Managing Backups", "Repository Types") and list backup-repositories as a top-level nav entry rather than nested under the overview. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/modules/solr-backup/nav.adoc | 2 +- docs/modules/solr-backup/pages/backup-repositories.adoc | 2 +- docs/modules/solr-backup/pages/index.adoc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/modules/solr-backup/nav.adoc b/docs/modules/solr-backup/nav.adoc index 29674ca5..91bf7f15 100644 --- a/docs/modules/solr-backup/nav.adoc +++ b/docs/modules/solr-backup/nav.adoc @@ -17,4 +17,4 @@ .Solr Backups * xref:index.adoc[] -** xref:backup-repositories.adoc[] +* xref:backup-repositories.adoc[] diff --git a/docs/modules/solr-backup/pages/backup-repositories.adoc b/docs/modules/solr-backup/pages/backup-repositories.adoc index d5c51b06..cb4103b1 100644 --- a/docs/modules/solr-backup/pages/backup-repositories.adoc +++ b/docs/modules/solr-backup/pages/backup-repositories.adoc @@ -1,4 +1,4 @@ -= Supported Repository Types += Repository Types // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information diff --git a/docs/modules/solr-backup/pages/index.adoc b/docs/modules/solr-backup/pages/index.adoc index e0c431c4..e248c53f 100644 --- a/docs/modules/solr-backup/pages/index.adoc +++ b/docs/modules/solr-backup/pages/index.adoc @@ -1,4 +1,4 @@ -= Solr Backups += Managing Backups // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information From fbdbcef9db090114c32c3b8916892de0e13323dd Mon Sep 17 00:00:00 2001 From: Houston Putman Date: Mon, 8 Jun 2026 16:10:48 -0700 Subject: [PATCH 5/7] Don't build docs in smoketest --- Makefile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 23a3b0bd..3b903acb 100644 --- a/Makefile +++ b/Makefile @@ -227,8 +227,16 @@ smoke-test: build-release-artifacts ## Run a full smoke test on a set of local r .PHONY: check check: lint test ## Do all checks, lints and tests for the Solr Operator +# Antora's content aggregation is git-based, so the docs build only works in a +# git checkout. Include it in `lint` only when .git is present; this skips it +# for an unpacked release source tarball (e.g. `make check` during smoke tests). +DOCS_LINT := +ifneq ($(wildcard $(PROJECT_DIR)/.git),) +DOCS_LINT := check-docs +endif + .PHONY: lint -lint: check-zk-op-version check-mod vet check-format check-licenses check-manifests check-generated check-helm check-docs ## Lint the codebase to check for formatting and correctness +lint: check-zk-op-version check-mod vet check-format check-licenses check-manifests check-generated check-helm $(DOCS_LINT) ## Lint the codebase to check for formatting and correctness .PHONY: check-format check-format: ## Check the codebase to make sure it adheres to golang standards From 2c4f3f5cc194b735dbcd4823d5aabdcff59e5adc Mon Sep 17 00:00:00 2001 From: Houston Putman Date: Tue, 9 Jun 2026 11:26:37 -0700 Subject: [PATCH 6/7] Use version variable in docs --- .../getting-started/pages/local-tutorial.adoc | 14 ++++++------- .../pages/running-the-operator.adoc | 6 +++--- .../upgrade-notes/pages/upgrade-notes.adoc | 6 +++--- hack/release/version/propagate_version.sh | 21 +++---------------- 4 files changed, 16 insertions(+), 31 deletions(-) diff --git a/docs/modules/getting-started/pages/local-tutorial.adoc b/docs/modules/getting-started/pages/local-tutorial.adoc index 172f998a..c1da57b9 100644 --- a/docs/modules/getting-started/pages/local-tutorial.adoc +++ b/docs/modules/getting-started/pages/local-tutorial.adoc @@ -90,12 +90,12 @@ $ helm repo update Next, install the Solr Operator chart. Note this is using Helm v3, in order to use Helm v2 please consult the https://hub.helm.sh/charts/solr-operator/solr-operator[Helm Chart documentation]. This will install the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] by default. -[source,bash] +[source,bash,subs="verbatim,attributes"] ---- # Install the Solr & Zookeeper CRDs -$ kubectl create -f https://solr.apache.org/operator/downloads/crds/v0.10.0-prerelease/all-with-dependencies.yaml +$ kubectl create -f https://solr.apache.org/operator/downloads/crds/v{operator-version}/all-with-dependencies.yaml # Install the Solr operator and Zookeeper Operator -$ helm install solr-operator apache-solr/solr-operator --version 0.10.0-prerelease +$ helm install solr-operator apache-solr/solr-operator --version {operator-version} ---- _Note that the Helm chart version does not contain a `v` prefix, which the downloads version does. The Helm chart version is the only part of the Solr Operator release that does not use the `v` prefix._ @@ -125,10 +125,10 @@ After inspecting the status of you Kube cluster, you should see a deployment for To start a Solr Cloud cluster, we will create a yaml that will tell the Solr Operator what version of Solr Cloud to run, and how many nodes, with how much memory etc. -[source,bash] +[source,bash,subs="verbatim,attributes"] ---- # Create a 3-node cluster v9.10.0 with 300m Heap each: -helm install example-solr apache-solr/solr --version 0.10.0-prerelease \ +helm install example-solr apache-solr/solr --version {operator-version} \ --set image.tag=9.10.0 \ --set solrOptions.javaMemory="-Xms300m -Xmx300m" \ --set addressability.external.method=Ingress \ @@ -218,13 +218,13 @@ By default, the helm chart does not set the `replicas` field, so it is safe to u So we wish to upgrade to a newer Solr version: -[source,bash] +[source,bash,subs="verbatim,attributes"] ---- # Take note of the current version curl -s http://default-example-solrcloud.ing.local.domain/solr/admin/info/system | grep solr-i # Update the solrCloud configuration with the new version, keeping all previous settings and the number of nodes set by the autoscaler. -helm upgrade example-solr apache-solr/solr --version 0.10.0-prerelease \ +helm upgrade example-solr apache-solr/solr --version {operator-version} \ --reuse-values \ --set image.tag=9.10.0 diff --git a/docs/modules/getting-started/pages/running-the-operator.adoc b/docs/modules/getting-started/pages/running-the-operator.adoc index 6fdd47a9..93fc388a 100644 --- a/docs/modules/getting-started/pages/running-the-operator.adoc +++ b/docs/modules/getting-started/pages/running-the-operator.adoc @@ -37,10 +37,10 @@ $ helm repo update Next, install the Solr Operator chart. Note this is using Helm v3, use the official Helm chart documentation linked to above. This will install the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] by default. -[source,bash] +[source,bash,subs="verbatim,attributes"] ---- -$ kubectl create -f https://solr.apache.org/operator/downloads/crds/v0.10.0-prerelease/all-with-dependencies.yaml -$ helm install solr-operator apache-solr/solr-operator --version 0.10.0-prerelease +$ kubectl create -f https://solr.apache.org/operator/downloads/crds/v{operator-version}/all-with-dependencies.yaml +$ helm install solr-operator apache-solr/solr-operator --version {operator-version} ---- _Note that the Helm chart version does not contain a `v` prefix, which the downloads version does. The Helm chart version is the only part of the Solr Operator release that does not use the `v` prefix._ diff --git a/docs/modules/upgrade-notes/pages/upgrade-notes.adoc b/docs/modules/upgrade-notes/pages/upgrade-notes.adoc index 0a382da4..e0d5a26c 100644 --- a/docs/modules/upgrade-notes/pages/upgrade-notes.adoc +++ b/docs/modules/upgrade-notes/pages/upgrade-notes.adoc @@ -123,11 +123,11 @@ It is *strongly recommended* to use `kubectl create` or `kubectl replace`, inste When upgrading the Solr Operator, you may need to upgrade the https://github.com/pravega/zookeeper-operator[Zookeeper Operator] at the same time. If you are using the Solr Helm chart to deploy the Zookeeper operator, then you won't need to do anything besides installing the CRD's with dependencies, and upgrade the Solr Operator helm deployment. -[source,bash] +[source,bash,subs="verbatim,attributes"] ---- # Just replace the Solr CRDs and all CRDs it might depend on (e.g. ZookeeperCluster) -kubectl replace -f "http://solr.apache.org/operator/downloads/crds/v0.10.0-prerelease/all-with-dependencies.yaml" -helm upgrade solr-operator apache-solr/solr-operator --version 0.10.0-prerelease +kubectl replace -f "http://solr.apache.org/operator/downloads/crds/v{operator-version}/all-with-dependencies.yaml" +helm upgrade solr-operator apache-solr/solr-operator --version {operator-version} ---- _Note that the Helm chart version does not contain a `v` prefix, which the downloads version does. The Helm chart version is the only part of the Solr Operator release that does not use the `v` prefix._ diff --git a/hack/release/version/propagate_version.sh b/hack/release/version/propagate_version.sh index 2715bd0d..c1dbe37e 100755 --- a/hack/release/version/propagate_version.sh +++ b/hack/release/version/propagate_version.sh @@ -98,24 +98,9 @@ fi } > helm/solr/README.md.tmp && mv helm/solr/README.md.tmp helm/solr/README.md -# Update Docs (Remove this when docs are generated with versioning info) -{ - cat docs/modules/getting-started/pages/local-tutorial.adoc | \ - sed -E "s|(kubectl.+/crds/)[^/<]+|\1${VERSION}|g" | \ - sed -E "s|(helm.+--version )[^ <]+|\1${VERSION#v}|g" -} > docs/modules/getting-started/pages/local-tutorial.adoc.tmp && mv docs/modules/getting-started/pages/local-tutorial.adoc.tmp docs/modules/getting-started/pages/local-tutorial.adoc -{ - cat docs/modules/upgrade-notes/pages/upgrade-notes.adoc | \ - sed -E "s|(kubectl.+/crds/)[^/<]+|\1${VERSION}|g" | \ - sed -E "s|(helm.+--version )[^ <]+|\1${VERSION#v}|g" -} > docs/modules/upgrade-notes/pages/upgrade-notes.adoc.tmp && mv docs/modules/upgrade-notes/pages/upgrade-notes.adoc.tmp docs/modules/upgrade-notes/pages/upgrade-notes.adoc -{ - cat docs/modules/getting-started/pages/running-the-operator.adoc | \ - sed -E "s|(kubectl.+/crds/)[^/<]+|\1${VERSION}|g" | \ - sed -E "s|(helm.+--version )[^ <]+|\1${VERSION#v}|g" -} > docs/modules/getting-started/pages/running-the-operator.adoc.tmp && mv docs/modules/getting-started/pages/running-the-operator.adoc.tmp docs/modules/getting-started/pages/running-the-operator.adoc - -# Regenerate the operator Antora component descriptor (docs/antora.yml) from version/version.go +# Regenerate the operator Antora component descriptor (docs/antora.yml) from +# version/version.go. Docs pages reference the version via the {operator-version} +# attribute defined there, so no per-page version edits are needed. ./hack/docs/generate_antora_yaml.sh make manifests From 44622caba62eea046db23f806bbb50b4c7d7354e Mon Sep 17 00:00:00 2001 From: Houston Putman Date: Tue, 9 Jun 2026 11:30:10 -0700 Subject: [PATCH 7/7] Ref guide display version should start with a v --- docs/antora.yml | 2 +- hack/docs/generate_antora_yaml.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/antora.yml b/docs/antora.yml index a3b28649..2bce6388 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -20,7 +20,7 @@ name: operator title: Apache Solr Operator version: '0_10' -display_version: '0.10-prerelease' +display_version: 'v0.10-prerelease' prerelease: -prerelease start_page: ROOT:index.adoc nav: diff --git a/hack/docs/generate_antora_yaml.sh b/hack/docs/generate_antora_yaml.sh index 27ec6154..8cc1b3da 100755 --- a/hack/docs/generate_antora_yaml.sh +++ b/hack/docs/generate_antora_yaml.sh @@ -41,7 +41,7 @@ SEMVER="${RAW_VERSION#v}" IFS='.' read -r MAJOR MINOR PATCH <<< "${SEMVER}" ANTORA_VERSION="${MAJOR}_${MINOR}" -DISPLAY_VERSION="${MAJOR}.${MINOR}" +DISPLAY_VERSION="v${MAJOR}.${MINOR}" OPERATOR_VERSION="${SEMVER}" if [[ -n "${SUFFIX}" ]]; then