Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runnable samples #146

Merged
merged 2 commits into from
Aug 3, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Reference implementation of the [ServiceBinding.io](https://servicebinding.io) [
- [Getting Started](#getting-started)
- [Running on the cluster](#running-on-the-cluster)
- [Undeploy controller](#undeploy-controller)
- [Samples](#samples)
- [Contributing](#contributing)
- [Test It Out](#test-it-out)
- [Modifying the API definitions](#modifying-the-api-definitions)
Expand Down Expand Up @@ -116,6 +117,15 @@ Undeploy the controller to the cluster:
make undeploy
```

## Samples

Samples are located in the [samples directory](./samples), including:

- [Spring PetClinic with MySQL](./samples/spring-petclinic)
- [Controlled Resource](./samples/controlled-resource)
- [Overridden Type and Provider](./samples/overridden-type-provider)
- [Multiple Bindings](./samples/multi-binding)

## Contributing

### Test It Out
Expand Down
92 changes: 92 additions & 0 deletions samples/controlled-resource/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Controlled Resource

Sometimes a the workload resource you create is not PodSpec-able, but it creates a child resource that is. In cases like this, we can inject into the child resource. Normally, it is not possible to mutate a controlled resource, as the controller should see the mutation and undo the change, however, `ServiceBinding`s are able to inject into controlled resources and keep the injected values in sync.

This behavior may not be portable across other service binding implementations.

## Setup

If not already installed, [install the ServiceBinding CRD and controller][install].

For this sample, we'll also need [Knative Serving][knative-install].

## Deploy

Apply the custom workload, service and connect them with a `ServiceBinding`:

```sh
kubectl apply -f ./samples/controlled-resource
```

## Understand

The workload.yaml defines a Knative `Service`, which in turn controls a Knative `Configuration`.
The `ServiceBinding`'s workload reference targets the `Configuration`, instead of the `Service`.

> Note: the Knative `Service` and `Configuration` resources are both PodSpec-able, and can both be the target of a service binding. Typically, a binding would target the service instead of the configuration resource. We're targeting the configuration in this sample to demonstrate targeting a controlled resource.

The workload reference is using a label selector to match the target configuration. Label selectors are useful when a binding needs to target multiple resources, or the name of the target resource is not known. Controllers may generate multiple child resources, or use a generated name which will not be known in advance.

We can see the binding applied to the Knative `Configuration`.

```sh
kubectl describe configurations.serving.knative.dev -l serving.knative.dev/service=controlled-resource
```

It will contain an environment variable `TARGET` provided by the binding.

```
...
Env:
Name: SERVICE_BINDING_ROOT
Value: /bindings
Name: TARGET
Value From:
Secret Key Ref:
Key: target
Name: controlled-resource
...
```

Try manually editing the configuration to add a new environment variable.

```sh
kubectl edit configurations.serving.knative.dev controlled-resource
```

The new value will be removed by the Knative controller.
This is normal for controlled resources.
The service binding is able to inject into controlled resources because it hooks directly into the cluster's API server via a mutating webhook.
The webhook is able to intercept requests from the Knative controller and transparently reapplies the binding, preventing the controller from removing the injected values.

Knative resources are not exposed by default for binding, This sample includes a ClusterRole that grants the controller access to project the service into Knative Serving resources. ClusterRoles that include the `servicebinding.io/controller: "true"` label are automatically available to the Service Binding Runtime.

## Play

Try invoking the Knative Service to view the message injected by the service binding

```sh
kubectl get ksvc controlled-resource --output=custom-columns=NAME:.metadata.name,URL:.status.url
```

Assuming ingress is properly configured, an invocable URL will be returned for the controlled-resource service.

```
NAME URL
controlled-resource http://controlled-resource.default.{YOUR_CLUSTERS_HOSTNAME}
```

Make a request to the service.

```sh
curl http://controlled-resource.default.{YOUR_CLUSTERS_HOSTNAME}
Hello service binding!
```

Going further, try changing the message in the controlled-resource `Secret`.
While values in the volume are updated in a running container, an environment variable will only be updated when a new Pod is created.
Because Knative will auto-scale workloads based on requests, new Pods will be created over time, but exactly when is highly dependant on the load.


[knative-install]: https://knative.dev/docs/install/yaml-install/serving/install-serving-with-yaml/
[install]: ../../README.md#getting-started
35 changes: 35 additions & 0 deletions samples/controlled-resource/rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright 2022 The Kubernetes Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: servicebinding-knative-serving
labels:
servicebinding.io/controller: "true"
rules:
- apiGroups:
- serving.knative.dev
resources:
- configurations
- revisions
- services
verbs:
- get
- list
- watch
- update
- patch
35 changes: 35 additions & 0 deletions samples/controlled-resource/service-binding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright 2020 The Kubernetes Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
apiVersion: servicebinding.io/v1beta1
kind: ServiceBinding
metadata:
name: controlled-resource
spec:
# direct Secret reference is used for compatibility, but not recommended for dynamically provisioned services
service:
apiVersion: v1
kind: Secret
name: controlled-resource
workload:
apiVersion: serving.knative.dev/v1
kind: Configuration
# use a label selector since we may not know the name of the controlled resource
selector:
matchLabels:
serving.knative.dev/service: controlled-resource
env:
- name: TARGET
key: target
22 changes: 22 additions & 0 deletions samples/controlled-resource/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2020 The Kubernetes Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
apiVersion: v1
kind: Secret
metadata:
name: controlled-resource
type: Opaque
stringData:
target: "service binding"
25 changes: 25 additions & 0 deletions samples/controlled-resource/workload.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2020 The Kubernetes Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: controlled-resource
spec:
template:
spec:
containers:
# from https://knative.dev/docs/serving/samples/hello-world/helloworld-go/
- image: gcr.io/knative-samples/helloworld-go
95 changes: 95 additions & 0 deletions samples/multi-binding/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Multi-bindings

Often an workload needs to consume more than one service.
In that case, multiple service binding resources can each bind a distinct service to the same workload.

In this sample, we'll use a [Kubernetes Job][kubernetes-jobs] to dump the environment to the logs and exit.

## Setup

If not already installed, [install the ServiceBinding CRD and controller][install].

## Deploy

Like Pods, Kubernetes Jobs are immutable after they are created.
We need to make sure the `ServiceBinding`s are fully configured before the workload is created.

Apply the services and `ServiceBinding`s:

```sh
kubectl apply -f ./samples/multi-binding/service.yaml -f ./samples/multi-binding/service-binding.yaml
```

Check on the status of the `ServiceBinding`:

```sh
kubectl get servicebinding -l multi-binding=true -oyaml
```

For each service binding, the `ServiceAvailable` condition should be `True` and the `Ready` condition `False`.

```
...
conditions:
- lastTransitionTime: "2022-08-02T21:28:45Z"
message: the workload was not found
reason: WorkloadNotFound
status: Unknown
type: Ready
- lastTransitionTime: "2022-08-02T21:28:45Z"
message: ""
reason: ResolvedBindingSecret
status: "True"
type: ServiceAvailable
```

Create the workload `Job`:

```sh
kubectl apply -f ./samples/multi-binding/workload.yaml
```

## Understand

Each `ServiceBinding` resource defines an environment variable that is projected into the workload in addition to the binding volume mount.

```sh
kubectl describe job multi-binding
```

```
...
Environment:
SERVICE_BINDING_ROOT: /bindings
MULTI_BINDING_1: <set to the key 'number' in secret 'multi-binding-1'> Optional: false
MULTI_BINDING_2: <set to the key 'number' in secret 'multi-binding-2'> Optional: false
...
```

The job dumps the environment to the log and then exits.
We should see our injected environment variable as well as other variable commonly found in Kubernetes containers.

Inspect the logs from the job:

```sh
kubectl logs -l job-name=multi-binding --tail 100
```

```
...
SERVICE_BINDING_ROOT=/bindings
MULTI_BINDING_1=1
MULTI_BINDING_2=2
...
```

## Play

Try adding yet another binding targeting the same Job.
Remember that Jobs are immutable after they are created, so you'll need to delete and recreate the Job to see the additional binding.

Alternatively, define a `Deployment` and update each binding to target the new Deployment.
Since Deployments are mutable, each service binding that is added or removed will be reflected on the Deployment and trigger the rollout of a new `ReplicaSet`.

[install]: ../../README.md#getting-started
[kubernetes-jobs]: https://kubernetes.io/docs/concepts/workloads/controllers/job/
55 changes: 55 additions & 0 deletions samples/multi-binding/service-binding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright 2020 The Kubernetes Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
apiVersion: servicebinding.io/v1beta1
kind: ServiceBinding
metadata:
name: multi-binding-1
labels:
multi-binding: "true"
spec:
# direct Secret reference is used for compatibility, but not recommended for dynamically provisioned services
service:
apiVersion: v1
kind: Secret
name: multi-binding-1
workload:
apiVersion: batch/v1
kind: Job
name: multi-binding
env:
- name: MULTI_BINDING_1
key: number

---
apiVersion: servicebinding.io/v1beta1
kind: ServiceBinding
metadata:
name: multi-binding-2
labels:
multi-binding: "true"
spec:
# direct Secret reference is used for compatibility, but not recommended for dynamically provisioned services
service:
apiVersion: v1
kind: Secret
name: multi-binding-2
workload:
apiVersion: batch/v1
kind: Job
name: multi-binding
env:
- name: MULTI_BINDING_2
key: number
Loading