This document describes the different deployment modes supported by KAR, including:
The KAR runtime system internally uses Redis as a persistent store and
Kafka as a reliable message transport (Kafka internally uses ZooKeeper
for distributed consensus). The Redis and Kafka instances must be reachable
by every kar
runtime process in order for them to operate correctly and
form the application service mesh.
The Redis and Kafka instances can be provided in multiple ways, each supporting different scenarios:
- They can be run locally as Docker containers, supporting a local clusterless mode which is suitable for development.
- They can be run as internally-accessible services/deployments on a Kubernetes or OpenShift cluster, supporting the deployment of KAR applications within that cluster.
- They can be run as externally-accessible services/deployments on a Kubernetes or OpenShift cluster, supporting the deployment of KAR applications both inside and outside that cluster.
- They can be provided as cloud managed services, supporting the deployment of KAR applications across multiple execution engines including Kubernetes and OpenShift clusters, IBM Code Engine, edge computing devices, and developer laptops. Depending on the scenario, Redis and Kafka may use clustered configurations to support high availability and increased scalability.
When deployed on a Kubernetes of OpenShift cluster, the KAR runtime system also includes a mutating web hook that supports injecting KAR runtime configuration data into Pods that are annotated as containing KAR application components. This significantly simplifies the configuration of these components by automating the injection of the credentials needed to connect to the Redis and Kafka instances being used by KAR.
Throughout this document, we assume that all of the prerequisites outlined in the getting started document have been met. We also assume that if you are deploying to a Kubernetes cluster or using other public cloud managed services in your deployment, that you have the necessary clis and tools already installed and have some familiarity with using them.
The Clusterless deployment mode runs Redis, Kafka, and ZooKeeper as docker containers on your local machine. Your application components and the KAR service mesh all run as local processes on your machine.
Deploy Redis, Kafka, and ZooKeeper using docker compose by running:
./scripts/docker-composer-start.sh
After the script completes, configure your shell environment
to enable kar
to access Redis and Kafka by doing
source ./scripts/kar-env-local.sh
In one window:
source scripts/kar-env-local.sh
cd examples/service-hello-js
npm install --prod
kar run -app hello-js -service greeter node server.js
In a second window:
source scripts/kar-env-local.sh
cd examples/service-hello-js
kar run -app hello-js node client.js
You should see output like shown below in both windows:
2020/04/02 17:41:23 [STDOUT] Hello John Doe!
2020/04/02 17:41:23 [STDOUT] Hello John Doe!
The client process will exit, while the server remains running. You can send another request, or exit the server with a Control-C.
You can also use the kar
cli to invoke the service directly:
kar rest -app hello-js post greeter helloJson '{"name": "Alan Turing"}'
Undeploy the Redis, Kafka, and ZooKeeper containers using docker compose by running:
./scripts/docker-composer-stop.sh
This section covers the base deployment scenario where all the components of the KAR application will be realized as Pods running within a single cluster. In this scenario, Redis, Kafka, and ZooKeeper are also deployed as Pods running within the cluster. For scenarios including multiple clusters and/or applications that are split between a cluster and edge devices (or developer laptops) see Hybrid Cloud below.
This section outlines some general principles that are true of any in-cluster deployment of KAR.
For its in-cluster configurations, the KAR runtime system is deployed
in the kar-system
namespace and includes a mutating webhook whose
job is to inject additional configuration information to enable
application Pods to be joined to the KAR application mesh. Application
Pods that should be mutated are indicated by annotating them with
kar.ibm.com/app
. We support two modes of operation. In the
recommended mode, the application container already contains the kar
executable and the webhook only needs to inject volume mounts and
environment variables to configure it. If the container does not
contain the kar
executable then the webhook can inject and configure
an additional "sidecar" container containing the kar
executable.
This sidecar mode enables unmodified containers to be joined to a KAR
application mesh, but is less resilient to failures due to incomplete
support by Kubernetes for sidecar container lifecycle operations.
The mutating webhook process the following annotations:
- kar.ibm.com/app - sets the
-app
argument ofkar run
- kar.ibm.com/actors: sets the
-actors
argument ofkar run
- kar.ibm.com/service: sets the
-service
argument ofkar run
- kar.ibm.com/verbose: sets the
-verbose
argument ofkar run
- kar.ibm.com/appPort: sets the
-app_port
argument ofkar run
- kar.ibm.com/runtimePort: sets the
-runtime_port
argument ofkar run
- kar.ibm.com/extraArgs: additional command line arguments for
kar run
- kar.ibm.com/sidecarContainer - "true" to enable injection of a sidecar container
If you are using a release version of the kar
cli then, by default,
the matching KAR runtime images will be pulled from our public quay.io
image repository. If you have built your own kar
cli from source then,
by default, the KAR runtime images will be pulled from your local image
repository that is expected to be running at localhost:5000
. It is also
possible to configure KAR to pull its runtime images from a non-local
private registry; this results in an additional kar.ibm.com.image-pull
secret being created.
After the KAR runtime system is successfully deployed to the
kar-system
namespace, you can enable other namespaces
to host KAR applications. This enablement entails labeling the namespace
with kar.ibm.com/enabled=true
and replicating the
kar.ibm.com.runtime-config
secret and, optionally, the kar.ibm.com.image-pull
secret in the namespace. The base installation script
automatically enables the default
namespace for KAR applications.
To enable additional namespaces, you can use the script
kar-k8s-namespace-enable.sh.
Once a namespace is thus enabled, you can deploy KAR application components to the namespace using Helm or kubectl by adding the annotations described above.
NOTE: We strongly recommend against enabling the kar-system
namespace
or any Kubernetes system namespace for KAR applications. Enabling
KAR sidecar injection for these namespaces can cause instability.
You will need a cluster on which you have the cluster-admin role.
Assuming you have set your kubectl context, you can deploy KAR into your IKS cluster in a single command:
./scripts/kar-k8s-deploy.sh
For an OpenShift cluster add -os
to the command:
./scripts/kar-k8s-deploy.sh -os
Note that if you are using a locally built development version of the
kar
cli, the kar-k8s-deploy.sh
script will default to trying to
deploy images from your localhost docker registry. This registry is
not reachable from an IBM Cloud cluster, so you will need to add
-r <some KAR version number>
to pull the needed KAR images from quay.io
.
Run the client and server as shown below:
$ cd examples/service-hello-js
$ kubectl apply -f deploy/server-quay.yaml
pod/hello-server created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-server 2/2 Running 0 3s
$ kubectl apply -f deploy/client-quay.yaml
job.batch/hello-client created
$ kubectl logs jobs/hello-client -c client
Hello John Doe!
Hello John Doe!
$ kubectl logs hello-server -c server
Hello John Doe!
Hello John Doe!
$ kubectl delete -f deploy/client-quay.yaml
job.batch "hello-client" deleted
$ kubectl delete -f deploy/server-quay.yaml
pod "hello-server" deleted
You can disable a specific namespace for KAR applications by running
./scripts/kar-k8s-namespace-disable.sh <namespace>
You can undeploy KAR entirely by running
./scripts/kar-k8s-undeploy.sh
For ease of development, it can be convenient to deploy KAR to a Kubernetes or OpenShift cluster running on your local development machine. Several options exist for creating a local cluster; we describe them next. In all cases, we recommend also running a local docker registry to enable Kubernetes to pull images without requiring you to push your development images to an external docker registry.
If you are using Docker Desktop on MacOS or Windows, you can enable a built-in Kubernetes cluster by checking a box in the UI.
We can use kind to create a virtual Kubernetes cluster using Docker on your development machine.
You will need kind
0.12.0 installed locally.
KAR requires specific configuration of kind
. We have automated
this in a script.
./scripts/kind-start.sh
Similar to Kind, K3D uses Docker to create a local kubernetes cluster. Follow the directions to install K3D and then start a K3D cluster with:
./scripts/k3d-start.sh
The rest of our instructions assume you will run a local docker
registry on localhost:5000
. To ensure one is running, execute
./scripts/start-local-registry.sh
Next, build the necessary docker images and push them to a local registry.
make docker
When you rebuild a KAR docker image and want it to be accessible to
your Kubernetes cluster, you will need to either do make docker
or individually docker push
the image to the localhost:5000 registry.
Next, deploy KAR in dev mode by doing:
./scripts/kar-k8s-deploy.sh
Run the client and server as shown below:
$ cd examples/service-hello-js
$ kubectl apply -f deploy/server.yaml
pod/hello-server created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-server 2/2 Running 0 3s
$ kubectl apply -f deploy/client.yaml
job.batch/hello-client created
$ kubectl logs jobs/hello-client -c client
Hello John Doe!
Hello John Doe!
$ kubectl logs hello-server -c server
Hello John Doe!
Hello John Doe!
$ kubectl delete -f deploy/client.yaml
job.batch "hello-client" deleted
$ kubectl delete -f deploy/server.yaml
pod "hello-server" deleted
You can disable a specific namespace for KAR applications by running
./scripts/kar-k8s-namespace-disable.sh <namespace>
You can undeploy KAR entirely with
./scripts/kar-k8s-undeploy.sh
IBM Code Engine is a multi-tenant Knative service provided by the IBM Public Cloud. We can use IBM Code Engine as the compute engine for KAR applications by deploying components as Code Engine applications (aka Knative services).
We will not deploy Redis and Kafka on Code Engine; instead we will
provision instances of Database for Redis and EventStreams in the same
IBM Public Cloud region as the Code Engine service we are using to run
the application components. We will configure the Code Engine project
to enable the kar
runtime processes to connect to these instances.
To simplify the flow of deploying on Code Engine, KAR application containers
intended for Code Engine deployment need to contain both the
application itself and the kar
cli. We configure these containers to
execute in "sidecar in container" mode. If you are using a container
derived from the KAR Java or JavaScript SDK base images, this can be
done simply by setting the KAR_SIDECAR_IN_CONTAINER
environment
variable.
There is currently no integration between Code Engine's autoscaling capabilities and the Kafka topics that indicate the actual application load. Therefore we currently bypass Code Engine's autoscaler and deploy with a fixed number of containers for each application component.
Use the IBM Cloud Console to create resources. Please consult the documentation for each managed service if you need detailed instructions.
You will need a Standard EventStreams instance. Once it is allocated, create a service credential to access it.
You will need a Database for Redis instance. Once it is allocated, create a service credential to access it, using the same name as you used for the EventStreams service credential.
Create a Code Engine project
ibmcloud ce project create --name kar-project
Then, configure the project for KAR by creating the
kar.ibm.com.runtime-config
secret.
This step is automated by a script that takes the
service credential name and
uses the ibmcloud
cli to extract information and create the secrets.
./scripts/kar-ce-project-enable.sh <service-credential>
Because we are using a Redis and Kafka instance that are accessible
both to containers running in IBM Code Engine and to your laptop, we
have the option of deploying applications with some components running
on the cloud in IBM Code Engine and others running locally. To enable
this option, you need to setup your local environment so that kar
can connect to your public cloud Redis and EventStreams instances.
Do this by running
source scripts/kar-env-ibmcloud.sh <service-credential>
Although deploying a KAR application component to Code Engine can can
be done directly with the ibmcloud ce
cli, it requires a fairly
extensive set of command line arguments. The script kar-ce-run.sh
wraps ibmcloud ce
to simplify the process. It automatically targets
the current Code Engine project (change the targeted project with
ibmcloud ce project target <project-name>
).
./scripts/kar-ce-run.sh -app hello -image quay.io/ibm/kar-examples-js-service-hello -name hello-js-server -service greeter
Once the server component is deployed, you can use the kar
cli to
invoke the service directly:
kar rest -app hello post greeter helloJson '{"name": "Alan Turing"}'
You've just run your first hybrid cloud application that uses KAR to connect components running on your laptop (an "edge device") and the IBM Public Cloud into a unified application mesh!
You can undeploy an application component with
ibmcloud ce application delete --name hello-js-server
You can disable a Code Engine project for KAR applications with
./scripts/kar-ce-project-disable.sh kar-project
or delete it entirely with
ibmcloud ce project delete --name kar-project
The key to a Hybrid Cloud deployment of KAR is to provision a Redis and Kafka instance that are accessible to all of the compute elements you want to utilize. This can include Kubernetes clusters, edge devices, virtual machines, development laptops, and managed compute services such as Code Engine.
In general, you need to first provision the Redis and Kafka instances
and then in each computing environment create the configuration
information that enables kar
to access them. In Kubernetes and
OpenShift clusters and in IBM Code Engine, this means creating the
kar.ibm.com.runtime-config
secret. For local environments or VMs
this means setting a collection of KAFKA_
and REDIS_
environment
variables.
Use the IBM Cloud Console to create resources. Please consult the documentation for each managed service if you need detailed instructions.
You will need a Standard EventStreams instance. Once it is allocated, create a service credential to access it.
You will need a Database for Redis instance. Once it is allocated, create a service credential to access it, using the same name as you used for the EventStreams service credential.
Install the KAR runtime system on your IKS cluster
./scripts/kar-k8s-deploy.sh -m <service-credential>
Enable a project for KAR applications
./scripts/kar-ce-project-enable.sh <service-credential>
Set the necessary KAFKA_
and REDIS_
environment variables with
source scripts/kar-env-ibmcloud.sh <service-credential>
Deploy each application component to the desired compute engine using the scripts/tooling appropriate for that engine as described elsewhere in this document.