Git
Kubernetes
Observability & Monitoring

GitOps with Kubernetes

GitOps is a practice that uses Git repositories as the source of truth for declarative infrastructure and application management.
June 10, 2024

What is GitOps

GitOps is a practice that uses Git repositories as the source of truth for declarative infrastructure and application management. It involves presenting the desired states of the software and storing them in a repository. 

It fundamentally integrates the principles of Infrastructure as Code with continuous deployment, where the system's desired state is defined in Git and automatically applied to the infrastructure using automation tools. This approach ensures that any changes to the system are versioned. It provides an easy rollback feature and a clear record of modifications with the commit history. This way, GitOps enhances communication among the development team, improves security, and reduces the complexity and risk of managing infrastructure and application updates.

GitOps with Kubernetes

While learning about GitOps, we will see information about Kubernetes. Theoretically, it is not a must that GitOps must work with Kubernetes and vice versa. However, an efficient GitOps approach is strongly recommended to rely on a declarative orchestration system, like Kubernetes. Without using Kubernetes, the infrastructure and its application can be complex to manage.

Kubernetes supports declarative APIs as its operation model. The cluster's desired state is defined in YAML files, which can be stored in Git repositories. GitOps tools will continuously monitor those repositories and the YAML files, then automatically update the cluster when any changes have been discovered.

Comparing the traditional way and GitOps with Kubernetes, it could be concluded in the following five aspects.

  • Configuration
  • Approach
  • Deployment process
  • Version control
  • Collaboration

For the configuration side, infrastructure and application configurations were often manually applied via CLI or GUI, which is prone to human error and inconsistencies. This situation can be highly improved in Kubernetes where its desired state is defined declaratively in YAML files and stored in a Git repository. While everything is defined in a universal format, it ensures consistency and reduces human error.

For the approach, we used an imperative approach in which commands were executed manually to make sure everything was in the desired state. It limited the way of automation as it is hard to replicate the environments consistently. You may need to customize the commands and scripts for each environment. With the help of GitOps tools, they synchronize the desired and actual state for you from the Git repository to the Kubernetes cluster. It will also continuously monitor the state to ensure they all match.

For the deployment process, the traditional way involves multiple steps and manual intervention for release and scaling. The procedures can vary between environments, especially for large-scale infrastructure and applications. The GitOps way provides automation that the deployments can be triggered by as simple as a single commit to the Git repository. It is a consistent and reusable deployment across all environments.

For the version control, those server initial scripts and configuration files may not be stored with versioning enabled, or even not in a centralized storage system. It leads to difficulties in tracking changes and rollbacks. Git itself is a powerful version control system that provides complete version history in a very detailed way. Reverting the commit can easily perform a rollback too.

Finally, the collaboration side could be a major challenge in many operation teams. Big changes made to infrastructure or small changes to the configuration are always not perfectly documented, or you can say that there is no such practice in the team. When everyone is doing it on their own, changes made by other people could be easily forgotten and ignored. They might not be peer-reviewed or tested consistently before release. Making good use of GitOps, they will all benefit from the Git workflow, including pull requests and code reviews. You can even integrate the CI/CD pipeline for automated testing and security scanning to improve overall reliability.

The traditional way may provide more flexibility in customizing the workflow, but there are more things to sacrifice like relying on manual and inconsistent commands. GitOps with Kubernetes leverages declarative configurations, automation, and Git to ensure reusability, reliability, and consistency.

GitOps vs DevOps

GitOps and DevOps could be confusing as they look similar. They are related concepts in software development and operations but different in their focus, principles, and practices.

DevOps focuses on the culture within the software development and operation teams. It aims to automate the processes between those teams with the most suitable practices. There are common DevOps practices but not the best practices, as the solution should be varied in each team and company. It should be continuously improving according to the working style of the engineers. The main concepts are continuous integration (CI), continuous delivery (CD), monitoring, collaboration, automation, and agile methodologies, to improve the speed and quality of software delivery.

GitOps is a subset of DevOps that focuses on continuous delivery by leveraging Git repositories as the single source of truth for the declarative infrastructure and application management. It is a more practical topic with its best practices by some popular GitOps tools like ArgoCD and Flux CD. The main concepts are Git-based workflows, declarative configurations, continuous deployment, and infrastructure as code (IaC), to enhance version control and collaboration for infrastructure changes, and automate deployments repeatable.

GitOps by ArgoCD

ArgoCD is a declarative, GitOps continuous delivery tool for Kubernetes from the Argo open-source project. It enables application delivery for Kubernetes native applications, as a comprehensive solution to deploy containers on Kubernetes clusters. As GitOps methodology is to control deployments in a centralized platform, ArgoCD is a great solution to enable GitOps on multiple clusters.

As the leading tool in GitOps, ArgoCD follows the core patterns and best practices. Its application definitions, configurations, and environments are declarative and version-controlled. It provides features to automate application deployment and lifecycle management with auditable history. 

It is implemented as a Kubernetes controller that continuously monitors running applications and compares the current and live state against the target state defined in a Git repository. If there is any difference, ArgoCD will mark it as `OutOfSync`. Depending on your needs, you can configure it to automatically or manually synchronize the live state to the desired state. In automatic mode, it will pull the desired state from the target Git repository when a new commit has been pushed or merged.

Figure 1 GitOps by ArgoCD | ArgoCD architecture.
Figure 1 GitOps by ArgoCD | ArgoCD architecture
Figure 2 GitOps by ArgoCD | ArgoCD UI
Figure 2 GitOps by ArgoCD | ArgoCD UI

Now, we will talk about the core components of ArgoCD.

Projects

In ArgoCD, a project is a way to group and manage applications logically, acting as the boundary for defining and enforcing policies and access control on these applications. If your ArgoCD is used by multiple teams and environments, it provides several important features to separate the resources correspondingly. The most common application segmentation is grouping them by environments like `dev`, `qa`, `staging`, and `prod`.

Highlights of features:

  • Restrict deployments from specific Git repositories
  • Restrict applications to be deployed on specific clusters or namespaces
  • Restrict what kinds of Kubernetes objects cannot be deployed
  • Set resource quotas and limits to prevent exhaustion

Example Project definition:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:  
  name: example-project  
  namespace: argocd
spec:  
  description: Example project for demo purposes  
  sourceRepos:    
    - https://github.com/example/repo  
  destinations:    
    - namespace: dev      
      server: https://kubernetes.default.svc    
    - namespace: prod      
      server: https://kubernetes.default.svc 
  clusterResourceWhitelist:    
    - group: '*'      
      kind: '*'  
  namespaceResourceWhitelist:    
    - group: '*'      
      kind: '*'  
  roles:    
    - name: admin      
      description: Admin role with full access      
      policies:        
        - p, proj:example-project:admin, applications, *, example-project/*, allow      
      groups:        
        - admins

In this example, the project `example-project` allows applications to be sourced from a specific GitHub repository, and deployed to namespaces `dev` and `prod`. It also defines an admin role to manage the application.

Applications

An ArgoCD Application is a resource that represents how your code is deployed in a Kubernetes cluster, as a group of Kubernetes resources defined by a manifest. It includes the configurations, deployment details, and the way to synchronize the status of the resources. 

As the most popular GitOps tool on the market, it supports most of the widely used deployment tools, including the basic Kubernetes manifests, Helm Charts, and Kustomize. It not only synchronizes the state defined in the specified Git repository but also performs health checks against the applications. ArgoCD Application also records the resources state that can automatically roll back to the previous state once it discovers deployment failure.

Example Application definition:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:  
  name: guestbook  
  namespace: argocd
spec:  
  project: default  
  source:    
    repoURL: 'https://github.com/argoproj/argocd-example-apps'    
    targetRevision: HEAD    
    path: guestbook  
  destination:    
    server: 'https://kubernetes.default.svc'    
    namespace: default  
  syncPolicy:    
    automated:      
      prune: true      
      selfHeal: true

In this example, it defines an ArgoCD application `guestbook`. The source of Kubernetes manifests is from a GitHub repository and deployed to the `default` namespace in the cluster. With automated synchronization enabled, it keeps the state up to date.

Figure 3 Applications | A visualized ArgoCD application
Figure 3 Applications | A visualized ArgoCD application

ApplicationSets

The ApplicationSet in ArgoCD is one of the most popular objects they provide. It allows you to manage multiple ArgoCD Applications effectively by defining multiple Applications in a single set object. It is particularly useful while deploying the same set of applications to multiple Kubernetes clusters. 

Key features:

  • Templating
  • Generators
  • Dynamic updates

The ApplicationSet works as a template for the Applications to be created, which includes the common configuration parameters that will be shared within the set. Once you have the template, you can provide the details to Generators that specify how the Applications should be generated, such as a list of clusters, Git repositories, and Helm value files. When there are any changes among the generators, it will update the whole set of applications automatically.

Example ApplicationSet definition:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:  
  name: guestbook-appset  
  namespace: argocd
spec:  
  generators:  
  - list:      
    elements:        
      - cluster: cluster-a          
        url: https://cluster-a.example.com        
      - cluster: cluster-b          
        url: https://cluster-b.example.com  
  template:    
    metadata:      
    name: '{{name}}-guestbook'    
  spec:      
    project: default      
    source:        
      repoURL: 'https://github.com/argoproj/argocd-example-apps'        
      targetRevision: HEAD        
      path: guestbook      
    destination:        
      server: '{{server}}'        
      namespace: '{{name}}'      
    syncPolicy:        
      automated:          
        prune: true          
        selfHeal: true

Conclusion

GitOps with Kubernetes is a fantastic approach to handling complex application deployment on the cloud. Using Git makes everything simpler as the developers or other engineers already know this tool. As a DevOps Engineer, you should integrate GitOps into your solution for a more stable and reliable workflow.