GitOps Driven Configuration of OCM Applications


This guide is the final part of our series exploring OCM, the ocm-controller and how to drive GitOps processes using OCM as the source of truth.

Checkout the previous guides if you haven’t already:

In this guide we will pick-up where we left off in the air-gapped example.

We have successfully transferred a component to our private environment and deployed it using the ocm-controller. However the Kubernetes Deployment for podinfo is failing because it does not have permission to access our private container images.

Let’s fix that.

Table of contents


Component Content Recap

We saw previously that podinfo component contains three resources:

  • podinfo container image
  • kubernetes deployment manifest for podinfo
  • configuration file read by the ocm-controller

We can list these resources using the ocm CLI:

ocm get resources -c v6.3.5

config     6.3.5            PlainText local
deployment 6.3.5            Directory local
image      6.3.5            ociImage  external

Let’s examine the config resource once again and this time focus on a section named configuration:

ocm download resource -c v6.3.5 config -O -

kind: ConfigData
  name: ocm-config
    serviceAccountName: default # this is the default value for our variable
  - value: (( serviceAccountName ))  # this variable
    file: deployment.yaml # will be inserted into this file
    path: spec.template.spec.serviceAccountName # at this path
  schema: # allows us to define constraints for configuration values
    type: object
    additionalProperties: false
        type: string

The configuration section contains a set of rules, some default values and a schema.

These can be used to provide configuration values which will be inserted into our resources at runtime by the ocm-controller

In the above resource we can see that there is a variable named serviceAccountName and a rule which specifies that this variable should be inserted into the path spec.template.spec.serviceAccountName in the deployment.yaml file.

GitOps & Configuration

Similar to how we Localized our deployment resource in the previous guide, we create another Custom Resource with the type Configuration in order to apply our configuration rules:

cat > ./components/localization.yaml >>EOF
kind: Configuration
  name: podinfo-deployment
  namespace: ocm-system
  interval: 1m
    kind: Localization
    name: podinfo-deployment # this is the podinfo deployment localization
    kind: ComponentVersion
    name: podinfo
      name: config # here we reference the configuration resource
    serviceAccountName: app-ops

You can see that this time we have used the Localization resource the input for the Configuration and have provided the configuration rules using the spec.configRef field. Finally we specify our service account name in the spec.values.serviceAccountName field.

Once again we need to update the FluxDeployer so that it consumes the Configuration rather than the Localization:

kind: FluxDeployer
  name: podinfo
  namespace: ocm-system
    kind: Configuration
    name: podinfo-deployment
    interval: 1m0s
    path: ./
    prune: true
    targetNamespace: default

Before we push these changes we need to actually create the ServiceAccount and image-pull Secret in the target namespace.

Let’s create the secret as we did previously (note in a real world scenario there are a number of ways to manage secrets when doing Gitops):

kubectl create secret docker-registry -n default ghcr-cred \ \
  --docker-username=$GITHUB_USER \

Now let’s add the ServiceAccount:

cat > ./clusters/kind/service_account.yaml <<EOF

apiVersion: v1
kind: ServiceAccount
  name: app-ops
  namespace: default
- name: ghcr-cred

Finally we are ready commit, push and reconcile these changes:

git add ./components ./clusters

git commit -m "move to air-gapped repository"

git push

flux reconcile source git flux-system

Verify Deployment

Flux should now be reconciling the Configured manifest with image references pointing to our private OCM repository and the correct ServiceAccount configured.

We can verify this using kubectl:

kubectl get deployment -n default podinfo -oyaml | grep serviceAccountName | xargs

serviceAccountName: app-ops
kubectl get deployment -n default podinfo -oyaml | grep image | xargs


Kubernetes can now retrieve the image and all pods should be happily running.


We have shown how OCM and Flux can be combined to configure applications at runtime.

GitOps driven configuration in tandem with the powerful Localization functionality provided by OCM offers tremendous flexibility, reliability and scalability when deploying your applications to any kind of compute environment be it public, private or edge.