Bookmark this page

GitOps for Application Management

Objectives

  • Deploy an Argo CD instance, from OpenShift GitOps, for application developers and application administrators.

Argo CD Instances

By default, the Red Hat OpenShift GitOps operator creates an Argo CD instance in the openshift-gitops namespace. This Argo CD instance has permissions to manage cluster-wide resources. Thus, Red Hat recommends using this instance only for administration purposes, and to create other, less privileged instances for regular application deployment.

To deploy regular applications, you can deploy new Argo CD instances. By default, the new Argo CD instances have permissions to manage resources only in the namespace where they are deployed.

To create an Argo CD instance, you can create a YAML file as follows:

apiVersion: argoproj.io/v1beta1
kind: ArgoCD
metadata:
  name: argocd-name
  namespace: argocd-ns
spec:
...output omitted...

You can allow an Argo CD instance to manage resources in other namespaces than where it is deployed by adding the argocd.argoproj.io/managed-by label to the namespace. The following example allows the Argo CD instance in the argocd-ns namespace to manage the resources in the managed-ns namespace.

[user@host ~]$ oc label namespace managed-ns \
  argocd.argoproj.io/managed-by=argocd-ns

The following diagram shows an example of using an Argo CD instance to manage resources in other namespaces.

In this diagram, a cluster administrator creates an Argo CD instance in the argocd-ns namespace. Thus, the Argo CD instance has permissions to manage resources only in that namespace.

The cluster administrator includes the argocd.argoproj.io/managed-by label in the managed-ns namespace. Thus, the Argo CD instance can manage resources in that namespace.

Developer users need only read permission in the managed-ns namespace for troubleshooting, according to the principle of least privilege, because they would be managing application resources in their projects by using Git.

Argo CD Authentication

Argo CD can both use local users and integrate with other identity providers.

The OpenShift GitOps operator configures the default Argo CD instance to use Dex. Dex is an identity service that uses the OpenID connect protocol to connect Argo CD with the identity provider.

The default Argo CD instance in the openshift-gitops namespace has permission to manage cluster-wide resources. You can log in with write permission to this instance only by using the local admin user with the credentials in the openshift-gitops-cluster secret in the openshift-gitops namespace, or by using an OpenShift user from the cluster-admins group in OpenShift.

You can also configure the Argo CD instances to use Keycloak instead of Dex. For example, use the groups in Keycloak to determine the privileges in Argo CD. Keycloak acts as an identity broker between the Argo CD instance and OpenShift.

Note

Configuring Keycloak as the SSO authentication provider for Argo CD is outside the scope of this course.

For more information, refer to https://access.redhat.com/documentation/en-us/red_hat_openshift_gitops/1.10/html-single/access_control_and_user_management/index#configuring-sso-for-argo-cd-using-keycloak

Dex

The OpenShift GitOps operator configures Dex to delegate the authentication to the built-in OAuth server in OpenShift. Thus, Dex provides the users and groups that are defined in OpenShift.

You can manually configure Dex as the SSO authentication provider and use the OpenShift OAuth server by setting the .spec.sso parameter as in the following example:

...output omitted...
spec:
  sso:
    provider: dex
    dex:
      openShiftOAuth: true
...output omitted...

Argo CD Permissions

By default, only the local Argo CD admin user and the OpenShift users in the cluster-admins group can log in to the default Argo CD instance with write permission. Other OpenShift users have only read permission. However, you can change the user and group level access by configuring the RBAC section in the Argo CD custom resource.

Important

Argo CD RBAC controls the use of resources through Argo CD, not through the Kubernetes API. Users with access to the Kubernetes API can modify those resources and modify Argo CD RBAC. You must set up Kubernetes role-based access control to prevent access to Argo CD Kubernetes resources.

Argo CD comes with the following predefined roles:

  • role:readonly, for read access to all the resources

  • role:admin, for read and write access to all the resources

For example, the default Argo CD instance includes the following RBAC configuration:

...output omitted...
spec:
  ...output omitted...
  rbac:
    defaultPolicy: ""
    policy: |
      g, system:cluster-admins, role:admin
      g, cluster-admins, role:admin
    scopes: '[groups]'
...output omitted...

Thus, for OpenShift users in the system:cluster-admins and cluster-admins groups, the predefined role:admin role is assigned by default.

Note

System groups, such as the system:cluster-admins group, are predefined groups that are built into the system to grant specific permissions to certain categories of users. Kubernetes creates these groups during the setup to control access to critical components and resources within the cluster. These groups are a part of cluster roles and cluster role bindings.

For more information, refer to https://kubernetes.io/docs/reference/access-authn-authz/rbac/#referring-to-subjects

To configure the Argo CD instance to assign the predefined role:readonly role to the users in the cluster-readers group, you can use the following RBAC configuration:

...output omitted...
spec:
  ...output omitted...
  rbac:
    defaultPolicy: ""
    policy: |
      g, system:cluster-admins, role:admin
      g, cluster-admins, role:admin
      g, cluster-readers, role:readonly
    scopes: '[groups]'
...output omitted...

You can use the defaultPolicy field to define a policy for other users that do not conform to an existing policy.

Fine-grained RBAC

If you want a finer-grained RBAC for your Argo CD instance, then you can break down the permissions for all the resources in Argo CD. The resources in Argo CD are accounts, applications, applicationsets, certificates, clusters, exec, extensions, gpgkeys, logs, projects, and repositories.

For all the resources, the Argo CD actions include create, delete, get, and update. For the applications resource, Argo CD also includes the action/group/kind/action-name, override, and sync actions.

You can define specific fine-grained RBAC permissions with the following syntax in the spec.rbac.policy parameter:

p, role/user/group, resource, action, target

The target field differs between the application resources and the other resources:

  • For the applications, applicationsets, logs, and exec resources, which belong to a project, the target field is project/object.

  • For other resources, the target field is object.

As an example, the following excerpt creates the project-devs and project-admin roles, and assigns them to the users in the OpenShift groups with the same names.

...output omitted...
spec:
  ...output omitted...
  rbac:
    defaultPolicy: ''
    policy: |
      g, project-devs, role:project-devs
      p, role:project-devs, applications, get, */*, allow
      p, role:project-devs, projects, get, *, allow
      p, role:project-devs, clusters, get, *, allow
      g, project-admins, role:project-admins
      p, role:project-admins, applications, *, */*, allow
      p, role:project-admins, projects, get, *, allow
      p, role:project-admins, clusters, get, *, allow
    scopes: '[groups]'
...output omitted...

Users in both the project-devs and project-admins groups can read the clusters and projects resources in Argo CD.

Users in the project-devs group can also read all the applications resources in any of the projects.

Users in the project-admins group can perform any action for the applications resources in any of the projects.

Note

Argo CD includes other RBAC features that are outside the scope of this course.

For more information, refer to https://argo-cd.readthedocs.io/en/stable/operator-manual/rbac/

Monorepo and Polyrepo Environments

If you give a user access to a Git repository, then the user has access to all the files in the repository. You cannot allow users to read or write only in certain paths within a repository. However, some products that build on top of Git, such as GitHub or GitLab, add features to improve protecting specific paths within a repository.

When setting up Git workflows for GitOps, you can either create only one repository for all your files, which is called a monorepo environment, or create repositories for different concerns, which is called a polyrepo environment.

In a monorepo environment, all the application sources, container files, Kubernetes manifests, and policy manifests are in a single Git repository.

A monorepo environment offers a centralized location for all the configuration changes. Thus, tracking, testing, and releasing processes are limited to a single Git repository. Moreover, having all your code in a single repository simplifies managing dependencies between your applications. However, users with access to the Git repository have access to all the code in the projects, which can lead to security issues.

From an Argo CD perspective, you can either treat the entire monorepo as a single application, to deploy changes across various services or components concurrently, or use paths to create several applications from a single repository. With the second option, you can use different paths for the application files and for the application configurations, such as network policies or quotas. This separation prevents application configuration changes from triggering unnecessary application rebuilds.

Another option when setting up Git workflows for GitOps is to separate the concerns by repository. A polyrepo environment enables different designs depending on your company needs.

For example, a polyrepo environment has several Git repositories for applications and configurations. Red Hat recommends using different repositories for application files and for application configurations, to prevent unnecessary application rebuilds. Independent lifecycles for application code and application configuration, along with specific approval processes, ensure smoother continuous integration. However, coordinating dependencies across repositories requires extra effort.

From an Argo CD perspective, you can create applications from the various repositories in a polyrepo environment. However, a polyrepo environment requires more complex configuration than a monorepo environment to manage the dependencies between repositories.

Organizing Applications by Environment

One GitOps practice separates the test and production environments by directory inside a Git repository, instead of creating different branches for them. This approach avoids the complexity of managing branches for various environments, where merging changes might not be straightforward because of configuration differences.

The goal is to avoid resource duplication across environments. Given that organizations often maintain many environments from development to production, replicating the entire set of deployment assets across these environments can lead to inconsistencies.

Tools such as Kustomize or Helm create reusable and modular configurations, to separate base manifests and environment-specific adjustments. With Kustomize declarative and scalable configuration management, you can create a set of base resource files to deploy the application, and then create a set of overlay files to adapt the application for the environment. With Helm, you can store in Git a Helm chart that contains all the necessary resources to deploy your application, and then use different Git repositories to store the application customization for each environment. Then, Argo CD uses the Helm chart and you can specify in Argo CD the values file to use for each environment.

Note

Kustomize is outside the scope of this course.

Using Kustomize in an OpenShift cluster is explained in the DO280: Red Hat OpenShift Administration II: Operating a Production Kubernetes Cluster course.

For more information, refer to https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/

Managing Sensitive Data in GitOps

To prevent security issues, you must ensure encryption or other protection of sensitive data or secrets. Sensitive data and secrets include passwords, APIs, encryption keys, SSH keys, tokens, or other digital credentials that allow users and applications access to other sensitive data, systems, and services.

Because Git users with access to the repository have access to all the files in the repository, they have access to any sensitive data that is stored in the repository. Thus, storing your sensitive data in Git repositories can introduce security concerns.

You can manually store your sensitive data in secret objects, outside a Git repository. However, if you do not correctly configure RBAC rules on your cluster, then anyone with API or etcd access can retrieve or modify a secret. Moreover, a user with permission to create a pod in a namespace can read any secret in that namespace. By default, cluster administrators can see the secrets of all users.

A mitigation is to use third-party secret management tools. Red Hat recommends using these secret management tools to mitigate security issues with features such as credential encryption, credential rotation, and short-lived tokens. Both commercial and open source solutions exist for this purpose.

For example, you can use the Secrets Store CSI Driver operator to manage multiple secrets, keys, and certificates. This driver enables Kubernetes pods to mount secrets that are stored in external secret management systems such as Azure Key Vault, AWS Secrets Manager, or HashiCorp Vault as volumes. This driver enhances security by centralizing secret management outside the cluster and allowing applications to access these secrets seamlessly through the Kubernetes API. The operator simplifies integrating and managing external secrets within Kubernetes deployments, to handle sensitive information more securely and efficiently.

Application Validation and Rollback

When you deploy an application to production, even with thorough testing you cannot predict or prevent all potential issues. Also, deploying an application requires actions before, during, and after application synchronization, and if that process fails.

For any production issues, you can roll back to known stable states the small increments of your application that CI/CD practices release. Increasing the release size also results in larger rollbacks, and implies more risks.

Argo CD provides some of these features for deploying your application.

Argo CD Resource Hooks

Argo CD provides resource hooks, which are customizable triggers in deployment lifecycles. With Argo CD resource hooks, you can define and execute actions during the lifecycle of an application synchronization process.

Argo CD can run resource hooks before, during, and after an application synchronization process, and also if the synchronization process fails. For example, you can run a resource hook before the synchronization process to migrate a database before deploying a new application version, or you can run a resource hook after the synchronization process for a smoke test of your application by verifying the application health.

Argo CD defines the following resource hooks:

  • PreSync: Argo CD executes these hooks before applying the manifests.

  • Sync: Argo CD executes these hooks only after it successfully completes all the PreSync hooks. These hooks are applied at the same time as applying the manifests.

  • Skip: This hook indicates to Argo CD to skip applying the manifests. Use this hook for resources that Argo CD must create, but that other resources modify and that must be out of Argo CD synchronization.

  • PostSync: Argo CD executes these hooks only after it successfully completes all the Sync hooks, and the application and its resources are in a healthy state.

  • SyncFail: Argo CD executes these hooks whenever the synchronization operation fails.

Argo CD resource hooks are Kubernetes resources that include the argocd.argoproj.io/hook annotation. Typically, Argo CD resource hooks are implemented through Kubernetes jobs.

The following example shows the annotation for a PreSync hook that migrates the database before deploying the new application version:

apiVersion: batch/v1
kind: Job
metadata:
  generateName: schema-migrate-database
  annotations:
    argocd.argoproj.io/hook: PreSync
...output omitted...

You can add the argocd.argoproj.io/hook-delete-policy annotation for your hooks, so Argo CD deletes them automatically according to one of the following policies:

  • HookSucceeded: Delete the hook resource after the hook succeeds.

  • HookFailed: Delete the hook resource after the hook fails.

  • BeforeHookCreation: Delete any existing hook resource before a new one is created.

The following excerpt shows the annotation for a PostSync hook that tests the application after the synchronization process and removes the hook if it succeeds:

apiVersion: batch/v1
kind: Job
metadata:
  generateName: integration-test-app
  annotations:
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
...output omitted...

Argo CD Rollback

Argo CD enables you to roll back your application to a known stable state if the new version has errors.

You can manually roll back your application by clicking the HISTORY AND ROLLBACK button. You can then access previous application deployments and restore the application to an earlier version. For example, with this feature you can restore the application to a working version until you push a fix in your application repository.

Argo CD can also automate rollbacks in certain conditions, such as for failing resource hooks.

Note

The Argo CD rollback feature is disabled if you enable automatic synchronization for your application, because Argo CD automatically synchronizes the application to the latest Git commit version.

To roll back your application, you can temporarily disable automatic synchronization in Argo CD, or revert the last commit in your Git repository.

Argo Rollouts

Argo Rollouts is a Kubernetes controller and a set of custom resource definitions that provide advanced deployment capabilities. These capabilities include update strategies, such as progressive rollouts, and automated rollbacks and promotions.

You can integrate Argo Rollouts with ingress controllers and service meshes, to gradually shift the traffic from your previous application version to a new one.

For example, you can use Argo Rollouts to deploy a new application version for only a small percentage of the production traffic, and then analyze if everything works as expected. Argo Rollouts can automatically roll back to the previous stable version if the deployment fails.

Note

Argo Rollouts is a Technology Preview feature only, and is outside the scope of this course.

References

For more information about configuring SSO on Argo CD by using Dex or Keycloak, refer to the Red Hat OpenShift GitOps 1.10 Access Control and User Management documentation at https://access.redhat.com/documentation/en-us/red_hat_openshift_gitops/1.10/html-single/access_control_and_user_management/index

For more information about Argo Rollouts, refer to the Red Hat OpenShift GitOps 1.10 Argo Rollouts documentation at https://access.redhat.com/documentation/en-us/red_hat_openshift_gitops/1.10/html-single/argo_rollouts/index

For more information about best practices for structuring Git workflows, refer to the The Path to GitOps book at https://developers.redhat.com/e-books/path-gitops

For more information about implementing GitOps with Argo CD in OpenShift, refer to the Getting GitOps: A Practical Platform with OpenShift, Argo CD, and Tekton book at https://developers.redhat.com/e-books/getting-gitops-practical-platform-openshift-argo-cd-and-tekton

Revision: do380-4.14-397a507