Cloud Native MQ GitOps Configuration¶
In the cluster configuration of this chapter, we installed the fundamental components for continuous integration and continuous deployment into our cluster. These included a sample GitOps repository, and ArgoCD.
In this section we're going to customize and enable the GitOps repository, so that we can install the components highlighted in our CP4S CICD process:
We'll examine these components in more detail throughout this section of the tutorial; here's an initial overview of their function:
ci-namespaceprovide an execution namespace for our pipelinestools-namespaceprovide an execution namespace for tools such as Artifactorycp4s-namespaceprovide an execution namespace for our deployed CP4S when running in the development environment. Later in the tutorial, we'll addstagingandprodnamespaces.ArgoCD applicationsmanage theci,toolsanddevnamespaces.
You may have already noticed that the GitOps repository contains YAMLs that refer to the ArgoCD and namespaces in the diagram above. We're now going to use these YAMLs to configure the cluster resources using GitOps.
Becoming comfortable with the concepts by practicing GitOps will help us in later chapters when we CP4S Cloud Pak
In this topic, we're going to:
- Explore the sample GitOps repository in a little more detail
- Customize the GitOps repository for our cluster
- Connect ArgoCD to the customized GitOps repository
- Bootstrap the cluster
- Explore how the
cinamespace is created - Try out some dynamic changes to the cluster with ArgoCD
- Explore how ArgoCD manages configuration drift
By the end of this topic we'll have a cluster up and running, having used GitOps to do it. We'll fully understand how ArgoCD manages cluster change and configuration drift.
Pre-requisites¶
Before attempting this section, you must have completed the following tasks:
- You have created an OCP cluster instance.
- You have installed on your local machine the
occommand that matches the version of your cluster. - You have also installed
npm,gitandtreecommands. - You have customized the GitOps repository and ArgoCD.
Please see the previous sections of this guide for information on how to do these tasks.
Video Walkthrough¶
This video demonstrates how to use ArgoCD and the GitOps repository to set up different infra related components.
This is a video walkthrough and it takes you step by step through the below sections.
The sample GitOps repository¶
Let's understand how GitOps works in practice by using it to install the components we've highlighted in the above diagram.
Let's first look at the high level structure of the multi-tenancy-gitops GitOps repository.
-
Ensure you're logged in to the cluster
Tip
Ensure you're in the terminal window that you used to set up your cluster, i.e. in the
multi-tenancy-gitopssubfolder.Log into your OCP cluster, substituting the
--tokenand--serverparameters with your values:oc login --token=<token> --server=<server>If you are unsure of these values, click your user ID in the OpenShift web console and select "Copy Login Command".
-
Locate your GitOps repository
If necessary, change to the root of your GitOps repository, which is stored in the
$GIT_ROOTenvironment variable.Issue the following command to change to your GitOps repository:
cd $GIT_ROOT cd multi-tenancy-gitops -
Explore the high level folder structure
Use the following command to display the folder structure:
tree . -d -L 2We can see the different folders in the GitOps repository:
. ├── 0-bootstrap │ ├── others │ └── single-cluster ├── doc │ ├── diagrams │ ├── experimental │ ├── images │ └── scenarios ├── scripts │ └── bom └── setup ├── ocp47 └── ocp4xThe
0-bootstrapfolder is the key folder that contains different profiles for different cluster topologies. A Cluster Profile such assingle-clusterwill control resources are deployed to a single cluster. We'll be using thesingle-clusterprofile, although you can see that other profiles are available.There are other folders containing utility scripts and some documentation; we'll explore these later.
-
The
0-bootstrapfolderThe process of installing components into a cluster is called bootstrapping because it's the first thing that happens to a cluster after it has been created. We will bootstrap our cluster using the
0-bootstrapfolder in themulti-tenancyrepository.Let us examine the
0-bootstrapfolder structure:tree ./0-bootstrap/ -d -L 2We can see the different folders:
./0-bootstrap/ ├── others │ ├── 1-shared-cluster │ ├── 2-isolated-cluster │ └── 3-multi-cluster └── single-cluster ├── 1-infra ├── 2-services └── 3-appsNotice the different cluster profiles. We're going to use the
single-clusterprofile. See how this profile has three sub-folders corresponding to three layers of components: infrastructure, services and applications. Every component in our architecture will be in one of these layers. -
The
single-clusterprofile in more detailUse the following command to display
single-clusterfolder in more detail:tree ./0-bootstrap/single-cluster/ -L 2We can see the different folders:
./0-bootstrap/single-cluster/ ├── 1-infra │ ├── 1-infra.yaml │ ├── argocd │ └── kustomization.yaml ├── 2-services │ ├── 2-services.yaml │ ├── argocd │ └── kustomization.yaml ├── 3-apps │ ├── 3-apps.yaml │ ├── argocd │ └── kustomization.yaml ├── bootstrap.yaml └── kustomization.yamlAgain, see the different layers of the architecture: infrastructure, service and application.
Notice how each of these high level folders (
1-infra,2-services,3-applications) has anargocdfolder. Theseargocdfolders contain the ArgoCD applications that control which resources in that architectural layer are deployed to the cluster. -
ArgoCD applications
Later in this tutorial, we'll see in detail how these ArgoCD applications work. For now, let's explore the range of ArgoCD applications that control the infrastructure components deployed to the cluster.
Type the following command :
tree 0-bootstrap/single-cluster/1-infra/It shows a list of ArgoCD applications that are used to manage Kubernetes infrastructure resources:
0-bootstrap/single-cluster/1-infra/ ├── 1-infra.yaml ├── argocd │ ├── consolelink.yaml │ ├── consolenotification.yaml │ ├── infraconfig.yaml │ ├── machinesets.yaml │ ├── namespace-baas.yaml │ ├── namespace-ci.yaml │ ├── namespace-cloudpak.yaml │ ├── namespace-db2.yaml │ ├── namespace-dev.yaml │ ├── namespace-ibm-common-services.yaml │ ├── namespace-instana-agent.yaml │ ├── namespace-istio-system.yaml │ ├── namespace-mq.yaml │ ├── namespace-openldap.yaml │ ├── namespace-openshift-storage.yaml │ ├── namespace-prod.yaml │ ├── namespace-robot-shop.yaml │ ├── namespace-sealed-secrets.yaml │ ├── namespace-spp-velero.yaml │ ├── namespace-spp.yaml │ ├── namespace-staging.yaml │ ├── namespace-tools.yaml │ ├── scc-wkc-iis.yaml │ ├── serviceaccounts-db2.yaml │ ├── serviceaccounts-ibm-common-services.yaml │ ├── serviceaccounts-mq.yaml │ ├── serviceaccounts-tools.yaml │ └── storage.yaml └── kustomization.yamlNotice the many
namespace-YAMLs; we'll see in a moment how these each define an ArgoCD application dedicated to managing a Kubernetes namespace in our cluster. theserviceaccount-YAMLs can similarly manage service accounts.There are similar ArgoCD applications for the service and application layers. Feel free to examine their corresponding folders; we will look at them in more detail later.
-
A word on terminology
As we get started with ArgoCD, it can be easy to confuse the term ArgoCD application with your application. That's because ArgoCD uses the term application to refer to a Kubernetes custom resource that was initially designed to manage a set of application resources. However, an ArgoCD application can automate the deployment of any Kubernetes resource within a cluster, such as a namespace, as we'll see a little later.
Why customize¶
We're now going to customize two of the sample GitOps repositories to enable them to be used by ArgoCD to deploy Kubernetes resources to your particular cluster. The process of customization is important to understand; we will use it throughout the tutorial.
Recall the different roles of the four repositories:
multi-tenancy-gitopsis the main GitOps repository. It contains the ArgoCD YAMLs for the fixed components in the cluster such as a namespace or a Tekton or SonarQube instance.multi-tenancy-gitops-infrais a library repository. It contains infrastructure YAMLs referred to by the ArgoCD YAMLs that manage infrastructure in the cluster, such as a namespace.multi-tenancy-gitops-servicesis a library repository. It contains the service YAMLs referred to the ArgoCD YAMLs that manage services in the cluster such as Tekton or SonarQube.multi-tenancy-gitops-appsis a GitOps repository containing the user application components that are deployed to the cluster. These components include applications, databases and queue managers, for example.
It is the multi-tenancy-gitops and multi-tenancy-gitops-apps repositories that need to be customized for your cluster. The other two repositories don't need to be customized because they perform the function of a library.
Tailor multi-tenancy-gitops¶
Let now customize the multi-tenancy-gitops repository for your organization. The repository provides a script that uses the $GIT_ORG environment variable to replace the generic values in the cloned repository with those of your GitHub organization.
Once customized, we'll push our updated repository back to GitHub where it can be accessed by ArgoCD.
-
Set your git branch
In this tutorial, we use the
masterbranch of themulti-tenancy-gitopsrepository. We will store this in the$GIT_BRANCHenvironment variable for use by various scripts and commands.Issue the following command to set its value:
export GIT_BRANCH=masterYou can verify your
$GIT_BRANCHas follows:echo $GIT_BRANCH -
Run the customization script
We customize the cloned
multi-tenancy-gitopsrepository to the relevant values for our cluster using theset-git-source.shscript. This script will replace various YAML elements in this repository to refer to your git organization via a GitHub URL.Now run the script:
./scripts/set-git-source.shThe script will list customizations it will use and all the files that it customizes:
Setting kustomization patches to https://github.com/prod-ref-guide/multi-tenancy-gitops.git on branch master Setting kustomization patches to https://github.com/prod-ref-guide/multi-tenancy-gitops-infra.git on branch master Setting kustomization patches to https://github.com/prod-ref-guide/multi-tenancy-gitops-services.git on branch master Setting kustomization patches to https://github.com/prod-ref-guide/multi-tenancy-gitops-apps.git on branch master done replacing variables in kustomization.yaml files git commit and push changes now -
Explore the customization changes
You can easily identify all the files that have been customized using the
git statuscommand.Issue the following command:
git statusto view the complete set of changed files in the
multi-tenancy-gitopsrepository:On branch master Your branch is up to date with 'origin/master'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: 0-bootstrap/bootstrap.yaml modified: 0-bootstrap/others/1-shared-cluster/bootstrap-cluster-1-cicd-dev-stage-prod.yaml modified: 0-bootstrap/others/1-shared-cluster/bootstrap-cluster-n-prod.yaml ... modified: 0-bootstrap/single-cluster/kustomization.yaml(We've abbreviated the list.)
You can see the kind of changes that the script has made with
git diffcommand:git diff 0-bootstrap/bootstrap.yamlwhich calculates the differences in the file as:
diff --git a/0-bootstrap/bootstrap.yaml b/0-bootstrap/bootstrap.yaml index 0754133..7303c53 100644 --- a/0-bootstrap/bootstrap.yaml +++ b/0-bootstrap/bootstrap.yaml @@ -10,8 +10,8 @@ spec: project: default source: path: 0-bootstrap/single-cluster - repoURL: ${GIT_BASEURL}/${GIT_ORG}/${GIT_GITOPS} - targetRevision: ${GIT_GITOPS_BRANCH} + repoURL: https://github.com/tutorial-org-123/multi-tenancy-gitops.git + targetRevision: master syncPolicy: automated: prune: trueSee how the
repoURLandtargetRevisionYAML elements now refer to your organization in GitHub rather than a generic name.By making YAMLs like this active in your cluster, ArgoCD is able to refer to your repository to manage its contents.
-
Add the changes to a git index, ready to push to GitHub
Now that we've customized the local clone of the
multi-tenancy-gitopsrepository, we should commit the changes, and push them back to GitHub where they can be accessed by ArgoCD.Firstly, we the changes to a git index:
git add . -
Commit the changes to git
We then commit these changes to git index:
git commit -s -m "GitOps customizations for organization and cluster"which will show the commit message:
[master a900c39] GitOps customizations for organization and cluster 46 files changed, 176 insertions(+), 176 deletions(-) -
Push changes to GitHub
Finally, we push this commit back to the
masterbranch on GitHub:git push origin $GIT_BRANCHwhich shows that the changes have now been pushed to your GitOps repository:
Enumerating objects: 90, done. Counting objects: 100% (90/90), done. Delta compression using up to 8 threads Compressing objects: 100% (47/47), done. Writing objects: 100% (48/48), 4.70 KiB | 1.57 MiB/s, done. Total 48 (delta 32), reused 0 (delta 0) remote: Resolving deltas: 100% (32/32), completed with 23 local objects. To https://github.com/tutorial-org-123/multi-tenancy-gitops.git d95eca5..a900c39 master -> masterWe've now customized the
multi-tenancy-gitopsrepository for your organization, and successfully pushed it to GitHub.
Connect ArgoCD to the GitOps repository¶
Let's now connect your customized GitOps repository to the instance of ArgoCD running in the cluster. Once connected, ArgoCD will use the contents of the repository to create necessary resources.
-
Locate your GitOps repository
If necessary, change to the root of your GitOps repository, which is stored in the
$GIT_ROOTenvironment variable.Issue the following command to change to your GitOps repository:
cd $GIT_ROOT cd multi-tenancy-gitops -
Review ArgoCD infrastructure folder
Let's examine the
0-bootstrap/single-cluster/1-infra/kustomization.yamlto see how ArgoCD manages the resources deployed to the cluster.Issue the following command:
cat 0-bootstrap/single-cluster/1-infra/kustomization.yamlWe can see the contents of the
kustomization.yaml:resources: #- argocd/consolelink.yaml #- argocd/consolenotification.yaml #- argocd/namespace-ibm-common-services.yaml #- argocd/namespace-ci.yaml #- argocd/namespace-dev.yaml #- argocd/namespace-staging.yaml #- argocd/namespace-prod.yaml #- argocd/namespace-cloudpak.yaml #- argocd/namespace-istio-system.yaml #- argocd/namespace-openldap.yaml #- argocd/namespace-sealed-secrets.yaml #- argocd/namespace-tools.yaml #- argocd/namespace-instana-agent.yaml #- argocd/namespace-robot-shop.yaml #- argocd/namespace-openshift-storage.yaml #- argocd/namespace-spp.yaml #- argocd/namespace-spp-velero.yaml #- argocd/namespace-baas.yaml #- argocd/serviceaccounts-tools.yaml #- argocd/storage.yaml #- argocd/infraconfig.yaml #- argocd/machinesets.yaml patches: - target: group: argoproj.io kind: Application labelSelector: "gitops.tier.layer=infra" patch: |- - op: add path: /spec/source/repoURL value: https://github.com/prod-ref-guide/multi-tenancy-gitops-infra.git - op: add path: /spec/source/targetRevision value: masterNotice that the resources that needs to be applied to the cluster are all
inactivateand commented out.Let us
enablethe resources that are needed by un-commenting them. -
Deploy Kubernetes resources with
kustomization.yamlOpen
0-bootstrap/single-cluster/1-infra/kustomization.yamland uncomment the below resources:argocd/namespace-ci.yaml argocd/consolenotification.yaml argocd/namespace-ibm-common-services.yaml argocd/namespace-tools.yamlYou will have the following resources un-commented for infrastructure:
resources: #- argocd/consolelink.yaml - argocd/consolenotification.yaml - argocd/namespace-ibm-common-services.yaml - argocd/namespace-ci.yaml #- argocd/namespace-dev.yaml #- argocd/namespace-staging.yaml #- argocd/namespace-prod.yaml #- argocd/namespace-cloudpak.yaml #- argocd/namespace-istio-system.yaml #- argocd/namespace-openldap.yaml #- argocd/namespace-sealed-secrets.yaml - argocd/namespace-tools.yaml #- argocd/namespace-instana-agent.yaml #- argocd/namespace-robot-shop.yaml #- argocd/namespace-openshift-storage.yaml #- argocd/namespace-spp.yaml #- argocd/namespace-spp-velero.yaml #- argocd/namespace-baas.yaml #- argocd/serviceaccounts-tools.yaml #- argocd/storage.yaml #- argocd/infraconfig.yaml #- argocd/machinesets.yaml patches: - target: group: argoproj.io kind: Application labelSelector: "gitops.tier.layer=infra" patch: |- - op: add path: /spec/source/repoURL value: https://github.com/prod-ref-guide/multi-tenancy-gitops-infra.git - op: add path: /spec/source/targetRevision value: masterCommit and push changes to your git repository:
git add . git commit -s -m "Intial boostrap setup for infrastructure" git push origin $GIT_BRANCHThe changes have now been pushed to your GitOps repository:
Enumerating objects: 11, done. Counting objects: 100% (11/11), done. Delta compression using up to 8 threads Compressing objects: 100% (6/6), done. Writing objects: 100% (6/6), 576 bytes | 576.00 KiB/s, done. Total 6 (delta 5), reused 0 (delta 0) remote: Resolving deltas: 100% (5/5), completed with 5 local objects. To https://github.com/prod-ref-guide/multi-tenancy-gitops.git a900c39..e3f696d master -> master -
Examine
bootstrap.yamlresiding in0-bootstrap/single-cluster/.The
bootstrap.yamlfile is used to create our first ArgoCD application calledbootstrap-single-cluster. This initial ArgoCD application will create all the other ArgoCD applications that control the application, service, and infrastructure resources (such as the ci and dev namespaces) deployed to the cluster.Examine the YAML that defines the ArgoCD bootstrap application:
cat 0-bootstrap/single-cluster/bootstrap.yamlNotice also how this ArgoCD application has been customized to use the GitOps repository repoURL:
https://github.com/prod-ref-guide/multi-tenancy-gitops.git.apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: bootstrap-single-cluster namespace: openshift-gitops spec: destination: namespace: openshift-gitops server: https://kubernetes.default.svc project: default source: path: 0-bootstrap/single-cluster repoURL: https://github.com/prod-ref-guide/multi-tenancy-gitops.git targetRevision: master syncPolicy: automated: prune: true selfHeal: trueMost importantly, see how
path: 0-bootstrap/single-clusterrefers to the0-bootstrap/single-clusterfolder within this repository. This will result in the creation of individual ArgoCD applications to manage our cluster resources.Access the
0-bootstrap/single-cluster/kustomization.yaml:cat 0-bootstrap/single-cluster/kustomization.yamlLet us for now only deploy
infraresources to the cluster. Open0-bootstrap/single-cluster/kustomization.yamland comment out the2-services/2-services.yamland3-apps/3-apps.yamlas follows:resources: - 1-infra/1-infra.yaml # - 2-services/2-services.yaml # - 3-apps/3-apps.yaml patches: - target: group: argoproj.io kind: Application labelSelector: "gitops.tier.layer=gitops" patch: |- - op: add path: /spec/source/repoURL value: https://github.com/prod-ref-guide/multi-tenancy-gitops.git - op: add path: /spec/source/targetRevision value: master - target: group: argoproj.io kind: AppProject labelSelector: "gitops.tier.layer=infra" patch: |- - op: add path: /spec/sourceRepos/- value: https://github.com/prod-ref-guide/multi-tenancy-gitops.git - op: add path: /spec/sourceRepos/- value: https://github.com/prod-ref-guide/multi-tenancy-gitops-infra.git - target: group: argoproj.io kind: AppProject labelSelector: "gitops.tier.layer=services" patch: |- - op: add path: /spec/sourceRepos/- value: https://github.com/prod-ref-guide/multi-tenancy-gitops.git - op: add path: /spec/sourceRepos/- value: https://github.com/prod-ref-guide/multi-tenancy-gitops-services.git - target: group: argoproj.io kind: AppProject labelSelector: "gitops.tier.layer=applications" patch: |- - op: add path: /spec/sourceRepos/- value: https://github.com/prod-ref-guide/multi-tenancy-gitops.git - op: add path: /spec/sourceRepos/- value: https://github.com/prod-ref-guide/multi-tenancy-gitops-apps.gitCommit and push changes to your git repository:
git add . git commit -s -m "Using only infra" git push origin $GIT_BRANCHThe changes have now been pushed to your GitOps repository:
Enumerating objects: 9, done. Counting objects: 100% (9/9), done. Delta compression using up to 8 threads Compressing objects: 100% (5/5), done. Writing objects: 100% (5/5), 456 bytes | 456.00 KiB/s, done. Total 5 (delta 4), reused 0 (delta 0) remote: Resolving deltas: 100% (4/4), completed with 4 local objects. To https://github.com/prod-ref-guide/multi-tenancy-gitops.git e3f696d..ea3b43f master -> master -
Apply ArgoCD
bootstrap.yamlRecall that you pushed the customized local copy of the GitOps repository to your GitHub account. The repository contains a
bootstrap-single-clusterArgoCD application that is watching this repository and using its contents to manage the cluster.When the
bootstrap-single-clusterArgoCD application is applied to the cluster, it will continuously ensure that all the activated resources are applied to the cluster.Apply the bootstrap YAML to the cluster:
oc apply -f 0-bootstrap/single-cluster/bootstrap.yamlKubernetes will confirm that the
bootstrapArgoCD application has been created:application.argoproj.io/bootstrap-single-cluster createdThe
bootstrapArgoCD application will watch the0-bootstrap/single-clusterfolder in our GitOps repository on GitHub.In this way, as resources are added to the infrastructure, service and application folders, they will be deployed to the cluster automatically.
This is therefore the only direct cluster operation we need to perform; from now on, all cluster operations will be performed via Git operations to this repository.
-
Verify the bootstrap deployment
Verify that the bootstrap ArgoCD application is running with the following command:
oc get app/bootstrap-single-cluster -n openshift-gitopsYou should see that the bootstrap application was recently updated:
NAME SYNC STATUS HEALTH STATUS bootstrap-single-cluster Synced HealthyHEALTH_STATUSmay temporarily showMissing; simply re-issue the command to confirm it moves toHealthy. -
Using the UI to view the newly deployed ArgoCD applications
In the previous section of this chapter you logged on to the ArgoCD web console. Switch back to that console, refresh the page and you should see the
bootstrap-single-clusterArgoCD application together with many other ArgoCD applications:
(You may need to select
Listview rather than theTilesview.)We can see that eleven ArgoCD applications have been deployed to the cluster as a result of applying
bootstrap.yaml. In the next section of the tutorial, we'll examine these applications to see how and why they were created, but for now let's focus on one of them -- thenamespace-ciArgoCD application. -
Examining the
namespace-ciArgoCD application resourcesLet's examine the Kubernetes resources applied to the cluster by the
namespace-ciArgoCD application.In the ArgoCD application list, click on
namespace-ci:
(You may need to
clear filtersto see this screenshot.)The directed graph shows that the
namespace-ciArgoCD app has created 4 Kubernetes resources; ourcinamespace and three role bindings. -
Verify the namespace using the
ocCLIWe've seen the new namespace definition in the GitOps repository and visually in the ArgoCD UI. Let's also verify it via the command line:
Type the following command:
oc get namespace ci -o yamlThis will list the full details of the
cinamespace:apiVersion: v1 kind: Namespace metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"v1","kind":"Namespace","metadata":{"annotations":{},"labels":{"app.kubernetes.io/instance":"namespace-ci"},"name":"ci"},"spec":{}} openshift.io/sa.scc.mcs: s0:c27,c9 openshift.io/sa.scc.supplemental-groups: 1000720000/10000 openshift.io/sa.scc.uid-range: 1000720000/10000 creationTimestamp: "2021-08-31T15:27:32Z" labels: app.kubernetes.io/instance: namespace-ci managedFields: - apiVersion: v1 fieldsType: FieldsV1 fieldsV1: f:metadata: f:annotations: .: {} f:kubectl.kubernetes.io/last-applied-configuration: {} f:labels: .: {} f:app.kubernetes.io/instance: {} f:status: f:phase: {} manager: argocd-application-controller operation: Update time: "2021-08-31T15:27:32Z" - apiVersion: v1 fieldsType: FieldsV1 fieldsV1: f:metadata: f:annotations: f:openshift.io/sa.scc.mcs: {} f:openshift.io/sa.scc.supplemental-groups: {} f:openshift.io/sa.scc.uid-range: {} manager: cluster-policy-controller operation: Update time: "2021-08-31T15:27:32Z" name: ci resourceVersion: "2255607" selfLink: /api/v1/namespaces/ci uid: fff6b82b-6318-4828-83bb-ade4e8e3c0cf spec: finalizers: - kubernetes status: phase: ActiveNotice how
manager: argocd-application-controlleridentifies that this namespace was created by ArgoCD.It's important to understand the sequence of actions. We simply deployed the
bootstrap-single-clusterArgoCD application, and it ultimately resulted in the creation of thenamespace-ciArgoCD application which created thecinamespace.We don't directly apply resources to the cluster once the
bootstrap-single-clusterArgoCD application has been applied; the cluster state is determined by an ArgoCD application YAML in the corresponding application, service or infrastructure related folders. It's these ArgoCD applications that create and manage the underlying Kubernetes resources using the GitOps repository as the source of truth. -
Understanding the
namespace-ciArgoCD applicationLet's examine the ArgoCD application
namespace-cito see how it created thecinamespace and three role bindings in the cluster.Issue the following command to examine its YAML:
cat 0-bootstrap/single-cluster/1-infra/argocd/namespace-ci.yamlNotice that
apiVersionandkindidentify this as an ArgoCD application:apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: namespace-ci labels: gitops.tier.layer: infra annotations: argocd.argoproj.io/sync-wave: "100" spec: destination: namespace: ci server: https://kubernetes.default.svc project: infra source: path: namespaces/ci syncPolicy: automated: prune: true selfHeal: trueMost importantly, see how this
namespace-ciArgoCD application monitors the folderpath: namespaces/ciinhttps://github.com/prod-ref-guide/multi-tenancy-gitops-infra.git; it then applies the contents of this folder to the cluster whenever its content changes.Notice the
SyncPolicyofautomated; any changes to this folder will automatically be applied to the cluster; we do not need to perform a manualSyncoperation from the ArgoCD UI. -
Examine the
cinamespace YAMLTo examine this, navigate to
multi-tenancy-gitops-infrarepository you cloned previously.cd $GIT_ROOT cd multi-tenancy-gitops-infraLet's examine the
cinamespace YAML in thenamespaces/cifolder:cat namespaces/ci/namespace.yamlIt's a very simple YAML:
apiVersion: v1 kind: Namespace metadata: name: ci spec: {}This is a YAML that we would normally apply to the cluster manually or via a script. However, when we use GitOps, we push the ArgoCD application that uses this YAML to GitHub, and it applies the
cinamespace YAML to the cluster. This is the essence of GitOps; we declare what we want to appear in the cluster using Git and ArgoCD synchronizes the cluster with this declaration. -
Examine the
cirolebinding YAMLNow that we've seen how the namespace was created, let's see how the three other rolebindings were created by the
namespace-ciArgoCD application.In the same
namespace/cifolder as thecinamespace YAML, there is arolebinding.yamlfile. This file will be also applied to the cluster by thenamespace-ciArgoCD application which is continuously watching this folder.Examine this file with the following command:
cat namespaces/ci/rolebinding.yamlThis YAML is slightly more complex than the namespace YAML:
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: system:image-puller-dev namespace: ci roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:image-puller subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: system:serviceaccounts:dev --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: system:image-puller-staging namespace: ci roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:image-puller subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: system:serviceaccounts:staging --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: system:image-puller-prod namespace: ci roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:image-puller subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: system:serviceaccounts:prod ---However its structure is quite straightforward; look carefully and you'll see that there are indeed three rolebindings defined in this YAML. Each of these rolebindings binds different roles to different service accounts associated with components that will run within the
cinamespace, such as Tekton pipelines for example.We'll see later how these rolebindings are important; they limit the operations that can be performed by the
cinamespace, creating a well governed cluster.This confirms why we saw four resources created by the
namespace-ciArgoCD application in the ArgoCD UI: one namespace and three rolebindings.Again, notice the pattern: a single ArgoCD application manages one or more Kubernetes resources in the cluster -- using one or more YAML files in which those resources are defined.
-
The
bootstrap-single-clusterArgoCD application in more detailIn the ArgoCD UI Applications view, click on the
bootstrap-single-clusterapplication:
You can see the bootstrap application creates two Kubernetes resources, the
infraArgoCD application and theinfraArgoCD project.An ArgoCD project is a mechanism by which we can group related resources; we keep all our ArgoCD applications that manage infrastructure in the
infraproject. Later, we'll create aservicesproject for the ArgoCD applications that manage the services we want deployed to the cluster such as the CP4S application. -
The
infraArgoCD applicationLet's examine the
infraArgoCD application in more detail to see how it works.In the ArgoCD UI Applications view, click on the
open applicationicon for theinfraapplication:
We can see that the
infraArgoCD application creates 9 ArgoCD applications, each of which is responsible for applying specific YAMLs to the cluster according to the folder the ArgoCD application is watching.It's the
infraArgoCD application that watches the0-bootstrap/single-cluster/1-infra/argocdfolder for ArgoCD applications that apply infrastructure resources to our cluster. It was theinfraapplication that created thenamespace-ciArgoCD application which manages thecinamespace that we've been exploring in this section of the tutorial.We'll continually reinforce these relationships as we work through the tutorial. You might like to spend some time exploring the ArgoCD UI and ArgoCD YAMLs before you proceed, though it's not necessary, as you'll get lots of practice as we proceed.
Managing change¶
We end this topic by exploring how ArgoCD provides some advanced resource management features. We'll focus on two aspects of how to manage resources:
-
Dynamic: We'll see how ArgoCD allows us to easily and quickly update any resource in the cluster. We're focussing on infrastructure components like namespaces, but the same principles will apply to applications, databases, workflow engines and messaging systems -- any resource within the cluster.
-
Governed: While we want to be agile, we also want a well governed system. As we've seen, GitOps allows us to define the state of the cluster from a git repository -- but can we also ensure that the cluster stays that way? We'll see how ArgoCD helps with configuration drift -- ensuring that a cluster only changes when properly approved.
Dynamic updates¶
-
Locate your GitOps repository
If necessary, change to the root of your GitOps repository, which is stored in the
$GIT_ROOTenvironment variable.Issue the following command to change to your GitOps repository:
cd $GIT_ROOT cd multi-tenancy-gitops -
Customize the web console banner
Examine the banner in the OpenShift web console:

We're going to use GitOps to modify this banner dynamically.
-
The banner YAML
This banner properties are defined by the YAML in
/0-bootstrap/single-cluster/1-infra/argocd/consolenotification.yaml. This YAML is currently being used by thecntk-consolenotificationArgoCD application that was deployed earlier.We can examine the YAML with the following command:
cat 0-bootstrap/single-cluster/1-infra/argocd/consolenotification.yamlwhich shows the banner properties are part of the
ConsoleNotificationcustom resource:apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: cntk-consolenotification labels: gitops.tier.layer: infra annotations: argocd.argoproj.io/sync-wave: "100" finalizers: - resources-finalizer.argocd.argoproj.io spec: syncPolicy: automated: prune: true selfHeal: true destination: namespace: openshift-gitops server: https://kubernetes.default.svc project: infra source: path: consolenotification helm: values: | ocp-console-notification: ## The name of the ConsoleNotification resource in the cluster name: "banner-env" ## The background color that should be used for the banner backgroundColor: teal ## The color of the text that will appear in the banner color: "'#fff'" ## The location of the banner. Options: BannerTop, BannerBottom, BannerTopBottom location: BannerTop ## The text that should be displayed in the banner. This value is required for the banner to be created text: "Cluster Description"See how the banner at the top of the screen:
- contains the text
Cluster Description - is located at top of the screen
- has the color
teal
- contains the text
-
Modify the YAML for this banner
Let's now change this YAML
In your editor, modify this YAML and change the below fields as follows:
ocp-console-notification: ## The name of the ConsoleNotification resource in the cluster name: "banner-env" ## The background color that should be used for the banner backgroundColor: red ## The color of the text that will appear in the banner color: "'#fff'" ## The location of the banner. Options: BannerTop, BannerBottom, BannerTopBottom location: BannerTop ## The text that should be displayed in the banner. This value is required for the banner to be created text: "Production Reference Guide"It's clear that our intention is to modify the banner's
backgroundColor:redandtext: Production Reference Guideto the newly specified values. If you look at thediff:git diffyou should see the following:
diff --git a/0-bootstrap/single-cluster/1-infra/argocd/consolenotification.yaml b/0-bootstrap/single-cluster/1-infra/argocd/consolenotification.yaml index 30adf1a..596e821 100644 --- a/0-bootstrap/single-cluster/1-infra/argocd/consolenotification.yaml +++ b/0-bootstrap/single-cluster/1-infra/argocd/consolenotification.yaml @@ -26,10 +26,10 @@ spec: name: "banner-env" ## The background color that should be used for the banner - backgroundColor: teal + backgroundColor: red ## The color of the text that will appear in the banner color: "'#fff'" ## The location of the banner. Options: BannerTop, BannerBottom, BannerTopBottom location: BannerTop ## The text that should be displayed in the banner. This value is required for the banner to be created - text: "Cluster Description" + text: "Production Reference Guide" -
Make the web console YAML change active
Let's make these changes visible to the
cntk-consolenotificationArgoCD application via GitHub.Add all changes in the current folder to a git index, commit them, and push them to GitHub:
git add . git commit -s -m "Modify console banner" git push origin $GIT_BRANCHYou'll see the changes being pushed to GitHub:
Enumerating objects: 13, done. Counting objects: 100% (13/13), done. Delta compression using up to 8 threads Compressing objects: 100% (7/7), done. Writing objects: 100% (7/7), 670 bytes | 670.00 KiB/s, done. Total 7 (delta 5), reused 0 (delta 0) remote: Resolving deltas: 100% (5/5), completed with 5 local objects. To https://github.com/tutorial-org-123/multi-tenancy-gitops.git a1e8292..b49dff5 master -> masterLet's see what effect they have on the web console.
-
A dynamic change to the web console
You can either wait for ArgoCD to automatically sync the
cntk-consolenotificationapplication or manuallyRefreshandSynctheinfraapplication yourself:
Returning to the OpenShift web console, you'll notice changes.

Notice the dynamic nature of these changes; we updated the console YAML, pushed our changes to our GitOps repository and everything else happened automatically.
As a result, our OpenShift console has a new banner color and text. This is a simple yet effective demonstration of how we can quickly rollout changes very visible changes.
Configuration drift¶
-
Governing changes to the
devnamespaceLet's now look at how ArgoCD monitors Kubernetes resources for configuration drift, and what happens if it detects an unexpected change to a monitored resource.
Don't worry about the following command; it might seem drastic and even reckless, but as you'll see, everything will be OK.
Let's delete the
devnamespace from the cluster:oc get namespace dev oc delete namespace devSee how the active namespace:
NAME STATUS AGE dev Active 2d18his deleted:
namespace "dev" deletedWe can see that the
devnamespace has been manually deleted from the cluster. -
GitOps repository as a source of truth
If you switch back to the ArgoCD UI, you may see that ArgoCD has detected a configuration drift:
- a resource is
Missing(thedevnamespace) namespace-devtherefore isOutOfSyncnamespace-devis thereforeSyncingwith the GitOps repository

After a while we'll see that
namespace-devisHealthyandSynced:
ArgoCD has detected a configuration drift, and resynched with GitOps repository, re-applying the
devnamespace to the cluster.Note
You may not seethe first screenshot if ArgoCD detects and corrects the missing
devnamespace before you get a chance to switch to the ArgoCD UI. Don't worry, you can try thedeleteoperation again! - a resource is
-
The restored
devnamespaceIssue the following command to determine the status of the
devnamespace:oc get namespace devwhich confirms that the
devnamespace has been re-instated:NAME STATUS AGE dev Active 115sNote that it is a different instance of the
devnamespace; as indicated by itsAGEvalue.Notice the well governed nature of these changes; GitOps is our source of truth about the resources deployed to the cluster. ArgoCD restores any resources that suffer from configuration drift to their GitOps-defined configuration. It doesn't really matter whether the change was accidental or not, ArgoCD considers any change to a managed resource (e.g. the
devnamespace) as invalid unless it's synced with its source of truth -- your GitOps repository.We'll see more about well governed changes when we look at Tekton pipelines that build and test any changes before they are deployed.
Congratulations!
You've used ArgoCD and the GitOps repository to set up ci, tools and dev namespaces. You've seen how to create ArgoCD applications that watch their respective GitOps namespace folders for details of the namespace resources they should apply to the cluster. You've seen how you can dynamically change deployed resources by updating the resource definition in the GitOps repository. Finally, you've experience how ArgoCD keeps the cluster synchronized with the GitOps repository as a source of truth; any unexpected configuration drift will be corrected without intervention.
In the next section of this tutorial, we're going to deploy some services into the infrastructure namespaces we've created in this topic. These services will include Artifactory and MQ operator.