Binding secondary workloads that are not compliant with PodSpec

A typical scenario in service binding involves configuring the backing service, the workload (Deployment), and Service Binding Operator. Consider a scenario that involves a secondary workload (which can also be an application Operator) that is not compliant with PodSpec and is between the primary workload (Deployment) and Service Binding Operator.

For such secondary workload resources, the location of the container path is arbitrary. For service binding, if the secondary workload in a CR is not compliant with the PodSpec, you must specify the location of the container path. Doing so projects the binding data into the container path specified in the secondary workload of the ServiceBinding custom resource (CR), for example, when you do not want the binding data inside a pod.

Service Binding Operator provides an option to configure the value of where the container path or secret path is and bind these paths at a custom location. This option is available only for the binding.operators.coreos.com API group when the binding data is projected as environment variables.

Configuring the custom location of the container path

Consider a secondary workload CR, which is not compliant with the PodSpec and has containers located at the spec.containers path:

Example: Secondary workload CR
apiVersion: "stable.example.com/v1"
kind: AppConfig
metadata:
    name: example-appconfig
spec:
    containers:
    - name: hello-world
      image: yusufkaratoprak/kubernetes-gosample:latest
      ports:
      - containerPort: 8090

Procedure

  • Configure the spec.containers path by specifying a value in the ServiceBinding CR and bind this path to a spec.application.bindingPath.containersPath custom location:

    Example: ServiceBinding CR with the spec.containers path in a custom location
    apiVersion: binding.operators.coreos.com/v1alpha1
    kind: ServiceBinding
    metadata:
        name: binding-request
    spec:
        namePrefix: qiye111
        application: (1)
          name: nodejs-app
          group: apps
          version: v1
          resource: deployments
        application: (2)
          name: example-appconfig
          group: stable.example.com
          version: v1
          resource: appconfigs
          bindingPath:
            containersPath: spec.containers (3)
        services:
        - group: postgres-operator.crunchydata.com
          version: v1alpha1
          kind: Database
          name: example-db
          id: postgresDB
        - group: ""
          version: v1
          kind: Secret
          name: production-db-secret
          id: postgresSecret
          namePrefix: qiye
    1 The sample application that points to a Deployment or any other similar resource with an embedded PodSpec.
    2 The secondary workload, which is not compliant with the PodSpec.
    3 The custom location of the container path.

After you specify the location of the container path, Service Binding Operator generates the binding data, which becomes available in the container path specified in the secondary workload of the ServiceBinding CR.

The following example shows the spec.containers path with the envFrom and secretRef fields:

Example: Secondary workload CR with the envFrom and secretRef fields
apiVersion: "operator.sbo.com/v1"
kind: AppConfig
metadata:
    name: example-appconfig
spec:
    containers:
    - env: (1)
      - name: ServiceBindingOperatorChangeTriggerEnvVar
        value: "31793"
      envFrom:
      - secretRef:
          name: binding-request (2)
      image: yusufkaratoprak/kubernetes-gosample:latest
      name: hello-world
      ports:
      - containerPort: 8090
      resources: {}
1 Unique array of containers with values generated by the Service Binding Operator. These values are based on the backing service CR.
2 Name of the Secret resource generated by the Service Binding Operator.

Configuring the custom location of the secret path

Consider a secondary workload CR, which is not compliant with the PodSpec, with only the secret at the spec.secret path:

Example: Secondary workload CR
apiVersion: "stable.example.com/v1"
kind: AppConfig
metadata:
    name: example-appconfig
spec:
    secret: ""

Procedure

  • Configure the spec.secret path by specifying a value in the ServiceBinding CR and bind this path at a spec.application.bindingPath.secretPath custom location:

    Example: ServiceBinding CR with the spec.secret path in a custom location
    apiVersion: binding.operators.coreos.com/v1alpha1
    kind: ServiceBinding
    metadata:
        name: binding-request
    spec:
    ...
        namePrefix: qiye111
        application: (1)
          name: example-appconfig
          group: stable.example.com
          version: v1
          resource: appconfigs
          bindingPath:
            secretPath: spec.secret (2)
        services:
        - group: postgres-operator.crunchydata.com
          version: v1alpha1
          kind: Database
          name: example-db
          id: postgresDB
          namePrefix: qiye
    ...
    1 The secondary workload, which is not compliant with the PodSpec.
    2 The custom location of the secret path that contains the name of the Secret resource.

After you specify the location of the secret path, Service Binding Operator generates the binding data, which becomes available in the secret path specified in the secondary workload of the ServiceBinding CR.

The following example shows the spec.secret path with the binding-request value:

Example: Secondary workload CR with the binding-request value
...
apiVersion: "stable.example.com/v1"
kind: AppConfig
metadata:
    name: example-appconfig
spec:
    secret: binding-request-72ddc0c540ab3a290e138726940591debf14c581 (1)
...
1 Unique name of the Secret resource generated by the Service Binding Operator.

Workload resource mapping

  • Workload resource mapping is available for the secondary workloads of the ServiceBinding custom resource (CR) for both the API groups: binding.operators.coreos.com and servicebinding.io.

  • You must namespace ClusterWorkloadResourceMapping resources only under the servicebinding.io API group. However, the ClusterWorkloadResourceMapping resources interact with ServiceBinding resources under both the binding.operators.coreos.com and servicebinding.io API groups.

The specification also provides a way to define exactly where binding data needs to be projected. Use this method when you are not able to configure custom path locations correctly by previous methods. You can define ClusterWorkloadResourceMapping resources only in the servicebinding.io API group, which specify where binding data is to be projected for a given workload kind.

Example: Schema of the ClusterWorkloadResourceMapping resource
apiVersion: servicebinding.io/v1beta1
kind: ClusterWorkloadResourceMapping
metadata:
  name: # string (1)
  ...
spec:
  versions: # required, at least one entry must be defined
  - version: # string (2)
    annotations: # string (Fixed JSONPath), optional (3)
    containers: # optional
    - path: # string (JSONPath) (4)
      name: # string (Fixed JSONPath), optional (5)
      env: # string (Fixed JSONPath), optional (6)
      volumeMounts: # string (Fixed JSONPath), optional (7)
    volumes: # string (Fixed JSONPath), optional (8)
1 Name of the ClusterWorkloadResourceMapping resource, which must be qualified as the plural.group of the mapped workload resource. For example, cronjobs.batch for CronJobs.
2 Version of the resource that is being mapped. Any version that is not specified can be matched with the "*" wildcard.
3 Optional: Identifier of the .annotations field in a pod, specified with a fixed JSONPath. The default value is .spec.template.spec.annotations.
4 Identifier of the .containers and .initContainers fields in a pod, specified with a JSONPath. If no entries under the containers field are defined, the Service Binding Operator defaults to two paths: .spec.template.spec.containers[] and .spec.template.spec.initContainers[], with all other fields set as their default. However, if you specify an entry, then you must define the .path field.
5 Optional: Identifier of the .name field in a container, specified with a fixed JSONPath. The default value is .name.
6 Optional: Identifier of the .env field in a container, specified with a fixed JSONPath. The default value is .env.
7 Optional: Identifier of the .volumeMounts field in a container, specified with a fixed JSONPath. The default value is .volumeMounts.
8 Optional: Identifier of the .volumes field in a pod, specified with a fixed JSONPath. The default value is .spec.template.spec.volumes.

In this context, a "Fixed JSONPath" is a subset of the JSONPath grammar that accepts only the following operations:

  • Field lookup: .spec.template

  • Array indexing: .spec['template']

All other operations are forbidden.

  • Most of these fields are optional. When they are not specified, the Service Binding Operator assumes defaults compatible with PodSpec resources.

  • The Service Binding Operator requires that each of these fields is structurally equivalent to the corresponding field in a pod deployment. For example, the contents of the .env field in a workload resource must be able to accept the same structure of data that the .env field in a Pod resource would. Otherwise, projecting binding data into such a workload might result in unexpected behavior from the Service Binding Operator.

Example: Mapping for CronJob.batch/v1 resources
apiVersion: servicebinding.io/v1beta1
kind: ClusterWorkloadResourceMapping
metadata:
 name: cronjobs.batch
spec:
  versions:
  - version: "v1"
    annotations: .spec.jobTemplate.spec.template.metadata.annotations
    containers:
    - path: .spec.jobTemplate.spec.template.spec.containers[*]
    - path: .spec.jobTemplate.spec.template.spec.initContainers[*]
    volumes: .spec.jobTemplate.spec.template.spec.volumes

The following behavior occurs only in the binding.operators.coreos.com API group:

  1. If a ServiceBinding resource with the bindAsFiles: false flag value is created together with one of these mappings, then environment variables are projected into the .envFrom field underneath each path field specified in the corresponding ClusterWorkloadResourceMapping resource.

  2. As a cluster administrator, you can specify both a ClusterWorkloadResourceMapping resource and the .spec.application.bindingPath.containersPath field in a ServiceBinding.bindings.coreos.com resource for binding purposes. The Service Binding Operator attempts to project binding data into the locations specified in both of these methods. This behavior is equivalent to adding a container entry to the corresponding ClusterWorkloadResourceMapping resource with the path: $containersPath attribute, with all other values taking their default value.