Skip to the content.

Service Binding Specification

Specification for binding services to runtime applications running in Kubernetes.

Terminology definition

Motivation

Proposal

The following sections outline the details of the specification.

Making a service bindable

Minimum requirements for being bindable

A bindable service MUST comply with one-of:

EXPERIMENTALThe service MUST also make itself discoverable by complying with one-of:

Pointer to binding data

This specification supports different scenarios for exposing bindable data. Below is a summary of how to indicate what is interesting for binding. Please see the annotation section for the full set with more details.

  1. OLM-enabled Operator: Use the statusDescriptor and/or specDescriptor parts of the CSV to mark which status and/or spec properties reference the binding data:
    • The reference’s x-descriptors with a possible combination of:
      • ConfigMap:

        - path: data.dbcredentials
          x-descriptors:
            - urn:alm:descriptor:io.kubernetes:ConfigMap
            - servicebinding
        
      • Secret:

        - path: data.dbcredentials
          x-descriptors:
            - urn:alm:descriptor:io.kubernetes:Secret
            - servicebinding
        
      • Individual binding items from a Secret:

        - urn:alm:descriptor:io.kubernetes:Secret
        - servicebinding:username
        
        - urn:alm:descriptor:io.kubernetes:Secret
        - servicebinding:password
        
      • Individual binding items from a ConfigMap:

        - urn:alm:descriptor:io.kubernetes:ConfigMap
        - servicebinding:port
        
        - urn:alm:descriptor:io.kubernetes:ConfigMap
        - servicebinding:host
        
      • Individual backing items from a path referencing a string value

        - path: data.uri
          x-descriptors:
            - servicebinding
        
  2. Non-OLM Operator: - An annotation in the Operator’s CRD to mark which status and/or spec properties reference the binding data :
    • ConfigMap:

      "servicebinding.dev/certificate":
      "path={.status.data.dbConfiguration},objectType=ConfigMap"
      
    • Secret:

      "servicebinding.dev/dbCredentials":
      "path={.status.data.dbCredentials},objectType=Secret"
      
    • Individual binding items from a ConfigMap

      “servicebinding.dev/host":
       “path={.status.data.dbConfiguration},objectType=ConfigMap,sourceKey=address"
      
      “servicebinding.dev/port":
      “path={.status.data.dbConfiguration},objectType=ConfigMap
      
    • Individual backing items from a path referencing a string value

      “servicebinding.dev/uri”:"path={.status.data.connectionURL}"
      
  3. Regular k8s resources (Ingress, Route, Service, Secret, ConfigMap etc) - An annotation in the corresponding Kubernetes resources that maps the status, spec or data properties to their corresponding binding data.

All annotations used in CRDs in the above section can be used for regular k8s resources, as well.

The above pattern can be used to expose external services (such as from a VM or external cluster), as long as there is an entity such as a Secret that provides the binding details.

Service Binding Schema

The core set of binding data is:

Extra binding properties can also be defined by the bindable service, using one of the patterns defined in Pointer to binding data.

The data that is injected or mounted into the container may have a different name because of a few reasons:

Application should rely on the SERVICE_BINDINGS environment variable for the accurate list of injected or mounted binding items, as defined below.

Request service binding

Binding is requested by the consuming application, or an entity on its behalf such as the Runtime Component Operator, via a custom resource that is applied in the same cluster where an implementation of this specification resides.

Since the reference implementation for most of this specification is the Service Binding Operator we will be using the ServiceBinding CRD, which resides in this folder, as the entity that holds the binding request.

Note - a few updates / enhancements are being proposed to the current ServiceBinding CR, tracked here.

Subscription-based services

There are a variety of service providers that require a subscription to be created before accessing the service. Examples:

The only requirement from this specification is that the subscription results in a k8s resources (Secret, etc), containing a partial or complete set of binding data (defined in Service Binding Schema). From the ServiceBinding CR’s perspective, this resource looks and feels like an additional service.

Example of a partial CR:

 services:
    - group: postgres.dev
      kind: Service
      resourceRef: global-user-db
      version: v1beta1
    - group: postgres.dev
      kind: Secret
      resourceRef: specific-user-db
      version: v1beta1

Mounting and injecting binding information

This specification allows for data to be mounted using volumes or injected using environment variables. The best practice is to mount any sensitive information, such as passwords, since that will avoid accidentally exposure via environment dumps and subprocesses. Also, binding binary data (e.g. .p12 certificate for Kafka) as an environment variable might cause a pod to fail to start (stuck on CrashLoopBackOff), so it advisable for backing services with such binding data to mark it with bindAs: volume.

The decision to mount vs inject is made in the following ascending order of precedence:

Injecting data

The key SERVICE_BINDINGS acts as a global map of the service bindings and MUST always be injected into the environment. It contains a JSON payload with bindingKeys key name containing a list of all available binding information available. Each item of the bindingKeys list includes an object containing name, bindAs and an optional mountPath (if it is bound as a volume).

Example:

SERVICE_BINDINGS = {
  "bindingKeys": [
    {
      "name": "KAFKA_USERNAME",
      "bindAs": "envVar"
    },
    {
      "name": "KAFKA_PASSWORD",
      "bindAs": "volume",
      "mountPath": "/platform/bindings/secret/"
    }
  ]
}

In the example above, the application can query the environment variable SERVICE_BINDINGS, walk its JSON payload and learn that KAFKA_USERNAME is available as an environment variable, and that KAFKA_PASSWORD is available as a mounted file inside the directory /platform/bindings/secret/.

Mounting data

Implementations of this specification must bind the following data into the consuming application container:

<mountPathPrefix>/bindings/secret/<persisted_secret>

Where: