Managed Backends¶
When you set managed: true on a backend spec, the operator provisions the database or cache cluster for you. This guide covers what is created, the topology options, and how readiness works.
Managed PostgreSQL (Percona PG Operator)¶
The operator provisions a PerconaPGCluster via the Percona PG Operator (pgv2.percona.com).
Standalone topology (development / single-instance)¶
The operator creates a minimal PerconaPGCluster named {instance-name}-pg. Suitable for non-production or development deployments.
HA topology (production)¶
spec:
postgres:
managed: true
topology: ha
pgbouncer: true
nodes: 3 # optional, defaults to 3 for HA
topology: haprovisions aPerconaPGClusterwith multiple replicas.pgbouncer: trueenables a PgBouncer connection pooler sidecar, strongly recommended for production GitLab loads.nodessets the number of PostgreSQL replicas (defaults to the profile value, or 3 for HA).
The production profile sets ha topology and pgbouncer: true by default:
# examples/profile-production.yaml
apiVersion: k8s.bnerd.com/v1alpha1
kind: GitlabProfile
metadata:
name: production
spec:
defaults:
postgres:
topology: ha
nodes: 3
redis:
topology: ha
elasticsearch:
nodes: 3
backupSchedule: "30 2 * * *"
What the operator creates¶
| Resource | Name | Notes |
|---|---|---|
PerconaPGCluster |
{instance}-pg |
No owner reference — survives instance deletion |
| PgUser (inside Percona) | gitlab |
Percona creates the user and emits a Secret |
| Credentials Secret | {instance}-pg-pguser-gitlab |
Created by Percona; consumed by the operator |
Readiness¶
The operator polls the PerconaPGCluster status and checks for a ready primary. While waiting, the instance stays in phase: Provisioning with condition Ready=False / PostgresProvisioning. Once ready, the operator extracts the primary hostname and proceeds to compose Helm values.
# Check PG cluster status
kubectl get perconapgcluster {instance}-pg -n {namespace}
kubectl describe perconapgcluster {instance}-pg -n {namespace}
Managed Redis (OT-Container-Kit redis-operator)¶
The operator provisions Redis CRs via the OT-Container-Kit redis-operator (redis.redis.opstreelabs.in).
Standalone topology¶
Creates a single-node Redis CR named {instance}-redis.
HA topology (Redis Sentinel)¶
Creates a RedisReplication and a RedisSentinel CR for high-availability quorum. The Sentinel endpoint is passed to the GitLab chart. The operator checks that both the main StatefulSet ({instance}-redis) and the sentinel StatefulSet ({instance}-redis-sentinel) have at least one ready replica.
What the operator creates¶
| Resource | Name | Topology |
|---|---|---|
Redis |
{instance}-redis |
standalone |
RedisReplication |
{instance}-redis |
ha |
RedisSentinel |
{instance}-redis |
ha (alongside RedisReplication) |
All Redis CRs carry no owner reference to the GitlabInstance and are retained on deletion.
Readiness¶
OT-Container-Kit v0.25.0 ships an empty RedisStatus struct; status.readyReplicas on the Redis CR is pruned by the API server. The operator falls back to inspecting the underlying StatefulSet ({instance}-redis, plus {instance}-redis-sentinel for HA) to determine readiness. This is fully transparent — no configuration is needed.
# Check Redis StatefulSets
kubectl get statefulsets -n {namespace}
kubectl describe statefulset {instance}-redis -n {namespace}
Managed Elasticsearch (ECK — EE only)¶
Elasticsearch is provisioned only for Enterprise Edition deployments with a valid license.
EE + licenseSecret both required
Setting elasticsearch.managed: true on a CE instance or on an EE instance without spec.licenseSecret has no effect — the Elasticsearch block is silently omitted from the composed Helm values.
What the operator creates¶
| Resource | Name | Notes |
|---|---|---|
ECK Elasticsearch |
{instance}-es |
No owner reference — retained on deletion |
| ECK credentials Secret | {instance}-es-elastic-user |
Created by ECK; key elastic |
The operator passes global.appConfig.elasticsearch.enabled: true, url: https://{instance}-es-es-http.{namespace}.svc.cluster.local:9200, and username: elastic to the GitLab chart.
Advanced Search index bootstrap is a manual step
The operator wires the Elasticsearch connection to the chart. The index creation (gitlab:elastic:* tasks) and enabling Advanced Search in GitLab Admin → Settings → Advanced Search must be completed manually after the first deploy, using the ECK-generated credentials Secret ({instance}-es-elastic-user, key elastic).
Readiness¶
The operator polls the ECK Elasticsearch status. While the cluster is initialising, the instance stays in phase: Provisioning with condition ElasticsearchProvisioning. ECK typically takes 3–5 minutes to provision a 3-node cluster.
kubectl get elasticsearch {instance}-es -n {namespace}
kubectl describe elasticsearch {instance}-es -n {namespace}
The full EE example¶
The following example from examples/gitlabinstance-ee-full.yaml shows all three managed backends in a production topology:
apiVersion: k8s.bnerd.com/v1alpha1
kind: GitlabInstance
metadata:
name: my-gitlab-ee
namespace: my-gitlab-ee
spec:
version: "17"
edition: ee
licenseSecret: my-gitlab-ee-license
profile: production
domains:
gitlab: git.example.com
registry: registry.example.com
kas: kas.example.com
pages: pages.example.com
postgres:
managed: true
topology: ha
pgbouncer: true
redis:
managed: true
topology: ha
elasticsearch:
managed: true
nodes: 3
objectStorage:
credentialsSecret: my-gitlab-ee-s3-credentials
smtp:
credentialsSecret: my-gitlab-ee-smtp-credentials
backups:
schedule: "30 2 * * *"
objectStorage:
credentialsSecret: my-gitlab-ee-s3-credentials
placement:
nodeSelector:
dedicated: my-gitlab-ee
tolerations:
- key: dedicated
operator: Equal
value: my-gitlab-ee
effect: NoSchedule