Skip to content

Latest commit

 

History

History
223 lines (165 loc) · 13.4 KB

README.md

File metadata and controls

223 lines (165 loc) · 13.4 KB

REUSE status

component-operator

About this project

The Kubernetes operator provided by this repository allows to manage the lifecycle of components in Kubernetes clusters. Here, components are understood as sets of Kubernetes resources (such as deployments, services, RBAC entities, ...), and components are described as instances of the custom resource type components.cs.core.sap.com (kind Component), which will be reconciled by component-operator. The Component type allows to specify

  • the source of the manifests describing the dependent resources
  • parameterization of these manifests, in case the manifests use go templates, such as Helm charts
  • dependencies to other component instances.

Thus, components are similar to flux kustomizations, but have some important advantages:

  • They use the component-operator-runtime framework to render and deploy dependent objects; therefore the manifest source can be any input that is understood by component-operator-runtime's KustomizeGenerator or HelmGenerator. In particular, go-templatized kustomizations are allowed; check the component-operator-runtime documentation for details.
  • It is possible to pin components to a specific source revision or digest through the spec.revision and spec.digest fields, respectively.
  • Dependencies (as specified in spec.dependencies) are not only honored at creation/update, but also on deletion.

A sample component could look like this:

---
apiVersion: core.cs.sap.com/v1alpha1
kind: Component
metadata:
  namespace: comp-ns
  name: comp-name
spec:
  namespace: target-ns
  name: target-name
  kubeConfig:
    secretRef:
      name: kubeconfig
  requeueInterval: 10m
  retryInterval: 3m
  timeout: 5m
  sourceRef:
    fluxGitRepository:
      namespace: source-ns
      name: source-name
  revision: main/4b14dbc37ca976be75a7508bb41fb99d4a36ab9
  path: ./deploy
  values:
    someKey: someValue
  valuesFrom:
  - name: values-secret
  decryption:
    provider: sops
    secretRef:
      name: sops-secret
  postBuild:
    substitute:
      VAR: VALUE
    substituteFrom:
    - name: subst-secret
  dependencies:
  - namespace: other-namespace
    name: other-component
  - name: another-component

Target namespace and name

The optional fields spec.namespace and spec.name may be provided to customize the deployment namespace/name of the component (as defined by component-operator-runtime). If not set, the target namespace and name will equal metadata.namespace and metadata.name of the component.

KubeConfig reference

By default, the dependent objects will be deployed in the same cluster where the component resides. A kubeconfig may be provided to deploy into a remote cluster, by specifying a secret (in the component's namespace) as spec.kubeConfig.secretRef.name. By default, the secret will be looked up at one of the following keys: value, value.yaml, value.yml (in this order). A custom key can be specified as spec.kubeConfig.secretRef.key. Note that the used kubeconfig must not use any kubectl plugins, such as kubelogin.

Reqeue interval, retry interval and timeout

The field spec.requeueInterval defines the period, after which a component is re-reconciled after a previously successful reconcilation. It is optional, the default is 10 minutes.

The field spec.retryInterval defines the period, after which a component is re-reconciled if a retriable error occurs. Check the component-operator-runtime documentation for more details about retriable errors. This field is optional; if unset the retry interval equals the effective requeue interval.

Finally, the field spec.timeout defines how long dependent objects are expected to take to become ready. If not all depenents are ready, then the component state is Processing until the timeout has elapsed; afterwards, the component state flips to Error. Note that the operator still tries to reconcile the dependent objects in that case, just as before. The timeout restarts counting down whenever the component itself, or the rendered dependent manifests change. The timeout field is optional; if unset, it is defaulted with the effective requeue interval.

Source reference

The mandatory field spec.sourceRef defines the source of the manifests used for generation of the dependent objects. Currently, the following types of sources are supported (exactly one must be present):

# Flux GitRepository
sourceRef:
  fluxGitRepository:
    # namespace: source-ns
    name: gitrepo-name

# Flux OciRepository
sourceRef:
  fluxOciRepository:
    # namespace: source-ns
    name: ocirepo-name

# Flux Bucket
sourceRef:
  fluxBucket:
    # namespace: source-ns
    name: bucket-name

# Flux HelmChart
sourceRef:
  fluxHelmChart:
    # namespace: source-ns
    name: helmchart-name

Cross-namespace references are allowed; if namespace is not provided, the source will be assumed to exist in the component's namespace.

Source revision and digest

It is possible to pin a Component resource to a specific revision or digest of the source artifact by setting spec.revision and spec.digest, respectively. Pinning means that the component will remain in a Pending state, until the used source object's revision or digest matches the the value specified in spec.revision or spec.digest. In case of flux sources, revision and digest refer to status.artifact.revision and status.artifact.digest of the according flux object. It should be noted that a revision or digest mismatch in the above sense never blocks the deletion of the component.

Source path

By default, the manifests (as kustomization or helm chart) are assumed to be located at the root folder of the specified source artifact. A subfolder can be specified by setting spec.path.

Values and ValuesFrom

Parameters for the referenced helm chart or kustomization can be provided either inline, by spec.Values or as a secret key references, listed in spec.ValuesFrom, such as

valuesFrom:
- name: values-secret
  # key: valuesKey

The key attribute is optional; if missing the following default keys will be tried: values, values.yaml, values.yml (in this order), until one is found in the referenced secret. If multiple secret keys are referenced in spec.valuesFrom, their contents will be deeply merged onto each other in the order of appearance. If in addition spec.values is defined, its content will be merged onto the merged values from spec.valuesFrom.

The aggregated values object obtained this way will then be passed as parameters to the according KustomizeGenerator or HelmGenerator, depending on whether the source artifacts contains a kustomization or a helm chart.

Decryption

Parts of the given manifests may be encrypted. Currently, only SOPS is supported as encryption provider. So spec.decryption.provider must be set to the value sops. In that case, a secret reference must be provided, which follows the exact same logic as used by flux. With the restriction that only GPG and Age are supported as encryption engines.

Post-build variable substitution

The rendered manifest may contain bash-style variable references, as defined by the envsubst Go package. The replacements may be defined either inline in spec.postBuild.substitute as KEY: VALUE pairs, or loaded by secret references, where the keys of the secrets will be interpreted as variable names (and therefore have to be valid bash variable names). If multiple secrets, and maybe inline substitutions are provided, they will be merged in the usual order (secrets in order of appearance, and then inline content).

Adoption policy

It can happen that a dependent object exists in the cluster already, but is not managed by the component object being reconciled (the ownership is determined through the label component-operator.cs.sap.com/owner-id). The behaviour of component-operator in that situation can be configured by setting spec.adoptionPolicy. The following values are possible:

  • IfUnowned (which is also the default behaviour if the adoption policy attribute is unset): adopt existing objects, unless they have the above label set, but with a value pointing to a different owning component; in that case, a failure will occur
  • Never: always fail if an object already exists (not owned by the current component of course)
  • Always: always adopt existing objects.

The adoption policy can be overridden on a per-object level by setting annotation component-operator.cs.sap.com/adoption-policy.

Update policy

It is possible to tweak how component-operator performs updates of dependent objects by setting spec.updatePolicy. The following values are supported:

  • Replace: use a PUT request to update the object; this corresponds to kubectl replace
  • Recreate: delete and recreate objects which are to be updated
  • SsaMerge: use a server-side-apply PATCH request to update the object; this corresponds to kubectl apply --server-side --force-conflicts
  • SsaOverride (which is the default behaviour if the update policy is not specified): same as SsaMerge and, in addition, claim all existing fields that have a field owner starting with prefix kubectl or helm; this reverts changes done by these field managers, respectively drops affected fields if not specified by the submitted intent and not owned by somebody else.

The update policy can be overridden on a per-object level by setting annotation component-operator.cs.sap.com/update-policy.

Delete policy

It is possible to tweak what happens with dependents objects when the owning component is deleted. By default objects are deleted. By setting spec.deletePolicy to Orphan, dependent objects will not be deleted in that case, but just left around in the cluster. Note that this affects only the case when the component is deleted. If a depdendent object becomes obsolete because a new revision of the component manifests does no longer contain it, it will still be removed from the cluster. The delete policy can be overridden on a per-object level by setting annotation component-operator.cs.sap.com/delete-policy.

Dependencies

As with flux kustomizations, it is possible to declare dependencies between Component objects, that means, to list other components, even cross-namespace, in spec.dependencies. Providing no namespace means that the referenced component is assumed to be in the same namespace as the depending component. During creation or update, a component will remain in status Pending until all its dependencies are in a Ready state. Other than in the flux case, where dependencies are only evaluated during creation/update, but not for deletion, component dependencies are honored (in reverse order) also during deletion. That means, if a component which is listed as dependency of one or more other components, is being deleted, then it will go into a DeletionPending state, until all these depending components are gone.

Requirements and Setup

The operator relies on the flux source controller, which can be installed by running

flux install --components source-controller

The recommended deployment method for the operator itself is to use the Helm chart included in this repository:

helm upgrade -i component-operator oci://ghcr.io/sap/component-operator/charts/component-operator

Documentation

The API reference can be found here: https://pkg.go.dev/github.com/sap/component-operator.

Support, Feedback, Contributing

This project is open to feature requests/suggestions, bug reports etc. via GitHub issues. Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our Contribution Guidelines.

Security / Disclosure

If you find any bug that may be a security problem, please follow our instructions at in our security policy on how to report it. Please do not create GitHub issues for security-related doubts or problems.

Code of Conduct

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its Code of Conduct at all times.

Licensing

Copyright 2024 SAP SE or an SAP affiliate company and component-operator contributors. Please see our LICENSE for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available via the REUSE tool.