Episode 0x0F: Argo Events

Table of Contents

NOTE: Many commands in this post make use of specific constants tied to my own setup. Make sure to tailor these to your own needs. These examples should serve as a guide, not as direct instructions to copy and paste.

NOTE: Check out the final code at geekembly and homelab repositories on my Github account.

Introduction

In the previous episode, we discussed the individual components necessary to create a weblog using Hugo, alongside implementing a CI/CD pipeline. In this episode, we will integrate these components using Argo Events. Specifically, we will set up an EventSource to receive webhooks from GitHub, and a Sensor to trigger our CI/CD pipeline in response to push events.

Installation

We can install Argo Events similar to our previous applications. Add the following to your apps.yaml file:

- apiVersion: argoproj.io/v1alpha1
  kind: Application
  metadata:
    name: argo-events
    namespace: argocd
  spec:
    destination:
      namespace: argo-events
      server: https://kubernetes.default.svc
    project: default
    source:
      chart: argo-events
      repoURL: https://argoproj.github.io/argo-helm
      targetRevision: 2.4.6
      helm:
        releaseName: argo-events
    syncPolicy:
      automated:
        prune: true
      syncOptions:
        - CreateNamespace=true

Then apply the configuration:

kubectl apply -f apps.yaml

Geekembly Deployment

With Argo Events installed, we need to modify our weblog deployments to leverage it.

Event Bus

First, create an event bus by adding this to an events.yaml file:

apiVersion: argoproj.io/v1alpha1
kind: EventBus
metadata:
  namespace: geekembly
  name: default
spec:
  nats:
    native:
      replicas: 3
      auth: token

Event Source

Provide your GitHub Personal API token created in episode 11 by running:

kubectl create secret generic github-access -n <namespace> --from-literal=token=<github-token> --from-literal=secret=<webhook-secret> --dry-run=client -o yaml | kubeseal -o yaml

Add an event source to handle GitHub webhooks to events.yaml:

apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
  namespace: geekembly
  name: github
spec:
  eventBusName: default
  service:
    ports:
      - port: 12000
        targetPort: 12000
  github:
    geekembly:
      repositories:
        - owner: cih2001
          names:
            - geekembly
      webhook:
        endpoint: /push
        port: "12000"
        method: POST
        url: https://github.<your-domain>.com
      events:
        - "*"
      apiToken:
        name: github-access
        key: token
      webhookSecret:
        name: github-access
        key: secret
      insecure: false
      active: true
      contentType: json

Argo Events will automatically configure the GitHub webhook on our project to receive events on https://github.<your-domain>.com. Also configure your ingress to route events to this event source:

- host: github.geekembly.com
  http:
    paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: github-eventsource-svc
            port:
              number: 12000

Sensor

In the CI step, we will check for changes in the blog contents. If any changes are detected, we’ll create a new Docker image and tag it. This tag will then be passed to our CD pipeline, where the deployment tag in our Kustomize file will be updated accordingly. The updated Kustomize file will be committed back to the main branch, which will subsequently trigger Argo CD to synchronize the deployment automatically.

Sensors in Argo Events listen to specific events and trigger actions based on those events. Create a sensor to respond to GitHub push events and trigger your CI/CD pipeline by creating a sensor.yaml file:

apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
  name: github
  namespace: geekembly
spec:
  template:
    serviceAccountName: default
  dependencies:
    - name: github-dep
      eventSourceName: github
      eventName: geekembly
      filters:
        data:
          - path: headers.X-Github-Event
            type: string
            value:
              - push
  triggers:
    - retryStrategy:
        steps: 3
      template:
        name: github-workflow-trigger
        k8s:
          operation: create
          source:
            resource:
              apiVersion: argoproj.io/v1alpha1
              kind: Workflow
              metadata:
                generateName: prod-ci-workflow-
                namespace: geekembly
              spec:
                volumeClaimTemplates:
                  - metadata:
                      name: workspace
                    spec:
                      accessModes: ["ReadWriteOnce"]
                      resources:
                        requests:
                          storage: 200Mi
                volumes:
                  - name: ssh-vol
                    secret:
                      secretName: github-ssh-key
                  - name: docker-vol
                    secret:
                      secretName: regcred
                entrypoint: main
                templates:
                  - name: main
                    steps:
                      - - name: ci-step
                          templateRef:
                            name: prod-ci
                            template: start
                      - - name: cd-step
                          templateRef:
                            name: prod-cd
                            template: start
                          arguments:
                            parameters:
                              - name: push-skipped
                                value: "{{steps.ci-step.outputs.parameters.push-skipped}}"
                              - name: release-tag
                                value: "{{steps.ci-step.outputs.parameters.release-tag}}"

Perhaps you also want to add more filters or configuration to the event triggers and actions. Refer to the Argo Events documentation for additional customization.

NOTE: prod-ci and prod-cd are workflow templates we created based on smaller components we discussed in the episode 14. Please checkout the full source code at geekembly.

Testing Pipeline

The above setup should activate a fully operational CI/CD pipeline. To test it, push changes to the main branch and verify that the pipeline is triggered.

Pipeline.

To view pipeline logs, use:

argo logs -n geekembly @latest --follow

Conclusion

Many different designs can be adopted to structure a CI/CD pipeline. The approach described here is just one example. Explore and experiment to suit your specific needs. You may want to enhance your pipeline to include setting up multiple environments, such as staging or per-PR environments.

In the next episode, we will integrate Prometheus and Grafana to monitor visits, downtimes, and the overall health of our Kubernetes cluster. Stay tuned! 🚀