Overview
Elasticsearch is a distributed search and analytics engine built on Apache Lucene. This template deploys an Elasticsearch 8.17.0 cluster whose nodes discover each other and elect a master automatically, a Kibana (on by default) workload for querying data and managing indices, and optional incremental snapshot backups to AWS S3 or GCS driven by Elasticsearch’s built-in Snapshot Lifecycle Management (SLM). The cluster runs with X-Pack security disabled: there is no username, password or TLS anywhere in the template, and the only access control is theinternal_access setting on each workload.
cpln workload exec, cpln logs and cpln helm uninstall all run against that GVC, and uninstalling the release never deletes it.What Gets Created
Prerequisites
None for a default install. Backups are optional and need a bucket and a Control Plane cloud account (plus an IAM policy on AWS) before they can be enabled. The per-provider steps are under Backing Up.Installation
A default install needs no--set values:
UI
CLI
Terraform
Pulumi
Configuration
Cluster
replicas value. Three nodes survive the loss of one. jvmHeap is not derived from resources — if you raise resources.maxMemory, decide separately whether to raise the heap, and keep it at roughly half the memory limit so the rest is available to the filesystem cache.
Resources
Volume Set
volumeset.capacity GiB. With autoscaling enabled, a volume grows by scalingFactor whenever its free space drops below minFreePercentage, up to maxCapacity.
Multi-Zone
Internal Access
workload-list, remember to list the template’s own consumers: //gvc/GVC_NAME/workload/RELEASE_NAME-kibana when Kibana is enabled, and //gvc/GVC_NAME/workload/RELEASE_NAME-backup-setup when backups are enabled — both reach Elasticsearch over this port.
Kibana
RELEASE_NAME-elasticsearch.GVC_NAME.cpln.local:9200 and has its own kibana.internal_access block with the same three options as Elasticsearch.
Backup
Connecting
Both workloads are reachable only from inside the GVC by default; external inbound traffic is closed and there is no public endpoint. Usecpln port-forward to reach either from your machine.
Operations
Backing Up
Backups are incremental Elasticsearch snapshots written straight to S3 or GCS by therepository-s3 and repository-gcs modules bundled in the official image — no separate backup image runs. Snapshot Lifecycle Management (SLM) takes them on backup.schedule and prunes them by backup.retention.
When backup.enabled: true, the template adds the RELEASE_NAME-backup-setup workload. It waits for the cluster to answer /_cluster/health, registers the snapshot repository as backup-repo, verifies the repository can reach the bucket, and creates an SLM policy named automated-snapshots that snapshots every index except Elasticsearch’s internal and history indices with include_global_state: false. The job is idempotent, so it is safe for it to run more than once. Watch it finish:
Backup Configuration Complete!, remove the job to free its resources:
backup.schedule uses Quartz cron format with 6 fields (seconds, minutes, hours, day-of-month, month, day-of-week), not the 5-field cron most schedulers use. "0 0 2 * * ?" runs daily at 02:00 UTC; the ? is required in day-of-week when day-of-month is set.AWS S3
Create the bucket
backup.aws.bucket to its name and backup.aws.region to its region.Create or pick a cloud account
backup.aws.cloudAccountName to its name.Create a bucket-scoped IAM policy
YOUR_BUCKET_NAME. Both resource ARNs are required: s3:ListBucket and s3:GetBucketLocation authorize against the bucket itself, the rest against its objects.backup.aws.policyName to the policy’s name. The template attaches it, together with the platform’s cpln-connector policy, to the release identity.GCS
Create the bucket
backup.gcp.bucket to its name.Create or pick a cloud account
backup.gcp.cloudAccountName to its name.Grant storage access
roles/storage.objectAdmin on the bucket to the release identity.Manual Snapshots
With a port-forward to Elasticsearch open (cpln port-forward RELEASE_NAME-elasticsearch 9200:9200 --gvc GVC_NAME), you can trigger a snapshot or inspect the repository directly:
Restoring a Backup
backup-repo). They have not been exercised end to end against this template. Rehearse a restore on a non-production release before you depend on it.cpln port-forward RELEASE_NAME-elasticsearch 9200:9200 --gvc GVC_NAME), then list what is available:
backup.enabled: true and the same bucket, prefix and provider as the lost cluster. The setup job registers the same repository, so the old snapshots become visible. Then restore everything except Elasticsearch’s internal indices:
Upgrading from 1.0.0
Version 1.0.1 removes the AWS managed policyaws::ReadOnlyAccess from the backup identity. That policy granted read access to every bucket in your AWS account and contained no write actions, so it never carried the backup itself — but it was silently supplying any read action your own bucket-scoped policy happened to omit. The identity now carries cpln-connector and your backup.aws.policyName policy only.
Before upgrading an AWS-backed release, compare your IAM policy with the full action list under Backing Up and add anything missing. If it already matches, no action is needed. Releases without backups, and GCS-backed releases, are unaffected.
Scaling and Availability
Scaling up. Raisereplicas to the next odd number and run cpln helm upgrade. The new nodes join the cluster automatically and Elasticsearch begins rebalancing shards onto them.
Changing replicas, jvmHeap, resources or image restarts the Elasticsearch nodes. Expect the cluster to report yellow while shards recover after a restart; reads and writes keep working as long as a quorum of nodes is up. With multiZone.enabled: true, replicas are spread across availability zones so the loss of a zone does not cost the quorum.
Troubleshooting
Install or upgrade fails with 'replicas must be a positive odd number'
Install or upgrade fails with 'replicas must be a positive odd number'
cpln helm install or cpln helm upgrade stops before creating anything with replicas must be a positive odd number, got: 4.Cause: The template validates replicas at render time because Elasticsearch needs an odd number of master-eligible nodes to elect a master.Fix: Set replicas to 1, 3, 5 or another odd number and rerun the command.Backup setup job logs 'ERROR: Failed to register repository'
Backup setup job logs 'ERROR: Failed to register repository'
cpln logs '{gvc="GVC_NAME", workload="RELEASE_NAME-backup-setup"}' --limit 50 --since 10m shows ERROR: Failed to register repository (HTTP 500) followed by the Elasticsearch response body.Cause: Elasticsearch could not write to the bucket. On AWS the usual reasons are a wrong backup.aws.bucket or backup.aws.region, an IAM policy missing one of the actions listed under Backing Up, or a cloud account not yet linked. On GCP it is usually a missing Storage Admin role. Right after enabling backups on a running cluster the same error appears for a few minutes while the nodes pick up the new configuration.Fix: Read the response body printed under the error — Elasticsearch names the failing permission or bucket. Correct the IAM policy or value, and run cpln helm upgrade if a value changed. The job restarts on its own and succeeds once the bucket is reachable.Restore is refused because an open index with the same name already exists
Restore is refused because an open index with the same name already exists
_restore call returns Cannot restore index [MY_INDEX] because an open index with same name already exists in the cluster.Cause: Elasticsearch never overwrites an open index during a restore.Fix: Either close or delete the existing index before restoring, or restore under a new name:Elasticsearch containers restart with OOMKilled
Elasticsearch containers restart with OOMKilled
OOMKilled:jvmHeap is too close to resources.maxMemory. The JVM heap is only part of what Elasticsearch uses; the rest of the limit must stay free for off-heap memory and the filesystem cache.Fix: Lower jvmHeap to roughly half of resources.maxMemory, or raise resources.maxMemory, and run cpln helm upgrade.Kibana shows 'Kibana server is not ready yet'
Kibana shows 'Kibana server is not ready yet'
Kibana server is not ready yet.Cause: Kibana cannot reach RELEASE_NAME-elasticsearch.GVC_NAME.cpln.local:9200. Either the cluster is still starting — nodes take a minute or two to become ready — or internal_access.type is workload-list and //gvc/GVC_NAME/workload/RELEASE_NAME-kibana is not in internal_access.workloads.Fix: Wait for the Elasticsearch deployment to report ready, then reload. If it stays unready, add the Kibana workload to internal_access.workloads and run cpln helm upgrade.Important Notes
- There is no authentication. X-Pack security is disabled, so anything
internal_accessadmits has full admin access to every index. Keepinternal_accessas narrow as your deployment allows. replicasmust be odd (1, 3, 5, …) or the chart refuses to render; an even count cannot hold a master quorum.jvmHeapdoes not followresources.maxMemory. Raising the memory limit does not raise the heap; setting the heap above about half the limit gets the node OOM-killed.- Snapshot before scaling down. Elasticsearch does not evacuate shards from nodes that are about to be removed.
backup.scheduleis 6-field Quartz cron, not 5-field cron, and needs?in the day-of-week field when day-of-month is set.- The AWS IAM policy needs both bucket ARNs —
arn:aws:s3:::BUCKETandarn:aws:s3:::BUCKET/*. - Enabling backups on a running cluster takes several minutes to settle; the setup job retries until every node can reach the bucket.