Skip to main content

2 posts tagged with "GitHub Action"

View All Tags

· 4 min read

Deployment Strategy of Argo CD

Argo CD is the most popular GitOps tool for Kubernetes. Argo CD makes it easy to define an application with its desired state in a repository and where it should be deployed. After a deployment, Argo CD constantly tracks updates to branches, tags, or pinned to a specific version of manifests at a Git commit.

Argo CD provides several different ways of tracking Kubernetes resource manifests. Among them, commit pinning is typically used to control production environments. Since commit SHAs cannot change the meaning, the live state of an application can be fixed and predictable. So the application remains stable.

  • HEAD / Branch Tracking
  • Tag Tracking
  • Commit Pinning

Commit Pinning By CLI

Now, we'll deploy the manifest in a specific commit from the Argo CD. First, before starting the demo, install the argocd command. More detailed installation instructions can be found via the CLI installation documentation.

The repository to be used as a demo has Kubernetes resources manifests under the app/ directory and it is customized through kustomize for each environment.

File Structure
app
├── base
│   ├── deployment.yaml
│   └── kustomization.yaml
└── overlays
├── dev
│   └── kustomization.yaml
└── prod
└── kustomization.yaml

First, we should create an Application for Argo CD:

Create App
argocd app create argocd-demo-prod \
--repo https://github.com/gitploy-io/argocd-demo.git \
--path app/overlays/prod \
--dest-server https://kubernetes.default.svc \
--dest-namespace argocd \
--sync-policy automated

We should change the Application's revision to the commit SHA. At the same time, we also update the image tag with commit SHA:

Update App
argocd app set argocd-demo-prod \
--revision COMMIT_SHA \
--kustomize-image gitployio/argocd-demo=gitployio/argocd-demo:sha-COMMIT_SHA

Finally, We should synchronize the desired state to the Kubernetes cluster:

Sync App
argocd app sync argocd-demo-prod --timeout 300

Then, Argo CD continuously synchronizes the manifest of the commit. As a result, the desired manifest and the live state of Kubernetes are always synchronized.

Integration With Argo CD

Demo

Commit pinning is appropriate for production environments, but changing revisions every time is difficult. As a result, many teams (or organizations) adopt HEAD/branch tracking because it is much easier than the commit pinning.

But the good thing is that Gitploy can solve this problem easily. Gitploy provides the way to deploy a commit easily, and the deployment event, which is dispatched to CD tooling, includes the commit SHA value. So the CD tool will be able to execute argocd app set command with the commit SHA from the deployment event.

Below is an example of a pipeline built with Gitploy and GitHub Actions. When Gitploy deploys a commit, it passes the payload including the Application name of the Argo CD to be deployed, and The GitHub Action pipeline accesses github.event.deployment.payload to get the Application name. Also, the GitHub Action pipeline gets the commit SHA through the github.sha value to deploy.

Gitploy Configuration
envs:
- name: dev
auto_merge: false
required_contexts:
- "publish-image"
payload:
application: argocd-demo-dev
- name: prod
auto_merge: true
required_contexts:
- "publish-image"
production_environment: true
payload:
application: argocd-demo-prod
GitHub Action Pipeline
name: deploy

on:
deployment

jobs:
deploy:
runs-on: ubuntu-latest
steps:
-
uses: chrnorm/deployment-status@releases/v2
with:
deployment-id: ${{ github.event.deployment.id }}
description: Trigger the pipeline
state: "queued"
token: "${{ github.token }}"
-
uses: chrnorm/deployment-status@releases/v2
with:
deployment-id: ${{ github.event.deployment.id }}
description: Start to deploy to the Kubernetes
log-url: https://gitploy.jp.ngrok.io/applications/${{ github.event.deployment.payload.application }}
state: "in_progress"
token: "${{ github.token }}"
-
name: Log in
uses: clowdhaus/argo-cd-action/@main
with:
version: 2.3.3
command: login gitploy.jp.ngrok.io
options: >
--username
admin
--password
${{ secrets.ARGOCD_PASSWORD }}
-
name: Set image tag
uses: clowdhaus/argo-cd-action/@main
with:
version: 2.3.3
command: app set ${{ github.event.deployment.payload.application }}
options: >
--revision ${{ github.sha }}
--kustomize-image gitployio/argocd-demo=gitployio/argocd-demo:sha-${{ github.sha }}
-
name: Sync
uses: clowdhaus/argo-cd-action/@main
with:
version: 2.3.3
command: app sync ${{ github.event.deployment.payload.application }}
options: >
--timeout 300
-
name: Wait
uses: clowdhaus/argo-cd-action/@main
with:
version: 2.3.3
command: app wait ${{ github.event.deployment.payload.application }}
options: >
--health
--timeout 600
-
if: success()
uses: chrnorm/deployment-status@releases/v2
with:
deployment-id: ${{ github.event.deployment.id }}
description: Finish to deploy successfully.
log-url: https://gitploy.jp.ngrok.io/applications/${{ github.event.deployment.payload.application }}
state: "success"
token: "${{ github.token }}"
-
if: failure()
uses: chrnorm/deployment-status@releases/v2
with:
deployment-id: ${{ github.event.deployment.id }}
description: Failed to deploy.
log-url: https://gitploy.jp.ngrok.io/applications/${{ github.event.deployment.payload.application }}
state: "failure"
token: "${{ github.token }}"

Now, when we deploy from Gitploy, we can see that the Argo CD pins the Application to the manifests defined at the specified commit. More details for the demo can be found in this repository. :)

Application

· 3 min read

Having a well-tuned workflow keeps a team productive and helps them deliver reliable software. One recommended practice for any significant software development is using multiple environments. Using multiple environments ensures that software is rigorously tested before deployed and made available to users.

A general way for deploying to an environment is the branch strategy. Users create branches for each environment and deploy them by pushing a commit to the branch. Then, The deployment tool such as GitHub Action or Circle CI will deploy to the environment corresponding to the branch name.

The following is an example that deploy to the Azure Function App by a GitHub Action. Firstly, it wants to trigger the workflow on push events for specific branches such as dev, staging and prod. And in the steps, through the if syntax, the workflow deploys it to a different environment for each branch.

Deploy By Branch Push
.github/workflows/deploy-by-branch.yaml
on:
push:
branches:
- dev
- staging
- prod

jobs:
deploy:
runs-on: ubuntu-latest
steps:
-
name: Set env vars for dev
if: github.ref_name == 'dev'
run: |
echo "AZURE_FUNCTIONAPP_NAME=gitploy-dev" >> $GITHUB_ENV
echo "PUBLISH_PROFILE_VAR_NAME=AZURE_FUNCTIONAPP_PUBLISH_PROFILE_DEV" >> $GITHUB_ENV
-
name: Set env vars for prod
if: github.ref_name == 'prod'
run: |
echo "AZURE_FUNCTIONAPP_NAME=gitploy-prod" >> $GITHUB_ENV
echo "PUBLISH_PROFILE_VAR_NAME=AZURE_FUNCTIONAPP_PUBLISH_PROFILE_PROD" >> $GITHUB_ENV
-
uses: Azure/functions-action@v1
with:
app-name: ${{ env.AZURE_FUNCTIONAPP_NAME }}
publish-profile: ${{ secrets[env.PUBLISH_PROFILE_VAR_NAME] }}
respect-funcignore: true

However, although the branch strategy is easy and fast, it is not flexible and scalable. The user must create a new branch and modify the workflow if a new environment is added.

On the other hand, Gitploy provides another solution. Gitploy dispatches an event that includes information necessary for deployment, such as the environment name, Function App name, and so on, through the deployment API.

To activate Gitploy, we should place the deploy.yml file in the root of the git repository like below. Note that the payload field has the informations for deployment, and it has different information for each environment, respectively. When a user triggers, the payload is passed to the deployment tooling.

deploy.yml
deploy.yml
envs:
- name: dev
auto_merge: false
payload:
AZURE_FUNCTIONAPP_NAME: gitploy-dev
PUBLISH_PROFILE_VAR_NAME: AZURE_FUNCTIONAPP_PUBLISH_PROFILE_DEV
- name: prod
auto_merge: false
payload:
AZURE_FUNCTIONAPP_NAME: gitploy-prod
PUBLISH_PROFILE_VAR_NAME: AZURE_FUNCTIONAPP_PUBLISH_PROFILE_PROD

And in the workflow, the information for deployment is read through the github.event.deployment.payload context so that the workflow does not need if syntax for conditional steps anymore.

Deploy By Gitploy
.github/workflows/deploy-by-gitploy.yaml
on:
deployment

jobs:
deploy:
runs-on: ubuntu-latest
steps:
-
uses: chrnorm/deployment-status@releases/v1
with:
deployment_id: ${{ github.event.deployment.id }}
description: Start to deploy.
state: "in_progress"
token: "${{ github.token }}"

-
uses: Azure/functions-action@v1
with:
app-name: ${{ github.event.deployment.payload['AZURE_FUNCTIONAPP_NAME'] }}
publish-profile: ${{ secrets[github.event.deployment.payload['PUBLISH_PROFILE_VAR_NAME'] }}
respect-funcignore: true

-
if: success()
uses: chrnorm/deployment-status@releases/v1
with:
deployment_id: ${{ github.event.deployment.id }}
description: Success to deploy.
state: "success"
token: "${{ github.token }}"
-
if: failure()
uses: chrnorm/deployment-status@releases/v1
with:
deployment_id: ${{ github.event.deployment.id }}
description: Failed to deploy.
state: "failure"
token: "${{ github.token }}"

Finally, when you trigger on Gitploy, you can see that it successfully deploys to the environment. 🚀

Demo

Thanks for reading, and stay tuned for a more good read. If you have a question, please post questions or comments to our community

Reference