ArgoCD - Simplifying GitOps Deployment blog banner image

ArgoCD - Simplifying GitOps Deployment

Introduction to Argo CD and GitOps

Argo CD is a declarative, GitOps continuous delivery tool for an Kubernetes applications. As a declarative, GitOps continuous delivery tool, it orchestrates application deployment, configuration, and lifecycle management, ensuring consistency and reliability across clusters.

Purpose of GitOps Strategy

  1. Infrastructure as Code (IaC): GitOps promotes the practice of managing infrastructure and application configurations through code stored in version control systems like Git. This approach enables teams to treat infrastructure as code, facilitating versioning, collaboration, and reproducibility.
  2. Consistency and Standardization: By defining infrastructure and deployment processes as code, GitOps ensures consistency across environments. This reduces the risk of configuration drift and minimizes human errors, leading to more reliable deployments.
  3. Audibility and Traceability: GitOps provides a clear audit trail of all changes made to the infrastructure and application configurations. Every modification is recorded in version control, allowing teams to track who made the change, when it was made, and why, which enhances accountability and compliance.
  4. Collaboration and Visibility: With GitOps, all team members have access to the same set of configuration files and deployment manifests stored in Git repositories. This fosters collaboration and transparency, as everyone can review, comment on, and contribute to the deployment process.
  5. Rollback and Disaster Recovery: In case of deployment failures or issues, GitOps simplifies rollback procedures by reverting to the last known good state stored in Git. This capability enhances resilience and facilitates disaster recovery, minimizing downtime and service disruptions.

Disclaimer: This blog post exclusively presents our organization's folder structure strategy designed for managing Helm and Kubernetes files within the Argo CD ecosystem. It does not include a comprehensive briefing on Helm, Kubernetes and Argo CD. For detailed information on Kubernetes and Argo CD, please refer to their respective documentation.

What ArgoCD doesnt solve?

Our journey towards optimizing GitOps repository management with Argo CD revolves around addressing key challenges while striving for specific objectives:

  1. Centralized Environment and Application Deployment: Our aim is to consolidate all application deployments for each environment and application within a single Git branch. This unified approach enhances organization and simplifies management, ensuring all relevant configurations and updates are readily accessible and effectively coordinated.
  2. Enforcement of Naming Conventions: Adhering to predefined naming conventions for releases, Argo CD applications, and related components promotes consistency and clarity across deployments. This standardized approach streamlines communication and fosters alignment with organizational standards and best practices.
  3. Mitigation of Human Error: We seek to minimize the risk of human error during the creation of Argo CD applications through structured folder frameworks, predefined templates, and standardized layouts. By doing so, we aim to reduce the likelihood of misconfigurations or oversights, enhancing deployment accuracy and reliability.
  4. Resolving Argo CD Shared Resource Warning: Implementing a well-defined folder structure helps mitigate the shared resource warning issued by Argo CD. This proactive measure ensures smoother deployment operations and helps maintain the integrity of the GitOps workflow, safeguarding against potential conflicts or inconsistencies.
  5. Straightforward Helm Release Management: Establishing a straightforward approach to deploying or managing Helm releases is crucial. The structured folder hierarchy provides clear pathways for Helm release management, facilitating ease of deployment and maintenance within the Argo CD ecosystem.

Folder Structure for Argo CD Deployment

To address these challenges and achieve our objectives, we've meticulously designed a folder structure tailored for Argo CD deployment. Let's dive into the details:

.
├── Chart.yaml
├── templates
│   ├── _helper.tpl
│   ├── apps.yaml
│   └── extras.yaml
├── values
│   ├── bitnami-kafka.yaml
│   ├── observability.yaml
└── values.yaml

Understanding the Structure

  1. Chart.yaml: This file contains essential metadata defining the chart, ensuring Argo CD recognizes our repository as a chart deployment.
  2. Templates: Within this directory lies essential templates crucial for rendering Argo CD application configurations:
    • _helper.tpl: Houses the Argo CD application named template logic, ensuring seamless application rendering.
    • apps.yaml: Contains the named template for rendering Argo CD applications.
    • extras.yaml: Holds named templates for rendering Argo CD applications specific to extras. More on this later.
  3. Values: Here, we store Helm release information in separate YAML files for each helm release:
    • bitnami-kafka.yaml
    • ingress-nginx.yaml
    • And more, as per the requirement.

Application Rendering Logic - templates/_helper.tpl

{{- define "tpl.argocd.application.helm" }}
{{ $appName := (printf "%s-%s-%s" .Values.application ((.appName).releaseName | default (.appName).chart.name) .Values.environment) }}
{{ $valuesFile := (printf "%s/%s%s.%s" "values" ((.path) | default "") ((.appName).releaseName | default (.appName).chart.name) "yaml") }}
{{- if (.appName).enabled }}
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: {{ $appName }}
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  source:
    repoURL: {{ (.appName).chart.repoURL }}
    targetRevision: {{ (.appName).chart.version }}
    chart: {{ (.appName).chart.name }}
    helm:
      releaseName: {{ (.appName).namespace | default .Values.namespace }}
      values: |
        {{- .Files.Get $valuesFile | nindent 8 }}
  {{- include "tpl.argocd.application.destination" $ | indent 2 }}
  {{- include "tpl.argocd.application.spec" $ | indent 2 }}
{{- end }}
{{- end }}

{{- define "tpl.argocd.application.destination" }}
destination:
  name: {{ .Values.server }}
  namespace: {{ (.appName).namespace | default .Values.namespace }}
{{- end }}

{{- define "tpl.argocd.application.spec" }}
project: {{ .Values.project }}
syncPolicy: {{ (.appName).syncPolicy | default .Values.syncPolicy | toYaml | nindent 2 }}
revisionHistoryLimit: 1
{{- if (.appName).ignoreDifferences }}
ignoreDifferences: {{ (.appName).ignoreDifferences | toYaml | nindent 2 }}
{{- end }}
{{- end }}

Rendering Argo CD Applications - templates/apps.yaml

{{- if .Values.enabled }}
{{- include "tpl.argocd.application.helm" (merge (dict "appName" .Values.bitnami.kafka ) $) }}
---
{{- include "tpl.argocd.application.helm" (merge (dict "appName" .Values.ingressNginx ) $) }}
{{- end }}

Configuration Values - values.yaml

enabled: true # disables all the Argo CD app deployment

# Argo CD application name will be formed as {{ application }}-{{ release-name }}-{{ environment }}
application: test # Stack name
environment: dev # Environment type
project: argocd-project-name # Name of the Argo CD project to use
server: test-cluster # Name of the Argo CD server to use
namespace: default # Default namespace to use for Helm releases

syncPolicy: # Argo CD sync policy
  automated:
    prune: true
    selfHeal: true
  syncOptions:
    - Validate=true
    - CreateNamespace=true
    - PrunePropagationPolicy=foreground
    - PruneLast=true
    - RespectIgnoreDifferences=true
    - ApplyOutOfSyncOnly=true
  retry:
    limit: 5
    backoff:
      duration: 5s
      factor: 2
      maxDuration: 3m

ingressNginx:
  enabled: true
  namespace: ingress-nginx
  chart:
    repoURL: https://kubernetes.github.io/ingress-nginx
    version: 4.8.3
    name: ingress-nginx

bitnami:
  kafka:
    enabled: true # install/uninstall helm release
    releaseName: bitnami-kafka # force release name to use. Defaults to chart name as release name
    namespace: kafka # Overrides .Values.namespace to use for deployment
    chart: # chart to use in helm release
      repoURL: registry-1.docker.io/bitnamicharts
      version: 26.8.1
      name: kafka
    syncPolicy: {} # Overrides .Values.syncPolicy
    ignoreDifferences: # force to ignore difference in Argo CD
      - group: apps
        kind: Service
        jsonPointers:
          - /spec

Deployment and Observations

Once you perform the Helm template operation using the command:

helm template argocd-apps . -f values.yaml > argocd-apps.yaml

After generating the argocd-apps.yaml file containing the rendered Argo CD applications, proceed to Argo CD and create an application or application set pointing to this repository and branch. Upon synchronization, you will witness a comprehensive representation of your applications, each aligning with a component within your stack, similar to the image below. These applications will showcase their deployment status and offer various options for further management and monitoring through the intuitive Argo CD interface.

ArgoCD Apps of App

apps 1.png

Kafka ArgoCD App

kafka 1.png

Conclusion

With a standardized and well-organized GitOps repository structure, optimized for Argo CD, you're well-equipped to streamline application deployment, enhance collaboration, and minimize errors. This approach fosters consistency, scalability, and resilience, ensuring smoother operations and greater efficiency in managing your Kubernetes infrastructure.

Next Steps: Extending Repository for Raw Kubernetes Manifests and Helm Charts

In the next section, we'll explore how to extend this GitOps repository to deploy raw Kubernetes manifest files and Helm charts that lack official public Helm charts, such as the Istio operator. This extension will enrich your repository's capabilities, enabling seamless integration and deployment of diverse Kubernetes resources within the same repository and branch. Stay tuned!