diff --git a/README.md b/README.md index a186dce4..a6ab1180 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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 diff --git a/samples/controlled-resource/README.md b/samples/controlled-resource/README.md new file mode 100644 index 00000000..4183fcb9 --- /dev/null +++ b/samples/controlled-resource/README.md @@ -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 diff --git a/samples/controlled-resource/rbac.yaml b/samples/controlled-resource/rbac.yaml new file mode 100644 index 00000000..da1046bb --- /dev/null +++ b/samples/controlled-resource/rbac.yaml @@ -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 diff --git a/samples/controlled-resource/service-binding.yaml b/samples/controlled-resource/service-binding.yaml new file mode 100644 index 00000000..cf7895d8 --- /dev/null +++ b/samples/controlled-resource/service-binding.yaml @@ -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 diff --git a/samples/controlled-resource/service.yaml b/samples/controlled-resource/service.yaml new file mode 100644 index 00000000..c0c4642c --- /dev/null +++ b/samples/controlled-resource/service.yaml @@ -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" diff --git a/samples/controlled-resource/workload.yaml b/samples/controlled-resource/workload.yaml new file mode 100644 index 00000000..36d6a651 --- /dev/null +++ b/samples/controlled-resource/workload.yaml @@ -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 diff --git a/samples/multi-binding/README.md b/samples/multi-binding/README.md new file mode 100644 index 00000000..32d55739 --- /dev/null +++ b/samples/multi-binding/README.md @@ -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: Optional: false + 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/ diff --git a/samples/multi-binding/service-binding.yaml b/samples/multi-binding/service-binding.yaml new file mode 100644 index 00000000..f2d8b2ad --- /dev/null +++ b/samples/multi-binding/service-binding.yaml @@ -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 diff --git a/samples/multi-binding/service.yaml b/samples/multi-binding/service.yaml new file mode 100644 index 00000000..3bc295eb --- /dev/null +++ b/samples/multi-binding/service.yaml @@ -0,0 +1,31 @@ +# 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: multi-binding-1 +type: Opaque +stringData: + number: "1" + +--- +apiVersion: v1 +kind: Secret +metadata: + name: multi-binding-2 +type: Opaque +stringData: + number: "2" diff --git a/samples/multi-binding/workload.yaml b/samples/multi-binding/workload.yaml new file mode 100644 index 00000000..f0312580 --- /dev/null +++ b/samples/multi-binding/workload.yaml @@ -0,0 +1,28 @@ +# 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: batch/v1 +kind: Job +metadata: + name: multi-binding +spec: + template: + spec: + containers: + - name: workload + image: ubuntu:bionic + command: ["env"] + enableServiceLinks: false + restartPolicy: OnFailure diff --git a/samples/overridden-type-provider/README.md b/samples/overridden-type-provider/README.md new file mode 100644 index 00000000..85073019 --- /dev/null +++ b/samples/overridden-type-provider/README.md @@ -0,0 +1,97 @@ +# Overridden Type and Provider + +When projected into the workload, the binding must contain a `type` entry and should contain a `provider` entry. +If the Secret doesn't contain a type or provider, or contains the wrong values, they can be overridden for the binding. + +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 service and `ServiceBinding`: + +```sh +kubectl apply -f ./samples/overridden-type-provider/service.yaml -f ./samples/overridden-type-provider/service-binding.yaml +``` + +Check on the status of the `ServiceBinding`: + +```sh +kubectl get servicebinding -l sample=overridden-type-provider -oyaml +``` + +For each service binding, the `ServiceAvailable` condition should be `True` and the `ProjectionReady` condition `False`. + +``` +... + conditions: + - lastTransitionTime: "2022-08-02T21:32:29Z" + message: the workload was not found + reason: WorkloadNotFound + status: Unknown + type: Ready + - lastTransitionTime: "2022-08-02T21:32:29Z" + message: "" + reason: ResolvedBindingSecret + status: "True" + type: ServiceAvailable +``` + +Create the workload `Job`: + +```sh +kubectl apply -f ./samples/overridden-type-provider/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 overridden-type-provider +``` + +``` +... + Environment: + SERVICE_BINDING_ROOT: /bindings + BOUND_PROVIDER: (v1:metadata.annotations['projector.servicebinding.io/provider-7b561828-a00b-4075-9ea5-64c69535230c']) + BOUND_TYPE: (v1:metadata.annotations['projector.servicebinding.io/type-7b561828-a00b-4075-9ea5-64c69535230c']) +... +``` + +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=overridden-type-provider --tail 100 +``` + +``` +... +SERVICE_BINDING_ROOT=/bindings +BOUND_PROVIDER=overridden-provider +BOUND_TYPE=overridden-type +... +``` + +The order of variables may vary. + +## Play + +Try changing the `.spec.type` or `.spec.provider` fields on the ServiceBinding, or return them to the original values (empty string). +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/ diff --git a/samples/overridden-type-provider/service-binding.yaml b/samples/overridden-type-provider/service-binding.yaml new file mode 100644 index 00000000..573c3a5b --- /dev/null +++ b/samples/overridden-type-provider/service-binding.yaml @@ -0,0 +1,38 @@ +# 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: overridden-type-provider + labels: + sample: overridden-type-provider +spec: + type: overridden-type + provider: overridden-provider + # direct Secret reference is used for compatibility, but not recommended for dynamically provisioned services + service: + apiVersion: v1 + kind: Secret + name: overridden-type-provider + workload: + apiVersion: batch/v1 + kind: Job + name: overridden-type-provider + env: + - name: BOUND_TYPE + key: type + - name: BOUND_PROVIDER + key: provider diff --git a/samples/overridden-type-provider/service.yaml b/samples/overridden-type-provider/service.yaml new file mode 100644 index 00000000..a58f5dce --- /dev/null +++ b/samples/overridden-type-provider/service.yaml @@ -0,0 +1,23 @@ +# 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: overridden-type-provider +type: Opaque +stringData: + type: original-type + provider: original-provider diff --git a/samples/overridden-type-provider/workload.yaml b/samples/overridden-type-provider/workload.yaml new file mode 100644 index 00000000..ca17f540 --- /dev/null +++ b/samples/overridden-type-provider/workload.yaml @@ -0,0 +1,28 @@ +# 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: batch/v1 +kind: Job +metadata: + name: overridden-type-provider +spec: + template: + spec: + containers: + - name: workload + image: ubuntu:bionic + command: ["env"] + enableServiceLinks: false + restartPolicy: OnFailure diff --git a/samples/spring-petclinic/README.md b/samples/spring-petclinic/README.md new file mode 100644 index 00000000..90cf6c14 --- /dev/null +++ b/samples/spring-petclinic/README.md @@ -0,0 +1,104 @@ +# Spring PetClinic with MySQL + +[Spring PetClinic][petclinic] is a sample [Spring Boot][boot] web application that can be used with MySQL. + +## Setup + +If not already installed, [install the ServiceBinding CRD and controller][install]. + +## Deploy + +Apply the PetClinic workload, MySQL service and connect them with a ServiceBinding: + +```sh +kubectl apply -f ./samples/spring-petclinic +``` + +Wait for the workload (and database) to start and become healthy: + +```sh +kubectl wait deployment spring-petclinic --for condition=available --timeout=2m +``` + +## Understand + +Inspect the PetClinic workload as bound: + +```sh +kubectl describe deployment spring-petclinic +``` + +If the ServiceBinding is working, a new environment variable (SERVICE_BINDING_ROOT), volume and volume mount (binding-49a23274b0590d5057aae1ae621be723716c4dd5) is added to the deployment. +The describe output will contain: + +```txt +... + Containers: + workload: + ... + Environment: + SPRING_PROFILES_ACTIVE: mysql + SERVICE_BINDING_ROOT: /bindings + Mounts: + /bindings/spring-petclinic-db from servicebinding-54dec81e-49f6-467d-934f-36029f2dfd26 (ro) + Volumes: + servicebinding-54dec81e-49f6-467d-934f-36029f2dfd26: + Type: Projected (a volume that contains injected data from multiple sources) + SecretName: spring-petclinic-db + SecretOptionalName: +... +``` + +The workload uses [Spring Cloud Bindings][scb], which discovers the bound MySQL service by type and reconfigures Spring Boot to consume the service. +Spring Cloud Bindings is automatically added to Spring applications built by Paketo buildpacks. + +We can see the effect of Spring Cloud Bindings by view the workload logs: + +```sh +kubectl logs -l app=spring-petclinic -c workload --tail 1000 +``` + +The logs should contain: + +```txt +... +Spring Cloud Bindings Enabled +... + + + |\ _,,,--,,_ + /,`.-'`' ._ \-;;,_ + _______ __|,4- ) )_ .;.(__`'-'__ ___ __ _ ___ _______ + | | '---''(_/._)-'(_\_) | | | | | | | | | + | _ | ___|_ _| | | | | |_| | | | __ _ _ + | |_| | |___ | | | | | | | | | | \ \ \ \ + | ___| ___| | | | _| |___| | _ | | _| \ \ \ \ + | | | |___ | | | |_| | | | | | | |_ ) ) ) ) + |___| |_______| |___| |_______|_______|___|_| |__|___|_______| / / / / + ==================================================================/_/_/_/ + +:: Built with Spring Boot :: 2.3.3.RELEASE + + +2022-08-02 21:35:27.236 INFO 1 --- [ main] o.s.s.petclinic.PetClinicApplication : Starting PetClinicApplication v2.3.0.BUILD-SNAPSHOT on spring-petclinic-5f868997f6-9q8jm with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace) +2022-08-02 21:35:27.243 INFO 1 --- [ main] o.s.s.petclinic.PetClinicApplication : The following profiles are active: mysql +2022-08-02 21:35:27.350 INFO 1 --- [ main] .BindingSpecificEnvironmentPostProcessor : Creating binding-specific PropertySource from Kubernetes Service Bindings +... +``` + +## Play + +To connect to the workload, forward a local port into the cluster: + +```sh +kubectl port-forward service/spring-petclinic 8080:80 +``` + +Then open `http://localhost:8080` in a browser. + + +[petclinic]: https://github.com/spring-projects/spring-petclinic +[boot]: https://spring.io/projects/spring-boot +[paketo]: https://paketo.io +[install]: ../../README.md#getting-started +[scb]: https://github.com/spring-cloud/spring-cloud-bindings diff --git a/samples/spring-petclinic/service-binding.yaml b/samples/spring-petclinic/service-binding.yaml new file mode 100644 index 00000000..97f6d8a8 --- /dev/null +++ b/samples/spring-petclinic/service-binding.yaml @@ -0,0 +1,29 @@ +# 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: spring-petclinic-db +spec: + # direct Secret reference is used for compatibility, but not recommended for dynamically provisioned services + service: + apiVersion: v1 + kind: Secret + name: spring-petclinic-db + workload: + apiVersion: apps/v1 + kind: Deployment + name: spring-petclinic diff --git a/samples/spring-petclinic/service.yaml b/samples/spring-petclinic/service.yaml new file mode 100644 index 00000000..d0f6c347 --- /dev/null +++ b/samples/spring-petclinic/service.yaml @@ -0,0 +1,91 @@ +# 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: spring-petclinic-db +type: servicebinding.io/mysql +stringData: + type: mysql + provider: mariadb + host: spring-petclinic-db + port: "3306" + database: default + # demo credentials + username: user + password: pass + +--- +apiVersion: v1 +kind: Service +metadata: + name: spring-petclinic-db +spec: + ports: + - port: 3306 + selector: + app: spring-petclinic-db + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spring-petclinic-db + labels: + app: spring-petclinic-db +spec: + selector: + matchLabels: + app: spring-petclinic-db + template: + metadata: + labels: + app: spring-petclinic-db + spec: + # no persistance configured, the database will be reset when the pod terminates + containers: + - image: mariadb:10.5 + name: mysql + env: + - name: MYSQL_USER + valueFrom: + secretKeyRef: + name: spring-petclinic-db + key: username + - name: MYSQL_PASSWORD + valueFrom: + secretKeyRef: + name: spring-petclinic-db + key: password + - name: MYSQL_DATABASE + valueFrom: + secretKeyRef: + name: spring-petclinic-db + key: database + - name: MYSQL_ROOT_PASSWORD + value: root + ports: + - containerPort: 3306 + name: mysql + livenessProbe: + tcpSocket: + port: mysql + readinessProbe: + tcpSocket: + port: mysql + startupProbe: + tcpSocket: + port: mysql diff --git a/samples/spring-petclinic/workload.yaml b/samples/spring-petclinic/workload.yaml new file mode 100644 index 00000000..75e896c5 --- /dev/null +++ b/samples/spring-petclinic/workload.yaml @@ -0,0 +1,68 @@ +# 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: Service +metadata: + name: spring-petclinic +spec: + ports: + - port: 80 + targetPort: 8080 + selector: + app: spring-petclinic + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spring-petclinic + labels: + app: spring-petclinic +spec: + replicas: 1 + selector: + matchLabels: + app: spring-petclinic + template: + metadata: + labels: + app: spring-petclinic + spec: + containers: + - name: workload + # built with CNB Paketo builder from https://github.com/spring-projects/spring-petclinic + image: ghcr.io/servicebinding/runtime/samples/spring-petclinic@sha256:83ab44832a1db6c03d34e758199b0d9cbf29ce5beeaac4fbf96443a63342b3d4 + env: + # tell the workload to use mysql instead of the default embedded database + - name: SPRING_PROFILES_ACTIVE + value: mysql + ports: + - name: http + containerPort: 8080 + livenessProbe: + httpGet: + path: /actuator/health/liveness + port: http + readinessProbe: + httpGet: + path: /actuator/health/readiness + port: http + startupProbe: + httpGet: + path: /actuator/health/liveness + port: http + failureThreshold: 20 + periodSeconds: 5