diff --git a/.gitignore b/.gitignore
index b440d2b597..d851849f66 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,11 @@ linklint-*.zip
linklint/
.checkstyle
**/.checkstyle
+
+# kubernetes download artifacts
+*kubectl*
+*checksums.txt
+awscli-exe*
+*aws_cli_public_key
+*.tar.gz
+*.sig
diff --git a/hbase-kubernetes-deployment/README.md b/hbase-kubernetes-deployment/README.md
new file mode 100644
index 0000000000..d240eacaae
--- /dev/null
+++ b/hbase-kubernetes-deployment/README.md
@@ -0,0 +1,27 @@
+
+
+# HBase Kubernetes Deployment
+
+This module contains Kubernetes configurations suitable for deploying ZooKeeper, HDFS, and HBase.
+It supports several physical topologies, including:
+ * a minimum deployment footprint consisting of a single instance of each architectural component.
+ * a high-avaiability deployment footprint consisting of redundancies for each architectural
+ component.
+ * a deployment where HBase region servers and HDFS data nodes share a pod, enabling short-circuit
+ read between them.
diff --git a/hbase-kubernetes-deployment/components/zookeeper/README.md b/hbase-kubernetes-deployment/components/zookeeper/README.md
new file mode 100644
index 0000000000..b6af185a87
--- /dev/null
+++ b/hbase-kubernetes-deployment/components/zookeeper/README.md
@@ -0,0 +1,23 @@
+
+
+Uses latest image from the apache zookeeper project.
+There is then a start script in 'single-instance/start.sh'
+which sets parameters for the zookeeper image and process
+on startup. Currently only logs to STDOUT/STDERR; there
+are no files in /var/log/zookeeper.
diff --git a/hbase-kubernetes-deployment/components/zookeeper/ha-ensemble/kustomization.yaml b/hbase-kubernetes-deployment/components/zookeeper/ha-ensemble/kustomization.yaml
new file mode 100644
index 0000000000..3d37c7bb8c
--- /dev/null
+++ b/hbase-kubernetes-deployment/components/zookeeper/ha-ensemble/kustomization.yaml
@@ -0,0 +1,45 @@
+# 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: kustomize.config.k8s.io/v1alpha1
+kind: Component
+
+replicas:
+- name: zookeeper
+ count: 5
+
+configMapGenerator:
+- name: zookeeper-quorum
+ behavior: merge
+ literals:
+ # Hard-coded. Default we expect a simple standalone zk at this location.
+ # One define is for hbase, the other for hadoop.
+ - HBASE_ZOOKEEPER_QUORUM="zookeeper-0,zookeeper-1,zookeeper-2,zookeeper-3,zookeeper-4"
+ - HA_ZOOKEEPER_QUORUM="zookeeper-0:2181,zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181,zookeeper-4:2181"
+ options:
+ disableNameSuffixHash: true
+
+patches:
+- target:
+ kind: StatefulSet
+ name: zookeeper
+ path: patch-zookeeper.yaml
+
+components:
+- ../single-instance
+
+resources:
+- zk-service.yaml
diff --git a/hbase-kubernetes-deployment/components/zookeeper/ha-ensemble/patch-zookeeper.yaml b/hbase-kubernetes-deployment/components/zookeeper/ha-ensemble/patch-zookeeper.yaml
new file mode 100644
index 0000000000..d59fc77b9a
--- /dev/null
+++ b/hbase-kubernetes-deployment/components/zookeeper/ha-ensemble/patch-zookeeper.yaml
@@ -0,0 +1,51 @@
+# 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.
+---
+- # increase container resource allocations
+ op: replace
+ path: /spec/template/spec/containers/0/resources
+ value:
+ requests:
+ cpu: '1.0'
+ memory: 1Gi
+ limits:
+ cpu: '2.0'
+ memory: 4Gi
+- # update the launch command
+ op: add
+ path: /spec/template/spec/containers/0/command
+ value:
+ - sh
+ - -c
+ - |-
+ # Make the heap be a fraction of the requested memory size.
+ # Make 'servers' count agree with replicas count.
+ /usr/bin/zookeeper/start.sh --servers=5 --percentage=50 --max_client_cnxns=300 --quorum_listen_on_all_ips=true
+- # increase storage volume size
+ op: replace
+ path: /spec/volumeClaimTemplates/0/spec/resources/requests/storage
+ value: 5Gi
+- # specify pod scheduling anti-affinity
+ op: add
+ path: /spec/template/spec/affinity
+ value:
+ podAntiAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ - labelSelector:
+ matchLabels:
+ app: hadoop
+ role: zookeeper
+ topologyKey: kubernetes.io/hostname
diff --git a/hbase-kubernetes-deployment/components/zookeeper/ha-ensemble/zk-service.yaml b/hbase-kubernetes-deployment/components/zookeeper/ha-ensemble/zk-service.yaml
new file mode 100644
index 0000000000..d0c1c37c3c
--- /dev/null
+++ b/hbase-kubernetes-deployment/components/zookeeper/ha-ensemble/zk-service.yaml
@@ -0,0 +1,130 @@
+# 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.
+#
+# Put a Service in front of each zookeeper so ip doesn't change on clients/admin.
+# The service is at zookeeper-?.svc.domain. The pod
+# it is proxying will be at zookeeper-?.${env.ZOOKEEPER_HEADLESS_SERVICE}.NAMESPACE.svc.domain.
+# TODO: Port for prometheus to scape.
+---
+kind: Service
+apiVersion: v1
+metadata:
+ name: zookeeper-0
+ labels:
+ # So helm prometheus standalone install will scrape this zk; TODO
+ # jmxexporter: enabled
+spec:
+ ports:
+ - port: 2181
+ name: client
+ - port: 2888
+ name: server
+ - port: 3888
+ name: leader-election
+ - port: 8080
+ name: http
+ selector:
+ role: zookeeper
+ statefulset.kubernetes.io/pod-name: zookeeper-0
+ cluster: zookeeper
+---
+kind: Service
+apiVersion: v1
+metadata:
+ name: zookeeper-1
+ labels:
+ # So helm prometheus standalone install will scrape this zk; TODO
+ # jmxexporter: enabled
+spec:
+ ports:
+ - port: 2181
+ name: client
+ - port: 2888
+ name: server
+ - port: 3888
+ name: leader-election
+ - port: 8080
+ name: http
+ selector:
+ role: zookeeper
+ statefulset.kubernetes.io/pod-name: zookeeper-1
+ cluster: zookeeper
+---
+kind: Service
+apiVersion: v1
+metadata:
+ name: zookeeper-2
+ labels:
+ # So helm prometheus standalone install will scrape this zk; TODO
+ # jmxexporter: enabled
+spec:
+ ports:
+ - port: 2181
+ name: client
+ - port: 2888
+ name: server
+ - port: 3888
+ name: leader-election
+ - port: 8080
+ name: http
+ selector:
+ role: zookeeper
+ statefulset.kubernetes.io/pod-name: zookeeper-2
+ cluster: zookeeper
+---
+kind: Service
+apiVersion: v1
+metadata:
+ name: zookeeper-3
+ labels:
+ # So helm prometheus standalone install will scrape this zk; TODO
+ # jmxexporter: enabled
+spec:
+ ports:
+ - port: 2181
+ name: client
+ - port: 2888
+ name: server
+ - port: 3888
+ name: leader-election
+ - port: 8080
+ name: http
+ selector:
+ role: zookeeper
+ statefulset.kubernetes.io/pod-name: zookeeper-3
+ cluster: zookeeper
+---
+kind: Service
+apiVersion: v1
+metadata:
+ name: zookeeper-4
+ labels:
+ # So helm prometheus standalone install will scrape this zk; TODO
+ # jmxexporter: enabled
+spec:
+ ports:
+ - port: 2181
+ name: client
+ - port: 2888
+ name: server
+ - port: 3888
+ name: leader-election
+ - port: 8080
+ name: http
+ selector:
+ role: zookeeper
+ statefulset.kubernetes.io/pod-name: zookeeper-4
+ cluster: zookeeper
diff --git a/hbase-kubernetes-deployment/components/zookeeper/single-instance/kustomization.yaml b/hbase-kubernetes-deployment/components/zookeeper/single-instance/kustomization.yaml
new file mode 100644
index 0000000000..1e87468cd7
--- /dev/null
+++ b/hbase-kubernetes-deployment/components/zookeeper/single-instance/kustomization.yaml
@@ -0,0 +1,35 @@
+# 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: kustomize.config.k8s.io/v1alpha1
+kind: Component
+
+configMapGenerator:
+- name: zookeeper-scripts
+ files:
+ - start.sh
+# Publish where the zk ensemble can be found.
+- name: zookeeper-quorum
+ literals:
+ # Hard-coded. Default we expect a simple standalone zk at this location.
+ # One define is for hbase, the other for hadoop.
+ - HBASE_ZOOKEEPER_QUORUM="zookeeper-0.zookeeper-headless"
+ - HA_ZOOKEEPER_QUORUM="zookeeper-0.zookeeper-headless:2181"
+ options:
+ disableNameSuffixHash: true
+
+resources:
+- zookeeper.yaml
diff --git a/hbase-kubernetes-deployment/components/zookeeper/single-instance/start.sh b/hbase-kubernetes-deployment/components/zookeeper/single-instance/start.sh
new file mode 100755
index 0000000000..48b3d91543
--- /dev/null
+++ b/hbase-kubernetes-deployment/components/zookeeper/single-instance/start.sh
@@ -0,0 +1,358 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+# Derived from work Copyright 2017 The Kubernetes Authors.
+# See https://github.com/kow3ns/kubernetes-zookeeper/blob/master/docker/scripts/start-zookeeper for more details
+# and then https://github.com/cloudurable/kube-zookeeper-statefulsets/
+# In the below we change the '--heap' argument to '--percentage' so
+# could set the server heap as a percentage of the container resource
+# limit rather than hard-code it.
+# Currently zookeeper.root.logger is CONSOLE only. We do not write
+# logs to files. Fix config. if you need it.
+#
+#
+# Usage: start-zookeeper [OPTIONS]
+# Starts a ZooKeeper server based on the supplied options.
+# --servers The number of servers in the ensemble. The default
+# value is 1.
+# --data_dir The directory where the ZooKeeper process will store its
+# snapshots. The default is /var/lib/zookeeper/data.
+# --data_log_dir The directory where the ZooKeeper process will store its
+# write ahead log. The default is
+# /var/lib/zookeeper/data/log.
+# --conf_dir The directory where the ZooKeeper process will store its
+# configuration. The default is /opt/zookeeper/conf.
+# --client_port The port on which the ZooKeeper process will listen for
+# client requests. The default is 2181.
+
+# --election_port The port on which the ZooKeeper process will perform
+# leader election. The default is 3888.
+
+# --server_port The port on which the ZooKeeper process will listen for
+# requests from other servers in the ensemble. The
+# default is 2888.
+
+# --tick_time The length of a ZooKeeper tick in ms. The default is
+# 2000.
+
+# --init_limit The number of Ticks that an ensemble member is allowed
+# to perform leader election. The default is 10.
+
+# --sync_limit The maximum session timeout that the ensemble will
+# allows a client to request. The default is 5.
+
+# --percentage The percentage of container memory to give to the JVM.
+
+# --max_client_cnxns The maximum number of client connections that the
+# ZooKeeper process will accept simultaneously. The
+# default is 60.
+
+# --snap_retain_count The maximum number of snapshots the ZooKeeper process
+# will retain if purge_interval is greater than 0. The
+# default is 3.
+
+# --purge_interval The number of hours the ZooKeeper process will wait
+# between purging its old snapshots. If set to 0 old
+# snapshots will never be purged. The default is 0.
+
+# --max_session_timeout The maximum time in milliseconds for a client session
+# timeout. The default value is 2 * tick time.
+
+# --min_session_timeout The minimum time in milliseconds for a client session
+# timeout. The default value is 20 * tick time.
+
+# --log_level The log level for the zookeeeper server. Either FATAL,
+# ERROR, WARN, INFO, DEBUG. The default is INFO.
+
+# --quorum_listen_on_all_ips
+# When set to true the ZooKeeper server will listen for
+# connections from its peers on all available IP addresses,
+# and not only the address configured in the server list of
+# the configuration file. It affects the connections handling
+# the ZAB protocol and the Fast Leader Election protocol.
+# Default value is false.
+set -x
+
+ZOOKEEPER_HOME="$( ls -d /apache-zookeeper* )"
+USER="$(whoami)"
+HOST="$(hostname -s)"
+DOMAIN="$(hostname -d)"
+LOG_LEVEL=INFO
+DATA_DIR="/var/lib/zookeeper/data"
+DATA_LOG_DIR="/var/lib/zookeeper/log"
+LOG_DIR="/var/log/zookeeper"
+CONF_DIR="/opt/zookeeper/conf"
+CLIENT_PORT=2181
+SERVER_PORT=2888
+ELECTION_PORT=3888
+PROM_PORT=7001
+TICK_TIME=2000
+INIT_LIMIT=10
+SYNC_LIMIT=5
+JVM_HEAP_PERCENTAGE_OF_RESOURCE_LIMIT=50
+MAX_CLIENT_CNXNS=1000
+SNAP_RETAIN_COUNT=3
+PURGE_INTERVAL=0
+SERVERS=1
+QUORUM_LISTEN_ON_ALL_IPS=false
+
+function print_usage() {
+echo "\
+Usage: start-zookeeper [OPTIONS]
+Starts a ZooKeeper server based on the supplied options.
+ --servers The number of servers in the ensemble. The default
+ value is 1.
+
+ --data_dir The directory where the ZooKeeper process will store its
+ snapshots. The default is /var/lib/zookeeper/data.
+
+ --data_log_dir The directory where the ZooKeeper process will store its
+ write ahead log. The default is
+ /var/lib/zookeeper/data/log.
+
+ --conf_dir The directoyr where the ZooKeeper process will store its
+ configuration. The default is /opt/zookeeper/conf.
+
+ --client_port The port on which the ZooKeeper process will listen for
+ client requests. The default is 2181.
+
+ --election_port The port on which the ZooKeeper process will perform
+ leader election. The default is 3888.
+
+ --server_port The port on which the ZooKeeper process will listen for
+ requests from other servers in the ensemble. The
+ default is 2888.
+
+ --tick_time The length of a ZooKeeper tick in ms. The default is
+ 2000.
+
+ --init_limit The number of Ticks that an ensemble member is allowed
+ to perform leader election. The default is 10.
+
+ --sync_limit The maximum session timeout that the ensemble will
+ allows a client to request. The default is 5.
+
+ --percentage The percentage of container memory to give to the JVM.
+
+ --max_client_cnxns The maximum number of client connections that the
+ ZooKeeper process will accept simultaneously. The
+ default is 60.
+
+ --snap_retain_count The maximum number of snapshots the ZooKeeper process
+ will retain if purge_interval is greater than 0. The
+ default is 3.
+
+ --purge_interval The number of hours the ZooKeeper process will wait
+ between purging its old snapshots. If set to 0 old
+ snapshots will never be purged. The default is 0.
+
+ --max_session_timeout The maximum time in milliseconds for a client session
+ timeout. The default value is 2 * tick time.
+
+ --min_session_timeout The minimum time in milliseconds for a client session
+ timeout. The default value is 20 * tick time.
+
+ --log_level The log level for the zookeeeper server. Either FATAL,
+ ERROR, WARN, INFO, DEBUG. The default is INFO.
+"
+}
+
+function create_data_dirs() {
+ if [ ! -d "$DATA_DIR" ]; then
+ mkdir -p "$DATA_DIR"
+ chown -R "$USER":"$USER" "$DATA_DIR"
+ fi
+
+ if [ ! -d "$DATA_LOG_DIR" ]; then
+ mkdir -p "$DATA_LOG_DIR"
+ chown -R "$USER":"$USER" "$DATA_LOG_DIR"
+ fi
+
+ if [ ! -d "$LOG_DIR" ]; then
+ mkdir -p "$LOG_DIR"
+ chown -R "$USER":"$USER" "$LOG_DIR"
+ fi
+ if [ ! -f "$ID_FILE" ] && [ "$SERVERS" -gt 1 ]; then
+ echo "$MY_ID" >> "$ID_FILE"
+ fi
+}
+
+function print_servers() {
+ for (( i=1; i<=SERVERS; i++ ))
+ do
+ echo "server.$i=$NAME-$((i-1)).$DOMAIN:$SERVER_PORT:$ELECTION_PORT"
+ done
+}
+
+function create_config() {
+ rm -f "$CONFIG_FILE"
+ {
+ echo "#This file was autogenerated DO NOT EDIT"
+ echo "clientPort=$CLIENT_PORT"
+ echo "dataDir=$DATA_DIR"
+ echo "dataLogDir=$DATA_LOG_DIR"
+ echo "tickTime=$TICK_TIME"
+ echo "initLimit=$INIT_LIMIT"
+ echo "syncLimit=$SYNC_LIMIT"
+ echo "maxClientCnxns=$MAX_CLIENT_CNXNS"
+ echo "minSessionTimeout=$MIN_SESSION_TIMEOUT"
+ echo "maxSessionTimeout=$MAX_SESSION_TIMEOUT"
+ echo "autopurge.snapRetainCount=$SNAP_RETAIN_COUNT"
+ echo "autopurge.purgeInteval=$PURGE_INTERVAL"
+ echo "quorumListenOnAllIPs=$QUORUM_LISTEN_ON_ALL_IPS"
+ # Allow running all zk commands.
+ echo "4lw.commands.whitelist=*"
+ if [ "$SERVERS" -gt 1 ]; then
+ print_servers
+ fi
+ echo "metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider"
+ echo "metricsProvider.httpPort=$PROM_PORT"
+ } >> "$CONFIG_FILE"
+ cat "$CONFIG_FILE" >&2
+}
+
+function create_jvm_props() {
+ rm -f "$JAVA_ENV_FILE"
+ {
+ echo "SERVER_JVMFLAGS=\"-XX:MaxRAMPercentage=${JVM_HEAP_PERCENTAGE_OF_RESOURCE_LIMIT} \
+ -XX:InitialRAMPercentage=${JVM_HEAP_PERCENTAGE_OF_RESOURCE_LIMIT}\""
+ echo "ZOO_LOG_DIR=$LOG_DIR"
+ echo "JVMFLAGS="
+ } >> "$JAVA_ENV_FILE"
+}
+
+function create_log_props() {
+ rm -f "$LOGGER_PROPS_FILE"
+ echo "Creating ZooKeeper log4j configuration"
+ {
+ echo "zookeeper.root.logger=CONSOLE"
+ echo "zookeeper.console.threshold=$LOG_LEVEL"
+ echo "log4j.rootLogger=\${zookeeper.root.logger}"
+ echo "log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender"
+ echo "log4j.appender.CONSOLE.Threshold=\${zookeeper.console.threshold}"
+ echo "log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout"
+ echo "log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n"
+ } >> "$LOGGER_PROPS_FILE"
+}
+
+optspec=":hv-:"
+while getopts "$optspec" optchar; do
+
+ case "${optchar}" in
+ -)
+ case "${OPTARG}" in
+ servers=*)
+ SERVERS=${OPTARG##*=}
+ ;;
+ data_dir=*)
+ DATA_DIR=${OPTARG##*=}
+ ;;
+ data_log_dir=*)
+ DATA_LOG_DIR=${OPTARG##*=}
+ ;;
+ log_dir=*)
+ LOG_DIR=${OPTARG##*=}
+ ;;
+ conf_dir=*)
+ CONF_DIR=${OPTARG##*=}
+ ;;
+ client_port=*)
+ CLIENT_PORT=${OPTARG##*=}
+ ;;
+ election_port=*)
+ ELECTION_PORT=${OPTARG##*=}
+ ;;
+ server_port=*)
+ SERVER_PORT=${OPTARG##*=}
+ ;;
+ tick_time=*)
+ TICK_TIME=${OPTARG##*=}
+ ;;
+ init_limit=*)
+ INIT_LIMIT=${OPTARG##*=}
+ ;;
+ sync_limit=*)
+ SYNC_LIMIT=${OPTARG##*=}
+ ;;
+ percentage=*)
+ JVM_HEAP_PERCENTAGE_OF_RESOURCE_LIMIT=${OPTARG##*=}
+ ;;
+ max_client_cnxns=*)
+ MAX_CLIENT_CNXNS=${OPTARG##*=}
+ ;;
+ snap_retain_count=*)
+ SNAP_RETAIN_COUNT=${OPTARG##*=}
+ ;;
+ purge_interval=*)
+ PURGE_INTERVAL=${OPTARG##*=}
+ ;;
+ max_session_timeout=*)
+ MAX_SESSION_TIMEOUT=${OPTARG##*=}
+ ;;
+ min_session_timeout=*)
+ MIN_SESSION_TIMEOUT=${OPTARG##*=}
+ ;;
+ quorum_listen_on_all_ips=*)
+ QUORUM_LISTEN_ON_ALL_IPS=${OPTARG##*=}
+ ;;
+ log_level=*)
+ LOG_LEVEL=${OPTARG##*=}
+ ;;
+ *)
+ echo "Unknown option --${OPTARG}" >&2
+ exit 1
+ ;;
+ esac;;
+ h)
+ print_usage
+ exit
+ ;;
+ v)
+ echo "Parsing option: '-${optchar}'" >&2
+ ;;
+ *)
+ if [ "$OPTERR" != 1 ] || [ "${optspec:0:1}" = ":" ]; then
+ echo "Non-option argument: '-${OPTARG}'" >&2
+ fi
+ ;;
+ esac
+done
+
+MIN_SESSION_TIMEOUT=${MIN_SESSION_TIMEOUT:- $((TICK_TIME*2))}
+MAX_SESSION_TIMEOUT=${MAX_SESSION_TIMEOUT:- $((TICK_TIME*20))}
+ID_FILE="$DATA_DIR/myid"
+if [ ! -d "$CONF_DIR" ]; then
+ mkdir -p "$CONF_DIR"
+ chown -R "$USER":"$USER" "$CONF_DIR"
+fi
+CONFIG_FILE="$CONF_DIR/zoo.cfg"
+LOGGER_PROPS_FILE="$CONF_DIR/log4j.properties"
+JAVA_ENV_FILE="$CONF_DIR/java.env"
+
+if [[ $HOST =~ (.*)-([0-9]+)$ ]]; then
+ NAME=${BASH_REMATCH[1]}
+ ORD=${BASH_REMATCH[2]}
+else
+ echo "Failed to parse name and ordinal of Pod"
+ exit 1
+fi
+
+MY_ID=$((ORD+1))
+
+export ZOOCFGDIR=${CONF_DIR}
+create_config && create_jvm_props && create_log_props && create_data_dirs && exec "${ZOOKEEPER_HOME}/bin/zkServer.sh" start-foreground
diff --git a/hbase-kubernetes-deployment/components/zookeeper/single-instance/zookeeper.yaml b/hbase-kubernetes-deployment/components/zookeeper/single-instance/zookeeper.yaml
new file mode 100644
index 0000000000..b01022972a
--- /dev/null
+++ b/hbase-kubernetes-deployment/components/zookeeper/single-instance/zookeeper.yaml
@@ -0,0 +1,142 @@
+# 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: apps/v1
+kind: StatefulSet
+metadata:
+ name: zookeeper
+spec:
+ replicas: 1
+ serviceName: zookeeper-headless
+ selector:
+ matchLabels:
+ cluster: zookeeper # has to match .spec.template.metadata.labels
+ role: zookeeper
+ updateStrategy:
+ type: RollingUpdate
+ podManagementPolicy: Parallel
+ template:
+ metadata:
+ labels:
+ cluster: zookeeper
+ role: zookeeper
+ spec:
+ containers:
+ - image: zookeeper
+ name: zookeeper
+ imagePullPolicy: IfNotPresent
+ resources:
+ requests:
+ cpu: '0.1'
+ memory: 768Mi
+ limits:
+ cpu: '1.0'
+ memory: 1Gi
+ env:
+ - name: JAVA_HOME
+ value: /usr/local/openjdk-11
+ - name: LANG
+ value: C.UTF-8
+ - name: PATH
+ value: /usr/local/openjdk-11/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+ - name: ZK_LOG_DIR
+ value: /var/log/zookeeper
+ ports:
+ - containerPort: 2181
+ name: client
+ - containerPort: 2888
+ name: server
+ - containerPort: 3888
+ name: leader-election
+ - containerPort: 7001
+ name: metrics
+ command:
+ - sh
+ - -c
+ - |-
+ export LOG_DIR="${ZK_LOG_DIR}"
+ /usr/bin/zookeeper/start.sh --servers=1 --percentage=50
+ readinessProbe:
+ exec:
+ command:
+ - /bin/bash
+ - -c
+ - |-
+ [ "$(echo ruok | nc 127.0.0.1 2181)" == "imok" ]
+ initialDelaySeconds: 10
+ timeoutSeconds: 5
+ livenessProbe:
+ exec:
+ command:
+ - /bin/bash
+ - -c
+ - |-
+ [ "$(echo ruok | nc 127.0.0.1 2181)" == "imok" ]
+ initialDelaySeconds: 10
+ timeoutSeconds: 5
+ volumeMounts:
+ - name: datadir
+ mountPath: /var/lib/zookeeper
+ - mountPath: /usr/bin/zookeeper
+ name: zookeeper-scripts
+ - mountPath: /var/log/zookeeper
+ name: zk-logs
+ volumes:
+ - emptyDir: {}
+ name: zk-logs
+ - configMap:
+ name: zookeeper-scripts
+ defaultMode: 0555
+ name: zookeeper-scripts
+ volumeClaimTemplates:
+ - metadata:
+ name: datadir
+ spec:
+ accessModes: [ "ReadWriteOnce" ]
+ resources:
+ requests:
+ storage: 2Gi
+---
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+ name: zookeeper-pdb
+spec:
+ selector:
+ matchLabels:
+ cluster: zookeeper
+ maxUnavailable: 1
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: zookeeper-headless
+spec:
+ ports:
+ - port: 2888
+ name: server
+ - port: 3888
+ name: leader-election
+ - port: 2181
+ name: client
+ - port: 8080
+ name: http
+ clusterIP: None
+ publishNotReadyAddresses: true
+ # Select our zookeeper app. This is what gets us dns entries
+ # https://kubernetes.io/docs/concepts/services-networking/service/#with-selectors
+ selector:
+ cluster: zookeeper
diff --git a/hbase-kubernetes-deployment/dockerfiles/kuttl/Dockerfile b/hbase-kubernetes-deployment/dockerfiles/kuttl/Dockerfile
new file mode 100644
index 0000000000..670fefd073
--- /dev/null
+++ b/hbase-kubernetes-deployment/dockerfiles/kuttl/Dockerfile
@@ -0,0 +1,167 @@
+# syntax=docker/dockerfile:1.2
+#
+# 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.
+
+ARG IMG_BASE='golang'
+ARG IMG_BASE_TAG='1.19-alpine'
+ARG BASE_IMG_ALPINE='alpine'
+ARG BASE_IMG_TAG_ALPINE='latest'
+ARG YQ_IMG='mikefarah/yq'
+ARG YQ_IMG_TAG='latest'
+
+FROM ${BASE_IMG_ALPINE}:${BASE_IMG_TAG_ALPINE} as alpine
+
+FROM ${YQ_IMG}:${YQ_IMG_TAG} as yq
+
+## -- Stages kubectl_${TARGETARCH} --
+# Define stages that facilitate bringing in platform-specific binaries.
+FROM alpine as kubectl_amd64
+ARG KUBECTL_SHA_AMD64
+ARG KUBECTL_BIN_AMD64
+WORKDIR /tmp/
+COPY ${KUBECTL_SHA_AMD64} /tmp/
+COPY ${KUBECTL_BIN_AMD64} /tmp/
+RUN echo "$(cat "${KUBECTL_SHA_AMD64}") ${KUBECTL_BIN_AMD64}" | sha512sum -c
+
+FROM alpine as kubectl_arm64
+ARG KUBECTL_SHA_ARM64
+ARG KUBECTL_BIN_ARM64
+WORKDIR /tmp/
+COPY ${KUBECTL_SHA_ARM64} /tmp/
+COPY ${KUBECTL_BIN_ARM64} /tmp/
+RUN echo "$(cat "${KUBECTL_SHA_ARM64}") ${KUBECTL_BIN_ARM64}" | sha512sum -c
+
+ARG TARGETARCH
+FROM kubectl_${TARGETARCH} as kubectl
+RUN mv /tmp/kubectl_* /tmp/kubectl \
+ && chmod a+x /tmp/kubectl
+
+## -- Stages kuttl_${TARGETARCH} --
+# Define stages that facilitate bringing in platform-specific binaries.
+FROM alpine as kuttl_amd64
+ARG KUTTL_CHECKSUMS
+ARG KUTTL_BIN_AMD64
+WORKDIR /tmp/
+COPY ${KUTTL_CHECKSUMS} /tmp/
+COPY ${KUTTL_BIN_AMD64} /tmp/
+RUN sha256sum -c <(grep "${KUTTL_BIN_AMD64}" "${KUTTL_CHECKSUMS}")
+
+FROM alpine as kuttl_arm64
+ARG KUTTL_CHECKSUMS
+ARG KUTTL_BIN_ARM64
+WORKDIR /tmp/
+COPY ${KUTTL_CHECKSUMS} /tmp/
+COPY ${KUTTL_BIN_ARM64} /tmp/
+RUN sha256sum -c <(grep "${KUTTL_BIN_ARM64}" "${KUTTL_CHECKSUMS}")
+
+ARG TARGETARCH
+FROM kuttl_${TARGETARCH} as kuttl
+RUN mv /tmp/kubectl-kuttl_* /tmp/kubectl-kuttl \
+ && chmod a+x /tmp/kubectl-kuttl
+
+## -- Stages kustomize_${TARGETARCH} --
+# Define stages that facilitate bringing in platform-specific binaries.
+FROM alpine as kustomize_amd64
+ARG KUSTOMIZE_CHECKSUMS
+ARG KUSTOMIZE_BIN_AMD64_TGZ
+WORKDIR /tmp/
+COPY ${KUSTOMIZE_CHECKSUMS} /tmp/
+COPY ${KUSTOMIZE_BIN_AMD64_TGZ} /tmp/
+RUN sha256sum -c <(grep "${KUSTOMIZE_BIN_AMD64_TGZ}" "${KUSTOMIZE_CHECKSUMS}") \
+ && cd /tmp \
+ && tar xzf "${KUSTOMIZE_BIN_AMD64_TGZ}"
+
+FROM alpine as kustomize_arm64
+ARG KUSTOMIZE_CHECKSUMS
+ARG KUSTOMIZE_BIN_ARM64_TGZ
+WORKDIR /tmp/
+COPY ${KUSTOMIZE_CHECKSUMS} /tmp/
+COPY ${KUSTOMIZE_BIN_ARM64_TGZ} /tmp/
+RUN sha256sum -c <(grep "${KUSTOMIZE_BIN_ARM64_TGZ}" "${KUSTOMIZE_CHECKSUMS}")
+
+ARG TARGETARCH
+FROM kustomize_${TARGETARCH} as kustomize
+RUN tar xzf /tmp/kustomize_*.tar.gz \
+ && chmod a+x /tmp/kustomize
+
+## -- Stage aws_cli_builder
+FROM alpine as aws_cli_builder
+ARG AWS_CLI_PUBLIC_KEY
+ARG AWS_CLI_SOURCES_TGZ
+ARG AWS_CLI_SOURCES_TGZ_SIG
+COPY ${AWS_CLI_PUBLIC_KEY} /tmp/
+COPY ${AWS_CLI_SOURCES_TGZ} /tmp/
+COPY ${AWS_CLI_SOURCES_TGZ_SIG} /tmp/
+WORKDIR /tmp
+RUN apk add --no-cache \
+ build-base \
+ cmake \
+ gnupg \
+ groff \
+ libffi-dev \
+ python3 \
+ python3-dev \
+ tar \
+ && gpg --import /tmp/aws_cli_public_key \
+ && gpg --verify /tmp/${AWS_CLI_SOURCES_TGZ_SIG} /tmp/${AWS_CLI_SOURCES_TGZ} \
+ && tar -xzf ${AWS_CLI_SOURCES_TGZ} \
+ && cd "${AWS_CLI_SOURCES_TGZ%.tar.gz}" \
+ && ./configure --with-install-type=portable-exe --with-download-deps \
+ && make \
+ && make install \
+ && rm -rf \
+ /usr/local/lib/aws-cli/aws_completer \
+ /usr/local/lib/aws-cli/awscli/data/ac.index \
+ /usr/local/lib/aws-cli/awscli/examples \
+ && find /usr/local/lib/aws-cli/awscli/data -name completions-1*.json -delete \
+ && find /usr/local/lib/aws-cli/awscli/botocore/data -name examples-1.json -delete \
+ && cd /usr/local/lib/aws-cli \
+ && for a in *.so* ; do test -f /lib/$a && rm $a; done
+
+FROM ${IMG_BASE}:${IMG_BASE_TAG} as final
+ARG IMG_BASE
+ARG IMG_BASE_TAG
+
+COPY --from=yq /usr/bin/yq /usr/bin/yq
+COPY --from=kubectl /tmp/kubectl /usr/local/bin/
+COPY --from=kuttl /tmp/kubectl-kuttl /usr/local/bin/
+COPY --from=kustomize /tmp/kustomize /usr/local/bin/
+COPY --from=aws_cli_builder /usr/local/lib/aws-cli/ /usr/local/lib/aws-cli/
+COPY hbase-kubernetes-deployment/dockerfiles/kuttl/entrypoint.sh /bin/
+
+# install python, needed by aws-cli
+ENV LANG C.UTF-8
+RUN apk add --update --no-cache \
+ bash \
+ docker-cli \
+ groff \
+ less \
+ python3 \
+ python3-dev \
+ && ln -s /usr/local/lib/aws-cli/aws /usr/local/bin/aws \
+ && /usr/local/bin/aws --version
+
+# replicate the test-related bits generated by `kubebuilder` into its Makefile.
+ENV GOBIN="${GOPATH}/bin"
+ENV ENVTEST_K8S_VERSION='1.23.x'
+RUN chmod a+x /bin/entrypoint.sh \
+ && go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest \
+ && "${GOBIN}/setup-envtest" use "${ENVTEST_K8S_VERSION}"
+# disable downloading remote content henceforth
+ENV ENVTEST_INSTALLED_ONLY=true
+
+ENTRYPOINT ["/bin/entrypoint.sh"]
diff --git a/hbase-kubernetes-deployment/dockerfiles/kuttl/README.md b/hbase-kubernetes-deployment/dockerfiles/kuttl/README.md
new file mode 100644
index 0000000000..221066a0df
--- /dev/null
+++ b/hbase-kubernetes-deployment/dockerfiles/kuttl/README.md
@@ -0,0 +1,73 @@
+
+
+# dockerfiles/kuttl
+
+This directory builds a docker image containing everything required to run `kubectl-kuttl` in
+"mocked control plane" mode. This image is used as the basis for both dev and test environments.
+
+## Build
+
+Building the docker image locally is a little picky because there's lots of input arguments
+(download of dependencies is externalized from the build) and because binary file names required
+by the build do not necissarily match the distribution artifact names. Start by downloading all
+the relevant binaries for your platform and naming them appropriately, see comments in
+[docker-bake.override.hcl](./docker-bake.override.hcl) for details.
+
+Next, create a buildx context that supports (optionally) multi-platform images. If you've created
+this context previously, it's enough to ensure that it's active via `docker buildx ls`.
+
+```shell
+$ docker buildx create \
+ --driver docker-container \
+ --platform linux/amd64,linux/arm64 \
+ --use \
+ --bootstrap
+```
+
+Finally, build the image using,
+
+```shell
+$ docker buildx bake \
+ --file dockerfiles/kuttl/docker-bake.hcl \
+ --file dockerfiles/kuttl/docker-bake.override.hcl \
+ --pull \
+ --load
+```
+
+This exports an image to your local repository that is tagged as `${USER}/hbase/operator-tools/kuttl:latest`.
+
+## Usage
+
+The image is configured with `kuttle` as the entrypoint.
+
+```shell
+$ docker container run --rm -it ${USER}/hbase/operator-tools/kuttl:latest --help
+
+```
+
+Running tests in the image requires mounting the workspace into the container image and passing
+appropriate parameters to `kuttl`. For example, run the "small" tests like this:
+
+```shell
+$ docker container run \
+ --mount type=bind,source=$(pwd),target=/workspace \
+ --workdir /workspace \
+ ${USER}/hbase/operator-tools/kuttl:latest \
+ --config tests/kuttl-test-small.yaml
+```
diff --git a/hbase-kubernetes-deployment/dockerfiles/kuttl/docker-bake.hcl b/hbase-kubernetes-deployment/dockerfiles/kuttl/docker-bake.hcl
new file mode 100644
index 0000000000..27c2015a68
--- /dev/null
+++ b/hbase-kubernetes-deployment/dockerfiles/kuttl/docker-bake.hcl
@@ -0,0 +1,72 @@
+# 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.
+#
+# A convenience script for build the kuttl image.
+# See hbase-kubernetes-deployment/dockerfiles/kuttl/README.md
+#
+
+# input variables
+variable KUBECTL_SHA_AMD64 {}
+variable KUBECTL_BIN_AMD64 {}
+variable KUBECTL_SHA_ARM64 {}
+variable KUBECTL_BIN_ARM64 {}
+variable KUTTL_CHECKSUMS {}
+variable KUTTL_BIN_AMD64 {}
+variable KUTTL_BIN_ARM64 {}
+variable KUSTOMIZE_CHECKSUMS {}
+variable KUSTOMIZE_BIN_AMD64_TGZ {}
+variable KUSTOMIZE_BIN_ARM64_TGZ {}
+variable AWS_CLI_PUBLIC_KEY {}
+variable AWS_CLI_SOURCES_TGZ {}
+variable AWS_CLI_SOURCES_TGZ_SIG {}
+
+# output variables
+variable USER {}
+variable IMAGE_TAG {
+ default = "latest"
+}
+variable IMAGE_NAME {
+ default = "${USER}/hbase/operator-tools/kuttl"
+}
+
+group default {
+ targets = [ "kuttl" ]
+}
+
+target kuttl {
+ dockerfile = "hbase-kubernetes-deployment/dockerfiles/kuttl/Dockerfile"
+ args = {
+ KUBECTL_SHA_AMD64 = KUBECTL_SHA_AMD64
+ KUBECTL_BIN_AMD64 = KUBECTL_BIN_AMD64
+ KUBECTL_SHA_ARM64 = KUBECTL_SHA_ARM64
+ KUBECTL_BIN_ARM64 = KUBECTL_BIN_ARM64
+ KUTTL_CHECKSUMS = KUTTL_CHECKSUMS
+ KUTTL_BIN_AMD64 = KUTTL_BIN_AMD64
+ KUTTL_BIN_ARM64 = KUTTL_BIN_ARM64
+ KUSTOMIZE_CHECKSUMS = KUSTOMIZE_CHECKSUMS
+ KUSTOMIZE_BIN_AMD64_TGZ = KUSTOMIZE_BIN_AMD64_TGZ
+ KUSTOMIZE_BIN_ARM64_TGZ = KUSTOMIZE_BIN_ARM64_TGZ
+ AWS_CLI_PUBLIC_KEY = AWS_CLI_PUBLIC_KEY
+ AWS_CLI_SOURCES_TGZ = AWS_CLI_SOURCES_TGZ
+ AWS_CLI_SOURCES_TGZ_SIG = AWS_CLI_SOURCES_TGZ_SIG
+ }
+ target = "final"
+ platforms = [
+ "linux/amd64",
+ "linux/arm64"
+ ]
+ tags = [ "${IMAGE_NAME}:${IMAGE_TAG}" ]
+}
diff --git a/hbase-kubernetes-deployment/dockerfiles/kuttl/docker-bake.override.hcl b/hbase-kubernetes-deployment/dockerfiles/kuttl/docker-bake.override.hcl
new file mode 100644
index 0000000000..d98c9ae077
--- /dev/null
+++ b/hbase-kubernetes-deployment/dockerfiles/kuttl/docker-bake.override.hcl
@@ -0,0 +1,83 @@
+# 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.
+#
+# Externalize default values of build parameters and document how to retrieve them.
+#
+
+variable KUBECTL_SHA_AMD64 {
+ # wget -O sha512_kubectl_v1.24.10_linux_amd64 'https://dl.k8s.io/release/v1.24.10/bin/linux/amd64/kubectl.sha512'
+ default = "sha512_kubectl_v1.24.10_linux_amd64"
+}
+
+variable KUBECTL_BIN_AMD64 {
+ # wget -O kubectl_v1.24.10_linux_amd64 'https://dl.k8s.io/release/v1.24.10/bin/linux/amd64/kubectl'
+ default = "kubectl_v1.24.10_linux_amd64"
+}
+
+variable KUBECTL_SHA_ARM64 {
+ # wget -O sha512_kubectl_v1.24.10_linux_arm64 'https://dl.k8s.io/release/v1.24.10/bin/linux/arm64/kubectl.sha512'
+ default = "sha512_kubectl_v1.24.10_linux_arm64"
+}
+
+variable KUBECTL_BIN_ARM64 {
+ # wget -O kubectl_v1.24.10_linux_arm64 'https://dl.k8s.io/release/v1.24.10/bin/linux/arm64/kubectl'
+ default = "kubectl_v1.24.10_linux_arm64"
+}
+
+variable KUTTL_CHECKSUMS {
+ # wget -O kuttl_checksums.txt 'https://github.com/kudobuilder/kuttl/releases/download/v0.15.0/checksums.txt'
+ default = "kuttl_checksums.txt"
+}
+
+variable KUTTL_BIN_AMD64 {
+ # wget -O kubectl-kuttl_0.15.0_linux_x86_64 'https://github.com/kudobuilder/kuttl/releases/download/v0.15.0/kubectl-kuttl_0.15.0_linux_x86_64'
+ default = "kubectl-kuttl_0.15.0_linux_x86_64"
+}
+
+variable KUTTL_BIN_ARM64 {
+ # wget -O kubectl-kuttl_0.15.0_linux_arm64 'https://github.com/kudobuilder/kuttl/releases/download/v0.15.0/kubectl-kuttl_0.15.0_linux_arm64'
+ default = "kubectl-kuttl_0.15.0_linux_arm64"
+}
+
+variable KUSTOMIZE_CHECKSUMS {
+ # wget -O kustomize_checksums.txt 'https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv4.5.4/checksums.txt'
+ default = "kustomize_checksums.txt"
+}
+
+variable KUSTOMIZE_BIN_AMD64_TGZ {
+ # wget -O kustomize_v4.5.4_linux_amd64.tar.gz 'https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv4.5.4/kustomize_v4.5.4_linux_amd64.tar.gz'
+ default = "kustomize_v4.5.4_linux_amd64.tar.gz"
+}
+
+variable KUSTOMIZE_BIN_ARM64_TGZ {
+ # wget -O kustomize_v4.5.4_linux_arm64.tar.gz 'https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv4.5.4/kustomize_v4.5.4_linux_arm64.tar.gz'
+ default = "kustomize_v4.5.4_linux_arm64.tar.gz"
+}
+
+variable AWS_CLI_PUBLIC_KEY {
+ # no download for this data ; copy it off of https://docs.aws.amazon.com/cli/latest/userguide/getting-started-source-install.html
+ default = "aws_cli_public_key"
+}
+
+variable AWS_CLI_SOURCES_TGZ {
+ # curl -LOSs 'https://awscli.amazonaws.com/awscli-2.10.4.tar.gz'
+ default = "awscli-2.10.4.tar.gz"
+}
+
+variable AWS_CLI_SOURCES_TGZ_SIG {
+ # curl -LOSs 'https://awscli.amazonaws.com/awscli-2.10.4.tar.gz.sig'
+ default = "awscli-2.10.4.tar.gz.sig"
+}
diff --git a/hbase-kubernetes-deployment/dockerfiles/kuttl/entrypoint.sh b/hbase-kubernetes-deployment/dockerfiles/kuttl/entrypoint.sh
new file mode 100644
index 0000000000..8436e82600
--- /dev/null
+++ b/hbase-kubernetes-deployment/dockerfiles/kuttl/entrypoint.sh
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+#
+# 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.
+
+set -e
+set -o pipefail
+set -x
+
+declare ENVTEST_K8S_VERSION
+
+declare KUBEBUILDER_ASSETS
+KUBEBUILDER_ASSETS="$(setup-envtest use -i "${ENVTEST_K8S_VERSION}" -p path)"
+export KUBEBUILDER_ASSETS
+
+/usr/local/bin/kubectl kuttl test "$@"
diff --git a/hbase-kubernetes-deployment/pom.xml b/hbase-kubernetes-deployment/pom.xml
new file mode 100644
index 0000000000..f0f8053dd8
--- /dev/null
+++ b/hbase-kubernetes-deployment/pom.xml
@@ -0,0 +1,41 @@
+
+
+
+ 4.0.0
+
+ hbase-operator-tools
+ org.apache.hbase.operator.tools
+ ${revision}
+ ..
+
+
+ hbase-kubernetes-deployment
+ Apache HBase - Kubernetes Deployment
+ Resource definitions for deploying HBase on Kubernetes.
+ pom
+
+
+
+
+
+
diff --git a/hbase-kubernetes-deployment/tests/bin/kustomize_into_tmpdir.sh b/hbase-kubernetes-deployment/tests/bin/kustomize_into_tmpdir.sh
new file mode 100755
index 0000000000..7e5cef1048
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/bin/kustomize_into_tmpdir.sh
@@ -0,0 +1,90 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+# Test runner using KUTTL against a target cluster.
+# https://kuttl.dev
+# https://kind.sigs.k8s.io
+#
+# Materialize a kustomize directory for a kuttl test.
+#
+# Kustomize is clunky for automated testing. It's pretty opinionated in that it will only evaluate
+# a directory off of disk -- you cannot generate a kustomization and pass it in via stdin.
+# In order to use kuttl generated namespaces within the kustomization, we have to modify the
+# kustomization.yaml before applying it. If we modify that file in the source tree, we end up with
+# the test namespace appended to the file under source control. So, this script creates a temp
+# directory, copies all the resources into that directory, and modifies the kustomization.yaml as
+# necessary. It then runs `kubectl apply -k` against that temporary directory.
+#
+
+declare DEBUG="${DEBUG:false}"
+if [ "${DEBUG}" = 'true' ] ; then
+ set -x
+fi
+
+set -eou pipefail
+
+declare NAMESPACE
+declare NEW_RESOURCES='[]'
+declare NEW_COMPONENTS='[]'
+declare kustomize_dir
+declare -a rewritten_resources=()
+declare -a rewritten_components=()
+
+kustomize_dir="$(mktemp -d -p /tmp "${NAMESPACE}.XXXXXXXXXX")"
+trap '[ -d "${kustomize_dir}" ] && rm -rf "${kustomize_dir}"' EXIT
+
+cp -r ./* "${kustomize_dir}/"
+
+for r in $(yq '.resources[]' kustomization.yaml) ; do
+ if [[ "${r}" =~ ^\.\./.* ]] ; then
+ # resolve the new relative location for any resource path that is not in the local directory
+ canonized="$(cd "${r}" ; pwd)"
+ r="../..${canonized}"
+ fi
+ rewritten_resources+=("'${r}'")
+done
+if [ "${#rewritten_resources[@]}" -gt 0 ] ; then
+ NEW_RESOURCES="[ $(printf '%s,' "${rewritten_resources[@]}") ]"
+fi
+
+for r in $(yq '.components[]' kustomization.yaml) ; do
+ if [[ "${r}" =~ ^\.\./.* ]] ; then
+ # resolve the new relative location for any resource path that is not in the local directory
+ canonized="$(cd "${r}" ; pwd)"
+ r="../..${canonized}"
+ fi
+ rewritten_components+=("'${r}'")
+done
+if [ "${#rewritten_components[@]}" -gt 0 ] ; then
+ NEW_COMPONENTS="[ $(printf '%s,' "${rewritten_components[@]}") ]"
+fi
+
+env NAMESPACE="${NAMESPACE}" \
+ NEW_RESOURCES="${NEW_RESOURCES}" \
+ NEW_COMPONENTS="${NEW_COMPONENTS}" \
+ yq -i '
+ .namespace = strenv(NAMESPACE) |
+ .resources = env(NEW_RESOURCES) |
+ .components = env(NEW_COMPONENTS)
+' "${kustomize_dir}/kustomization.yaml"
+
+if [ "${DEBUG}" = 'true' ] ; then
+ cat "${kustomize_dir}/kustomization.yaml"
+fi
+
+kubectl apply -k "${kustomize_dir}"
diff --git a/hbase-kubernetes-deployment/tests/integration/components_zookeeper_ha-ensemble/00-assert-zookeeper.yaml b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_ha-ensemble/00-assert-zookeeper.yaml
new file mode 100644
index 0000000000..ef02b396a5
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_ha-ensemble/00-assert-zookeeper.yaml
@@ -0,0 +1,26 @@
+# 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.
+#
+# Asserts on the ZooKeeper portion of the deployment.
+#
+---
+# assert that there is a `StatefulSet` named "zookeeper" that has one live instance.
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: zookeeper
+status:
+ availableReplicas: 5
diff --git a/hbase-kubernetes-deployment/tests/integration/components_zookeeper_ha-ensemble/00-kustomize.yaml b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_ha-ensemble/00-kustomize.yaml
new file mode 100644
index 0000000000..b365471f5f
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_ha-ensemble/00-kustomize.yaml
@@ -0,0 +1,21 @@
+# 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: kuttl.dev/v1beta1
+kind: TestStep
+
+commands:
+- script: ../../bin/kustomize_into_tmpdir.sh
diff --git a/hbase-kubernetes-deployment/tests/integration/components_zookeeper_ha-ensemble/kustomization.yaml b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_ha-ensemble/kustomization.yaml
new file mode 100644
index 0000000000..cc21a69e4f
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_ha-ensemble/kustomization.yaml
@@ -0,0 +1,21 @@
+# 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: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+components:
+ - ../../../components/zookeeper/ha-ensemble
diff --git a/hbase-kubernetes-deployment/tests/integration/components_zookeeper_single/00-assert-zookeeper.yaml b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_single/00-assert-zookeeper.yaml
new file mode 100644
index 0000000000..4e109f0846
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_single/00-assert-zookeeper.yaml
@@ -0,0 +1,26 @@
+# 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.
+#
+# Asserts on the ZooKeeper portion of the deployment.
+#
+---
+# assert that there is a `StatefulSet` named "zookeeper" that has one live instance.
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: zookeeper
+status:
+ availableReplicas: 1
diff --git a/hbase-kubernetes-deployment/tests/integration/components_zookeeper_single/00-kustomize.yaml b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_single/00-kustomize.yaml
new file mode 100644
index 0000000000..b365471f5f
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_single/00-kustomize.yaml
@@ -0,0 +1,21 @@
+# 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: kuttl.dev/v1beta1
+kind: TestStep
+
+commands:
+- script: ../../bin/kustomize_into_tmpdir.sh
diff --git a/hbase-kubernetes-deployment/tests/integration/components_zookeeper_single/kustomization.yaml b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_single/kustomization.yaml
new file mode 100644
index 0000000000..e70699d316
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/integration/components_zookeeper_single/kustomization.yaml
@@ -0,0 +1,21 @@
+# 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: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+components:
+ - ../../../components/zookeeper/single-instance
diff --git a/hbase-kubernetes-deployment/tests/kuttl-test-integration.yaml b/hbase-kubernetes-deployment/tests/kuttl-test-integration.yaml
new file mode 100644
index 0000000000..7b1710efe2
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/kuttl-test-integration.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.
+#
+# Test runner using KUTTL against a target cluster.
+# https://kuttl.dev
+# https://kind.sigs.k8s.io
+#
+# Test runner using KUTTL against a target cluster.
+# https://kuttl.dev
+# https://kind.sigs.k8s.io
+---
+# Does not use Kuttl's built-in KIND support -- it doesn't quite work correctly with a VM-based
+# (Docker Desktop) style of runtime. Instead, assumes the cluster is established outside of kuttl
+# and configuration is provided via `--env`.
+apiVersion: kuttl.dev/v1beta1
+kind: TestSuite
+testDirs:
+- ./tests/integration
+timeout:
+ # these tests allocate several pods with dependencies between them, allow some time for
+ # everything to launch and settle.
+ 300
+reportName: kuttl-report-integration
+reportFormat: xml
diff --git a/hbase-kubernetes-deployment/tests/kuttl-test-unit.yaml b/hbase-kubernetes-deployment/tests/kuttl-test-unit.yaml
new file mode 100644
index 0000000000..ddc9dadf0c
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/kuttl-test-unit.yaml
@@ -0,0 +1,28 @@
+# 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.
+#
+# Test runner using KUTTL against a target cluster.
+# https://kuttl.dev
+# https://kind.sigs.k8s.io
+# Test runner using https://kuttl.dev
+---
+apiVersion: kuttl.dev/v1beta1
+kind: TestSuite
+startControlPlane: true
+testDirs:
+- ./tests/unit
+reportName: kuttl-report-unit
+reportFormat: xml
diff --git a/hbase-kubernetes-deployment/tests/unit/components_zookeeper_ha-ensemble/00-assert-zookeeper.yaml b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_ha-ensemble/00-assert-zookeeper.yaml
new file mode 100644
index 0000000000..9deb6316a6
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_ha-ensemble/00-assert-zookeeper.yaml
@@ -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.
+#
+# Asserts on the ZooKeeper portion of the deployment.
+#
+---
+# assert that there is a `ConfigMap` named "zookeeper-scripts-XXX"
+# TODO: kuttl does not support generated names
+#apiVersion: v1
+#kind: ConfigMap
+#metadata:
+# name: zookeeper-scripts-c94h8k249d
+---
+# assert that there is a `ConfigMap` named "zookeeper-quorum"
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: zookeeper-quorum
+---
+# assert that there is a `PodDisruptionBudget` named "zookeeper-pdb"
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+ name: zookeeper-pdb
+---
+# assert that there is a `StatefulSet` named "zookeeper" that:
+# - provides pods labeled role:zookeeper
+# - has 5 replicas
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: zookeeper
+spec:
+ replicas: 5
+ template:
+ metadata:
+ labels:
+ role: zookeeper
+---
+# assert that there is a `Service` named "zookeeper-0" that:
+# - points to pods labeled role:zookeeper
+# - points the pod of the same name
+apiVersion: v1
+kind: Service
+metadata:
+ name: zookeeper-0
+spec:
+ selector:
+ role: zookeeper
+ statefulset.kubernetes.io/pod-name: zookeeper-0
+---
+# assert that there is a `Service` named "zookeeper-1" that:
+# - points to pods labeled role:zookeeper
+# - points the pod of the same name
+apiVersion: v1
+kind: Service
+metadata:
+ name: zookeeper-1
+spec:
+ selector:
+ role: zookeeper
+ statefulset.kubernetes.io/pod-name: zookeeper-1
+---
+# assert that there is a `Service` named "zookeeper-2" that:
+# - points to pods labeled role:zookeeper
+# - points the pod of the same name
+apiVersion: v1
+kind: Service
+metadata:
+ name: zookeeper-2
+spec:
+ selector:
+ role: zookeeper
+ statefulset.kubernetes.io/pod-name: zookeeper-2
+---
+# assert that there is a `Service` named "zookeeper-3" that:
+# - points to pods labeled role:zookeeper
+# - points the pod of the same name
+apiVersion: v1
+kind: Service
+metadata:
+ name: zookeeper-3
+spec:
+ selector:
+ role: zookeeper
+ statefulset.kubernetes.io/pod-name: zookeeper-3
+---
+# assert that there is a `Service` named "zookeeper-4" that:
+# - points to pods labeled role:zookeeper
+# - points the pod of the same name
+apiVersion: v1
+kind: Service
+metadata:
+ name: zookeeper-4
+spec:
+ selector:
+ role: zookeeper
+ statefulset.kubernetes.io/pod-name: zookeeper-4
diff --git a/hbase-kubernetes-deployment/tests/unit/components_zookeeper_ha-ensemble/00-kustomize.yaml b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_ha-ensemble/00-kustomize.yaml
new file mode 100644
index 0000000000..b365471f5f
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_ha-ensemble/00-kustomize.yaml
@@ -0,0 +1,21 @@
+# 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: kuttl.dev/v1beta1
+kind: TestStep
+
+commands:
+- script: ../../bin/kustomize_into_tmpdir.sh
diff --git a/hbase-kubernetes-deployment/tests/unit/components_zookeeper_ha-ensemble/kustomization.yaml b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_ha-ensemble/kustomization.yaml
new file mode 100644
index 0000000000..cc21a69e4f
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_ha-ensemble/kustomization.yaml
@@ -0,0 +1,21 @@
+# 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: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+components:
+ - ../../../components/zookeeper/ha-ensemble
diff --git a/hbase-kubernetes-deployment/tests/unit/components_zookeeper_single/00-assert-zookeeper.yaml b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_single/00-assert-zookeeper.yaml
new file mode 100644
index 0000000000..41fc2d8581
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_single/00-assert-zookeeper.yaml
@@ -0,0 +1,49 @@
+# 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.
+#
+# Asserts on the ZooKeeper portion of the deployment.
+#
+---
+# assert that there is a `ConfigMap` named "zookeeper-scripts-XXX"
+# TODO: kuttl does not support generated names
+#apiVersion: v1
+#kind: ConfigMap
+#metadata:
+# name: zookeeper-scripts-c94h8k249d
+---
+# assert that there is a `ConfigMap` named "zookeeper-quorum"
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: zookeeper-quorum
+---
+# assert that there is a `PodDisruptionBudget` named "zookeeper-pdb"
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+ name: zookeeper-pdb
+---
+# assert that there is a `StatefulSet` named "zookeeper" that:
+# - provides pods labeled role:zookeeper
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: zookeeper
+spec:
+ template:
+ metadata:
+ labels:
+ role: zookeeper
diff --git a/hbase-kubernetes-deployment/tests/unit/components_zookeeper_single/00-kustomize.yaml b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_single/00-kustomize.yaml
new file mode 100644
index 0000000000..b365471f5f
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_single/00-kustomize.yaml
@@ -0,0 +1,21 @@
+# 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: kuttl.dev/v1beta1
+kind: TestStep
+
+commands:
+- script: ../../bin/kustomize_into_tmpdir.sh
diff --git a/hbase-kubernetes-deployment/tests/unit/components_zookeeper_single/kustomization.yaml b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_single/kustomization.yaml
new file mode 100644
index 0000000000..e70699d316
--- /dev/null
+++ b/hbase-kubernetes-deployment/tests/unit/components_zookeeper_single/kustomization.yaml
@@ -0,0 +1,21 @@
+# 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: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+components:
+ - ../../../components/zookeeper/single-instance
diff --git a/pom.xml b/pom.xml
index bd3637ad18..3bfeff5b07 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,6 +56,7 @@
hbase-table-reporter
hbase-hbck2
+ hbase-kubernetes-deployment
hbase-operator-tools-assembly