In this blog post we are going to introduce Multi-cluster Management patterns with GitOps and how you can implement these patterns on OpenShift.
If you’re interested in diving into an interactive tutorial, try this link.
In the introductory blog post to GitOps we described some of the use cases that we can solve with GitOps on OpenShift. In
today's blog post we are going to describe how we can leverage GitOps patterns to perform tasks on multiple clusters.
We are going to explore the following use cases:
- Deploy an application to multiple clusters
- Customize the application by cluster
- Perform a canary deployment
During this blog post we are not going to cover advanced GitOps workflows, instead we are going to show you basic capabilities around
the topic. More advanced posts around GitOps workflows will follow.
Environment
- Two OpenShift 4.1 clusters, one for
preproduction(context: pre) environment and one forproduction(context: pro) environment. - ArgoCD used as the GitOps tool
- Demo files here
Deploy an Application to Multiple Clusters
In this first example, we are going to deploy our base application to both clusters.
As we are using ArgoCD as our GitOps tool an ArgoCD Server is already deployed in our environment as well as the argocd cli tool.
Our application definition can be found here
- Ensure we have access to both clusters
$ oc --context pre get nodes
NAME STATUS ROLES AGE VERSION
ip-10-0-128-17.ap-southeast-1.compute.internal Ready master 19h v1.13.4+ab8449285
ip-10-0-136-41.ap-southeast-1.compute.internal Ready worker 19h v1.13.4+ab8449285
ip-10-0-151-90.ap-southeast-1.compute.internal Ready worker 19h v1.13.4+ab8449285$ oc --context pro get nodes
NAME STATUS ROLES AGE VERSION
ip-10-0-140-239.ap-southeast-1.compute.internal Ready master 19h v1.13.4+ab8449285
ip-10-0-142-57.ap-southeast-1.compute.internal Ready worker 19h v1.13.4+ab8449285
ip-10-0-170-168.ap-southeast-1.compute.internal Ready worker 19h v1.13.4+ab8449285
- Ensure we have our clusters registered in ArgoCD
$ argocd cluster list
SERVER NAME STATUS MESSAGE
https://api.openshift.pre.example.com:6443 pre Successful
https://api.openshift.pro.example.com:6443 pro Successful
https://kubernetes.default.svc Successful
- Add our GitOps repository to ArgoCD
$ argocd repo add https://github.com/mvazquezc/gitops-demo.gitrepository 'https://github.com/mvazquezc/gitops-demo.git' added
- Deploy our application to preproduction and production clusters
# Create the application on Preproduction cluster
$ argocd app create --project default --name pre-reversewords --repo https://github.com/mvazquezc/gitops-demo.git --path reversewords_app/base --dest-server https://api.openshift.pre.example.com:6443 --dest-namespace reverse-words --revision preapplication 'pre-reversewords' created
# Create the application on Production cluster
$ argocd app create --project default --name pro-reversewords --repo https://github.com/mvazquezc/gitops-demo.git --path reversewords_app/base --dest-server https://api.openshift.pro.example.com:6443 --dest-namespace reverse-words --revision proapplication 'pro-reversewords' created
4.1 Above commands create a new ArgoCD Application named
pre-reversewordsandpro-reversewordsthat will be deployed onpreproductionandproductionclusters in reverse-words namespace using the code frompre/probranch located under pathreversewords_app/base -
As we haven't defined a sync policy, we need to force ArgoCD to sync the Git repo content on our
preandproclusters$ argocd app sync pre-reversewords
$ argocd app sync pro-reversewords
- After a few seconds we will see our application deployed on
preandproclusters# Get application status on preproduction cluster
$ argocd app get pre-reversewordsName: pre-reversewords
Project: default
Server: https://api.openshift.pre.example.com:6443
Namespace: reverse-words
URL: https://argocd.apps.example.com/applications/pre-reversewords
Repo: https://github.com/mvazquezc/gitops-demo.git
Target: pre
Path: reversewords_app/base
Sync Policy: <none>
Sync Status: Synced to pre (306ce10)
Health Status: HealthyGROUP KIND NAMESPACE NAME STATUS HEALTH
Namespace reverse-words Synced
Service reverse-words reverse-words Synced Healthy
apps Deployment reverse-words reverse-words Synced Healthy# Get application status on production cluster
$ argocd app get pro-reversewordsName: pro-reversewords
Project: default
Server: https://api.openshift.pro.example.com:6443
Namespace: reverse-words
URL: https://argocd.apps.example.com/applications/pro-reversewords
Repo: https://github.com/mvazquezc/gitops-demo.git
Target: pro
Path: reversewords_app/base
Sync Policy: <none>
Sync Status: Synced to pro (98bbfb1)
Health Status: HealthyGROUP KIND NAMESPACE NAME STATUS HEALTH
Namespace reverse-words Synced
Service reverse-words reverse-words Synced Healthy
apps Deployment reverse-words reverse-words Synced Healthy
- Our application defines a service for accessing its API, let's try to access and get the release name for both clusters
# Get the preproduction cluster LB hostname
$ PRE_LB_HOSTNAME=$(oc --context pre -n reverse-words get svc reverse-words -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')
# Get the production cluster LB hostname
$ PRO_LB_HOSTNAME=$(oc --context pro -n reverse-words get svc reverse-words -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')
# Access the preproduccion LB and get the release name
$ curl http://${PRE_LB_HOSTNAME}:8080Reverse Words Release: Base release. App version: v0.0.2
# Access the production LB and get the release name
$ curl http://${PRO_LB_HOSTNAME}:8080Reverse Words Release: Base release. App version: v0.0.2
As you have seen, we have been able to deploy to multiple clusters from a single tool (ArgoCD). In the next section we are going to explore how we can override some configurations depending on the destination cluster by using embedded Kustomize on ArgoCD.
Customize the Application by Cluster
In this second example, we are going to modify the application behavior depending on which cluster is deployed.
We want the application to have a release name preproduction or production depending on which environment the application gets deployed on.
ArgoCD leverages Kustomize under the hood to deal with configuration overrides across environments.
The way we organize our application in Git is as follows:
- The Git Repository has two branches,
prewhich has manifests for preproduction env, andprofor production env.
Application overrides can be found in their respective folders and branch:
- We placed the application overrides in the Git repository, there is only one override that configures a release name different than the default based on the cluster the application gets deployed
- Deploy our
Kustomizedapplication to preproduction and production clusters# Create the application on Preproduction cluster
argocd app create --project default --name pre-kustomize-reversewords --repo https://github.com/mvazquezc/gitops-demo.git --path reversewords_app/overlays/pre --dest-server https://api.openshift.pre.example.com:6443 --dest-namespace reverse-words --revision pre --sync-policy automatedapplication 'pre-kustomize-reversewords' created
# Create the application on Production cluster
argocd app create --project default --name pro-kustomize-reversewords --repo https://github.com/mvazquezc/gitops-demo.git --path reversewords_app/overlays/pro --dest-server https://api.openshift.pro.example.com:6443 --dest-namespace reverse-words --revision pro --sync-policy automatedapplication 'pro-kustomize-reversewords' created
2.1 Above commands create a new ArgoCD Application named
pre-kustomize-reversewordsandpro-kustomize-reversewordsthat will be deployed onpreproductionandproductionclusters in reverse-words namespace using the code frompreandprobranch respectively. Each application will get the code from a different folder in ouroverlaysfolder, that way the application will be customized depending on which environment it gets deployed on. Note that only the modified values are stored in the overlay folder, the base application is still deployed from thebasefolder, so we don't end up having duplicate application files. -
As we have defined an
automatedsync policy we don't need to force the sync, ArgoCD will start synching our application once it gets created. On top of that, if changes were made to the application repository, ArgoCD would re-deploy the changes for us. -
After a few seconds we will see our application deployed on
precluster# Get application status on preproduction cluster
$ argocd app get pre-kustomize-reversewordsName: pre-kustomize-reversewords
Project: default
Server: https://api.openshift.pre.example.com:6443
Namespace: reverse-words
URL: https://argocd.apps.example.com/applications/pre-kustomize-reversewords
Repo: https://github.com/mvazquezc/gitops-demo.git
Target: pre
Path: reversewords_app/overlays/pre
Sync Policy: Automated
Sync Status: Synced to pre (306ce10)
Health Status: HealthyGROUP KIND NAMESPACE NAME STATUS HEALTH
Namespace reverse-words Synced
Service reverse-words reverse-words Synced Healthy
apps Deployment reverse-words reverse-words Synced Healthy# Get application status on production cluster
$ argocd app get pro-kustomize-reversewordsName: pro-kustomize-reversewords
Project: default
Server: https://api.openshift.pro.example.com:6443
Namespace: reverse-words
URL: https://argocd.apps.example.com/applications/pro-kustomize-reversewords
Repo: https://github.com/mvazquezc/gitops-demo.git
Target: pro
Path: reversewords_app/overlays/pro
Sync Policy: Automated
Sync Status: Synced to pro (98bbfb1)
Health Status: HealthyGROUP KIND NAMESPACE NAME STATUS HEALTH
Namespace reverse-words Synced
Service reverse-words reverse-words Synced Healthy
apps Deployment reverse-words reverse-words Synced Healthy
- Our application defines a service for accessing its API, let's try to access and get the release name for both clusters
# Get the preproduction cluster LB hostname
$ PRE_LB_HOSTNAME=$(oc --context pre -n reverse-words get svc reverse-words -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')
# Get the production cluster LB hostname
$ PRO_LB_HOSTNAME=$(oc --context pro -n reverse-words get svc reverse-words -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')
# Access the preproduccion LB and get the release name
$ curl http://${PRE_LB_HOSTNAME}:8080Reverse Words Release: Preproduction release. App version: v0.0.2
# Access the production LB and get the release name
$ curl http://${PRO_LB_HOSTNAME}:8080Reverse Words Release: Production release. App version: v0.0.2
As you have seen, we have been able to deploy to multiple clusters and use custom configurations depending on which cluster we are using to deploy the application. In the next section we are going to explore how we can use GitOps to perform a basic canary deployment.
Perform a Canary Deployment
A common practice is to deploy a new version of an application to a small subset of the available clusters, and once the application has been proven to work as expected, then it gets promoted to the rest of the clusters.
We are going to use the Kustomized apps that we created before, let's verify which versions are we running:
# Get the preproduction cluster LB hostname
$ PRE_LB_HOSTNAME=$(oc --context pre -n reverse-words get svc reverse-words -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')
# Get the production cluster LB hostname
$ PRO_LB_HOSTNAME=$(oc --context pro -n reverse-words get svc reverse-words -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')
# Access the preproduccion LB and get the release name
$ curl http://${PRE_LB_HOSTNAME}:8080Reverse Words Release: Preproduction release. App version: v0.0.2
# Access the production LB and get the release name
$ curl http://${PRO_LB_HOSTNAME}:8080
Reverse Words Release: Production release. App version: v0.0.2
As you can see the current deployed version is v0.0.2, let's perform a canary deployment to v0.0.3.
- We need to update the container image that will be used on preproduction cluster, we are going to modify the Deployment overlay as follows:
# reversewords_app/overlays/pre/deployment.yaml in git branch pre
apiVersion: apps/v1
kind: Deployment
metadata:
name: reverse-words
labels:
app: reverse-words
spec:
template:
spec:
containers:
- name: reverse-words
image: quay.io/mavazque/reversewords:v0.0.3
env:
- name: RELEASE
value: "Preproduction release"
- $patch: replace
- We send our changes to the git repository
git add reversewords_app/overlays/pre/deployment.yaml
git commit -m "Updated preproduction image version from v0.0.2 to v0.0.3"
git push origin pre
- ArgoCD will detect the update in our code and will deploy the new changes, now we should see the version
v0.0.3deployed on pre and the versionv0.0.2deployed on pro.# Access the preproduccion LB and get the release name
$ curl http://${PRE_LB_HOSTNAME}:8080Reverse Words Release: Preproduction release. App version: v0.0.3
# Access the production LB and get the release name
$ curl http://${PRO_LB_HOSTNAME}:8080Reverse Words Release: Production release. App version: v0.0.2
- Let's verify that our application is working as expected
$ curl http://${PRE_LB_HOSTNAME}:8080 -X POST -d '{"word":"PALC"}'{"reverse_word":"CLAP"}
- The application is working fine, now it's time to update production to
v0.0.3as well. Let's update the overlay:# reversewords_app/overlays/pro/deployment.yaml in git branch pro
apiVersion: apps/v1
kind: Deployment
metadata:
name: reverse-words
labels:
app: reverse-words
spec:
template:
spec:
containers:
- name: reverse-words
image: quay.io/mavazque/reversewords:v0.0.3
env:
- name: RELEASE
value: "Production release"
- $patch: replace
- Send the changes to Git
git add reversewords_app/overlays/pro/deployment.yaml
git commit -m "Updated production image version from v0.0.2 to v0.0.3"
git push origin pro
- Get versions in use
# Access the preproduccion LB and get the release name
$ curl http://${PRE_LB_HOSTNAME}:8080Reverse Words Release: Preproduction release. App version: v0.0.3
# Access the production LB and get the release name
$ curl http://${PRO_LB_HOSTNAME}:8080Reverse Words Release: Production release. App version: v0.0.3
- We should now update the base deployment so newer deployments use
v0.0.3version
Final Thoughts
- We have updated our application by modifying the application overlays in Git, this is a very basic scenario, advanced scenarios may include CI tests, multiple approvals, etc.
-
We have pushed our code to the
pre/probranches directly, that is not a good practice, in a real life scenario a more advanced workflow should be used. We will discuss GitOps workflows in future blog posts. -
We have ArgoCD Cli, ArgoCD has a WebUI where you can do almost the same operations as with the cli, on top of that you can visualize your applications and its components.
Next Steps
In future blog posts we will talk about multiple topics related to GitOps such as:
- GitOps Workflows in Production
- Disaster Recovery with GitOps
- Moving to GitOps
À propos de l'auteur
Plus de résultats similaires
Red Hat and Sylva unify the future for telco cloud
Bridging the gap: Secure virtual and container workloads with Red Hat OpenShift and Palo Alto Networks
Can Kubernetes Help People Find Love? | Compiler
Scaling For Complexity With Container Adoption | Code Comments
Parcourir par canal
Automatisation
Les dernières nouveautés en matière d'automatisation informatique pour les technologies, les équipes et les environnements
Intelligence artificielle
Actualité sur les plateformes qui permettent aux clients d'exécuter des charges de travail d'IA sur tout type d'environnement
Cloud hybride ouvert
Découvrez comment créer un avenir flexible grâce au cloud hybride
Sécurité
Les dernières actualités sur la façon dont nous réduisons les risques dans tous les environnements et technologies
Edge computing
Actualité sur les plateformes qui simplifient les opérations en périphérie
Infrastructure
Les dernières nouveautés sur la plateforme Linux d'entreprise leader au monde
Applications
À l’intérieur de nos solutions aux défis d’application les plus difficiles
Virtualisation
L'avenir de la virtualisation d'entreprise pour vos charges de travail sur site ou sur le cloud