GitOps has evolved significantly to address the complexities of multi-cloud environments. This guide presents modern GitOps patterns for 2025 that enable reliable, consistent management of infrastructure and applications across AWS, Azure, and GCP.
Core GitOps Principles: 2025 Edition
The foundational principles of GitOps have expanded to accommodate multi-cloud realities:
Declarative Infrastructure - All infrastructure, not just applications, is defined declaratively
Git as Single Source of Truth - All changes across clouds are tracked in version control
Pull-Based Deployments - Controllers in each cloud pull desired state from Git
Continuous Reconciliation - System automatically corrects drift from the desired state
Immutable Infrastructure - Resources are replaced, not modified
Security by Default - Security controls are embedded in the GitOps workflow
Observability Integration - GitOps workflows emit metrics, logs, and traces
Implementation Architecture
Centralized vs. Federated GitOps Models
1. Centralized Model
In a centralized model, a single Git repository contains configurations for all clouds, with separate directories for each provider:
Copy infrastructure/
├── aws/
│ ├── eks/
│ ├── networking/
│ └── security/
├── azure/
│ ├── aks/
│ ├── networking/
│ └── security/
└── gcp/
├── gke/
├── networking/
└── security/
Benefits:
Unified view across all environments
Consistent policies and patterns
Simplified cross-cloud orchestration
Challenges:
Repository can become large and complex
Teams may have different cloud ownership
Security boundaries might be more complex
Example implementation with Flux:
Copy # Root Kustomization for multi-cloud deployment
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infrastructure
namespace: flux-system
spec:
interval: 10m
path: ./infrastructure
prune: true
sourceRef:
kind: GitRepository
name: flux-system
---
# Cloud-specific Kustomizations
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: aws-infrastructure
namespace: flux-system
spec:
dependsOn:
- name: infrastructure
interval: 10m
path: ./infrastructure/aws
prune: true
sourceRef:
kind: GitRepository
name: flux-system
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: azure-infrastructure
namespace: flux-system
spec:
dependsOn:
- name: infrastructure
interval: 10m
path: ./infrastructure/azure
prune: true
sourceRef:
kind: GitRepository
name: flux-system
2. Federated Model
In a federated model, separate repositories exist for each cloud provider with a "meta-repo" that references them:
Copy # Meta repository structure
fleet/
├── aws-fleet.yaml
├── azure-fleet.yaml
└── gcp-fleet.yaml
Each cloud-specific repository contains its own configuration:
Copy # aws-infrastructure repository
eks/
networking/
security/
Benefits:
Clear separation of concerns
Independent team ownership
Smaller, more focused repositories
Challenges:
Cross-cloud coordination is more complex
Requires additional synchronization mechanisms
Can be challenging to implement holistic policies
Example implementation with ArgoCD:
Copy # Application of applications pattern
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: fleet-of-clouds
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/organization/fleet.git
targetRevision: HEAD
path: .
destination:
server: https://kubernetes.default.svc
namespace: argocd
---
# AWS-specific application in fleet repo
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: aws-infrastructure
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/organization/aws-infrastructure.git
targetRevision: HEAD
path: .
destination:
server: https://kubernetes.default.svc
namespace: aws-infra
1. Flux
Flux is a set of continuous and progressive delivery solutions for Kubernetes that can be extended to manage cloud resources.
Copy # Example Flux Terraform Controller deployment
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: terraform-aws
namespace: flux-system
spec:
interval: 1m
url: https://github.com/organization/terraform-aws
ref:
branch: main
---
apiVersion: infra.contrib.fluxcd.io/v1alpha1
kind: Terraform
metadata:
name: aws-vpc
namespace: flux-system
spec:
interval: 10m
path: ./vpc
sourceRef:
kind: GitRepository
name: terraform-aws
approvePlan: auto
writeOutputsToSecret:
name: aws-vpc-outputs
2. ArgoCD
ArgoCD is a declarative GitOps continuous delivery tool for Kubernetes that can be extended with plugins for multi-cloud scenarios.
Copy # ArgoCD with AWS plugin
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: aws-resources
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/organization/aws-resources.git
targetRevision: HEAD
path: .
plugin:
name: argocd-vault-plugin
destination:
server: https://kubernetes.default.svc
namespace: aws-resources
3. Crossplane
Crossplane is a control plane that enables platform teams to create cloud-native applications using managed services from multiple providers.
Copy # Crossplane AWS VPC configuration
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: VPC
metadata:
name: production-vpc
spec:
forProvider:
region: us-west-2
cidrBlock: 10.0.0.0/16
enableDnsSupport: true
enableDnsHostNames: true
tags:
environment: production
providerConfigRef:
name: aws-provider
Advanced GitOps Patterns
1. Multi-Cluster Configuration Management
For organizations managing multiple Kubernetes clusters across different clouds:
Copy # Centralized configuration with cluster-specific overlays
clusters/
├── base/
│ ├── monitoring/
│ │ └── prometheus.yaml
│ └── security/
│ └── network-policies.yaml
└── overlays/
├── aws-prod/
│ ├── kustomization.yaml
│ └── monitoring/
│ └── prometheus-aws.yaml
├── azure-prod/
│ ├── kustomization.yaml
│ └── monitoring/
│ └── prometheus-azure.yaml
└── gcp-prod/
├── kustomization.yaml
└── monitoring/
└── prometheus-gcp.yaml
2. Progressive Delivery Across Clouds
Implementing canary and blue/green deployments across multiple cloud environments:
Copy # Flux Canary Release for multi-cloud
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: podinfo
namespace: podinfo
spec:
interval: 5m
chart:
spec:
chart: podinfo
version: '>=6.0.0'
sourceRef:
kind: HelmRepository
name: podinfo
values:
replicaCount: 3
upgrade:
# Gradual rollout across clusters
remediation:
remediateLastFailure: true
strategy:
canary:
steps:
- setWeight: 5
- pause: {duration: 5m}
- setWeight: 20
- pause: {duration: 10m}
- setWeight: 50
- pause: {duration: 10m}
3. Policy-as-Code Integration
Enforcing consistent policies across all cloud environments:
Copy # OPA/Gatekeeper constraint template
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg}] {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("Missing required labels: %v", [missing])
}
4. Secret Management in GitOps Workflows
Secure handling of secrets across multiple clouds:
Copy # External Secrets Operator with AWS Parameter Store
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: aws-secret
spec:
refreshInterval: "1h"
secretStoreRef:
name: aws-parameterstore
kind: ClusterSecretStore
target:
name: application-secrets
creationPolicy: Owner
data:
- secretKey: dbPassword
remoteRef:
key: /myapp/production/db-password
CI/CD Integration with GitOps
1. Pull Request Workflows
Modern GitOps implementations include CI processes that validate changes before they're merged:
Copy # GitHub Actions workflow for multi-cloud validation
name: Validate Changes
on:
pull_request:
branches: [ main ]
paths:
- 'infrastructure/**'
jobs:
validate:
runs-on: ubuntu-latest
strategy:
matrix:
provider: [aws, azure, gcp]
include:
- provider: aws
workdir: ./infrastructure/aws
validate_cmd: terraform validate
- provider: azure
workdir: ./infrastructure/azure
validate_cmd: az bicep build --file main.bicep
- provider: gcp
workdir: ./infrastructure/gcp
validate_cmd: gcloud beta terraform vet
steps:
- uses: actions/checkout@v3
- name: Setup provider tools
run: |
if [ "${{ matrix.provider }}" == "aws" ]; then
# AWS setup
curl -s "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# Install Terraform
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install terraform
elif [ "${{ matrix.provider }}" == "azure" ]; then
# Azure setup
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
az bicep install
elif [ "${{ matrix.provider }}" == "gcp" ]; then
# GCP setup
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
sudo apt-get update && sudo apt-get install google-cloud-sdk
fi
- name: Validate ${{ matrix.provider }} configuration
working-directory: ${{ matrix.workdir }}
run: ${{ matrix.validate_cmd }}
- name: Run Policy Checks
uses: open-policy-agent/conftest-action@v2.0.0
with:
files: ${{ matrix.workdir }}
policy: ./policies/${{ matrix.provider }}
2. Post-Merge Verification
After changes are merged to the main branch, automated processes verify successful application:
Copy # GitLab CI post-merge verification
stages:
- validate
- apply
- verify
verify-aws:
stage: verify
script:
- aws cloudformation describe-stacks --stack-name production-stack --query "Stacks[0].StackStatus" | grep -q "COMPLETE"
- aws eks describe-cluster --name production --query "cluster.status" | grep -q "ACTIVE"
only:
- main
verify-azure:
stage: verify
script:
- az deployment group show --name production-deployment --resource-group production --query "properties.provisioningState" | grep -q "Succeeded"
only:
- main
verify-gcp:
stage: verify
script:
- gcloud deployment-manager deployments describe production --format="json" | jq '.operation.status' | grep -q "DONE"
only:
- main
Multi-Cloud GitOps Best Practices
Adopt Common Tooling : Use the same GitOps tools across clouds when possible
Define Consistent Patterns : Create templates and standards that work across providers
Implement Strong RBAC : Use granular permissions to control who can change what
Cross-Cloud Testing : Implement testing across all target environments
Standardize Observability : Use consistent monitoring and alerting across clouds
Automate Drift Detection : Implement regular checks for configuration drift
Document Failure Modes : Plan for GitOps controller failures or Git outages
Implement Backup Strategies : Ensure GitOps state can be recovered
Real-World Examples
Example 1: Financial Services Multi-Cloud Deployment
A financial services company implements GitOps across AWS (primary) and Azure (secondary) for regulatory compliance:
Copy # ArgoCD ApplicationSet for multi-region deployment
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: financial-application
spec:
generators:
- list:
elements:
- cloud: aws
region: us-east-1
clusterUrl: https://aws-east.example.com
- cloud: aws
region: us-west-2
clusterUrl: https://aws-west.example.com
- cloud: azure
region: eastus
clusterUrl: https://azure-east.example.com
template:
metadata:
name: '{{cloud}}-{{region}}-app'
spec:
project: default
source:
repoURL: https://github.com/financial-org/app-configs.git
targetRevision: main
path: overlays/{{cloud}}/{{region}}
destination:
server: '{{clusterUrl}}'
namespace: financial-app
syncPolicy:
automated:
prune: true
selfHeal: true
Example 2: Retail Company with Edge Locations
A retail company manages Kubernetes clusters across AWS, Azure, and edge locations:
Copy # Flux deployment with multi-type structure
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: retail-infrastructure
namespace: flux-system
spec:
interval: 10m
path: ./base
prune: true
sourceRef:
kind: GitRepository
name: retail-infrastructure
postBuild:
substituteFrom:
- kind: ConfigMap
name: cluster-config
---
# ConfigMap with cluster-specific values
apiVersion: v1
kind: ConfigMap
metadata:
name: cluster-config
namespace: flux-system
data:
CLUSTER_TYPE: "EDGE" # Alternative: AWS, AZURE
REGION: "store-1234"
RESOURCE_TIER: "small" # Depends on the location's size
Conclusion
Modern GitOps patterns enable organizations to maintain consistency across multi-cloud environments while respecting the unique characteristics of each provider. By implementing these patterns, teams can achieve greater reliability, improved security, and faster deployment cycles across their entire infrastructure.
Resources