This demo will provide a local demo instance of the "Application Catalog" concept of VSHN.
The demo environment runs three Kubernetes clusters to demonstrate the separation of concerns:
- Service Consumer
appc-consumer1
-
This is where the end-user deploys the applications and consumes services from the application catalog. It runs the Kubernetes Service Catalog operator which integrates with the Crossplane Service Broker.
- Control Plane
appc-control
-
Crossplane and the Crossplane Service Broker is running on this cluster. It orchestrates the service provisioning on the service clusters.
- Service Cluster
appc-service1
-
The actual service instances are provisioned on this cluster via Helm. This is taken care of by the Crossplane Helm Provider. No other service is provisioned on this cluster. There can be many service clusters, not just one like in this example.
For a detailed write-up, have a look at Crossplane Service Broker.
-
Create three local Kubernetes clusters:
# linux export DOCKER_NETWORK_GATEWAY=$(docker network inspect bridge | jq -r '.[0].IPAM.Config[0].Gateway') # macos with docker for desktop # interface has to be adjusted export DOCKER_NETWORK_GATEWAY=$(ipconfig getifaddr en6) k3d cluster create appc-control -p "30000-30002:30000-30002@server:0" k3d cluster create appc-service1 --api-port 0.0.0.0:42042 -p "30003-30010:30003-30010@server:0" --k3s-arg "--tls-san=${DOCKER_NETWORK_GATEWAY}@server:0" k3d cluster create appc-consumer1
-
Install Crossplane and Secrets Generator on
appc-control
:kubectl config use-context k3d-appc-control helm repo add crossplane https://charts.crossplane.io/stable helm repo add secret-generator https://helm.mittwald.de helm install crossplane --create-namespace --namespace crossplane-system crossplane/crossplane --set "args[0]='--debug'" helm install secret-generator --create-namespace --namespace secret-generator secret-generator/kubernetes-secret-generator
Tip
|
For OpenShift you can use the provided crossplane-openshift-values.yaml Helm values file for Crossplane to be compatible with the permissions.
|
-
Create kubeconfig secret to access
appc-service1
fromappc-control
kubectl -n crossplane-system create secret generic appc-service1-kubeconfig --from-literal=kubeconfig="$(k3d kubeconfig get appc-service1 | sed -e 's|server:\s*.*$|server: https://'${DOCKER_NETWORK_GATEWAY}':42042|g')"
-
Install and configure providers (Helm and SQL) and Secrets Generator Operator:
kubectl apply -f 01-base/provider.yaml while ! $(kubectl get ProviderConfig >/dev/null 2>&1); do echo "provider not ready yet - waiting"; sleep 1; done kubectl apply -f 01-base/providerconfig.yaml
-
Install Compositions (aka Plans)
kubectl apply -f 02-app-catalog/app-catalog.yaml kubectl apply -f 02-app-catalog/redis.yaml # TODO kubectl apply -f 02-app-catalog/mariadb.yaml
-
Instantiate your first service:
kubectl apply -f 03-instances/redis1.yaml # TODO kubectl apply -f 03-instances/mariadb1.yaml
-
And now see what happens:
kubectl get release # wait until READY = true kubectl get redisinstances.syn.tools -w kubectl config use-context k3d-appc-service1 kubectl -n redis1 get pods
-
Cleanup:
kubectl config use-context k3d-appc-control kubectl delete -f 03-instances/redis1.yaml
We’ll install and configure the Crossplane Service Provider PoC:
kubectl config use-context k3d-appc-control
kubectl apply -f 04-service-broker/deployment.yaml
We’ll use the Open Service Broker API via curl
to not rely on any external utility.
With these few steps a new instance is provisioned, a binding made and finally the instance deprovisioned again.
-
Prepare environment
export SB_BROKER_USERNAME=osbuser export SB_BROKER_PASSWORD=Passw0rd export SB_BROKER_URL=http://localhost:30001 export SB_INSTANCE_NAME=mysvcinstance1
-
Provision a service instance
curl -i -s -X PUT -H "X-Broker-API-Version: 2.16" -H "Content-Type: application/json" --user "$SB_BROKER_USERNAME:$SB_BROKER_PASSWORD" "${SB_BROKER_URL}/v2/service_instances/${SB_INSTANCE_NAME}?accepts_incomplete=true" -d '{"service_id": "redis-k8s", "plan_id": "redis-small"}'
-
Wait some time, then create a binding. If the instance is still provisioning the answer is
instance is being updated and cannot be retrieved
.curl -i -s -X PUT -H "X-Broker-API-Version: 2.16" -H "Content-Type: application/json" --user "$SB_BROKER_USERNAME:$SB_BROKER_PASSWORD" "${SB_BROKER_URL}/v2/service_instances/${SB_INSTANCE_NAME}/service_bindings/binding1" --data '{"service_id": "redis-k8s", "plan_id": "redis-small"}'
-
Cleanup by deprovisioning the instance again
curl -i -s -X DELETE -H "X-Broker-API-Version: 2.16" -H "Content-Type: application/json" --user "$SB_BROKER_USERNAME:$SB_BROKER_PASSWORD" "${SB_BROKER_URL}/v2/service_instances/${SB_INSTANCE_NAME}?accepts_incomplete=true&service_id=redis-k8s&plan_id=redis-small"
-
Install the Kubernetes Service Catalog:
kubectl config use-context k3d-appc-consumer1 helm repo add service-catalog https://kubernetes-sigs.github.io/service-catalog helm install catalog --create-namespace --namespace catalog service-catalog/catalog
-
Get the latest svcat binary.
-
Register the Crossplane Service Broker
kubectl create secret generic broker-creds --from-literal=username=osbuser --from-literal=password=Passw0rd svcat register redisbroker --url http://172.17.0.1:30001 --basic-secret broker-creds svcat marketplace
-
Provision an instance
svcat provision myredis --plan small --class redis-k8s
-
Check the state of the provisioning and wait until state is ready
svcat get instances
-
Create a service binding
svcat bind myredis
-
Check the state of the binding and wait until state is ready
svcat get bindings
-
A new secret is available containing the connection details for Redis
kubectl describe secret myredis
-
Cleanup by unbinding and deprovisioning (deprovisioning is blocked until unbinding is done)
svcat unbind myredis svcat deprovision myredis