Secrets Management
Secrets Management for Kubernetes Workloads
Section titled “Secrets Management for Kubernetes Workloads”This guide explains how to securely manage and expose secrets to your Runway Kubernetes workloads (GKE and EKS). Runway uses GitLab’s Vault installation to securely store secrets, which are then automatically made available as environment variables or mounted as files to your containers.
Overview
Section titled “Overview”Runway uses a flexible approach to secrets management using Vault as the source of truth:
- Secrets are stored in Vault and referenced by your Runway configuration
- Multiple secret keys can be defined within a single Vault secret
- Secrets can be exposed to your container in two ways:
- As environment variables (each key becomes an environment variable)
- As mounted volumes (each key becomes a file; useful for file-based credentials)
Constraints
Section titled “Constraints”- Secret keys (which become environment variable names) should follow standard environment variable naming conventions (uppercase, letters/numbers/underscores only)
- When mounting secrets as volumes, the mount path must be an absolute path (starting with
/
)
Setup Access to Vault
Section titled “Setup Access to Vault”To manage secrets, you need access to the GitLab Vault installation. Follow these steps:
- Create an Access Request to provision an Okta group (Example)
- Create a Merge Request to set secret policy in Vault (Example)
When complete, service owners will only be granted access to secrets for their services.
Recommendation: Step 1 can take ~2 weeks for IT due to change management, so start the process as soon as you anticipate the need for secrets management.
Managing Secrets in Vault
Section titled “Managing Secrets in Vault”Adding Secrets
Section titled “Adding Secrets”-
Determine your Runway service ID
This is the ID defined in the Runway workload configuration file:
-
Log into Vault
If you do not have access to Vault, follow the instructions here. The path you need access to is
runway/env/$environment/service/$runway_service_id
. -
Go to your workload’s secrets path
Navigate to
runway/env/$environment/service/$runway_service_id
where$environment
is the environment (eitherstaging
orproduction
) and$runway_service_id
is your service ID. A service without any secrets will have a single empty secret called.placeholder
. -
Create a secret with multiple keys
Click on the
Create secret
button. AtPath for this secret
, enter a descriptive name for your secret collection (e.g.,env-vars
,database-credentials
, orgcp-service-account
).Under
Secret data
, add multiple key-value pairs:- Each key will become an environment variable name (when using
secretEnvFrom
) or a file name (when usingsecretVolumes
) - For environment variables, keys should be in uppercase and contain only letters, numbers, and underscores
- For file-based secrets, keys should be valid file names
- Values should be the actual secret values you want to expose
For example, for environment variables:
API_KEY: "your-api-key-here"DATABASE_PASSWORD: "your-database-password"JWT_SECRET: "your-jwt-secret"For file-based secrets (e.g., GCP service account):
credentials.json: '{"type": "service_account", "project_id": "..."}' - Each key will become an environment variable name (when using
-
Save the secret
Click
Save
to store your secret in Vault.
Secret Deployment Timing
Section titled “Secret Deployment Timing”Secrets added to Vault are available immediately as the External Secrets Operator has direct connectivity to Vault. You just need to configure secrets in your app.
Runway on Kubernetes deploys secrets separately from code deployments, unlike Runway on Cloud Run where they’re deployed together.
Since EKS clusters cannot directly access Vault, we use Terraform (provisioner) to synchronize secrets from Vault to AWS Secrets Manager. The provisioner automatically discovers and syncs all secrets under your workload path, so no additional configuration is needed — simply place your secrets in the correct path as outlined above.
Important considerations
- Secret synchronization depends on the provisioner’s Terraform plan/apply cycle, which may introduce deployment delays.
- For time-sensitive deployments, contact
#f_runway
to request manual provisioner pipeline execution.
Rotating Secrets
Section titled “Rotating Secrets”- Log into Vault and go to the secret path for your environment/service
- Click on the existing secret you wish to change
- Click on
Create new version
in the top right - Update the key-value pairs as needed
- Click
Save
The new secret values will be synchronized to your Kubernetes cluster according to the deployment schedule.
Removing Secrets
Section titled “Removing Secrets”- Log into Vault and go to the secret path for your environment/service
- Click on the
...
next to the secret, and choosePermanently delete
Alternatively, you can remove individual keys from a secret by editing it and deleting the specific key-value pairs.
Accessing Secrets in Your Application
Section titled “Accessing Secrets in Your Application”Configuring Secrets
Section titled “Configuring Secrets”First, you need to list all secrets your application needs to access in the Runway configuration file (.runway/${RUNWAY_SERVICE_ID}/gke-service.yaml
or .runway/${RUNWAY_SERVICE_ID}/eks-service.yaml
):
# Example Runway configurationexample_service_id: workloadSecrets: - name: env-vars - name: database-credentials targetName: k8s-secret-name refreshInterval: 5m - name: gcp-service-account
Option 1: Environment Variables
Section titled “Option 1: Environment Variables”To make secrets accessible as environment variables, add the secret to the secretEnvFrom
list in your configuration:
# Example Runway configurationexample_service_id: workloadSecrets: - name: env-vars - name: database-credentials targetName: k8s-secret-name refreshInterval: 5m secretEnvFrom: - env-vars - k8s-secret-name
This will inject all keys from the referenced secrets as environment variables in your container.
Once deployed, all keys from the referenced secrets will be available as environment variables in your container. You can access them using your programming language’s standard method for reading environment variables.
Option 2: Volume Mounts
Section titled “Option 2: Volume Mounts”To mount secrets as files in your container filesystem, use the secretVolumes
configuration.
This is particularly useful for file-based credentials like GCP service accounts, SSL certificates, or configuration files:
# Example Runway configurationexample_service_id: workloadSecrets: - name: gcp-service-account - name: ssl-certificates
# Mount secrets as files secretVolumes: - name: gcp-service-account path: /secrets/gcp - name: ssl-certificates path: /etc/ssl/certs/custom
# Point Google APIs to the service account credentials spec: services: app: environment: GOOGLE_APPLICATION_CREDENTIALS: '/secrets/gcp/credentials.json'
With this configuration:
- The
gcp-service-account
secret will be mounted at/secrets/gcp
- Each key in the secret becomes a file in that directory
- For example, if the secret contains a key
credentials.json
, it will be available at/secrets/gcp/credentials.json
- Files are mounted with read-only permissions (mode 0400) for security
- The
GOOGLE_APPLICATION_CREDENTIALS
is added to theapp
service to configure Google APIs to use the credentials
Using Both Methods Together
Section titled “Using Both Methods Together”You can use both environment variables and volume mounts for different secrets in the same application:
# Example combining both methodsexample_service_id: workloadSecrets: - name: env-vars - name: database-credentials - name: gcp-service-account
# Expose as environment variables secretEnvFrom: - env-vars - database-credentials
# Mount as files secretVolumes: - name: gcp-service-account path: /secrets/gcp
Best Practices
Section titled “Best Practices”- Group related secrets: Use descriptive names for your secret collections and group related secrets together
- Choose the right method:
- Use environment variables (
secretEnvFrom
) for simple key-value configurations - Use volume mounts (
secretVolumes
) for file-based credentials or complex configuration files
- Use environment variables (
- Limit access: Only grant Vault access to team members who need to manage secrets
- Use secure values: Generate strong, random values for secrets
- Rotate regularly: Establish a routine schedule for rotating sensitive credentials
- Follow naming conventions for secret keys:
- For environment variables: use uppercase with underscores (e.g.,
DATABASE_PASSWORD
) - For volume mounts: use file names (e.g.
credentials.json
)
- For environment variables: use uppercase with underscores (e.g.,