Permalink
1714 lines (1488 sloc) 76.3 KB

Getting Started

Spring Cloud Data Flow is a toolkit for building data integration and real-time data-processing pipelines.

Pipelines consist of Spring Boot apps, built with the Spring Cloud Stream or Spring Cloud Task microservice frameworks. This makes Spring Cloud Data Flow suitable for a range of data-processing use cases, from import-export to event-streaming and predictive analytics.

This project provides support for using Spring Cloud Data Flow with Kubernetes as the runtime for these pipelines, with applications packaged as Docker images.

Installation

This section covers how to install the Spring Cloud Data Flow Server on a Kubernetes cluster. Spring Cloud Data Flow depends on a few services and their availability. For example, we need an RDBMS service for the application registry, stream and task repositories, and task management. For streaming pipelines, we also need Skipper server for lifecycle management and a messaging middleware option, such as Apache Kafka or RabbitMQ. In addition, if the analytics features are in use, we need a Redis service.

Important
This guide describes setting up an environment for testing Spring Cloud Data Flow on Google Kubernetes Engine and is not meant to be a definitive guide for setting up a production environment. Feel free to adjust the suggestions to fit your test setup. Remember that a production environment requires much more consideration for persistent storage of message queues, high availability, security, and other concerns.
Note

Currently, only applications registered with a --uri property pointing to a Docker resource are supported by the Data Flow Server for Kubernetes. However, we do support Maven resources for the --metadata-uri property, which is used to list the properties supported by each application. For example, the following application registration is valid:

dataflow:>app register --type source --name time --uri docker://springcloudstream/time-source-rabbit:{docker-time-source-rabbit-version} --metadata-uri maven://org.springframework.cloud.stream.app:time-source-rabbit:jar:metadata:{docker-time-source-rabbit-version}

However, any application registered with a Maven, HTTP, or File resource for the executable jar (by using a --uri property prefixed with maven://, http:// or file://) is not supported.

Kubernetes Compatibility

The Spring Cloud Data Flow implementation for Kubernetes uses the Spring Cloud Deployer Kubernetes library for orchestration. Before you begin setting up a Kubernetes cluster, refer to the compatibility matrix to learn more about deployer and server compatibility against Kubernetes release versions.

The following outlines the compatibility between Spring Cloud Data Flow for Kubernetes Server and Kubernetes versions:

| Versions: SCDF K8S Server - K8S Deployer \ Kubernetes | 1.8.x | 1.9.x | 1.10.x |
|-------------------------------------------------------|-------|-------|--------|
| Server: 1.4.x - Deployer: 1.3.2                       | ✓     | ✓     | ✓     |
| Server: 1.5.x - Deployer: 1.3.6                       | ✓     | ✓     | ✓     |
| Server: 1.6.x - Deployer: 1.3.7                       | ✓     | ✓     | ✓     |
| Server: 1.7.x - Deployer: 1.3.9                       | ✓     | ✓     | ✓     |
|--------------------------------------------------------------------------------|

Create a Kubernetes Cluster

The Kubernetes Picking the Right Solution guide lets you choose among many options, so you can pick the one that you are most comfortable using.

All our testing is done against Google Kubernetes Engine as well as Pivotal Container Service. GKE is used as the target platform for this section. We have also successfully deployed with Minikube. We note where you need to adjust for deploying on Minikube.

Note
When starting Minikube, you should allocate some extra resources, since we deploy several services. We start with minikube start --cpus=4 --memory=4096. Please note that the allocated memory and cpu for the Minikube VM directly gets assigned to the number of applications deployed in a stream/task. The more you add, the more VM resources is required.

The rest of this getting started guide assumes that you have a working Kubernetes cluster and a kubectl command line utility. See the docs for installation instructions: Installing and Setting up kubectl.

Deploying with kubectl

To deploy with kubectl

  1. Get the Kubernetes configuration files.

    You can use the sample deployment and service YAML files in the https://github.com/{github-repo} repository as a starting point. They have the required metadata set for service discovery by the different applications and services deployed. To check out the code, enter the following commands:

    $ git clone https://github.com/{github-repo}
    $ cd spring-cloud-dataflow-server-kubernetes
    $ git checkout {github-tag}

Choosing a Message Broker

For deployed applications to communicate with each other, you need to select a message broker. The sample deployment and service YAML files provide configurations for RabbitMQ and Kafka. You need to configure only one message broker.

  • RabbitMQ

    Run the following command to start the RabbitMQ service:

    $ kubectl create -f src/kubernetes/rabbitmq/

    You can use kubectl get all -l app=rabbitmq to verify that the deployment, pod, and service resources are running. You can use kubectl delete all -l app=rabbitmq to clean up afterwards.

  • Kafka

    Run the following command to start the Kafka service:

    $ kubectl create -f src/kubernetes/kafka/

    You can use kubectl get all -l app=kafka to verify that the deployment, pod, and service resources are running. You can use kubectl delete all -l app=kafka to clean up afterwards.

Deploy Services, Skipper and Data Flow

You must deploy a number of services and the Data Flow server. To do so:

  1. Deploy MySQL.

    We use MySQL for this guide, but you could use a Postgres or H2 database instead. We include JDBC drivers for all three of these databases. To use a database other than MySQL, you must adjust the database URL and driver class name settings.

    Important
    You can modify the password in the src/kubernetes/mysql/mysql-deployment.yaml files if you prefer to be more secure. If you do modify the password, you must also provide it as base64-encoded string in the src/kubernetes/mysql/mysql-secrets.yaml file.

    Run the following command to start the MySQL service:

    kubectl create -f src/kubernetes/mysql/

    You can use kubectl get all -l app=mysql to verify that the deployment, pod, and service resources are running. You can use kubectl delete all,pvc,secrets -l app=mysql to clean up afterwards.

  2. Deploy Redis.

    The Redis service is used for the analytics functionality. Run the following command to start the Redis service:

    kubectl create -f src/kubernetes/redis/
    Note

    If you do not need the analytics functionality, you can turn this feature off by setting SPRING_CLOUD_DATAFLOW_FEATURES_ANALYTICS_ENABLED to false in the src/kubernetes/server/server-deployment.yaml file. If you do not install the Redis service, you should also remove the Redis configuration settings from the following files depending on your message broker:

    • RabbitMQ: src/kubernetes/server/server-config-rabbit.yaml

    • Kafka: src/kubernetes/server/server-config-kafka.yaml

    You can use kubectl get all -l app=redis to verify that the deployment, pod, and service resources are running. You can use kubectl delete all -l app=redis to clean up afterwards.

  3. Deploy the Metrics Collector.

    The Metrics Collector provides message rates for all deployed stream applications. These message rates are visible in the Dashboard UI. Run one of the following commands (depending on your message broker) to start the Metrics Collector:

    • RabbitMQ: kubectl create -f src/kubernetes/metrics/metrics-deployment-rabbit.yaml

    • Kafka: kubectl create -f src/kubernetes/metrics/metrics-deployment-kafka.yaml

      Create the metrics service:

      $ kubectl create -f src/kubernetes/metrics/metrics-svc.yaml

      You can use kubectl get all -l app=metrics to verify that the deployment, pod, and service resources are running. You can use kubectl delete all -l app=metrics to clean up afterwards.

  4. Create Role Bindings and Service account

    Important
    Since version 1.9, the latest releases of Kubernetes have enabled RBAC on the api-server. If your target platform has RBAC enabled, you must ask a cluster-admin to create the roles and role-bindings for you before deploying the Data Flow server. They associate the Data Flow service account with the roles it needs to be run with.

    To create Role Bindings and Service account:

    kubectl create -f src/kubernetes/server/server-roles.yaml
    kubectl create -f src/kubernetes/server/server-rolebinding.yaml
    kubectl create -f src/kubernetes/server/service-account.yaml

    You can use kubectl get roles and kubectl get sa to list the available roles and service accounts.

    To cleanup roles, bindings and the service account, use the following commands:

    $ kubectl delete role scdf-role
    $ kubectl delete rolebinding scdf-rb
    $ kubectl delete serviceaccount scdf-sa
  5. Deploy Skipper

    Data Flow delegates to Skipper the streams lifecycle management. Deploy Skipper to enable the stream management features. For more details, see Spring Cloud Skipper Reference Guide for a complete overview.

    Important
    Specify the version of Skipper that you want to deploy.

    The deployment is defined in the src/kubernetes/skipper/skipper-deployment.yaml file. To control what version of Skipper gets deployed, modify the tag used for the Docker image in the container specification, as the following example shows:

        spec:
          containers:
          - name: skipper
            image: springcloud/spring-cloud-skipper-server:1.2.0.RELEASE   (1)
            imagePullPolicy: Always
    1. You may change the version as you like.

    Note
    Skipper includes the concept of platforms, so it is important to define the “accounts” based on the project preferences. In the preceding YAML file, the accounts map to minikube as the platform. You can modify this, and you can have any number of platform definitions. More details are in the Spring Cloud Skipper Reference Guide.

    If you want to orchestrate stream processing pipelines with Apache Kafka as the messaging middleware by using Skipper, you must change the SPRING_APPLICATION_JSON environment variable value in the src/kubernetes/skipper/skipper-deployment.yaml file as follows:

    "{\"spring.cloud.skipper.server.enableLocalPlatform\" : false, \"spring.cloud.skipper.server.platform.kubernetes.accounts.minikube.environmentVariables\": \"SPRING_CLOUD_STREAM_KAFKA_BINDER_BROKERS=${KAFKA_SERVICE_HOST}:${KAFKA_SERVICE_PORT}, SPRING_CLOUD_STREAM_KAFKA_BINDER_ZK_NODES=${KAFKA_ZK_SERVICE_HOST}:${KAFKA_ZK_SERVICE_PORT}\",\"spring.cloud.skipper.server.platform.kubernetes.accounts.minikube.memory\" : \"1024Mi\"}"

    Additionally, if you want to use the Apache Kafka Streams Binder, configure the SPRING_APPLICATION_JSON environment variable in src/kubernetes/skipper/skipper-deployment.yaml as follows:

    "{\"spring.cloud.skipper.server.enableLocalPlatform\" : false, \"spring.cloud.skipper.server.platform.kubernetes.accounts.minikube.environmentVariables\": \"SPRING_CLOUD_STREAM_KAFKA_BINDER_BROKERS=${KAFKA_SERVICE_HOST}:${KAFKA_SERVICE_PORT}, SPRING_CLOUD_STREAM_KAFKA_BINDER_ZK_NODES=${KAFKA_ZK_SERVICE_HOST}:${KAFKA_ZK_SERVICE_PORT}, SPRING_CLOUD_STREAM_KAFKA_STREAMS_BINDER_BROKERS=${KAFKA_SERVICE_HOST}:${KAFKA_SERVICE_PORT}, SPRING_CLOUD_STREAM_KAFKA_STREAMS_BINDER_ZK_NODES=${KAFKA_ZK_SERVICE_HOST}:${KAFKA_ZK_SERVICE_PORT}\",\"spring.cloud.skipper.server.platform.kubernetes.accounts.minikube.memory\" : \"1024Mi\"}"

    Run the following commands to start Skipper as the companion server for Spring Cloud Data Flow:

    kubectl create -f src/kubernetes/skipper/skipper-deployment.yaml
    kubectl create -f src/kubernetes/skipper/skipper-svc.yaml

    You can use the command kubectl get all -l app=skipper to verify that the deployment, pod, and service resources are running. You can use kubectl delete all -l app=skipper to clean up afterwards.

  6. Deploy the Data Flow Server.

    Important
    Specify the version of Spring Cloud Data Flow server that you want to deploy.

    The deployment is defined in the src/kubernetes/server/server-deployment.yaml file. To control which version of Spring Cloud Data Flow server gets deployed, modify the tag used for the Docker image in the container specification, as follows:

        spec:
          containers:
          - name: scdf-server
            image: springcloud/spring-cloud-dataflow-server-kubernetes:2.0.0.RELEASE   (1)
            imagePullPolicy: Always
    1. Change the version as you like. This document is based on the {project-version} release. The docker tag latest can be used for BUILD-SNAPSHOT releases.

    Important
    The Skipper service should be running and the SPRING_CLOUD_SKIPPER_CLIENT_SERVER_URI property in src/kubernetes/server/server-deployment.yaml should point to it.

    The Data Flow Server uses the Fabric8 Java client library to connect to the Kubernetes cluster. We use environment variables to set the values needed when deploying the Data Flow server to Kubernetes. We also use the Fabric8 Spring Cloud integration with Kubernetes library to access the Kubernetes ConfigMap and Secrets settings. The ConfigMap settings for RabbitMQ are specified in the src/kubernetes/server/server-config-rabbit.yaml file and for Kafka in the src/kubernetes/server/server-config-kafka.yaml file. MySQL secrets are located in the src/kubernetes/mysql/mysql-secrets.yaml file. If you modified the password for MySQL, you should change it in the src/kubernetes/mysql/mysql-secrets.yaml file. Any secrets have to be provided in base64 encoding.

    Note
    We now configure the Data Flow server with file-based security, and the default user is 'user' with a password of 'password'. You should change these values in src/kubernetes/server/server-config-rabbit.yaml for RabbitMQ or src/kubernetes/server/server-config-kafka.yaml for Kafka.
    Note
    The default memory for the pods is 1024Mi. If you expect most of your applications to require more memory, update the value in the src/kubernetes/server/server-deployment.yaml file .
    • RabbitMQ: kubectl create -f src/kubernetes/server/server-config-rabbit.yaml

    • Kafka: kubectl create -f src/kubernetes/server/server-config-kafka.yaml

      To create a server deployment:

      kubectl create -f src/kubernetes/server/server-svc.yaml
      kubectl create -f src/kubernetes/server/server-deployment.yaml

      You can use kubectl get all -l app=scdf-server to verify that the deployment, pod, and service resources are running. You can use kubectl delete all,cm -l app=scdf-server to clean up afterwards.

      You can use the kubectl get svc scdf-server command to locate the EXTERNAL_IP address assigned to scdf-server. We use that later to connect from the shell. The following example (with output) shows how to do so:

      $ kubectl get svc scdf-server
      NAME         CLUSTER-IP       EXTERNAL-IP       PORT(S)    AGE
      scdf-server  10.103.246.82    130.211.203.246   80/TCP     4m

      The URL you need to use is in this case is http://130.211.203.246.

      If you use Minikube, you do not have an external load balancer and the EXTERNAL_IP shows as <pending>. You need to use the NodePort assigned for the scdf-server service. You can use the following command to look up the URL to use:

      $ minikube service --url scdf-server
      http://192.168.99.100:31991

Helm Installation

Spring Cloud Data Flow offers a Helm Chart for deploying the Spring Cloud Data Flow server and its required services to a Kubernetes Cluster.

Note
The Helm chart is available since the 1.2 GA release of Spring Cloud Data Flow for Kubernetes.

The following instructions cover how to initialize Helm and install Spring Cloud Data Flow on a Kubernetes cluster.

  1. Installing Helm

    Helm is comprised of two components: the client (Helm) and the server (Tiller). The Helm client runs on your local machine and can be installed by following the instructions found here. If Tiller has not been installed on your cluster, run the following Helm client command:

    $ helm init
    Note
    To verify that the Tiller pod is running, use the following command: kubectl get pod --namespace kube-system. You should see the Tiller pod running.
  2. Installing the Spring Cloud Data Flow Server and required services.

    Update the Helm repository and install the chart:

    $ helm repo update
    $ helm install --name my-release stable/spring-cloud-data-flow
Note

As of Spring Cloud Data Flow 1.7.0, the Helm chart has been promoted to the Stable repository. If you would like to install a previous version, you need access to the incubator repository. To add this repository to our Helm set and install the chart, run the following commands:

$ helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com
$ helm repo update
$ helm install --name my-release incubator/spring-cloud-data-flow
Note

If you run on a Kubernetes cluster without a load balancer, such as in Minikube, you should override the service type to use NodePort. To do so, add the --set server.service.type=NodePort override, as follows:

helm install --name my-release --set server.service.type=NodePort \
    stable/spring-cloud-data-flow
Note

If you run on a Kubernetes cluster without RBAC, such as in Minikube, you should override rbac.create to false. By default, it is set to true (based on best practices). To do so, add the --set rbac.create=false override, as follows:

helm install --name my-release --set server.service.type=NodePort \
    --set rbac.create=false \
    stable/spring-cloud-data-flow

If you wish to specify a version of Spring Cloud Data Flow other than the current GA release, you can set the server.version, as follows (replacing stable with incubator if needed):

helm install --name my-release stable/spring-cloud-data-flow --set server.version=<version-you-want>
Note
To see all of the settings that can be configured on the Spring Cloud Data Flow chart, view the README.
Note

The following listing shows Spring Cloud Data Flow’s Kubernetes version compatibility with the respective Helm Chart releases:

| SCDF-K8S-Server Version \ Chart Version | 0.1.x | 0.2.x | 1.0.x |
|-----------------------------------------|-------|---------------|
|1.2.x                                    |✓      |✕     |✕      |
|1.3.x                                    |✕      |✓     |✕      |
|1.4.x                                    |✕      |✓     |✕      |
|1.5.x                                    |✕      |✓     |✕      |
|1.6.x                                    |✕      |✓     |✕      |
|1.7.x                                    |✕      |✕     |✓      |
|-----------------------------------------------------------------|

You should see the following output:

NAME:   my-release
LAST DEPLOYED: Sat Mar 10 11:33:29 2018
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Secret
NAME                  TYPE    DATA  AGE
my-release-mysql      Opaque  2     1s
my-release-data-flow  Opaque  2     1s
my-release-redis      Opaque  1     1s
my-release-rabbitmq   Opaque  2     1s

==> v1/ConfigMap
NAME                          DATA  AGE
my-release-data-flow-server   1     1s
my-release-data-flow-skipper  1     1s

==> v1/PersistentVolumeClaim
NAME                 STATUS   VOLUME                                    CAPACITY  ACCESSMODES  STORAGECLASS  AGE
my-release-rabbitmq  Bound    pvc-e9ed7f55-2499-11e8-886f-08002799df04  8Gi       RWO          standard      1s
my-release-mysql     Pending  standard                                  1s
my-release-redis     Pending  standard                                  1s

==> v1/ServiceAccount
NAME                  SECRETS  AGE
my-release-data-flow  1        1s

==> v1/Service
NAME                          CLUSTER-IP      EXTERNAL-IP  PORT(S)                                AGE
my-release-mysql              10.110.98.253   <none>       3306/TCP                               1s
my-release-data-flow-server   10.105.216.155  <pending>    80:32626/TCP                           1s
my-release-redis              10.111.63.33    <none>       6379/TCP                               1s
my-release-data-flow-metrics  10.107.157.1    <none>       80/TCP                                 1s
my-release-rabbitmq           10.106.76.215   <none>       4369/TCP,5672/TCP,25672/TCP,15672/TCP  1s
my-release-data-flow-skipper  10.100.28.64    <none>       80/TCP                                 1s

==> v1beta1/Deployment
NAME                          DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
my-release-mysql              1        1        1           0          1s
my-release-rabbitmq           1        1        1           0          1s
my-release-data-flow-metrics  1        1        1           0          1s
my-release-data-flow-skipper  1        1        1           0          1s
my-release-redis              1        1        1           0          1s
my-release-data-flow-server   1        1        1           0          1s


NOTES:
1. Get the application URL by running these commands:
     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
           You can watch the status of the server by running 'kubectl get svc -w my-release-data-flow-server'
  export SERVICE_IP=$(kubectl get svc --namespace default my-release-data-flow-server -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  echo http://$SERVICE_IP:80

You have just created a new release in the default namespace of your Kubernetes cluster. The NOTES section gives instructions for connecting to the newly installed server. It takes a couple of minutes for the application and its required services to start up. You can check on the status by issuing a kubectl get pod -w command. Wait for the READY column to show 1/1 for all pods. Once that is done, you can connect to the Data Flow server with the external IP listed by the kubectl get svc my-release-data-flow-server command. The default username is user, and its password is password.

Note

If you run on Minikube, you can use the following command to get the URL for the server:

minikube service --url my-release-data-flow-server

To see what Helm releases you have running, you can use the helm list command. When it is time to delete the release, run helm delete my-release. This removes any resources created for the release but keeps release information so that you can rollback any changes by using a helm rollback my-release 1 command. To completely delete the release and purge any release metadata, use helm delete my-release --purge.

Important

There is an issue with generated secrets used for the required services getting rotated on chart upgrades. To avoid this issue, set the password for these services when installing the chart. You can use the following command:

helm install --name my-release \
    --set rabbitmq.rabbitmqPassword=rabbitpwd \
    --set mysql.mysqlRootPassword=mysqlpwd \
    --set redis.redisPassword=redispwd incubator/spring-cloud-data-flow

Deploying Streams

This section covers how to deploy streams with Spring Cloud Data Flow and Skipper. For more about Skipper, see https://cloud.spring.io/spring-cloud-skipper.

We assume that Spring Cloud Data Flow, Spring Cloud Skipper, an RDBMS, and your desired messaging middleware is up and running in minikube. We use RabbitMQ as the messaging middleware.

Before you get started, you can see what applications are running. The following example (with output) shows how to do so:

$ kubectl get all
NAME                              READY     STATUS    RESTARTS   AGE
po/mysql-777890292-z0dsw          1/1       Running   0          38m
po/rabbitmq-317767540-2qzrr       1/1       Running   0          38m
po/redis-4054078334-37m0l         1/1       Running   0          38m
po/scdf-server-2734071167-bjd3g   1/1       Running   0          48s
po/skipper-2408247821-50z31       1/1       Running   0          3m

...
...

Create Streams

This section describes how to create streams (using Skipper). To do so:

  1. Download and run the Spring Cloud Data Flow shell.

    wget http://repo.spring.io/{dataflow-version-type-lowercase}/org/springframework/cloud/spring-cloud-dataflow-shell/{dataflow-project-version}/spring-cloud-dataflow-shell-{dataflow-project-version}.jar
    
    java -jar spring-cloud-dataflow-shell-{dataflow-project-version}.jar

    You should see the following startup message from the shell:

      ____                              ____ _                __
     / ___| _ __  _ __(_)_ __   __ _   / ___| | ___  _   _  __| |
     \___ \| '_ \| '__| | '_ \ / _` | | |   | |/ _ \| | | |/ _` |
      ___) | |_) | |  | | | | | (_| | | |___| | (_) | |_| | (_| |
     |____/| .__/|_|  |_|_| |_|\__, |  \____|_|\___/ \__,_|\__,_|
      ____ |_|    _          __|___/                 __________
     |  _ \  __ _| |_ __ _  |  ___| | _____      __  \ \ \ \ \ \
     | | | |/ _` | __/ _` | | |_  | |/ _ \ \ /\ / /   \ \ \ \ \ \
     | |_| | (_| | || (_| | |  _| | | (_) \ V  V /    / / / / / /
     |____/ \__,_|\__\__,_| |_|   |_|\___/ \_/\_/    /_/_/_/_/_/
    
    {dataflow-project-version}
    
    Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help".
    server-unknown:>

    You can connect the Shell to a Data Flow Server running on different host. Use the kubectl get svc scdf-server command to retrieve the EXTERNAL-IP assigned to scdf-server and use that to connect from the shell. The following example shows how to get the external IP address:

    kubectl get svc scdf-server
    NAME         CLUSTER-IP       EXTERNAL-IP       PORT(S)    AGE
    scdf-server  10.103.246.82    130.211.203.246   80/TCP     4m

    In the preceding example, the URL to use is http://130.211.203.246

    If you use Minikube, you do not have an external load balancer and the EXTERNAL-IP column shows <pending>. You need to use the NodePort assigned for the skipper service. The following example (with output) shows how to look up the URL to use:

    $ minikube service --url scdf-server
    http://192.168.99.100:31991

    The following example (with output) shows how to configure the Data Flow server URI (with the default user and password settings):

    server-unknown:>dataflow config server --username user --password password --uri http://130.211.203.246
    Successfully targeted http://130.211.203.246
    dataflow:>

    Alternatively, you can use the --dataflow.uri command line option. The shell’s --help command line option shows what is available.

  2. Verify the registered platforms in Skipper, as the following example (with output) shows:

    dataflow:>stream platform-list
    ╔════════╤══════════╤════════════════════════════════════════════════════════════════════════════════════════════════╗
    ║  Name  │   Type   │                                      Description                                               ║
    ╠════════╪══════════╪════════════════════════════════════════════════════════════════════════════════════════════════╣
    ║minikube│kubernetes│master url = [https://kubernetes.default.svc/], namespace = [default], api version = [v1]       ║
    ╚════════╧══════════╧════════════════════════════════════════════════════════════════════════════════════════════════╝
  3. Register the Docker images of the Rabbit binder based time and log apps by using the shell.

    We start by deploying a stream with the time-source pointing to the 1.3.0.RELEASE and log-sink pointing to the 1.2.0.RELEASE. The goal is to perform a rolling upgrade of the log-sink application to 1.3.0.RELEASE. The following multi-step example (with output after each command) shows how to do so:

    dataflow:>app register --type source --name time --uri docker://springcloudstream/time-source-rabbit:1.3.0.RELEASE --metadata-uri maven://org.springframework.cloud.stream.app:time-source-rabbit:jar:metadata:1.3.0.RELEASE
    Successfully registered application 'source:time'
    
    dataflow:>app register --type sink --name log --uri docker://springcloudstream/log-sink-rabbit:1.2.0.RELEASE --metadata-uri maven://org.springframework.cloud.stream.app:log-sink-rabbit:jar:metadata:1.2.0.RELEASE
    Successfully registered application 'sink:log'
    
    dataflow:>app info time --type source
    Information about source application 'time':
    Version: '1.3.0.RELEASE':
    Default application version: 'true':
    Resource URI: docker://springcloudstream/time-source-rabbit:1.3.0.RELEASE
    ╔══════════════════════════════╤══════════════════════════════╤══════════════════════════════╤══════════════════════════════╗
    ║         Option Name          │         Description          │           Default            │             Type             ║
    ╠══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╣
    ║trigger.time-unit             │The TimeUnit to apply to delay│<none>                        │java.util.concurrent.TimeUnit ║
    ║                              │values.                       │                              │                              ║
    ║trigger.fixed-delay           │Fixed delay for periodic      │1                             │java.lang.Integer             ║
    ║                              │triggers.                     │                              │                              ║
    ║trigger.cron                  │Cron expression value for the │<none>                        │java.lang.String              ║
    ║                              │Cron Trigger.                 │                              │                              ║
    ║trigger.initial-delay         │Initial delay for periodic    │0                             │java.lang.Integer             ║
    ║                              │triggers.                     │                              │                              ║
    ║trigger.max-messages          │Maximum messages per poll, -1 │1                             │java.lang.Long                ║
    ║                              │means infinity.               │                              │                              ║
    ║trigger.date-format           │Format for the date value.    │<none>                        │java.lang.String              ║
    ╚══════════════════════════════╧══════════════════════════════╧══════════════════════════════╧══════════════════════════════╝
    
    dataflow:>app info log --type sink
    Information about sink application 'log':
    Version: '1.2.0.RELEASE':
    Default application version: 'true':
    Resource URI: docker://springcloudstream/log-sink-rabbit:1.2.0.RELEASE
    ╔══════════════════════════════╤══════════════════════════════╤══════════════════════════════╤══════════════════════════════╗
    ║         Option Name          │         Description          │           Default            │             Type             ║
    ╠══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╣
    ║log.name                      │The name of the logger to use.│<none>                        │java.lang.String              ║
    ║log.level                     │The level at which to log     │<none>                        │org.springframework.integratio║
    ║                              │messages.                     │                              │n.handler.LoggingHandler$Level║
    ║log.expression                │A SpEL expression (against the│payload                       │java.lang.String              ║
    ║                              │incoming message) to evaluate │                              │                              ║
    ║                              │as the logged message.        │                              │                              ║
    ╚══════════════════════════════╧══════════════════════════════╧══════════════════════════════╧══════════════════════════════╝
    Note

    For Kafka binder application registration may look like this:

    dataflow:>app register --type source --name time --uri docker://springcloudstream/time-source-kafka-10:{docker-time-source-kafka-version} --metadata-uri maven://org.springframework.cloud.stream.app:time-source-kafka-10:jar:metadata:{docker-time-source-kafka-version}
    dataflow:>app register --type sink --name log --uri docker://springcloudstream/log-sink-kafka-10:{docker-log-sink-kafka-version} --metadata-uri maven://org.springframework.cloud.stream.app:log-sink-kafka-10:jar:metadata:{docker-log-sink-kafka-version}

    Alternatively, if you want register all out-of-the-box stream applications for a particular binder in bulk, you can use one of the following commands:

    For more details, review how to register applications.

  4. Create a simple stream in the shell, by running the following command:

    The following example shows how to create a stream:

    dataflow:>stream create mystream --definition "time | log"
    Created new stream 'mystream'
  5. Deploy the stream.

    The following example shows how to deploy the stream:

    dataflow:>stream deploy mystream --platformName minikube
    Deployment request has been sent for stream 'mystream'
    Note
    While deploying the stream, we supply --platformName, which indicates the platform repository (in this case, minikube) to use when deploying the stream applications with Skipper.
  6. List the pods.

    The following command (with output) shows how to list the pods. You can run this from the shell by by adding a "!" before the command (which makes a command run as an OS command):

    $ kubectl get pods
    NAME                              READY     STATUS    RESTARTS   AGE
    mystream-log-v1-0-2k4r8             1/1       Running   0          2m
    mystream-time-v1-qhdqq              1/1       Running   0          2m
    mysql-777890292-z0dsw          1/1       Running   0          49m
    rabbitmq-317767540-2qzrr       1/1       Running   0          49m
    redis-4054078334-37m0l         1/1       Running   0          49m
    scdf-server-2734071167-bjd3g   1/1       Running   0          12m
    skipper-2408247821-50z31       1/1       Running   0          15m
    
    ...
    ...
  7. Verify the logs.

    The followig example shows how to make sure that the values you expect appear in the logs:

    $ kubectl logs -f mystream-log-v1-0-2k4r8
    ...
    ...
    2017-10-30 22:59:04.966  INFO 1 --- [ mystream.time.mystream-1] log-sink                                 : 10/30/17 22:59:04
    2017-10-30 22:59:05.968  INFO 1 --- [ mystream.time.mystream-1] log-sink                                 : 10/30/17 22:59:05
    2017-10-30 22:59:07.000  INFO 1 --- [ mystream.time.mystream-1] log-sink                                 : 10/30/17 22:59:06
  8. Verify the stream history.

    The following example (with output) shows how to display the stream history, so that you can verify its content:

    dataflow:>stream history --name mystream
    ╔═══════╤════════════════════════════╤════════╤════════════╤═══════════════╤════════════════╗
    ║Version│        Last updated        │ Status │Package Name│Package Version│  Description   ║
    ╠═══════╪════════════════════════════╪════════╪════════════╪═══════════════╪════════════════╣
    ║1      │Mon Oct 30 16:18:28 PDT 2017│DEPLOYED│mystream    │1.0.0          │Install complete║
    ╚═══════╧════════════════════════════╧════════╧════════════╧═══════════════╧════════════════╝
  9. Verify the package manifest.

    The log-sink should be at 1.2.0.RELEASE. The following example (with output) shows how to display the package manifest so that you can ensure the version of the log-sink application:

    dataflow:>stream manifest --name mystream
    
    ---
    # Source: log.yml
    apiVersion: skipper.spring.io/v1
    kind: SpringCloudDeployerApplication
    metadata:
      "name": "log"
    spec:
      resource: "docker:springcloudstream/log-sink-rabbit"
      resourceMetadata: "docker:springcloudstream/log-sink-rabbit:jar:metadata:1.2.0.RELEASE"
      version: "1.2.0.RELEASE"
      applicationProperties:
        "spring.metrics.export.triggers.application.includes": "integration**"
        "spring.cloud.dataflow.stream.app.label": "log"
        "spring.cloud.stream.metrics.key": "mystream.log.${spring.cloud.application.guid}"
        "spring.cloud.stream.bindings.input.group": "mystream"
        "spring.cloud.stream.metrics.properties": "spring.application.name,spring.application.index,spring.cloud.application.*,spring.cloud.dataflow.*"
        "spring.cloud.stream.bindings.applicationMetrics.destination": "metrics"
        "spring.cloud.dataflow.stream.name": "mystream"
        "spring.cloud.dataflow.stream.app.type": "sink"
        "spring.cloud.stream.bindings.input.destination": "mystream.time"
      deploymentProperties:
        "spring.cloud.deployer.group": "mystream"
    
    ---
    # Source: time.yml
    apiVersion: skipper.spring.io/v1
    kind: SpringCloudDeployerApplication
    metadata:
      "name": "time"
    spec:
      resource: "docker:springcloudstream/time-source-rabbit"
      resourceMetadata: "docker:springcloudstream/time-source-rabbit:jar:metadata:1.3.0.RELEASE"
      version: "1.3.0.RELEASE"
      applicationProperties:
        "spring.metrics.export.triggers.application.includes": "integration**"
        "spring.cloud.dataflow.stream.app.label": "time"
        "spring.cloud.stream.metrics.key": "mystream.time.${spring.cloud.application.guid}"
        "spring.cloud.stream.bindings.output.producer.requiredGroups": "mystream"
        "spring.cloud.stream.metrics.properties": "spring.application.name,spring.application.index,spring.cloud.application.*,spring.cloud.dataflow.*"
        "spring.cloud.stream.bindings.applicationMetrics.destination": "metrics"
        "spring.cloud.stream.bindings.output.destination": "mystream.time"
        "spring.cloud.dataflow.stream.name": "mystream"
        "spring.cloud.dataflow.stream.app.type": "source"
      deploymentProperties:
        "spring.cloud.deployer.group": "mystream"
  10. Register the log-sink application version 1.3.0.RELEASE and update your stream to use it

    The following example (with output after each command) shows how to register the log-sink application and update its version:

    dataflow:>app register --name log --type sink --uri docker:springcloudstream/log-sink-rabbit:1.3.0.RELEASE --force
    Successfully registered application 'sink:log'
    
    dataflow:>stream update --name mystream --properties version.log=1.3.0.RELEASE
    Update request has been sent for stream 'mystream'
  11. List the pods again.

    The following example (with output) shows how to list the pods, so that you can see your application in the list:

    $ kubectl get pods
    NAME                              READY     STATUS        RESTARTS   AGE
    mystream-log-v1-0-2k4r8        1/1       Terminating   0          3m
    mystream-log-v2-0-fjnlt        0/1       Running       0          9s
    mystream-time-v1-qhdqq         1/1       Running       0          3m
    mysql-777890292-z0dsw          1/1       Running       0          51m
    rabbitmq-317767540-2qzrr       1/1       Running       0          51m
    redis-4054078334-37m0l         1/1       Running       0          51m
    scdf-server-2734071167-bjd3g   1/1       Running       0          14m
    skipper-2408247821-50z31       1/1       Running       0          16m
    
    ...
    ...
    Note
    The list shows two versions of the log-sink applications. The mystream-log-v1-0-2k4r8 pod is going down and the newly spawned mystream-log-v2-0-fjnlt pod is bootstrapping. The version number is incremented and the version-number (v2) is included in the new application name.
  12. Once the new pod is up and running, you can verify the logs.

    The following example shows how to display the logs so that you can verify their content:

    $ kubectl logs -f mystream-log-v2-0-fjnlt
    ...
    ...
    2017-10-30 23:24:30.016  INFO 1 --- [ mystream.time.mystream-1] log-sink                                 : 10/30/17 23:24:30
    2017-10-30 23:24:31.017  INFO 1 --- [ mystream.time.mystream-1] log-sink                                 : 10/30/17 23:24:31
    2017-10-30 23:24:32.018  INFO 1 --- [ mystream.time.mystream-1] log-sink                                 : 10/30/17 23:24:32
  13. View the updated package manifest persisted in Skipper. You should now see log-sink at 1.3.0.RELEASE.

    The following example (with output) shows how to view the updated package manifest:

    dataflow:>stream manifest --name mystream
    
    ---
    # Source: log.yml
    apiVersion: skipper.spring.io/v1
    kind: SpringCloudDeployerApplication
    metadata:
      "name": "log"
    spec:
      resource: "docker:springcloudstream/log-sink-rabbit"
      resourceMetadata: "docker:springcloudstream/log-sink-rabbit:jar:metadata:1.3.0.RELEASE"
      version: "1.3.0.RELEASE"
      applicationProperties:
        "spring.metrics.export.triggers.application.includes": "integration**"
        "spring.cloud.dataflow.stream.app.label": "log"
        "spring.cloud.stream.metrics.key": "mystream.log.${spring.cloud.application.guid}"
        "spring.cloud.stream.bindings.input.group": "mystream"
        "spring.cloud.stream.metrics.properties": "spring.application.name,spring.application.index,spring.cloud.application.*,spring.cloud.dataflow.*"
        "spring.cloud.stream.bindings.applicationMetrics.destination": "metrics"
        "spring.cloud.dataflow.stream.name": "mystream"
        "spring.cloud.dataflow.stream.app.type": "sink"
        "spring.cloud.stream.bindings.input.destination": "mystream.time"
      deploymentProperties:
        "spring.cloud.deployer.group": "mystream"
        "spring.cloud.deployer.count": "1"
    
    ---
    # Source: time.yml
    apiVersion: skipper.spring.io/v1
    kind: SpringCloudDeployerApplication
    metadata:
      "name": "time"
    spec:
      resource: "docker:springcloudstream/time-source-rabbit"
      resourceMetadata: "docker:springcloudstream/time-source-rabbit:jar:metadata:1.3.0.RELEASE"
      version: "1.3.0.RELEASE"
      applicationProperties:
        "spring.metrics.export.triggers.application.includes": "integration**"
        "spring.cloud.dataflow.stream.app.label": "time"
        "spring.cloud.stream.metrics.key": "mystream.time.${spring.cloud.application.guid}"
        "spring.cloud.stream.bindings.output.producer.requiredGroups": "mystream"
        "spring.cloud.stream.metrics.properties": "spring.application.name,spring.application.index,spring.cloud.application.*,spring.cloud.dataflow.*"
        "spring.cloud.stream.bindings.applicationMetrics.destination": "metrics"
        "spring.cloud.stream.bindings.output.destination": "mystream.time"
        "spring.cloud.dataflow.stream.name": "mystream"
        "spring.cloud.dataflow.stream.app.type": "source"
      deploymentProperties:
        "spring.cloud.deployer.group": "mystream"
  14. Verify stream history for the latest updates.

    The following example (with output) shows how to display the version history of your stream so that you can verify the version:

    dataflow:>stream history --name mystream
    ╔═══════╤════════════════════════════╤════════╤════════════╤═══════════════╤════════════════╗
    ║Version│        Last updated        │ Status │Package Name│Package Version│  Description   ║
    ╠═══════╪════════════════════════════╪════════╪════════════╪═══════════════╪════════════════╣
    ║2      │Mon Oct 30 16:21:55 PDT 2017│DEPLOYED│mystream    │1.0.0          │Upgrade complete║
    ║1      │Mon Oct 30 16:18:28 PDT 2017│DELETED │mystream    │1.0.0          │Delete complete ║
    ╚═══════╧════════════════════════════╧════════╧════════════╧═══════════════╧════════════════╝

Rolling back to a Previous Version

Skipper includes a rollback command so that you can roll back to a previous version. The following example (with output) shows how to use it:

dataflow:>stream rollback --name mystream
Rollback request has been sent for the stream 'mystream'

...
...

dataflow:>stream history --name mystream
╔═══════╤════════════════════════════╤════════╤════════════╤═══════════════╤════════════════╗
║Version│        Last updated        │ Status │Package Name│Package Version│  Description   ║
╠═══════╪════════════════════════════╪════════╪════════════╪═══════════════╪════════════════╣
║3      │Mon Oct 30 16:22:51 PDT 2017│DEPLOYED│mystream    │1.0.0          │Upgrade complete║
║2      │Mon Oct 30 16:21:55 PDT 2017│DELETED │mystream    │1.0.0          │Delete complete ║
║1      │Mon Oct 30 16:18:28 PDT 2017│DELETED │mystream    │1.0.0          │Delete complete ║
╚═══════╧════════════════════════════╧════════╧════════════╧═══════════════╧════════════════╝

Destroy a Stream

Destroy the stream, by using the following command:

dataflow:>stream destroy --name mystream

Troubleshoot Stream Deployment

To troubleshoot issues such as a container that has a fatal error starting up, add the --previous option to view the last terminated container log. You can also get more detailed information about the pods by using the kubctl describe, as the following example shows:

kubectl describe pods/mystream-log-qnk72
Note
If you need to specify any of the application-specific configuration properties, you might use the “long form” of them by including the application-specific prefix (for example, --jdbc.tableName=TEST_DATA). If you did not register the --metadata-uri for the Docker based starter applications, this form is required. In this case, you also do not see the configuration properties listed when using the app info command or in the Dashboard GUI.

Accessing an Application from outside the Cluster

If you need to be able to connect from outside of the Kubernetes cluster to an application that you deploy (such as the http-source), you need to use either an external load balancer for the incoming connections or you need to use a NodePort configuration that exposes a proxy port on each Kubetnetes node. If your cluster does not support external load balancers (such as Minikube), you must use the NodePort approach. You can use deployment properties to configure the access. To specify that you want to have a load balancer with an external IP address created for your application’s service, use deployer.http.kubernetes.createLoadBalancer=true for the application. For the NodePort configuration, use deployer.http.kubernetes.createNodePort=<port>, where <port> is a number between 30000 and 32767.

  1. Register the http-source by using one of the following commands:

    RabbitMQ:

    dataflow:>app register --type source --name http --uri docker//springcloudstream/http-source-rabbit:{docker-http-source-rabbit-version} --metadata-uri maven://org.springframework.cloud.stream.app:http-source-rabbit:jar:metadata:{docker-http-source-rabbit-version}

    Kafka:

    dataflow:>app register --type source --name http --uri docker//springcloudstream/http-source-kafka:{docker-http-source-kafka-version} --metadata-uri maven://org.springframework.cloud.stream.app:http-source-kafka:jar:metadata:{docker-http-source-kafka-version}
  2. Create the http | log stream without deploying it by using the following command:

    dataflow:>stream create --name test --definition "http | log"

    If your cluster supports an External LoadBalancer for the http-source, you can use the following command to deploy the stream:

    dataflow:>stream deploy test --properties "deployer.http.kubernetes.createLoadBalancer=true"
  3. Check whether the pods have started by using the following command:

    dataflow:>! kubectl get pods -l role=spring-app
    command is:kubectl get pods -l role=spring-app
    NAME               READY     STATUS    RESTARTS   AGE
    test-http-2bqx7    1/1       Running   0          3m
    test-log-0-tg1m4   1/1       Running   0          3m

    Pods that are ready show 1/1 in the READY column. Now you can look up the external IP address for the http application (it can sometimes take a minute or two for the external IP to get assigned) by using the following command:

    dataflow:>! kubectl get service test-http
    command is:kubectl get service test-http
    NAME         CLUSTER-IP       EXTERNAL-IP      PORT(S)    AGE
    test-http    10.103.251.157   130.211.200.96   8080/TCP   58s

    If you use Minikube or any cluster that does not support an external load balancer, you should deploy the stream with a NodePort in the range of 30000-32767. You can use the following command to deploy it:

    dataflow:>stream deploy test --properties "deployer.http.kubernetes.createNodePort=32123"
  4. Check whether the pods have started by using the following command:

    dataflow:>! kubectl get pods -l role=spring-app
    command is:kubectl get pods -l role=spring-app
    NAME               READY     STATUS    RESTARTS   AGE
    test-http-9obkq    1/1       Running   0          3m
    test-log-0-ysiz3   1/1       Running   0          3m

    Pods that are ready show 1/1 in the READY column. Now you can look up the URL to use with the following command:

    dataflow:>! minikube service --url test-http
    command is:minikube service --url test-http
    http://192.168.99.100:32123
  5. Post some data to the test-http application either by using the EXTERNAL_IP address (mentioned earlier) with port 8080 or by using the URL provided by the following Minikube command:

    dataflow:>http post --target http://130.211.200.96:8080 --data "Hello"
  6. View the logs for the test-log pod, by using the following command:

    dataflow:>! kubectl get pods-l role=spring-app
    command is:kubectl get pods-l role=spring-app
    NAME              READY     STATUS             RESTARTS   AGE
    test-http-9obkq   1/1       Running            0          2m
    test-log-0-ysiz3  1/1       Running            0          2m
    dataflow:>! kubectl logs test-log-0-ysiz3
    command is:kubectl logs test-log-0-ysiz3
    ...
    2016-04-27 16:54:29.789  INFO 1 --- [           main] o.s.c.s.b.k.KafkaMessageChannelBinder$3  : started inbound.test.http.test
    2016-04-27 16:54:29.799  INFO 1 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 0
    2016-04-27 16:54:29.799  INFO 1 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147482647
    2016-04-27 16:54:29.895  INFO 1 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
    2016-04-27 16:54:29.896  INFO 1 --- [  kafka-binder-] log.sink                                 : Hello
  7. Destroy the stream

    dataflow:>stream destroy --name test

Deploying Tasks

This section covers how to deploy tasks. To do so:

  1. Create a task and launch it. To do so, register the timestamp task app and create a simple task definition and launch it, as follows:

    dataflow:>app register --type task --name timestamp --uri docker:springcloudtask/timestamp-task:{docker-timestamp-task-version} --metadata-uri maven://org.springframework.cloud.task.app:timestamp-task:jar:metadata:{docker-timestamp-task-version}
    dataflow:>task create task1 --definition "timestamp"
    dataflow:>task launch task1

    You can now list the tasks and executions byusing the following commands:

    dataflow:>task list
    ╔═════════╤═══════════════╤═══════════╗
    ║Task Name│Task Definition│Task Status║
    ╠═════════╪═══════════════╪═══════════╣
    ║task1    │timestamp      │running    ║
    ╚═════════╧═══════════════╧═══════════╝
    
    dataflow:>task execution list
    ╔═════════╤══╤════════════════════════════╤════════════════════════════╤═════════╗
    ║Task Name│ID│         Start Time         │          End Time          │Exit Code║
    ╠═════════╪══╪════════════════════════════╪════════════════════════════╪═════════╣
    ║task1    │1 │Fri May 05 18:12:05 EDT 2017│Fri May 05 18:12:05 EDT 2017│0        ║
    ╚═════════╧══╧════════════════════════════╧════════════════════════════╧═════════╝
  2. Destroy the task, by using the following command:

    dataflow:>task destroy --name task1

Application and Server Properties

This section covers how you can customize the deployment of your applications. You can use a number of properties to influence settings for the applications that are deployed. Properties can be applied on a per-application basis or in the server configuration for all deployed applications.

Note
Properties set on a per-application basis always take precedence over properties set as the server configuration. This arrangement allows for the ability to override global server level properties on a per-application basis.

See KubernetesDeployerProperties for more on the supported options.

Using Deployments

The deployer uses ReplicationController by default. To use deployments instead, you can set the following option as part of the container env section in a deployment YAML file:

env:
- name: SPRING_CLOUD_DEPLOYER_KUBERNETES_CREATE_DEPLOYMENT
  value: 'true'

This is now the preferred setting and will be the default in future releases of the deployer.

Memory and CPU Settings

The apps are deployed by default with the following Limits and Requests settings:

Limits:
  cpu:	500m
  memory:	512Mi
Requests:
  cpu:	500m
  memory:	512Mi

You might find that the 512Mi memory limit is too low. To increase it, you can provide a common spring.cloud.deployer.memory deployer property, as the following example shows (replace <app> with the name of the app for which you want to set the memory):

deployer.<app>.memory=640m

This property affects both the Requests and Limits memory value set for the container.

If you want to set the Requests and Limits values separately, you can use the deployer properties that are specific to the Kubernetes deployer. The following example shows how to set Limits to 1000m for CPU and 1024Mi for memory and Requests to 800m for CPU and 640Mi for memory:

deployer.<app>.kubernetes.limits.cpu=1000m
deployer.<app>.kubernetes.limits.memory=1024Mi
deployer.<app>.kubernetes.requests.cpu=800m
deployer.<app>.kubernetes.requests.memory=640Mi

Those values results in the following container settings being used:

Limits:
  cpu:	1
  memory:	1Gi
Requests:
  cpu:	800m
  memory:	640Mi
Note
When using the common memory property, you should use an m suffix for the value. When using the Kubernetes-specific properties, you should use the Kubernetes Mi style suffix.

You can also control the default values to which to set the cpu and memory requirements for the pods that are created as part of application deployments. You can declare the following as part of the container env section in a deployment YAML file:

env:
- name: SPRING_CLOUD_DEPLOYER_KUBERNETES_CPU
  value: 500m
- name: SPRING_CLOUD_DEPLOYER_KUBERNETES_MEMORY
  value: 640Mi

The settings we have used so far only affect the settings for the container. They do not affect the memory setting for the JVM process in the container. If you would like to set JVM memory settings, you can provide an environment variable to do so. See the next section for details.

Environment Variables

To influence the environment settings for a given application, you can take advantage of the spring.cloud.deployer.kubernetes.environmentVariables deployer property. For example, a common requirement in production settings is to influence the JVM memory arguments. You can achieve this by using the JAVA_TOOL_OPTIONS environment variable, as the following example shows:

deployer.<app>.kubernetes.environmentVariables=JAVA_TOOL_OPTIONS=-Xmx1024m
Note
The environmentVariables property accepts a comma-delimited string. If an environment variable contains a value which is also a comma-delimited string, it must be enclosed in single quotation marks — for example, spring.cloud.deployer.kubernetes.environmentVariables=spring.cloud.stream.kafka.binder.brokers='somehost:9092, anotherhost:9093'

This overrides the JVM memory setting for the desired <app> (replace <app> with the name of your application).

Liveness and Readiness Probes

The liveness and readiness probes use paths called /health and /info respectively. They use a delay of 10 for both and a period of 60 and 10 respectively. You can change these defaults when you deploy the stream by using deployer properties.

The following example changes the liveness probe (replace <app> with the name of your application) by setting deployer properties:

deployer.<app>.kubernetes.livenessProbePath=/health
deployer.<app>.kubernetes.livenessProbeDelay=120
deployer.<app>.kubernetes.livenessProbePeriod=20

The same can be declared as part of the container env section in a deployment YAML file:

env:
- name: SPRING_CLOUD_DEPLOYER_KUBERNETES_LIVENESS_PROBE_PATH
  value: '/health'
- name: SPRING_CLOUD_DEPLOYER_KUBERNETES_LIVENESS_PROBE_DELAY
  value: '120'
- name: SPRING_CLOUD_DEPLOYER_KUBERNETES_LIVENESS_PROBE_PERIOD
  value: '20'

Similarly, you can swap liveness for readiness to override the default readiness settings.

By default, port 8080 is used as the probe port. You can change the defaults for both liveness and readiness probe ports by using deployer properties, as the following example shows:

deployer.<app>.kubernetes.readinessProbePort=7000
deployer.<app>.kubernetes.livenessProbePort=7000

You can also set the port values in the container env section of a deployment YAML file:

env:
- name: SPRING_CLOUD_DEPLOYER_KUBERNETES_READINESS_PROBE_PORT
  value: '7000'
- name: SPRING_CLOUD_DEPLOYER_KUBERNETES_LIVENESS_PROBE_PORT
  value: '7000'
Note

If you intend to use Spring Boot 2.x+, all Actuator endpoints in Spring Boot 2.x have been moved under /actuator by default. You must adjust the liveness and readiness probe paths to the new defaults. The following example configures Spring Boot 2.x+ liveness and readiness endpoint paths (replace <app> with the name of your application):

deployer.<app>.kubernetes.livenessProbePath=/actuator/health
deployer.<app>.kubernetes.readinessProbePath=/actuator/info

To automatically set both liveness and readiness endpoints on a per-application basis to the default Spring Boot 2.x paths, you can set the following property:

deployer.<app>.kubernetes.bootMajorVersion=2

See the Spring Boot 2.0 Migration Guide for more information and how to restore the Spring Boot 1.x base path behavior.

You can access secured probe endpoints by using credentials stored in a Kubernetes secret. You can use an existing secret, provided the credentials are contained under the credentials key name of the secret’s data block. You can configure probe authentication on a per-application basis. When enabled, it is applied to both the liveness and readiness probe endpoints by using the same credentials and authentication type. Currently, only Basic authentication is supported.

To create a new secret:

  1. First generate the base64 string with the credentials used to access the secured probe endpoints.

    Basic authentication encodes a username and password as a base64 string in the format of username:password.

    The following example (which includes output and in which you should replace user and pass with your values) shows how to generate a base64 string:

    $ echo -n "user:pass" | base64
    dXNlcjpwYXNz
    $
  2. With the encoded credentials, create a file (for example, myprobesecret.yml) with the following contents:

    apiVersion: v1
    kind: Secret
    metadata:
      name: myprobesecret
    type: Opaque
    data:
      credentials: GENERATED_BASE64_STRING
  3. Replace GENERATED_BASE64_STRING with the base64-encoded value generated earlier.

  4. Create the secret by using kubectl, as the following example shows:

    $ kubectl create -f ./myprobesecret.yml
    secret "myprobesecret" created
    $
  5. Set the following deployer properties to use authentication when accessing probe endpoints, as the following example shows:

    deployer.<app>.kubernetes.probeCredentialsSecret=myprobesecret

    Replace <app> with the name of the application to which to apply authentication.

Using SPRING_APPLICATION_JSON

You can use a SPRING_APPLICATION_JSON environment variable to set Data Flow server properties (including the configuration of maven repository settings) that are common across all of the Data Flow server implementations. These settings go at the server level in the container env section of a deployment YAML. The following example shows how to do so:

env:
- name: SPRING_APPLICATION_JSON
  value: "{ \"maven\": { \"local-repository\": null, \"remote-repositories\": { \"repo1\": { \"url\": \"https://repo.spring.io/libs-snapshot\"} } } }"

Private Docker Registry

You can pull Docker images from a private registry on a per-application basis. First, you must create a secret in the cluster. Follow the Pull an Image from a Private Registry guide to create the secret.

Once you have created the secret, use the imagePullSecret property to set the secret to use, as the following example shows:

deployer.<app>.kubernetes.imagePullSecret=mysecret

Replace <app> with the name of your application and mysecret with the name of the secret you created earlier.

You can also configure the image pull secret at the server level in the container env section of a deployment YAML, as the following example shows:

env:
- name: SPRING_CLOUD_DEPLOYER_KUBERNETES_IMAGE_PULL_SECRET
  value: mysecret

Replace mysecret with the name of the secret you created earlier.

Annotations

You can add annotations to Kubernetes objects on a per-application basis. The supported object types are pod Deployment, Service and Job. Annotations are defined in a key:value format allowing for multiple annotations separated by a comma. For more information and use cases on annotations see Annotations.

The following example shows how you can configure applications to use annotations:

deployer.<app>.kubernetes.podAnnotations=annotationName:annotationValue
deployer.<app>.kubernetes.serviceAnnotations=annotationName:annotationValue,annotationName2:annotationValue2
deployer.<app>.kubernetes.jobAnnotations=annotationName:annotationValue

Replace <app> with the name of your application and the value of your annotations.

Entry Point Style

An Entry Point Style affects how application properties are passed to the container to be deployed. Currently, three styles are supported:

  • exec: (default) Passes all application properties and command line arguments in the deployment request as container args. Application properties are transformed into the format of --key=value.

  • shell: Passes all application properties as environment variables. Command line arguments from the deployment request are not converted into environment variables nor set on the container. Application properties are transformed into an uppercase string and . characters are replaced with _.

  • boot: Creates an environment variable called SPRING_APPLICATION_JSON that contains a JSON representation of all application properties. Command line arguments from the deployment request are set as container args.

Note
In all cases, environment variables defined at the server level configuration and on a per-application basis are set onto the container as-is.

You can configure applications as follows:

deployer.<app>.kubernetes.entryPointStyle=<Entry Point Style>

Replace <app> with the name of your application and <Entry Point Style> with your desired Entry Point Style.

You can also configure the Entry Point Style at the server level in the container env section of a deployment YAML, as the following example shows:

env:
- name: SPRING_CLOUD_DEPLOYER_KUBERNETES_ENTRY_POINT_STYLE
  value: entryPointStyle

Replace entryPointStye with the desired Entry Point Style.

You should choose an Entry Point Style of either exec or shell, to correspond to how the ENTRYPOINT syntax is defined in the container’s Dockerfile. For more information and uses cases on exec vs shell, see the ENTRYPOINT section of the Docker documentation.

Using the boot Entry Point Style corresponds to using the exec style ENTRYPOINT. Command line arguments from the deployment request are passed to the container, with the addition of application properties mapped into the SPRING_APPLICATION_JSON environment variable rather than command line arguments.

Note
When you use the boot Entry Point Style, the deployer.<app>.kubernetes.environmentVariables property must not contain SPRING_APPLICATION_JSON.

Deployment Service Account

You can configure a custom service account for application deployments through properties. You can use an existing service account or create a new one. One way to create a service account is by using kubectl, as the following example shows:

$ kubectl create serviceaccount myserviceaccountname
serviceaccount "myserviceaccountname" created

Then you can configure individual applications as follows:

deployer.<app>.kubernetes.deploymentServiceAccountName=myserviceaccountname

Replace <app> with the name of your application and myserviceaccountname with your service account name.

You can also configure the service account name at the server level in the container env section of a deployment YAML, as the following example shows:

env:
- name: SPRING_CLOUD_DEPLOYER_KUBERNETES_DEPLOYMENT_SERVICE_ACCOUNT_NAME
  value: myserviceaccountname

Replace myserviceaccountname with the service account name to be applied to all deployments.

Image Pull Policy

An image pull policy defines when a Docker image should be pulled to the local registry. Currently, three policies are supported:

  • IfNotPresent: (default) Do not pull an image if it already exists.

  • Always: Always pull the image regardless of whether it already exists.

  • Never: Never pull an image. Use only an image that already exists.

The following example shows how you can individually configure applications:

deployer.<app>.kubernetes.imagePullPolicy=Always

Replace <app> with the name of your application and Always with your desired image pull policy.

You can configure an image pull policy at the server level in the container env section of a deployment YAML, as the following example shows:

        env:
        - name: SPRING_CLOUD_DEPLOYER_KUBERNETES_IMAGE_PULL_POLICY
          value: Always

Replace Always with your desired image pull policy.

Deployment Labels

Custom labels can be set on Deployment related objects. See Labels for more information on labels. Labels are specified in key:value format.

The following example shows how you can individually configure applications:

deployer.<app>.kubernetes.deploymentLabels=myLabelName:myLabelValue

Replace <app> with the name of your application, myLabelName with your label name and myLabelValue with the value of your label.

Additionally, multiple labels can be applied, for example:

deployer.<app>.kubernetes.deploymentLabels=myLabelName:myLabelValue,myLabelName2:myLabelValue2