top of page

Stakater Blog

Follow our blog for the latest updates in the world of DevSecOps, Cloud and Kubernetes

Tehreem Nisa

Managing OpenShift Operators Lifecycle with Argo CD

In OpenShift environments, effectively managing the lifecycle of Operators is essential for ensuring smooth application operations. OpenShift Operators are extensions to Kubernetes that utilize custom resources to manage applications and their components. In this guide, we'll demonstrate how we can efficiently handle the lifecycle of OpenShift Operators using ArgoCD, a GitOps continuous delivery tool.


Prerequisites

  • We need access to an OpenShift cluster.

  • We should have ArgoCD installed and configured.

  • It's helpful to have a basic understanding of Kubernetes resources.


Procedure

Install operator via ArgoCD


1. Creating a subscription:

First, we create a Subscription resource to install the operator. This resource specifies which operator to install and which channel to subscribe to for updates. When we create the Subscription, it triggers the creation of an InstallPlan, which outlines the necessary installation steps.

yaml
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: my-operator
spec:
  channel: stable
  name: my-operator
  source: my-operator-source
  sourceNamespace: operators

2. Configuring OperatorGroup:

An OperatorGroup specifies the namespaces where the operator will manage resources. If we're installing the operator in a namespace other than openshift-operators, we need to create the OperatorGroup in that namespace. This ensures that the operator has the required permissions to operate within those namespaces.


Code example

Here's an example YAML snippet demonstrating the creation of a Subscription and OperatorGroup for an OpenShift operator:

yaml
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
  name: my-operator-group
  namespace: my-namespace
spec:
  targetNamespaces:
  - my-target-namespace

3. Apply via GitOps with ArgoCD:

  • ArgoCD enables GitOps practices, where cluster states are defined in a Git repository.

  • Make sure your Subscription and OperatorGroup manifests reside in a Git repository accessible to ArgoCD.

  • Create an ArgoCD Application manifest to synchronize the Git repository with your OpenShift cluster.

yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: openshift-operator-app
  namespace: argocd
spec:
  source:
    repoURL: <git_repository_url>
    targetRevision: HEAD
    path: <path_to_operator_resources>
    syncPolicy:
      automated:
        prune: true
        selfHeal: true
  destination:
    server: https://kubernetes.default.svc
    namespace: <target_namespace>
  project: <project_name>
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

To ensure a clean and efficient environment, it's also essential to manage and clean up unused resources. Check out this guide on auto cleanup resources on Kubernetes and OpenShift for more details.


4. Approval of install plan:

  • After applying the Subscription, the Operator generates an Install Plan.

  • This plan details the steps needed for installation.

  • Manual approval might be required to proceed with the installation.

5. Monitor operator installation:

  • While the Operator pod remains inactive, its status shows as 'NotInstalled'.

  • Keep track of the installation progress by monitoring the Install Plan and Operator pod status.

6. Configure health checks with ArgoCD:

  • Ensure effective monitoring of the Operator's health by configuring health checks in ArgoCD.

  • Define health checks based on custom metrics, pod health, or other relevant criteria.

  • Update the ArgoCD Application manifest to include these health check configurations.

Health check configuration

yaml
Example Manifest for an Argocd Instance with Healthchecks 

apiVersion: argoproj.io/v1alpha1
kind: ArgoCD
metadata:
  name: openshift-gitops
  namespace: openshift-gitops
spec:
  ...
  resourceHealthChecks:
    - check: |
        hs = {}
        hs.status = "Progressing"
        hs.message = ""
        if obj.status ~= nil then
          if obj.status.health ~= nil then
            if obj.status.sync.status == 'Synced' then
              hs.status = obj.status.health.status
              if obj.status.health.message ~= nil then
                hs.message = obj.status.health.message
              end
            end
          end
        end
        return hs
      group: argoproj.io
      kind: Application
    - check: |
        health_status = {}
        if obj.status ~= nil then
          if obj.status.conditions ~= nil then
            numDegraded = 0
            numPending = 0
            msg = ""
            for i, condition in pairs(obj.status.conditions) do
              msg = msg .. i .. ": " .. condition.type .. " | " .. condition.status .. "\n"
              if condition.type == "InstallPlanPending" and condition.status == "True" then
                numPending = numPending + 1
              elseif (condition.type == "InstallPlanMissing" and condition.reason ~= "ReferencedInstallPlanNotFound") then
                numDegraded = numDegraded + 1
              elseif (condition.type == "CatalogSourcesUnhealthy" or condition.type == "InstallPlanFailed" or condition.type == "ResolutionFailed") and condition.status == "True" then
                numDegraded = numDegraded + 1
              end
            end
          end
          if numDegraded == 0 and numPending == 0 then
            health_status.status = "Healthy"
            health_status.message = msg
            return health_status
          elseif numPending > 0 and numDegraded == 0 and obj.spec.installPlanApproval == "Manual" then
            health_status.status = "Healthy"
            health_status.message = "An install plan for a subscription is pending installation but install plan approval is set to manual so considering this as healthy: " .. msg
            return health_status
          elseif numPending > 0 and numDegraded == 0 then
            health_status.status = "Progressing"
            health_status.message = "An install plan for a subscription is pending installation"
            return health_status
          else
            health_status.status = "Degraded"
            health_status.message = msg
            return health_status
          end
        end
        return health_status
      group: operators.coreos.com
      kind: Subscription
    - check: |
        hs = {}
        if obj.status ~= nil then
          if obj.status.phase ~= nil then
            if obj.status.phase == "Complete" then
              hs.status = "Healthy"
              hs.message = obj.status.phase
              return hs
            end
          end
        end
        hs.status = "Progressing"
        hs.message = "Waiting for InstallPlan to complete"
        return hs
      group: operators.coreos.com
      kind: InstallPlan

To streamline the deployment process, especially when dealing with configuration changes, consider using OpenShift DeploymentConfig for Stakater Reloader.


7. Setting up an example operator:

We'll demonstrate setting up the Crunchy PostgreSQL Operator using ArgoCD, and health checks will ensure the application's health upon installation.

Add the following manifests to your GitOps repository.

01-operatorgroup.yaml

yaml
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
  name: postgres-operator
  namespace: postgres-operator
spec:
  targetNamespaces:
    - postgres-operator
```
02-subscription.yaml

```yaml
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: postgresql
  namespace: postgres-operator
spec:
  channel: "v5"
  installPlanApproval: "Automatic"
  name: "postgresql"
  source: "community-operators"
  sourceNamespace: "openshift-marketplace"
  startingCSV: "postgresoperator.v5.4.2"

Applying the ArgoCD application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: postgres-operator-app
  namespace: argocd
spec:
  destination:
    namespace: rh-openshift-gitops-instance
    server: https://kubernetes.default.svc
  project: default
  source:
    path: postgres-operator
    repoURL: 'git@github.com:your-org/gitops-repo'
    targetRevision: HEAD
  syncPolicy:
    automated:
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

Ensuring our application is syncing




We ensure the successful installation of the operator in the namespace before marking the app as green in ArgoCD.



If the installation fails, ArgoCD health checks will mark it as degraded with specified reasons in the health check.


Managing the lifecycle of OpenShift Operators is crucial for maintaining stability and performance in applications on OpenShift clusters. By integrating ArgoCD into our process, we automate the deployment, monitoring, and maintenance of Operators, ensuring a reliable and efficient operational environment.


To further enhance your OpenShift environment, consider exploring OpenShift as a Service offered by Stakater. For expert guidance and support, you can explore our Kubernetes Consultancy.

571 views0 comments

Comments


bottom of page