You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@openwhisk.apache.org by GitBox <gi...@apache.org> on 2018/04/17 15:44:44 UTC

[GitHub] dgrove-oss closed pull request #182: Use helm to deploy openwhisk on top of kuberentes.

dgrove-oss closed pull request #182: Use helm to deploy openwhisk on top of kuberentes.
URL: https://github.com/apache/incubator-openwhisk-deploy-kube/pull/182
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/helm/Chart.yaml b/helm/Chart.yaml
new file mode 100644
index 0000000..c6d25f3
--- /dev/null
+++ b/helm/Chart.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+description: A Helm chart to deploy Apache OpenWhisk for Kubernetes
+name: openwhisk
+version: 0.1.0
+keywords:
+  - Apache OpenWhisk
+maintainers:
+  - name: Tom Xing
+    email: xingzhou@cn.ibm.com
diff --git a/helm/README.md b/helm/README.md
new file mode 100644
index 0000000..3624054
--- /dev/null
+++ b/helm/README.md
@@ -0,0 +1,137 @@
+## Overview
+
+[Apache OpenWhisk](http://www.openwhisk.org) is a popular container-native serverless platform. 
+This chart targets to deploy an OpenWhisk cluster over Kubernetes cluster.
+
+This chart is designed to deploy the following 6 kinds of containers on a running Kubernetes cluster:
+
+- `zookeeper`: deployed in Kubernetes as a `Service`(backended by a `Deployment`). Provides `zookeeper` service for `kafka` node.
+- `kafka`: deployed in Kubernetes as a `StatefulSet`. Depends on `zookeeper` service and provides message service for `controller` node and `invoker` node.
+- `couchdb`: deployed in Kubernetes as a `Service`(backended by a `Deployment`). Provides database service for `controller` node and `invoker` node.
+- `controller`: OpenWhisk controller component, deployed as a `StatefulSet`.
+- `invoker`: OpenWhisk invoker component, deployed as a `StatefulSet`.
+- `nginx`: deployed in Kubernetes as a combination of a `Service`(of type `NodePort`, backended by a `Deployment`), a `ConfigMap` and a `Secret`. Provides public access endpoint for end user to visit OpenWhisk.
+
+By default, deploying this chart will result in deploying 6 containers in a Kubernetes cluster, which forms a minimum deployment of a workable OpenWhisk environment. Please modify `values.yaml` and corresponding template files to deploy a bigger customized OpenWhisk cluster.
+
+## Deployment Steps
+
+Please follow the following steps in this section to use [Helm](https://github.com/kubernetes/helm) to deploy this chart.
+
+### Step 1. Prepare Docker Images
+
+The first step is to prepare docker images used by this chart on your Kubernetes node. Here is a summary of the images needed:
+
+- `zookeeper`: uses `zookeeper:3.4` at present.
+- `kafka`: uses `wurstmeister/kafka:0.11.0.1`.
+- `couchdb`: uses `openwhisk/kube-couchdb`, this is a pre-built docker image made from official `openwhisk-on-kubernetes`. For more information, please check the [docker file](https://github.com/apache/incubator-openwhisk-deploy-kube/blob/master/docker/couchdb/Dockerfile) for this image.
+- `controller`: uses OpenWhisk official `openwhisk/controller` image.
+- `invoker`: uses OpenWhisk official `openwhisk/invoker` image.
+- `nginx`: uses `nginx:1.11`.
+
+This chart provides default images for all of the above containers, so you can try deploy without building any images in advance.
+
+This chart will also automatically pull the following action images for `invoker` once deployment is finished:
+
+- openwhisk/nodejsactionbase 
+- openwhisk/nodejs6action
+- openwhisk/dockerskeleton
+- openwhisk/python2action
+- openwhisk/python3action
+- openwhisk/action-swift-v3.1.1
+- openwhisk/swift3action
+- openwhisk/java8action
+
+### Step 2. Prepare Kubernetes and Helm
+
+Make sure that you have a running Kubernetes cluster and a `kubectl` client connected to this cluster.
+
+Then please install [Helm](https://github.com/kubernetes/helm) and run the following command to init `Helm Tiller`:
+```shell
+helm init
+
+```
+
+Please check with the following command to make sure `Helm` is up and running:
+```shell
+kubectl get pods -n kube-system
+
+```
+
+Then grant corresponding cluster role to `Helm` user:
+```shell
+kubectl create clusterrolebinding tiller-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default
+```
+
+Finally, create a new namespace named `openwhisk`:
+```shell
+kubectl create namespace openwhisk
+```
+
+Now, you should have an available environment to deploy OpenWhisk!
+
+### Deploy Charts
+
+Deployment can be done by using the following single command:
+```shell
+helm install . --namespace=openwhisk --name=your_release_name
+```
+
+After a while, if you can see all the pods listed by the following command are in `Running` state, congratulations, you have finished OpenWhisk deployment:
+```shell
+kubectl get pods -n openwhisk
+```
+
+### Test Deployment
+
+Install an [OpenWhisk client](https://github.com/apache/incubator-openwhisk/tree/master/docs) to test the deployed OpenWhisk environment.
+
+For now, we are using nginx to provide web access for OpenWhisk client. By default, the nginx service is configured to run at port 30000 for HTTP connection and 30001 for HTTPS connection.
+
+As a result, please run the following command to config your OpenWhisk client:
+```shell
+wsk property set --apihost http://<nginx_node_IP>:30000
+wsk property set --auth 23bc46b1-71f6-4ed5-8c54-816aa4f8c502:123zO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP
+```
+
+Prepare a small js function like the following and save it to `greeting.js`:
+```js
+/**
+ * Return a simple greeting message for someone.
+ *
+ * @param name A person's name.
+ * @param place Where the person is from.
+ */
+function main(params) {
+    var name = params.name || params.payload || 'stranger';
+    var place = params.place || 'somewhere';
+    return {payload:  'Hello, ' + name + ' from ' + place + '!'};
+}
+```
+
+Create an OpenWhisk action by:
+```shell
+wsk action create hello ./greeting.js
+```
+
+And try this action:
+```shell
+wsk action invoke hello -b
+```
+
+If the action is invoked and message is returned without error, congratulations, you have a running OpenWhisk cluster on Kubernetes, enjoy it!
+
+## Cleanup
+
+Use the following command to remove the deployment:
+```shell
+helm delete <release_name>
+```
+or with a `--purge` option if you want to completely remove the deployment from helm:
+```shell
+helm delete <release_name> --purge
+```
+
+## References
+Part of this chart is based on the project [OpenWhisk Deployment for Kubernetes](https://github.com/apache/incubator-openwhisk-deploy-kube).
+This is a project using [ansible](https://www.ansible.com) to deploy OpenWhisk on Kubernetes. Please visit the project on github to get more details.
diff --git a/helm/charts/couchdb/Chart.yaml b/helm/charts/couchdb/Chart.yaml
new file mode 100644
index 0000000..9ee0613
--- /dev/null
+++ b/helm/charts/couchdb/Chart.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+description: A Helm chart to deploy couchdb service for Kubernetes
+name: couchdb
+version: 0.1.0
+keywords:
+  - couchdb
+maintainers:
+  - name: Tom Xing
+    email: xingzhou@cn.ibm.com
diff --git a/helm/charts/couchdb/templates/NOTES.txt b/helm/charts/couchdb/templates/NOTES.txt
new file mode 100644
index 0000000..c011009
--- /dev/null
+++ b/helm/charts/couchdb/templates/NOTES.txt
@@ -0,0 +1,11 @@
+
+
+
+Thank you for installing {{ .Chart.Name }}.
+
+Your release is named {{ .Release.Name }}.
+
+To learn more about the release, try:
+
+  $ helm status {{ .Release.Name }}
+  $ helm get {{ .Release.Name }}
diff --git a/helm/charts/couchdb/templates/_helpers.tpl b/helm/charts/couchdb/templates/_helpers.tpl
new file mode 100644
index 0000000..3cfb249
--- /dev/null
+++ b/helm/charts/couchdb/templates/_helpers.tpl
@@ -0,0 +1,19 @@
+{{/* Set Couchdb service name */}}
+{{- define "couchdb_service_name" -}}
+{{ .Values.global.couchdbServiceName | default "couchdb" | quote }}
+{{- end -}}
+
+{{/* Set Couchdb port */}}
+{{- define "couchdb_port" -}}
+{{ .Values.global.couchdbPort | default 5984 }}
+{{- end -}}
+
+{{/* Set Couchdb deployment name */}}
+{{- define "couchdb_deployment_name" -}}
+{{ .Values.deploymentName | default "couchdb" | quote }}
+{{- end -}}
+
+{{/* Set Couchdb PVC name */}}
+{{- define "couchdb_pvc_name" -}}
+{{ .Values.pvcName | default "couchdb-pvc" | quote }}
+{{- end -}}
diff --git a/helm/charts/couchdb/templates/deployment.yaml b/helm/charts/couchdb/templates/deployment.yaml
new file mode 100644
index 0000000..010a196
--- /dev/null
+++ b/helm/charts/couchdb/templates/deployment.yaml
@@ -0,0 +1,71 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: {{ template "couchdb_deployment_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: {{ template "couchdb_deployment_name" . }}
+spec:
+  replicas: {{ .Values.replicaCount | default 1 }}
+  template:
+    metadata:
+      labels:
+        name: {{ template "couchdb_deployment_name" . }}
+    spec:
+      restartPolicy: Always
+
+      {{- if .Values.global.affinity.enabled }}
+      affinity:
+        nodeAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+            nodeSelectorTerms:
+            - matchExpressions:
+              - key: nodeType
+                operator: In
+                values:
+                - {{ .Values.global.affinity.kafkaNodeLabel }}
+      {{- end }}
+
+      containers:
+      - name: {{ template "couchdb_deployment_name" . }}
+        imagePullPolicy: {{ .Values.imagePullPolicy | default "IfNotPresent" | quote }}
+        image: {{ .Values.image | default "openwhisk/kube-couchdb" | quote }}
+        command: ["/init.sh"]
+        ports:
+        - name: couchdb
+          containerPort: {{ template "couchdb_port" .}}
+        env:
+        - name: "DB_HOST"
+          value: "127.0.0.1"
+        - name: "DB_PREFIX"
+          value: {{ .Values.dbPrefix | default "test_" | quote }}
+        - name: "COUCHDB_USER"
+          value: {{ .Values.global.couchdbUserName | default "whisk_admin" | quote }}
+        - name: "COUCHDB_PASSWORD"
+          value: {{ .Values.global.couchdbPassword | default "some_passw0rd" | quote }}
+        - name: "DB_PORT"
+          value: {{ include "couchdb_port" . | quote }}
+        - name: "NODENAME"
+          value: "couchdb0"
+        readinessProbe:
+          httpGet:
+            port: {{ template "couchdb_port" . }}
+            # Tempting to say "/$(DB_PREFIX)_activations", but probe runs
+            # externally, therefore can't access the container environment...
+            path: "/test_activations"
+          initialDelaySeconds: 60
+          periodSeconds: 10
+          failureThreshold: 10
+          timeoutSeconds: 1
+        {{- if .Values.persistence.enabled }}
+        volumeMounts:
+          - name: database-storage
+            mountPath: /usr/local/var/lib/couchdb
+        {{- end }}
+      {{- if .Values.persistence.enabled }}
+      volumes:
+        - name: database-storage
+          persistentVolumeClaim:
+            claimName: couchdb-pvc
+      {{- end }}
+
diff --git a/helm/charts/couchdb/templates/pv.yaml b/helm/charts/couchdb/templates/pv.yaml
new file mode 100644
index 0000000..4570714
--- /dev/null
+++ b/helm/charts/couchdb/templates/pv.yaml
@@ -0,0 +1,17 @@
+{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+  name: couchdb-pv
+  labels:
+    type: couchdb
+  namespace: openwhisk
+spec:
+  accessModes:
+    - {{ .Values.persistence.accessMode | quote }}
+  capacity:
+    storage: {{ .Values.persistence.size | quote }}
+  nfs:
+    path: {{ .Values.persistence.nfs_path }}
+    server: {{ .Values.persistence.nfs_server }}
+{{- end }}
diff --git a/helm/charts/couchdb/templates/pvc.yaml b/helm/charts/couchdb/templates/pvc.yaml
new file mode 100644
index 0000000..d3a9684
--- /dev/null
+++ b/helm/charts/couchdb/templates/pvc.yaml
@@ -0,0 +1,22 @@
+{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+  name: {{ template "couchdb_pvc_name" . }}
+  labels:
+    type: couchdb
+  namespace: {{ .Release.Namespace | quote }}
+spec:
+  accessModes:
+    - {{ .Values.persistence.accessMode | quote }}
+  resources:
+    requests:
+      storage: {{ .Values.persistence.size | quote }}
+{{- if .Values.persistence.storageClass }}
+{{- if (eq "-" .Values.persistence.storageClass) }}
+  storageClassName: ""
+{{- else }}
+  storageClassName: "{{ .Values.persistence.storageClass }}"
+{{- end }}
+{{- end }}
+{{- end }}
diff --git a/helm/charts/couchdb/templates/service.yaml b/helm/charts/couchdb/templates/service.yaml
new file mode 100644
index 0000000..2fae8bd
--- /dev/null
+++ b/helm/charts/couchdb/templates/service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ template "couchdb_service_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: {{ template "couchdb_service_name" . }}
+spec:
+  selector:
+    name: {{ template "couchdb_service_name" . }}
+  ports:
+    - port: {{ template "couchdb_port" . }}
+      targetPort: {{ template "couchdb_port" . }}
+      name: couchdb
diff --git a/helm/charts/kafka/Chart.yaml b/helm/charts/kafka/Chart.yaml
new file mode 100755
index 0000000..7b1d9b7
--- /dev/null
+++ b/helm/charts/kafka/Chart.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+description: A Helm chart to deploy kafka service for Kubernetes
+name: kafka
+version: 0.1.0
+keywords:
+  - zookeeper
+  - kafka
+maintainers:
+  - name: Tom Xing
+    email: xingzhou@cn.ibm.com
diff --git a/helm/charts/kafka/templates/NOTES.txt b/helm/charts/kafka/templates/NOTES.txt
new file mode 100644
index 0000000..29863d3
--- /dev/null
+++ b/helm/charts/kafka/templates/NOTES.txt
@@ -0,0 +1,8 @@
+Thank you for installing {{ .Chart.Name }}.
+
+Your release is named {{ .Release.Name }}.
+
+To learn more about the release, try:
+
+  $ helm status {{ .Release.Name }}
+  $ helm get {{ .Release.Name }}
diff --git a/helm/charts/kafka/templates/_helpers.tpl b/helm/charts/kafka/templates/_helpers.tpl
new file mode 100644
index 0000000..1c39467
--- /dev/null
+++ b/helm/charts/kafka/templates/_helpers.tpl
@@ -0,0 +1,19 @@
+{{/* Get statefulset name */}}
+{{- define "kafka_statefulset_name" -}}
+{{ .Values.statefulsetName | default "kafka" | quote }}
+{{- end -}}
+
+{{/* Get service name */}}
+{{- define "kafka_service_name" -}}
+{{ .Values.global.kafkaServiceName | default "kafka" | quote }}
+{{- end -}}
+
+{{/* Generate Zookeeper service address */}}
+{{- define "zookeeper_service_address" -}}
+{{ .Values.global.zookeeperServiceName }}.{{ .Release.Namespace }}:{{ .Values.global.zookeeperPort }}
+{{- end -}}
+
+{{/* Get kafka port */}}
+{{- define "kafka_port" -}}
+{{ .Values.global.kafkaPort | default 9092 }}
+{{- end -}}
diff --git a/helm/charts/kafka/templates/service.yaml b/helm/charts/kafka/templates/service.yaml
new file mode 100644
index 0000000..a3d012b
--- /dev/null
+++ b/helm/charts/kafka/templates/service.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ template "kafka_service_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+spec:
+  ports:
+  - name: broker
+    port: {{ template "kafka_port" . }} 
+  clusterIP: None
+  selector:
+    app: {{ template "kafka_statefulset_name" . }}
diff --git a/helm/charts/kafka/templates/statefulset.yaml b/helm/charts/kafka/templates/statefulset.yaml
new file mode 100644
index 0000000..b349f45
--- /dev/null
+++ b/helm/charts/kafka/templates/statefulset.yaml
@@ -0,0 +1,55 @@
+apiVersion: apps/v1beta1
+kind: StatefulSet
+metadata:
+  name: {{ template "kafka_statefulset_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+spec:
+  serviceName: {{ template "kafka_service_name" . }} 
+  replicas: {{ .Values.replicaCount | default 1 }}
+  template:
+    metadata:
+      labels:
+        app: {{ template "kafka_statefulset_name" . }}
+    spec:
+      {{- if .Values.global.affinity.enabled }}
+      affinity:
+        nodeAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+            nodeSelectorTerms:
+            - matchExpressions:
+              - key: nodeType
+                operator: In
+                values:
+                - {{ .Values.global.affinity.kafkaNodeLabel }}
+      {{- end }}
+
+      initContainers:
+      - name: "wait-for-zookeeper"
+        image: "busybox"
+        imagePullPolicy: "IfNotPresent"
+        command: ["sh", "-c", "result=1; until [ $result -eq 0 ]; do nslookup {{ .Values.global.zookeeperServiceName}}.{{ .Release.Namespace }}; result=$?; echo waiting for {{ .Values.global.zookeeperServiceName}}.{{ .Release.Namespace }}; sleep 1; done;"]
+
+      containers:
+      - name: {{ template "kafka_statefulset_name" . }}
+        image: {{ .Values.image | default "wurstmeister/kafka:0.11.0.1" | quote }}
+        imagePullPolicy: {{ .Values.imagePullPolicy | default "IfNotPresent" | quote }}
+        ports:
+        - containerPort: {{ template "kafka_port" . }}
+          name: kafka
+        env:
+        - name: "KAFKA_BROKER_ID"
+          value: "0"
+        - name: "KAFKA_ADVERTISED_HOST_NAME"
+          value: {{ template "kafka_statefulset_name" . }}
+        - name: "KAFKA_ADVERTISED_PORT"
+          value: "{{ template "kafka_port" .}}"
+        - name: "KAFKA_HOST_NAME"
+          valueFrom:
+            fieldRef:
+              fieldPath: status.podIP
+        - name: "KAFKA_PORT"
+          value: "{{ template "kafka_port" .}}"
+
+        # zookeeper info
+        - name: "KAFKA_ZOOKEEPER_CONNECT"
+          value: {{ include "zookeeper_service_address" . | quote }}
diff --git a/helm/charts/nginx/Chart.yaml b/helm/charts/nginx/Chart.yaml
new file mode 100644
index 0000000..e464e5a
--- /dev/null
+++ b/helm/charts/nginx/Chart.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+description: A Helm chart to deploy nginx service for Kubernetes
+name: nginx
+version: 0.1.0
+keywords:
+  - nginx
+maintainers:
+  - name: Tom Xing
+    email: xingzhou@cn.ibm.com
diff --git a/helm/charts/nginx/templates/NOTES.txt b/helm/charts/nginx/templates/NOTES.txt
new file mode 100644
index 0000000..29863d3
--- /dev/null
+++ b/helm/charts/nginx/templates/NOTES.txt
@@ -0,0 +1,8 @@
+Thank you for installing {{ .Chart.Name }}.
+
+Your release is named {{ .Release.Name }}.
+
+To learn more about the release, try:
+
+  $ helm status {{ .Release.Name }}
+  $ helm get {{ .Release.Name }}
diff --git a/helm/charts/nginx/templates/_helpers.tpl b/helm/charts/nginx/templates/_helpers.tpl
new file mode 100644
index 0000000..520c523
--- /dev/null
+++ b/helm/charts/nginx/templates/_helpers.tpl
@@ -0,0 +1,49 @@
+{ Generate controller url */}}
+{{- define "controller_url" -}}
+http://{{ .Values.global.controllerStatefulSetName | default "controller" }}-0.{{ .Values.global.controllerServiceName | default "controller" }}.{{ .Release.Namespace }}:{{ .Values.global.controllerPort | default 8080 }}
+{{- end -}}
+
+{ Generate controller url witout port */}}
+{{- define "controller_url_without_port" -}}
+{{ .Values.global.controllerStatefulSetName | default "controller" }}-0.{{ .Values.global.controllerServiceName | default "controller" }}.{{ .Release.Namespace }}
+{{- end -}}
+
+{{/* Set deployment name */}}
+{{- define "nginx_deployment_name" -}}
+{{ .Values.deploymentName | default "nginx" | quote }}
+{{- end -}}
+
+{{/* Set service name */}}
+{{- define "nginx_service_name" -}}
+{{ .Values.serviceName | default "nginx" | quote }}
+{{- end -}}
+
+{{/* Set secret name */}}
+{{- define "nginx_secret_name" -}}
+{{ .Values.secretName | default "nginx" | quote }}
+{{- end -}}
+
+{{/* Set configmap name */}}
+{{- define "nginx_configmap_name" -}}
+{{ .Values.configmapName | default "nginx" | quote }}
+{{- end -}}
+
+{{/* Set http port */}}
+{{- define "nginx_http_port" -}}
+{{ .Values.httpPort | default 80 }}
+{{- end -}}
+
+{{/* Set https port */}}
+{{- define "nginx_https_port" -}}
+{{ .Values.httpsPort | default 443 }}
+{{- end -}}
+
+{{/* Set https admin port */}}
+{{- define "nginx_https_admin_port" -}}
+{{ .Values.httpsAdminPort | default 8443 }}
+{{- end -}}
+
+{{/* Set controller statefulset name */}}
+{{- define "controller_statefulset_name" -}}
+{{ .Values.global.controllerStatefulSetName | default "controller" }}
+{{- end -}}
diff --git a/helm/charts/nginx/templates/configmap.yaml b/helm/charts/nginx/templates/configmap.yaml
new file mode 100644
index 0000000..cc4d45a
--- /dev/null
+++ b/helm/charts/nginx/templates/configmap.yaml
@@ -0,0 +1,102 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ template "nginx_configmap_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+data:
+  nginx.conf: |
+    events {
+      worker_connections  4096;
+    }
+
+    http {
+      client_max_body_size 50M;
+
+      rewrite_log on;
+      log_format combined-upstream '$remote_addr - $remote_user [$time_local] '
+          '$request $status $body_bytes_sent '
+          '$http_referer $http_user_agent $upstream_addr';
+      access_log /logs/nginx_access.log combined-upstream;
+
+      server {
+          listen 80;
+          listen 443 default ssl;
+
+          # match namespace, note while OpenWhisk allows a richer character set for a
+          # namespace, not all those characters are permitted in the (sub)domain name;
+          # if namespace does not match, no vanity URL rewriting takes place.
+          server_name ~^(?<namespace>[0-9a-zA-Z-]+)\.localhost$;
+
+          ssl_session_cache    shared:SSL:1m;
+          ssl_session_timeout  10m;
+          ssl_certificate      /etc/nginx/certs/tls.crt;
+          ssl_certificate_key  /etc/nginx/certs/tls.key;
+          ssl_verify_client off;
+          ssl_protocols        TLSv1 TLSv1.1 TLSv1.2;
+          ssl_ciphers RC4:HIGH:!aNULL:!MD5;
+          ssl_prefer_server_ciphers on;
+          proxy_ssl_session_reuse on;
+          proxy_ssl_verify off;
+
+          # Hack to convince nginx to dynamically resolve the dns entry.
+          resolver kube-dns.kube-system;
+          set $controllers controller.openwhisk.svc.cluster.local;
+
+          # proxy to the web action path
+          location / {
+              if ($namespace) {
+                rewrite    /(.*) /api/v1/web/${namespace}/$1 break;
+              }
+
+              proxy_pass http://$controllers:8080;
+              proxy_read_timeout 70s; # 60+10 additional seconds to allow controller to terminate request
+          }
+
+          # proxy to 'public/html' web action by convention
+          location = / {
+              if ($namespace) {
+                rewrite    ^ /api/v1/web/${namespace}/public/index.html break;
+              }
+
+              proxy_pass http://$controllers:8080;
+              proxy_read_timeout 70s; # 60+10 additional seconds to allow controller to terminate request
+          }
+
+                  location /blackbox.tar.gz {
+            return 301 https://github.com/apache/incubator-openwhisk-runtime-docker/releases/download/sdk%400.1.0/blackbox-0.1.0.tar.gz;
+        }
+        # leaving this for a while for clients out there to update to the new endpoint
+        location /blackbox-0.1.0.tar.gz {
+            return 301 /blackbox.tar.gz;
+        }
+
+        location /OpenWhiskIOSStarterApp.zip {
+            return 301 https://github.com/openwhisk/openwhisk-client-swift/releases/download/0.2.3/starterapp-0.2.3.zip;
+        }
+
+        # redirect requests for specific binaries to the matching one from the latest openwhisk-cli release.
+        location /cli/go/download/linux/amd64 {
+            return 301 https://github.com/apache/incubator-openwhisk-cli/releases/download/latest/OpenWhisk_CLI-latest-linux-amd64.tgz;
+        }
+        location /cli/go/download/linux/386 {
+            return 301 https://github.com/apache/incubator-openwhisk-cli/releases/download/latest/OpenWhisk_CLI-latest-linux-386.tgz;
+        }
+        location /cli/go/download/mac/amd64 {
+            return 301 https://github.com/apache/incubator-openwhisk-cli/releases/download/latest/OpenWhisk_CLI-latest-mac-amd64.zip;
+        }
+        location /cli/go/download/mac/386 {
+            return 301 https://github.com/apache/incubator-openwhisk-cli/releases/download/latest/OpenWhisk_CLI-latest-mac-386.zip;
+        }
+        location /cli/go/download/windows/amd64 {
+            return 301 https://github.com/apache/incubator-openwhisk-cli/releases/download/latest/OpenWhisk_CLI-latest-windows-amd64.zip;
+        }
+        location /cli/go/download/windows/386 {
+            return 301 https://github.com/apache/incubator-openwhisk-cli/releases/download/latest/OpenWhisk_CLI-latest-windows-386.zip;
+        }
+
+        # redirect top-level cli downloads to the latest openwhisk-cli release.
+        location /cli/go/download {
+            return 301 https://github.com/apache/incubator-openwhisk-cli/releases/latest;
+        }
+      }
+    }
diff --git a/helm/charts/nginx/templates/deployment.yaml b/helm/charts/nginx/templates/deployment.yaml
new file mode 100644
index 0000000..2e790b5
--- /dev/null
+++ b/helm/charts/nginx/templates/deployment.yaml
@@ -0,0 +1,52 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: {{ template "nginx_deployment_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: nginx
+spec:
+  replicas: {{ .Values.replicaCount | default 1 }}
+  template:
+    metadata:
+      labels:
+        name: {{ template "nginx_deployment_name" . }}
+      annotations:
+        pod.beta.kubernetes.io/init-containers: '[
+            {
+                "name": "wait-for-controller",
+                "image": "busybox",
+                "imagePullPolicy": "IfNotPresent",
+                "command": ["sh", "-c", "until nslookup {{ template "controller_url_without_port" . }}; do echo waiting for {{ template "controller_url_without_port" . }}; sleep 1; done;"]
+            }
+        ]'
+    spec:
+      restartPolicy: Always
+      volumes:
+      - name: nginx-certs
+        secret:
+          secretName: {{ template "nginx_secret_name" . }}
+      - name: nginx-conf
+        configMap:
+          name: {{ template "nginx_configmap_name" . }}
+      - name: logs
+        emptyDir: {}
+      containers:
+      - name: {{ template "nginx_deployment_name" . }}
+        imagePullPolicy: {{ .Values.imagePullPolicy | default "IfNotPresent" | quote }}
+        image: {{ .Values.image | default "nginx:1.11" | quote }}
+        ports:
+        - name: http
+          containerPort: {{ template "nginx_http_port" . }}
+        - name: http-api
+          containerPort: {{ template "nginx_https_port" . }}
+        - name: https-admin
+          containerPort: {{ template "nginx_https_admin_port" . }}
+        volumeMounts:
+        - name: nginx-conf
+          mountPath: "/etc/nginx/nginx.conf"
+          subPath: "nginx.conf"
+        - name: nginx-certs
+          mountPath: "/etc/nginx/certs"
+        - name: logs
+          mountPath: "/logs"
diff --git a/helm/charts/nginx/templates/secret.yaml b/helm/charts/nginx/templates/secret.yaml
new file mode 100644
index 0000000..a79dc20
--- /dev/null
+++ b/helm/charts/nginx/templates/secret.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ template "nginx_secret_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+type: tls
+data:
+  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMrekNDQWVPZ0F3SUJBZ0lKQU1IQ0FaQk1LRmxxTUEwR0NTcUdTSWIzRFFFQkN3VUFNQlF4RWpBUUJnTlYKQkFNTUNXeHZZMkZzYUc5emREQWVGdzB4TnpBNE1UWXdOek0yTXpKYUZ3MHhPREE0TVRZd056TTJNekphTUJReApFakFRQmdOVkJBTU1DV3h2WTJGc2FHOXpkRENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DCmdnRUJBUHVrZndBbjZXb0xBTWNqSnpQemR2NGlPQ1g5bHR4cVpGeEFjUHhBS1BQcE16dWJnOG1ObjhZWllzQ3oKbjRTUjdRYndZK0RTRHVsczZaekRxaGdpa1hDOUs1L2doRm9zS1FaY0gzVERSSUNsS2ZDeFdlb04xc0tEQ1RCdQpia2YzRkNqL0dBUmJ4TE0yM3QvMS9kby9nMU4rUXYxeDRXL2VpNWZva1gwNXRNcWJLcnM2OHU3U3lGaEZhTTYyCnZQclhlc1JEWDVuRlZ5ekpqaDdBbHpralZHTWltOU5sMmhuM0dIK1Y1RWt2dVR6ODJnVjBEWXc4OEFXb29PTjgKYXVLamlROTVRWUJkR2tUR1U3Z0pqTmRxeGk4Q3dadnlPTnhoRU9rOURvV1RjWVU2T1orZXc3QUVlbENMTnRheApWcGlWd0lLc1o3UnlPUGZSQzRFNVBpWEZ4ZThDQXdFQUFhTlFNRTR3SFFZRFZSME9CQllFRk5kajlvT2grZ1ZtCndiTkhnM1BiUVlvYUhlODlNQjhHQTFVZEl3UVlNQmFBRk5kajlvT2grZ1Ztd2JOSGczUGJRWW9hSGU4OU1Bd0cKQTFVZEV3UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFBdW1UTzRMYmh0WFZWa0lsclhJc09vawpzSG13UEoyWTJQN1hjZ3BrQ3VYNjVRYUN2Q3JNMlNUSXFrb0RabE9MbFRXUmRqSU8zc3JISlh6UFhLRXowR2dJCmV4bm5oZTIrbm1PNWdnSmVIR2lReVZnZTEvVUFMcWpYSGRNR2JqMFdodnlkQjUwcTVpSDV2eHRGZy95ODBFWFUKa0ZQa0E4NkZmQlhmSHdUNVIyYzB0VFRzSUNWdzk5MkhJMHNxOUZSMnA1bE5xYTBHOTVSOG5UUEhFZUIzMTF0MAozM3oyb3lScTNpam05RHNlOGNPTTAxcVZUcTJzQU9COTR2eE56WXAxZTVLUUl2bnJJQ3ptTDg2YzJxMEY3cVhnClFqWkltRHE2WXNXTE5vVTMrc1V1U2Npc09KbUQxSGFvRmEzKzRIcUp3dWpPamYwdkpuUmJGSHRNcDVFQms1az0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
+  tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRRDdwSDhBSitscUN3REgKSXljejgzYitJamdsL1piY2FtUmNRSEQ4UUNqejZUTTdtNFBKalovR0dXTEFzNStFa2UwRzhHUGcwZzdwYk9tYwp3Nm9ZSXBGd3ZTdWY0SVJhTENrR1hCOTB3MFNBcFNud3NWbnFEZGJDZ3drd2JtNUg5eFFvL3hnRVc4U3pOdDdmCjlmM2FQNE5UZmtMOWNlRnYzb3VYNkpGOU9iVEtteXE3T3ZMdTBzaFlSV2pPdHJ6NjEzckVRMStaeFZjc3lZNGUKd0pjNUkxUmpJcHZUWmRvWjl4aC9sZVJKTDdrOC9Ob0ZkQTJNUFBBRnFLRGpmR3JpbzRrUGVVR0FYUnBFeGxPNApDWXpYYXNZdkFzR2I4ampjWVJEcFBRNkZrM0dGT2ptZm5zT3dCSHBRaXpiV3NWYVlsY0NDckdlMGNqajMwUXVCCk9UNGx4Y1h2QWdNQkFBRUNnZ0VBT0JjaWQ5WnRvTVZ6RnZBdS9OVjM0STJnRmxmQUdNRmVQWEhmdlZwUHhvNWsKYlJUcyt6QW1QUEhMb1Vob2RoUlEwUXNrT0NpYVNrMk1oUFRZSlNrUFlpSElaNHFUOWNXQ0gzakpTaTE4UjNDSgpPSzFQYld4SVFuTVN5VWpVTEJaVzJBeUVQZlIyazd2WFVmUnk4UUxYTXZVaDJYeFkwNmEzVnRUd0dRbVQwdFR5Ck9renArUVcyY0JKcjZuYzRQdzJ4dWN1bFBnTjRlY04rdkl5QllSNWZVa1VDcTREbTI2aU1LSXZ1SlFSeXFmK0oKRk1HU0x1K1FkTG9vSmoyZTUrSjgxdHcyLzlxWENuN2poeWpka08vVjJNTVhtejRHTHVFZmdYUlpvUFVNcjN2VApNZXRPV3o0Q0F1cXIxTUNuODlXSEdsbDF2VEVpM0ZRSFlyb1lZN2txQVFLQmdRRC92RDk4ZHpMOFNrcVpzZ3BnCk1PeEFILzczNzFzRjBtWGxtNTdmem84Y1BHTVVZWWc1dUlMdFI4Z1BkS0F1dmd0YjFiNzcxbkY3cnMyVy9OM28KK296bEdQT1JqdmROU24vcytTRld3MTVKTGZmUnZ1ZDkzYWhUbnlGekY2aUFuMndVQ2VCVExBd2dyR0YzVGxXNwpFR1pyWVdkVHRXM3k4YUhxNHlMYTM2OEtud0tCZ1FENzV5bnU3c3diM1ppOXlEZzdUOWZlUXJ4dU9kTVNVQlhYCkRwSXczbUxjdTBmK21uWFcxbU45RXU0OVpwbkg3ZkRnejFocTNkeEo3SzQ2OW9BaWVkNTZsTWxNd0pUSlBrNlIKUW5tbkw1S3RwRnNmajBZbUtPN2lRYURoYjFmR2VvdWxlL2xSUnVocWN0OHZhNG51SzJzbEwwZVpvSzhJWWNDVwpROFpIMVZmU3NRS0JnUUNsNVdhQnhZbXJwRDMwcWt5VXplZlVTVzFMUlZpVTFFSUp5d1FyUjRJSzNSbWhGUXdiCjlaZnBlVkZNeFdsTUtUaVJJSDIrUFFSdEtaNXd2aVR1aCtweWk5Y2xxOHE5dHdCNXA3dDYzMDRBeHZNbWUyTU0KZ1lnNmh0WmFKUlRJSzZNZTlMRXpBelh5MUNCK0ZyRUNvc2J1RGNmTHc3eEpoM3AwTjFoYkNCUXpIUUtCZ0NaRwplNktvZWk4SnZybW5nSlBTai9SZm80NEVEMFJMRXVaNGVsSWVtRnI5d2ZTM3Q0d0xTMWFuMTdkUXJiRXBRRjZJCll1RHFFUnpTYjY3WjRhSmJiaWltRHVnd291cnBJcnNEcE1SNGdBc09YQ0l4ZlBFemF3akovQTRGQXd0UGQ0U1AKajlSL3Q3VGsrM0NUSUlRbDZNUGZxVHQ0cE4vYktvNHFnaWhNREdvaEFvR0FNcXRXbTVLMERJN0pWQnB4SndWSwpKZmpSKzljT2J1T1M0N2E3bGxwZG55d2RYbTZkOGR4eW9mTEVNQVl3ODUyNEM5OUF2UlBmdWoyOUVEM0JlcHpuCklIWkhpWTlmaHE1YldnYTVRd2Z1dXBubGhlMzJXU2JzRHk2MEZrL05SbUI0MWhacm9GTEp3Ri9Ub2hlQlpBZ3kKRVBLbkpBc00wdCswbUJyWG9IM1ArcU09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
diff --git a/helm/charts/nginx/templates/service.yaml b/helm/charts/nginx/templates/service.yaml
new file mode 100644
index 0000000..0fe2dae
--- /dev/null
+++ b/helm/charts/nginx/templates/service.yaml
@@ -0,0 +1,30 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ template "nginx_service_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: {{ template "nginx_service_name" . }}
+spec:
+  type: NodePort
+  selector:
+    name: {{ template "nginx_deployment_name" . }}
+  ports:
+    - port: {{ template "nginx_http_port" . }}
+      targetPort: {{ template "nginx_http_port" . }}
+      {{- if .Values.httpNodePort }}
+      nodePort: {{ .Values.httpNodePort }}
+      {{- end }}
+      name: http
+    - port: {{ template "nginx_https_port" . }}
+      targetPort: {{ template "nginx_https_port" . }}
+      {{- if .Values.httpsNodePort }}
+      nodePort: {{ .Values.httpsNodePort }}
+      {{- end }}
+      name: https-api
+    - port: {{ template "nginx_https_admin_port" . }}
+      targetPort: {{ template "nginx_https_admin_port" . }}
+      {{- if .Values.httpsAdminNodePort }}
+      nodePort: {{ .Values.httpsAdminNodePort }}
+      {{- end }}
+      name: https-admin
diff --git a/helm/charts/redis/Chart.yaml b/helm/charts/redis/Chart.yaml
new file mode 100644
index 0000000..249a3d9
--- /dev/null
+++ b/helm/charts/redis/Chart.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+description: A Helm chart to deploy redis service for Kubernetes
+name: redis
+version: 0.1.0
+keywords:
+  - redis
+maintainers:
+  - name: Tom Xing
+    email: xingzhou@cn.ibm.com
diff --git a/helm/charts/redis/templates/NOTES.txt b/helm/charts/redis/templates/NOTES.txt
new file mode 100644
index 0000000..29863d3
--- /dev/null
+++ b/helm/charts/redis/templates/NOTES.txt
@@ -0,0 +1,8 @@
+Thank you for installing {{ .Chart.Name }}.
+
+Your release is named {{ .Release.Name }}.
+
+To learn more about the release, try:
+
+  $ helm status {{ .Release.Name }}
+  $ helm get {{ .Release.Name }}
diff --git a/helm/charts/redis/templates/_helpers.tpl b/helm/charts/redis/templates/_helpers.tpl
new file mode 100644
index 0000000..d0c0826
--- /dev/null
+++ b/helm/charts/redis/templates/_helpers.tpl
@@ -0,0 +1,14 @@
+{ Get redis service name */}}
+{{- define "redis_service_name" -}}
+{{ .Values.global.redisServiceName | default "redis" | quote }}
+{{- end -}}
+
+{ Get redis deployment name */}}
+{{- define "redis_deployment_name" -}}
+{{ .Values.deploymentName | default "redis" | quote }}
+{{- end -}}
+
+{{/* Set port */}}
+{{- define "redis_port" -}}
+{{ .Values.global.redisServicePort | default 6379 }}
+{{- end -}}
diff --git a/helm/charts/redis/templates/deployment.yaml b/helm/charts/redis/templates/deployment.yaml
new file mode 100644
index 0000000..f2634e2
--- /dev/null
+++ b/helm/charts/redis/templates/deployment.yaml
@@ -0,0 +1,23 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: {{ template "redis_deployment_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: {{ template "redis_deployment_name" . }}
+spec:
+  replicas: {{ .Values.replicaCount | default 1 }}
+  template:
+    metadata:
+      labels:
+        name: {{ template "redis_deployment_name" . }}
+    spec:
+      restartPolicy: Always
+
+      containers:
+      - name: redis
+        imagePullPolicy: {{ .Values.imagePullPolicy | default "IfNotPresent" | quote }}
+        image: {{ .Values.image | default "redis:3.2" | quote }}
+        ports:
+        - name: redis-port
+          containerPort: {{ template "redis_port" . }}
\ No newline at end of file
diff --git a/helm/charts/redis/templates/service.yaml b/helm/charts/redis/templates/service.yaml
new file mode 100644
index 0000000..3c7649e
--- /dev/null
+++ b/helm/charts/redis/templates/service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ template "redis_service_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: {{ template "redis_service_name" . }}
+spec:
+  selector:
+    name: {{ template "redis_deployment_name" . }}
+  ports:
+    - port: {{ template "redis_port" . }}
+      targetPort: {{ template "redis_port" . }}
+      name: redis
\ No newline at end of file
diff --git a/helm/charts/zookeeper/Chart.yaml b/helm/charts/zookeeper/Chart.yaml
new file mode 100644
index 0000000..c951bd8
--- /dev/null
+++ b/helm/charts/zookeeper/Chart.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+description: A Helm chart to deploy zookeeper service for Kubernetes
+name: zookeeper
+version: 0.1.0
+keywords:
+  - zookeeper
+maintainers:
+  - name: Tom Xing
+    email: xingzhou@cn.ibm.com
diff --git a/helm/charts/zookeeper/templates/NOTES.txt b/helm/charts/zookeeper/templates/NOTES.txt
new file mode 100644
index 0000000..29863d3
--- /dev/null
+++ b/helm/charts/zookeeper/templates/NOTES.txt
@@ -0,0 +1,8 @@
+Thank you for installing {{ .Chart.Name }}.
+
+Your release is named {{ .Release.Name }}.
+
+To learn more about the release, try:
+
+  $ helm status {{ .Release.Name }}
+  $ helm get {{ .Release.Name }}
diff --git a/helm/charts/zookeeper/templates/_helpers.tpl b/helm/charts/zookeeper/templates/_helpers.tpl
new file mode 100644
index 0000000..47f54d8
--- /dev/null
+++ b/helm/charts/zookeeper/templates/_helpers.tpl
@@ -0,0 +1,24 @@
+{{/* Get deployment name */}}
+{{- define "zookeeper_deployment_name" -}}
+{{ .Values.deploymentName | default "zookeeper" | quote }}
+{{- end -}}
+
+{{/* Get service name */}}
+{{- define "zookeeper_service_name" -}}
+{{ .Values.global.zookeepserServiceName | default "zookeeper" | quote }}
+{{- end -}}
+
+{{/* Set zookeeper port */}}
+{{- define "zookeeper_port" -}}
+{{ .Values.global.zookeeperPort | default 2181 }}
+{{- end -}}
+
+{{/* Set server port */}}
+{{- define "zookeeper_server_port" -}}
+{{ .Values.serverPort | default 2888 }}
+{{- end -}}
+
+{{/* Set leader election port */}}
+{{- define "zookeeper_leader_election_port" -}}
+{{ .Values.leaderElectionPort | default 3888 }}
+{{- end -}}
diff --git a/helm/charts/zookeeper/templates/deployment.yaml b/helm/charts/zookeeper/templates/deployment.yaml
new file mode 100644
index 0000000..39f0482
--- /dev/null
+++ b/helm/charts/zookeeper/templates/deployment.yaml
@@ -0,0 +1,39 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: {{ template "zookeeper_deployment_name" . }}
+  namespace: {{ .Release.Namespace | default "openwhisk" | quote}}
+  labels:
+    name: {{ template "zookeeper_deployment_name" . }}
+spec:
+  replicas: {{ .Values.replicaCount | default 1}}
+  template:
+    metadata:
+      labels:
+        name: {{ template "zookeeper_deployment_name" . }}
+    spec:
+      restartPolicy: {{ .Values.restartPolicy | default "Always" | quote }}
+
+      {{- if .Values.global.affinity.enabled }}
+      affinity:
+        nodeAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+            nodeSelectorTerms:
+            - matchExpressions:
+              - key: nodeType
+                operator: In
+                values:
+                - {{ .Values.global.affinity.kafkaNodeLabel }}
+      {{- end }}
+
+      containers:
+      - name: {{ .Values.containerName | default "zookeeper" | quote }}
+        image: {{ .Values.image | default "zookeeper:3.4" | quote }}
+        imagePullPolicy: {{ .Values.imagePullPolicy | default "IfNotPresent" | quote }}
+        ports:
+        - name: zookeeper
+          containerPort: {{ template "zookeeper_port" . }}
+        - name: server
+          containerPort: {{ template "zookeeper_server_port" . }}
+        - name: leader-election
+          containerPort: {{ template "zookeeper_leader_election_port" . }}
diff --git a/helm/charts/zookeeper/templates/service.yaml b/helm/charts/zookeeper/templates/service.yaml
new file mode 100644
index 0000000..44ed5cc
--- /dev/null
+++ b/helm/charts/zookeeper/templates/service.yaml
@@ -0,0 +1,20 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ template "zookeeper_service_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: {{ template "zookeeper_service_name" . }}
+spec:
+  selector:
+    name: {{ template "zookeeper_deployment_name" . }}
+  ports:
+    - port: {{ template "zookeeper_port" . }}
+      targetPort: {{ template "zookeeper_port" . }}
+      name: "zookeeper"
+    - port: {{ template "zookeeper_server_port" .}}
+      targetPort: {{ template "zookeeper_server_port" . }}
+      name: "server"
+    - port: {{ template "zookeeper_leader_election_port" . }}
+      targetPort: {{ template "zookeeper_leader_election_port" . }}
+      name: "leader-election"
diff --git a/helm/templates/NOTES.txt b/helm/templates/NOTES.txt
new file mode 100644
index 0000000..29863d3
--- /dev/null
+++ b/helm/templates/NOTES.txt
@@ -0,0 +1,8 @@
+Thank you for installing {{ .Chart.Name }}.
+
+Your release is named {{ .Release.Name }}.
+
+To learn more about the release, try:
+
+  $ helm status {{ .Release.Name }}
+  $ helm get {{ .Release.Name }}
diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl
new file mode 100644
index 0000000..cfd4446
--- /dev/null
+++ b/helm/templates/_helpers.tpl
@@ -0,0 +1,85 @@
+{{/* Set controller service name */}}
+{{- define "controller_service_name" -}}
+{{ .Values.global.controllerServiceName | default "controller" | quote }}
+{{- end -}}
+
+{{/* Set controller statefulset name */}}
+{{- define "controller_statefulset_name" -}}
+{{ .Values.global.controllerStatefulSetName | default "controller" | quote }}
+{{- end -}}
+
+{{/* Set controller port */}}
+{{- define "controller_port" -}}
+{{ .Values.global.controllerPort | default 8080 }}
+{{- end -}}
+
+{{/* Set activations table */}}
+{{- define "activations_table" -}}
+{{ .Values.activationsTable | default "test_activations" | quote }}
+{{- end -}}
+
+{{/* Set actions table */}}
+{{- define "actions_table" -}}
+{{ .Values.actionsTable | default "test_whisks" | quote }}
+{{- end -}}
+
+{{/* Set auths table */}}
+{{- define "auths_table" -}}
+{{ .Values.authTable | default "test_subjects" | quote }}
+{{- end -}}
+
+{{/* Set invoker statefulset name */}}
+{{- define "invoker_statefulset_name" -}}
+{{ .Values.invokerStatefulsetName | default "invoker" | quote }}
+{{- end -}}
+
+{{/* Generate kafka url without port */}}
+{{- define "kafka_url_without_port" -}}
+{{ .Values.global.kafkaServiceName | default "kafka" }}.{{ .Release.Namespace }}
+{{- end -}}
+
+
+{{/* Set Couchdb user name */}}
+{{- define "couchdb_username" -}}
+{{ .Values.global.couchdbUserName | default "whisk_admin" | quote }}
+{{- end -}}
+
+{{/* Set Couchdb password */}}
+{{- define "couchdb_password" -}}
+{{ .Values.global.couchdbPassword | default "some_passw0rd" | quote }}
+{{- end -}}
+
+{{/* Generate Couchdb url without port */}}
+{{- define "couchdb_url_without_port" -}}
+{{ .Values.global.couchdbServiceName | default "couchdb" }}.{{ .Release.Namespace }}
+{{- end -}}
+
+{{/* Set Couchdb port */}}
+{{- define "couchdb_port" -}}
+{{ .Values.global.couchdb_port | default 5984 }}
+{{- end -}}
+
+{{/* Set API Gateway service name */}}
+{{- define "apigateway_service_name" -}}
+{{ .Values.serviceName | default "apigateway" | quote }}
+{{- end -}}
+
+{{/* Set API Gateway management port */}}
+{{- define "apigateway_mgmt_port" -}}
+{{ .Values.mgmtPort | default 8080 }}
+{{- end -}}
+
+{{/* Set API Gateway API port */}}
+{{- define "apigateway_api_port" -}}
+{{ .Values.apiPort | default 9000 }}
+{{- end -}}
+
+{{/* Set API Gateway deployment name */}}
+{{- define "apigateway_deployment_name" -}}
+{{ .Values.deploymentName | default "apigateway" | quote }}
+{{- end -}}
+
+{{/* Generate redis service url */}}
+{{- define "redis_url" -}}
+{{ .Values.global.redisServiceName | default "redis" }}.{{ .Release.Namespace }}
+{{- end -}}
\ No newline at end of file
diff --git a/helm/templates/apigateway_deployment.yml b/helm/templates/apigateway_deployment.yml
new file mode 100644
index 0000000..f7cd6ee
--- /dev/null
+++ b/helm/templates/apigateway_deployment.yml
@@ -0,0 +1,52 @@
+{{- if .Values.apigatwayEnabled }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ template "apigateway_service_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: {{ template "apigateway_service_name" . }}
+spec:
+  selector:
+    name: {{ template "apigateway_deployment_name" . }}
+  ports:
+    - port: {{ template "apigateway_mgmt_port" . }}
+      targetPort: {{ template "apigateway_mgmt_port" . }}
+      name: mgmt
+    - port: {{ template "apigateway_api_port" . }}
+      targetPort: {{ template "apigateway_api_port" . }}
+      name: api
+
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: {{ template "apigateway_deployment_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: {{ template "apigateway_deployment_name" . }}
+spec:
+  replicas: {{ .Values.apigatewayReplicaCount | default 1 }}
+  template:
+    metadata:
+      labels:
+        name: {{ template "apigateway_deployment_name" . }}
+    spec:
+      restartPolicy: Always
+
+      containers:
+      - name: apigateway
+        imagePullPolicy: {{ .Values.apigatewayImagePullPolicy | default "IfNotPresent" | quote }}
+        image: {{ .Values.apigatewayImage | default "openwhisk/apigateway" | quote }}
+        ports:
+        - name: mgmt
+          containerPort: {{ template "apigateway_mgmt_port" . }}
+        - name: api
+          containerPort: {{ template "apigateway_api_port" . }}
+        env:
+        - name: "REDIS_HOST"
+          value: {{ include "redis_url" . | quote }}
+        - name: "REDIS_PORT"
+          value: {{ .Values.global.redisPort | default "6379" | quote }}
+{{ end }}
diff --git a/helm/templates/controller_statefulset.yml b/helm/templates/controller_statefulset.yml
new file mode 100644
index 0000000..ed47c8e
--- /dev/null
+++ b/helm/templates/controller_statefulset.yml
@@ -0,0 +1,153 @@
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ template "controller_service_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: {{ template "controller_service_name" . }}
+spec:
+  selector:
+    name: {{ template "controller_statefulset_name" . }}
+  clusterIP: None
+  ports:
+    - port: {{ template "controller_port" . }}
+      targetPort: {{ template "controller_port" . }}
+      name: http
+---
+apiVersion: apps/v1beta1
+kind: StatefulSet
+metadata:
+  name: {{ template "controller_statefulset_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: {{ template "controller_statefulset_name" . }} 
+spec:
+  replicas: {{ .Values.global.controllerReplicaCount | default 2 }}
+  serviceName: {{ template "controller_service_name" . }}
+  template:
+    metadata:
+      labels:
+        name: {{ template "controller_statefulset_name" . }}
+    spec:
+      restartPolicy: Always
+
+      {{- if .Values.global.affinity.enabled }}
+      affinity:
+        nodeAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+            nodeSelectorTerms:
+            - matchExpressions:
+              - key: nodeType
+                operator: In
+                values:
+                - {{ .Values.global.affinity.controllerNodeLabel }}
+        podAntiAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+          - labelSelector:
+              matchExpressions:
+              - key: name
+                operator: In
+                values:
+                - {{ template "controller_statefulset_name" . }}
+            topologyKey: "kubernetes.io/hostname"
+      {{- end }}
+
+      initContainers:
+      - name: "wait-for-kafka"
+        image: "busybox"
+        imagePullPolicy: "IfNotPresent"
+        command: ["sh", "-c", "result=1; until [ $result -eq 0 ]; do nslookup {{ .Values.global.kafkaServiceName}}.{{ .Release.Namespace }}; result=$?; echo waiting for {{ .Values.global.kafkaServiceName}}.{{ .Release.Namespace }}; sleep 1; done;"]
+
+      containers:
+      - name: {{ template "controller_statefulset_name" . }}
+        imagePullPolicy: {{ .Values.controllerImagePullPolicy | default "IfNotPresent" | quote }}
+        image: {{ .Values.controllerImage | default "openwhisk/controller" | quote }}
+        command: ["/bin/bash", "-c", "COMPONENT_NAME=$(hostname | cut -d'-' -f2) /init.sh `hostname | cut -d'-' -f2`"]
+        ports:
+        - name: controller
+          containerPort: {{ template "controller_port" . }}
+        livenessProbe:
+          httpGet:
+            path: "/ping"
+            port: {{ template "controller_port" . }}
+            scheme: "HTTP"
+          initialDelaySeconds: 5
+          periodSeconds: 10
+          timeoutSeconds: 1
+        env:
+        - name: "PORT"
+          value: {{ include "controller_port" . | quote }}
+
+        # Loadbalancer options
+        - name: "LOADBALANCER_INVOKERBUSYTHRESHOLD"
+          value: "16"
+
+        # This needs to stay up to date with the lates runtime in Ansible Groupvars
+        - name: "RUNTIMES_MANIFEST"
+          value: '{ "defaultImagePrefix": "openwhisk", "defaultImageTag": "latest", "runtimes": { "nodejs": [ { "kind": "nodejs", "image": { "name": "nodejsaction" }, "deprecated": true }, { "kind": "nodejs:6", "default": true, "image": { "name": "nodejs6action" }, "deprecated": false } ], "python": [ { "kind": "python", "image": { "name": "python2action" }, "deprecated": false }, { "kind": "python:2", "default": true, "image": { "name": "python2action" }, "deprecated": false }, { "kind": "python:3", "image": { "name": "python3action" }, "deprecated": false } ], "swift": [ { "kind": "swift", "image": { "name": "swiftaction" }, "deprecated": true }, { "kind": "swift:3", "image": { "name": "swift3action" }, "deprecated": false }, { "kind": "swift:3.1.1", "default": true, "image": { "name": "action-swift-v3.1.1" }, "deprecated": false } ], "java": [ { "kind": "java", "default": true, "image": { "name": "java8action" }, "deprecated": false, "attached": { "attachmentName": "jarfile", "attachmentType": "application/java-archive" }, "sentinelledLogs": false, "requireMain": true } ] }, "blackboxes": [ { "name": "dockerskeleton" } ] }'
+
+        # this version is the day it is deployed and should be configured every time
+        - name:  "WHISK_VERSION_DATE"
+          value: "2017-01-01T00:00:00Z"
+        # the buildno should be the docker image tag to use
+        - name: "WHISK_VERSION_BUILDNO"
+          value: "latest"
+        - name: "WHISK_VERSION_NAME"
+          value: ""
+
+        # Java options
+        - name: "JAVA_OPTS"
+          value: "-Xmx2g"
+
+        # Kafka properties
+        - name: "KAFKA_HOSTS"
+          value: {{ include "kafka_url_without_port" . }}:{{ .Values.global.kafkaPort | default 9092 }}
+        - name: "KAFKA_HOST_PORT"
+          value: {{ .Values.global.kafkaPort | default 9092 | quote }}
+
+        # specific controller arguments
+        - name: "CONTROLLER_OPTS"
+          value: ""
+
+        # properties for DB connection
+        - name: "CONFIG_whisk_couchdb_username"
+          value: {{ template "couchdb_username" . }}
+        - name: "CONFIG_whisk_couchdb_password"
+          value: {{ template "couchdb_password" . }}
+        - name: "CONFIG_whisk_couchdb_port"
+          value: {{ include "couchdb_port" . | quote}}
+        - name: "CONFIG_whisk_couchdb_protocol"
+          value: "http"
+        - name: "CONFIG_whisk_couchdb_host"
+          value: {{ include "couchdb_url_without_port" . | quote }} 
+        - name: "CONFIG_whisk_couchdb_provider"
+          value: "CouchDB"
+        - name: "CONFIG_whisk_couchdb_databases_WhiskActivation"
+          value: {{ template "activations_table" . }}
+        - name: "CONFIG_whisk_couchdb_databases_WhiskEntity"
+          value: {{ template "actions_table" . }}
+        - name: "CONFIG_whisk_couchdb_databases_WhiskAuth"
+          value: {{ template "auths_table" . }}
+
+        - name: "LIMITS_ACTIONS_SEQUENCE_MAXLENGTH"
+          value: {{ .Values.controllerLimitsActionsSequenceMaxlength | default 1000 | quote }}
+        - name: "LIMITS_TRIGGERS_FIRES_PERMINUTE"
+          value: {{ .Values.controllerLimitsTriggersFiresPerminute | default 100 | quote }}
+        - name: "LIMITS_ACTIONS_INVOKES_PERMINUTE"
+          value: {{ .Values.controllerLimitsActionsInvokesPerminute | default 100 | quote }}
+        - name: "LIMITS_ACTIONS_INVOKES_CONCURRENTINSYSTEM"
+          value: {{ .Values.controllerLimitsActionsInvokesConcurrentinsystem | default 100 | quote }}
+        - name: "LIMITS_ACTIONS_INVOKES_CONCURRENT"
+          value: {{ .Values.controllerLimitsActionsInvokesConcurrent | default 100 | quote }}
+
+        - name: "CONTROLLER_INSTANCES"
+          value: {{ .Values.global.controllerReplicaCount | default 2 | quote }}
+        - name: "CONTROLLER_LOCALBOOKKEEPING"
+          value: {{ .Values.controllerLocalbookkeeping | default false | quote }}
+        - name: "AKKA_CLUSTER_SEED_NODES"
+          value: {{ .Values.controllerSeedNodes | default "[]" | quote }}
+        - name: "CONTROLLER_HA"
+          value: {{ .Values.controllerHA | default false | quote }}
+        - name: "CONFIG_akka_actor_provider"
+          value: "cluster"
diff --git a/helm/templates/invoker_deployment.yml b/helm/templates/invoker_deployment.yml
new file mode 100644
index 0000000..d749bc1
--- /dev/null
+++ b/helm/templates/invoker_deployment.yml
@@ -0,0 +1,151 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: {{ template "invoker_statefulset_name" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    name: {{ template "invoker_statefulset_name" . }} 
+spec:
+  replicas: {{ .Values.invokerReplicasetCount | default 2 }}
+  #serviceName: {{ template "invoker_statefulset_name" . }}
+  template:
+    metadata:
+      labels:
+        name: {{ template "invoker_statefulset_name" . }}
+    spec:
+      restartPolicy: Always
+
+      volumes:
+      - name: cgroup
+        hostPath:
+          path: "/sys/fs/cgroup"
+      - name: runc
+        hostPath:
+          path: "/run/runc"
+      - name: dockerrootdir
+        hostPath:
+          path: "/var/lib/docker/containers"
+      - name: dockersock
+        hostPath:
+          path: "/var/run/docker.sock"
+      - name: apparmor
+        hostPath:
+          path: "/usr/lib/x86_64-linux-gnu/libapparmor.so.1"
+
+      {{- if .Values.global.affinity.enabled }}
+      affinity:
+        nodeAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+            nodeSelectorTerms:
+            - matchExpressions:
+              - key: nodeType
+                operator: In
+                values:
+                - {{ .Values.global.affinity.invokerNodeLabel }}
+        podAntiAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+            - labelSelector:
+                matchExpressions:
+                - key: name
+                  operator: In
+                  values:
+                  - {{ template "invoker_statefulset_name" . }}
+              topologyKey: "kubernetes.io/hostname"
+      {{- end }}
+     
+      initContainers: 
+      - name: "wait-for-kafka"
+        image: "busybox"
+        imagePullPolicy: "IfNotPresent"
+        command: ["sh", "-c", "result=1; until [ $result -eq 0 ]; do nslookup {{ .Values.global.kafkaServiceName}}.{{ .Release.Namespace }}; result=$?; echo waiting for {{ .Values.global.kafkaServiceName}}.{{ .Release.Namespace }}; sleep 1; done;"]
+
+      containers:
+      - name: {{ template "invoker_statefulset_name" . }}
+        imagePullPolicy: {{ .Values.invokerImagePullPolicy | default "IfNotPresent" | quote }}
+        image: {{ .Values.invokerImage | default "openwhisk/invoker" | quote }}
+        command: [ "/bin/bash", "-c", "COMPONENT_NAME=$(hostname | cut -d'-' -f2) /init.sh"]
+        resources:
+          requests:
+            memory: "100Mi"
+            cpu: "0.1"
+        env:
+          - name: "PORT"
+            value: "8080"
+          - name: "WHISK_API_HOST_NAME"
+            value: "nginx.openwhisk"
+          - name: "INVOKER_CONTAINER_NETWORK"
+            value: "bridge"
+          - name: "INVOKER_USE_RUNC"
+            value: "false"
+
+          # Properties for invoker image
+          - name: "DOCKER_IMAGE_PREFIX"
+            value: "openwhisk"
+          - name: "DOCKER_IMAGE_TAG"
+            value: "latest"
+          - name: "DOCKER_REGISTRY"
+            value: ""
+
+          - name: "INVOKER_NAME"
+            valueFrom:
+              fieldRef:
+                fieldPath: metadata.name
+
+          # Java options
+          - name: "JAVA_OPTS"
+            value: "-Xmx2g"
+
+          # Invoker options
+          - name: "INVOKER_OPTS"
+            value: {{ .Values.invokerOptions | quote }}
+
+          # This property can change since it is generated via Ansible GroupVars
+          - name: "RUNTIMES_MANIFEST"
+            value: '{ "defaultImagePrefix": "openwhisk", "defaultImageTag": "latest", "runtimes": { "nodejs": [ { "kind": "nodejs", "image": { "name": "nodejsaction" }, "deprecated": true }, { "kind": "nodejs:6", "default": true, "image": { "name": "nodejs6action" }, "deprecated": false } ], "python": [ { "kind": "python", "image": { "name": "python2action" }, "deprecated": false }, { "kind": "python:2", "default": true, "image": { "name": "python2action" }, "deprecated": false }, { "kind": "python:3", "image": { "name": "python3action" }, "deprecated": false } ], "swift": [ { "kind": "swift", "image": { "name": "swiftaction" }, "deprecated": true }, { "kind": "swift:3", "image": { "name": "swift3action" }, "deprecated": false }, { "kind": "swift:3.1.1", "default": true, "image": { "name": "action-swift-v3.1.1" }, "deprecated": false } ], "java": [ { "kind": "java", "default": true, "image": { "name": "java8action" }, "deprecated": false, "attached": { "attachmentName": "jarfile", "attachmentType": "application/java-archive" }, "sentinelledLogs": false, "requireMain": true } ] }, "blackboxes": [ { "name": "dockerskeleton" } ] }'
+
+          # Default to empty logs dir. This is because logs should go to stdout
+          - name: "WHISK_LOGS_DIR"
+            value: ""
+
+          # this version is the day it is deployed,
+          - name:  "WHISK_VERSION_DATE"
+            value: "2017-01-01T00:00:00Z"
+
+          # properties for DB connection
+          - name: "CONFIG_whisk_couchdb_username"
+            value: {{ template "couchdb_username" . }}
+          - name: "CONFIG_whisk_couchdb_password"
+            value: {{ template "couchdb_password" . }} 
+          - name: "CONFIG_whisk_couchdb_port"
+            value: {{ include "couchdb_port" . | quote }}
+          - name:  "CONFIG_whisk_couchdb_protocol"
+            value: "http"
+          - name: "CONFIG_whisk_couchdb_host"
+            value: {{ include "couchdb_url_without_port" . | quote }}
+          - name: "CONFIG_whisk_couchdb_provider"
+            value: "CouchDB"
+          - name: "CONFIG_whisk_couchdb_databases_WhiskActivation"
+            value: {{ template "activations_table" . }}
+          - name: "CONFIG_whisk_couchdb_databases_WhiskEntity"
+            value: {{ template "actions_table" . }}
+          - name: "CONFIG_whisk_couchdb_databases_WhiskAuth"
+            value: {{ template "auths_table" . }}
+          - name: "KAFKA_HOSTS"
+            value: "{{ .Values.global.kafkaServiceName }}.{{ .Release.Namespace }}:{{ .Values.global.kafkaPort | default 9092 }}"
+          - name: "ZOOKEEPER_HOSTS"
+            value: "{{ .Values.global.zookeeperServiceName }}.{{ .Release.Namespace }}:{{ .Values.global.zookeeperPort | default 2181 }}"
+
+        ports:
+        - name: invoker
+          containerPort: 8080
+        volumeMounts:
+        - name: cgroup
+          mountPath: "/sys/fs/cgroup"
+        - name: runc
+          mountPath: "/run/runc"
+        - name: dockersock
+          mountPath: "/var/run/docker.sock"
+        - name: dockerrootdir
+          mountPath: "/containers"
+        - name: apparmor
+          mountPath: "/usr/lib/x86_64-linux-gnu/libapparmor.so.1"
diff --git a/helm/values.yaml b/helm/values.yaml
new file mode 100644
index 0000000..2928e06
--- /dev/null
+++ b/helm/values.yaml
@@ -0,0 +1,113 @@
+# Default values for OpenWhisk.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+# zookeeper configurations
+zookeeper:
+  deploymentName: "zookeeper"
+  replicaCount: 1
+  restartPolicy: "Always"
+  containerName: "zookeeper"
+  image: "zookeeper:3.4"
+  imagePullPolicy: "IfNotPresent"
+  serverPort: 2888
+  leaderElectionPort: 3888
+
+# kafka configurations
+kafka:
+  statefulsetName: "kafka"
+  replicaCount: 1
+  image: "wurstmeister/kafka:0.11.0.1"
+  imagePullPolicy: "IfNotPresent"
+
+# Couchdb configurations
+couchdb:
+  deploymentName: "couchdb"
+  replicaCount: 1  
+  imagePullPolicy: "IfNotPresent"
+  image: "openwhisk/kube-couchdb"
+  dbPrefix: "test_"
+  persistence:
+    enabled: false
+    pvcName: couchdb-pvc
+    size: 8Gi
+    storageClass: CouchDBSC 
+    accessMode: ReadWriteOnce
+    # nfs_path: /home/nfs
+    # nfs_server: 172.20.5.175
+
+
+# Nginx configurations
+nginx:
+  secretName: "nginx"
+  configmapName: "nginx"
+  deploymentName: "nginx"
+  replicaCount: 1
+  image: "nginx:1.11"
+  imagePullPolicy: "IfNotPresent"
+  httpPort: 80
+  httpNodePort: 30000
+  httpsPort: 443
+  httpsNodePort: 30001
+  httpsAdminPort: 8443
+  httpsAdminNodePort: 30002
+  serviceName: "nginx"
+
+
+# Redis configurations
+redis:
+  deploymentName: "redis"
+  replicaCount: 1
+  image: redis:3.2
+  imagePullPolicy: "IfNotPresent"
+
+# Controller configurations
+controllerImagePullPolicy: "IfNotPresent"
+controllerImage: "openwhisk/controller" 
+controllerLimitsActionsInvokesConcurrentinsystem: 100
+controllerLimitsTriggersFiresPerminute: 100
+controllerLimitsActionsSequenceMaxlength: 1000
+controllerLimitsActionsInvokesConcurrent: 100
+controllerLimitsActionsInvokesConcurrentinsystem: 100
+controllerLocalbookkeeping: true
+controllerSeedNodes: "[]"
+controllerHA: false
+
+# Invoker configurations
+invokerStatefulsetName: "invoker"
+invokerReplicasetCount: 1
+invokerImagePullPolicy: "IfNotPresent"
+invokerImage: "openwhisk/invoker"
+invokerOptions: ""
+
+# API Gateway configurations
+apigatewayEnabled: false
+apigatewayReplicaCount: 1
+
+activationsTable: "test_activations"
+actionsTable: "test_whisks"
+authsTable: "test_subjects"
+
+# Global configurations
+global:
+  zookeeperServiceName: "zookeeper"
+  kafkaServiceName: "kafka"
+  zookeeperPort: 2181
+  kafkaPort: 9092
+  couchdbServiceName: "couchdb"
+  couchdbInstances: 1
+  couchdbPort: 5984
+  controllerStatefulSetName: "controller"
+  controllerServiceName: "controller"
+  controllerPort: 8080
+  controllerReplicaCount: 1
+  couchdbUserName: "whisk_admin"
+  couchdbPassword: "some_passw0rd"
+  redisServiceName: "redis"
+  redisServicePort: 6379
+  # Resolve the pod/node affinity for invoker, controller and other components.
+  affinity:
+    enabled: false
+    invokerNodeLabel: invoker
+    controllerNodeLabel: controller
+    kafkaNodeLabel: kafka


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services