You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by gr...@apache.org on 2019/06/12 20:30:32 UTC

[kudu] branch master updated: KUDU-2834: Build Kudu Kubernetes cluster using Helm chart

This is an automated email from the ASF dual-hosted git repository.

granthenke pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git


The following commit(s) were added to refs/heads/master by this push:
     new ad79839  KUDU-2834: Build Kudu Kubernetes cluster using Helm chart
ad79839 is described below

commit ad798391fdf22c1632a641dbb6be80085636602a
Author: SandishKumarHN <sa...@gmail.com>
AuthorDate: Sat Jun 8 14:32:16 2019 -0700

    KUDU-2834: Build Kudu Kubernetes cluster using Helm chart
    
    Helm is a package manager for Kubernetes. Helps to define, install,
    and upgrade Kubernetes applications.
    
    Change-Id: I9f839b690322fc349a566ee643d39f039f72ffa6
    Reviewed-on: http://gerrit.cloudera.org:8080/13568
    Reviewed-by: Grant Henke <gr...@apache.org>
    Tested-by: Grant Henke <gr...@apache.org>
---
 docker/kudu-entrypoint.sh                          |   2 +-
 kubernetes/README.adoc                             | 105 ++++++++++
 kubernetes/helm/README.adoc                        | 111 ++++++++++
 kubernetes/helm/kudu-expose-all.yaml               |  31 +++
 kubernetes/helm/kudu-rolebinding.yaml              |  37 ++++
 kubernetes/helm/kudu/Chart.yaml                    |  27 +++
 kubernetes/helm/kudu/templates/_helmutils.tpl      |  74 +++++++
 kubernetes/helm/kudu/templates/kudu-service.yaml   | 232 +++++++++++++++++++++
 .../helm/kudu/templates/tests/health-test.yaml     |  46 ++++
 kubernetes/helm/kudu/values.yaml                   | 100 +++++++++
 kubernetes/kudu-services.yaml                      |  75 +++++++
 kubernetes/kudu-statefulset.yaml                   |  69 +-----
 kubernetes/namespace.yaml                          |  23 ++
 13 files changed, 869 insertions(+), 63 deletions(-)

diff --git a/docker/kudu-entrypoint.sh b/docker/kudu-entrypoint.sh
index e330180..ea13f5d 100755
--- a/docker/kudu-entrypoint.sh
+++ b/docker/kudu-entrypoint.sh
@@ -77,7 +77,7 @@ function wait_for_master_hosts() {
     ATTEMPTS=0
     until `ping -c1 "$HOST" &>/dev/null;` || [[ "$ATTEMPTS" -eq "$MAX_ATTEMPTS" ]]; do
       ATTEMPTS=$((ATTEMPTS + 1))
-      sleep 1;
+      sleep 2;
     done
   done
   unset IFS
diff --git a/kubernetes/README.adoc b/kubernetes/README.adoc
new file mode 100644
index 0000000..0d9cec4
--- /dev/null
+++ b/kubernetes/README.adoc
@@ -0,0 +1,105 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+= Building Kubernetes StatefulSet Kudu Cluster
+
+NOTE: All of this work is experimental and subject to change or removal.
+
+== Getting Started
+
+Kubernetes — container-orchestration system for automating application deployment, scaling, and management.
+
+NOTE: Read more about Kubernetes here https://kubernetes.io/docs/tutorials/kubernetes-basics/
+
+==== System Requirements
+
+    kubectl
+    minikube or kubeadm
+    docker
+
+==== Build Kudu Docker Image
+
+    ../../docker/docker-build.sh
+
+==== Creating Namespace
+
+    kubectl create -f ../namespace.yaml
+
+=== Create Services for Kudu Masters and Kudu TServers
+
+    kubectl create -f kudu-services.yaml
+
+Check status of kudu services:
+
+    kubectl get services -n apache-kudu
+
+You should see below output on stdout
+
+```
+NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
+kudu-master-ui   NodePort    10.110.150.101   <none>        8051:30082/TCP      8m2s
+kudu-masters     ClusterIP   None             <none>        8051/TCP,8050/TCP   8m2s
+kudu-tservers    ClusterIP   None             <none>        7050/TCP,7051/TCP   8m2s
+tiller-deploy    ClusterIP   10.96.104.11     <none>        44134/TCP           47h
+```
+
+=== Create StatefulSet for Kudu Masters and Kudu TServers
+
+    kubectl create -f kudu-statefulset.yaml
+
+Check status of kudu statefulset:
+
+    kubectl get statefulset -n apache-kudu
+
+    kubectl get pods -n apache-kudu
+
+You should see below output on stdout
+
+```
+NAME           READY   AGE
+kudu-master    2/3     16s
+kudu-tserver   3/3     16s
+
+
+NAME                             READY   STATUS    RESTARTS   AGE
+kudu-master-0                    1/1     Running   0          9m9s
+kudu-master-1                    1/1     Running   0          9m9s
+kudu-master-2                    1/1     Running   0          9m9s
+kudu-tserver-0                   1/1     Running   0          9m19s
+kudu-tserver-1                   1/1     Running   0          9m5s
+kudu-tserver-2                   1/1     Running   0          9m5s
+```
+
+==== Port Forward The Kudu Master UI
+
+    kubectl port-forward kudu-master-0 8051 -n apache-kudu
+    OR
+    minikube service kudu-master-ui --url -n apache-kudu
+
+==== Destroy The Kudu Cluster
+
+Destroy Services:
+
+    kubectl delete -f kudu-services.yaml
+
+Destroy StatefulSets:
+
+    kubectl delete -f kudu-statefulset.yaml
+
+==== Display Kudu Master Logs:
+
+    kubectl logs kudu-master-0 --namespace apache-kudu
diff --git a/kubernetes/helm/README.adoc b/kubernetes/helm/README.adoc
new file mode 100644
index 0000000..f1311c8
--- /dev/null
+++ b/kubernetes/helm/README.adoc
@@ -0,0 +1,111 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+= Building Kubernetes Kudu Cluster Using Helm Chart
+
+NOTE: All of this work is experimental and subject to change or removal.
+
+== Getting Started
+
+Helm — The package manager for Kubernetes. Helps to define, install, and upgrade Kubernetes applications
+
+NOTE: Read more about Helm here https://helm.sh/docs/using_helm/#quickstart
+
+==== System Requirements
+
+    kubectl
+    minikube or kubeadm
+    docker
+    helm
+
+==== Build Kudu Docker Image
+
+    ../../docker/docker-build.sh
+
+==== Creating Namespace
+
+    kubectl create -f ../namespace.yaml
+
+==== Creating ServiceAccount And Role Binding (RBAC)
+
+    kubectl create -f kudu-rbac.yaml
+
+==== Initializing Helm Tiller
+
+    helm init --service-account kudu-helm --tiller-namespace apache-kudu --upgrade --wait
+
+Check if tiller is initialized and you should not see any authorization errors.
+
+    helm ls --namespace apache-kudu --tiller-namespace apache-kudu
+
+==== Helm Launch Kudu cluster
+
+    helm install kudu --namespace apache-kudu --name apache-kudu --tiller-namespace apache-kudu --wait
+
+    helm install kudu -f kudu-expose-all.yaml --namespace apache-kudu --name apache-kudu --tiller-namespace apache-kudu --wait
+
+You should see below output on stdout
+
+```
+NAME:   apache-kudu
+LAST DEPLOYED: Fri Jun  7 12:03:47 2019
+NAMESPACE: apache-kudu
+STATUS: DEPLOYED
+
+RESOURCES:
+==> v1/Pod(related)
+NAME            READY  STATUS   RESTARTS  AGE
+kudu-master-0   1/1    Running  0         12s
+kudu-master-1   1/1    Running  0         12s
+kudu-master-2   1/1    Running  0         12s
+kudu-tserver-0  1/1    Running  0         12s
+kudu-tserver-1  1/1    Running  0         12s
+
+==> v1/Service
+NAME                  TYPE       CLUSTER-IP     EXTERNAL-IP  PORT(S)                        AGE
+kudu-master-service   NodePort   10.100.28.117  <none>       8051:31198/TCP,8050:31182/TCP  12s
+kudu-masters          ClusterIP  None           <none>       8051/TCP,8050/TCP              12s
+kudu-tserver-service  NodePort   10.103.171.31  <none>       7051:30967/TCP,7050:32543/TCP  12s
+kudu-tservers         ClusterIP  None           <none>       7051/TCP,7050/TCP              12s
+
+==> v1/StatefulSet
+NAME          READY  AGE
+kudu-master   3/3    12s
+kudu-tserver  2/2    12s
+
+==> v1beta1/PodDisruptionBudget
+NAME              MIN AVAILABLE  MAX UNAVAILABLE  ALLOWED DISRUPTIONS  AGE
+kudu-tserver-pdb  N/A            1                1                    12s
+```
+
+==== Port Forward The Kudu Master UI
+
+    kubectl port-forward kudu-master-0 8051 -n apache-kudu
+    OR
+    minikube service kudu-master-service --url -n apache-kudu
+
+==== Destroy The Kudu Cluster
+
+    helm del --purge apache-kudu --tiller-namespace apache-kudu
+
+==== Display Kudu Master Logs:
+
+    kubectl logs kudu-master-0 --namespace apache-kudu
+
+==== Running Helm Test for Kudu HealthCheck
+
+    helm test apache-kudu --tiller-namespace apache-kudu
\ No newline at end of file
diff --git a/kubernetes/helm/kudu-expose-all.yaml b/kubernetes/helm/kudu-expose-all.yaml
new file mode 100644
index 0000000..3f3edc1
--- /dev/null
+++ b/kubernetes/helm/kudu-expose-all.yaml
@@ -0,0 +1,31 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+serviceEndpoints:
+  - name: "kudu-master-service"
+    type: NodePort
+    app: "kudu-master"
+    ports:
+      ui: "8050"
+      rpc-port: "8051"
+
+  - name: "kudu-tserver-service"
+    type: NodePort
+    app: "kudu-tserver"
+    ports:
+      ui: "7050"
+      rpc-port: "7051"
diff --git a/kubernetes/helm/kudu-rolebinding.yaml b/kubernetes/helm/kudu-rolebinding.yaml
new file mode 100644
index 0000000..b0dda8b
--- /dev/null
+++ b/kubernetes/helm/kudu-rolebinding.yaml
@@ -0,0 +1,37 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Role-based access control (RBAC) definitions.
+
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: kudu-helm
+  namespace: apache-kudu
+---
+apiVersion: rbac.authorization.k8s.io/v1beta1
+kind: ClusterRoleBinding
+metadata:
+  name: kudu-helm
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: cluster-admin
+subjects:
+  - kind: ServiceAccount
+    name: kudu-helm
+    namespace: apache-kudu
diff --git a/kubernetes/helm/kudu/Chart.yaml b/kubernetes/helm/kudu/Chart.yaml
new file mode 100644
index 0000000..b0e3153
--- /dev/null
+++ b/kubernetes/helm/kudu/Chart.yaml
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Helm Chart Definitions.
+apiVersion: v1
+description: Apache Kudu, A new addition to the open source Apache Hadoop ecosystem, Apache Kudu completes Hadoop's
+             storage layer to enable fast analytics on fast data.
+name: kudu
+version:  latest
+keywords: [apache, kudu, apache-kudu]
+sources: [https://github.com/apache/kudu]
+home: https://kudu.apache.org/
+icon: https://raw.githubusercontent.com/apache/kudu/master/www/logo.png
diff --git a/kubernetes/helm/kudu/templates/_helmutils.tpl b/kubernetes/helm/kudu/templates/_helmutils.tpl
new file mode 100644
index 0000000..7ec2665
--- /dev/null
+++ b/kubernetes/helm/kudu/templates/_helmutils.tpl
@@ -0,0 +1,74 @@
+{{/*
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+*/}}
+
+{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "kudu.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "kudu.fullname" -}}
+{{- if .Values.fullnameOverride -}}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- if contains $name .Release.Name -}}
+{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "kudu.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+  Generate Kudu Masters String
+*/}}
+{{- define "kudu.gen_kudu_masters" -}}
+{{- $master_replicas := .Values.replicas.master | int -}}
+{{- $domain_name := .Values.domainName -}}
+  {{- range .Values.Services }}
+    {{- if eq .name "kudu-masters" }}
+      {{range $index := until $master_replicas }}{{if ne $index 0}},{{end}}kudu-master-{{ $index }}.kudu-masters.$(NAMESPACE).svc.{{ $domain_name }}{{end}}
+    {{- end -}}
+  {{- end -}}
+{{- end -}}
+
+{{/*
+Generate the maximum number of fail-over pods based on master replicas
+Ensures that the number of replicas running is never brought below the number needed for a quorum.
+*/}}
+{{- define "kudu.max_failovers" -}}
+{{- $master_replicas := .Values.replicas.master | int | mul 100 -}}
+{{- $master_replicas := 100 | div (100 | sub (2 | div ($master_replicas | add 100))) -}}
+{{- printf "%d" $master_replicas -}}
+{{- end -}}
diff --git a/kubernetes/helm/kudu/templates/kudu-service.yaml b/kubernetes/helm/kudu/templates/kudu-service.yaml
new file mode 100644
index 0000000..a49ac60
--- /dev/null
+++ b/kubernetes/helm/kudu/templates/kudu-service.yaml
@@ -0,0 +1,232 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+{{- $head := . -}}
+---
+{{- range .Values.Services }}
+{{- $service := . -}}
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: "{{ .name }}"
+  namespace: "{{ $head.Release.Namespace }}"
+  labels:
+    app: "{{ .label }}"
+    heritage: {{ $head.Release.Service | quote }}
+    release: {{ $head.Release.Name | quote }}
+    chart: "{{ $head.Chart.Name }}-{{ $head.Chart.Version }}"
+    component: "{{ $head.Values.Component }}"
+spec:
+  clusterIP: None
+  ports:
+    {{- range $label, $port := .ports }}
+    - name: {{ $label | quote }}
+      port: {{ $port }}
+    {{- end}}
+  selector:
+    app: "{{ .label }}"
+
+{{ if $head.Values.enableNodePort }}
+{{- range $endpoint :=  $head.Values.serviceEndpoints }}
+{{- if eq $service.label $endpoint.app }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: "{{ $endpoint.name }}"
+  namespace: "{{ $head.Release.Namespace }}"
+  annotations:
+{{ toYaml $endpoint.annotations | indent 4 }}
+  labels:
+    app: "{{ $endpoint.app }}"
+    heritage: {{ $head.Release.Service | quote }}
+    release: {{ $head.Release.Name | quote }}
+    chart: "{{ $head.Chart.Name }}-{{ $head.Chart.Version }}"
+    component: "{{ $head.Values.Component }}"
+spec:
+  clusterIP:
+  ports:
+    {{- range $label, $port := $endpoint.ports }}
+    - name: {{ $label | quote }}
+      port: {{ $port }}
+    {{- end}}
+  selector:
+    app: "{{ $endpoint.app }}"
+  type: {{ $endpoint.type }}
+{{- end}}
+{{- end}}
+{{ end }}
+
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: "{{ .label }}"
+  namespace: "{{ $head.Release.Namespace }}"
+  labels:
+    app: "{{ .label }}"
+    heritage: {{ $head.Release.Service | quote }}
+    release: {{ $head.Release.Name | quote }}
+    chart: "{{ $head.Chart.Name }}-{{ $head.Chart.Version }}"
+    component: "{{ $head.Values.Component }}"
+spec:
+  serviceName: "{{ .name }}"
+  podManagementPolicy: {{ $head.Values.PodManagementPolicy }}
+  {{ if eq .name "kudu-masters" }}
+  replicas: {{ $head.Values.replicas.master }}
+  {{ else }}
+  replicas: {{ $head.Values.replicas.tserver  }}
+  {{ end }}
+  volumeClaimTemplates:
+    {{- $storageInfo := (eq .name "kudu-masters") | ternary $head.Values.storage.master $head.Values.storage.tserver -}}
+    {{- range $i := until (int ($storageInfo.count )) }}
+    - metadata:
+        name: datadir{{ $i }}
+        annotations:
+          volume.beta.kubernetes.io/storage-class: {{ $storageInfo.storageClass }}
+        labels:
+          heritage: {{ $head.Release.Service | quote }}
+          release: {{ $head.Release.Name | quote }}
+          chart: "{{ $head.Chart.Name }}-{{ $head.Chart.Version }}"
+          component: "{{ $head.Values.Component }}"
+      spec:
+        accessModes:
+          - "ReadWriteOnce"
+        {{- if $storageInfo.storageClass }}
+        storageClassName: {{ $storageInfo.storageClass }}
+        {{- end }}
+        resources:
+          requests:
+            storage: {{ $storageInfo.size }}
+    {{- end }}
+  updateStrategy:
+    type: RollingUpdate
+    rollingUpdate:
+      {{ if eq .name "kudu-masters" }}
+      partition: {{ $head.Values.partition.master }}
+      {{ else }}
+      partition: {{ $head.Values.partition.tserver }}
+      {{ end }}
+  selector:
+    matchLabels:
+      app: "{{ .label }}"
+  template:
+    metadata:
+      {{ if $head.Values.networkAnnotation }}
+      annotations:
+{{ toYaml $head.Values.networkAnnotation | indent 8}}
+      {{ end }}
+      labels:
+        app: "{{ .label }}"
+        heritage: {{ $head.Release.Service | quote }}
+        release: {{ $head.Release.Name | quote }}
+        chart: "{{ $head.Chart.Name }}-{{ $head.Chart.Version }}"
+        component: "{{ $head.Values.Component }}"
+    spec:
+      {{- if $head.Values.Image.pullSecretName }}
+      imagePullSecrets:
+      - name: {{ $head.Values.Image.pullSecretName }}
+      {{ end }}
+      {{- if $head.Values.nodeSelector }}
+      nodeSelector:
+      {{ toYaml $head.Values.nodeSelector | indent 8 }}
+      {{- end }}
+      containers:
+      - name: "{{ .label }}"
+        image: "{{ $head.Values.Image.repository }}:{{ $head.Values.Image.tag }}"
+        imagePullPolicy: {{ $head.Values.Image.pullPolicy }}
+        env:
+        - name: POD_IP
+          valueFrom:
+            fieldRef:
+              fieldPath: status.podIP
+        - name: HOSTNAME
+          valueFrom:
+            fieldRef:
+              fieldPath: metadata.name
+        - name: NAMESPACE
+          valueFrom:
+            fieldRef:
+              fieldPath: metadata.namespace
+        - name: KUDU_MASTERS
+          value: "{{ include "kudu.gen_kudu_masters" $head | trim }}"
+        resources:
+        {{ if eq .name "kudu-masters" }}
+{{ toYaml $head.Values.resource.master | indent 10 }}
+        {{ else }}
+{{ toYaml $head.Values.resource.tserver | indent 10 }}
+        {{ end }}
+        args:
+        {{ if eq .name "kudu-masters" }}
+          - "master"
+        {{ else }}
+          - "tserver"
+        {{ end }}
+        ports:
+          {{- range $label, $port := .ports }}
+          - containerPort: {{ $port }}
+            name: {{ $label | quote }}
+          {{- end}}
+        volumeMounts:
+          {{- range $i := until (int ($storageInfo.count)) }}
+          - name: datadir{{ $i }}
+            mountPath: /mnt/disk{{ $i }}
+          {{- end }}
+      volumes:
+        {{- range $i := until (int ($storageInfo.count)) }}
+        - name: datadir{{ $i }}
+          hostPath:
+            path: /mnt/disks/ssd{{ $i }}
+        {{- end }}
+      affinity:
+        {{ if $head.Values.AZ }}
+        nodeAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+            nodeSelectorTerms:
+              - matchExpressions:
+                  - key: failure-domain.beta.kubernetes.io/zone
+                    operator: In
+                    values:
+                      - {{ $head.Values.AZ }}
+        {{ end }}
+        podAntiAffinity:
+          preferredDuringSchedulingIgnoredDuringExecution:
+            - weight: 100
+              podAffinityTerm:
+                labelSelector:
+                  matchExpressions:
+                    - key: app
+                      operator: In
+                      values:
+                        - "{{ .label }}"
+                topologyKey: kubernetes.io/hostname
+# POD Disruption Budgets for high availability
+{{- if eq $head.Values.isMultiAz false }}
+---
+apiVersion: policy/v1beta1
+kind: PodDisruptionBudget
+metadata:
+  name: {{ .label }}-pdb
+spec:
+  maxUnavailable: {{ include "kudu.max_failovers" $head }}
+  selector:
+    matchLabels:
+      app: {{ .label }}
+{{- end }}
+{{- end }}
diff --git a/kubernetes/helm/kudu/templates/tests/health-test.yaml b/kubernetes/helm/kudu/templates/tests/health-test.yaml
new file mode 100644
index 0000000..014bb64
--- /dev/null
+++ b/kubernetes/helm/kudu/templates/tests/health-test.yaml
@@ -0,0 +1,46 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Helm test pod, to check the health of kudu cluster.
+
+apiVersion: v1
+kind: Pod
+metadata:
+  name: "{{.Release.Name}}-test"
+  namespace: "{{ .Release.Namespace }}"
+  annotations:
+    "helm.sh/hook": test-success
+  {{- if and (.Values.NetworkPolicy.Enabled) (not .Values.NetworkPolicy.AllowExternal) }}
+labels:
+  "{{.Release.Name}}-{{.Values.Component}}-client": true
+  {{- end }}
+spec:
+  containers:
+    - name: "client-test"
+      image: "{{ .Values.Image.repository }}:{{ .Values.Image.tag }}"
+      imagePullPolicy: "{{ .Values.Image.pullPolicy }}"
+      env:
+      - name: NAMESPACE
+        valueFrom:
+          fieldRef:
+            fieldPath: metadata.namespace
+      command:
+        - "kudu"
+        - "cluster"
+        - "ksck"
+        - "{{ include "kudu.gen_kudu_masters" . | trim }}"
+  restartPolicy: Never
\ No newline at end of file
diff --git a/kubernetes/helm/kudu/values.yaml b/kubernetes/helm/kudu/values.yaml
new file mode 100644
index 0000000..0da7928
--- /dev/null
+++ b/kubernetes/helm/kudu/values.yaml
@@ -0,0 +1,100 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+# Place to declare variables which will be passed to helm templates.
+# Below are defaults values for Kudu Cluster Setup.
+
+Component: "kududb"
+Image:
+  repository: "apache/kudu"
+  tag: latest
+  pullPolicy: IfNotPresent
+
+storage:
+  master:
+    count: 3
+    size: 5Gi
+    storageClass: standard
+  tserver:
+    count: 3
+    size: 5Gi
+    storageClass: standard
+
+serviceEndpoints:
+  - name: "kudu-master-ui"
+    type: NodePort
+    app: "kudu-master"
+    ports:
+      ui: "8050"
+      rpc-port: "8051"
+
+Services:
+  - name: "kudu-masters"
+    label: "kudu-master"
+    ports:
+      ui: "8050"
+      rpc-port: "8051"
+
+  - name: "kudu-tservers"
+    label: "kudu-tserver"
+    ports:
+      ui: "7050"
+      rpc-port: "7051"
+
+resource:
+  master:
+    requests:
+      cpu: 1
+      memory: 0.5Gi
+    limits:
+      cpu: 1
+      memory: 0.5Gi
+  tserver:
+    requests:
+      cpu: 1
+      memory: 1Gi
+    limits:
+      cpu: 1
+      memory: 1Gi
+
+replicas:
+  master: 3
+  tserver: 3
+
+partition:
+  master: 0
+  tserver: 0
+
+enableNodePort: True
+
+NetworkPolicy:
+  Enabled: false
+
+PodManagementPolicy: Parallel
+
+isMultiAz: False
+
+domainName: "cluster.local"
+
+nodeSelector: {}
+
+resources: {}
+
+affinity: {}
+
+tolerations: []
diff --git a/kubernetes/kudu-services.yaml b/kubernetes/kudu-services.yaml
new file mode 100644
index 0000000..a5d0dfc
--- /dev/null
+++ b/kubernetes/kudu-services.yaml
@@ -0,0 +1,75 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+---
+# headless service for kudu masters
+
+apiVersion: v1
+kind: Service
+metadata:
+  name: kudu-masters
+  namespace: apache-kudu
+  labels:
+    app: kudu-master
+spec:
+  clusterIP: None
+  ports:
+    - name: ui
+      port: 8051
+    - name: rpc-port
+      port: 8050
+  selector:
+    app: kudu-master
+
+---
+# headless service for masters
+apiVersion: v1
+kind: Service
+metadata:
+  name: kudu-master-ui
+  namespace: apache-kudu
+  labels:
+    app: kudu-master
+spec:
+  clusterIP:
+  ports:
+    - name: ui
+      port: 8051
+  selector:
+    app: kudu-master
+  type: NodePort
+  target-port:
+  externalTrafficPolicy: Local
+
+---
+# headless service for tservers
+apiVersion: v1
+kind: Service
+metadata:
+  name: kudu-tservers
+  namespace: apache-kudu
+  labels:
+    app: kudu-tserver
+spec:
+  clusterIP: None
+  ports:
+    - name: ui
+      port: 7050
+    - name: rpc-port
+      port: 7051
+  selector:
+    app: kudu-tserver
diff --git a/kubernetes/kudu-statefulset.yaml b/kubernetes/kudu-statefulset.yaml
index 39c7143..eddae07 100644
--- a/kubernetes/kudu-statefulset.yaml
+++ b/kubernetes/kudu-statefulset.yaml
@@ -14,52 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
-# More about kubernetes statefulset https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
-# build kudu docker image from ../docker folder: ../docker/docker-build.sh
-# create statefulset kudu kubernetes cluster : kubectl create -f kudu-statefulset.yaml
-# get kudu master url: minikube service kudu-master-ui --url
-# scale kudu tserver cluster : kubectl scale statefulset kudu-tserver --replicas=5
-# destroy kudu kubernetes cluster: kubectl delete -f kudu-statefulset.yaml
 
-apiVersion: v1
-kind: Service
-metadata:
-  name: kudu-masters
-  labels:
-    app: kudu-master
-spec:
-  clusterIP: None
-  ports:
-    - name: ui
-      port: 8051
-    - name: rpc-port
-      port: 8050
-  selector:
-    app: kudu-master
----
-# headless service for masters
-apiVersion: v1
-kind: Service
-metadata:
-  name: kudu-master-ui
-  labels:
-    app: kudu-master
-spec:
-  clusterIP:
-  ports:
-    - name: ui
-      port: 8051
-  selector:
-    app: kudu-master
-  type: NodePort
-  target-port:
-  externalTrafficPolicy: Local
----
 apiVersion: apps/v1
 kind: StatefulSet
 metadata:
   name: kudu-master
+  namespace: apache-kudu
   labels:
     app: kudu-master
 spec:
@@ -90,7 +50,7 @@ spec:
                 fieldRef:
                   fieldPath: metadata.name
             - name: KUDU_MASTERS
-              value: "kudu-master-0.kudu-masters.default.svc.cluster.local,kudu-master-1.kudu-masters.default.svc.cluster.local,kudu-master-2.kudu-masters.default.svc.cluster.local"
+              value: "kudu-master-0.kudu-masters.apache-kudu.svc.cluster.local,kudu-master-1.kudu-masters.apache-kudu.svc.cluster.local,kudu-master-2.kudu-masters.apache-kudu.svc.cluster.local"
           args: ["master"]
           ports:
             - containerPort: 8050
@@ -123,30 +83,12 @@ spec:
           requests:
             storage: 10Gi
         storageClassName: standard
-
----
-# headless service for tservers
-apiVersion: v1
-kind: Service
-metadata:
-  name: kudu-tservers
-  namespace: default
-  labels:
-    app: kudu-tserver
-spec:
-  clusterIP: None
-  ports:
-    - name: ui
-      port: 7050
-    - name: rpc-port
-      port: 7051
-  selector:
-    app: kudu-tserver
 ---
 apiVersion: apps/v1
 kind: StatefulSet
 metadata:
   name: kudu-tserver
+  namespace: apache-kudu
   labels:
     app: kudu-tserver
 spec:
@@ -177,7 +119,7 @@ spec:
                 fieldRef:
                   fieldPath: metadata.name
             - name: KUDU_MASTERS
-              value: "kudu-master-0.kudu-masters.default.svc.cluster.local,kudu-master-1.kudu-masters.default.svc.cluster.local,kudu-master-2.kudu-masters.default.svc.cluster.local"
+              value: "kudu-master-0.kudu-masters.apache-kudu.svc.cluster.local,kudu-master-1.kudu-masters.apache-kudu.svc.cluster.local,kudu-master-2.kudu-masters.apache-kudu.svc.cluster.local"
           args: ["tserver"]
           ports:
             - containerPort: 7050
@@ -201,6 +143,9 @@ spec:
                 topologyKey: kubernetes.io/hostname
   updateStrategy:
     type: RollingUpdate
+    rollingUpdate:
+      # partition option will be useful for staging update scenario,
+      partition: 0
   volumeClaimTemplates:
     - metadata:
         name: datadir
diff --git a/kubernetes/namespace.yaml b/kubernetes/namespace.yaml
new file mode 100644
index 0000000..7afe80f
--- /dev/null
+++ b/kubernetes/namespace.yaml
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: "apache-kudu"
+  labels:
+    name: "apache-kudu"