GitLab-CI Kubernetes Variables aren't set?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
When GitLab CI/CD variables are not available in Kubernetes deployments, the most common causes are: the variable is not exported to the Kubernetes runner environment, envsubst or variable substitution is not applied to manifest files, or the variable scope is restricted to a specific environment or branch. GitLab CI variables are available as environment variables in the runner shell, but they do not automatically propagate into Kubernetes manifests. You must explicitly inject them using envsubst, Helm values, or Kubernetes secrets.
How GitLab CI Variables Work
GitLab CI variables are environment variables in the runner's shell. They are not automatically substituted inside files referenced by kubectl apply. The Kubernetes API receives the literal text $APP_VERSION, not the value.
Fix 1: Use envsubst
envsubst replaces ${VAR} placeholders with environment variable values before passing the manifest to kubectl.
Fix 2: Use sed for Targeted Replacement
Fix 3: Use Helm Values
Fix 4: Create Kubernetes Secrets from CI Variables
Variable Scope Issues
In GitLab Settings > CI/CD > Variables, each variable can be scoped to a specific environment (staging, production) or branch (main, develop). If a variable appears empty, check its scope settings.
Debugging Missing Variables
Protected and Masked Variables
Common Pitfalls
- Expecting kubectl manifests to auto-substitute variables:
kubectl apply -f deploy.yamlreads the file literally.${APP_VERSION}in the YAML is treated as a string, not expanded. Useenvsubst < deploy.yaml | kubectl apply -f -to substitute variables before applying. - Variable scoped to wrong environment or branch: GitLab CI/CD variables can be restricted to specific environments (production, staging) or protected branches. A variable set for "production" is empty in the staging pipeline. Check Settings > CI/CD > Variables and verify the scope matches your deployment target.
- Protected variables empty on non-protected branches: Variables marked as "Protected" in GitLab are only injected on protected branches (typically main/master). Feature branch pipelines do not receive these variables. Either mark the branch as protected or create non-protected copies of the variables.
- envsubst replacing unintended placeholders:
envsubstreplaces all$VARand${VAR}patterns in the file, including Kubernetes YAML that uses $(...)for container command substitution. Useenvsubst '$APP_VERSION $DB_HOST'to limit substitution to specific variables only. - Not base64-encoding secrets in Kubernetes manifests: Kubernetes
Secretresources expect base64-encoded values in thedatafield. Injecting a raw CI variable intodata.passwordwithout encoding it causes a validation error. Usekubectl create secret --from-literalinstead, which handles encoding automatically.
Summary
- GitLab CI variables are shell environment variables — they do not auto-propagate into Kubernetes YAML files
- Use
envsubst,sed, or Helm--setto inject variables into manifests before applying - Check variable scope (environment, branch) and protection settings when variables appear empty
- Use
kubectl create secret --from-literalto safely create Kubernetes secrets from CI variables - Debug with
env | grepto verify which variables are actually available in the runner
Related reading
- GKE - How to serve HTTPS via the L7 load balancer?
- GKE autopilot has scaled up my container resources contary to resource requests
- GKE cluster suddenly not autoscaling nodepool
- GKE does not scale to/from 0 when autoscaling enabled
- GitLab remote HTTP Basic Access denied and fatal Authentication
- GitLab Runner Failed to register the runner. You may be having network problems
- Glusterfs Not Replicating data
- go get results in 'terminal prompts disabled' error for GitHub private repo

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.