π Executive Summary
This guide documents a complete migration of a production GitOps infrastructure from GitHub to GitLab, including CI/CD pipelines, multi-cluster ArgoCD setup, and AWS Secrets Manager integration.
4
Repositories Migrated
30
Minutes Total Time
0
Minutes Downtime
100%
Success Rate
β
Migration Completed: December 5, 2025 - All repositories, CI/CD pipelines, and ArgoCD configurations successfully migrated with zero customer-facing downtime.
ποΈ Architecture Overview
GitOps Flow
Source Repositories β Docker Hub β GitOps Deploy β ArgoCD β EKS Clusters
π¦ GitLab CI/CD Layer
- demo-task-api (API source) β Builds Docker images
- demo-task-app (App source) β Builds Docker images
- demo-task-api-deploy (K8s manifests) β Updated with new image tags
π³ Docker Hub Registry
- bedigital/gitops-demo-app:api-* - API images
- bedigital/gitops-demo-app:v1.0.* - App images
- CI/CD automatically updates deploy repo with new tags
βΈοΈ Kubernetes Clusters
| Cluster |
ArgoCD Sync |
Applications |
Secrets |
| gitops-dev (EKS) |
Auto-sync enabled |
β’ api-app-dev (2 replicas)
β’ demo-app-dev (2 replicas)
|
External Secrets Operator (GitLab creds from AWS SM) |
| gitops-prod (EKS) |
Manual sync |
β’ api-app-prod (3 replicas)
β’ demo-app-prod (3 replicas)
|
External Secrets Operator (GitLab creds from AWS SM) |
π― Key Architecture Decisions:
- Multi-Cluster Isolation: Separate EKS clusters for DEV and PROD
- Separate ArgoCD Instances: Each cluster manages its own applications
- AWS Secrets Manager: Centralized credential management with External Secrets Operator
- GitLab CI/CD: Comprehensive security scanning (SAST, dependency, container)
- Zero Downtime: Migration performed without affecting running applications
π¦ Repository Mapping & Details
| Local Folder |
GitHub Repository |
GitLab Repository |
Status |
| gitops-demo-api |
BeDigital/gitops-demo-api |
devop212/demo-task-api |
β
Migrated |
| gitops-deploy |
BeDigital/gitops-deploy |
devop212/demo-task-api-deploy |
β
Migrated |
| gitops-demo-app |
BeDigital/gitops-demo-app |
devop212/demo-task-app |
β
Migrated |
| gitops-infra |
BeDigital/gitops-infra |
devop212/demo-task-infra |
β
Migrated |
Repository Details
1. gitops-demo-api (Task Manager REST API)
Technology: Node.js, Express
Purpose: Full-featured REST API for task management with Bruno/Postman collections
- Public endpoints: Health checks, echo, API info
- Tasks CRUD with query filters (completion, priority, search)
- Protected endpoints with API key authentication
- Test utilities for HTTP response code testing
- Live on both DEV and PROD clusters
2. gitops-demo-app (Node.js Express Application)
Technology: Node.js 20, Express, Jest, Docker
Purpose: Minimal Express app demonstrating containerization and GitOps patterns
- Health check endpoints for Kubernetes probes
- Environment-aware configuration (dev/prod)
- Multi-stage Docker builds with Alpine base
- Cross-platform support (AMD64/ARM64)
- Comprehensive unit tests with Jest
3. gitops-deploy (Kubernetes Manifests)
Technology: Kustomize, Kubernetes YAML, ArgoCD
Purpose: GitOps deployment repository with environment overlays
- Base manifests for common resources
- DEV overlay: Auto-sync, 2 replicas
- PROD overlay: Manual sync, 3 replicas
- ArgoCD application definitions
- Rolling updates with zero downtime
4. gitops-infra (Terraform Infrastructure)
Technology: Terraform, AWS, Helm
Purpose: Production-grade IaC for multi-environment Kubernetes clusters
- Modular Terraform design (VPC, EKS, ArgoCD, ALB, External Secrets)
- Remote state management with S3 and DynamoDB
- Multi-environment support with separate state files
- High availability across multiple AZs
- Cost-optimized: DEV $150/mo, PROD $400/mo
β±οΈ Migration Timeline
| Step |
Task |
Time |
| 1 |
Create GitLab repositories |
2 min |
| 2 |
Create GitLab CI/CD variables |
3 min |
| 3 |
Reinitialize git repos & push |
5 min |
| 4 |
Verify GitLab CI pipelines |
5 min |
| 5 |
Create AWS Secrets Manager secret |
2 min |
| 6 |
Deploy ExternalSecret for ArgoCD |
2 min |
| 7 |
Update ArgoCD applications |
3 min |
| 8 |
Configure multi-cluster setup |
5 min |
| 9 |
Verification & testing |
3 min |
| Total |
~30 min |
π§ Key Migration Steps
1. GitLab Repository Setup
Created four new repositories on GitLab to mirror the GitHub structure:
- demo-task-api - REST API source code
- demo-task-app - Frontend application source
- demo-task-api-deploy - Kubernetes manifests (GitOps)
- demo-task-infra - Terraform infrastructure code
2. CI/CD Variables Configuration
Configured the following variables in GitLab CI/CD settings for each repository:
| Variable |
Description |
Masked |
DOCKERHUB_USERNAME |
Docker Hub username |
No |
DOCKERHUB_TOKEN |
Docker Hub access token |
β
Yes |
GITLAB_TOKEN |
GitLab Personal Access Token |
β
Yes |
3. Pipeline Conversion
Converted GitHub Actions workflows to GitLab CI/CD pipelines with enhanced security scanning:
Pipeline Stages:
- test - Unit tests + SAST + Secret Detection + Dependency Scanning
- build - Docker image build and push
- container_scanning - Docker image vulnerability scan
- update-deploy - Auto-update DEV environment
- promote-prod - Manual promotion to PROD (button click required)
4. AWS Secrets Manager Integration
Stored GitLab credentials in AWS Secrets Manager for secure ArgoCD access:
aws secretsmanager create-secret \
--name "gitops/argocd/gitlab-repo-creds" \
--secret-string '{
"username":"oauth2",
"password":"YOUR_GITLAB_TOKEN",
"url":"https://gitlab.com/devop212/demo-task-api-deploy.git"
}'
5. External Secrets Operator
Deployed ExternalSecret resources to sync GitLab credentials from AWS Secrets Manager to Kubernetes secrets in both clusters.
6. Multi-Cluster ArgoCD Configuration
Configured separate ArgoCD instances for DEV and PROD clusters:
- DEV ArgoCD: Auto-sync enabled for fast iteration
- PROD ArgoCD: Manual sync required for controlled deployments
π Security Scanning
GitLab CI/CD includes comprehensive built-in security scanning:
| Scanner |
Purpose |
Stage |
| SAST (semgrep) |
Static code analysis for vulnerabilities |
test |
| Secret Detection |
Scans for leaked credentials/API keys |
test |
| Dependency Scanning |
Checks npm packages for CVEs |
test |
| Container Scanning |
Scans Docker images for vulnerabilities |
build |
Pipeline Flow:
Automated Pipeline Stages:
- test (+ SAST, Secret Detection, Dependency Scanning) β Validates code quality and security
- build β Creates multi-platform Docker images
- container_scanning β Scans Docker images for vulnerabilities
- update-deploy β Automatically updates DEV environment manifests
- promote-to-prod β MANUAL APPROVAL REQUIRED β Updates PROD environment
Flow: test β build β container_scanning β update-deploy (DEV auto) β promote-to-prod (MANUAL)
β‘ Zero Downtime Analysis
Application Downtime: Zero Minutes
The migration was designed to be completely non-disruptive. Running applications were never affected:
| Component |
Downtime |
Reason |
| Running Applications |
0 min |
Pods in EKS were never touched during migration |
| API (api-app-dev/prod) |
0 min |
Already deployed, continued serving traffic |
| Frontend (demo-app-dev/prod) |
0 min |
Already deployed, continued serving traffic |
| Load Balancers (ALB) |
0 min |
No changes to ingress |
Why Zero Downtime Was Achieved:
- GitOps Decoupling: Running infrastructure (EKS, pods, services) was completely decoupled from CI/CD migration
- Blue-Green by Design: Old GitHub setup could have remained active as fallback
- Control Plane vs Data Plane: Migration was a control plane change (where code lives) rather than a data plane change (where apps run)
MTTR for Issues Encountered
| Issue |
Time to Detect |
Time to Resolve |
Total MTTR |
| npm test missing script |
~2 min |
~3 min |
~5 min |
| Git push hanging |
~5 min |
~10 min |
~15 min |
| ExternalSecret IAM path mismatch |
~3 min |
~5 min |
~8 min |
| ArgoCD stale revision errors |
~2 min |
~3 min |
~5 min |
π Sync Policy Comparison
| Environment |
Sync Policy |
Reason |
| DEV |
automated: true
prune: true
selfHeal: true |
Fast iteration, auto-deploy on commit |
| PROD |
Manual sync only |
Best practice - controlled deployments with approval |
π CI/CD Variable Comparison
| GitHub Secret |
GitLab Variable |
Purpose |
DOCKERHUB_USERNAME |
DOCKERHUB_USERNAME |
Docker Hub login |
DOCKERHUB_TOKEN |
DOCKERHUB_TOKEN |
Docker Hub authentication |
GH_PAT |
GITLAB_TOKEN |
Git repository access |
GITOPS_PAT |
GITLAB_TOKEN |
Deploy repo access |
π Troubleshooting
GitLab CI Pipeline Not Triggering
Solutions:
- Ensure
.gitlab-ci.yml is in the repository root
- Check that the file has valid YAML syntax
- Verify the branch name matches (e.g.,
main vs master)
ExternalSecret Shows SecretSyncedError
Solutions:
- Check IAM policy allows access to the secret path
- Ensure secret path starts with
gitops/ (matches IAM policy)
- Verify ClusterSecretStore exists:
kubectl get clustersecretstore
ArgoCD Shows "Unknown" Sync Status
Solutions:
- Force refresh the application
- Check repository credentials:
kubectl get secret gitlab-repo-creds -n argocd
- Verify the GitLab token has correct permissions
Docker Push Fails
Solutions:
- Verify Docker Hub credentials are correct
- Check that the image name matches your Docker Hub repository
- Ensure the account has push permissions
π‘ Key Learnings
What Went Well
- Zero Downtime: GitOps architecture enabled migration without affecting running services
- Security First: GitLab's built-in security scanning provided immediate value
- AWS Secrets Manager: Centralized credential management simplified multi-cluster setup
- External Secrets Operator: Seamless integration between AWS and Kubernetes
- Multi-Cluster Isolation: Separate ArgoCD instances prevented cross-environment issues
Challenges Overcome
- IAM Path Matching: Ensured secret paths matched IAM policy patterns
- Git Push Timeouts: Resolved by reinitializing repositories
- ArgoCD Stale Revisions: Fixed with force refresh
- Pipeline Syntax: Converted GitHub Actions to GitLab CI YAML format
Best Practices Implemented
- Manual PROD Sync: Prevents accidental production deployments
- Comprehensive Security Scanning: SAST, secrets, dependencies, containers
- Separate Clusters: Complete blast radius isolation
- Infrastructure as Code: All changes tracked in Git
- Automated DEV, Manual PROD: Fast iteration with production safety
π Migration Summary
4
Repos Migrated
2
EKS Clusters
6
Applications
4
Security Scanners
β
Migration Achievements:
- Repository Migration: 4 repos moved from GitHub to GitLab
- CI/CD Conversion: GitHub Actions β GitLab CI pipelines with enhanced security
- Secrets Management: AWS Secrets Manager + External Secrets Operator integration
- Multi-Cluster Setup: Separate ArgoCD instances per environment
- Best Practices: Auto-sync for DEV, manual sync for PROD
- Zero Downtime: No customer-facing service interruption
The GitOps workflow is now fully operational on GitLab with enterprise-grade security via AWS KMS-encrypted secrets and comprehensive CI/CD security scanning.
π Resources
GitLab Repositories
Documentation
Related Projects
π Ready to Migrate?
This migration guide demonstrates a complete, production-ready approach to moving GitOps infrastructure from GitHub to GitLab with zero downtime.
Need Help with Your Migration?
I specialize in GitOps, Kubernetes, and cloud infrastructure migrations. Whether you're moving from GitHub to GitLab, implementing ArgoCD, or setting up multi-cluster environments, I can help.
Contact: Be-Digital.biz
View GitOps Portfolio
Visit Be-Digital.biz