Modern runtime applications designed to be Cloud Native
must also been able to connect to backend
systems (SQL, NoSQL, Broker, etc) as this is the case for applications
running on physical or virtual machines.
To access a system, it is needed to configure different resources (e.g. Datasource) and to declare different parameters (e.g jdbc url, username, password, database name) using
by example for Spring Boot or Quarkus runtimes such a configuration config file: application.properties
able to configure the connection with a SQL database.
To avoid to hard code such parameters, we use mostly a kubernetes secret and pass the needed information as a list of key/value pairs.
type: postgresql
provider: bitnami
database: fruits_database
uri: postgresql:5432
username: healthy
password: healthy
This approach is subject to different problems as:
error prone
,application.properties
Primaza name comes from the Greek word πρυμάτσα, which represent a stern line
used to tie boats to the dock.
Primaza aims to support the discoverability, life cycle management & connection of services running in Kubernetes (or outside) with a runtime applications.
Primaza introduces new concepts supporting such a vision:
To bind a service to a runtime, it is needed to create a Claim CR. This claim contains the name of the service, its version and optional some additional parameters like: role, target environment.
When the controller detects such a new Claim CR, then it will populate a request and will call the Primaza Claim REST endpoint.
According to the information received, Primaza will check if a match exists between a claim
and a service
registered and will discover it on the target cluster (dev test, etc).
To determine if a kubernetes service is available, Primaza will use the service endpoint definition and more specifically the protocol:port
of the service to be watched.
Next, the credential associated with the service will be retrieved locally or using a secret store and a secret will be created containing as information:
type // Service Type: postgresql, mysql
provider // Service provider: bitnami, etc
uri // kubernetes DNS name and port
username // user to be used to access the service
password // Password to be used to access the service
database // (optional): Database name to connect to a SQL database
The secret is created under the namespace of the application and a volume is created, part of the application to mount the secret using the workload projection convention.
To use primaza
, it is needed to perform a couple of things like:
http://localhost:8080/clusters/new
http://localhost:8080/services/new
to let Primaza to discover ithttp://localhost:8080/credentials/new
http://localhost:8080/claims/new
You can run the quarkus primaza application in dev mode using the command:
cd app
./mvnw compile quarkus:dev
The command will launch the runtime at the following address: http://localhost:8080
but will also run different containers: database (h2) & vault secret engine if your docker or podman daemon is running locally !
You can discover the quarkus dev services and injected config by pressing on the key c
within your terminal.
Next follow then the instructions of the Demo time section :-)
In order to use Primaza on kubernetes, it is needed first to setup a cluster (kind, minikube, etc) and to install an ingress controller. You can use the following script able to install using kind a kubernetes cluster locally:
curl -s -L "https://raw.githubusercontent.com/snowdrop/k8s-infra/main/kind/kind.sh" | bash -s install
Remark: To see all the options proposed by the script, use the command
curl -s -L "https://raw.githubusercontent.com/snowdrop/k8s-infra/main/kind/kind.sh" | bash -s -h
If the cluster is up and running, install vault using the following script ./scripts/vault.sh
. We recommend to use this script as it is needed to perform different steps
post vault installation such as:
.vault/cluster-keys.json
, bob
and passwordsinclair
Note: If creation of the vault's pod is taking more than 60s as the container image must be downloaded, then the process will stop. In this case, remove the helm chart
./scripts/vault.sh remove
and repeat the operation.Tip: Notice the messages displayed within the terminal as they told you how to get the root token and where they are stored, where to access the keys, etc !
We can now install Crossplane and its Helm provider
./scripts/crossplane.sh
Tip: Script usage is available using the
-h
parameter
Create the primaza namespace
kubectl create namespace primaza
Set the VAULT_URL
variable to let primaza to access storage engine using the Kubernetes DNS service name:
export VAULT_URL=http://vault-internal.vault:8200
Next, deploy Primaza and its Postgresql DB using the following helm chart
helm install \
--devel \
--repo https://halkyonio.github.io/helm-charts \
primaza-app \
primaza-app \
-n primaza \
--set app.image=<CONTAINER_REGISTRY>/<ORG>/primaza-app:latest \
--set app.host=primaza.${VM_IP}.nip.io \
--set app.envs.vault.url=${VAULT_URL}
Tip: When the pod is started, you can access Primaza using its ingress host url:
http://primaza.<VM_IP>.nip.io
If you prefer to install everything all-in-one, use our bash scripts on a kind
k8s cluster:
VM_IP=<VM_IP>
export VAULT_URL=http://vault-internal.vault:8200
export PRIMAZA_IMAGE_NAME=kind-registry:5000/local/primaza-app
$(pwd)/scripts/vault.sh
$(pwd)/scripts/crossplane.sh
$(pwd)/scripts/primaza.sh build
$(pwd)/scripts/primaza.sh localdeploy
Note: If you prefer to use the helm chart pushed on Halkyon repository, don't use the parameters
build
andlocaldeploy
And now, you can demo it ;-)
To play with Primaza, you can use the following scenario:
primaza
locally and open your browser at the address http://localhost:8080
cluster
and service
recordsdiscover
. It should be empty as no backend service currently runsdiscover
. It should be thereregistered service
its credential
fruits
databaseclaim
to tell to Primaza that the Atomic fruits app would like to access a Posgresql DBQuarkus Fruits application
from the screen applications
and click on the button claim
bound
and the ingress URL should be displayedEverything is in place to claim a Service using the following commands:
Deploy the Quarkus Fruits application within the namespace app
helm install fruits-app halkyonio/fruits-app \
-n app --create-namespace \
--set app.image=quay.io/halkyonio/atomic-fruits:latest \
--set app.host=atomic-fruits.<VM_IP>.nip.io \
--set app.serviceBinding.enabled=false \
--set db.enabled=false
Create an entry within the secret store engine at the path primaza/fruits
. This path will be used to configure the credentials to access the fruits_database
.
// When vault runs on kubernetes
export VAULT_ADDR=http://vault.<VM_IP>.nip.io
vault login -method=userpass username=bob password=sinclair
// When using mvn quarkus:dev
export VAULT_TOKEN=root
export VAULT_ADDR=http://localhost:<VAULT_PORT>
// Next create the key that we need to access the Postgresql fruits db
vault kv put -mount=secret primaza/fruits username=healthy password=healthy database=fruits_database
vault kv get -mount=secret primaza/fruits
Create now different records to let Primaza to access the local cluster, discover the services, claim a service using the credentials stored under vault
// When deployed on kubernetes
export PRIMAZA_URL=primaza.<VM_IP>.nip.io
// When using quarkus:dev
export PRIMAZA_URL=localhost:8080
// To be executed when steps are done manually or when using quarkus:dev
export KIND_URL=$(kubectl config view -o json | jq -r --arg ctx kind-kind '.clusters[] | select(.name == $ctx) | .cluster.server')
$(pwd)/scripts/data/cluster.sh
// Common steps
$(pwd)/scripts/data/services.sh
$(pwd)/scripts/data/credentials.sh
$(pwd)/scripts/data/claims.sh
Open the browser ate the address: http://localhost:8080
Click on the different UI screens to verify if the cluster has been well registered and if its status is OK
, that the application atomic fruits
, if primaza has discovered the postgresql db
Select the Atomic Fruits application
from the screen applications
and click on the button claim
Select the claim fruits-claim
to bind from the list and click on the button bind
Wait 1-2 seconds and refresh the screen
If the binding succeeded, then the status should be bound
and the ingress URL should be displayed
Click on the URL to access the application's screen
Alternatively curl
or httpie
the URL (http http://atomic-fruits.127.0.0.1.nip.io/fruits
)
Enjoy :-)
This section describes different use cases that you can play manually top of a k8s cluster where:
vault kv put -mount=secret primaza/fruits username=healthy password=healthy database=fruits_database
VM_IP=127.0.0.1
helm uninstall fruits-app -n app
helm install fruits-app halkyonio/fruits-app \
-n app --create-namespace \
--set app.image=quay.io/halkyonio/atomic-fruits:latest \
--set app.host=atomic-fruits.$VM_IP.nip.io \
--set app.serviceBinding.enabled=false \
--set db.enabled=false
DB_PASSWORD=healthy
DB_DATABASE=fruits_database
RELEASE_NAME=postgresql
VERSION=11.9.13
helm uninstall postgresql -n db kubectl delete pvc -lapp.kubernetes.io/name=$RELEASE_NAME -n db
helm install $RELEASE_NAME bitnami/postgresql \ --version $VERSION \ --set auth.username=$DB_USERNAME \ --set auth.password=$DB_PASSWORD \ --set auth.database=$DB_DATABASE \ --create-namespace \ -n db
- Open the primaza `applications` screen and next to the line of the `fruits` application, click on the claim button
- Create a new claim
- Wait a few moments till the status is `bound` and open the ingress URL
### Service deployed using Crossplane
- Open the primaza `services catalog` screen and click on the `installable` checkbox of the service `postgresql`
- If not yet done, specify the Helm repo `https://charts.bitnami.com/bitnami`, chart name `postgresql` and version `11.9.13` to be deployed
- Next, open the primaza `applications` screen and next to the line of the `fruits` application, click on the claim button
- Create a new claim
- Wait a few moments till the status is `bound` and open the ingress URL