Tutorial: how to set up the promoter with Argo CD and GitHub
This is a step by step tutorial to set up GitOps Promoter in a test environment.
We have 3 main goals:
- Set up the cluster with Argo CD and GitOps Promoter
- Set up a sample GitOps repository on GitHub
- Deploy the applications
Once there, we can play with the promotion strategies and explore the Promoter further.
Requirements
To complete this tutorial, you will need the following:
- Kind installed, or any kubernetes cluster with internet access.
- Kubectl installed
- A GitHub Account
- Git
Note
GitOps Promoter provides several opt-in Argo CD integrations that improve the user experience. Check out the Integrating with Argo CD page for more information.
Tip
For the impatient, the steps below are also available as a command ./gitops-promoter demo
It will run the whole tutorial in a local k8s cluster, with Argo CD and GitOps Promoter installed, and a sample application deployed.
Set up the test cluster
Create the cluster
If you don't have a test cluster yet, create one. With kind, simply run kind create cluster
Tip
You can name the cluster with kind create cluster --name promoter
Confirm that your access works with kubectl get nodes. Nodes should have a name starting with the name of your cluster (per example: promoter-control-plane)
Install Argo CD
More information in Argo CD official documentation
More information on the Argo CD Source Hydrator
kubectl create namespace argocd
kubectl apply --server-side -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install-with-hydrator.yaml
We want access to the UI, so open a dedicated terminal and run
kubectl port-forward svc/argocd-server -n argocd 8080:443
Open your browser on http://localhost:8080, you should have the UI.
To get the admin password if you don't have the argocd CLI:
kubectl get secret -n argocd argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 --decode | xargs echo
Connect with this password for the admin user.
Install GitOps Promoter
See Getting Started
kubectl apply -f https://github.com/argoproj-labs/gitops-promoter/releases/download/v0.31.1/install-without-ui.yaml
Note
You may want to run the command twice to deploy the controller configuration after the CRDs were deployed.
Set up a sample repository
Create a fork
Argo provides an example repository: https://github.com/argoproj/argocd-example-apps. Fork it!
Important
Make sure your staging branches (environment/development-next, environment/staging-next, etc.) are not auto-deleted
when PRs are merged. You can do this either by disabling auto-deletion of branches in the repository settings (in
Settings > Automatically delete head branches) or by adding a branch protection rule for a matching pattern such as
environment/*-next (/ characters are separators in GitHub's glob implementation, so *-next will not work).
Create a GitHub application
In your GitHub account, go to Settings > Developer settings > GitHub Apps.
Click on New GitHub App, pass the MFA challenge.
Fill up the form with the following (leave non specified to defaults):
| Field | Value |
|---|---|
| GitHub App name | A unique name of your choice (unique across the whole world) |
| Homepage URL | The URL of your profile |
| Webhook > Active | False (unless you configure it with Smee, as described below) |
| Permissions > Repository Permissions > Checks | Read and write |
| Permissions > Repository Permissions > Content | Read and write |
| Permissions > Repository Permissions > Pull requests | Read and write |
Hit the Create GitHub App button.
Once the app is created. Go to Install app and install it in your account.
Using the webhook
The webhook notifies the Promoter and Argo CD that a new commit was pushed/merged to the main branch. It greatly reduces the latency between deployments.
If you want your local demo to be very responsive, you can use Smee.io to forward the webhook events to your local machine.
kubectl port-forward -n promoter-system svc/promoter-webhook-receiver 3333:3333
smee -u https://smee.io/<YOUR CHANNEL ID> -t http://localhost:3333/
Then set the webhook URL in your GitHub App settings to https://smee.io/<YOUR CHANNEL ID>.
In the Subscribe to events section, check Push.
Using requeue durations
If you don't need superfast responsiveness for your local demo, you can just adjust the requeue duration down to something reasonably low like 30 seconds.
kubectl patch -n promoter-system controllerconfiguration promoter-controller-configuration \
--type merge \
-p '{"spec":{"promotionStrategy":{"workQueue":{"requeueDuration":"30s"}},"changeTransferPolicy":{"workQueue":{"requeueDuration":"30s"}},"argocdCommitStatus":{"workQueue":{"requeueDuration":"30s"}},"pullRequest":{"workQueue":{"requeueDuration":"30s"}}}}'
Generate a key
In the app config, in the section General. Under Private keys. Click on Generate a private key.
Keep the file close for later use.
Get the App ID
In the app config, in the section General. Find the "App ID" field and take note of the number.
Install the app in your org
Go to the Install App section, and click on Install beside your account name. Choose Only select repositories and select your fork of argocd-example-apps.
Prepare the terminal environment
We need to set up some temporary environment variables.
export GITHUB_ACCOUNT=<your-account-slug>
export GITHUB_APP_KEY_PATH=<path-to-the-generate-private-key>
export GITHUB_APP_ID=<your-github-app-id>
Configure the repo secret
Create the secret.
kubectl create secret generic -n argocd github-app \
--from-literal=url=https://github.com/${GITHUB_ACCOUNT}/argocd-example-apps \
--from-literal=type=git \
--from-literal=githubAppID=$GITHUB_APP_ID \
--from-file=githubAppPrivateKey=$GITHUB_APP_KEY_PATH
kubectl label secret -n argocd github-app argocd.argoproj.io/secret-type=repository-write
Deploy an application for 3 environments
Then create the application with the following:
for env in 'development' 'staging' 'prod'; do
cat << EOF | kubectl apply -f-
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: ${env}-helm-guestbook
namespace: argocd
labels:
# This label allows the ArgoCDCommitStatus to find the applications.
app-name: helm-guestbook
spec:
project: default
destination:
server: https://kubernetes.default.svc
namespace: ${env}
sourceHydrator:
drySource:
repoURL: https://github.com/${GITHUB_ACCOUNT}/argocd-example-apps
path: helm-guestbook
targetRevision: HEAD
hydrateTo:
targetBranch: environment/${env}-next
syncSource:
targetBranch: environment/${env}
path: helm-guestbook
syncPolicy:
automated:
prune: true
allowEmpty: true
selfHeal: true
syncOptions:
- CreateNamespace=true
EOF
done
If you go to the Argo CD UI, in the applications, you should now see the "SOURCE HYDRATOR" section in the header.
It should have the message "from HEAD (...) to environment/development-next (...)"
Important
The Application will have an error under "APP CONDITIONS" that "app path does not exist." That's because the Promoter has not yet moved the hydrated manifests to the syncSource branches. That's the next step.
This means three things in case of a change in the main branch:
- Nothing will change in our application (it is sync on the non "-next" branch)
- Argo CD Hydrator will push a new commit to the "-next" branch
- We need to manually create a pull request from the "-next" branch to environment branch. This for each environment...
Fortunately, GitOps Promoter is here to automate the process.
Deploy GitOps Promoter resources
Create the secret
kubectl create secret generic github-app-promoter \
--from-file=githubAppPrivateKey=$GITHUB_APP_KEY_PATH
Create the SCM Provider
cat << EOF | kubectl apply -f-
apiVersion: promoter.argoproj.io/v1alpha1
kind: ScmProvider
metadata:
name: github
spec:
secretRef:
name: github-app-promoter
github:
appID: ${GITHUB_APP_ID}
EOF
Create the git repository
cat << EOF | kubectl apply -f-
apiVersion: promoter.argoproj.io/v1alpha1
kind: GitRepository
metadata:
name: github-argocd-example-apps
spec:
github:
owner: ${GITHUB_ACCOUNT}
name: argocd-example-apps
scmProviderRef:
name: github
EOF
Create the promotion strategy
Create the promotion strategy.
cat << EOF | kubectl apply -f-
apiVersion: promoter.argoproj.io/v1alpha1
kind: PromotionStrategy
metadata:
name: demo-github
spec:
activeCommitStatuses:
# The ArgoCDCommitStatus CR will maintain this commit status based on the application health.
- key: argocd-health
environments:
- autoMerge: true
branch: environment/development
- autoMerge: true
branch: environment/staging
- autoMerge: false
branch: environment/prod
gitRepositoryRef:
name: github-argocd-example-apps
EOF
Finally, create an ArgoCDCommitStatus resource to monitor the status of the Argo CD applications and maintain the
argocd-health commit status.
cat << EOF | kubectl apply -f-
apiVersion: promoter.argoproj.io/v1alpha1
kind: ArgoCDCommitStatus
metadata:
name: argocd-health
spec:
promotionStrategyRef:
name: demo-github
applicationSelector:
matchLabels:
app-name: helm-guestbook
EOF
Here, we implement a simple strategy:
- Auto-merge on development
- Auto-merge on staging (if development is successful)
- Manual merge on production
Note
You should see 2 PRs getting merged automatically and 1 PR to merge manually for the production. That is normal: we branched from the main branch which is DRY. The promoter detects changes and does what's needed to sync the two branches.
Play with your environment
We deployed the application "helm-guestbook" from the example repository.
Try editing the main branch: number of replicas, helm templates... And see the PRs getting promoted from development to staging, then wait for your approval for the prod.
Note
Since we are not using the webhook. It can take 5 to 15 minutes to complete the cycle unless you've set the requeue duration to a lower value.