Skip to content
A GitOps Operator for Kubernetes
Go Shell Dockerfile Makefile
Branch: master
Clone or download
Type Name Latest commit message Commit time
Failed to load latest commit information.
build Switch operator image to distroless Jun 25, 2019
cmd/manager initial public release May 29, 2019
deploy Issue 3: Add a None option for Resource Handling. (#11) Aug 6, 2019
examples switch to latest image and remove old image push script Aug 5, 2019
media initial public release May 29, 2019
pkg Issue 3: Add a None option for Resource Handling. (#11) Aug 6, 2019
template-processors Issue 3: Add a None option for Resource Handling. (#11) Aug 6, 2019
test Issue 3: Add a None option for Resource Handling. (#11) Aug 6, 2019
version Add linting and unit tests execution to Travis CI (#61) Jul 3, 2019
.travis.yml Add e2e tests to travis CI (#76) Aug 2, 2019 Switch to helm charts and provide simple gitopsconfig roles (#67) Jul 30, 2019
Makefile Issue 3: Add a None option for Resource Handling. (#11) Aug 6, 2019 Adding trouble shooting guide Jun 23, 2019
go.sum Switch to Go modules Jun 28, 2019


Eunomia - a GitOps Operator for Kubernetes

Join the chat at Build Status Docker Repository on Quay Go Report Card

Who is Eunomia

According to Wikipedia:

Eunomia (Greek: Εὐνομία) was a minor Greek goddess of law and legislation (her name can be translated as "good order", "governance according to good laws"), as well as the spring-time goddess of green pastures (eû means "well, good" in Greek, and νόμος, nómos, means "law", while pasturelands are called nomia).

What is GitOps

GitOps is all about turning day 2 operations into code! Not just that, it means you start thinking about day 2 on day 1. This is a dream come true for any Operations team! GitOps leverages the strength of automation and combines it with the power of git based workflows. It is a natural evolution beyond infrastrcture-as-code and builds on top of DevOps best practices.

Next Generation Change Management

Especially in large Enterprises, Change Management is usually a painful experience. GitOps allows to take a lot of that pain out and streamline the process itself. It does so by still providing what the process tries to accomplish (and thus still meet audit requirements), but does so in a way that is much faster, much more secure, and much more reliable.

Your changes now all of a sudden provide:

  • Version Control
  • Peer Reviews
  • Approvals
  • Audit Trail
  • Reproducibility
  • Consistency
  • Reliability

What's your backout plan for your change? How about simply moving back to the previous commit and getting EXACTLY what you had before?


The Eunomia provides the ability to implement these git-based flows for any resources in Kubernetes. Eunomia does not care if you have a plain Kubernetes, a cloud based Kubernetes (like GKE), or a complete PaaS platform based on Kubernetes (like OpenShift). Eunomia also does not care how you want to structure your data, how many repos you want to use, or which templating engine is your favourite.

Eunomia can handle straight-up (static) yaml files with the complete definition or create dynamic ones based on your templating engine of choice. Eunomia already supports Helm Charts, OpenShift Templates, and Jinja2 Templates, but can easily be extended to support ohers.

These templates will be merged and processesed with a set of environment-specific parameters to get a list of resource manifests. Then these manifest can be created/updated/deleted in Kubernetes.


While this controller can certainly be used to directly populate an individual namespace with a configuration stored in git, the vision is that a hierarchy of controllers will be used to populate multiple namespaces. Ideally this approach will be used to bring a newly created cluster to a desired configured state. Only the initial seeding CR should have cluster-level permissions. Any sub-CRs should have progressively less access assigned to their service accounts.

Here is a very simple example of how the hierarchy might look like:


The main sections of the GitOpsConfig CRD are described below.


The configuration is described in the GitOpsConfig CRD, here is an example:

kind: GitOpsConfig
  name: simple-test
  # Add fields here
    ref: master
    contextDir: simple/templates
    secretRef: template-gitconfig
    contextDir: simple/parameters
    secretRef: parameter-gitconfig  
  - type: Change
  - type: Webhook
  - type: Periodic
    cron: "0 * * * *"
  ServiceAccountRef:      "mysvcaccount",
  ResourceDeletionMode:   "Cascade",
  ResourceHandlingMode:   "CreateOrMerge",

TemplateSource and ParameterSource

The TemplateSource and ParameterSource specify where the templates and the parameters are stored. The exact contents of these locations depend on the templating engine that has been selected.

The fields of this section are:

    ref: master
    contextDir: simple/templates
    HTTPProxy: <http proxy>
    HTTPSProxy: <https proxy>
    NOProxy: <no Proxy>
    SecretRef: <gitconfig and credentials secret>

    ref: master
    contextDir: seed/parameters
    HTTPProxy: <http proxy>
    HTTPSProxy: <https proxy>
    NOProxy: <no Proxy>
    SecretRef: <gitconfig and credentials secret>

These are the mandatory contraints and default behaviors of the fields:

field name mandatory default
uri yes N/A
ref no master
contextDir no .
HTTPProxy no
HTTPSProxy no
NOProxy no
SecretRef no

If a secret is provided, then it is assumed that the conenction to Git requires authentication. See the [Git Authentication] (#git authentication) section below for more details.

If the uri is not specified in the parameterSource section, then it will default to the uri specified under templateSource.

Git Authentication

Specifing a SecretRef will automatically turn on git authentication. The secrets for the template and parameter repos will be mounted respectively in the /template-gitconfig and /parameter-gitconfig of the job pod. The referenced secrets must be available and how they are provisioned is beyond the scope of this operator. See the Vision paragraph on how to build a hierachical structure, where the resourecs needed to run a given GitOpsConfig are configured by a predecessor GitpOpsConfig instance.

This secret will be linked from ~/ of the used running the pod. The secret must contain a .gitconfig file and may contain other files. The passed .gitconfig will be used during the git operations. It is advised to referece any additional files via the absolute path.

Username and password authentication

For username and password based authentication create the following .gitconfig:

    sslCAInfo = /template-gitconfig/ca.crt

    name = gitconfig

    helper = store

When the credential helper is of type store, credentials are by default retrieved from the ~/.git-credentials file. This file should also be added to the secret and has the following format:

https://<username>:<password>@<git server fqdn>

Don't forget to provide the ca.crt file to the secret.

Certificate based authentication

For certifciate based authentication, create the following .gitconfig:

    sshCommand = 'ssh -i /template-gitconfig/mykey.rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'

and add the mykey.rsa file to the secret.


You can enable one or multiple triggers.

Name Description
Change This triggers every time the CR is changed, including when it is created.
Periodic Periodically apply the configuration. This can be used to either schedule changes for a specific time, use it for drift management to revert any changes, or as a safeguard in case webhooks were missed. It uses a cron-style expression.
Webhook This triggers when something on git changes. You have to configure the webhook yourself.

Template Engine

When it's time to apply a configuration, the GitOps controller runs a job pod. The image of the job pod can be specified in the templateProcessorImage field. This is the plugin mechanism to support multiple template engines. A base image is provided that can be inherited to simplify the process of adding support for a new templating engine. The base image provides the following workflow:

  1. : This will clone the template and parameter repos. It is expected that there will be no need to customize this. Any required changes are most likely worthy of a pull-request upstream.

  2. : This will create a set of environment variables that are specific to the target Kubernetes environment. Currently the following variable are supported:

    Name Description
    CA_BUNDLE Platform-level CA bundle
    SERVICE_CA_BUNDLE Service-level CA bundle
    DEFAULT_ROUTE_DOMAIN Base route domain for the default router
    NAMESPACE Current namespace
  3. : This shell that needs to be overwritten in order to support a different templating engine. The contract is the following:

    • Templates are available at the location specified by the variable: CLONED_TEMPLATE_GIT_DIR
    • Parameters are available at the location pecified by the variable: CLONED_PARAMETER_GIT_DIR
    • After the template processing completes, the processed manifests should be stored at the location of this variable: MANIFEST_DIR
  4. : Processes the resources in MANIFEST_DIR. One or more files can be present, and all will be processed.

Currently the following templating engines are supported (follow the link to see examples of how new template processors can be added):


This is the service account used by the job pod that will process the resources. The service account must be present in the same namespace as the one where the GitOpsConfig CR is and must have enough permission to manage the resources. It is out of scope of this controller how that service account is provisioned, although you can use a different GitOpsConfig CR to provision it (seeding CR).

Resource Handling Mode

This field specifies how resources should be handled, once the templates are processed. The following modes are currently supported:

  1. CreateOrMerge, which is roughly equivalent to kubectl apply.
  2. CreateOrUpdate, which will overwrite any existing configuration.
  3. Patch. Patch requires objects to already exists and will patch them. It's useful when customizing objects that are provided through other means.
  4. None. In some cases there may be template processors or automation frameworks where the processing of templates and handling of generated resources are a single step. In that case, Eunomia can be configured to skip the built-in resource handling step.

Resource Deletion Mode

This field specifies how to handle resources when the GitOpsConfig object is deleted. Two options are available:

  1. Retain, resources previsouly created are left intact.
  2. Delete, resources are delete with the cascade option.
  3. None, resource deletion is not handled at all.

Installing Eunomia

Installing on Kubernetes

Simply use the helm chart to install it on your flavor of Kubernetes.

# Deploy the operator pre-requisites, which require cluster-admin access
helm template deploy/helm/prereqs/ | kubectl apply -f -

# Deploy the operator
helm template deploy/helm/operator/ | kubectl apply -f -

Installing on OpenShift

Use the below command to install Eunomia on OpenShift. This will also give you the route for the ingress webhook.

# Deploy the operator pre-requisites, which require cluster-admin access
helm template deploy/helm/prereqs/ | oc apply -f -

# Deploy the operator
helm template deploy/helm/operator/ --set openshift.route.enabled=true | oc apply -f -

Examples / Demos

We've created several examples for you to test out Eunomonia. See EXAMPLES for details.


Please see our development documentation for details.


Please see our troubleshooting guide for details.


See LICENSE for details.

Code of Conduct

See for details.

You can’t perform that action at this time.