How Vinted uses GitOps to
deploy thousands of pods to
Kubernetes
Edgaras Apšega
Site Reliability Engineer / CNCF Ambassador
@apsega
Vinted infrastructure
3x growth over 2 years Kubernetes production stats
● All services running on Kubernetes*
● 2000 deployments per day
● 10k+ running pods
● 480+ physical nodes (70k CPU cores; 190TB memory)
*Almost
What’s GitOps, anyway?
GitOps
Coined in August 2017 by Weaveworks CEO Alexis Richardson
GitOps is a DevOps process characterized by:
Best practices of deployment, management and monitoring of containerized
applications
Experience for managing applications with fully automated pipelines/workflows using
Git for development and operations
Use of Git revision control system to track and approve changes to the infrastructure
Why GitOps?
Infrastructure as a Code (IaC)
Repeatability
Reliability
Efficiency
Visibility
Self-service / Internal Developer Platform (Backstage)
Code reviews
Imperative vs. Declarative
Imperative Declarative
$ kubectl run busybox --image=busybox:1.29
--restart=Never --command -- sleep 3600
apiVersion: v1
kind: Pod
metadata:
labels:
run: busybox
name: busybox
spec:
containers:
- command:
- sleep
- "3600"
image: busybox:1.29
imagePullPolicy: Always
name: busybox
Build
Docker
push
Test
Git commit
and push
Git clone
config repo
Update
manifests
kubectl
apply
Git clone
config repo
Discover
manifests
GitOps continuous integration
GitOps continuous deployment
Git strategies
Single branch (multiple directories) Multiple branches
Do use directories for GitOps environments
kubernetes-deployments
├── demo-app
│ ├── development
│ ├── production
│ └── staging
└── guestbook
├── development
├── production
└── staging
Don’t use long-running branches for GitOps
environments
Environment promotion
Telefonistka Kargo
Configuration management
Helm Kustomize
Package manager
Go templating language
Environments per values files
No parameters and templates - as
close as you can get to Kubernetes
manifests
No parameters and templates -
limiting in edge cases
Overlays per environment
More a language than a tool
JSON with comments and
templating
Not Kubernetes specific
Jsonnet
Vinted case study:
GitOps
ArgoCD App of Apps Pattern
App of Apps manifest ArgoCD custom plugins
Kubernetes deployments
Kubernetes deployments directory Application manifests
kubernetes-deployments
├── guestbook
│ ├── frontend
│ │ ├── development-values.yaml
│ │ ├── development-application.yaml
│ │ ├── staging-values.yaml
│ │ ├── staging-application.yaml
│ │ ├── production-values.yaml
│ │ └── production-application.yaml
│ ├── backend
│ │ ├── development-values.yaml
│ │ ├── development-application.yaml
│ │ ├── staging-values.yaml
│ │ ├── staging-application.yaml
│ │ ├── production-values.yaml
│ │ └── production-application.yaml
│ └── common-values.yaml
└── demo-app
├── development-values.yaml
├── development-application.yaml
├── staging-values.yaml
├── staging-application.yaml
├── production-values.yaml
└── production-application.yaml
Helm charts
Centralized Helm charts Helm chart values files
Helm charts (2)
Centralized Helm charts
Helm chart values files in Kubernetes
deployments repository
ArgoCD application view
Change image tag in deployments repo
Jenkinsfile in code repo
git clone
yq write 
--inplace "${params.ENVIRONMENT}-values.yaml" 
--tag '!!str' image.tag  "${params.IMAGE_TAG}"
git push
stage('Build') {
when {
branch 'master'
}
steps {
echo 'Build and push Docker image'
DockerImageBuildAndPublish('frontend')
}
}
stage('Deploy App to Kubernetes') {
when {
branch 'master'
}
steps {
KubernetesDeploymentsApply('frontend',
'production')
}
}
Jenkins update image tag action
ArgoCD Sync waves
Supports application dependencies and defines
deployments order
Supports only definitions within same defined application
Prolongs deployments
Use when doing frequent deployments
argocd app sync $(APP_NAME) 
--revision ${ARGOCD_APP_REVISION}
Sync wave example
Sync waves
Bonus: scaling ArgoCD
for high load
ArgoCD architecture
argocd-api-server
argocd-api-server
argocd-api-server
argocd-api-server
argocd-api-server
argocd-application-controller
argocd-api-server
argocd-api-server
argocd-repo-server Git
Redis
Visualize
Changes
Apply
changes
Retrieve
manifests
Application controller
Too many applications:
increase number of processes
Too many clusters:
shard application controller (increase replicas)
Typically running 3-4 servers is enough
reposerver.parallelism.limit
Cache with webhooks
Repo server
GitOps is awesome (while GitHub/GitLab works)
Use directories for GitOps environments
Separate code and configuration repositories
Use common values for repetitive configuration
Avoid using cross application dependencies
Thank you!
@apsega

Lessons learned using GitOps

  • 1.
    How Vinted usesGitOps to deploy thousands of pods to Kubernetes Edgaras Apšega Site Reliability Engineer / CNCF Ambassador @apsega
  • 2.
    Vinted infrastructure 3x growthover 2 years Kubernetes production stats ● All services running on Kubernetes* ● 2000 deployments per day ● 10k+ running pods ● 480+ physical nodes (70k CPU cores; 190TB memory) *Almost
  • 3.
  • 4.
    GitOps Coined in August2017 by Weaveworks CEO Alexis Richardson GitOps is a DevOps process characterized by: Best practices of deployment, management and monitoring of containerized applications Experience for managing applications with fully automated pipelines/workflows using Git for development and operations Use of Git revision control system to track and approve changes to the infrastructure
  • 5.
    Why GitOps? Infrastructure asa Code (IaC) Repeatability Reliability Efficiency Visibility Self-service / Internal Developer Platform (Backstage) Code reviews
  • 6.
    Imperative vs. Declarative ImperativeDeclarative $ kubectl run busybox --image=busybox:1.29 --restart=Never --command -- sleep 3600 apiVersion: v1 kind: Pod metadata: labels: run: busybox name: busybox spec: containers: - command: - sleep - "3600" image: busybox:1.29 imagePullPolicy: Always name: busybox
  • 7.
    Build Docker push Test Git commit and push Gitclone config repo Update manifests kubectl apply Git clone config repo Discover manifests GitOps continuous integration GitOps continuous deployment
  • 8.
    Git strategies Single branch(multiple directories) Multiple branches Do use directories for GitOps environments kubernetes-deployments ├── demo-app │ ├── development │ ├── production │ └── staging └── guestbook ├── development ├── production └── staging Don’t use long-running branches for GitOps environments
  • 9.
  • 10.
    Configuration management Helm Kustomize Packagemanager Go templating language Environments per values files No parameters and templates - as close as you can get to Kubernetes manifests No parameters and templates - limiting in edge cases Overlays per environment More a language than a tool JSON with comments and templating Not Kubernetes specific Jsonnet
  • 11.
  • 12.
    ArgoCD App ofApps Pattern App of Apps manifest ArgoCD custom plugins
  • 13.
    Kubernetes deployments Kubernetes deploymentsdirectory Application manifests kubernetes-deployments ├── guestbook │ ├── frontend │ │ ├── development-values.yaml │ │ ├── development-application.yaml │ │ ├── staging-values.yaml │ │ ├── staging-application.yaml │ │ ├── production-values.yaml │ │ └── production-application.yaml │ ├── backend │ │ ├── development-values.yaml │ │ ├── development-application.yaml │ │ ├── staging-values.yaml │ │ ├── staging-application.yaml │ │ ├── production-values.yaml │ │ └── production-application.yaml │ └── common-values.yaml └── demo-app ├── development-values.yaml ├── development-application.yaml ├── staging-values.yaml ├── staging-application.yaml ├── production-values.yaml └── production-application.yaml
  • 14.
    Helm charts Centralized Helmcharts Helm chart values files
  • 15.
    Helm charts (2) CentralizedHelm charts Helm chart values files in Kubernetes deployments repository
  • 16.
  • 17.
    Change image tagin deployments repo Jenkinsfile in code repo git clone yq write --inplace "${params.ENVIRONMENT}-values.yaml" --tag '!!str' image.tag "${params.IMAGE_TAG}" git push stage('Build') { when { branch 'master' } steps { echo 'Build and push Docker image' DockerImageBuildAndPublish('frontend') } } stage('Deploy App to Kubernetes') { when { branch 'master' } steps { KubernetesDeploymentsApply('frontend', 'production') } } Jenkins update image tag action
  • 18.
    ArgoCD Sync waves Supportsapplication dependencies and defines deployments order Supports only definitions within same defined application Prolongs deployments Use when doing frequent deployments argocd app sync $(APP_NAME) --revision ${ARGOCD_APP_REVISION} Sync wave example Sync waves
  • 19.
  • 20.
  • 21.
    Application controller Too manyapplications: increase number of processes Too many clusters: shard application controller (increase replicas)
  • 22.
    Typically running 3-4servers is enough reposerver.parallelism.limit Cache with webhooks Repo server
  • 23.
    GitOps is awesome(while GitHub/GitLab works) Use directories for GitOps environments Separate code and configuration repositories Use common values for repetitive configuration Avoid using cross application dependencies
  • 24.