Skip to content

Memorystore for Redis

Runway can provision a managed Memorystore for Redis instance for your GKE workload and wire the connection details into your service automatically. Runway owns the lifecycle of the instance and its credentials: it provisions the instance in the Runway GCP projects, writes the address and auth string to Vault, and injects the connection secret into your Helm chart. You do not create or manage the secret yourself.

This guide assumes you already have a working Runway for Kubernetes deployment. If you do not, start with Getting Started first.

Provisioning Redis touches four places. Three of them describe the instance and grant access to it; the fourth tells your deployment to consume it:

  1. Declare the dependency in your Fairway manifest — your chart requires (or optionally accepts) Redis.
  2. Define the instance in the provisioner (memorystore.yml) — sizing, version, region, and a unique identifier.
  3. Grant your workload access in the provisioner (workloads.yml) — references the instance by its globally unique name.
  4. Reference the instance from your Runway manifest (deployment.yaml) — references it by its identifier.

The name and the identifier are two different handles for the same instance, used in different files. Keep both straight: workloads.yml uses the name, the Runway manifest uses the identifier.

Step 1: Declare the dependency in your Fairway manifest

Section titled “Step 1: Declare the dependency in your Fairway manifest”

In your Fairway manifest, declare that your chart needs a Redis connection. This only states whether Redis is required or optional — it does not say how to connect.

fairway manifest
kind: FairwayManifest
apiVersion: fairway/v1
metadata:
name: example-service
spec:
# ...
infrastructure:
redis:
presence: REQUIRED

presence accepts:

  • REQUIRED — Helm refuses to install the chart unless a Redis connection is configured. Use this when your service cannot run without Redis.
  • OPTIONAL — the chart installs whether or not Redis is configured. Your application must handle the absence gracefully (see Connecting from your application).

File an MR to add your instance to config/runtimes/gke/memorystore.yml in the Runway provisioner:

config/runtimes/gke/memorystore.yml
- name: runway-redis-example-service-gke
identifier: MAIN
provider: GCP
engine: REDIS
instance_type: CACHE
redis_version: REDIS_7_2
tier: STANDARD_HA
memory_size_gb: 4
regions:
- us-east1
read_replicas_enabled: false
labels:
owner_email_handle: my-team
department: eng-infra
department_group: eng-infra-my-group
product_category: my-category

One instance is provisioned per region and per environment (staging and production), all from this single entry. The instances live in the gitlab-runway-staging and gitlab-runway-production GCP projects.

FieldRequiredAllowed valuesNotes
nameyesstring matching ^runway-redis-.*Globally unique. The runway-redis- prefix is enforced. Referenced from workloads.yml and used as the type label in metrics.
identifieryes^[A-Z0-9_]{1,20}$Short, app-unique handle referenced from the Runway manifest. Free-form, but conventional values are MAIN, CACHE, and SIDEKIQ.
redis_versionyesREDIS_7_0, REDIS_7_2REDIS_7_2 is recommended for new instances. On the BASIC tier, upgrading incurs downtime; downgrading recreates the instance.
regionsyesone or more valid Runway GKE regionsShould match the regions of the workload that consumes it. See the GKE regions list.
instance_typeyesCACHEOnly CACHE is supported today.
provideryesGCPOnly GCP is supported today.
engineyesREDISMust be set explicitly. Only REDIS is supported today.
memory_size_gbyesnumber (GiB)Instance memory size. Size this for your working set plus headroom; ask in #f_runway if unsure.
tiernoBASIC, STANDARD_HADefaults to BASIC (single node, no HA). Use STANDARD_HA for a highly available primary/replica pair — recommended for anything user-facing.
read_replicas_enablednobooleanDefaults to false. Only valid on STANDARD_HA.
replica_countno15Only when read_replicas_enabled: true (default 2). Ignored when read replicas are disabled.
labelsyesobjectRequired infrastructure labels — owner_email_handle, department, department_group, product_category. See the Infrastructure Standards.

Create the MR and assign it to a Runway team member (see CODEOWNERS), and ensure the pipeline passes before requesting review.

In config/runtimes/gke/workloads.yml, add a redis_instances key to your workload entry, referencing the instance by its name (not its identifier):

config/runtimes/gke/workloads.yml
- runway_service_id: example-service-gke
project_id: 12345678
regions:
- us-east1
redis_instances:
- runway-redis-example-service-gke

This grants the workload’s service account the access it needs to read the connection secret.

Step 4: Reference the instance from your Runway manifest

Section titled “Step 4: Reference the instance from your Runway manifest”

In your Runway manifest (deployment.yaml), reference the instance by its identifier (not its name) under spec.infrastructure.redis:

.runway/example-service-gke/deployment.yaml
apiVersion: runway/v2
kind: RunwayManifest
metadata:
name: example-service-gke
spec:
chartRef: "oci://registry.gitlab.com/gitlab-com/gl-infra/platform/runway/example-service/chart/example-service-gke:{% .ChartVersion %}"
infrastructure:
redis:
- identifier: MAIN

That is all that is required. On deployment, Runway resolves the identifier to the provisioned instance for the current environment and region, and injects the connection secret into your chart (see below).

The manifest entry only takes identifier. Connection tuning — timeouts, pool sizing, logical db, Prometheus metric namespace, and so on — is configured on the infrastructure.redis block of your chart’s Helm values. The full set of tunable fields is documented in the Fairway Redis schema.

Two fields are managed by Runway and should be left alone:

  • secretRef is injected by Runway. If you set it yourself, Runway overwrites it and logs a warning.
  • clientName defaults to the instance identifier (used in logs and as a constant Prometheus label). Override it only if you have a reason to.

You should not need to touch any of this, but for reference:

  1. The provisioner writes the connection details to Vault (mount runway) at platform/<runway_service_id>/redis/<identifier>/<environment>/<region>. The secret has two fields: addrs (the host:port of the instance) and password (the auth string).
  2. On deployment, Runway creates an ExternalSecret that syncs that Vault secret into a Kubernetes Secret in your namespace.
  3. Runway injects infrastructure.redis.secretRef into your Helm values, pointing at that Secret, so the generated chart reads the address and password from it at runtime.

The result is that your application receives a fully configured Redis connection without you handling any credentials directly.

Use redis.New() from LabKit. It reads the injected infrastructure config, resolves the address and auth from the secret, and returns an instrumented client — you do not parse any environment variables or secret files yourself.

import (
"errors"
"gitlab.com/gitlab-org/labkit/v2/infrastructure"
"gitlab.com/gitlab-org/labkit/v2/redis"
)
client, err := redis.New(ctx,
redis.WithRegisterer(reg), // Prometheus metrics
redis.WithTracer(tracer), // OpenTelemetry spans
redis.WithLogger(logger), // structured per-command logs
)
if err != nil {
return err
}
// client implements app.Component: call client.Start(ctx) during startup to
// verify connectivity, and client.Shutdown(ctx) on teardown. Use
// client.Redis() to obtain the underlying go-redis UniversalClient for commands.

redis.New() returns a client that transparently handles single-node, Sentinel, and Cluster topologies through one interface, so your code does not change if the underlying instance type does.

  • Review the Memorystore schema for the authoritative field definitions.
  • See Secrets management for other secret needs your service may have.
  • Ask the Runway team in #f_runway for help sizing your instance or troubleshooting a deployment.