Getting Started
This guide walks you through onboarding a service to Runway for GitLab Dedicated. On Dedicated, your service is a modular feature (or module): a Helm chart that is deployed into the Kubernetes cluster of every Dedicated tenant that enables it, together with the AWS infrastructure it needs.
How it works
Section titled “How it works”Unlike the GKE and EKS runtimes, Runway does not deploy your service from your project’s pipeline. Releasing and deploying are separate steps:
- Release. When you tag a release, your project’s pipeline builds and publishes the Helm chart with Fairway, and creates an entry for the release in the Module Catalog. The entry records the Helm chart, its default values, and the infrastructure the module needs.
- Provision and deploy. For each tenant, the Tenant Model decides whether the
module is enabled, which version runs, and the tenant-specific settings. Dedicated’s Instrumentor runs two Runway
actions, each with only the permissions it needs:
- the provision action (
runwayctl dedicated provision) creates the AWS infrastructure in the tenant’s AWS account, such as S3 buckets and RDS instances; - the deploy action (
runwayctl dedicated deploy) deploys the module version from the Module Catalog into the tenant’s Kubernetes cluster.
- the provision action (
Before you begin
Section titled “Before you begin”Your service repository needs the same prerequisites as for the Kubernetes runtimes. See Kubernetes: Before you begin for details:
- Container image pipeline: Your repository builds and pushes container images to the GitLab Container Registry.
- Semantic versioning: Include the
semantic-releasejob. Every release creates a new module version in the Module Catalog. Your repository must have at least one tag matchingvX.Y.Z.
Step 1: Add your service to the workload inventory
Section titled “Step 1: Add your service to the workload inventory”The workload inventory registers your service with Runway. Runway then creates the deployment project that publishes your releases to the Module Catalog.
-
Choose a Runway service ID: Tenants use this ID as the module name, so choose it with care. It must be 1 to 53 lowercase letters, digits, and hyphens, and must start and end with a letter or digit. It’s also used as the Kubernetes namespace on the tenant’s cluster. If you also deploy to GKE or EKS, use a separate service ID for each runtime, for example
example-service-dedicated. -
Add your service to
config/runtimes/dedicated/workloads.ymlin the provisioner:- runway_service_id: example-service-dedicatedproject_id: 12345678groups:- gitlab-org/your-groupDedicated workloads have no
regions: the Tenant Model decides where a module runs. -
Create a merge request and assign it to a Runway team member (see
CODEOWNERS).
Step 2: Configure job token permissions
Section titled “Step 2: Configure job token permissions”The deployment project downloads the catalog entry from your project’s pipeline.
- Navigate to your project’s Settings → CI/CD → Job token permissions.
- In the CI/CD job token allowlist section, add
gitlab-com/gl-infra/platform/runway/deployments/<runway-service-id>. - Set Permission configuration to Default permissions.
Step 3: Create the Runway directory
Section titled “Step 3: Create the Runway directory”Dedicated uses the Fairway manifest and the values files of the Runway v2 layout, with a runway/v3 module manifest, module.yaml, in place of the deployment*.yaml Runway manifest.
If your service already runs on GKE with Runway v2, add the Dedicated files to the existing directory:
values.yaml is shared, while module.yaml and values-dedicated.yaml only apply to Dedicated.
.runway/├── fairway.yaml # chart definition, including infrastructure dependencies├── module.yaml # Runway v3 manifest for the Dedicated service ID├── values.yaml # Helm values shared by all runtimes└── values-dedicated.yaml # Helm values for Dedicated (optional)Fairway manifest
Section titled “Fairway manifest”fairway.yaml defines your service’s Helm chart.
The v2 migration guide and the
Fairway service owner guide
describe it in detail.
Declare the infrastructure your module needs under spec.infrastructure. Each dependency has a presence:
| Presence | Meaning |
|---|---|
REQUIRED |
The module doesn’t work without it. The module manifest must enable a default for it. |
OPTIONAL |
The module works with or without it. Tenants may configure it. |
UNUSED |
The module doesn’t use it (the default). Tenants must not configure it. |
apiVersion: fairway/v1kind: FairwayManifestmetadata: name: example-frontendspec: image: "registry.gitlab.com/gitlab-com/gl-infra/platform/runway/example-service" command: ["/bin/frontend"] containerPort: 8080
infrastructure: postgresql: presence: OPTIONAL object_store: presence: REQUIREDThe presence is copied into the Module Catalog entry. When a tenant deploys the module, Runway checks the tenant’s buckets and instances against it. The S3, RDS, and ElastiCache pages describe each dependency.
Module manifest
Section titled “Module manifest”module.yaml is the Runway manifest of your module on Dedicated, and is required.
Its metadata.name is your Dedicated service ID: any file named module.yaml or module-<suffix>.yaml works, and Runway picks the one whose metadata.name is the Runway service ID.
It sets the default configuration of the buckets and instances your module uses, keyed by a logical name.
Tenants override these defaults in the Tenant Model.
A REQUIRED dependency needs an enabled default, and an UNUSED one must have none.
If your module talks to another module on the tenant, declare the peer under spec.connections, and Runway delivers the credentials for that connection to your pods.
If your module needs a key that no other system owns, such as an encryption key, declare it under spec.secrets, and Runway generates it and delivers it to your pods.
See the Module Manifest reference, Connections, and Secrets.
apiVersion: runway/v3kind: RunwayManifestmetadata: name: example-service-dedicatedspec: infrastructure: s3: uploads: defaultConfig: {}The chart is published to your project’s container registry under /chart/<fairway-manifest-name>, and the Module Catalog entry records it from there, so the module manifest doesn’t name it.
Helm values
Section titled “Helm values”Runway merges the default Helm values of each release in this order. Later layers override earlier ones: objects are merged, lists are replaced.
- Fairway’s built-in defaults.
spec.valuesfromfairway.yaml.values.yaml.values-dedicated.yaml.- Any files listed in the module manifest’s
spec.extraValueFiles. File names can use{{ .Runtime }}, which isdedicated.
The result is stored in the Module Catalog entry. Tenants can override any of it with
values_override.helm.values in the Tenant Model.
Helm Values describes the files, the merge, and the templates for tenant-specific
values such as the GitLab instance’s domain.
Step 4: Add the CI components
Section titled “Step 4: Add the CI components”How you set up CI depends on where the Helm chart is deployed.
Dedicated only
Section titled “Dedicated only”Include the release-platform
component from common-ci-tasks with runtime: dedicated. It builds and publishes the Fairway chart, creates the
catalog entry, and triggers the deployment project.
include: inputs: runway_service_id: example-service-dedicated runtime: dedicatedIf your Runway directory is not .runway, set runway_dir, for example runway_dir: .runway/frontend.
GitLab.com and Dedicated
Section titled “GitLab.com and Dedicated”A modular feature often runs on GitLab.com (GKE) and is published for Dedicated, using the same Helm chart.
release-platform builds the chart and deploys it to one runtime, so include it for GKE, and add runwayctl’s
kubernetes-v2-service component for Dedicated. Both use the chart that release-platform builds.
.runway/├── fairway.yaml # one chart for both runtimes├── deployment-gke.yaml # GKE, metadata.name: example-service-gke├── module.yaml # Dedicated, metadata.name: example-service-dedicated├── values.yaml # shared by both runtimes├── values-staging.yaml # GKE staging (optional)├── values-production.yaml # GKE production (optional)└── values-dedicated.yaml # Dedicated (optional)include: # Builds and publishes the Helm chart, and deploys it to GKE. inputs: runway_service_id: example-service-gke runtime: gke runway_version: v4.100.0
# Publishes the same Helm chart to the Module Catalog for Dedicated. inputs: runway_service_id: example-service-dedicated runtime: dedicated runway_version: v4.100.0 runway_dir: .runway fairway_manifest: .runway/fairway.yaml stage: deployEach service ID needs its own workload inventory entry, in
config/runtimes/gke/workloads.yml and config/runtimes/dedicated/workloads.yml respectively, and its own
deployment project in the job token allowlist.
Step 5: Release
Section titled “Step 5: Release”Open a merge request with the new .runway/ files and the CI change. The merge request pipeline runs in dry-run mode:
it creates the catalog entry and triggers the deployment project, but doesn’t publish anything.
Use it to check that your manifests and values are valid.
After the merge request is merged, a feat: or fix: commit triggers semantic-release. The tag pipeline:
- publishes the Helm chart,
- creates the catalog entry (
runwayctl catalog create), and - triggers the deployment project, which adds the entry to the
Module Catalog as
data/<runway-service-id>/<version>.yaml.
Catalog entries are never changed or deleted: every release adds a new version.
Step 6: Enable the module on a tenant
Section titled “Step 6: Enable the module on a tenant”A module runs on a tenant once the tenant’s Tenant Model enables it:
{ "modular_features": { "modules": { "example-service-dedicated": { "enabled": true, "version": "v1.25.0" } } }}The Tenant Model reference lists every option, including the infrastructure and Helm value overrides.