Skip to content

Commit d878896

Browse files
committed
post: draft post on quarkus and service binding
1 parent 43b3edc commit d878896

File tree

1 file changed

+275
-0
lines changed
  • using-quarkus-with-the-service-binding-operator

1 file changed

+275
-0
lines changed
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
#+BLOG: iocanel.com
2+
#+ORG2BLOG:
3+
#+OPTIONS: toc:nil num:nil todo:nil pri:nil tags:nil ^:nil
4+
#+TITLE: Using Quarkus with the Service Binding Operator
5+
#+DESCRIPTION: A quick walkthrough on how to use Quarkus with the Service Binding Operator
6+
#+CATEGORY: Hints, Cloud, Development
7+
#+TAGS: Java, Quarkus, Kubernetes
8+
9+
* Introduction
10+
11+
[[https://kubernetes.io][Kubernetes]] is around for almost 7 years now and ever since the beggining there have been efforts to make consuming / binding to services simpler.
12+
And while discovering the actual service is not so much of an issue (if you employ a set of conventions), getting the credentials etc is slightly trickier.
13+
14+
The [[https://svc-cat.io][Service Catalog]] has been an effort that promised to simplify provisioning and binding to services, but it seems that it has lost its momentum. The lack
15+
of uniformity between providers, the differences in how each service communicated the binding information and the fact that people tend to favor operators for provisioning services made it pretty hard to use in practice.
16+
17+
The [[https://github.com/redhat-developer/service-binding-operator][Service Binding Operator]] is a more recent and modern initiative. It stays out of the way of service provisioning (leaving that to operators) and focuses on how to best communicate the binding information to the application.
18+
An interesting part of the specification is the [[https://github.com/servicebinding/spec#workload-projection][workload projection]], which defines a directory structure that will be mounted to the application container when the binding happens in order to pass all the required binding information:
19+
20+
- type
21+
- uri
22+
- credentials
23+
24+
Other parts of the specification are related to the `ServiceBinding` resource (which controls what services are bound to which application and how).
25+
26+
[[https://quarkus.io/][Quarkus]] already supports the [[https://github.com/servicebinding/spec#workload-projection][workload projection]] part of the spec and recently received enhancments on the binding part, which is going to be the focus of this post.
27+
In particular this post is going to discuss how the `ServiceBinding` can be automatically genenerated for the user and will walk you through the whole process from installing the needed operators to configuring and deploying the application.
28+
29+
For the shake of this post I am going to use [[https://kind.sigs.k8s.io/][kind]] where I am going to install the [[https://github.com/redhat-developer/service-binding-operator][Service Binding Operator]] and the [[https://github.com/CrunchyData/postgres-operator][Crunchy data operator for Postgres]].
30+
Then, I am going to create a postgres cluster and finally I am going to use one of the [[https://quarkus.io/][Quarkus]] quickstarts to bind to the provisioned postgres.
31+
32+
** Start a new kind cluster
33+
34+
If you've already created one, or don't use [[https://kind.sigs.k8s.io/][kind]] at all, feel free to skip.
35+
36+
#+begin_src sh
37+
kind create cluster
38+
#+end_src
39+
40+
** Install the OLM
41+
42+
Both operators that will be installed in this post, will be installed through the [[https://operatorhub.io][Operatorhub]].
43+
So, the first step is to install the [[https://olm.operatorframework.io/][Operator Lifecycle Manager]].
44+
45+
#+begin_src sh
46+
curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.19.1/install.sh | bash -s v0.19.1
47+
#+end_src
48+
49+
** Install the Service Binding Operator
50+
51+
#+begin_src sh
52+
kubectl create -f https://operatorhub.io/install/service-binding-operator.yaml
53+
#+end_src
54+
55+
To verify the installation execute the following command.
56+
57+
#+begin_src sh
58+
kubectl get csv -n operators
59+
#+end_src
60+
61+
When the `phase` of the [[https://github.com/redhat-developer/service-binding-operator][Service Binding Operator]] is `Succeeded` you may proceed to the next step.
62+
63+
** Install the Postgres Crunchy Operator
64+
65+
#+begin_src sh
66+
kubectl create -f https://operatorhub.io/install/postgresql.yaml
67+
#+end_src
68+
69+
As above to verify the installation execute:
70+
71+
#+begin_src sh
72+
kubectl get csv -n operators
73+
#+end_src
74+
75+
When the `phase` of the operator is `Succeeded` you may proceed to the next step.
76+
77+
78+
** Create a Postgres cluster
79+
80+
We shall create a new namespace, where we will install our cluster and application
81+
82+
#+begin_src sh
83+
kubectl create ns demo
84+
kubectl config set-context --current --namespace=demo
85+
#+end_src
86+
87+
88+
To create the cluster we need to apply the following custom resource:
89+
90+
#+begin_src yaml :tangle ~/pg-cluster.yml
91+
apiVersion: postgres-operator.crunchydata.com/v1beta1
92+
kind: PostgresCluster
93+
metadata:
94+
name: pg-cluster
95+
namespace: demo
96+
spec:
97+
image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-ha:centos8-13.4-0
98+
postgresVersion: 13
99+
instances:
100+
- name: instance1
101+
dataVolumeClaimSpec:
102+
accessModes:
103+
- "ReadWriteOnce"
104+
resources:
105+
requests:
106+
storage: 1Gi
107+
backups:
108+
pgbackrest:
109+
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.33-2
110+
repos:
111+
- name: repo1
112+
volume:
113+
volumeClaimSpec:
114+
accessModes:
115+
- "ReadWriteOnce"
116+
resources:
117+
requests:
118+
storage: 1Gi
119+
- name: repo2
120+
volume:
121+
volumeClaimSpec:
122+
accessModes:
123+
- "ReadWriteOnce"
124+
resources:
125+
requests:
126+
storage: 1Gi
127+
proxy:
128+
pgBouncer:
129+
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbouncer:centos8-1.15-2
130+
#+end_src
131+
132+
This resource has been borrowed from [[https://redhat-developer.github.io/service-binding-operator/userguide/getting-started/quick-start.html][Service Binding Operator Quickstart]], which is definitely something worth looking into (if you haven't already).
133+
134+
Let's save that file under `pg-cluster.yml` and apply it using `kubectl`
135+
136+
#+begin_src sh
137+
kubectl apply -f ~/pg-cluster.yml
138+
#+end_src
139+
140+
Let's check the pods to verify the installation:
141+
142+
#+begin_src sh
143+
kubectl get pods -n demo
144+
#+end_src
145+
146+
** Create a Quarkus application that will bind to Postgres
147+
148+
Instead of creating an application from scratch, I am going to use one of the [[https://github.com/quarkusio/quarkus-quickstarts.git][Quarkus Quickstarts]].
149+
150+
*** Grab a quickstart that uses postgres
151+
152+
The quickstart repository is quite large, So if you don't want to [[clone the repo]] you can just perform a [[sparse checkout]].
153+
Both ways are demonstrated below and in both cases the quickstart from `2.3.1.Final` tag should be available under `~/quickstarts/hibernate-orm-panache-quickstart`.
154+
155+
**** clone the repo
156+
157+
#+begin_src sh
158+
git clone --depth 1 --branch 2.3.1.Final [email protected]:quarkusio/quarkus-quickstarts.git ~/quickstarts
159+
cd ~/quickstarts/hibernate-orm-panache-quickstart
160+
#+end_src
161+
162+
**** sparse checkout
163+
164+
#+begin_src sh
165+
mkdir ~/quickstarts
166+
cd ~/quickstarts
167+
git init
168+
git config core.sparseCheckout true
169+
git remote add origin [email protected]:quarkusio/quarkus-quickstarts.git
170+
echo "hibernate-orm-panache-quickstart/" > .git/info/sparse-checkout
171+
git pull origin 2.3.1.Final
172+
cd hibernate-orm-panache-quickstart
173+
#+end_src
174+
175+
176+
*** Add the Kubernetes and Service Binding extensions
177+
178+
#+begin_src sh :dir ~/quickstarts/hibernate-orm-panache-quickstart/
179+
quarkus ext add -B kubernetes
180+
quarkus ext add -B kubernetes-service-binding
181+
quarkus ext add -B container-image-docker
182+
#+end_src
183+
184+
*** Bind to the target Postgres cluster
185+
186+
In order to bind the postgres service to our application we need to either provide a `ServiceBidning` resource or have it generated.
187+
To have the binding generated for us we need to provide the service coordinates:
188+
189+
- apiVersion: `postgres-operator.crunchydata.com/v1beta1`
190+
- kind: `PostgresCluster`
191+
- name: `pg-cluster`
192+
193+
prefixed with `quarkus.kubernetes-service-binding.services.<id>.` as shown below:
194+
195+
#+begin_src sh
196+
echo "quarkus.kubernetes-service-binding.services.my-db.api-version=postgres-operator.crunchydata.com/v1beta1
197+
quarkus.kubernetes-service-binding.services.my-db.kind=PostgresCluster
198+
quarkus.kubernetes-service-binding.services.my-db.name=pg-cluster" >> ~/quickstarts/hibernate-orm-panache-quickstart/src/main/resources/application.properties
199+
#+end_src
200+
201+
*Note*: The <id> can be anything at this point. It's only used for correlating the service coordinates.
202+
203+
*** Switch the latest Quarkus version
204+
205+
Generation of the Service Binding resource is not available in `2.3.1.Final` so we are going to switch to a snapshot version.
206+
This means that you need to checkout and build quarkus from latest `main`.
207+
This post assumes you have already done so and skips directly to the next step, which is switching to the snapshot version:
208+
209+
#+begin_src sh :dir ~/quickstarts/hibernate-orm-panache-quickstart
210+
sed -i "s|2.3.1.Final|999-SNAPSHOT|g" pom.xml
211+
#+end_src
212+
213+
*** Prepare for deployment
214+
215+
To deploy, we need to perform a container image build, load the image to our cluster (remember we are using [[https://kind.sigs.k8s.io/][kind]]), generate the resource and perform the deployment.
216+
217+
**** Build the container image
218+
219+
To build the container image, you can use:
220+
221+
#+begin_src sh :dir ~/quickstarts/hibernate-orm-panache-quickstart
222+
mvn clean install -Dquarkus.container-image.build=true -DskipTests
223+
#+end_src
224+
225+
This assumes that you have docker up and running.
226+
227+
**** Load the docker image to the cluster
228+
229+
#+begin_src sh
230+
kind load docker-image iocanel/hibernate-orm-panache-quickstart:1.0.0-SNAPSHOT
231+
#+end_src
232+
233+
***** Loading the image on minikube
234+
235+
If you are using [[https://minikube.sigs.k8s.io/docs/start/][minikube]] instead, then execute:
236+
#+begin_src sh
237+
eval $(minikube docker-env)
238+
#+end_src
239+
240+
and re-build the image.
241+
242+
When using tools like [[https://kind.sigs.k8s.io/][kind]] or [[https://minikube.sigs.k8s.io/docs/start/][minikube]], it is generally a good idea to change the image pull policy to `IfNotPresent` to avoid uneeded pulls, since most of the time the image will be loaded from the local docker daemon, as shown above.
243+
To set the image pull policy:
244+
245+
#+begin_src sh
246+
echo "quarkus.kubernetes.image-pull-policy=IfNotPresent" >> ~/quickstarts/hibernate-orm-panache-quickstart/src/main/resources/application.properties
247+
#+end_src
248+
249+
**** Deploy the application
250+
251+
The next step will generate the deployment manifest, including the `ServiceBinding` and will apply them on kubernetes.
252+
253+
#+begin_src sh :dir ~/quickstarts/hibernate-orm-panache-quickstart
254+
mvn clean install -Dquarkus.kubernetes.deploy=true -DskipTests
255+
#+end_src
256+
257+
258+
**** Verify the installation
259+
260+
#+begin_src sh
261+
kubectl port-forward service/hibernate-orm-panache-quickstart 8080:80
262+
#+end_src
263+
264+
Open your browser on [[http://localhost:8080]] and enjoy!
265+
266+
* Thoughs and future steps
267+
268+
I am really excited with the progress on the Service binding front. Thinks are looking great and can look even better.
269+
Some potential improvements I can see coming in the near future, is reducing the amount of needed configuration, with the use of smart conventions (e.g. assuming that custom resource name is the same as the database name unless explicitly specified) and a reasonable set of defaults (e.g. assuming that for postgres the default operator is [[https://github.com/CrunchyData/postgres-operator][CrunchyData operator]]).
270+
This could even allow us to bind to services with zero config, without really sacrificing in flexibility and customizability!
271+
272+
I hope I could get you even half as excited as I am!
273+
274+
275+

0 commit comments

Comments
 (0)