diff --git a/addons-cluster/hadoop/.helmignore b/addons-cluster/hadoop/.helmignore
new file mode 100644
index 0000000000..691fa13d6a
--- /dev/null
+++ b/addons-cluster/hadoop/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
\ No newline at end of file
diff --git a/addons-cluster/hadoop/Chart.yaml b/addons-cluster/hadoop/Chart.yaml
new file mode 100644
index 0000000000..2979cdb6d8
--- /dev/null
+++ b/addons-cluster/hadoop/Chart.yaml
@@ -0,0 +1,25 @@
+annotations:
+ category: BigData
+ kubeblocks.io/min-version: "1.1.0"
+apiVersion: v2
+name: hadoop
+type: application
+version: 1.1.0-alpha.0
+description: A Hadoop HDFS cluster Helm chart for KubeBlocks.
+dependencies:
+ - name: kblib
+ version: 0.1.2
+ repository: file://../kblib
+ alias: extra
+appVersion: "3.3.4"
+keywords:
+ - hadoop
+ - hdfs
+ - bigdata
+home: https://github.com/apecloud/kubeblocks/tree/main/deploy/hadoop
+icon: https://kubeblocks.io/img/logo.png
+maintainers:
+ - name: ApeCloud
+ url: https://kubeblocks.io/
+sources:
+ - https://github.com/apecloud/kubeblocks/
diff --git a/addons-cluster/hadoop/releases_notes.yaml b/addons-cluster/hadoop/releases_notes.yaml
new file mode 100644
index 0000000000..c07f490f76
--- /dev/null
+++ b/addons-cluster/hadoop/releases_notes.yaml
@@ -0,0 +1,7 @@
+releases:
+ - version: 1.1.0-alpha.0
+ notes:
+ en: >
+ Minimum supported KubeBlocks version is 1.1.0.
+ zh: >
+ 最低支持的 KubeBlocks 版本为 1.1.0。
diff --git a/addons-cluster/hadoop/templates/_helpers.tpl b/addons-cluster/hadoop/templates/_helpers.tpl
new file mode 100644
index 0000000000..73241d78f1
--- /dev/null
+++ b/addons-cluster/hadoop/templates/_helpers.tpl
@@ -0,0 +1,10 @@
+{{- define "hadoop-cluster.clusterCommon" }}
+apiVersion: apps.kubeblocks.io/v1
+kind: Cluster
+metadata:
+ name: {{ include "kblib.clusterName" . }}
+ namespace: {{ .Release.Namespace }}
+ labels: {{ include "kblib.clusterLabels" . | nindent 4 }}
+spec:
+ terminationPolicy: {{ .Values.extra.terminationPolicy }}
+{{- end }}
\ No newline at end of file
diff --git a/addons-cluster/hadoop/templates/cluster.yaml b/addons-cluster/hadoop/templates/cluster.yaml
new file mode 100644
index 0000000000..0c305962d1
--- /dev/null
+++ b/addons-cluster/hadoop/templates/cluster.yaml
@@ -0,0 +1,261 @@
+{{- $isCluster := eq .Values.topology "cluster" }}
+{{- $isStandalone := eq .Values.topology "standalone" }}
+{{- $haNameNodeIds := splitList "," .Values.hdfs.ha.nameNodeIds }}
+{{- if not (or $isCluster $isStandalone) }}
+{{- fail "topology must be either 'cluster' or 'standalone'" }}
+{{- end }}
+{{- if and $isCluster (ne (.Values.replicas.namenode | int) 2) }}
+{{- fail "cluster topology requires replicas.namenode = 2; this addon currently supports only active/standby NameNode HA" }}
+{{- end }}
+{{- if and $isCluster (ne (len $haNameNodeIds) 2) }}
+{{- fail "cluster topology requires exactly 2 hdfs.ha.nameNodeIds entries while active/standby NameNode HA is enforced" }}
+{{- end }}
+{{- include "hadoop-cluster.clusterCommon" . }}
+ clusterDef: hadoop
+ topology: {{ .Values.topology }}
+ componentSpecs:
+{{- if $isCluster }}
+ - name: journalnode
+ componentDef: hdfs-journalnode
+ configs:
+ - name: hdfs-common-config
+ variables:
+ HDFS_TRASH_INTERVAL: {{ .Values.hdfs.trash.interval | quote }}
+ HDFS_HADOOP_TMP_DIR: {{ .Values.hdfs.core.hadoopTmpDir | quote }}
+ HDFS_SECURITY_AUTHENTICATION: {{ .Values.hdfs.security.authentication | quote }}
+ HDFS_SECURITY_AUTHORIZATION: {{ .Values.hdfs.security.authorization | quote }}
+ HDFS_HA_ZOOKEEPER_PARENT_ZNODE: {{ .Values.hdfs.ha.zookeeper.parentZnodePrefix | quote }}
+ HDFS_JMX_PORT: {{ .Values.hdfs.ports.journalnode.jmx | quote }}
+ HDFS_NAMENODE_JMX_PORT: {{ .Values.hdfs.ports.namenode.jmx | quote }}
+ HDFS_DATANODE_JMX_PORT: {{ .Values.hdfs.ports.datanode.jmx | quote }}
+ HDFS_JOURNALNODE_JMX_PORT: {{ .Values.hdfs.ports.journalnode.jmx | quote }}
+ HDFS_ZKFC_JMX_PORT: {{ .Values.hdfs.ports.zkfc.jmx | quote }}
+ HDFS_NAMENODE_HEAP: {{ .Values.hdfs.jvm.namenodeHeapSize | quote }}
+ HDFS_DATANODE_HEAP: {{ .Values.hdfs.jvm.datanodeHeapSize | quote }}
+ HDFS_JOURNALNODE_HEAP: {{ .Values.hdfs.jvm.journalnodeHeapSize | quote }}
+ HDFS_ZKFC_HEAP: {{ .Values.hdfs.jvm.zkfcHeapSize | quote }}
+ HDFS_HA_ZOOKEEPER_SESSION_TIMEOUT_MS: {{ .Values.hdfs.ha.zookeeper.sessionTimeoutMs | quote }}
+ HDFS_IPC_CLIENT_CONNECTION_MAX_IDLE_TIME_MS: {{ .Values.hdfs.ipc.clientConnectionMaxIdleTimeMs | quote }}
+ HDFS_IPC_CLIENT_CONNECT_TIMEOUT_MS: {{ .Values.hdfs.ipc.clientConnectTimeoutMs | quote }}
+ HDFS_IPC_CLIENT_CONNECTION_POOL_SIZE: {{ .Values.hdfs.ipc.clientConnectionPoolSize | quote }}
+ HDFS_IPC_CLIENT_CONNECT_RETRY_INTERVAL_MS: {{ .Values.hdfs.ipc.clientConnectRetryIntervalMs | quote }}
+ HDFS_IPC_CLIENT_PING: {{ .Values.hdfs.ipc.clientPing | quote }}
+ HDFS_IPC_PING_INTERVAL_MS: {{ .Values.hdfs.ipc.pingIntervalMs | quote }}
+ HDFS_HA_NAMENODE_IDS: {{ .Values.hdfs.ha.nameNodeIds | quote }}
+ - name: journalnode-config
+ variables:
+ HDFS_JOURNALNODE_EDITS_DIR: {{ .Values.hdfs.paths.journalnodeEditsDir | quote }}
+ HDFS_JOURNALNODE_RPC_PORT: {{ .Values.hdfs.ports.journalnode.rpc | quote }}
+ HDFS_JOURNALNODE_HTTP_PORT: {{ .Values.hdfs.ports.journalnode.http | quote }}
+ HDFS_JOURNALNODE_ENABLE_SYNC: {{ .Values.hdfs.journalnode.enableSync | quote }}
+ HDFS_JOURNALNODE_EDIT_CACHE_SIZE_BYTES: {{ .Values.hdfs.journalnode.editCacheSizeBytes | quote }}
+ HDFS_JOURNALNODE_SYNC_INTERVAL_MS: {{ .Values.hdfs.journalnode.syncIntervalMs | quote }}
+ replicas: {{ .Values.replicas.journalnode }}
+ resources:
+ requests:
+ cpu: {{ .Values.resources.journalnode.requests.cpu | quote }}
+ memory: {{ .Values.resources.journalnode.requests.memory }}
+ limits:
+ cpu: {{ .Values.resources.journalnode.limits.cpu | quote }}
+ memory: {{ .Values.resources.journalnode.limits.memory }}
+ schedulingPolicy:
+ topologySpreadConstraints:
+ - maxSkew: 1
+ topologyKey: kubernetes.io/hostname
+ whenUnsatisfiable: DoNotSchedule
+ labelSelector:
+ matchLabels:
+ apps.kubeblocks.io/component-name: journalnode
+ volumeClaimTemplates:
+ - name: edits-dir
+ spec:
+ accessModes:
+{{ toYaml .Values.storage.journalnode.accessModes | indent 14 }}
+ resources:
+ requests:
+ storage: {{ .Values.storage.journalnode.size }}
+{{- if .Values.storage.journalnode.storageClassName }}
+ storageClassName: {{ .Values.storage.journalnode.storageClassName }}
+{{- end }}
+{{- end }}
+ - name: namenode
+ componentDef: {{ ternary "hdfs-namenode" "hdfs-namenode-standalone" $isCluster }}
+{{- if $isCluster }}
+ serviceRefs:
+ - name: hadoopZookeeper
+ namespace: {{ .Values.serviceRefs.hadoopZookeeper.namespace }}
+ clusterServiceSelector:
+ cluster: {{ .Values.serviceRefs.hadoopZookeeper.clusterServiceSelector.cluster }}
+ service:
+ component: {{ .Values.serviceRefs.hadoopZookeeper.clusterServiceSelector.service.component }}
+ service: {{ .Values.serviceRefs.hadoopZookeeper.clusterServiceSelector.service.service }}
+ port: {{ .Values.serviceRefs.hadoopZookeeper.clusterServiceSelector.service.port }}
+{{- end }}
+ configs:
+ - name: hdfs-common-config
+ variables:
+ HDFS_TRASH_INTERVAL: {{ .Values.hdfs.trash.interval | quote }}
+ HDFS_HADOOP_TMP_DIR: {{ .Values.hdfs.core.hadoopTmpDir | quote }}
+ HDFS_SECURITY_AUTHENTICATION: {{ .Values.hdfs.security.authentication | quote }}
+ HDFS_SECURITY_AUTHORIZATION: {{ .Values.hdfs.security.authorization | quote }}
+ HDFS_HA_ZOOKEEPER_PARENT_ZNODE: {{ .Values.hdfs.ha.zookeeper.parentZnodePrefix | quote }}
+ HDFS_JMX_PORT: {{ .Values.hdfs.ports.namenode.jmx | quote }}
+ HDFS_NAMENODE_JMX_PORT: {{ .Values.hdfs.ports.namenode.jmx | quote }}
+ HDFS_DATANODE_JMX_PORT: {{ .Values.hdfs.ports.datanode.jmx | quote }}
+ HDFS_JOURNALNODE_JMX_PORT: {{ .Values.hdfs.ports.journalnode.jmx | quote }}
+ HDFS_ZKFC_JMX_PORT: {{ .Values.hdfs.ports.zkfc.jmx | quote }}
+ HDFS_NAMENODE_HEAP: {{ .Values.hdfs.jvm.namenodeHeapSize | quote }}
+ HDFS_DATANODE_HEAP: {{ .Values.hdfs.jvm.datanodeHeapSize | quote }}
+ HDFS_JOURNALNODE_HEAP: {{ .Values.hdfs.jvm.journalnodeHeapSize | quote }}
+ HDFS_ZKFC_HEAP: {{ .Values.hdfs.jvm.zkfcHeapSize | quote }}
+ HDFS_IPC_CLIENT_CONNECTION_MAX_IDLE_TIME_MS: {{ .Values.hdfs.ipc.clientConnectionMaxIdleTimeMs | quote }}
+ HDFS_IPC_CLIENT_CONNECT_TIMEOUT_MS: {{ .Values.hdfs.ipc.clientConnectTimeoutMs | quote }}
+ HDFS_IPC_CLIENT_CONNECTION_POOL_SIZE: {{ .Values.hdfs.ipc.clientConnectionPoolSize | quote }}
+ HDFS_IPC_CLIENT_CONNECT_RETRY_INTERVAL_MS: {{ .Values.hdfs.ipc.clientConnectRetryIntervalMs | quote }}
+ HDFS_IPC_CLIENT_PING: {{ .Values.hdfs.ipc.clientPing | quote }}
+ HDFS_IPC_PING_INTERVAL_MS: {{ .Values.hdfs.ipc.pingIntervalMs | quote }}
+ HDFS_HA_NAMENODE_IDS: {{ .Values.hdfs.ha.nameNodeIds | quote }}
+{{- if $isCluster }}
+ HDFS_HA_ZOOKEEPER_SESSION_TIMEOUT_MS: {{ .Values.hdfs.ha.zookeeper.sessionTimeoutMs | quote }}
+{{- else }}
+ HDFS_NAMENODE_RPC_PORT: {{ .Values.hdfs.ports.namenode.rpc | quote }}
+{{- end }}
+ - name: namenode-config
+ variables:
+ HDFS_NAMENODE_NAME_DIR: {{ .Values.hdfs.paths.namenodeMetadataDir | quote }}
+ HDFS_NAMENODE_RPC_PORT: {{ .Values.hdfs.ports.namenode.rpc | quote }}
+ HDFS_NAMENODE_HTTP_PORT: {{ .Values.hdfs.ports.namenode.http | quote }}
+ HDFS_NAMENODE_HANDLER_COUNT: {{ .Values.hdfs.namenode.handlerCount | quote }}
+ HDFS_PERMISSIONS_ENABLED: {{ .Values.hdfs.permissions.enabled | quote }}
+ HDFS_PERMISSIONS_SUPERUSERGROUP: {{ .Values.hdfs.permissions.superusergroup | quote }}
+ HDFS_REGISTRATION_IP_HOSTNAME_CHECK: {{ .Values.hdfs.registration.ipHostnameCheck | quote }}
+ HDFS_NAMENODE_WEBHDFS_ENABLED: {{ .Values.hdfs.namenode.webhdfsEnabled | quote }}
+ HDFS_NAMENODE_RESOURCE_DU_RESERVED: {{ .Values.hdfs.namenode.resourceDuReserved | quote }}
+ HDFS_CLIENT_RETRY_POLICY_ENABLED: {{ .Values.hdfs.client.retryPolicyEnabled | quote }}
+ HDFS_CLIENT_RETRY_POLICY_SPEC: {{ .Values.hdfs.client.retryPolicySpec | quote }}
+{{- if $isCluster }}
+ HDFS_REPLICATION: {{ .Values.hdfs.replication | quote }}
+ HDFS_REPLICATION_MAX: {{ .Values.hdfs.replicationMax | quote }}
+ HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY: {{ .Values.hdfs.client.replaceDatanodeOnFailurePolicy | quote }}
+ HDFS_JOURNALNODE_RPC_PORT: {{ .Values.hdfs.ports.journalnode.rpc | quote }}
+ HDFS_HA_AUTOMATIC_FAILOVER_ENABLED: {{ .Values.hdfs.ha.automaticFailoverEnabled | quote }}
+ HDFS_HA_FENCING_METHODS: {{ .Values.hdfs.ha.fencingMethods | quote }}
+ HDFS_HA_FENCING_SSH_CONNECT_TIMEOUT_MS: {{ .Values.hdfs.ha.fencingSshConnectTimeoutMs | quote }}
+ HDFS_HA_ZOOKEEPER_SESSION_TIMEOUT_MS: {{ .Values.hdfs.ha.zookeeper.sessionTimeoutMs | quote }}
+ HDFS_HA_ZOOKEEPER_OPERATION_RETRIES: {{ .Values.hdfs.ha.zookeeper.operationRetries | quote }}
+ HDFS_HA_NAMENODE_IDS: {{ .Values.hdfs.ha.nameNodeIds | quote }}
+ HDFS_HA_LOG_ROLL_PERIOD: {{ .Values.hdfs.namenode.haLogRollPeriod | quote }}
+ HDFS_HA_TAIL_EDITS_PERIOD: {{ .Values.hdfs.namenode.haTailEditsPeriod | quote }}
+{{- else }}
+ HDFS_REPLICATION: "1"
+ HDFS_REPLICATION_MAX: "1"
+ HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY: "NEVER"
+{{- end }}
+ replicas: {{ ternary (.Values.replicas.namenode | int) 1 $isCluster }}
+ resources:
+ requests:
+ cpu: {{ .Values.resources.namenode.requests.cpu | quote }}
+ memory: {{ .Values.resources.namenode.requests.memory }}
+ limits:
+ cpu: {{ .Values.resources.namenode.limits.cpu | quote }}
+ memory: {{ .Values.resources.namenode.limits.memory }}
+{{- if $isCluster }}
+ schedulingPolicy:
+ topologySpreadConstraints:
+ - maxSkew: 1
+ topologyKey: kubernetes.io/hostname
+ whenUnsatisfiable: DoNotSchedule
+ labelSelector:
+ matchLabels:
+ apps.kubeblocks.io/component-name: namenode
+{{- end }}
+ volumeClaimTemplates:
+ - name: metadata-dir
+ spec:
+ accessModes:
+{{ toYaml .Values.storage.namenode.accessModes | indent 14 }}
+ resources:
+ requests:
+ storage: {{ .Values.storage.namenode.size }}
+{{- if .Values.storage.namenode.storageClassName }}
+ storageClassName: {{ .Values.storage.namenode.storageClassName }}
+{{- end }}
+ - name: datanode
+ componentDef: {{ ternary "hdfs-datanode" "hdfs-datanode-standalone" $isCluster }}
+ configs:
+ - name: hdfs-common-config
+ variables:
+ HDFS_TRASH_INTERVAL: {{ .Values.hdfs.trash.interval | quote }}
+ HDFS_HADOOP_TMP_DIR: {{ .Values.hdfs.core.hadoopTmpDir | quote }}
+ HDFS_SECURITY_AUTHENTICATION: {{ .Values.hdfs.security.authentication | quote }}
+ HDFS_SECURITY_AUTHORIZATION: {{ .Values.hdfs.security.authorization | quote }}
+ HDFS_HA_ZOOKEEPER_PARENT_ZNODE: {{ .Values.hdfs.ha.zookeeper.parentZnodePrefix | quote }}
+ HDFS_JMX_PORT: {{ .Values.hdfs.ports.datanode.jmx | quote }}
+ HDFS_NAMENODE_JMX_PORT: {{ .Values.hdfs.ports.namenode.jmx | quote }}
+ HDFS_DATANODE_JMX_PORT: {{ .Values.hdfs.ports.datanode.jmx | quote }}
+ HDFS_JOURNALNODE_JMX_PORT: {{ .Values.hdfs.ports.journalnode.jmx | quote }}
+ HDFS_ZKFC_JMX_PORT: {{ .Values.hdfs.ports.zkfc.jmx | quote }}
+ HDFS_NAMENODE_HEAP: {{ .Values.hdfs.jvm.namenodeHeapSize | quote }}
+ HDFS_DATANODE_HEAP: {{ .Values.hdfs.jvm.datanodeHeapSize | quote }}
+ HDFS_JOURNALNODE_HEAP: {{ .Values.hdfs.jvm.journalnodeHeapSize | quote }}
+ HDFS_ZKFC_HEAP: {{ .Values.hdfs.jvm.zkfcHeapSize | quote }}
+ HDFS_IPC_CLIENT_CONNECTION_MAX_IDLE_TIME_MS: {{ .Values.hdfs.ipc.clientConnectionMaxIdleTimeMs | quote }}
+ HDFS_IPC_CLIENT_CONNECT_TIMEOUT_MS: {{ .Values.hdfs.ipc.clientConnectTimeoutMs | quote }}
+ HDFS_IPC_CLIENT_CONNECTION_POOL_SIZE: {{ .Values.hdfs.ipc.clientConnectionPoolSize | quote }}
+ HDFS_IPC_CLIENT_CONNECT_RETRY_INTERVAL_MS: {{ .Values.hdfs.ipc.clientConnectRetryIntervalMs | quote }}
+ HDFS_IPC_CLIENT_PING: {{ .Values.hdfs.ipc.clientPing | quote }}
+ HDFS_IPC_PING_INTERVAL_MS: {{ .Values.hdfs.ipc.pingIntervalMs | quote }}
+ HDFS_HA_NAMENODE_IDS: {{ .Values.hdfs.ha.nameNodeIds | quote }}
+{{- if not $isCluster }}
+ HDFS_NAMENODE_RPC_PORT: {{ .Values.hdfs.ports.namenode.rpc | quote }}
+{{- end }}
+ - name: datanode-config
+ variables:
+ HDFS_DATANODE_DATA_DIR: {{ .Values.hdfs.paths.datanodeDataDir | quote }}
+ HDFS_NAMENODE_RPC_PORT: {{ .Values.hdfs.ports.namenode.rpc | quote }}
+ HDFS_NAMENODE_HTTP_PORT: {{ .Values.hdfs.ports.namenode.http | quote }}
+ HDFS_DATANODE_HANDLER_COUNT: {{ .Values.hdfs.datanode.handlerCount | quote }}
+ HDFS_DATANODE_FAILED_VOLUMES_TOLERATED: {{ .Values.hdfs.datanode.failedVolumesTolerated | quote }}
+ HDFS_DATANODE_DU_RESERVED: {{ .Values.hdfs.datanode.duReserved | quote }}
+ HDFS_PERMISSIONS_ENABLED: {{ .Values.hdfs.permissions.enabled | quote }}
+ HDFS_HA_NAMENODE_IDS: {{ .Values.hdfs.ha.nameNodeIds | quote }}
+ HDFS_CLIENT_RETRY_POLICY_ENABLED: {{ .Values.hdfs.client.retryPolicyEnabled | quote }}
+ HDFS_CLIENT_RETRY_POLICY_SPEC: {{ .Values.hdfs.client.retryPolicySpec | quote }}
+{{- if $isCluster }}
+ HDFS_REPLICATION: {{ .Values.hdfs.replication | quote }}
+ HDFS_REPLICATION_MAX: {{ .Values.hdfs.replicationMax | quote }}
+ HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY: {{ .Values.hdfs.client.replaceDatanodeOnFailurePolicy | quote }}
+{{- else }}
+ HDFS_REPLICATION: "1"
+ HDFS_REPLICATION_MAX: "1"
+ HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY: "NEVER"
+{{- end }}
+ replicas: {{ ternary (.Values.replicas.datanode | int) 1 $isCluster }}
+ resources:
+ requests:
+ cpu: {{ .Values.resources.datanode.requests.cpu | quote }}
+ memory: {{ .Values.resources.datanode.requests.memory }}
+ limits:
+ cpu: {{ .Values.resources.datanode.limits.cpu | quote }}
+ memory: {{ .Values.resources.datanode.limits.memory }}
+{{- if $isCluster }}
+ schedulingPolicy:
+ topologySpreadConstraints:
+ - maxSkew: 1
+ topologyKey: kubernetes.io/hostname
+ whenUnsatisfiable: DoNotSchedule
+ labelSelector:
+ matchLabels:
+ apps.kubeblocks.io/component-name: datanode
+{{- end }}
+ volumeClaimTemplates:
+ - name: hdfs-data-0
+ spec:
+ accessModes:
+{{ toYaml .Values.storage.datanode.accessModes | indent 14 }}
+ resources:
+ requests:
+ storage: {{ .Values.storage.datanode.size }}
+{{- if .Values.storage.datanode.storageClassName }}
+ storageClassName: {{ .Values.storage.datanode.storageClassName }}
+{{- end }}
diff --git a/addons-cluster/hadoop/templates/prometheus/monitor.yaml b/addons-cluster/hadoop/templates/prometheus/monitor.yaml
new file mode 100644
index 0000000000..95adf6f28c
--- /dev/null
+++ b/addons-cluster/hadoop/templates/prometheus/monitor.yaml
@@ -0,0 +1,20 @@
+{{- if and (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1/PodMonitor") .Values.prometheus.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: PodMonitor
+metadata:
+ name: {{ include "kblib.clusterName" . }}-metrics-monitor
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "kblib.clusterLabels" . | nindent 4 }}
+spec:
+ podMetricsEndpoints:
+ - path: /metrics
+ port: http-metrics
+ scheme: http
+ namespaceSelector:
+ matchNames:
+ - {{ .Release.Namespace }}
+ selector:
+ matchLabels:
+ app.kubernetes.io/instance: {{ include "kblib.clusterName" . | quote }}
+{{- end }}
diff --git a/addons-cluster/hadoop/values.schema.json b/addons-cluster/hadoop/values.schema.json
new file mode 100644
index 0000000000..13ff4157eb
--- /dev/null
+++ b/addons-cluster/hadoop/values.schema.json
@@ -0,0 +1,246 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "type": "object",
+ "properties": {
+ "topology": {
+ "type": "string",
+ "enum": ["standalone", "cluster"],
+ "default": "cluster"
+ },
+ "replicas": {
+ "type": "object",
+ "properties": {
+ "core": { "type": "integer", "default": 1, "minimum": 1 },
+ "journalnode": { "type": "integer", "default": 3, "minimum": 3 },
+ "namenode": { "type": "integer", "default": 2, "minimum": 1, "maximum": 2 },
+ "datanode": { "type": "integer", "default": 1, "minimum": 1 }
+ }
+ },
+ "resources": {
+ "type": "object",
+ "properties": {
+ "core": { "$ref": "#/definitions/resourceSchema" },
+ "journalnode": { "$ref": "#/definitions/resourceSchema" },
+ "namenode": { "$ref": "#/definitions/resourceSchema" },
+ "datanode": { "$ref": "#/definitions/resourceSchema" }
+ }
+ },
+ "storage": {
+ "type": "object",
+ "properties": {
+ "journalnode": { "$ref": "#/definitions/storageSchema" },
+ "namenode": { "$ref": "#/definitions/storageSchema" },
+ "datanode": { "$ref": "#/definitions/storageSchema" }
+ }
+ },
+ "hdfs": {
+ "type": "object",
+ "properties": {
+ "ports": {
+ "type": "object",
+ "properties": {
+ "namenode": {
+ "type": "object",
+ "properties": {
+ "rpc": { "type": "integer", "default": 8020, "minimum": 1, "maximum": 65535 },
+ "http": { "type": "integer", "default": 9870, "minimum": 1, "maximum": 65535 },
+ "jmx": { "type": "integer", "default": 10101, "minimum": 1, "maximum": 65535 }
+ }
+ },
+ "journalnode": {
+ "type": "object",
+ "properties": {
+ "rpc": { "type": "integer", "default": 8485, "minimum": 1, "maximum": 65535 },
+ "http": { "type": "integer", "default": 8480, "minimum": 1, "maximum": 65535 },
+ "jmx": { "type": "integer", "default": 10103, "minimum": 1, "maximum": 65535 }
+ }
+ },
+ "datanode": {
+ "type": "object",
+ "properties": {
+ "jmx": { "type": "integer", "default": 10102, "minimum": 1, "maximum": 65535 }
+ }
+ },
+ "zkfc": {
+ "type": "object",
+ "properties": {
+ "jmx": { "type": "integer", "default": 10104, "minimum": 1, "maximum": 65535 }
+ }
+ }
+ }
+ },
+ "paths": {
+ "type": "object",
+ "properties": {
+ "namenodeMetadataDir": { "type": "string", "default": "/hadoop/dfs/metadata" },
+ "datanodeDataDir": { "type": "string", "default": "/hadoop/dfs/data0" },
+ "journalnodeEditsDir": { "type": "string", "default": "/hadoop/dfs/journal" }
+ }
+ },
+ "core": {
+ "type": "object",
+ "properties": {
+ "hadoopTmpDir": { "type": "string", "default": "/hadoop/tmp" }
+ }
+ },
+ "replication": { "type": "integer", "default": 1, "minimum": 1 },
+ "replicationMax": { "type": "integer", "default": 6, "minimum": 1 },
+ "client": {
+ "type": "object",
+ "properties": {
+ "replaceDatanodeOnFailurePolicy": {
+ "type": "string",
+ "enum": ["NEVER", "DEFAULT", "ALWAYS"],
+ "default": "NEVER"
+ },
+ "retryPolicyEnabled": { "type": "boolean", "default": true },
+ "retryPolicySpec": { "type": "string", "default": "1000,1" }
+ }
+ },
+ "permissions": {
+ "type": "object",
+ "properties": {
+ "enabled": { "type": "boolean", "default": false },
+ "superusergroup": { "type": "string", "default": "hadoop" }
+ }
+ },
+ "security": {
+ "type": "object",
+ "properties": {
+ "authentication": { "type": "string", "default": "simple" },
+ "authorization": { "type": "boolean", "default": false }
+ }
+ },
+ "registration": {
+ "type": "object",
+ "properties": {
+ "ipHostnameCheck": { "type": "boolean", "default": false }
+ }
+ },
+ "ha": {
+ "type": "object",
+ "properties": {
+ "nameNodeIds": { "type": "string", "default": "nn0,nn1" },
+ "automaticFailoverEnabled": { "type": "boolean", "default": true },
+ "fencingMethods": { "type": "string", "default": "shell(/bin/true)" },
+ "fencingSshConnectTimeoutMs": { "type": "integer", "default": 30000, "minimum": 1 },
+ "zookeeper": {
+ "type": "object",
+ "properties": {
+ "parentZnodePrefix": { "type": "string", "default": "/hadoop-ha" },
+ "includeClusterUID": { "type": "boolean", "default": true },
+ "sessionTimeoutMs": { "type": "integer", "default": 60000, "minimum": 1 },
+ "operationRetries": { "type": "integer", "default": 3, "minimum": 0 }
+ }
+ }
+ }
+ },
+ "journalnode": {
+ "type": "object",
+ "properties": {
+ "enableSync": { "type": "boolean", "default": true },
+ "editCacheSizeBytes": { "type": "integer", "default": 104857600, "minimum": 1 },
+ "syncIntervalMs": { "type": "integer", "default": 120000, "minimum": 1 }
+ }
+ },
+ "ipc": {
+ "type": "object",
+ "properties": {
+ "clientConnectionMaxIdleTimeMs": { "type": "integer", "default": 300000, "minimum": 1 },
+ "clientConnectTimeoutMs": { "type": "integer", "default": 20000, "minimum": 1 },
+ "clientConnectionPoolSize": { "type": "integer", "default": 8, "minimum": 1 },
+ "clientConnectRetryIntervalMs": { "type": "integer", "default": 1000, "minimum": 1 },
+ "clientPing": { "type": "boolean", "default": true },
+ "pingIntervalMs": { "type": "integer", "default": 30000, "minimum": 1 }
+ }
+ },
+ "namenode": {
+ "type": "object",
+ "properties": {
+ "handlerCount": { "type": "integer", "default": 64, "minimum": 1 },
+ "webhdfsEnabled": { "type": "boolean", "default": false },
+ "resourceDuReserved": { "type": "integer", "default": 1073741824, "minimum": 0 },
+ "haLogRollPeriod": { "type": "integer", "default": 120, "minimum": 0 },
+ "haTailEditsPeriod": { "type": "integer", "default": 60, "minimum": 0 }
+ }
+ },
+ "datanode": {
+ "type": "object",
+ "properties": {
+ "handlerCount": { "type": "integer", "default": 64, "minimum": 1 },
+ "failedVolumesTolerated": { "type": "integer", "default": 0, "minimum": 0 },
+ "duReserved": { "type": "integer", "default": 1073741824, "minimum": 0 }
+ }
+ }
+ }
+ },
+ "serviceRefs": {
+ "type": "object",
+ "properties": {
+ "hadoopZookeeper": {
+ "type": "object",
+ "properties": {
+ "namespace": { "type": "string", "default": "kubeblocks" },
+ "clusterServiceSelector": {
+ "type": "object",
+ "properties": {
+ "cluster": { "type": "string", "default": "zk" },
+ "service": {
+ "type": "object",
+ "properties": {
+ "component": { "type": "string", "default": "zookeeper" },
+ "service": { "type": "string", "default": "headless" },
+ "port": { "type": "string", "default": "client" }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "prometheus": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ },
+ "definitions": {
+ "resourceSchema": {
+ "type": "object",
+ "properties": {
+ "requests": {
+ "type": "object",
+ "properties": {
+ "cpu": { "type": "string", "default": "0.5" },
+ "memory": { "type": "string", "default": "0.5Gi" }
+ }
+ },
+ "limits": {
+ "type": "object",
+ "properties": {
+ "cpu": { "type": "string", "default": "0.5" },
+ "memory": { "type": "string", "default": "2Gi" }
+ }
+ }
+ }
+ },
+ "storageSchema": {
+ "type": "object",
+ "properties": {
+ "size": { "type": "string", "default": "10Gi" },
+ "storageClassName": { "type": "string", "default": "" },
+ "accessModes": {
+ "type": "array",
+ "items": { "type": "string" },
+ "default": ["ReadWriteOnce"],
+ "minItems": 1
+ }
+ }
+ }
+ }
+}
diff --git a/addons-cluster/hadoop/values.yaml b/addons-cluster/hadoop/values.yaml
new file mode 100644
index 0000000000..4accdf7f40
--- /dev/null
+++ b/addons-cluster/hadoop/values.yaml
@@ -0,0 +1,142 @@
+topology: cluster
+
+replicas:
+ journalnode: 3
+ namenode: 2
+ datanode: 3
+
+resources:
+ journalnode:
+ requests:
+ cpu: "500m"
+ memory: 1Gi
+ limits:
+ cpu: "2"
+ memory: 2Gi
+ namenode:
+ requests:
+ cpu: "1"
+ memory: 2Gi
+ limits:
+ cpu: "4"
+ memory: 4Gi
+ datanode:
+ requests:
+ cpu: "500m"
+ memory: 1Gi
+ limits:
+ cpu: "2"
+ memory: 2Gi
+ zkfc:
+ requests:
+ cpu: "100m"
+ memory: 256Mi
+ limits:
+ cpu: "500m"
+ memory: 512Mi
+
+storage:
+ journalnode:
+ size: 20Gi
+ storageClassName: ""
+ accessModes:
+ - ReadWriteOnce
+ namenode:
+ size: 50Gi
+ storageClassName: ""
+ accessModes:
+ - ReadWriteOnce
+ datanode:
+ size: 100Gi
+ storageClassName: ""
+ accessModes:
+ - ReadWriteOnce
+
+hdfs:
+ core:
+ hadoopTmpDir: /hadoop/tmp
+ security:
+ authentication: simple
+ authorization: false
+ ports:
+ namenode:
+ rpc: 8020
+ http: 9870
+ jmx: 10101
+ journalnode:
+ rpc: 8485
+ http: 8480
+ jmx: 10103
+ datanode:
+ jmx: 10102
+ zkfc:
+ jmx: 10104
+ paths:
+ namenodeMetadataDir: /hadoop/dfs/metadata
+ datanodeDataDir: /hadoop/dfs/data0
+ journalnodeEditsDir: /hadoop/dfs/journal
+ replication: 3
+ replicationMax: 6
+ client:
+ replaceDatanodeOnFailurePolicy: DEFAULT
+ retryPolicyEnabled: true
+ retryPolicySpec: "1000,1"
+ permissions:
+ enabled: false
+ superusergroup: hadoop
+ registration:
+ ipHostnameCheck: false
+ ha:
+ nameNodeIds: "nn0,nn1"
+ automaticFailoverEnabled: true
+ fencingMethods: "sshfence\nshell(/bin/true)"
+ fencingSshConnectTimeoutMs: 30000
+ zookeeper:
+ parentZnodePrefix: /hadoop-ha
+ includeClusterUID: true
+ sessionTimeoutMs: 60000
+ operationRetries: 3
+ ipc:
+ clientConnectionMaxIdleTimeMs: 300000
+ clientConnectTimeoutMs: 20000
+ clientConnectionPoolSize: 8
+ clientConnectRetryIntervalMs: 1000
+ clientPing: true
+ pingIntervalMs: 30000
+ trash:
+ interval: 1440
+ jvm:
+ namenodeHeapSize: "2g"
+ datanodeHeapSize: "1g"
+ journalnodeHeapSize: "1g"
+ zkfcHeapSize: "256m"
+ datanode:
+ handlerCount: 64
+ failedVolumesTolerated: 0
+ duReserved: 1073741824
+ namenode:
+ handlerCount: 64
+ webhdfsEnabled: false
+ resourceDuReserved: 1073741824
+ haLogRollPeriod: 120
+ haTailEditsPeriod: 60
+ journalnode:
+ enableSync: true
+ editCacheSizeBytes: 104857600
+ syncIntervalMs: 120000
+
+serviceRefs:
+ hadoopZookeeper:
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: zk
+ service:
+ component: zookeeper
+ service: headless
+ port: client
+
+prometheus:
+ enabled: false
+
+extra:
+ terminationPolicy: Delete
diff --git a/addons-cluster/hbase/.helmignore b/addons-cluster/hbase/.helmignore
new file mode 100644
index 0000000000..691fa13d6a
--- /dev/null
+++ b/addons-cluster/hbase/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
\ No newline at end of file
diff --git a/addons-cluster/hbase/Chart.yaml b/addons-cluster/hbase/Chart.yaml
new file mode 100644
index 0000000000..d374e67535
--- /dev/null
+++ b/addons-cluster/hbase/Chart.yaml
@@ -0,0 +1,25 @@
+annotations:
+ category: BigData
+ kubeblocks.io/min-version: "1.1.0"
+apiVersion: v2
+name: hbase-cluster
+type: application
+version: 1.1.0-alpha.0
+description: A HBase Helm chart for KubeBlocks.
+dependencies:
+ - name: kblib
+ version: 0.1.2
+ repository: file://../kblib
+ alias: extra
+appVersion: "2.5.6"
+keywords:
+ - hbase
+ - bigdata
+ - database
+home: https://github.com/apecloud/kubeblocks/tree/main/deploy/hbase
+icon: https://kubeblocks.io/img/logo.png
+maintainers:
+ - name: ApeCloud
+ url: https://kubeblocks.io/
+sources:
+ - https://github.com/apecloud/kubeblocks/
diff --git a/addons-cluster/hbase/releases_notes.yaml b/addons-cluster/hbase/releases_notes.yaml
new file mode 100644
index 0000000000..50ab69fe68
--- /dev/null
+++ b/addons-cluster/hbase/releases_notes.yaml
@@ -0,0 +1,10 @@
+releases:
+- version: 1.1.0
+ released_at: '2026-05-21'
+ status: stable
+ git_branch: release-1.1
+ git_tag: v1.1.0
+ commit_sha: ''
+ notes:
+ en: Minimum supported KubeBlocks version is 1.1.0.
+ zh: 最低支持的 KubeBlocks 版本为 1.1.0。
diff --git a/addons-cluster/hbase/templates/_helpers.tpl b/addons-cluster/hbase/templates/_helpers.tpl
new file mode 100644
index 0000000000..5ef39e6c78
--- /dev/null
+++ b/addons-cluster/hbase/templates/_helpers.tpl
@@ -0,0 +1,10 @@
+{{- define "hbase-cluster.clusterCommon" }}
+apiVersion: apps.kubeblocks.io/v1
+kind: Cluster
+metadata:
+ name: {{ include "kblib.clusterName" . }}
+ namespace: {{ .Release.Namespace }}
+ labels: {{ include "kblib.clusterLabels" . | nindent 4 }}
+spec:
+ terminationPolicy: {{ .Values.extra.terminationPolicy }}
+{{- end }}
\ No newline at end of file
diff --git a/addons-cluster/hbase/templates/cluster.yaml b/addons-cluster/hbase/templates/cluster.yaml
new file mode 100644
index 0000000000..a2fa20b47e
--- /dev/null
+++ b/addons-cluster/hbase/templates/cluster.yaml
@@ -0,0 +1,227 @@
+{{- $isCluster := eq .Values.topology "cluster" }}
+{{- $isStandalone := eq .Values.topology "standalone" }}
+{{- if not (or $isCluster $isStandalone) }}
+{{- fail "topology must be either 'cluster' or 'standalone'" }}
+{{- end }}
+{{- include "hbase-cluster.clusterCommon" . }}
+ clusterDef: hbase
+ topology: {{ .Values.topology }}
+ componentSpecs:
+{{- if $isCluster }}
+ - name: hmaster
+ componentDef: hbase-hmaster-2.5
+ serviceVersion: 2.5.6
+ replicas: {{ .Values.replicas.hmaster }}
+ serviceRefs:
+ - name: hbase-zookeeper
+ namespace: {{ .Values.serviceRefs.hbaseZookeeper.namespace }}
+ clusterServiceSelector:
+ cluster: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.cluster }}
+ service:
+ component: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.service.component }}
+ service: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.service.service }}
+ port: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.service.port }}
+ - name: hdfs-namenode
+ namespace: {{ .Values.serviceRefs.hdfsNamenode.namespace }}
+ clusterServiceSelector:
+ cluster: {{ .Values.serviceRefs.hdfsNamenode.clusterServiceSelector.cluster }}
+ service:
+ component: {{ .Values.serviceRefs.hdfsNamenode.clusterServiceSelector.service.component }}
+ service: {{ .Values.serviceRefs.hdfsNamenode.clusterServiceSelector.service.service }}
+ port: {{ .Values.serviceRefs.hdfsNamenode.clusterServiceSelector.service.port }}
+ configs:
+ - name: hbase-config
+ variables:
+ HDFS_NAMESERVICE: {{ .Values.serviceRefs.hdfsNamenode.clusterServiceSelector.cluster | quote }}
+ HDFS_NAMENODE_NODES: {{ .Values.hdfs.namenodeNodes | quote }}
+ HDFS_NAMENODE_RPC_PORT: {{ .Values.hdfs.namenodeRpcPort | quote }}
+ HDFS_NAMENODE_HTTP_PORT: {{ .Values.hdfs.namenodeHttpPort | quote }}
+ HDFS_HA_ZK_PARENT: {{ .Values.hdfs.haZkParent | quote }}
+ HDFS_REPLICATION: {{ .Values.hdfs.replication | quote }}
+ HDFS_PERMISSIONS_ENABLED: {{ .Values.hdfs.permissionsEnabled | quote }}
+ HDFS_FS_TRASH_INTERVAL: {{ .Values.hdfs.fs.trashInterval | quote }}
+ HADOOP_SECURITY_AUTHENTICATION: {{ .Values.hdfs.security.authentication | quote }}
+ HADOOP_SECURITY_AUTHORIZATION: {{ .Values.hdfs.security.authorization | quote }}
+ HADOOP_IPC_CLIENT_CONNECTION_MAXIDLETIME: {{ .Values.hdfs.ipc.clientConnectionMaxIdleTime | quote }}
+ HADOOP_IPC_CLIENT_CONNECT_TIMEOUT: {{ .Values.hdfs.ipc.clientConnectTimeout | quote }}
+ HADOOP_IPC_PING_INTERVAL: {{ .Values.hdfs.ipc.pingInterval | quote }}
+ HADOOP_TMP_DIR: {{ .Values.hdfs.paths.tmpDir | quote }}
+ HDFS_COMMON_CLIENT_RETRY_POLICY_ENABLED: {{ .Values.hdfs.client.commonRetryPolicy.enabled | quote }}
+ HDFS_COMMON_CLIENT_RETRY_POLICY_SPEC: {{ .Values.hdfs.client.commonRetryPolicy.spec | quote }}
+ HDFS_WEBHDFS_ENABLED: {{ .Values.hdfs.client.webhdfsEnabled | quote }}
+ HDFS_CLIENT_FAILOVER_MAX_ATTEMPTS: {{ .Values.hdfs.client.failoverMaxAttempts | quote }}
+ HDFS_CLIENT_FAILOVER_SLEEP_BASE_MILLIS: {{ .Values.hdfs.client.failoverSleepBaseMillis | quote }}
+ HDFS_CLIENT_FAILOVER_SLEEP_MAX_MILLIS: {{ .Values.hdfs.client.failoverSleepMaxMillis | quote }}
+ HBASE_HDFS_CLIENT_RETRY_POLICY_ENABLED: {{ .Values.hdfs.client.retryPolicy.enabled | quote }}
+ HBASE_HDFS_CLIENT_RETRY_POLICY_SPEC: {{ .Values.hdfs.client.retryPolicy.spec | quote }}
+ HBASE_IPC_CLIENT_CONNECT_TIMEOUT: {{ .Values.hdfs.hbaseClient.ipcClientConnectTimeout | quote }}
+ HBASE_IPC_CLIENT_CONNECT_MAX_RETRIES: {{ .Values.hdfs.hbaseClient.ipcClientConnectMaxRetries | quote }}
+ HBASE_ZOOKEEPER_SESSION_TIMEOUT: {{ .Values.hbase.zk.sessionTimeout | quote }}
+ HBASE_ZOOKEEPER_MAX_CLIENT_CNXNS: {{ .Values.hbase.zk.maxClientCnxns | quote }}
+ HBASE_REGIONSERVER_HANDLER_COUNT: {{ .Values.hbase.cluster.regionserverHandlerCount | quote }}
+ HBASE_HSTORE_FLUSHER_COUNT: {{ .Values.hbase.cluster.hstoreFlusherCount | quote }}
+ HBASE_CLIENT_SCANNER_CACHING: {{ .Values.hbase.common.clientScannerCaching | quote }}
+ HBASE_HREGION_MAX_FILESIZE: {{ .Values.hbase.cluster.regionMaxFileSize | quote }}
+ HBASE_HREGION_MEMSTORE_FLUSH_SIZE: {{ .Values.hbase.common.regionMemstoreFlushSize | quote }}
+ HBASE_HREGION_MAJORCOMPACTION: {{ .Values.hbase.cluster.regionMajorCompaction | quote }}
+ HBASE_MASTER_WAIT_ON_REGIONSERVERS_TIMEOUT: {{ .Values.hbase.cluster.masterWaitOnRegionserversTimeout | quote }}
+ HBASE_MASTER_STARTUP_RETAINASSIGN_TIMEOUT: {{ .Values.hbase.cluster.masterStartupRetainassignTimeout | quote }}
+ HBASE_OLDWALS_CLEANER_THREAD_TIMEOUT_MSEC: {{ .Values.hbase.cluster.oldWalsCleanerThreadTimeoutMsec | quote }}
+ HBASE_MASTER_LOGCLEANER_TTL: {{ .Values.hbase.cluster.masterLogCleanerTtl | quote }}
+ HBASE_MASTER_HFILECLEANER_TTL: {{ .Values.hbase.cluster.masterHfileCleanerTtl | quote }}
+ HBASE_BALANCER_PERIOD: {{ .Values.hbase.cluster.balancerPeriod | quote }}
+ HBASE_PROCEDURE_STORE_WAL_USE_HSYNC: {{ .Values.hbase.cluster.procedureStoreWalUseHsync | quote }}
+ HBASE_REGIONSERVER_OPTIONALCACHEFLUSHINTERVAL: {{ .Values.hbase.cluster.regionserverOptionalCacheFlushInterval | quote }}
+ HBASE_REGIONSERVER_STARTUP_RETRIES: {{ .Values.hbase.cluster.regionserverStartupRetries | quote }}
+ HBASE_REGIONSERVER_STARTUP_RETRY_INTERVAL: {{ .Values.hbase.cluster.regionserverStartupRetryInterval | quote }}
+ HBASE_REPLICATION_ENABLED: {{ .Values.hbase.cluster.replicationEnabled | quote }}
+ HBASE_SECURITY_AUTHENTICATION: {{ .Values.hbase.security.authentication | quote }}
+ HBASE_SECURITY_AUTHORIZATION: {{ .Values.hbase.security.authorization | quote }}
+ HBASE_SPLITLOG_MANAGER_TIMEOUT: {{ .Values.hbase.cluster.splitlogManagerTimeout | quote }}
+ resources:
+ requests:
+ cpu: {{ .Values.resources.hmaster.requests.cpu | quote }}
+ memory: {{ .Values.resources.hmaster.requests.memory }}
+ limits:
+ cpu: {{ .Values.resources.hmaster.limits.cpu | quote }}
+ memory: {{ .Values.resources.hmaster.limits.memory }}
+ schedulingPolicy:
+ topologySpreadConstraints:
+ - maxSkew: 1
+ topologyKey: kubernetes.io/hostname
+ whenUnsatisfiable: DoNotSchedule
+ labelSelector:
+ matchLabels:
+ apps.kubeblocks.io/component-name: hmaster
+ - name: hregionserver
+ componentDef: hbase-hregionserver-2.5
+ serviceVersion: 2.5.6
+ replicas: {{ .Values.replicas.hregionserver }}
+ serviceRefs:
+ - name: hbase-zookeeper
+ namespace: {{ .Values.serviceRefs.hbaseZookeeper.namespace }}
+ clusterServiceSelector:
+ cluster: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.cluster }}
+ service:
+ component: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.service.component }}
+ service: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.service.service }}
+ port: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.service.port }}
+ - name: hdfs-namenode
+ namespace: {{ .Values.serviceRefs.hdfsNamenode.namespace }}
+ clusterServiceSelector:
+ cluster: {{ .Values.serviceRefs.hdfsNamenode.clusterServiceSelector.cluster }}
+ service:
+ component: {{ .Values.serviceRefs.hdfsNamenode.clusterServiceSelector.service.component }}
+ service: {{ .Values.serviceRefs.hdfsNamenode.clusterServiceSelector.service.service }}
+ port: {{ .Values.serviceRefs.hdfsNamenode.clusterServiceSelector.service.port }}
+ configs:
+ - name: hbase-config
+ variables:
+ HDFS_NAMESERVICE: {{ .Values.serviceRefs.hdfsNamenode.clusterServiceSelector.cluster | quote }}
+ HDFS_NAMENODE_NODES: {{ .Values.hdfs.namenodeNodes | quote }}
+ HDFS_NAMENODE_RPC_PORT: {{ .Values.hdfs.namenodeRpcPort | quote }}
+ HDFS_NAMENODE_HTTP_PORT: {{ .Values.hdfs.namenodeHttpPort | quote }}
+ HDFS_HA_ZK_PARENT: {{ .Values.hdfs.haZkParent | quote }}
+ HDFS_REPLICATION: {{ .Values.hdfs.replication | quote }}
+ HDFS_PERMISSIONS_ENABLED: {{ .Values.hdfs.permissionsEnabled | quote }}
+ HDFS_FS_TRASH_INTERVAL: {{ .Values.hdfs.fs.trashInterval | quote }}
+ HADOOP_SECURITY_AUTHENTICATION: {{ .Values.hdfs.security.authentication | quote }}
+ HADOOP_SECURITY_AUTHORIZATION: {{ .Values.hdfs.security.authorization | quote }}
+ HADOOP_IPC_CLIENT_CONNECTION_MAXIDLETIME: {{ .Values.hdfs.ipc.clientConnectionMaxIdleTime | quote }}
+ HADOOP_IPC_CLIENT_CONNECT_TIMEOUT: {{ .Values.hdfs.ipc.clientConnectTimeout | quote }}
+ HADOOP_IPC_PING_INTERVAL: {{ .Values.hdfs.ipc.pingInterval | quote }}
+ HADOOP_TMP_DIR: {{ .Values.hdfs.paths.tmpDir | quote }}
+ HDFS_COMMON_CLIENT_RETRY_POLICY_ENABLED: {{ .Values.hdfs.client.commonRetryPolicy.enabled | quote }}
+ HDFS_COMMON_CLIENT_RETRY_POLICY_SPEC: {{ .Values.hdfs.client.commonRetryPolicy.spec | quote }}
+ HDFS_WEBHDFS_ENABLED: {{ .Values.hdfs.client.webhdfsEnabled | quote }}
+ HDFS_CLIENT_FAILOVER_MAX_ATTEMPTS: {{ .Values.hdfs.client.failoverMaxAttempts | quote }}
+ HDFS_CLIENT_FAILOVER_SLEEP_BASE_MILLIS: {{ .Values.hdfs.client.failoverSleepBaseMillis | quote }}
+ HDFS_CLIENT_FAILOVER_SLEEP_MAX_MILLIS: {{ .Values.hdfs.client.failoverSleepMaxMillis | quote }}
+ HBASE_HDFS_CLIENT_RETRY_POLICY_ENABLED: {{ .Values.hdfs.client.retryPolicy.enabled | quote }}
+ HBASE_HDFS_CLIENT_RETRY_POLICY_SPEC: {{ .Values.hdfs.client.retryPolicy.spec | quote }}
+ HBASE_IPC_CLIENT_CONNECT_TIMEOUT: {{ .Values.hdfs.hbaseClient.ipcClientConnectTimeout | quote }}
+ HBASE_IPC_CLIENT_CONNECT_MAX_RETRIES: {{ .Values.hdfs.hbaseClient.ipcClientConnectMaxRetries | quote }}
+ HBASE_ZOOKEEPER_SESSION_TIMEOUT: {{ .Values.hbase.zk.sessionTimeout | quote }}
+ HBASE_ZOOKEEPER_MAX_CLIENT_CNXNS: {{ .Values.hbase.zk.maxClientCnxns | quote }}
+ HBASE_REGIONSERVER_HANDLER_COUNT: {{ .Values.hbase.cluster.regionserverHandlerCount | quote }}
+ HBASE_HSTORE_FLUSHER_COUNT: {{ .Values.hbase.cluster.hstoreFlusherCount | quote }}
+ HBASE_CLIENT_SCANNER_CACHING: {{ .Values.hbase.common.clientScannerCaching | quote }}
+ HBASE_HREGION_MAX_FILESIZE: {{ .Values.hbase.cluster.regionMaxFileSize | quote }}
+ HBASE_HREGION_MEMSTORE_FLUSH_SIZE: {{ .Values.hbase.common.regionMemstoreFlushSize | quote }}
+ HBASE_HREGION_MAJORCOMPACTION: {{ .Values.hbase.cluster.regionMajorCompaction | quote }}
+ HBASE_MASTER_WAIT_ON_REGIONSERVERS_TIMEOUT: {{ .Values.hbase.cluster.masterWaitOnRegionserversTimeout | quote }}
+ HBASE_MASTER_STARTUP_RETAINASSIGN_TIMEOUT: {{ .Values.hbase.cluster.masterStartupRetainassignTimeout | quote }}
+ HBASE_OLDWALS_CLEANER_THREAD_TIMEOUT_MSEC: {{ .Values.hbase.cluster.oldWalsCleanerThreadTimeoutMsec | quote }}
+ HBASE_MASTER_LOGCLEANER_TTL: {{ .Values.hbase.cluster.masterLogCleanerTtl | quote }}
+ HBASE_MASTER_HFILECLEANER_TTL: {{ .Values.hbase.cluster.masterHfileCleanerTtl | quote }}
+ HBASE_BALANCER_PERIOD: {{ .Values.hbase.cluster.balancerPeriod | quote }}
+ HBASE_PROCEDURE_STORE_WAL_USE_HSYNC: {{ .Values.hbase.cluster.procedureStoreWalUseHsync | quote }}
+ HBASE_REGIONSERVER_OPTIONALCACHEFLUSHINTERVAL: {{ .Values.hbase.cluster.regionserverOptionalCacheFlushInterval | quote }}
+ HBASE_REGIONSERVER_STARTUP_RETRIES: {{ .Values.hbase.cluster.regionserverStartupRetries | quote }}
+ HBASE_REGIONSERVER_STARTUP_RETRY_INTERVAL: {{ .Values.hbase.cluster.regionserverStartupRetryInterval | quote }}
+ HBASE_REPLICATION_ENABLED: {{ .Values.hbase.cluster.replicationEnabled | quote }}
+ HBASE_SECURITY_AUTHENTICATION: {{ .Values.hbase.security.authentication | quote }}
+ HBASE_SECURITY_AUTHORIZATION: {{ .Values.hbase.security.authorization | quote }}
+ HBASE_SPLITLOG_MANAGER_TIMEOUT: {{ .Values.hbase.cluster.splitlogManagerTimeout | quote }}
+ resources:
+ requests:
+ cpu: {{ .Values.resources.hregionserver.requests.cpu | quote }}
+ memory: {{ .Values.resources.hregionserver.requests.memory }}
+ limits:
+ cpu: {{ .Values.resources.hregionserver.limits.cpu | quote }}
+ memory: {{ .Values.resources.hregionserver.limits.memory }}
+ schedulingPolicy:
+ topologySpreadConstraints:
+ - maxSkew: 1
+ topologyKey: kubernetes.io/hostname
+ whenUnsatisfiable: DoNotSchedule
+ labelSelector:
+ matchLabels:
+ apps.kubeblocks.io/component-name: hregionserver
+{{- else }}
+ - name: hbase-standalone
+ componentDef: hbase-standalone-2.5
+ serviceVersion: 2.5.6
+ replicas: 1
+ serviceRefs:
+ - name: hbase-zookeeper
+ namespace: {{ .Values.serviceRefs.hbaseZookeeper.namespace }}
+ clusterServiceSelector:
+ cluster: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.cluster }}
+ service:
+ component: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.service.component }}
+ service: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.service.service }}
+ port: {{ .Values.serviceRefs.hbaseZookeeper.clusterServiceSelector.service.port }}
+ configs:
+ - name: hbase-standalone-config
+ variables:
+ HBASE_ZOOKEEPER_SESSION_TIMEOUT: {{ .Values.hbase.zk.sessionTimeout | quote }}
+ HBASE_ZOOKEEPER_MAX_CLIENT_CNXNS: {{ .Values.hbase.zk.maxClientCnxns | quote }}
+ HBASE_REGIONSERVER_HANDLER_COUNT: {{ .Values.hbase.standalone.regionserverHandlerCount | quote }}
+ HBASE_HSTORE_FLUSHER_COUNT: {{ .Values.hbase.standalone.hstoreFlusherCount | quote }}
+ HBASE_CLIENT_SCANNER_CACHING: {{ .Values.hbase.common.clientScannerCaching | quote }}
+ HBASE_HREGION_MAX_FILESIZE: {{ .Values.hbase.standalone.regionMaxFileSize | quote }}
+ HBASE_HREGION_MEMSTORE_FLUSH_SIZE: {{ .Values.hbase.common.regionMemstoreFlushSize | quote }}
+ HBASE_PROCEDURE_STORE_WAL_USE_HSYNC: {{ .Values.hbase.standalone.procedureStoreWalUseHsync | quote }}
+ HBASE_REPLICATION_ENABLED: {{ .Values.hbase.standalone.replicationEnabled | quote }}
+ HBASE_SECURITY_AUTHENTICATION: {{ .Values.hbase.security.authentication | quote }}
+ HBASE_SECURITY_AUTHORIZATION: {{ .Values.hbase.security.authorization | quote }}
+ resources:
+ requests:
+ cpu: {{ .Values.resources.hbasestandalone.requests.cpu | quote }}
+ memory: {{ .Values.resources.hbasestandalone.requests.memory }}
+ limits:
+ cpu: {{ .Values.resources.hbasestandalone.limits.cpu | quote }}
+ memory: {{ .Values.resources.hbasestandalone.limits.memory }}
+ volumeClaimTemplates:
+ - name: data
+ spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: {{ .Values.storage.standalone.data }}
+{{- if .Values.storage.storageClassName }}
+ storageClassName: {{ .Values.storage.storageClassName }}
+{{- end }}
+{{- end }}
diff --git a/addons-cluster/hbase/templates/prometheus/monitor.yaml b/addons-cluster/hbase/templates/prometheus/monitor.yaml
new file mode 100644
index 0000000000..95adf6f28c
--- /dev/null
+++ b/addons-cluster/hbase/templates/prometheus/monitor.yaml
@@ -0,0 +1,20 @@
+{{- if and (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1/PodMonitor") .Values.prometheus.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: PodMonitor
+metadata:
+ name: {{ include "kblib.clusterName" . }}-metrics-monitor
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "kblib.clusterLabels" . | nindent 4 }}
+spec:
+ podMetricsEndpoints:
+ - path: /metrics
+ port: http-metrics
+ scheme: http
+ namespaceSelector:
+ matchNames:
+ - {{ .Release.Namespace }}
+ selector:
+ matchLabels:
+ app.kubernetes.io/instance: {{ include "kblib.clusterName" . | quote }}
+{{- end }}
diff --git a/addons-cluster/hbase/values.schema.json b/addons-cluster/hbase/values.schema.json
new file mode 100644
index 0000000000..359bfe76f6
--- /dev/null
+++ b/addons-cluster/hbase/values.schema.json
@@ -0,0 +1,455 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "type": "object",
+ "properties": {
+ "topology": {
+ "type": "string",
+ "enum": [
+ "cluster",
+ "standalone"
+ ],
+ "default": "cluster"
+ },
+ "replicas": {
+ "type": "object",
+ "properties": {
+ "hmaster": {
+ "type": "integer",
+ "default": 2,
+ "minimum": 1
+ },
+ "hregionserver": {
+ "type": "integer",
+ "default": 2,
+ "minimum": 1
+ }
+ }
+ },
+ "resources": {
+ "type": "object",
+ "properties": {
+ "hmaster": {
+ "$ref": "#/definitions/resourceSchema"
+ },
+ "hregionserver": {
+ "$ref": "#/definitions/resourceSchema"
+ },
+ "hbasestandalone": {
+ "$ref": "#/definitions/resourceSchema"
+ }
+ }
+ },
+ "storage": {
+ "type": "object",
+ "properties": {
+ "storageClassName": {
+ "type": "string",
+ "default": ""
+ },
+ "standalone": {
+ "type": "object",
+ "properties": {
+ "data": {
+ "type": "string",
+ "default": "20Gi"
+ }
+ }
+ }
+ }
+ },
+ "serviceRefs": {
+ "type": "object",
+ "properties": {
+ "hbaseZookeeper": {
+ "$ref": "#/definitions/serviceRefSchema"
+ },
+ "hdfsNamenode": {
+ "$ref": "#/definitions/serviceRefSchema"
+ }
+ }
+ },
+ "hdfs": {
+ "type": "object",
+ "properties": {
+ "namenodeNodes": {
+ "type": "string",
+ "default": "nn0,nn1"
+ },
+ "namenodeRpcPort": {
+ "type": "integer",
+ "default": 8020,
+ "minimum": 1,
+ "maximum": 65535
+ },
+ "namenodeHttpPort": {
+ "type": "integer",
+ "default": 9870,
+ "minimum": 1,
+ "maximum": 65535
+ },
+ "haZkParent": {
+ "type": "string",
+ "default": "/hadoop-ha"
+ },
+ "replication": {
+ "type": "string",
+ "default": "3"
+ },
+ "permissionsEnabled": {
+ "type": "boolean",
+ "default": false
+ },
+ "fs": {
+ "type": "object",
+ "properties": {
+ "trashInterval": {
+ "type": "integer",
+ "default": 1440,
+ "minimum": 0
+ }
+ }
+ },
+ "security": {
+ "type": "object",
+ "properties": {
+ "authentication": {
+ "type": "string",
+ "default": "simple"
+ },
+ "authorization": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ipc": {
+ "type": "object",
+ "properties": {
+ "clientConnectionMaxIdleTime": {
+ "type": "integer",
+ "default": 30000,
+ "minimum": 0
+ },
+ "clientConnectTimeout": {
+ "type": "integer",
+ "default": 10000,
+ "minimum": 1
+ },
+ "pingInterval": {
+ "type": "integer",
+ "default": 60000,
+ "minimum": 1
+ }
+ }
+ },
+ "paths": {
+ "type": "object",
+ "properties": {
+ "tmpDir": {
+ "type": "string",
+ "default": "/hadoop/tmp"
+ }
+ }
+ },
+ "client": {
+ "type": "object",
+ "properties": {
+ "webhdfsEnabled": {
+ "type": "boolean",
+ "default": false
+ },
+ "failoverMaxAttempts": {
+ "type": "integer",
+ "default": 15,
+ "minimum": 1
+ },
+ "failoverSleepBaseMillis": {
+ "type": "integer",
+ "default": 500,
+ "minimum": 0
+ },
+ "failoverSleepMaxMillis": {
+ "type": "integer",
+ "default": 15000,
+ "minimum": 0
+ },
+ "retryPolicy": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "default": true
+ },
+ "spec": {
+ "type": "string",
+ "default": "10000,6,60000,10"
+ }
+ }
+ },
+ "commonRetryPolicy": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "default": true
+ },
+ "spec": {
+ "type": "string",
+ "default": "1000,1"
+ }
+ }
+ }
+ }
+ },
+ "hbaseClient": {
+ "type": "object",
+ "properties": {
+ "ipcClientConnectTimeout": {
+ "type": "integer",
+ "default": 30000,
+ "minimum": 1
+ },
+ "ipcClientConnectMaxRetries": {
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ }
+ }
+ }
+ }
+ },
+ "hbase": {
+ "type": "object",
+ "properties": {
+ "zk": {
+ "type": "object",
+ "properties": {
+ "sessionTimeout": {
+ "type": "integer",
+ "default": 30000,
+ "minimum": 1
+ },
+ "maxClientCnxns": {
+ "type": "integer",
+ "default": 4000,
+ "minimum": 1
+ }
+ }
+ },
+ "security": {
+ "type": "object",
+ "properties": {
+ "authentication": {
+ "type": "string",
+ "default": "simple"
+ },
+ "authorization": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "common": {
+ "type": "object",
+ "properties": {
+ "clientScannerCaching": {
+ "type": "integer",
+ "default": 100,
+ "minimum": 1
+ },
+ "regionMemstoreFlushSize": {
+ "type": "integer",
+ "default": 134217728,
+ "minimum": 1
+ }
+ }
+ },
+ "cluster": {
+ "type": "object",
+ "properties": {
+ "regionserverHandlerCount": {
+ "type": "integer",
+ "default": 100,
+ "minimum": 1
+ },
+ "hstoreFlusherCount": {
+ "type": "integer",
+ "default": 4,
+ "minimum": 1
+ },
+ "regionMaxFileSize": {
+ "type": "integer",
+ "default": 53687091200,
+ "minimum": 1
+ },
+ "regionMajorCompaction": {
+ "type": "integer",
+ "default": 0,
+ "minimum": 0
+ },
+ "masterWaitOnRegionserversTimeout": {
+ "type": "integer",
+ "default": 300000,
+ "minimum": 0
+ },
+ "masterStartupRetainassignTimeout": {
+ "type": "integer",
+ "default": 300000,
+ "minimum": 0
+ },
+ "oldWalsCleanerThreadTimeoutMsec": {
+ "type": "integer",
+ "default": 60000,
+ "minimum": 0
+ },
+ "masterLogCleanerTtl": {
+ "type": "integer",
+ "default": 60000,
+ "minimum": 0
+ },
+ "masterHfileCleanerTtl": {
+ "type": "integer",
+ "default": 600000,
+ "minimum": 0
+ },
+ "balancerPeriod": {
+ "type": "integer",
+ "default": 1800000,
+ "minimum": 0
+ },
+ "procedureStoreWalUseHsync": {
+ "type": "boolean",
+ "default": true
+ },
+ "regionserverOptionalCacheFlushInterval": {
+ "type": "integer",
+ "default": 28800000,
+ "minimum": 0
+ },
+ "regionserverStartupRetries": {
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "regionserverStartupRetryInterval": {
+ "type": "integer",
+ "default": 10000,
+ "minimum": 0
+ },
+ "replicationEnabled": {
+ "type": "boolean",
+ "default": true
+ },
+ "splitlogManagerTimeout": {
+ "type": "integer",
+ "default": 600000,
+ "minimum": 0
+ }
+ }
+ },
+ "standalone": {
+ "type": "object",
+ "properties": {
+ "regionserverHandlerCount": {
+ "type": "integer",
+ "default": 30,
+ "minimum": 1
+ },
+ "hstoreFlusherCount": {
+ "type": "integer",
+ "default": 2,
+ "minimum": 1
+ },
+ "regionMaxFileSize": {
+ "type": "integer",
+ "default": 10737418240,
+ "minimum": 1
+ },
+ "procedureStoreWalUseHsync": {
+ "type": "boolean",
+ "default": false
+ },
+ "replicationEnabled": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "prometheus": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ },
+ "definitions": {
+ "resourceSchema": {
+ "type": "object",
+ "properties": {
+ "requests": {
+ "type": "object",
+ "properties": {
+ "cpu": {
+ "type": "string",
+ "default": "0.5"
+ },
+ "memory": {
+ "type": "string",
+ "default": "1Gi"
+ }
+ }
+ },
+ "limits": {
+ "type": "object",
+ "properties": {
+ "cpu": {
+ "type": "string",
+ "default": "2"
+ },
+ "memory": {
+ "type": "string",
+ "default": "4Gi"
+ }
+ }
+ }
+ }
+ },
+ "serviceRefSchema": {
+ "type": "object",
+ "properties": {
+ "namespace": {
+ "type": "string",
+ "default": "kubeblocks"
+ },
+ "clusterServiceSelector": {
+ "type": "object",
+ "properties": {
+ "cluster": {
+ "type": "string"
+ },
+ "service": {
+ "type": "object",
+ "properties": {
+ "component": {
+ "type": "string"
+ },
+ "service": {
+ "type": "string",
+ "default": "headless"
+ },
+ "port": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/addons-cluster/hbase/values.yaml b/addons-cluster/hbase/values.yaml
new file mode 100644
index 0000000000..77ec11c8af
--- /dev/null
+++ b/addons-cluster/hbase/values.yaml
@@ -0,0 +1,124 @@
+topology: cluster
+
+replicas:
+ hmaster: 2
+ hregionserver: 2
+
+resources:
+ hmaster:
+ requests:
+ cpu: "0.5"
+ memory: 1Gi
+ limits:
+ cpu: "2"
+ memory: 4Gi
+ hregionserver:
+ requests:
+ cpu: "0.5"
+ memory: 1Gi
+ limits:
+ cpu: "2"
+ memory: 6Gi
+ hbasestandalone:
+ requests:
+ cpu: "0.2"
+ memory: 0.5Gi
+ limits:
+ cpu: "1"
+ memory: 1Gi
+
+storage:
+ storageClassName: ""
+ standalone:
+ data: 20Gi
+
+serviceRefs:
+ hbaseZookeeper:
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: zk
+ service:
+ component: zookeeper
+ service: headless
+ port: client
+ hdfsNamenode:
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: hdfs
+ service:
+ component: namenode
+ service: headless
+ port: fs
+
+hdfs:
+ namenodeNodes: nn0,nn1
+ namenodeRpcPort: 8020
+ namenodeHttpPort: 9870
+ haZkParent: /hadoop-ha
+ replication: "3"
+ permissionsEnabled: false
+ fs:
+ trashInterval: 1440
+ security:
+ authentication: simple
+ authorization: false
+ ipc:
+ clientConnectionMaxIdleTime: 30000
+ clientConnectTimeout: 10000
+ pingInterval: 60000
+ paths:
+ tmpDir: /hadoop/tmp
+ client:
+ webhdfsEnabled: false
+ failoverMaxAttempts: 15
+ failoverSleepBaseMillis: 500
+ failoverSleepMaxMillis: 15000
+ retryPolicy:
+ enabled: true
+ spec: "10000,6,60000,10"
+ commonRetryPolicy:
+ enabled: true
+ spec: "1000,1"
+ hbaseClient:
+ ipcClientConnectTimeout: 30000
+ ipcClientConnectMaxRetries: 10
+
+hbase:
+ zk:
+ sessionTimeout: 30000
+ maxClientCnxns: 4000
+ security:
+ authentication: simple
+ authorization: false
+ common:
+ clientScannerCaching: 100
+ regionMemstoreFlushSize: 134217728
+ cluster:
+ regionserverHandlerCount: 100
+ hstoreFlusherCount: 4
+ regionMaxFileSize: 53687091200
+ regionMajorCompaction: 0
+ masterWaitOnRegionserversTimeout: 300000
+ masterStartupRetainassignTimeout: 300000
+ oldWalsCleanerThreadTimeoutMsec: 60000
+ masterLogCleanerTtl: 60000
+ masterHfileCleanerTtl: 600000
+ balancerPeriod: 1800000
+ procedureStoreWalUseHsync: true
+ regionserverOptionalCacheFlushInterval: 28800000
+ regionserverStartupRetries: 10
+ regionserverStartupRetryInterval: 10000
+ replicationEnabled: true
+ splitlogManagerTimeout: 600000
+ standalone:
+ regionserverHandlerCount: 30
+ hstoreFlusherCount: 2
+ regionMaxFileSize: 10737418240
+ procedureStoreWalUseHsync: false
+ replicationEnabled: false
+
+prometheus:
+ enabled: false
+
+extra:
+ terminationPolicy: Delete
diff --git a/addons/hadoop/.helmignore b/addons/hadoop/.helmignore
new file mode 100644
index 0000000000..691fa13d6a
--- /dev/null
+++ b/addons/hadoop/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
\ No newline at end of file
diff --git a/addons/hadoop/Chart.yaml b/addons/hadoop/Chart.yaml
new file mode 100644
index 0000000000..4630c38285
--- /dev/null
+++ b/addons/hadoop/Chart.yaml
@@ -0,0 +1,27 @@
+annotations:
+ category: BigData
+ addon.kubeblocks.io/kubeblocks-version: ">=1.0.0"
+ addon.kubeblocks.io/model: "key-value"
+ addon.kubeblocks.io/provider: "community"
+apiVersion: v2
+name: hadoop
+description: A Helm chart for Hadoop HDFS on KubeBlocks.
+type: application
+version: 1.1.0-alpha.0
+appVersion: "3.3.4"
+dependencies:
+ - name: kblib
+ version: 0.1.0
+ repository: file://../kblib
+ alias: extra
+keywords:
+ - hadoop
+ - hdfs
+ - bigdata
+home: https://github.com/apecloud/kubeblocks/tree/main/deploy/hadoop
+icon: https://kubeblocks.io/img/logo.png
+maintainers:
+ - name: ApeCloud
+ url: https://kubeblocks.io/
+sources:
+ - https://github.com/apecloud/kubeblocks/
\ No newline at end of file
diff --git a/addons/hadoop/README.md b/addons/hadoop/README.md
new file mode 100644
index 0000000000..3ac09f37db
--- /dev/null
+++ b/addons/hadoop/README.md
@@ -0,0 +1,296 @@
+# Hadoop HDFS Addon for KubeBlocks
+
+[中文说明](./README.zh-CN.md)
+
+This document describes what the Hadoop HDFS addon provides, how it is structured, what configuration surfaces are available today, and what was added recently for deploy-time configuration through the cluster chart.
+
+## Overview
+
+The Hadoop addon under `addons/hadoop` provides HDFS on KubeBlocks with:
+
+- `cluster` topology: `journalnode + namenode + datanode`
+- `standalone` topology: `namenode + datanode`
+- ZooKeeper-backed HA failover for cluster mode
+- configurable DataNode `hostNetwork`
+- standard parameter management resources in the addon itself:
+ - `ParametersDefinition`
+ - `ParamConfigRenderer`
+ - CUE config constraints
+- an additional deploy-time configuration surface in `addons-cluster/hadoop`
+
+Supported service version:
+
+| Major Version | Actual Version |
+|---------------|----------------|
+| 3.3 | 3.3.4 |
+
+## What This Addon Contains
+
+The addon package under `addons/hadoop` defines:
+
+- `ClusterDefinition` named `hadoop`
+- component definitions for:
+ - `hdfs-journalnode`
+ - `hdfs-namenode`
+ - `hdfs-namenode-standalone`
+ - `hdfs-datanode`
+ - `hdfs-datanode-standalone`
+- component versions for NameNode, DataNode, and JournalNode
+- config templates for:
+ - `core-site.xml`
+ - `hdfs-site.xml`
+ - `hadoop-env.sh`
+ - `hdfs-jmx-exporter.yaml`
+- startup and init scripts for NameNode, DataNode, JournalNode, and ZKFC
+- parameter management resources:
+ - `paramsdef-hdfs-common.yaml`
+ - `paramsdef-hdfs-namenode.yaml`
+ - `paramsdef-hdfs-datanode.yaml`
+ - `paramsdef-hdfs-journalnode.yaml`
+ - corresponding `pcr-*` resources
+
+The deployable cluster chart under `addons-cluster/hadoop` provides a ready-to-use `Cluster` manifest and exposes a first batch of deploy-time overrides through `values.yaml`.
+
+## Topologies
+
+### Cluster Topology
+
+Cluster mode is the default topology and contains:
+
+| Component | Role | Default Replicas |
+|-----------|------|------------------|
+| `journalnode` | quorum journal for HA edits | 3 |
+| `namenode` | active/standby NameNode pair | 2 |
+| `datanode` | HDFS data service | 3 |
+
+Behavior notes:
+
+- HA is implemented as active/standby NameNode, not arbitrary multi-NN observer mode.
+- `hdfs.ha.nameNodeIds` is configurable, but cluster mode currently requires exactly 2 entries.
+- JournalNode count is not hard-coded to 3 by template logic, but odd replica counts such as 3 or 5 remain the practical recommendation.
+- DataNode count is a deployment default, not an addon hard limit.
+
+### Standalone Topology
+
+Standalone mode contains:
+
+| Component | Role | Default Replicas |
+|-----------|------|------------------|
+| `namenode` | local NameNode | 1 |
+| `datanode` | local DataNode | 1 |
+
+This topology is intended for development, smoke testing, and functional verification.
+
+## Prerequisites
+
+- Kubernetes >= v1.21
+- KubeBlocks >= 1.1
+- the Hadoop addon installed
+- a ZooKeeper cluster available when using `cluster` topology
+- a dedicated namespace is recommended, for example:
+
+```bash
+kubectl create ns demo
+```
+
+## Configuration Surfaces
+
+There are two different configuration surfaces in this repository.
+
+### 1. Standard KubeBlocks Parameter Management in the Addon
+
+The addon itself already contains standard parameter-management artifacts:
+
+- `ParametersDefinition`
+- `ParamConfigRenderer`
+- CUE constraints
+
+These resources are defined in `addons/hadoop/templates/paramsdef-*` and `addons/hadoop/templates/pcr-*`.
+
+This means the addon is not limited to raw static config templates. The standard KubeBlocks parameter chain already exists for addon-managed configuration files such as:
+
+- `hdfs-common-config`
+- `namenode-config`
+- `datanode-config`
+- `journalnode-config`
+
+### 2. Deploy-Time Overrides in the Cluster Chart
+
+In addition, `addons-cluster/hadoop` now exposes a first batch of deploy-time values that flow through:
+
+`values.yaml -> templates/cluster.yaml -> configs.variables -> runtime config templates`
+
+This deploy-time surface is useful for:
+
+- environment-specific defaults
+- cluster bootstrap-time sizing
+- HA/network/security knobs that should be set before the cluster starts
+
+## Newly Exposed Deploy-Time Values
+
+The cluster chart now exposes deploy-time overrides for the following groups.
+
+| Value Path | Purpose |
+|------------|---------|
+| `hdfs.core.hadoopTmpDir` | `hadoop.tmp.dir` |
+| `hdfs.security.authentication` | Hadoop auth mode |
+| `hdfs.security.authorization` | Hadoop authorization switch |
+| `hdfs.client.retryPolicyEnabled` | client retry enablement |
+| `hdfs.client.retryPolicySpec` | retry policy spec |
+| `hdfs.permissions.superusergroup` | HDFS superuser group |
+| `hdfs.ha.nameNodeIds` | configurable HA NameNode IDs |
+| `hdfs.ha.fencingSshConnectTimeoutMs` | fencing SSH timeout |
+| `hdfs.namenode.webhdfsEnabled` | WebHDFS switch |
+| `hdfs.namenode.resourceDuReserved` | NameNode reserved local disk |
+| `hdfs.namenode.haLogRollPeriod` | HA log roll period |
+| `hdfs.namenode.haTailEditsPeriod` | HA tail edits period |
+| `hdfs.datanode.failedVolumesTolerated` | tolerated failed volumes |
+| `hdfs.datanode.duReserved` | DataNode reserved disk |
+| `hdfs.journalnode.enableSync` | JournalNode sync switch |
+| `hdfs.journalnode.editCacheSizeBytes` | JournalNode edit cache size |
+| `hdfs.journalnode.syncIntervalMs` | JournalNode sync interval |
+| `hdfs.replicationMax` | `dfs.replication.max` |
+
+The deploy-time defaults live in:
+
+- `addons-cluster/hadoop/values.yaml`
+- `addons-cluster/hadoop/values.schema.json`
+
+## Config Templates
+
+The addon renders different template files for different components and topologies.
+
+| Source Template | Rendered File | Used By | Purpose |
+|----------------|---------------|---------|---------|
+| `config/core-site.tpl` | `core-site.xml` | cluster components | common Hadoop client settings for cluster mode |
+| `config/core-site-standalone.tpl` | `core-site.xml` | standalone components | common Hadoop client settings for standalone mode |
+| `config/hdfs-namenode.tpl` | `hdfs-site.xml` | cluster NameNode | HA NameNode configuration |
+| `config/hdfs-namenode-standalone.tpl` | `hdfs-site.xml` | standalone NameNode | standalone NameNode configuration |
+| `config/hdfs-datanode.tpl` | `hdfs-site.xml` | cluster DataNode | HA-aware DataNode configuration |
+| `config/hdfs-datanode-standalone.tpl` | `hdfs-site.xml` | standalone DataNode | standalone DataNode configuration |
+| `config/hdfs-journalnode.tpl` | `hdfs-site.xml` | JournalNode | JournalNode configuration |
+| `config/hadoop-env.sh.tpl` | `hadoop-env.sh` | all components | runtime environment variables |
+
+## Runtime and Image Notes
+
+### DataNode Network Mode
+
+DataNode supports runtime network tuning through addon values:
+
+- `runtime.datanode.hostNetwork`
+- `runtime.datanode.hostPID`
+- `runtime.datanode.dnsPolicy`
+
+### NameNode and Init Container Images
+
+By default, NameNode init containers reuse the NameNode image unless explicitly overridden.
+
+Relevant values:
+
+- `nameNode.image.*`
+- `nameNode.initImages.initNameNodeFormat.*`
+- `nameNode.initImages.initZkfcFormat.*`
+
+This keeps the default path simple while still allowing custom init-container images when needed.
+
+## HA Notes and Current Limits
+
+Current HA behavior is intentionally conservative:
+
+- cluster topology enforces `replicas.namenode = 2`
+- `hdfs.ha.nameNodeIds` must contain exactly 2 entries in cluster mode
+- the NameNode startup script maps peer nodes by configured ID order
+- standby bootstrap is guarded to avoid the old `OrderedReady` timing problem during initial bring-up
+
+This means the current addon supports configurable NameNode IDs for the existing 2NN active/standby model, not general N-way NameNode scaling.
+
+## Observability
+
+Hadoop metrics are now exposed through a `jmx-exporter` sidecar instead of the old `metrics2 JmxSink` path.
+
+- the old `hadoop-metrics2.properties` JmxSink path has been removed
+- NameNode, DataNode, and JournalNode pods now include a `jmx-exporter` sidecar
+- the exporter scrapes local JVM JMX over loopback and exposes `/metrics`
+
+If you want Prometheus discovery metadata on the component service, set `spec.componentSpecs[*].disableExporter=false` in the deployed `Cluster`.
+
+Typical PodMonitor endpoint:
+
+```yaml
+podMetricsEndpoints:
+ - path: /metrics
+ port: http-metrics
+ scheme: http
+```
+
+## Quick Start
+
+### Install the Addon
+
+From the repository root:
+
+```bash
+helm install hadoop-addon ./addons/hadoop
+```
+
+### Deploy with the Cluster Chart
+
+Cluster mode:
+
+```bash
+helm install hdfs-cluster ./addons-cluster/hadoop \
+ -n demo \
+ --create-namespace \
+ --set topology=cluster \
+ --set serviceRefs.hadoopZookeeper.namespace=kubeblocks \
+ --set serviceRefs.hadoopZookeeper.clusterServiceSelector.cluster=zk
+```
+
+Standalone mode:
+
+```bash
+helm install hdfs-standalone ./addons-cluster/hadoop \
+ -n demo \
+ --create-namespace \
+ --set topology=standalone
+```
+
+### Example Deploy-Time Overrides
+
+```yaml
+topology: cluster
+
+replicas:
+ journalnode: 3
+ namenode: 2
+ datanode: 3
+
+hdfs:
+ core:
+ hadoopTmpDir: /hadoop/tmp
+ security:
+ authentication: simple
+ authorization: false
+ ha:
+ nameNodeIds: "nn0,nn1"
+ fencingSshConnectTimeoutMs: 30000
+ namenode:
+ webhdfsEnabled: false
+ resourceDuReserved: 1073741824
+ haLogRollPeriod: 120
+ haTailEditsPeriod: 60
+ datanode:
+ failedVolumesTolerated: 0
+ duReserved: 1073741824
+ journalnode:
+ enableSync: true
+ editCacheSizeBytes: 104857600
+ syncIntervalMs: 120000
+```
+
+## Requirements and Caveats
+
+- cluster mode requires ZooKeeper service references
+- current HA implementation is strictly a 2NN active/standby model
+- deploy-time values in `addons-cluster/hadoop` are not a replacement for the addon's standard parameter-management resources; they are an additional deployment convenience layer
+- if you need environment-specific image layout or custom bootstrap images, use the image override fields instead of patching vendor manifests directly
diff --git a/addons/hadoop/README.zh-CN.md b/addons/hadoop/README.zh-CN.md
new file mode 100644
index 0000000000..bd66dafaa0
--- /dev/null
+++ b/addons/hadoop/README.zh-CN.md
@@ -0,0 +1,299 @@
+# Hadoop HDFS Addon for KubeBlocks
+
+[English](./README.md)
+
+本文档说明 `addons/hadoop` 当前提供的能力、拓扑结构、参数入口,以及 `addons-cluster/hadoop` 这次新增的部署阶段配置能力。
+
+## 概览
+
+`addons/hadoop` 当前提供:
+
+- `cluster` 拓扑:`journalnode + namenode + datanode`
+- `standalone` 拓扑:`namenode + datanode`
+- 基于 ZooKeeper 的 HDFS HA failover
+- 可配置的 DataNode `hostNetwork`
+- Addon 内置的标准参数管理链路:
+ - `ParametersDefinition`
+ - `ParamConfigRenderer`
+ - CUE config constraints
+- `addons-cluster/hadoop` 中额外暴露的一批部署阶段可覆盖项
+
+当前支持的服务版本:
+
+| 大版本 | 实际版本 |
+|--------|----------|
+| 3.3 | 3.3.4 |
+
+## Addon 当前包含的内容
+
+`addons/hadoop` 目录定义了:
+
+- `ClusterDefinition`:`hadoop`
+- 组件定义:
+ - `hdfs-journalnode`
+ - `hdfs-namenode`
+ - `hdfs-namenode-standalone`
+ - `hdfs-datanode`
+ - `hdfs-datanode-standalone`
+- 组件版本定义:NameNode、DataNode、JournalNode
+- 配置模板:
+ - `core-site.xml`
+ - `hdfs-site.xml`
+ - `hadoop-env.sh`
+ - `hdfs-jmx-exporter.yaml`
+- NameNode、DataNode、JournalNode、ZKFC 的启动和初始化脚本
+- 标准参数管理资源:
+ - `paramsdef-hdfs-common.yaml`
+ - `paramsdef-hdfs-namenode.yaml`
+ - `paramsdef-hdfs-datanode.yaml`
+ - `paramsdef-hdfs-journalnode.yaml`
+ - 对应的 `pcr-*` 资源
+
+`addons-cluster/hadoop` 目录则提供了一个可直接部署的 cluster chart,并通过 `values.yaml` 暴露了一批部署阶段参数。
+
+## 拓扑说明
+
+### Cluster 拓扑
+
+Cluster 模式是默认拓扑,包含:
+
+| 组件 | 角色 | 默认副本数 |
+|------|------|------------|
+| `journalnode` | HA edits quorum | 3 |
+| `namenode` | Active/Standby NameNode 对 | 2 |
+| `datanode` | HDFS 数据服务 | 3 |
+
+行为说明:
+
+- 当前 HA 实现是 active/standby 2NN 模型,不是任意多 NameNode 的 observer 模式。
+- `hdfs.ha.nameNodeIds` 已支持配置,但 cluster 模式下当前强制要求正好 2 个条目。
+- JournalNode 模板能力本身没有写死只能 3 个,但工程上仍建议使用 3 或 5 这类奇数副本。
+- DataNode 副本数只是部署默认值,不是 addon 代码硬限制。
+
+### Standalone 拓扑
+
+Standalone 模式包含:
+
+| 组件 | 角色 | 默认副本数 |
+|------|------|------------|
+| `namenode` | 本地 NameNode | 1 |
+| `datanode` | 本地 DataNode | 1 |
+
+该拓扑适合开发、冒烟验证和轻量功能测试。
+
+## 前置条件
+
+- Kubernetes >= v1.21
+- KubeBlocks >= 1.1
+- Hadoop addon 已安装
+- 使用 `cluster` 拓扑时,需要可用的 ZooKeeper 集群
+- 建议使用独立 namespace,例如:
+
+```bash
+kubectl create ns demo
+```
+
+## 配置入口说明
+
+当前仓库里有两类配置入口,需要分清楚。
+
+### 1. Addon 内的标准参数管理链路
+
+`addons/hadoop` 本身已经包含标准 KubeBlocks 参数链路:
+
+- `ParametersDefinition`
+- `ParamConfigRenderer`
+- CUE constraints
+
+这些资源定义在:
+
+- `addons/hadoop/templates/paramsdef-*`
+- `addons/hadoop/templates/pcr-*`
+
+因此,README 不能简单理解成“只有静态配置模板”。Addon 自身已经具备标准参数管理能力,覆盖的配置集合包括:
+
+- `hdfs-common-config`
+- `namenode-config`
+- `datanode-config`
+- `journalnode-config`
+
+### 2. Cluster Chart 的部署阶段覆盖入口
+
+除此之外,`addons-cluster/hadoop` 这次新增了一批部署阶段参数,链路是:
+
+`values.yaml -> templates/cluster.yaml -> configs.variables -> runtime config templates`
+
+这层主要用于:
+
+- 环境差异化默认值
+- 集群首次部署时的容量和网络参数
+- 需要在启动前就确定的 HA / 安全 / 路径类参数
+
+## 本次新增的部署阶段参数面
+
+当前 cluster chart 已经暴露以下第一批参数:
+
+| 参数路径 | 作用 |
+|----------|------|
+| `hdfs.core.hadoopTmpDir` | `hadoop.tmp.dir` |
+| `hdfs.security.authentication` | Hadoop 认证模式 |
+| `hdfs.security.authorization` | Hadoop 鉴权开关 |
+| `hdfs.client.retryPolicyEnabled` | 客户端重试开关 |
+| `hdfs.client.retryPolicySpec` | 客户端重试策略 |
+| `hdfs.permissions.superusergroup` | HDFS 超级用户组 |
+| `hdfs.ha.nameNodeIds` | HA NameNode ID 列表 |
+| `hdfs.ha.fencingSshConnectTimeoutMs` | fencing SSH 超时 |
+| `hdfs.namenode.webhdfsEnabled` | WebHDFS 开关 |
+| `hdfs.namenode.resourceDuReserved` | NameNode 本地保留磁盘 |
+| `hdfs.namenode.haLogRollPeriod` | HA log roll 周期 |
+| `hdfs.namenode.haTailEditsPeriod` | HA tail edits 周期 |
+| `hdfs.datanode.failedVolumesTolerated` | 容忍坏盘数 |
+| `hdfs.datanode.duReserved` | DataNode 保留磁盘 |
+| `hdfs.journalnode.enableSync` | JournalNode sync 开关 |
+| `hdfs.journalnode.editCacheSizeBytes` | JournalNode edit cache 大小 |
+| `hdfs.journalnode.syncIntervalMs` | JournalNode sync 周期 |
+| `hdfs.replicationMax` | `dfs.replication.max` |
+
+这些默认值和 schema 定义位于:
+
+- `addons-cluster/hadoop/values.yaml`
+- `addons-cluster/hadoop/values.schema.json`
+
+## 配置模板与组件映射
+
+当前 addon 会为不同组件和拓扑渲染不同模板:
+
+| 模板文件 | 最终文件 | 使用组件 | 作用 |
+|----------|----------|----------|------|
+| `config/core-site.tpl` | `core-site.xml` | cluster 组件 | cluster 模式下的 Hadoop 通用客户端配置 |
+| `config/core-site-standalone.tpl` | `core-site.xml` | standalone 组件 | standalone 模式下的 Hadoop 通用客户端配置 |
+| `config/hdfs-namenode.tpl` | `hdfs-site.xml` | cluster NameNode | HA NameNode 配置 |
+| `config/hdfs-namenode-standalone.tpl` | `hdfs-site.xml` | standalone NameNode | standalone NameNode 配置 |
+| `config/hdfs-datanode.tpl` | `hdfs-site.xml` | cluster DataNode | HA 感知的 DataNode 配置 |
+| `config/hdfs-datanode-standalone.tpl` | `hdfs-site.xml` | standalone DataNode | standalone DataNode 配置 |
+| `config/hdfs-journalnode.tpl` | `hdfs-site.xml` | JournalNode | JournalNode 配置 |
+| `config/hadoop-env.sh.tpl` | `hadoop-env.sh` | 全部组件 | 运行时环境变量 |
+
+## 运行时与镜像说明
+
+### DataNode 网络模式
+
+DataNode 当前支持以下网络相关配置:
+
+- `runtime.datanode.hostNetwork`
+- `runtime.datanode.hostPID`
+- `runtime.datanode.dnsPolicy`
+
+### NameNode 与 initContainer 镜像
+
+默认情况下,NameNode 的 initContainer 复用 NameNode 主镜像;如果有特殊需求,也支持单独覆盖。
+
+相关参数为:
+
+- `nameNode.image.*`
+- `nameNode.initImages.initNameNodeFormat.*`
+- `nameNode.initImages.initZkfcFormat.*`
+
+这样做既保留了默认路径的简洁性,也支持在必要时做定制镜像切换。
+
+## HA 说明与当前限制
+
+当前 HA 设计是有意收敛的:
+
+- cluster 模式强制要求 `replicas.namenode = 2`
+- cluster 模式下 `hdfs.ha.nameNodeIds` 必须正好包含 2 个条目
+- NameNode 启动脚本按配置列表顺序解析 peer,而不是依赖固定的 `nn0/nn1` 字面值
+- standby bootstrap 已做启动时序保护,避免首次拉起时再次遇到 `OrderedReady` 场景下的 bootstrapStandby 问题
+
+因此,当前能力是“可配置 NameNode ID 的 2NN active/standby 模型”,不是通用 N 个 NameNode 横向扩展模型。
+
+## 监控说明
+
+Hadoop 当前的监控出口已经切到 `jmx-exporter` sidecar,不再依赖旧的 `metrics2 JmxSink`。
+
+- 旧的 `hadoop-metrics2.properties` JmxSink 路径已经移除
+- NameNode、DataNode、JournalNode Pod 现在都会带一个 `jmx-exporter` sidecar
+- sidecar 通过本地 loopback 抓取 JVM JMX,并对外暴露 `/metrics`
+
+如果希望组件 Service 上带 Prometheus 发现信息,需要在实际部署的 `Cluster` 里将 `spec.componentSpecs[*].disableExporter=false`。
+
+典型的 `PodMonitor` endpoint 如下:
+
+```yaml
+podMetricsEndpoints:
+ - path: /metrics
+ port: http-metrics
+ scheme: http
+```
+
+## 快速开始
+
+### 安装 Addon
+
+在仓库根目录执行:
+
+```bash
+helm install hadoop-addon ./addons/hadoop
+```
+
+### 使用 Cluster Chart 部署
+
+Cluster 模式:
+
+```bash
+helm install hdfs-cluster ./addons-cluster/hadoop \
+ -n demo \
+ --create-namespace \
+ --set topology=cluster \
+ --set serviceRefs.hadoopZookeeper.namespace=kubeblocks \
+ --set serviceRefs.hadoopZookeeper.clusterServiceSelector.cluster=zk
+```
+
+Standalone 模式:
+
+```bash
+helm install hdfs-standalone ./addons-cluster/hadoop \
+ -n demo \
+ --create-namespace \
+ --set topology=standalone
+```
+
+### 部署阶段参数覆盖示例
+
+```yaml
+topology: cluster
+
+replicas:
+ journalnode: 3
+ namenode: 2
+ datanode: 3
+
+hdfs:
+ core:
+ hadoopTmpDir: /hadoop/tmp
+ security:
+ authentication: simple
+ authorization: false
+ ha:
+ nameNodeIds: "nn0,nn1"
+ fencingSshConnectTimeoutMs: 30000
+ namenode:
+ webhdfsEnabled: false
+ resourceDuReserved: 1073741824
+ haLogRollPeriod: 120
+ haTailEditsPeriod: 60
+ datanode:
+ failedVolumesTolerated: 0
+ duReserved: 1073741824
+ journalnode:
+ enableSync: true
+ editCacheSizeBytes: 104857600
+ syncIntervalMs: 120000
+```
+
+## 注意事项
+
+- cluster 模式依赖 ZooKeeper serviceRef
+- 当前 HA 实现严格限定为 2NN active/standby
+- `addons-cluster/hadoop` 里的 deploy-time values 不是对 addon 标准参数链路的替代,而是一层额外的部署便利入口
+- 如果需要按环境切换镜像或 initContainer 镜像,请使用 values 覆盖,不要直接改 vendor 产物
diff --git a/addons/hadoop/config/core-site-standalone.tpl b/addons/hadoop/config/core-site-standalone.tpl
new file mode 100644
index 0000000000..5a480d1cb6
--- /dev/null
+++ b/addons/hadoop/config/core-site-standalone.tpl
@@ -0,0 +1,71 @@
+
+
+
+
+
+ fs.defaultFS
+ hdfs://{{- .CLUSTER_NAME }}-namenode-0.{{- .CLUSTER_NAME }}-namenode-headless.{{-
+ .NAMESPACE }}.svc.{{- .CLUSTER_DOMAIN }}:{{- .HDFS_NAMENODE_RPC_PORT }}
+
+
+
+ fs.trash.interval
+ {{- .HDFS_TRASH_INTERVAL }}
+
+
+
+ io.compression.codecs
+
+ org.apache.hadoop.io.compress.GzipCodec,org.apache.hadoop.io.compress.DefaultCodec,org.apache.hadoop.io.compress.BZip2Codec,org.apache.hadoop.io.compress.SnappyCodec,org.apache.hadoop.io.compress.Lz4Codec
+
+
+
+ hadoop.http.staticuser.user
+ hdfs
+
+
+
+ hadoop.security.authentication
+ {{- .HDFS_SECURITY_AUTHENTICATION }}
+
+
+
+ hadoop.security.authorization
+ {{- .HDFS_SECURITY_AUTHORIZATION }}
+
+
+
+ ipc.client.connection.maxidletime
+ {{- .HDFS_IPC_CLIENT_CONNECTION_MAX_IDLE_TIME_MS }}
+
+
+
+ ipc.client.connect.timeout
+ {{- .HDFS_IPC_CLIENT_CONNECT_TIMEOUT_MS }}
+
+
+
+ ipc.client.connection.pool.size
+ {{- .HDFS_IPC_CLIENT_CONNECTION_POOL_SIZE }}
+
+
+
+ ipc.client.connect.retry.interval
+ {{- .HDFS_IPC_CLIENT_CONNECT_RETRY_INTERVAL_MS }}
+
+
+
+ ipc.client.ping
+ {{- .HDFS_IPC_CLIENT_PING }}
+
+
+
+ ipc.ping.interval
+ {{- .HDFS_IPC_PING_INTERVAL_MS }}
+
+
+
+ hadoop.tmp.dir
+ {{- .HDFS_HADOOP_TMP_DIR }}
+
+
\ No newline at end of file
diff --git a/addons/hadoop/config/core-site.tpl b/addons/hadoop/config/core-site.tpl
new file mode 100644
index 0000000000..cd107b6213
--- /dev/null
+++ b/addons/hadoop/config/core-site.tpl
@@ -0,0 +1,90 @@
+
+
+
+
+
+ fs.defaultFS
+ hdfs://{{- .CLUSTER_NAME }}
+
+
+
+ fs.trash.interval
+ {{- .HDFS_TRASH_INTERVAL }}
+
+
+
+ io.compression.codecs
+
+ org.apache.hadoop.io.compress.GzipCodec,org.apache.hadoop.io.compress.DefaultCodec,org.apache.hadoop.io.compress.BZip2Codec,org.apache.hadoop.io.compress.SnappyCodec,org.apache.hadoop.io.compress.Lz4Codec
+
+
+
+ ha.zookeeper.quorum
+ {{- .ZOOKEEPER_ENDPOINTS }}
+
+
+
+ ha.zookeeper.parent-znode
+ {{- .HDFS_HA_ZOOKEEPER_PARENT_ZNODE }}
+
+
+
+ ha.zookeeper.session-timeout.ms
+ {{- .HDFS_HA_ZOOKEEPER_SESSION_TIMEOUT_MS }}
+
+
+
+ hadoop.http.staticuser.user
+ hdfs
+
+
+
+ hadoop.security.authentication
+ {{- .HDFS_SECURITY_AUTHENTICATION }}
+
+
+
+ hadoop.security.authorization
+ {{- .HDFS_SECURITY_AUTHORIZATION }}
+
+
+
+ ipc.client.connection.maxidletime
+ {{- .HDFS_IPC_CLIENT_CONNECTION_MAX_IDLE_TIME_MS }}
+
+
+
+ ipc.client.connect.timeout
+ {{- .HDFS_IPC_CLIENT_CONNECT_TIMEOUT_MS }}
+
+
+
+ ipc.client.connection.pool.size
+ {{- .HDFS_IPC_CLIENT_CONNECTION_POOL_SIZE }}
+
+
+
+ ipc.client.connect.retry.interval
+ {{- .HDFS_IPC_CLIENT_CONNECT_RETRY_INTERVAL_MS }}
+
+
+
+ ipc.client.ping
+ {{- .HDFS_IPC_CLIENT_PING }}
+
+
+
+ ipc.ping.interval
+ {{- .HDFS_IPC_PING_INTERVAL_MS }}
+
+
+
+ hadoop.tmp.dir
+ {{- .HDFS_HADOOP_TMP_DIR }}
+
+
+
+ hadoop.home.dir
+ /user
+
+
\ No newline at end of file
diff --git a/addons/hadoop/config/dfs.exclude b/addons/hadoop/config/dfs.exclude
new file mode 100644
index 0000000000..62275f3622
--- /dev/null
+++ b/addons/hadoop/config/dfs.exclude
@@ -0,0 +1,3 @@
+# dfs.exclude - DataNode decommission list (blacklist)
+# Add DN hostnames/IPs here and run `hdfs dfsadmin -refreshNodes` to start decommission.
+# DataNodes listed here will be decommissioned and excluded from the cluster.
diff --git a/addons/hadoop/config/dfs.include b/addons/hadoop/config/dfs.include
new file mode 100644
index 0000000000..e94637cf8c
--- /dev/null
+++ b/addons/hadoop/config/dfs.include
@@ -0,0 +1,3 @@
+# dfs.include - DataNode include list (whitelist)
+# Initially empty; add DN hostnames/IPs to explicitly allow them to register.
+# When non-empty, only DataNodes listed here can connect to the NameNode.
diff --git a/addons/hadoop/config/hadoop-env.sh.tpl b/addons/hadoop/config/hadoop-env.sh.tpl
new file mode 100644
index 0000000000..50fe62b23e
--- /dev/null
+++ b/addons/hadoop/config/hadoop-env.sh.tpl
@@ -0,0 +1,22 @@
+export JAVA_HOME=${JAVA_HOME:-/usr/local/openjdk-8}
+export HADOOP_HOME=${HADOOP_HOME:-/opt/hadoop}
+export HADOOP_CONF_DIR=${HADOOP_CONF_DIR:-${HADOOP_HOME}/etc/hadoop}
+export HADOOP_LOG_DIR=${HADOOP_LOG_DIR:-/var/log/hadoop}
+export HADOOP_PID_DIR=${HADOOP_PID_DIR:-/tmp/hadoop}
+export HADOOP_IDENT_STRING=${HADOOP_IDENT_STRING:-$USER}
+
+export HADOOP_OPTS="${HADOOP_OPTS} -Djava.net.preferIPv4Stack=true -Dsun.net.inetaddr.ttl=10 -XX:+UseG1GC -XX:MaxGCPauseMillis=50 -XX:ParallelGCThreads=8"
+export HDFS_HA_NAMENODE_IDS="${HDFS_HA_NAMENODE_IDS:-{{ .HDFS_HA_NAMENODE_IDS }}}"
+export HADOOP_JMX_BASE="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=127.0.0.1"
+
+export HDFS_NAMENODE_OPTS="${HDFS_NAMENODE_OPTS:-} $HADOOP_JMX_BASE -Dcom.sun.management.jmxremote.port={{ .HDFS_NAMENODE_JMX_PORT }} -Dcom.sun.management.jmxremote.rmi.port={{ .HDFS_NAMENODE_JMX_PORT }} -Xms{{ .HDFS_NAMENODE_HEAP }} -Xmx{{ .HDFS_NAMENODE_HEAP }} -Dhadoop.security.logger=INFO,RFAS -Dhdfs.audit.logger=INFO,NullAppender"
+
+export HDFS_DATANODE_OPTS="${HDFS_DATANODE_OPTS:-} $HADOOP_JMX_BASE -Dcom.sun.management.jmxremote.port={{ .HDFS_DATANODE_JMX_PORT }} -Dcom.sun.management.jmxremote.rmi.port={{ .HDFS_DATANODE_JMX_PORT }} -Xms{{ .HDFS_DATANODE_HEAP }} -Xmx{{ .HDFS_DATANODE_HEAP }} -Dhadoop.security.logger=ERROR,RFAS -Ddfs.datanode.hostname=${POD_FQDN}"
+
+export HDFS_JOURNALNODE_OPTS="${HDFS_JOURNALNODE_OPTS:-} $HADOOP_JMX_BASE -Dcom.sun.management.jmxremote.port={{ .HDFS_JOURNALNODE_JMX_PORT }} -Dcom.sun.management.jmxremote.rmi.port={{ .HDFS_JOURNALNODE_JMX_PORT }} -Xms{{ .HDFS_JOURNALNODE_HEAP }} -Xmx{{ .HDFS_JOURNALNODE_HEAP }}"
+
+export HDFS_ZKFC_OPTS="${HDFS_ZKFC_OPTS:-} $HADOOP_JMX_BASE -Dcom.sun.management.jmxremote.port={{ .HDFS_ZKFC_JMX_PORT }} -Dcom.sun.management.jmxremote.rmi.port={{ .HDFS_ZKFC_JMX_PORT }} -Xms{{ .HDFS_ZKFC_HEAP }} -Xmx{{ .HDFS_ZKFC_HEAP }}"
+
+export HADOOP_CLIENT_OPTS="${HADOOP_CLIENT_OPTS:-} -Xmx512m"
+
+export LD_LIBRARY_PATH="${HADOOP_HOME}/lib/native:${LD_LIBRARY_PATH:-}"
diff --git a/addons/hadoop/config/hdfs-common-config-constraint.cue b/addons/hadoop/config/hdfs-common-config-constraint.cue
new file mode 100644
index 0000000000..eddde1662e
--- /dev/null
+++ b/addons/hadoop/config/hdfs-common-config-constraint.cue
@@ -0,0 +1,72 @@
+package kubeblocks
+
+import "strings"
+
+#HDFSCommonParameter: {
+ fsDefaultFS?: string
+ ioFileBufferSize?: int
+ ioBytesPerChecksum?: int
+ ipcClientConnectTimeout?: int
+ ipcClientConnectMaxRetries?: int
+ ipcClientConnectRetryInterval?: int
+ ipcServerListenQueueSize?: int
+ hadoopSecurityAuthorization?: bool
+}
+
+parameter: [string]: {
+ value: string
+ description?: string
+ type: "string" | "int" | "bool"
+ mutable?: bool
+}
+
+parameter: {
+ "fs.defaultFS": {
+ value: #HDFSCommonParameter.fsDefaultFS
+ description: "The name of the default file system. A URI whose scheme and authority determine the FileSystem implementation."
+ type: "string"
+ mutable: false
+ }
+ "io.file.buffer.size": {
+ value: "\( #HDFSCommonParameter.ioFileBufferSize )"
+ description: "The size of buffer for use in sequence files, RPC, etc."
+ type: "int"
+ mutable: true
+ }
+ "io.bytes.per.checksum": {
+ value: "\( #HDFSCommonParameter.ioBytesPerChecksum )"
+ description: "The number of bytes per checksum. Must be less than or equal to io.file.buffer.size."
+ type: "int"
+ mutable: false
+ }
+ "ipc.client.connect.timeout": {
+ value: "\( #HDFSCommonParameter.ipcClientConnectTimeout )"
+ description: "The socket connect timeout in milliseconds."
+ type: "int"
+ mutable: true
+ }
+ "ipc.client.connect.max.retries": {
+ value: "\( #HDFSCommonParameter.ipcClientConnectMaxRetries )"
+ description: "The number of retries for socket connections."
+ type: "int"
+ mutable: true
+ }
+ "ipc.client.connect.retry.interval": {
+ value: "\( #HDFSCommonParameter.ipcClientConnectRetryInterval )"
+ description: "The retry interval in milliseconds for socket connections."
+ type: "int"
+ mutable: true
+ }
+ "ipc.server.listen.queue.size": {
+ value: "\( #HDFSCommonParameter.ipcServerListenQueueSize )"
+ description: "The maximum backlog of TCP connections."
+ type: "int"
+ mutable: true
+ }
+ "hadoop.security.authorization": {
+ value: strings.ToLower("\( #HDFSCommonParameter.hadoopSecurityAuthorization )")
+ description: "Enable service-level authorization checks."
+ type: "bool"
+ mutable: false
+ }
+}
diff --git a/addons/hadoop/config/hdfs-datanode-config-constraint.cue b/addons/hadoop/config/hdfs-datanode-config-constraint.cue
new file mode 100644
index 0000000000..0dbad5c79b
--- /dev/null
+++ b/addons/hadoop/config/hdfs-datanode-config-constraint.cue
@@ -0,0 +1,156 @@
+// Copyright (C) 2022-2023 ApeCloud Co., Ltd
+//
+// This file is part of KubeBlocks project
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+#DataNodeParameter: {
+ // The datanode server address and port for data transfer.
+ "dfs.datanode.address": string | "0.0.0.0:9866"
+
+ // The datanode http server address and port.
+ "dfs.datanode.http.address": string | "0.0.0.0:9864"
+
+ // The datanode ipc server address and port.
+ "dfs.datanode.ipc.address ": string | "0.0.0.0:9867"
+
+ // DataNode配置中用于指定允许进行短路读操作的用户的密钥。
+ "dfs.block.local-path-access.user"?: string
+
+ // 若设置为正整数,表示从DataNode向NameNode上报新增块的等待时间,单位:ms。默认值0,取值范围0~86400000
+ "dfs.blockreport.incremental.intervalMsec": int & <=86400000 | *0
+
+ // 首次块上报的延时时间,单位:秒。默认值0,取值范围0~1500
+ "dfs.blockreport.initialDelay": int & <=1500 | *0
+
+ // 块上报间隔时间,单位:毫秒。默认值21600000,取值范围100~86400000
+ "dfs.blockreport.intervalMsec": int & >=100 & <=86400000 | *21600000
+
+ // DataNode上的块数低于此阈值时将单个消息发送块报告,超过时分开发送。默认值1000000,取值范围0~2000000
+ "dfs.blockreport.split.threshold": int & <=2000000 | *1000000
+
+ // 每个校验和的字节数,不能大于dfs.stream-buffer-size且必须能被dfs.blocksize整除。默认值512,取值范围大于0
+ "dfs.bytes-per-checksum": int & >=1 | *512
+
+ // 控制新块分配到拥有更多可用磁盘空间的卷的比例,适用于AvailableSpaceVolumeChoosingPolicy。默认值0.75,取值范围0~1
+ "dfs.datanode.available-space-volume-choosing-policy.balanced-space-preference-fraction": number | *0.75
+
+ // 控制DataNode卷的负载均衡范围,适用于AvailableSpaceVolumeChoosingPolicy。默认值10737418240,取值范围大于0
+ "dfs.datanode.available-space-volume-choosing-policy.balanced-space-threshold": int & >=1 | *10737418240
+
+ // DataNode可用于负载均衡的最大带宽量(每秒的字节数)。默认值20971520,取值范围1048576~1073741824
+ "dfs.datanode.balance.bandwidthPerSec": int & >=1048576 & <=1073741824 | *20971520
+
+ // 允许在DataNode上进行负载均衡的最大线程数。默认值32,取值范围5~1000
+ "dfs.datanode.balance.max.concurrent.moves": int & >=5 & <=1000 | *32
+
+ // 是否禁止移动写入指定DataNode上的数据块。默认值false
+ "dfs.datanode.block-pinning.enabled": bool | *false
+
+ // DataNode升级时创建前一版本到当前版本硬链接的线程数。默认值24,取值范围大于1
+ "dfs.datanode.block.id.layout.upgrade.threads": int & >=1 | *24
+
+ // DataNode在本地文件系统中存储块的位置。默认值%{@auto.detect.datapart.dn}
+ "dfs.datanode.data.dir": string | *"%{@auto.detect.datapart.dn}"
+
+ // dfs.datanode.data.dir的权限。默认值700
+ "dfs.datanode.data.dir.perm": string | *700
+
+ // DataNode扫描数据目录在磁盘上的块和内存中的块之间的区别的间隔时间,单位:秒。默认值21600,取值范围1~258000
+ "dfs.datanode.directoryscan.interval": int & >=1 & <=258000 | *21600
+
+ // 并行扫描DataNode目录并生成报告的线程数。默认值1,取值范围1~1024
+ "dfs.datanode.directoryscan.threads": int & >=1 & <=1024 | *1
+
+ // DataNode应该上报它IP地址的网络接口名称。默认值"default"
+ "dfs.datanode.dns.interface": string | *"default"
+
+ // DataNode在和NameNode交流时应该用的DNS服务地址主机名或IP地址。默认值"default"
+ "dfs.datanode.dns.nameserver": string | *"default"
+
+ // 是否在读取数据后自动清除缓存中的数据。默认值false
+ "dfs.datanode.drop.cache.behind.reads": bool | *false
+
+ // 是否在写入磁盘后自动清除缓存中的数据。默认值false
+ "dfs.datanode.drop.cache.behind.writes": bool | *false
+
+ // 每个磁盘的保留空间,单位:字节。默认值0,取值范围大于等于0
+ "dfs.datanode.du.reserved": int | *0
+
+ // DataNode上EC数据块的读取缓存大小,单位:字节。默认值131072,取值范围大于1024
+ "dfs.datanode.ec.reconstruction.stripedread.buffer.size": int & >=1024 | *131072
+
+ // DataNode上EC数据块的读取超时时间,单位:毫秒。默认值15000,取值范围大于2000
+ "dfs.datanode.ec.reconstruction.stripedread.timeout.millis": int & >=2000 | *15000
+
+ // DataNode进行EC数据块恢复的线程数。默认值32,取值范围1~1024
+ "dfs.datanode.ec.reconstruction.threads": int & >=1 & <=1024 | *32
+
+ // EC数据块恢复线程数的比重。默认值0.5,取值范围0~1
+ "dfs.datanode.ec.reconstruction.xmits.weight": number | *0.5
+
+ // DataNode停止提供服务前允许失败的卷数。默认值-1,取值范围-1~32768
+ "dfs.datanode.failed.volumes.tolerated": int & >=-1 & <=32768 | *-1
+
+ // DataNode写操作时选择副本的存放位置时考虑每个卷的可用磁盘空间。默认值AvailableSpaceVolumeChoosingPolicy
+ "dfs.datanode.fsdataset.volume.choosing.policy": string & ("org.apache.hadoop.hdfs.server.datanode.fsdataset.RoundRobinVolumeChoosingPolicy" | "org.apache.hadoop.hdfs.server.datanode.fsdataset.AvailableSpaceVolumeChoosingPolicy") | *"org.apache.hadoop.hdfs.server.datanode.fsdataset.AvailableSpaceVolumeChoosingPolicy"
+
+ // 每个卷用于缓存新数据的最大线程数。默认值4,取值范围大于0
+ "dfs.datanode.fsdatasetcache.max.threads.per.volume": int & >=1 | *4
+
+ // DataNode的服务线程数。默认值32,取值范围1~1024
+ "dfs.datanode.handler.count": int & >=1 & <=1024 | *32
+
+ // DataNode的内部web代理端口。默认值50175,取值范围1024~65535
+ "dfs.datanode.http.internal-proxy.port": int & >=1024 & <=65535 | *50175
+
+ // 从DataNode向NameNode发送Lifeline协议消息的间隔周期,单位:秒
+ "dfs.datanode.lifeline.interval.seconds"?: int
+
+ // DataNode用于缓存块副本的内存大小,单位:字节。默认值0,取值范围0~1800000000000
+ "dfs.datanode.max.locked.memory": int & <=1800000000000 | *0
+
+ // DataNode间传输数据的线程的最大数。默认值8192,取值范围1~32768
+ "dfs.datanode.max.transfer.threads": int & >=1 & <=32768 | *8192
+
+ // 要激活的DataNode插件清单
+ "dfs.datanode.plugins"?: string
+
+ // DataNode尝试预先读取的字节数。默认值4194304,取值范围大于等于0
+ "dfs.datanode.readahead.bytes": int | *4194304
+
+ // DataNode是否指示操作系统在写数据后立即写入磁盘。默认值true,取值范围true或false
+ "dfs.datanode.sync.behind.writes": bool | *true
+
+ // DataNode向NameNode发送心跳的时间间隔,单位:秒。默认值10,取值范围3~180
+ "dfs.heartbeat.interval": int & >=3 & <=180 | *10
+
+ // DataNode启用拥塞信令能力。默认值false,取值范围true或false
+ "dfs.pipeline.ecn": bool | *false
+
+ // 流文件缓冲区的大小。默认值4096,取值范围大于0
+ "dfs.stream-buffer-size": int & >=1 | *4096
+
+ // 【说明】是否禁止移动写入指定DataNode上的数据块。该参数值设置为true,在进行Balancer或Mover时,使用colocation写入的文件将不会被移动。【默认值】false
+ "dfs.datanode.block-pinning.enabled": bool | *false
+
+ // 【说明】设置从DataNode向NameNode发送DataNode Lifeline协议消息的间隔周期。单位:秒。该参数值必须大于dfs.heartbeat.interval的值。如果不定义该参数,则默认计算值是dfs.heartbeat.interval值的3倍。
+ "dfs.datanode.lifeline.interval.seconds"?: int
+
+ // 【说明】是否允许备/从NameNode跟踪in-progress状态的edit logs。当客户希望备/从NameNode节点拥有更多较新的数据时,可以设置该参数为true。当QuorumJournalManager共享edit logs时,该参数允许通过RPC机制获取edit logs,而不是文件流,这使得数据传输更快。当使用从NameNode处理读操作时,该参数必须设置为true。【默认值】true
+ "dfs.ha.tail-edits.in-progress": bool | *true
+
+ // 【说明】DataNode向NameNode发送心跳的时间间隔,单位为秒。【默认值】10【取值范围】3~180
+ "dfs.heartbeat.interval": int & >=3 & <=180 | *10
+}
\ No newline at end of file
diff --git a/addons/hadoop/config/hdfs-datanode-standalone.tpl b/addons/hadoop/config/hdfs-datanode-standalone.tpl
new file mode 100644
index 0000000000..70393f2675
--- /dev/null
+++ b/addons/hadoop/config/hdfs-datanode-standalone.tpl
@@ -0,0 +1,100 @@
+
+
+
+
+
+ dfs.datanode.data.dir
+ {{- .HDFS_DATANODE_DATA_DIR }}
+
+
+
+ dfs.datanode.data.dir.perm
+ 700
+
+
+
+ dfs.datanode.failed.volumes.tolerated
+ {{- .HDFS_DATANODE_FAILED_VOLUMES_TOLERATED }}
+
+
+
+ dfs.datanode.max.transfer.threads
+ {{- .HDFS_DATANODE_HANDLER_COUNT }}
+
+
+
+ dfs.datanode.handler.count
+ {{- .HDFS_DATANODE_HANDLER_COUNT }}
+
+
+
+ dfs.datanode.address
+ 0.0.0.0:{{- .HDFS_DATANODE_DATA_PORT }}
+
+
+
+ dfs.datanode.http.address
+ 0.0.0.0:{{- .HDFS_DATANODE_HTTP_PORT }}
+
+
+
+ dfs.datanode.ipc.address
+ 0.0.0.0:{{- .HDFS_DATANODE_IPC_PORT }}
+
+
+
+ dfs.datanode.du.reserved
+ {{- .HDFS_DATANODE_DU_RESERVED }}
+
+
+
+ dfs.datanode.use.datanode.hostname
+ false
+
+
+
+ dfs.namenode.rpc-address
+ {{- .CLUSTER_NAME }}-namenode-0.{{- .CLUSTER_NAME }}-namenode-headless.{{-
+ .NAMESPACE }}.svc.{{- .CLUSTER_DOMAIN }}:{{- .HDFS_NAMENODE_RPC_PORT }}
+
+
+ dfs.namenode.http-address
+ {{- .CLUSTER_NAME }}-namenode-0.{{- .CLUSTER_NAME }}-namenode-headless.{{-
+ .NAMESPACE }}.svc.{{- .CLUSTER_DOMAIN }}:{{- .HDFS_NAMENODE_HTTP_PORT }}
+
+
+
+ dfs.replication
+ {{- .HDFS_REPLICATION }}
+
+
+
+ dfs.client.block.write.replace-datanode-on-failure.policy
+ {{- .HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY }}
+
+
+
+ dfs.permissions.enabled
+ {{- .HDFS_PERMISSIONS_ENABLED }}
+
+
+
+ dfs.hosts
+ {{- .HDFS_CONF_DIR }}/dfs.include
+
+
+
+ dfs.hosts.exclude
+ {{- .HDFS_CONF_DIR }}/dfs.exclude
+
+
+
+ dfs.client.retry.policy.enabled
+ {{- .HDFS_CLIENT_RETRY_POLICY_ENABLED }}
+
+
+
+ dfs.client.retry.policy.spec
+ {{- .HDFS_CLIENT_RETRY_POLICY_SPEC }}
+
+
\ No newline at end of file
diff --git a/addons/hadoop/config/hdfs-datanode.tpl b/addons/hadoop/config/hdfs-datanode.tpl
new file mode 100644
index 0000000000..e812de6cca
--- /dev/null
+++ b/addons/hadoop/config/hdfs-datanode.tpl
@@ -0,0 +1,116 @@
+
+
+
+{{- $name_node_ids := splitList "," .HDFS_HA_NAMENODE_IDS }}
+
+
+ dfs.nameservices
+ {{- .CLUSTER_NAME }}
+
+
+
+ dfs.datanode.data.dir
+ {{- .HDFS_DATANODE_DATA_DIR }}
+
+
+
+ dfs.datanode.data.dir.perm
+ 700
+
+
+
+ dfs.datanode.failed.volumes.tolerated
+ {{- .HDFS_DATANODE_FAILED_VOLUMES_TOLERATED }}
+
+
+
+ dfs.datanode.max.transfer.threads
+ {{- .HDFS_DATANODE_HANDLER_COUNT }}
+
+
+
+ dfs.datanode.handler.count
+ {{- .HDFS_DATANODE_HANDLER_COUNT }}
+
+
+
+ dfs.datanode.address
+ 0.0.0.0:{{- .HDFS_DATANODE_DATA_PORT }}
+
+
+
+ dfs.datanode.http.address
+ 0.0.0.0:{{- .HDFS_DATANODE_HTTP_PORT }}
+
+
+
+ dfs.datanode.ipc.address
+ 0.0.0.0:{{- .HDFS_DATANODE_IPC_PORT }}
+
+
+
+ dfs.datanode.du.reserved
+ {{- .HDFS_DATANODE_DU_RESERVED }}
+
+
+
+ dfs.datanode.use.datanode.hostname
+ false
+
+
+
+ dfs.ha.namenodes.{{- .CLUSTER_NAME }}
+ {{ join "," $name_node_ids }}
+ {{- range $nn_ordinal, $nn_id :=
+ $name_node_ids }}
+ dfs.namenode.rpc-address.{{- $.CLUSTER_NAME }}.{{ $nn_id }}
+ {{- $.CLUSTER_NAME }}-namenode-{{ $nn_ordinal }}.{{- $.CLUSTER_NAME
+ }}-namenode-headless.{{-
+ $.NAMESPACE }}.svc.{{- $.CLUSTER_DOMAIN }}:{{- $.HDFS_NAMENODE_RPC_PORT }}
+
+ {{- end }} {{- range $nn_ordinal, $nn_id := $name_node_ids }}
+ dfs.namenode.http-address.{{- $.CLUSTER_NAME }}.{{ $nn_id }}
+ {{- $.CLUSTER_NAME }}-namenode-{{ $nn_ordinal }}.{{- $.CLUSTER_NAME
+ }}-namenode-headless.{{-
+ $.NAMESPACE }}.svc.{{- $.CLUSTER_DOMAIN }}:{{- $.HDFS_NAMENODE_HTTP_PORT }}
+
+ {{- end }}
+ dfs.client.failover.proxy.provider.{{- .CLUSTER_NAME }}
+ org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
+
+
+
+ dfs.replication
+ {{- .HDFS_REPLICATION }}
+
+
+
+ dfs.client.block.write.replace-datanode-on-failure.policy
+ {{- .HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY }}
+
+
+
+ dfs.permissions.enabled
+ {{- .HDFS_PERMISSIONS_ENABLED }}
+
+
+
+ dfs.hosts
+ {{- .HDFS_CONF_DIR }}/dfs.include
+
+
+
+ dfs.hosts.exclude
+ {{- .HDFS_CONF_DIR }}/dfs.exclude
+
+
+
+ dfs.client.retry.policy.enabled
+ {{- .HDFS_CLIENT_RETRY_POLICY_ENABLED }}
+
+
+
+ dfs.client.retry.policy.spec
+ {{- .HDFS_CLIENT_RETRY_POLICY_SPEC }}
+
+
\ No newline at end of file
diff --git a/addons/hadoop/config/hdfs-jmx-exporter.yaml.tpl b/addons/hadoop/config/hdfs-jmx-exporter.yaml.tpl
new file mode 100644
index 0000000000..29b8b50c22
--- /dev/null
+++ b/addons/hadoop/config/hdfs-jmx-exporter.yaml.tpl
@@ -0,0 +1,9 @@
+jmxUrl: service:jmx:rmi:///jndi/rmi://127.0.0.1:{{ .HDFS_JMX_PORT }}/jmxrmi
+ssl: false
+lowercaseOutputName: true
+lowercaseOutputLabelNames: true
+whitelistObjectNames:
+ - "Hadoop:*"
+ - "java.lang:*"
+rules:
+ - pattern: ".*"
diff --git a/addons/hadoop/config/hdfs-journalnode-config-constraint.cue b/addons/hadoop/config/hdfs-journalnode-config-constraint.cue
new file mode 100644
index 0000000000..a98583de7c
--- /dev/null
+++ b/addons/hadoop/config/hdfs-journalnode-config-constraint.cue
@@ -0,0 +1,75 @@
+// Copyright (C) 2022-2023 ApeCloud Co., Ltd
+//
+// This file is part of KubeBlocks project
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+#JournalNodeParameter: {
+ // 【说明】JournalNode守护进程存储其本地状态的路径。该路径是JournalNode在所在机器上的使用的用来存储edits和其状态一个绝对路径。只可以配置为单个路径。【默认值】${BIGDATA_DATADIR}/journalnode【注意】${BIGDATA_DATADIR}为系统安装时指定的集群数据根目录。请谨慎修改该项。如果配置不当,将造成服务不可用。
+ "dfs.journalnode.edits.dir": string | *"/hadoop/dfs/journal"
+
+ // Permissions for the directories on on the local filesystem where the DFS journal node stores the edits. The permissions can either be octal or symbolic.
+ "dfs.journalnode.edits.dir.perm": int | *"700"
+
+ // The JournalNode RPC server address and port.
+ "dfs.journalnode.rpc-address": string | "0.0.0.0:8485"
+
+ // The address and port the JournalNode HTTP server listens on. If the port is 0 then the server will start on a free port.
+ "dfs.journalnode.http-address": string | "0.0.0.0:8480"
+
+ // The address and port the JournalNode HTTPS server listens on. If the port is 0 then the server will start on a free port.
+ "dfs.journalnode.https-address": string | "0.0.0.0:8481"
+
+ // The actual address the HTTP server will bind to. If this optional address is set, it overrides only the hostname portion of dfs.journalnode.http-address. This is useful for making the JournalNode HTTP server listen on allinterfaces by setting it to 0.0.0.0.
+ "dfs.journalnode.enable.sync": bool | *true
+
+ // 【说明】JournalNode在内存中缓存的edit logs的大小,单位是byte。该缓存用于备/从NameNode通过RPC机制跟踪edit logs,仅当dfs.ha.tail-edits.in-progress时有效。事务的平均大小约为200字节,因此该参数的默认值100MB可以储存大约500000个事务。【默认值】104857600【取值范围】大于1048576
+ "dfs.journalnode.edit-cache-size.bytes": int & >=1048576 | *104857600
+
+ // Time interval, in milliseconds, between two Journal Node syncs. This configuration takes effect only if the journalnode sync is enabled by setting the configuration parameter dfs.journalnode.enable.sync to true.
+ "dfs.journalnode.sync.interval": int & >=1 & <=360000 | *120000
+
+ // 【说明】JVM用于gc的参数。仅当GC_PROFILE设置为custom时该配置才会生效。需确保GC_OPTS参数设置正确,否则进程启动会失败。【默认值】-Xms1G -Xmx2G -XX:NewSize=64M -XX:MaxNewSize=128M -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=128M -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=65 -XX:PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=1M -Djdk.tls.ephemeralDHKeySize=3072 -Djdk.tls.rejectClientInitiatedRenegotiation=true -Djava.io.tmpdir=${Bigdata_tmp_dir}
+ "GC_OPTS": string | *"-Xms1G -Xmx2G -XX:NewSize=64M -XX:MaxNewSize=128M -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=128M -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=65 -XX:PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=1M -Djdk.tls.ephemeralDHKeySize=3072 -Djdk.tls.rejectClientInitiatedRenegotiation=true -Djava.io.tmpdir=${Bigdata_tmp_dir}"
+
+ // 【说明】设置可用于gc的内存大小等级。high表示4G,medium表示2G,low表示256M,custom表示根据实际数据量大小在GC_OPTS中设置内存大小。【默认值】custom【取值范围】high,medium,low,custom
+ "GC_PROFILE": string & ("high" | "medium" | "low" | "custom") | *"custom"
+
+ // 【说明】web服务器允许的最大请求数。【默认值】2000【取值范围】1~1000000
+ "hadoop.http.server.MaxRequests": int & >=1 & <=1000000 | *2000
+
+ // 【说明】运行日志文件的最大个数。【默认值】100【取值范围】1~999
+ "hadoop.log.maxbackupindex": int & >=1 & <=999 | *100
+
+ // 【说明】单个运行日志文件的最大大小。【默认值】100 MB
+ "hadoop.log.maxfilesize": string | *"100MB"
+
+ // 【说明】审计日志级别。【默认值】INFO【取值范围】TRACE、DEBUG、INFO、WARN、ERROR、OFF
+ "hdfs.audit.log.level": string & ("TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR" | "OFF") | *"INFO"
+
+ // 【说明】审计日志文件的最大个数。【默认值】100【取值范围】1~999
+ "hdfs.audit.log.maxbackupindex": int & >=1 & <=999 | *100
+
+ // 【说明】单个审计日志文件的最大大小。【默认值】100MB
+ "hdfs.audit.log.maxfilesize": string | *"100MB"
+
+ // 【说明】日志级别。【默认值】INFO【取值范围】DEBUG、INFO、WARN、ERROR、FATAL
+ "hdfs.log.level": string & ("DEBUG" | "INFO" | "WARN" | "ERROR" | "FATAL") | *"INFO"
+
+ // 【说明】安全审计日志级别。【默认值】WARN【取值范围】INFO、WARN、ERROR、OFF
+ "hdfs.security.log.level": string & ("INFO" | "WARN" | "ERROR" | "OFF") | *"WARN"
+
+ // 【说明】用于指定写入Sequence文件时的缓冲数据的长度,也用于指定读写文件时的缓冲数据的长度,单位为Byte。【默认值】131072【取值范围】大于或等于4096【注意】该大小需要设置为硬件页面大小(Intel x86硬件上,页面大小为4096)的整数倍。
+ "io.file.buffer.size": int & >=1024 | *131072
+}
diff --git a/addons/hadoop/config/hdfs-journalnode.tpl b/addons/hadoop/config/hdfs-journalnode.tpl
new file mode 100644
index 0000000000..744afe4578
--- /dev/null
+++ b/addons/hadoop/config/hdfs-journalnode.tpl
@@ -0,0 +1,64 @@
+
+
+
+
+
+ dfs.nameservices
+ {{- .CLUSTER_NAME }}
+
+
+
+ dfs.journalnode.edits.dir
+ {{- .HDFS_JOURNALNODE_EDITS_DIR }}
+
+
+
+ dfs.journalnode.rpc-address
+ 0.0.0.0:{{- .HDFS_JOURNALNODE_RPC_PORT }}
+
+
+
+ dfs.journalnode.http-address
+ 0.0.0.0:{{- .HDFS_JOURNALNODE_HTTP_PORT }}
+
+
+
+ dfs.journalnode.bind-host
+ 0.0.0.0
+
+
+
+ dfs.permissions.enabled
+ {{- .HDFS_PERMISSIONS_ENABLED }}
+
+
+
+ dfs.replication
+ {{- .HDFS_REPLICATION }}
+
+
+
+ dfs.hosts
+ {{- .HDFS_CONF_DIR }}/dfs.include
+
+
+
+ dfs.hosts.exclude
+ {{- .HDFS_CONF_DIR }}/dfs.exclude
+
+
+
+ dfs.journalnode.enable.sync
+ {{- .HDFS_JOURNALNODE_ENABLE_SYNC }}
+
+
+
+ dfs.journalnode.edit-cache-size.bytes
+ {{- .HDFS_JOURNALNODE_EDIT_CACHE_SIZE_BYTES }}
+
+
+
+ dfs.journalnode.sync.interval
+ {{- .HDFS_JOURNALNODE_SYNC_INTERVAL_MS }}
+
+
diff --git a/addons/hadoop/config/hdfs-namenode-config-constraint.cue b/addons/hadoop/config/hdfs-namenode-config-constraint.cue
new file mode 100644
index 0000000000..79a9a1e0e4
--- /dev/null
+++ b/addons/hadoop/config/hdfs-namenode-config-constraint.cue
@@ -0,0 +1,252 @@
+// Copyright (C) 2022-2023 ApeCloud Co., Ltd
+//
+// This file is part of KubeBlocks project
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+#NameNodeParameter: {
+ // Cluster
+ "dfs.nameservices"?: string | "{{- .CLUSTER_NAME }}"
+
+ // DFS NameNode在本地文件系统存储事务(edits)文件的位置。默认值同dfs.namenode.name.dir的默认值
+ "dfs.namenode.edits.dir": string | *"/hadoop/dfs/metadata"
+
+ // DFS NameNode在本地文件系统存储fsimage的目录,默认值/hadoop/dfs/metadata
+ "dfs.namenode.name.dir": string | *"/hadoop/dfs/metadata"
+
+ // 是否让NameNode尝试恢复失败的dfs.namenode.name.dir。默认值true,取值范围true或false
+ "dfs.namenode.name.dir.restore": bool | *true
+
+ // 执行Balancer时,字节数小于该参数值的块将不会被移动(单位:字节)。默认值10485760,取值范围大于0
+ "dfs.balancer.getBlocks.min-block-size": int | *10485760
+
+ // 在Balancer中,从NameNode获取源DataNode的块列表时,所获取的所有块的总大小 (单位:字节)。默认值2147483648,取值范围大于1073741824
+ "dfs.balancer.getBlocks.size": int & >=1073741824 | *2147483648
+
+ // 执行Balancer时,每次迭代移动的最大字节数。默认值32212254720,取值范围大于1073741824
+ "dfs.balancer.max-size-to-move": int & >=1073741824 | *32212254720
+
+ // 指定NameNode扫描DataNode待删除块的最大数量及向DataNode发送的待删除块数量。默认值10000,取值范围100~1000000
+ "dfs.block.invalidate.limit": int & >=100 & <=1000000 | *10000
+
+ // 选择EC文件的块放置DataNode策略。默认值org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyRackFaultTolerant
+ "dfs.block.placement.ec.classname": string & ("org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyDefault" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyWithRackGroup" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyWithNodeLabel" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyWithNodeGroup" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyWithNonAffinityNodeGroup" | "org.apache.hadoop.hdfs.server.blockmanagement.AvailableSpaceBlockPlacementPolicy" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyRackFaultTolerant" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyWithAZExpression") | *"org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyRackFaultTolerant"
+
+ // 选择副本放置DataNode策略。默认值org.apache.hadoop.hdfs.server.blockmanagement.AvailableSpaceBlockPlacementPolicy
+ "dfs.block.replicator.classname": string & ("org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyDefault" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyWithRackGroup" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyWithNodeLabel" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyWithNodeGroup" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyWithNonAffinityNodeGroup" | "org.apache.hadoop.hdfs.server.blockmanagement.AvailableSpaceBlockPlacementPolicy" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyRackFaultTolerant" | "org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyWithAZExpression") | *"org.apache.hadoop.hdfs.server.blockmanagement.AvailableSpaceBlockPlacementPolicy"
+
+ // 每个校验和的字节数,不能大于dfs.stream-buffer-size值且必须能被dfs.blocksize值整除。默认值512,取值范围大于0
+ "dfs.bytes-per-checksum": int & >=1 | *512
+
+ // 读取EC文件的并发线程数。默认值256,取值范围大于16
+ "dfs.client.read.striped.threadpool.size": int & >=16 | *256
+
+ // 禁止移动写入指定DataNode上的数据块,默认为false。进行Balancer或Mover时,colocation写入的文件不会被移动
+ "dfs.datanode.block-pinning.enabled": bool | *false
+
+ // 设置DataNode向NameNode发送Lifeline协议消息的时间间隔。单位:秒,值必须大于dfs.heartbeat.interval的值
+ "dfs.datanode.lifeline.interval.seconds"?: int
+
+ // 设置磁盘均衡操作时磁盘存储量与理想状态的差异阈值,默认值10,取值范围1~100
+ "dfs.disk.balancer.block.tolerance.percent": int & >=1 & <=100 | *10
+
+ // 设置数据移动过程中容忍的最大错误次数,超过此阈值则移动失败,默认值5,取值范围大于0
+ "dfs.disk.balancer.max.disk.errors": int & >=1 | *5
+
+ // 设置Disk Balancer特性传输数据时使用的最大磁盘带宽,单位:MB/s,默认值10,取值范围大于0
+ "dfs.disk.balancer.max.disk.throughputInMBperSec": int & >=1 | *10
+
+ // 设置两磁盘之间数据密度域值差的容忍阈值,超过此值则需要数据均衡,默认值10,取值范围1~100
+ "dfs.disk.balancer.plan.threshold.percent": int & >=1 & <=100 | *10
+
+ // 备用节点连接主用节点进行edit日志拆分的时间间隔,单位:秒,默认值120,取值范围0~86400
+ "dfs.ha.log-roll.period": int & <=86400 | *120
+
+ // 备用节点检查共享edit日志的时间间隔,单位:毫秒,默认值60000,取值范围0~864000
+ "dfs.ha.tail-edits.period": int & <=864000 | *60000
+
+ // DataNode向NameNode发送心跳的时间间隔,单位:秒,默认值10,取值范围3~180
+ "dfs.heartbeat.interval": int & >=3 & <=180 | *10
+
+ // 是否压缩fsimage,默认值false,取值范围true或false
+ "dfs.image.compress": bool | *false
+
+ // 设置fsimage压缩的codec,默认值org.apache.hadoop.io.compress.DefaultCodec
+ "dfs.image.compression.codec": string & ("none" | "org.apache.hadoop.io.compress.BZip2Codec" | "org.apache.hadoop.io.compress.DefaultCodec" | "org.apache.hadoop.io.compress.DeflateCodec" | "org.apache.hadoop.io.compress.Lz4Codec" | "org.apache.hadoop.io.compress.SnappyCodec" | "org.apache.hadoop.io.compress.GzipCodec" | "org.apache.hadoop.io.compress.ZStandardCodec") | *"org.apache.hadoop.io.compress.DefaultCodec"
+
+ // fsimage包含的inode数量少于该阈值时不生成sub-section,禁用并行加载特性,默认值1000000
+ "dfs.image.parallel.inode.threshold": int & >=1 | *1000000
+
+ // 是否启用fsimage并行加载特性,默认值true,取值范围true或false
+ "dfs.image.parallel.load": bool | *true
+
+ // 生成fsimage时将一个section分解为多少个sub-section,默认值100
+ "dfs.image.parallel.target.sections": int & >=1 | *100
+
+ // 并行加载的线程数量,默认值50,取值范围大于等于1
+ "dfs.image.parallel.threads": int & >=1 | *50
+
+ // fsimage传输带宽,单位:B/s,默认值104857600,取值范围0~1073741824
+ "dfs.image.transfer.bandwidthPerSec": int & <=1073741824 | *104857600
+
+ // fsimage传输超时时间,单位:毫秒,默认值600000,取值范围1~3600000
+ "dfs.image.transfer.timeout": int & >=1 & <=3600000 | *600000
+
+ // HDFS文件访问时间精确到该值,默认值3600000,取值范围大于等于0
+ "dfs.namenode.accesstime.precision": int | *3600000
+
+ // 是否启用HDFS ACL,默认值true,取值范围true或false
+ "dfs.namenode.acls.enabled": bool | *true
+
+ // 是否启用异步审计日志,默认值false,取值范围true或false
+ "dfs.namenode.audit.log.async": bool | *false
+
+ // 审计日志命令列表,默认值"open,getfileinfo,getAclStatus"
+ "dfs.namenode.audit.log.debug.cmdlist": string | *"open,getfileinfo,getAclStatus"
+
+ // 是否优先选择客户端所在节点的DataNode,默认值false
+ "dfs.namenode.available-space-block-placement-policy.balance-local-node": bool | *false
+
+ // 控制新块分配到拥有更多可用磁盘空间的DataNode的比例,默认值0.6,取值范围0~1
+ "dfs.namenode.available-space-block-placement-policy.balanced-space-preference-fraction": number | *0.6
+
+ // 是否避免写入失效DataNode,默认值true,取值范围true或false
+ "dfs.namenode.avoid.write.stale.datanode": bool | *true
+
+ // 增量删除块的数量,默认值1000,取值范围大于等于1
+ "dfs.namenode.block.deletion.increment": int & >=1 | *1000
+
+ // 备NameNode每隔dfs.namenode.checkpoint.check.period秒轮询查询未检查点的事务,默认值60,取值范围0~86400
+ "dfs.namenode.checkpoint.check.period": int & <=86400 | *60
+
+ // 两个检查点间的时间间隔,单位:秒,默认值3600
+ "dfs.namenode.checkpoint.period": int | *360
+
+ // 让备NameNode或检查点节点创建检查点的事务数,无论"dfs.namenode.checkpoint.period"是否到达。默认值5000000,取值范围1~10000000000
+ "dfs.namenode.checkpoint.txns": int & >=1 & <=10000000000 | *5000000
+
+ // EC策略可以设置的数据块大小的最大值,单位为Byte。默认值4194304,取值范围大于131072
+ "dfs.namenode.ec.policies.max.cellsize": int & >=131072 | *4194304
+
+ // 给目录设置EC策略时,如果不指定具体的EC策略,将默认使用该策略。默认值RS-6-3-1024k
+ "dfs.namenode.ec.system.default.policy": string & ("RS-3-2-1024k" | "RS-6-3-1024k" | "RS-10-4-1024k" | "RS-LEGACY-6-3-1024k" | "XOR-2-1-1024k") | *"RS-6-3-1024k"
+
+ // 是否对edit日志文件通道进行持久化。默认值false
+ "dfs.namenode.edits.noeditlogchannelflush": bool | *false
+
+ // 是否在NameNode启用重试缓存。默认值true,取值范围true或false
+ "dfs.namenode.enable.retrycache": bool | *true
+
+ // 所有块提交后文件才关闭,N个块提交且其他块完成后才关闭文件。默认值0,取值范围大于等于0
+ "dfs.namenode.file.close.num-committed-allowed": int | *0
+
+ // 每个文件可包含的最大块数,NameNode写操作时使用。默认值1048576,取值范围大于0
+ "dfs.namenode.fs-limits.max-blocks-per-file": int & >=1 | *1048576
+
+ // 定义路径的每个组成部分中的最大UTF-8编码字节数。默认值7999,取值范围255~7999
+ "dfs.namenode.fs-limits.max-component-length": int & >=255 & <=7999 | *7999
+
+ // 定义目录中包含的最大条目数。默认值1048576,取值范围1~6400000
+ "dfs.namenode.fs-limits.max-directory-items": int & >=1 & <=6400000 | *1048576
+
+ // 最小块大小,NameNode创建块时使用。单位:字节,默认值1048576,取值范围大于0
+ "dfs.namenode.fs-limits.min-block-size": int & >=1 | *1048576
+
+ // NameNode的RPC服务端用于监听客户端请求的线程数。默认值128,取值范围1~1024
+ "dfs.namenode.handler.count": int & >=1 & <=1024 | *128
+
+ // 再次检查DataNode可用性的间隔,单位:毫秒。默认值300000,取值范围1000~86400000
+ "dfs.namenode.heartbeat.recheck-interval": int & >=1000 & <=86400000 | *300000
+
+ // Inode属性插件。默认值com.huawei.hadoop.adapter.hdfs.plugin.HWRangerHdfsAuthorizer
+ "dfs.namenode.inode.attributes.provider.class": string | *"com.huawei.hadoop.adapter.hdfs.plugin.HWRangerHdfsAuthorizer"
+
+ // NameNode扫描待删除块时扫描的DataNode数量占总DN数量的百分比。默认值0.32,取值范围0~1
+ "dfs.namenode.invalidate.work.pct.per.iteration": number | *0.32
+
+ // NameNode的RPC服务端用于处理DataNode的lifeline协议和HA健康检查请求的线程数。默认值16,取值范围1~1024
+ "dfs.namenode.lifeline.handler.count": int & >=1 & <=1024 | *16
+
+ // NameNode保存的fsimage文件个数。默认值3,取值范围1~86400
+ "dfs.namenode.num.checkpoints.retained": int & >=1 & <=86400 | *3
+
+ // 为NameNode重启所保留的额外事务数。默认值1000000,取值范围大于等于0
+ "dfs.namenode.num.extra.edits.retained": int | *1000000
+
+ // 为缓存块映射分配的Java堆比例。默认值"0.25f"
+ "dfs.namenode.path.based.cache.block.map.allocation.percent": string | *"0.25f"
+
+ // 初始化Quota的并发线程数。默认值32,取值范围大于0
+ "dfs.namenode.quota.init-threads": int & >=1 | *32
+
+ // 块重建的超时参数,单位:秒。默认值900,取值范围大于等于-1
+ "dfs.namenode.reconstruction.pending.timeout-sec": int & >=-1 | *900
+
+ // 给新文件选择DataNode时是否考虑DataNode的负载。默认值true,取值范围true或false
+ "dfs.namenode.redundancy.considerLoad": bool | *true
+
+ // 当DataNode负载超过平均负载的倍数时,不会选择它存储新文件。默认值4,取值范围1~100
+ "dfs.namenode.redundancy.considerLoad.factor": number | *4
+
+ // NameNode发送块复制命令时并行传输的块总量。默认值32,取值范围0~9223372036854775807
+ "dfs.namenode.replication.work.multiplier.per.iteration": int & <=9223372036854775807 | *32
+
+ // 重试缓存条目保留时长,单位:毫秒。默认值600000,取值范围大于0
+ "dfs.namenode.retrycache.expirytime.millis": int & >=1 | *600000
+
+ // 为重试缓存分配的堆大小比例。默认值"0.03f"
+ "dfs.namenode.retrycache.heap.percent": string | *"0.03f"
+
+ // NameNode退出安全模式前的时间,单位:毫秒。默认值15000,取值范围0~3600000
+ "dfs.namenode.safemode.extension": int & <=3600000 | *15000
+
+ // NameNode退出安全模式前必须处于alive状态的DataNode数。默认值0,取值范围0~65535
+ "dfs.namenode.safemode.min.datanodes": int & <=65535 | *0
+
+ // NameNode的RPC服务端用于监听DataNode请求的线程数。默认值32,取值范围1~1024
+ "dfs.namenode.service.handler.count": int & >=1 & <=1024 | *32
+
+ // 将DataNode标记为失效的时间间隔。默认值30000,取值范围大于0
+ "dfs.namenode.stale.datanode.interval": int | *30000
+
+ // NameNode启动后,块删除的延迟时间,单位:秒。默认值3600,取值范围0~65535
+ "dfs.namenode.startup.delay.block.deletion.sec": int & <=65535 | *3600
+
+ // 当失效DataNode数和总数比值大于该比例时,停止避免写入失效DataNode。默认值0.5f,取值范围0~1f
+ "dfs.namenode.write.stale.datanode.ratio": string | *"0.5f"
+
+ // 是否为HDFS启用权限检查。默认值true,取值范围true或false
+ "dfs.permissions.ContentSummary.subAccess": bool | *true
+
+ // 是否为HDFS启用权限检查。默认值true,取值范围true或false
+ "dfs.permissions.enabled": bool | *true
+
+ // quorum journal edits的队列大小,单位:MB。默认值150,取值范围10~4096
+ "dfs.qjournal.queued-edits.limit.mb": int & >=10 & <=4096 | *150
+
+ // 将事务写入大部分quorum journal节点的等待时间,单位:毫秒。默认值20000,取值范围1~3600000
+ "dfs.qjournal.write-txns.timeout.ms": int & >=1 & <=3600000 | *20000
+
+ // 最大块副本数。默认值512,取值范围3~1024
+ "dfs.replication.max": int & >=3 & <=1024 | *512
+
+ // 启用异构存储。默认值true,取值范围true或false
+ "dfs.storage.policy.enabled": bool | *true
+
+ // 流文件缓冲区大小。默认值4096,取值范围大于0
+ "dfs.stream-buffer-size": int & >=1 | *4096
+
+ // 是否使用DFSNetworkTopology选择副本放置的DataNode。默认值true,取值范围true或false
+ "dfs.use.dfs.network.topology": bool | *true
+}
diff --git a/addons/hadoop/config/hdfs-namenode-standalone.tpl b/addons/hadoop/config/hdfs-namenode-standalone.tpl
new file mode 100644
index 0000000000..781c062272
--- /dev/null
+++ b/addons/hadoop/config/hdfs-namenode-standalone.tpl
@@ -0,0 +1,89 @@
+
+
+
+
+
+ dfs.namenode.name.dir
+ {{- .HDFS_NAMENODE_NAME_DIR }}
+
+
+
+ dfs.namenode.rpc-address
+ 0.0.0.0:{{- .HDFS_NAMENODE_RPC_PORT }}
+
+
+
+ dfs.namenode.http-address
+ 0.0.0.0:{{- .HDFS_NAMENODE_HTTP_PORT }}
+
+
+
+ dfs.namenode.rpc-bind-host
+ 0.0.0.0
+
+
+
+ dfs.namenode.http-bind-host
+ 0.0.0.0
+
+
+
+ dfs.permissions.enabled
+ {{- .HDFS_PERMISSIONS_ENABLED }}
+
+
+
+ dfs.permissions.superusergroup
+ {{- .HDFS_PERMISSIONS_SUPERUSERGROUP }}
+
+
+
+ dfs.namenode.datanode.registration.ip-hostname-check
+ {{- .HDFS_REGISTRATION_IP_HOSTNAME_CHECK }}
+
+
+
+ dfs.replication
+ {{- .HDFS_REPLICATION }}
+
+
+
+ dfs.replication.max
+ {{- .HDFS_REPLICATION_MAX }}
+
+
+
+ dfs.client.block.write.replace-datanode-on-failure.policy
+ {{- .HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY }}
+
+
+
+ dfs.namenode.handler.count
+ {{- .HDFS_NAMENODE_HANDLER_COUNT }}
+
+
+
+ dfs.hosts
+ {{- .HDFS_CONF_DIR }}/dfs.include
+
+
+
+ dfs.hosts.exclude
+ {{- .HDFS_CONF_DIR }}/dfs.exclude
+
+
+
+ dfs.webhdfs.enabled
+ {{- .HDFS_NAMENODE_WEBHDFS_ENABLED }}
+
+
+
+ dfs.client.retry.policy.enabled
+ {{- .HDFS_CLIENT_RETRY_POLICY_ENABLED }}
+
+
+
+ dfs.client.retry.policy.spec
+ {{- .HDFS_CLIENT_RETRY_POLICY_SPEC }}
+
+
diff --git a/addons/hadoop/config/hdfs-namenode.tpl b/addons/hadoop/config/hdfs-namenode.tpl
new file mode 100644
index 0000000000..5294b97182
--- /dev/null
+++ b/addons/hadoop/config/hdfs-namenode.tpl
@@ -0,0 +1,211 @@
+
+
+
+{{- $fqnds := splitList "," .JOURNALNODE_POD_FQDN_LIST }}
+{{- $journalnode_fqdns := printf "qjournal://" }}
+{{- $journalnode_rpc_port := .HDFS_JOURNALNODE_RPC_PORT }}
+{{- $name_node_ids := splitList "," .HDFS_HA_NAMENODE_IDS }}
+{{- range $i, $fqdn := $fqnds }}
+{{- $journalnode_fqdns = printf "%s%s:%s" $journalnode_fqdns $fqdn $journalnode_rpc_port }}
+{{- if lt $i (sub (len $fqnds) 1) }}
+{{- $journalnode_fqdns = printf "%s;" $journalnode_fqdns }}
+{{- end }}
+{{- end }}
+{{- $journalnode_fqdns = printf "%s/%s" $journalnode_fqdns .CLUSTER_NAME }}
+
+
+
+ dfs.nameservices
+ {{- .CLUSTER_NAME }}
+
+
+
+ dfs.namenode.name.dir
+ {{- .HDFS_NAMENODE_NAME_DIR }}
+
+
+
+ dfs.ha.namenodes.{{- .CLUSTER_NAME }}
+ {{ join "," $name_node_ids }}
+ {{- range $nn_ordinal, $nn_id :=
+ $name_node_ids }}
+ dfs.namenode.rpc-address.{{- $.CLUSTER_NAME }}.{{ $nn_id }}
+ {{- $.CLUSTER_NAME }}-namenode-{{ $nn_ordinal }}.{{- $.CLUSTER_NAME
+ }}-namenode-headless.{{-
+ $.NAMESPACE }}.svc.{{- $.CLUSTER_DOMAIN }}:{{- $.HDFS_NAMENODE_RPC_PORT }}
+
+ {{- end }} {{- range $nn_ordinal, $nn_id := $name_node_ids }}
+ dfs.namenode.http-address.{{- $.CLUSTER_NAME }}.{{ $nn_id }}
+ {{- $.CLUSTER_NAME }}-namenode-{{ $nn_ordinal }}.{{- $.CLUSTER_NAME
+ }}-namenode-headless.{{-
+ $.NAMESPACE }}.svc.{{- $.CLUSTER_DOMAIN }}:{{- $.HDFS_NAMENODE_HTTP_PORT }}
+
+ {{- end }}
+ dfs.namenode.rpc-bind-host
+ 0.0.0.0
+
+
+ dfs.namenode.http-bind-host
+ 0.0.0.0
+
+
+
+ dfs.namenode.shared.edits.dir
+ {{- $journalnode_fqdns }}
+
+
+
+ dfs.client.failover.proxy.provider.{{- .CLUSTER_NAME }}
+ org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
+
+
+
+ dfs.ha.fencing.methods
+ {{- .HDFS_HA_FENCING_METHODS }}
+
+
+
+ dfs.ha.fencing.ssh.private-key-files
+ /var/lib/hadoop-hdfs/.ssh/id_dsa
+
+
+
+ dfs.ha.fencing.ssh.connect-timeout
+ {{- .HDFS_HA_FENCING_SSH_CONNECT_TIMEOUT_MS }}
+
+
+
+ dfs.ha.automatic-failover.enabled
+ {{- .HDFS_HA_AUTOMATIC_FAILOVER_ENABLED }}
+
+
+
+ dfs.ha.failover-controller.active-standby-elector.zk.op.retries
+ {{- .HDFS_HA_ZOOKEEPER_OPERATION_RETRIES }}
+
+
+
+ dfs.permissions.enabled
+ {{- .HDFS_PERMISSIONS_ENABLED }}
+
+
+
+ dfs.permissions.superusergroup
+ {{- .HDFS_PERMISSIONS_SUPERUSERGROUP }}
+
+
+
+ dfs.namenode.datanode.registration.ip-hostname-check
+ {{- .HDFS_REGISTRATION_IP_HOSTNAME_CHECK }}
+
+
+
+ dfs.replication
+ {{- .HDFS_REPLICATION }}
+
+
+
+ dfs.replication.max
+ {{- .HDFS_REPLICATION_MAX }}
+
+
+
+ dfs.client.block.write.replace-datanode-on-failure.policy
+ {{- .HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY }}
+
+
+
+ dfs.namenode.handler.count
+ {{- .HDFS_NAMENODE_HANDLER_COUNT }}
+
+
+
+ dfs.namenode.service.handler.count
+ {{- .HDFS_NAMENODE_HANDLER_COUNT }}
+
+
+
+ dfs.hosts
+ {{- .HDFS_CONF_DIR }}/dfs.include
+
+
+
+ dfs.hosts.exclude
+ {{- .HDFS_CONF_DIR }}/dfs.exclude
+
+
+
+ dfs.webhdfs.enabled
+ {{- .HDFS_NAMENODE_WEBHDFS_ENABLED }}
+
+
+
+ dfs.datanode.block-pinning.enabled
+ true
+
+
+
+ dfs.namenode.avoid.read.stale.datanode
+ true
+
+
+
+ dfs.namenode.avoid.write.stale.datanode
+ true
+
+
+
+ dfs.namenode.resource.du.reserved
+ {{- .HDFS_NAMENODE_RESOURCE_DU_RESERVED }}
+
+
+
+ dfs.client.retry.policy.enabled
+ {{- .HDFS_CLIENT_RETRY_POLICY_ENABLED }}
+
+
+
+ dfs.client.retry.policy.spec
+ {{- .HDFS_CLIENT_RETRY_POLICY_SPEC }}
+
+
+
+ dfs.namenode.stale.datanode.interval
+ 30000
+
+
+
+ dfs.ha.log-roll.period
+ {{- .HDFS_HA_LOG_ROLL_PERIOD }}
+
+
+
+ dfs.ha.tail-edits.period
+ {{- .HDFS_HA_TAIL_EDITS_PERIOD }}
+
+
+
+ dfs.image.transfer.bandwidthPerSec
+ 0
+
+
+
+ dfs.namenode.num.checkpoints.retained
+ 2
+
+
+
+ dfs.namenode.num.extra.edits.retained
+ 1000000
+
+
+
+ dfs.journalnode.http-address
+ 0.0.0.0:8480
+
+
+
+ dfs.journalnode.rpc-address
+ 0.0.0.0:8485
+
+
\ No newline at end of file
diff --git a/addons/hadoop/config/log4j.properties b/addons/hadoop/config/log4j.properties
new file mode 100644
index 0000000000..91504edb77
--- /dev/null
+++ b/addons/hadoop/config/log4j.properties
@@ -0,0 +1,59 @@
+# Set root logger level to INFO and output to console and file
+log4j.rootLogger=INFO, console, file
+
+# Console log output
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p %c{2}: %m%n
+
+# File log output
+log4j.appender.file=org.apache.log4j.RollingFileAppender
+log4j.appender.file.File=${hadoop.log.dir}/hadoop.log
+log4j.appender.file.MaxFileSize=256MB
+log4j.appender.file.MaxBackupIndex=5
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d{ISO8601} %-5p %c{2}: %m%n
+
+# NameNode log configuration
+log4j.logger.org.apache.hadoop.hdfs.server.namenode.NameNode=INFO, namenodeAppender
+log4j.appender.namenodeAppender=org.apache.log4j.RollingFileAppender
+log4j.appender.namenodeAppender.File=${hadoop.log.dir}/hadoop-hdfs-namenode.log
+log4j.appender.namenodeAppender.MaxFileSize=256MB
+log4j.appender.namenodeAppender.MaxBackupIndex=5
+log4j.appender.namenodeAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.namenodeAppender.layout.ConversionPattern=%d{ISO8601} %-5p %c{2}: %m%n
+
+# DataNode log configuration
+log4j.logger.org.apache.hadoop.hdfs.server.datanode.DataNode=INFO, datanodeAppender
+log4j.appender.datanodeAppender=org.apache.log4j.RollingFileAppender
+log4j.appender.datanodeAppender.File=${hadoop.log.dir}/hadoop-hdfs-datanode.log
+log4j.appender.datanodeAppender.MaxFileSize=256MB
+log4j.appender.datanodeAppender.MaxBackupIndex=5
+log4j.appender.datanodeAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.datanodeAppender.layout.ConversionPattern=%d{ISO8601} %-5p %c{2}: %m%n
+
+# ResourceManager log configuration
+log4j.logger.org.apache.hadoop.yarn.server.resourcemanager.ResourceManager=INFO, resourcemanagerAppender
+log4j.appender.resourcemanagerAppender=org.apache.log4j.RollingFileAppender
+log4j.appender.resourcemanagerAppender.File=${hadoop.log.dir}/hadoop-yarn-resourcemanager.log
+log4j.appender.resourcemanagerAppender.MaxFileSize=256MB
+log4j.appender.resourcemanagerAppender.MaxBackupIndex=5
+log4j.appender.resourcemanagerAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.resourcemanagerAppender.layout.ConversionPattern=%d{ISO8601} %-5p %c{2}: %m%n
+
+# NodeManager log configuration
+log4j.logger.org.apache.hadoop.yarn.server.nodemanager.NodeManager=INFO, nodemanagerAppender
+log4j.appender.nodemanagerAppender=org.apache.log4j.RollingFileAppender
+log4j.appender.nodemanagerAppender.File=${hadoop.log.dir}/hadoop-yarn-nodemanager.log
+log4j.appender.nodemanagerAppender.MaxFileSize=256MB
+log4j.appender.nodemanagerAppender.MaxBackupIndex=5
+log4j.appender.nodemanagerAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.nodemanagerAppender.layout.ConversionPattern=%d{ISO8601} %-5p %c{2}: %m%n
+
+# Log configuration for other components
+log4j.logger.org.apache.hadoop.security=INFO
+log4j.logger.org.apache.hadoop.ipc=INFO
+log4j.logger.org.apache.hadoop.mapred=INFO
+log4j.logger.org.apache.hadoop.hdfs=INFO
+log4j.logger.org.apache.hadoop.yarn=INFO
diff --git a/addons/hadoop/releases_notes.yaml b/addons/hadoop/releases_notes.yaml
new file mode 100644
index 0000000000..5816a13013
--- /dev/null
+++ b/addons/hadoop/releases_notes.yaml
@@ -0,0 +1,5 @@
+releases:
+ - version: 1.1.0
+ notes:
+ en: Initial HDFS HA cluster support on KubeBlocks
+ zh: 在 KubeBlocks 上的初始 HDFS HA 集群支持
\ No newline at end of file
diff --git a/addons/hadoop/scripts/check-data-status.sh b/addons/hadoop/scripts/check-data-status.sh
new file mode 100644
index 0000000000..6b89f4adb9
--- /dev/null
+++ b/addons/hadoop/scripts/check-data-status.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+set -o errexit
+set -o errtrace
+set -o nounset
+set -o pipefail
+
+_PORTS="${HDFS_DATANODE_HTTP_PORT:-9864}"
+_URL_PATH="jmx?qry=Hadoop:service=DataNode,name=DataNodeInfo"
+_CLUSTER_ID=""
+for _PORT in $_PORTS; do
+ _CLUSTER_ID+=$(curl -s http://localhost:${_PORT}/$_URL_PATH | grep ClusterId) || true
+done
+echo $_CLUSTER_ID | grep -q -v null
diff --git a/addons/hadoop/scripts/check-journal-status.sh b/addons/hadoop/scripts/check-journal-status.sh
new file mode 100644
index 0000000000..eb34b26592
--- /dev/null
+++ b/addons/hadoop/scripts/check-journal-status.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+# Exit on error. Append "|| true" if you expect an error.
+set -o errexit
+# Exit on error inside any functions or subshells.
+set -o errtrace
+# Do not allow use of undefined vars. Use ${VAR:-} to use an undefined VAR
+set -o nounset
+# Catch an error in command pipes. e.g. mysqldump fails (but gzip succeeds)
+# in `mysqldump |gzip`
+set -o pipefail
+# Turn on traces, useful while debugging.
+set -o xtrace
+
+# Check if datanode registered with the namenode and got non-null cluster ID.
+_PORTS="${HDFS_JOURNALNODE_HTTP_PORT:-8480}"
+_URL_PATH="jmx?qry=Hadoop:service=JournalNode,name=JournalNodeInfo"
+_CLUSTER_ID=""
+for _PORT in $_PORTS; do
+ _CLUSTER_ID+=$(curl -s http://localhost:${_PORT}/$_URL_PATH | \
+ grep ClusterId) || true
+done
+echo $_CLUSTER_ID | grep -q -v null
diff --git a/addons/hadoop/scripts/check-name-status.sh b/addons/hadoop/scripts/check-name-status.sh
new file mode 100644
index 0000000000..198d6d80af
--- /dev/null
+++ b/addons/hadoop/scripts/check-name-status.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+set -o errexit
+set -o errtrace
+set -o nounset
+set -o pipefail
+
+: "${HADOOP_HOME:=/opt/hadoop}"
+: "${HADOOP_CONF_DIR:=${HADOOP_HOME}/etc/hadoop}"
+export HADOOP_HOME HADOOP_CONF_DIR
+
+_NN_HTTP_PORT="${HDFS_NAMENODE_HTTP_PORT:-9870}"
+
+CLUSTER_ID_RESP=$(curl -s --connect-timeout 5 --max-time 10 "http://localhost:${_NN_HTTP_PORT}/jmx?qry=Hadoop:service=NameNode,name=NameNodeInfo" 2>/dev/null || echo "")
+if echo "${CLUSTER_ID_RESP}" | grep -q '"ClusterId"'; then
+ NN_STATUS=$(curl -s --connect-timeout 5 --max-time 10 "http://localhost:${_NN_HTTP_PORT}/jmx?qry=Hadoop:service=NameNode,name=NameNodeStatus" 2>/dev/null || echo "")
+ STATE=$(echo "${NN_STATUS}" | grep -o '"State"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"State"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
+ if [[ -z "$STATE" ]]; then
+ echo "NameNode is up but state could not be determined, considering alive"
+ exit 0
+ fi
+ if [[ "$STATE" == "active" || "$STATE" == "standby" ]]; then
+ echo "NameNode is ${STATE}"
+ exit 0
+ fi
+ echo "NameNode is in unexpected state: ${STATE}"
+ exit 1
+fi
+
+echo "NameNode JMX not ready yet"
+exit 1
diff --git a/addons/hadoop/scripts/datanode-decommission.sh b/addons/hadoop/scripts/datanode-decommission.sh
new file mode 100644
index 0000000000..d8ea6c32f1
--- /dev/null
+++ b/addons/hadoop/scripts/datanode-decommission.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+set -o errexit
+set -o errtrace
+set -o nounset
+set -o pipefail
+
+: "${HADOOP_HOME:=/opt/hadoop}"
+: "${HADOOP_CONF_DIR:=${HADOOP_HOME}/etc/hadoop}"
+export HADOOP_HOME HADOOP_CONF_DIR
+
+EXCLUDE_FILE="${HADOOP_CONF_DIR}/dfs.exclude"
+CURRENT_HOST=$(hostname -f 2>/dev/null || hostname)
+
+echo "[$(date)] Starting DataNode decommission for ${CURRENT_HOST}..."
+
+if [[ -f "$EXCLUDE_FILE" ]]; then
+ if grep -q "${CURRENT_HOST}" "$EXCLUDE_FILE" 2>/dev/null; then
+ echo "[$(date)] Host already in exclude file"
+ else
+ echo "${CURRENT_HOST}" >> "$EXCLUDE_FILE"
+ fi
+else
+ echo "${CURRENT_HOST}" > "$EXCLUDE_FILE"
+fi
+
+"${HADOOP_HOME}/bin/hdfs" dfsadmin -refreshNodes || true
+
+echo "[$(date)] Waiting for decommission to complete (max wait 300s)..."
+for i in $(seq 1 60); do
+ DECOMM_STATUS=$("${HADOOP_HOME}/bin/hdfs" dfsadmin -report 2>/dev/null | grep -A 5 "Name: ${CURRENT_HOST}" | grep "Decommission Status" | head -1 || echo "")
+ if echo "$DECOMM_STATUS" | grep -q "Decommissioned"; then
+ echo "[$(date)] DataNode ${CURRENT_HOST} successfully decommissioned"
+ exit 0
+ fi
+ sleep 5
+done
+
+echo "[$(date)] Decommission wait timed out, proceeding with shutdown anyway"
+exit 0
diff --git a/addons/hadoop/scripts/init-namenode-format.sh b/addons/hadoop/scripts/init-namenode-format.sh
new file mode 100644
index 0000000000..74a3ff4b62
--- /dev/null
+++ b/addons/hadoop/scripts/init-namenode-format.sh
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+set -o errexit
+set -o errtrace
+set -o nounset
+set -o pipefail
+
+: "${HADOOP_HOME:=/opt/hadoop}"
+: "${HADOOP_CONF_DIR:=${HADOOP_HOME}/etc/hadoop}"
+export HADOOP_HOME HADOOP_CONF_DIR
+
+POD_NAME="${POD_NAME:-$(hostname)}"
+if [[ "$POD_NAME" != *"-0" ]] && [[ "$(hostname)" != *"-0" ]]; then
+ echo "Only namenode ordinal 0 formats; this pod is $(hostname), skipping format"
+ exit 0
+fi
+
+SLEEP_TIME=$((RANDOM % 120))
+echo "Sleeping ${SLEEP_TIME}s to reduce race risk between NN-0 and NN-1 bootstrap..."
+sleep "$SLEEP_TIME"
+
+NAME_DIRS=$("${HADOOP_HOME}/bin/hdfs" getconf -confKey dfs.namenode.name.dir 2>/dev/null || echo "")
+NN_DIR="${NAME_DIRS%%,*}"
+NN_DIR="${NN_DIR#file://}"
+NN_CURRENT_DIR="${NN_DIR}/current"
+
+if [[ -d "$NN_CURRENT_DIR" ]] && find "$NN_CURRENT_DIR" -maxdepth 1 -type f -name 'fsimage_*' ! -name '*.md5' 2>/dev/null | grep -q .; then
+ echo "Valid fsimage already exists, skipping format"
+ exit 0
+fi
+
+NAMESERVICES=$("${HADOOP_HOME}/bin/hdfs" getconf -confKey dfs.nameservices 2>/dev/null || echo "")
+if [[ -z "$NAMESERVICES" ]]; then
+ echo "No dfs.nameservices configured (standalone mode), using default format"
+ echo "N" | "${HADOOP_HOME}/bin/hdfs" namenode -format || true
+else
+ echo "Formatting NameNode for nameservice ${NAMESERVICES}"
+ echo "N" | "${HADOOP_HOME}/bin/hdfs" namenode -format "$NAMESERVICES" || true
+fi
diff --git a/addons/hadoop/scripts/init-refresh-nodes.sh b/addons/hadoop/scripts/init-refresh-nodes.sh
new file mode 100644
index 0000000000..ccfa149ff0
--- /dev/null
+++ b/addons/hadoop/scripts/init-refresh-nodes.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+set -o errexit
+set -o errtrace
+set -o nounset
+set -o pipefail
+
+: "${HADOOP_HOME:=/opt/hadoop}"
+: "${HADOOP_CONF_DIR:=${HADOOP_HOME}/etc/hadoop}"
+export HADOOP_HOME HADOOP_CONF_DIR
+
+echo "[$(date)] Refreshing DataNode include/exclude lists on NameNode..."
+"${HADOOP_HOME}/bin/hdfs" dfsadmin -refreshNodes || true
+echo "[$(date)] refreshNodes completed"
diff --git a/addons/hadoop/scripts/init-zkfc-format.sh b/addons/hadoop/scripts/init-zkfc-format.sh
new file mode 100644
index 0000000000..deae5f36a2
--- /dev/null
+++ b/addons/hadoop/scripts/init-zkfc-format.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+set -o errexit
+set -o errtrace
+set -o nounset
+set -o pipefail
+
+: "${HADOOP_HOME:=/opt/hadoop}"
+: "${HADOOP_CONF_DIR:=${HADOOP_HOME}/etc/hadoop}"
+export HADOOP_HOME HADOOP_CONF_DIR
+
+echo "Formatting ZKFC (creating HA znode in ZooKeeper)..."
+echo "N" | "${HADOOP_HOME}/bin/hdfs" zkfc -formatZK || true
+echo "ZKFC format completed"
diff --git a/addons/hadoop/scripts/start-datanode.sh b/addons/hadoop/scripts/start-datanode.sh
new file mode 100644
index 0000000000..83c882e47e
--- /dev/null
+++ b/addons/hadoop/scripts/start-datanode.sh
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+set -o errexit
+set -o errtrace
+set -o nounset
+set -o pipefail
+
+: "${HADOOP_HOME:=/opt/hadoop}"
+: "${HADOOP_CONF_DIR:=${HADOOP_HOME}/etc/hadoop}"
+: "${HADOOP_LOG_DIR:=/var/log/hadoop}"
+: "${HADOOP_PID_DIR:=/tmp/hadoop}"
+export HADOOP_HOME HADOOP_CONF_DIR HADOOP_LOG_DIR HADOOP_PID_DIR
+mkdir -p "${HADOOP_LOG_DIR}" "${HADOOP_PID_DIR}"
+
+USER=$(whoami)
+LOG_FILE="${HADOOP_LOG_DIR}/hadoop-${USER}-datanode-$(hostname).log"
+
+shutdown() {
+ echo "[$(date)] Stopping DataNode..."
+ "${HADOOP_HOME}/bin/hdfs" --daemon stop datanode || true
+ exit 0
+}
+trap shutdown SIGTERM SIGINT
+
+echo "[$(date)] Starting DataNode..."
+"${HADOOP_HOME}/bin/hdfs" datanode 2>&1 | tee -a "$LOG_FILE" &
+DN_PID=$!
+wait $DN_PID
diff --git a/addons/hadoop/scripts/start-journalnode.sh b/addons/hadoop/scripts/start-journalnode.sh
new file mode 100644
index 0000000000..2652a7b41b
--- /dev/null
+++ b/addons/hadoop/scripts/start-journalnode.sh
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+set -o errexit
+set -o errtrace
+set -o nounset
+set -o pipefail
+
+: "${HADOOP_HOME:=/opt/hadoop}"
+: "${HADOOP_CONF_DIR:=${HADOOP_HOME}/etc/hadoop}"
+: "${HADOOP_LOG_DIR:=/var/log/hadoop}"
+: "${HADOOP_PID_DIR:=/tmp/hadoop}"
+export HADOOP_HOME HADOOP_CONF_DIR HADOOP_LOG_DIR HADOOP_PID_DIR
+mkdir -p "${HADOOP_LOG_DIR}" "${HADOOP_PID_DIR}"
+
+USER=$(whoami)
+LOG_FILE="${HADOOP_LOG_DIR}/hadoop-${USER}-journalnode-$(hostname).log"
+
+shutdown() {
+ echo "[$(date)] Stopping JournalNode..."
+ "${HADOOP_HOME}/bin/hdfs" --daemon stop journalnode || true
+ exit 0
+}
+trap shutdown SIGTERM SIGINT
+
+echo "[$(date)] Starting JournalNode..."
+"${HADOOP_HOME}/bin/hdfs" journalnode 2>&1 | tee -a "$LOG_FILE" &
+JN_PID=$!
+wait $JN_PID
diff --git a/addons/hadoop/scripts/start-namenode.sh b/addons/hadoop/scripts/start-namenode.sh
new file mode 100644
index 0000000000..a132d64cc5
--- /dev/null
+++ b/addons/hadoop/scripts/start-namenode.sh
@@ -0,0 +1,159 @@
+#!/usr/bin/env bash
+set -o errexit
+set -o errtrace
+set -o nounset
+set -o pipefail
+
+: "${HADOOP_HOME:=/opt/hadoop}"
+: "${HADOOP_CONF_DIR:=${HADOOP_HOME}/etc/hadoop}"
+: "${HADOOP_LOG_DIR:=/var/log/hadoop}"
+: "${HADOOP_PID_DIR:=/tmp/hadoop}"
+: "${HDFS_HA_NAMENODE_IDS:=nn0,nn1}"
+: "${HDFS_HA_STANDBY_ORDINAL:=1}"
+: "${LIFECYCLE_DIR:=/lifecycle}"
+
+export HADOOP_HOME HADOOP_CONF_DIR HADOOP_LOG_DIR HADOOP_PID_DIR
+mkdir -p "${HADOOP_LOG_DIR}" "${HADOOP_PID_DIR}" "${LIFECYCLE_DIR}"
+
+USER=$(whoami)
+LOG_FILE="${HADOOP_LOG_DIR}/hadoop-${USER}-namenode-$(hostname).log"
+
+# 功能:仅在 standby ordinal 上执行 bootstrapStandby,避免与 OrderedReady 启动顺序冲突。
+# 参数:无,依赖 POD_NAME、HADOOP_HOME、HADOOP_CONF_DIR 等环境变量。
+# 返回值:成功返回 0,失败返回非 0。
+bootstrap_standby_if_needed() {
+ local pod_name host_name ordinal nameservices nn_ids peer_id peer_rpc peer_host
+ local name_dirs nn_dir nn_current_dir
+
+ pod_name="${POD_NAME:-$(hostname)}"
+ host_name="$(hostname)"
+ ordinal="${pod_name##*-}"
+ [[ "$ordinal" == "$pod_name" ]] && ordinal="${host_name##*-}"
+
+ # ponytail: 当前 addon 的 HA 语义固定为双 NameNode,standby ordinal 集中在这里;扩展更多 NN 时再引入 observer/多角色编排。
+ [[ "$ordinal" == "${HDFS_HA_STANDBY_ORDINAL}" ]] || return 0
+
+ nameservices=$("${HADOOP_HOME}/bin/hdfs" getconf -confKey dfs.nameservices 2>/dev/null || echo "")
+ [[ -n "$nameservices" ]] || return 0
+
+ nn_ids=$("${HADOOP_HOME}/bin/hdfs" getconf -confKey "dfs.ha.namenodes.${nameservices}" 2>/dev/null || echo "")
+ [[ "$nn_ids" == *","* ]] || return 0
+
+ name_dirs=$("${HADOOP_HOME}/bin/hdfs" getconf -confKey dfs.namenode.name.dir 2>/dev/null || echo "")
+ [[ -n "$name_dirs" ]] || return 0
+ nn_dir="${name_dirs%%,*}"
+ nn_dir="${nn_dir#file://}"
+ nn_current_dir="${nn_dir}/current"
+
+ if [[ -d "$nn_current_dir" ]] && find "$nn_current_dir" -maxdepth 1 -type f -name 'fsimage_*' ! -name '*.md5' 2>/dev/null | grep -q .; then
+ echo "[$(date)] Valid fsimage found at ${nn_current_dir}, skipping bootstrapStandby"
+ return 0
+ fi
+
+ IFS=',' read -r -a nn_id_array <<< "${HDFS_HA_NAMENODE_IDS}"
+ if [[ "${#nn_id_array[@]}" -lt 2 ]]; then
+ echo "[$(date)] HDFS_HA_NAMENODE_IDS must contain two entries for active/standby HA" >&2
+ return 1
+ fi
+ if [[ "$ordinal" == "0" ]]; then
+ peer_id="${nn_id_array[1]}"
+ else
+ peer_id="${nn_id_array[0]}"
+ fi
+ peer_rpc=$("${HADOOP_HOME}/bin/hdfs" getconf -confKey "dfs.namenode.rpc-address.${nameservices}.${peer_id}" 2>/dev/null || echo "")
+ peer_host="${peer_rpc%:*}"
+ if [[ -z "$peer_host" || "$peer_host" == "$peer_rpc" ]]; then
+ echo "[$(date)] Cannot determine active peer host for ${peer_id}, skipping bootstrapStandby"
+ return 1
+ fi
+
+ for attempt in $(seq 1 30); do
+ if getent hosts "$peer_host" >/dev/null 2>&1; then
+ break
+ fi
+ if [[ "$attempt" -eq 30 ]]; then
+ echo "[$(date)] Peer ${peer_host} is still unresolved after 60s" >&2
+ return 1
+ fi
+ sleep 2
+ done
+
+ echo "[$(date)] No valid fsimage, running bootstrapStandby with retries..."
+ for attempt in $(seq 1 30); do
+ if "${HADOOP_HOME}/bin/hdfs" namenode -bootstrapStandby -nonInteractive; then
+ echo "[$(date)] bootstrapStandby succeeded on attempt ${attempt}"
+ return 0
+ fi
+ echo "[$(date)] bootstrapStandby failed on attempt ${attempt}, retrying in 10s..."
+ sleep 10
+ done
+
+ echo "[$(date)] bootstrapStandby failed after 30 attempts" >&2
+ return 1
+}
+
+shutdown() {
+ echo "[$(date)] Received SIGTERM, stopping NameNode gracefully..."
+ local is_active=0
+ if "${HADOOP_HOME}/bin/hdfs" haadmin -getAllServiceState 2>/dev/null | grep -q "$(hostname -f).*active"; then
+ is_active=1
+ fi
+
+ if [[ $is_active -eq 1 ]]; then
+ local nameservices standby_service=""
+ nameservices=$("${HADOOP_HOME}/bin/hdfs" getconf -confKey dfs.nameservices 2>/dev/null || echo "")
+ if [[ -n "$nameservices" ]]; then
+ local nns
+ nns=$("${HADOOP_HOME}/bin/hdfs" getconf -confKey "dfs.ha.namenodes.${nameservices}" 2>/dev/null || echo "")
+ for nn_id in $(echo "$nns" | tr ',' '\n'); do
+ local state
+ state=$("${HADOOP_HOME}/bin/hdfs" haadmin -getServiceState "$nn_id" 2>/dev/null || echo "")
+ if [[ "$state" == "standby" ]]; then
+ standby_service="$nn_id"
+ break
+ fi
+ done
+
+ local my_service=""
+ for nn_id in $(echo "$nns" | tr ',' '\n'); do
+ local rpc_addr
+ rpc_addr=$("${HADOOP_HOME}/bin/hdfs" getconf -confKey "dfs.namenode.rpc-address.${nameservices}.${nn_id}" 2>/dev/null || echo "")
+ local rpc_host="${rpc_addr%:*}"
+ if [[ "$rpc_host" == "$(hostname -f)" ]] || [[ "$rpc_host" == "$(hostname)" ]]; then
+ my_service="$nn_id"
+ break
+ fi
+ done
+
+ if [[ -n "$my_service" && -n "$standby_service" && "$my_service" != "$standby_service" ]]; then
+ echo "[$(date)] Active NN ${my_service}, failing over to standby ${standby_service}"
+ "${HADOOP_HOME}/bin/hdfs" haadmin -failover "$my_service" "$standby_service" || true
+ else
+ echo "[$(date)] Cannot determine my_service/standby_service (my=${my_service}, standby=${standby_service}), skipping explicit failover"
+ fi
+ fi
+ echo "[$(date)] Waiting 60s for failover to complete..."
+ sleep 60
+ else
+ echo "[$(date)] NameNode is not active, no failover needed"
+ fi
+
+ touch "${LIFECYCLE_DIR}/nn-terminated"
+ echo "[$(date)] Stopping NameNode daemon"
+ "${HADOOP_HOME}/bin/hdfs" --daemon stop namenode || true
+ exit 0
+}
+
+EXCLUDE_PATH=$("${HADOOP_HOME}/bin/hdfs" getconf -confKey dfs.hosts.exclude 2>/dev/null || echo "")
+if [[ -n "$EXCLUDE_PATH" ]]; then
+ touch "$EXCLUDE_PATH" || true
+fi
+
+trap shutdown SIGTERM SIGINT
+
+bootstrap_standby_if_needed
+
+echo "[$(date)] Starting NameNode..."
+"${HADOOP_HOME}/bin/hdfs" namenode 2>&1 | tee -a "$LOG_FILE" &
+NN_PID=$!
+wait $NN_PID
diff --git a/addons/hadoop/scripts/start-zkfc.sh b/addons/hadoop/scripts/start-zkfc.sh
new file mode 100644
index 0000000000..7c576d9fd4
--- /dev/null
+++ b/addons/hadoop/scripts/start-zkfc.sh
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+set -o errexit
+set -o errtrace
+set -o nounset
+set -o pipefail
+
+: "${HADOOP_HOME:=/opt/hadoop}"
+: "${HADOOP_CONF_DIR:=${HADOOP_HOME}/etc/hadoop}"
+: "${HADOOP_LOG_DIR:=/var/log/hadoop}"
+: "${HADOOP_PID_DIR:=/tmp/hadoop}"
+: "${LIFECYCLE_DIR:=/lifecycle}"
+
+export HADOOP_HOME HADOOP_CONF_DIR HADOOP_LOG_DIR HADOOP_PID_DIR
+mkdir -p "${HADOOP_LOG_DIR}" "${HADOOP_PID_DIR}" "${LIFECYCLE_DIR}"
+
+USER=$(whoami)
+LOG_FILE="${HADOOP_LOG_DIR}/hadoop-${USER}-zkfc-$(hostname).log"
+
+shutdown() {
+ echo "[$(date)] Received SIGTERM, waiting for NameNode to terminate..."
+ while true; do
+ if [[ -f "${LIFECYCLE_DIR}/nn-terminated" ]]; then
+ echo "[$(date)] NameNode terminated signal received, stopping ZKFC"
+ sleep 10
+ "${HADOOP_HOME}/bin/hdfs" --daemon stop zkfc || true
+ exit 0
+ fi
+ sleep 2
+ done
+}
+
+trap shutdown SIGTERM SIGINT
+
+echo "[$(date)] Starting ZKFC..."
+"${HADOOP_HOME}/bin/hdfs" zkfc 2>&1 | tee -a "$LOG_FILE" &
+ZKFC_PID=$!
+wait $ZKFC_PID
diff --git a/addons/hadoop/templates/_helpers.tpl b/addons/hadoop/templates/_helpers.tpl
new file mode 100644
index 0000000000..c0f77179d4
--- /dev/null
+++ b/addons/hadoop/templates/_helpers.tpl
@@ -0,0 +1,102 @@
+{{/*
+Chart name
+*/}}
+{{- define "hadoop.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Chart name and version for labels
+*/}}
+{{- define "hadoop.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "hadoop.labels" -}}
+helm.sh/chart: {{ include "hadoop.chart" . }}
+{{ include "hadoop.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "hadoop.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "hadoop.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Common annotations
+*/}}
+{{- define "hadoop.annotations" -}}
+{{ include "kblib.helm.resourcePolicy" . }}
+{{ include "hadoop.apiVersion" . }}
+{{- end }}
+
+{{/*
+API version annotation
+*/}}
+{{- define "hadoop.apiVersion" -}}
+kubeblocks.io/crd-api-version: apps.kubeblocks.io/v1
+{{- end }}
+
+{{/*
+Component definition regex patterns
+*/}}
+{{- define "hadoop.hdfsJournalnodeCmpdRegexPattern" -}}
+^hdfs-journalnode$
+{{- end }}
+
+{{- define "hadoop.hdfsNamenodeCmpdRegexPattern" -}}
+^hdfs-namenode$
+{{- end }}
+
+{{- define "hadoop.hdfsNamenodeStandaloneCmpdRegexPattern" -}}
+^hdfs-namenode-standalone$
+{{- end }}
+
+{{- define "hadoop.hdfsDatanodeCmpdRegexPattern" -}}
+^hdfs-datanode$
+{{- end }}
+
+{{- define "hadoop.hdfsDatanodeStandaloneCmpdRegexPattern" -}}
+^hdfs-datanode-standalone$
+{{- end }}
+
+{{/*
+Image references
+*/}}
+{{- define "hadoop.commonImage" -}}
+{{ .Values.image.common.registry }}/{{ .Values.image.common.repository }}:{{ .Values.image.common.tag }}
+{{- end }}
+
+{{- define "hadoop.journalNodeImage" -}}
+{{ .Values.journalNode.image.registry }}/{{ .Values.journalNode.image.repository }}:{{ .Values.journalNode.image.tag }}
+{{- end }}
+
+{{- define "hadoop.nameNodeImage" -}}
+{{ .Values.nameNode.image.registry }}/{{ .Values.nameNode.image.repository }}:{{ .Values.nameNode.image.tag }}
+{{- end }}
+
+{{- define "hadoop.initNameNodeFormatImage" -}}
+{{ default .Values.nameNode.image.registry .Values.nameNode.initImages.initNameNodeFormat.registry }}/{{ default .Values.nameNode.image.repository .Values.nameNode.initImages.initNameNodeFormat.repository }}:{{ default .Values.nameNode.image.tag .Values.nameNode.initImages.initNameNodeFormat.tag }}
+{{- end }}
+
+{{- define "hadoop.initZkfcFormatImage" -}}
+{{ default .Values.nameNode.image.registry .Values.nameNode.initImages.initZkfcFormat.registry }}/{{ default .Values.nameNode.image.repository .Values.nameNode.initImages.initZkfcFormat.repository }}:{{ default .Values.nameNode.image.tag .Values.nameNode.initImages.initZkfcFormat.tag }}
+{{- end }}
+
+{{- define "hadoop.dataNodeImage" -}}
+{{ .Values.dataNode.image.registry }}/{{ .Values.dataNode.image.repository }}:{{ .Values.dataNode.image.tag }}
+{{- end }}
+
+{{- define "hadoop.jmxExporterImage" -}}
+{{ .Values.image.jmxExporter.registry }}/{{ .Values.image.jmxExporter.repository }}:{{ .Values.image.jmxExporter.tag }}
+{{- end }}
diff --git a/addons/hadoop/templates/clusterdefinition.yaml b/addons/hadoop/templates/clusterdefinition.yaml
new file mode 100644
index 0000000000..ae42eec5d4
--- /dev/null
+++ b/addons/hadoop/templates/clusterdefinition.yaml
@@ -0,0 +1,41 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ClusterDefinition
+metadata:
+ name: hadoop
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.apiVersion" . | nindent 4 }}
+spec:
+ topologies:
+ - name: standalone
+ components:
+ - name: namenode
+ compDef: {{ include "hadoop.hdfsNamenodeStandaloneCmpdRegexPattern" . }}
+ - name: datanode
+ compDef: {{ include "hadoop.hdfsDatanodeStandaloneCmpdRegexPattern" . }}
+ orders:
+ provision:
+ - namenode
+ - datanode
+ terminate:
+ - datanode
+ - namenode
+ - name: cluster
+ default: true
+ components:
+ - name: journalnode
+ compDef: {{ include "hadoop.hdfsJournalnodeCmpdRegexPattern" . }}
+ - name: namenode
+ compDef: {{ include "hadoop.hdfsNamenodeCmpdRegexPattern" . }}
+ - name: datanode
+ compDef: {{ include "hadoop.hdfsDatanodeCmpdRegexPattern" . }}
+ orders:
+ provision:
+ - journalnode
+ - namenode
+ - datanode
+ terminate:
+ - datanode
+ - namenode
+ - journalnode
diff --git a/addons/hadoop/templates/cmpd-hdfs-datanode-standalone.yaml b/addons/hadoop/templates/cmpd-hdfs-datanode-standalone.yaml
new file mode 100644
index 0000000000..0b13ffccb4
--- /dev/null
+++ b/addons/hadoop/templates/cmpd-hdfs-datanode-standalone.yaml
@@ -0,0 +1,233 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentDefinition
+metadata:
+ name: hdfs-datanode-standalone
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.apiVersion" . | nindent 4 }}
+spec:
+ provider: kubeblocks
+ description: {{ .Chart.Description }}
+ serviceKind: hdfs-datanode-standalone
+ exporter:
+ containerName: jmx-exporter
+ scrapePath: /metrics
+ runtime:
+ hostNetwork: {{ .Values.runtime.datanode.hostNetwork }}
+ hostPID: {{ .Values.runtime.datanode.hostPID }}
+ dnsPolicy: {{ .Values.runtime.datanode.dnsPolicy }}
+ terminationGracePeriodSeconds: 120
+ initContainers:
+ - name: hadoop-common
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsUser: {{ .Values.securityContext.initRunAsUser }}
+ command:
+ - /bin/bash
+ args:
+ - -ec
+ - |
+ cp -r {{ .Values.runtime.hadoopSoftwareDir }}/* {{ .Values.runtime.hadoopHome }}
+ mkdir -p {{ .Values.hdfs.paths.datanodeDataDir }}
+ chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} {{ .Values.runtime.hadoopHome }}
+ chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} {{ .Values.hdfs.paths.datanodeDataDir }}
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: hdfs-data-0
+ mountPath: {{ .Values.hdfs.paths.datanodeDataDir }}
+ subPath: data0
+ containers:
+ - name: hdfs-datanode
+ image: {{ include "hadoop.dataNodeImage" . | quote }}
+ imagePullPolicy: {{ .Values.dataNode.image.pullPolicy }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/start-datanode.sh
+ env:
+ - name: DEBUG_MODEL
+ value: {{ .Values.runtime.debug | quote }}
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: POD_FQDN
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.annotations['kubeblocks.io/pod-fqdn']
+ - name: HADOOP_HOME
+ value: {{ .Values.runtime.hadoopHome }}
+ - name: HADOOP_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ - name: HADOOP_LOG_DIR
+ value: {{ .Values.runtime.hadoopLogDir }}
+ ports:
+ - containerPort: {{ .Values.hdfs.ports.datanode.data }}
+ name: data
+ - containerPort: {{ .Values.hdfs.ports.datanode.ipc }}
+ name: ipc
+ - containerPort: {{ .Values.hdfs.ports.datanode.http }}
+ name: http
+ startupProbe:
+ failureThreshold: 30
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-data-status.sh
+ livenessProbe:
+ failureThreshold: {{ .Values.probes.datanode.liveness.failureThreshold }}
+ initialDelaySeconds: {{ .Values.probes.datanode.liveness.initialDelaySeconds }}
+ periodSeconds: {{ .Values.probes.datanode.liveness.periodSeconds }}
+ successThreshold: 1
+ timeoutSeconds: {{ .Values.probes.datanode.liveness.timeoutSeconds }}
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-data-status.sh
+ readinessProbe:
+ failureThreshold: {{ .Values.probes.datanode.readiness.failureThreshold }}
+ initialDelaySeconds: {{ .Values.probes.datanode.readiness.initialDelaySeconds }}
+ periodSeconds: {{ .Values.probes.datanode.readiness.periodSeconds }}
+ successThreshold: 1
+ timeoutSeconds: {{ .Values.probes.datanode.readiness.timeoutSeconds }}
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-data-status.sh
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/hadoop-env.sh
+ subPath: hadoop-env.sh
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.include
+ subPath: dfs.include
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.exclude
+ subPath: dfs.exclude
+ - name: datanode-config
+ mountPath: {{ .Values.runtime.configDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: datanode-config
+ mountPath: {{ .Values.runtime.configDir }}/log4j.properties
+ subPath: log4j.properties
+ - name: hdfs-data-0
+ mountPath: {{ .Values.hdfs.paths.datanodeDataDir }}
+ subPath: data0
+ - name: hadoop-logs
+ mountPath: {{ .Values.runtime.hadoopLogDir }}
+ - name: scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ runAsNonRoot: {{ .Values.securityContext.runAsNonRoot }}
+ privileged: {{ .Values.securityContext.privileged }}
+ allowPrivilegeEscalation: {{ .Values.securityContext.allowPrivilegeEscalation }}
+ capabilities:
+{{ toYaml .Values.securityContext.capabilities | nindent 12 }}
+ seccompProfile:
+{{ toYaml .Values.securityContext.seccompProfile | nindent 12 }}
+ - name: jmx-exporter
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsNonRoot: {{ .Values.exporter.securityContext.runAsNonRoot }}
+ runAsUser: {{ .Values.exporter.securityContext.runAsUser }}
+ command:
+ - java
+ args:
+ - -XX:MaxRAMPercentage=100
+ - -XshowSettings:vm
+ - -jar
+ - jmx_prometheus_httpserver.jar
+ - {{ .Values.jmxExporter.port | quote }}
+ - /etc/jmx-exporter/hdfs-jmx-exporter.yaml
+ ports:
+ - name: http-metrics
+ containerPort: {{ .Values.jmxExporter.port }}
+ volumeMounts:
+ - name: hdfs-common-config
+ mountPath: /etc/jmx-exporter/hdfs-jmx-exporter.yaml
+ subPath: hdfs-jmx-exporter.yaml
+ securityContext:
+ fsGroupChangePolicy: {{ .Values.securityContext.fsGroupChangePolicy }}
+ fsGroup: {{ .Values.securityContext.fsGroup }}
+ volumes:
+ - name: hadoop-common
+ emptyDir: {}
+ - name: hadoop-logs
+ emptyDir: {}
+ updateStrategy: {{ .Values.updateStrategy }}
+ vars:
+ - name: CLUSTER_NAME
+ valueFrom:
+ clusterVarRef:
+ clusterName: Required
+ - name: NAMESPACE
+ valueFrom:
+ clusterVarRef:
+ namespace: Required
+ - name: CLUSTER_DOMAIN
+ value: {{ .Values.extra.clusterDomain }}
+ - name: HDFS_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ - name: HDFS_JMX_PORT
+ value: {{ .Values.hdfs.ports.datanode.jmx | quote }}
+ - name: HDFS_NAMENODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.namenode.jmx | quote }}
+ - name: HDFS_DATANODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.datanode.jmx | quote }}
+ - name: HDFS_JOURNALNODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.journalnode.jmx | quote }}
+ - name: HDFS_ZKFC_JMX_PORT
+ value: {{ .Values.hdfs.ports.zkfc.jmx | quote }}
+ - name: HDFS_DATANODE_DATA_DIR
+ value: {{ .Values.hdfs.paths.datanodeDataDir | quote }}
+ - name: HDFS_DATANODE_HANDLER_COUNT
+ value: {{ .Values.hdfs.datanode.handlerCount | quote }}
+ - name: HDFS_DATANODE_DATA_PORT
+ value: {{ .Values.hdfs.ports.datanode.data | quote }}
+ - name: HDFS_DATANODE_HTTP_PORT
+ value: {{ .Values.hdfs.ports.datanode.http | quote }}
+ - name: HDFS_DATANODE_IPC_PORT
+ value: {{ .Values.hdfs.ports.datanode.ipc | quote }}
+ - name: HDFS_NAMENODE_RPC_PORT
+ value: {{ .Values.hdfs.ports.namenode.rpc | quote }}
+ - name: HDFS_NAMENODE_HTTP_PORT
+ value: {{ .Values.hdfs.ports.namenode.http | quote }}
+ - name: HDFS_REPLICATION
+ value: "1"
+ - name: HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY
+ value: "NEVER"
+ - name: HDFS_PERMISSIONS_ENABLED
+ value: {{ .Values.hdfs.permissions.enabled | quote }}
+ - name: POD_FQDN
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.annotations['kubeblocks.io/pod-fqdn']
+ apiVersion: v1
+ configs:
+ - name: hdfs-common-config
+ template: hdfs-common-standalone-config-template
+ volumeName: hdfs-common-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.config.defaultMode }}
+ - name: datanode-config
+ template: datanode-standalone-config-template
+ volumeName: datanode-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.config.defaultMode }}
+ scripts:
+ - name: hadoop-scripts
+ template: hadoop-scripts
+ volumeName: scripts
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.scripts.defaultMode }}
diff --git a/addons/hadoop/templates/cmpd-hdfs-datanode.yaml b/addons/hadoop/templates/cmpd-hdfs-datanode.yaml
new file mode 100644
index 0000000000..8c3c472dd3
--- /dev/null
+++ b/addons/hadoop/templates/cmpd-hdfs-datanode.yaml
@@ -0,0 +1,245 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentDefinition
+metadata:
+ name: hdfs-datanode
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.apiVersion" . | nindent 4 }}
+spec:
+ provider: kubeblocks
+ description: {{ .Chart.Description }}
+ serviceKind: hdfs-datanode
+ exporter:
+ containerName: jmx-exporter
+ scrapePath: /metrics
+ runtime:
+ hostNetwork: {{ .Values.runtime.datanode.hostNetwork }}
+ hostPID: {{ .Values.runtime.datanode.hostPID }}
+ dnsPolicy: {{ .Values.runtime.datanode.dnsPolicy }}
+ terminationGracePeriodSeconds: 300
+ initContainers:
+ - name: hadoop-common
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsUser: {{ .Values.securityContext.initRunAsUser }}
+ command:
+ - /bin/bash
+ args:
+ - -ec
+ - |
+ cp -r {{ .Values.runtime.hadoopSoftwareDir }}/* {{ .Values.runtime.hadoopHome }}
+ mkdir -p {{ .Values.hdfs.paths.datanodeDataDir }}
+ chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} {{ .Values.runtime.hadoopHome }}
+ chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} {{ .Values.hdfs.paths.datanodeDataDir }}
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: hdfs-data-0
+ mountPath: {{ .Values.hdfs.paths.datanodeDataDir }}
+ subPath: data0
+ containers:
+ - name: hdfs-datanode
+ image: {{ include "hadoop.dataNodeImage" . | quote }}
+ imagePullPolicy: {{ .Values.dataNode.image.pullPolicy }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/start-datanode.sh
+ env:
+ - name: DEBUG_MODEL
+ value: {{ .Values.runtime.debug | quote }}
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: POD_FQDN
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.annotations['kubeblocks.io/pod-fqdn']
+ - name: HADOOP_HOME
+ value: {{ .Values.runtime.hadoopHome }}
+ - name: HADOOP_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ - name: HADOOP_LOG_DIR
+ value: {{ .Values.runtime.hadoopLogDir }}
+ ports:
+ - containerPort: {{ .Values.hdfs.ports.datanode.data }}
+ name: data
+ - containerPort: {{ .Values.hdfs.ports.datanode.ipc }}
+ name: ipc
+ - containerPort: {{ .Values.hdfs.ports.datanode.http }}
+ name: http
+ startupProbe:
+ failureThreshold: 30
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-data-status.sh
+ livenessProbe:
+ failureThreshold: {{ .Values.probes.datanode.liveness.failureThreshold }}
+ initialDelaySeconds: {{ .Values.probes.datanode.liveness.initialDelaySeconds }}
+ periodSeconds: {{ .Values.probes.datanode.liveness.periodSeconds }}
+ successThreshold: 1
+ timeoutSeconds: {{ .Values.probes.datanode.liveness.timeoutSeconds }}
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-data-status.sh
+ readinessProbe:
+ failureThreshold: {{ .Values.probes.datanode.readiness.failureThreshold }}
+ initialDelaySeconds: {{ .Values.probes.datanode.readiness.initialDelaySeconds }}
+ periodSeconds: {{ .Values.probes.datanode.readiness.periodSeconds }}
+ successThreshold: 1
+ timeoutSeconds: {{ .Values.probes.datanode.readiness.timeoutSeconds }}
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-data-status.sh
+ lifecycle:
+ preStop:
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/datanode-decommission.sh
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/hadoop-env.sh
+ subPath: hadoop-env.sh
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.include
+ subPath: dfs.include
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.exclude
+ subPath: dfs.exclude
+ - name: datanode-config
+ mountPath: {{ .Values.runtime.configDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: datanode-config
+ mountPath: {{ .Values.runtime.configDir }}/log4j.properties
+ subPath: log4j.properties
+ - name: hdfs-data-0
+ mountPath: {{ .Values.hdfs.paths.datanodeDataDir }}
+ subPath: data0
+ - name: hadoop-logs
+ mountPath: {{ .Values.runtime.hadoopLogDir }}
+ - name: scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ runAsNonRoot: {{ .Values.securityContext.runAsNonRoot }}
+ privileged: {{ .Values.securityContext.privileged }}
+ allowPrivilegeEscalation: {{ .Values.securityContext.allowPrivilegeEscalation }}
+ capabilities:
+{{ toYaml .Values.securityContext.capabilities | nindent 12 }}
+ seccompProfile:
+{{ toYaml .Values.securityContext.seccompProfile | nindent 12 }}
+ - name: jmx-exporter
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsNonRoot: {{ .Values.exporter.securityContext.runAsNonRoot }}
+ runAsUser: {{ .Values.exporter.securityContext.runAsUser }}
+ command:
+ - java
+ args:
+ - -XX:MaxRAMPercentage=100
+ - -XshowSettings:vm
+ - -jar
+ - jmx_prometheus_httpserver.jar
+ - {{ .Values.jmxExporter.port | quote }}
+ - /etc/jmx-exporter/hdfs-jmx-exporter.yaml
+ ports:
+ - name: http-metrics
+ containerPort: {{ .Values.jmxExporter.port }}
+ volumeMounts:
+ - name: hdfs-common-config
+ mountPath: /etc/jmx-exporter/hdfs-jmx-exporter.yaml
+ subPath: hdfs-jmx-exporter.yaml
+ securityContext:
+ fsGroupChangePolicy: {{ .Values.securityContext.fsGroupChangePolicy }}
+ fsGroup: {{ .Values.securityContext.fsGroup }}
+ volumes:
+ - name: hadoop-common
+ emptyDir: {}
+ - name: hadoop-logs
+ emptyDir: {}
+ updateStrategy: {{ .Values.updateStrategy }}
+ vars:
+ - name: CLUSTER_NAME
+ valueFrom:
+ clusterVarRef:
+ clusterName: Required
+ - name: NAMESPACE
+ valueFrom:
+ clusterVarRef:
+ namespace: Required
+ - name: CLUSTER_DOMAIN
+ value: {{ .Values.extra.clusterDomain }}
+ - name: HDFS_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ - name: HDFS_JMX_PORT
+ value: {{ .Values.hdfs.ports.datanode.jmx | quote }}
+ - name: HDFS_NAMENODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.namenode.jmx | quote }}
+ - name: HDFS_DATANODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.datanode.jmx | quote }}
+ - name: HDFS_JOURNALNODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.journalnode.jmx | quote }}
+ - name: HDFS_ZKFC_JMX_PORT
+ value: {{ .Values.hdfs.ports.zkfc.jmx | quote }}
+ - name: NAMENODE_POD_FQDN_LIST
+ valueFrom:
+ componentVarRef:
+ compDef: hdfs-namenode
+ optional: false
+ podFQDNs: Required
+ - name: HDFS_DATANODE_DATA_DIR
+ value: {{ .Values.hdfs.paths.datanodeDataDir | quote }}
+ - name: HDFS_DATANODE_HANDLER_COUNT
+ value: {{ .Values.hdfs.datanode.handlerCount | quote }}
+ - name: HDFS_DATANODE_DATA_PORT
+ value: {{ .Values.hdfs.ports.datanode.data | quote }}
+ - name: HDFS_DATANODE_HTTP_PORT
+ value: {{ .Values.hdfs.ports.datanode.http | quote }}
+ - name: HDFS_DATANODE_IPC_PORT
+ value: {{ .Values.hdfs.ports.datanode.ipc | quote }}
+ - name: HDFS_NAMENODE_RPC_PORT
+ value: {{ .Values.hdfs.ports.namenode.rpc | quote }}
+ - name: HDFS_NAMENODE_HTTP_PORT
+ value: {{ .Values.hdfs.ports.namenode.http | quote }}
+ - name: HDFS_REPLICATION
+ value: {{ .Values.hdfs.replication | quote }}
+ - name: HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY
+ value: {{ .Values.hdfs.client.replaceDatanodeOnFailurePolicy | quote }}
+ - name: HDFS_PERMISSIONS_ENABLED
+ value: {{ .Values.hdfs.permissions.enabled | quote }}
+ - name: POD_FQDN
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.annotations['kubeblocks.io/pod-fqdn']
+ apiVersion: v1
+ configs:
+ - name: hdfs-common-config
+ template: hdfs-common-config-template
+ volumeName: hdfs-common-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.config.defaultMode }}
+ - name: datanode-config
+ template: datanode-config-template
+ volumeName: datanode-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.config.defaultMode }}
+ scripts:
+ - name: hadoop-scripts
+ template: hadoop-scripts
+ volumeName: scripts
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.scripts.defaultMode }}
diff --git a/addons/hadoop/templates/cmpd-hdfs-journalnode.yaml b/addons/hadoop/templates/cmpd-hdfs-journalnode.yaml
new file mode 100644
index 0000000000..8895fe3c52
--- /dev/null
+++ b/addons/hadoop/templates/cmpd-hdfs-journalnode.yaml
@@ -0,0 +1,216 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentDefinition
+metadata:
+ name: hdfs-journalnode
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.apiVersion" . | nindent 4 }}
+spec:
+ provider: kubeblocks
+ description: {{ .Chart.Description }}
+ serviceKind: hdfs-journalnode
+ exporter:
+ containerName: jmx-exporter
+ scrapePath: /metrics
+ services:
+ - name: default
+ spec:
+ ports:
+ - name: jn
+ port: {{ .Values.hdfs.ports.journalnode.rpc }}
+ - name: http
+ port: {{ .Values.hdfs.ports.journalnode.http }}
+ runtime:
+ terminationGracePeriodSeconds: 60
+ initContainers:
+ - name: hadoop-common
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsUser: {{ .Values.securityContext.initRunAsUser }}
+ command:
+ - /bin/bash
+ args:
+ - -ec
+ - |
+ cp -r {{ .Values.runtime.hadoopSoftwareDir }}/* {{ .Values.runtime.hadoopHome }}
+ mkdir -p {{ .Values.hdfs.paths.journalnodeEditsDir }}
+ chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} {{ .Values.hdfs.paths.journalnodeEditsDir }}
+ chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} {{ .Values.runtime.hadoopHome }}
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: edits-dir
+ mountPath: {{ .Values.hdfs.paths.journalnodeEditsDir }}
+ subPath: journal
+ containers:
+ - name: hdfs-journalnode
+ image: {{ include "hadoop.journalNodeImage" . | quote }}
+ imagePullPolicy: {{ .Values.journalNode.image.pullPolicy }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/start-journalnode.sh
+ env:
+ - name: DEBUG_MODEL
+ value: {{ .Values.runtime.debug | quote }}
+ - name: HADOOP_HOME
+ value: {{ .Values.runtime.hadoopHome }}
+ - name: HADOOP_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ - name: HADOOP_LOG_DIR
+ value: {{ .Values.runtime.hadoopLogDir }}
+ ports:
+ - containerPort: {{ .Values.hdfs.ports.journalnode.rpc }}
+ name: jn
+ - containerPort: {{ .Values.hdfs.ports.journalnode.http }}
+ name: http
+ startupProbe:
+ failureThreshold: 30
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-journal-status.sh
+ livenessProbe:
+ failureThreshold: {{ .Values.probes.journalnode.liveness.failureThreshold }}
+ initialDelaySeconds: {{ .Values.probes.journalnode.liveness.initialDelaySeconds }}
+ periodSeconds: {{ .Values.probes.journalnode.liveness.periodSeconds }}
+ successThreshold: 1
+ timeoutSeconds: {{ .Values.probes.journalnode.liveness.timeoutSeconds }}
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-journal-status.sh
+ readinessProbe:
+ failureThreshold: {{ .Values.probes.journalnode.readiness.failureThreshold }}
+ initialDelaySeconds: {{ .Values.probes.journalnode.readiness.initialDelaySeconds }}
+ periodSeconds: {{ .Values.probes.journalnode.readiness.periodSeconds }}
+ successThreshold: 1
+ timeoutSeconds: {{ .Values.probes.journalnode.readiness.timeoutSeconds }}
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-journal-status.sh
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: edits-dir
+ mountPath: {{ .Values.hdfs.paths.journalnodeEditsDir }}
+ subPath: journal
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/hadoop-env.sh
+ subPath: hadoop-env.sh
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.include
+ subPath: dfs.include
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.exclude
+ subPath: dfs.exclude
+ - name: journalnode-config
+ mountPath: {{ .Values.runtime.configDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: journalnode-config
+ mountPath: {{ .Values.runtime.configDir }}/log4j.properties
+ subPath: log4j.properties
+ - name: hadoop-logs
+ mountPath: {{ .Values.runtime.hadoopLogDir }}
+ - name: scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ runAsNonRoot: {{ .Values.securityContext.runAsNonRoot }}
+ privileged: {{ .Values.securityContext.privileged }}
+ allowPrivilegeEscalation: {{ .Values.securityContext.allowPrivilegeEscalation }}
+ capabilities:
+{{ toYaml .Values.securityContext.capabilities | nindent 12 }}
+ seccompProfile:
+{{ toYaml .Values.securityContext.seccompProfile | nindent 12 }}
+ - name: jmx-exporter
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsNonRoot: {{ .Values.exporter.securityContext.runAsNonRoot }}
+ runAsUser: {{ .Values.exporter.securityContext.runAsUser }}
+ command:
+ - java
+ args:
+ - -XX:MaxRAMPercentage=100
+ - -XshowSettings:vm
+ - -jar
+ - jmx_prometheus_httpserver.jar
+ - {{ .Values.jmxExporter.port | quote }}
+ - /etc/jmx-exporter/hdfs-jmx-exporter.yaml
+ ports:
+ - name: http-metrics
+ containerPort: {{ .Values.jmxExporter.port }}
+ volumeMounts:
+ - name: hdfs-common-config
+ mountPath: /etc/jmx-exporter/hdfs-jmx-exporter.yaml
+ subPath: hdfs-jmx-exporter.yaml
+ securityContext:
+ fsGroupChangePolicy: {{ .Values.securityContext.fsGroupChangePolicy }}
+ fsGroup: {{ .Values.securityContext.fsGroup }}
+ volumes:
+ - name: hadoop-common
+ emptyDir: {}
+ - name: hadoop-logs
+ emptyDir: {}
+ updateStrategy: {{ .Values.updateStrategy }}
+ vars:
+ - name: CLUSTER_NAME
+ valueFrom:
+ clusterVarRef:
+ clusterName: Required
+ - name: NAMESPACE
+ valueFrom:
+ clusterVarRef:
+ namespace: Required
+ - name: JOURNALNODE_POD_FQDN_LIST
+ valueFrom:
+ componentVarRef:
+ optional: false
+ podFQDNs: Required
+ - name: HDFS_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ - name: HDFS_JMX_PORT
+ value: {{ .Values.hdfs.ports.journalnode.jmx | quote }}
+ - name: HDFS_NAMENODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.namenode.jmx | quote }}
+ - name: HDFS_DATANODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.datanode.jmx | quote }}
+ - name: HDFS_JOURNALNODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.journalnode.jmx | quote }}
+ - name: HDFS_ZKFC_JMX_PORT
+ value: {{ .Values.hdfs.ports.zkfc.jmx | quote }}
+ - name: HDFS_JOURNALNODE_EDITS_DIR
+ value: {{ .Values.hdfs.paths.journalnodeEditsDir | quote }}
+ - name: HDFS_JOURNALNODE_RPC_PORT
+ value: {{ .Values.hdfs.ports.journalnode.rpc | quote }}
+ - name: HDFS_JOURNALNODE_HTTP_PORT
+ value: {{ .Values.hdfs.ports.journalnode.http | quote }}
+ - name: HDFS_PERMISSIONS_ENABLED
+ value: {{ .Values.hdfs.permissions.enabled | quote }}
+ - name: HDFS_REPLICATION
+ value: {{ .Values.hdfs.replication | quote }}
+ configs:
+ - name: hdfs-common-config
+ template: hdfs-common-config-template
+ volumeName: hdfs-common-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.config.defaultMode }}
+ - name: journalnode-config
+ template: journalnode-config-template
+ volumeName: journalnode-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.config.defaultMode }}
+ scripts:
+ - name: hadoop-scripts
+ template: hadoop-scripts
+ volumeName: scripts
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.scripts.defaultMode }}
diff --git a/addons/hadoop/templates/cmpd-hdfs-namenode-standalone.yaml b/addons/hadoop/templates/cmpd-hdfs-namenode-standalone.yaml
new file mode 100644
index 0000000000..cad435ff48
--- /dev/null
+++ b/addons/hadoop/templates/cmpd-hdfs-namenode-standalone.yaml
@@ -0,0 +1,274 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentDefinition
+metadata:
+ name: hdfs-namenode-standalone
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.apiVersion" . | nindent 4 }}
+spec:
+ provider: kubeblocks
+ description: {{ .Chart.Description }}
+ serviceKind: hdfs-namenode-standalone
+ exporter:
+ containerName: jmx-exporter
+ scrapePath: /metrics
+ services:
+ - name: default
+ spec:
+ ports:
+ - name: fs
+ port: {{ .Values.hdfs.ports.namenode.rpc }}
+ - name: http
+ port: {{ .Values.hdfs.ports.namenode.http }}
+ runtime:
+ terminationGracePeriodSeconds: 120
+ initContainers:
+ - name: hadoop-common
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsUser: {{ .Values.securityContext.initRunAsUser }}
+ command:
+ - /bin/bash
+ args:
+ - -ec
+ - |
+ cp -r {{ .Values.runtime.hadoopSoftwareDir }}/* {{ .Values.runtime.hadoopHome }}
+ mkdir -p {{ .Values.hdfs.paths.namenodeMetadataDir }}
+ chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} /hadoop
+ chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} {{ .Values.runtime.hadoopHome }}
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: metadata-dir
+ mountPath: /hadoop
+ - name: init-namenode-format
+ image: {{ include "hadoop.initNameNodeFormatImage" . | quote }}
+ imagePullPolicy: {{ default .Values.nameNode.image.pullPolicy .Values.nameNode.initImages.initNameNodeFormat.pullPolicy }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: HADOOP_HOME
+ value: {{ .Values.runtime.hadoopHome }}
+ - name: HADOOP_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/init-namenode-format.sh
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: metadata-dir
+ mountPath: /hadoop
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/hadoop-env.sh
+ subPath: hadoop-env.sh
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.include
+ subPath: dfs.include
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.exclude
+ subPath: dfs.exclude
+ - name: namenode-config
+ mountPath: {{ .Values.runtime.configDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: hadoop-logs
+ mountPath: {{ .Values.runtime.hadoopLogDir }}
+ - name: scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ containers:
+ - name: hdfs-namenode
+ image: {{ include "hadoop.nameNodeImage" . | quote }}
+ imagePullPolicy: {{ .Values.nameNode.image.pullPolicy }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/start-namenode.sh
+ env:
+ - name: DEBUG_MODEL
+ value: {{ .Values.runtime.debug | quote }}
+ - name: CURRENT_POD
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: HADOOP_HOME
+ value: {{ .Values.runtime.hadoopHome }}
+ - name: HADOOP_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ - name: HADOOP_LOG_DIR
+ value: {{ .Values.runtime.hadoopLogDir }}
+ ports:
+ - containerPort: {{ .Values.hdfs.ports.namenode.rpc }}
+ name: fs
+ - containerPort: {{ .Values.hdfs.ports.namenode.http }}
+ name: http
+ startupProbe:
+ failureThreshold: 60
+ initialDelaySeconds: 30
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-name-status.sh
+ livenessProbe:
+ failureThreshold: {{ .Values.probes.namenode.liveness.failureThreshold }}
+ initialDelaySeconds: {{ .Values.probes.namenode.liveness.initialDelaySeconds }}
+ periodSeconds: {{ .Values.probes.namenode.liveness.periodSeconds }}
+ successThreshold: 1
+ timeoutSeconds: {{ .Values.probes.namenode.liveness.timeoutSeconds }}
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-name-status.sh
+ readinessProbe:
+ failureThreshold: {{ .Values.probes.namenode.readiness.failureThreshold }}
+ initialDelaySeconds: {{ .Values.probes.namenode.readiness.initialDelaySeconds }}
+ periodSeconds: {{ .Values.probes.namenode.readiness.periodSeconds }}
+ successThreshold: 1
+ timeoutSeconds: {{ .Values.probes.namenode.readiness.timeoutSeconds }}
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-name-status.sh
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: metadata-dir
+ mountPath: /hadoop
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/hadoop-env.sh
+ subPath: hadoop-env.sh
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.include
+ subPath: dfs.include
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.exclude
+ subPath: dfs.exclude
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/log4j.properties
+ subPath: log4j.properties
+ - name: namenode-config
+ mountPath: {{ .Values.runtime.configDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: hadoop-logs
+ mountPath: {{ .Values.runtime.hadoopLogDir }}
+ - name: scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ runAsNonRoot: {{ .Values.securityContext.runAsNonRoot }}
+ privileged: {{ .Values.securityContext.privileged }}
+ allowPrivilegeEscalation: {{ .Values.securityContext.allowPrivilegeEscalation }}
+ capabilities:
+{{ toYaml .Values.securityContext.capabilities | nindent 12 }}
+ seccompProfile:
+{{ toYaml .Values.securityContext.seccompProfile | nindent 12 }}
+ - name: jmx-exporter
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsNonRoot: {{ .Values.exporter.securityContext.runAsNonRoot }}
+ runAsUser: {{ .Values.exporter.securityContext.runAsUser }}
+ command:
+ - java
+ args:
+ - -XX:MaxRAMPercentage=100
+ - -XshowSettings:vm
+ - -jar
+ - jmx_prometheus_httpserver.jar
+ - {{ .Values.jmxExporter.port | quote }}
+ - /etc/jmx-exporter/hdfs-jmx-exporter.yaml
+ ports:
+ - name: http-metrics
+ containerPort: {{ .Values.jmxExporter.port }}
+ volumeMounts:
+ - name: hdfs-common-config
+ mountPath: /etc/jmx-exporter/hdfs-jmx-exporter.yaml
+ subPath: hdfs-jmx-exporter.yaml
+ securityContext:
+ fsGroupChangePolicy: {{ .Values.securityContext.fsGroupChangePolicy }}
+ fsGroup: {{ .Values.securityContext.fsGroup }}
+ volumes:
+ - name: hadoop-common
+ emptyDir: {}
+ - name: hadoop-logs
+ emptyDir: {}
+ updateStrategy: {{ .Values.updateStrategy }}
+ vars:
+ - name: CLUSTER_NAME
+ valueFrom:
+ clusterVarRef:
+ clusterName: Required
+ - name: CLUSTER_UID
+ valueFrom:
+ clusterVarRef:
+ clusterUID: Required
+ - name: NAMESPACE
+ valueFrom:
+ clusterVarRef:
+ namespace: Required
+ - name: CLUSTER_DOMAIN
+ value: {{ .Values.extra.clusterDomain }}
+ - name: HDFS_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ - name: HDFS_JMX_PORT
+ value: {{ .Values.hdfs.ports.namenode.jmx | quote }}
+ - name: HDFS_NAMENODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.namenode.jmx | quote }}
+ - name: HDFS_DATANODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.datanode.jmx | quote }}
+ - name: HDFS_JOURNALNODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.journalnode.jmx | quote }}
+ - name: HDFS_ZKFC_JMX_PORT
+ value: {{ .Values.hdfs.ports.zkfc.jmx | quote }}
+ - name: HDFS_NAMENODE_NAME_DIR
+ value: {{ .Values.hdfs.paths.namenodeMetadataDir | quote }}
+ - name: HDFS_NAMENODE_RPC_PORT
+ value: {{ .Values.hdfs.ports.namenode.rpc | quote }}
+ - name: HDFS_NAMENODE_HTTP_PORT
+ value: {{ .Values.hdfs.ports.namenode.http | quote }}
+ - name: HDFS_PERMISSIONS_ENABLED
+ value: {{ .Values.hdfs.permissions.enabled | quote }}
+ - name: HDFS_REGISTRATION_IP_HOSTNAME_CHECK
+ value: {{ .Values.hdfs.registration.ipHostnameCheck | quote }}
+ - name: HDFS_REPLICATION
+ value: "1"
+ - name: HDFS_REPLICATION_MAX
+ value: "1"
+ - name: HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY
+ value: "NEVER"
+ - name: HDFS_NAMENODE_HANDLER_COUNT
+ value: {{ .Values.hdfs.namenode.handlerCount | quote }}
+ configs:
+ - name: hdfs-common-config
+ template: hdfs-common-standalone-config-template
+ volumeName: hdfs-common-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.config.defaultMode }}
+ - name: namenode-config
+ template: namenode-standalone-config-template
+ volumeName: namenode-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.config.defaultMode }}
+ scripts:
+ - name: hadoop-scripts
+ template: hadoop-scripts
+ volumeName: scripts
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.scripts.defaultMode }}
diff --git a/addons/hadoop/templates/cmpd-hdfs-namenode.yaml b/addons/hadoop/templates/cmpd-hdfs-namenode.yaml
new file mode 100644
index 0000000000..94193d5867
--- /dev/null
+++ b/addons/hadoop/templates/cmpd-hdfs-namenode.yaml
@@ -0,0 +1,421 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentDefinition
+metadata:
+ name: hdfs-namenode
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.apiVersion" . | nindent 4 }}
+spec:
+ provider: kubeblocks
+ description: {{ .Chart.Description }}
+ serviceKind: hdfs-namenode
+ exporter:
+ containerName: jmx-exporter
+ scrapePath: /metrics
+ services:
+ - name: default
+ spec:
+ ports:
+ - name: fs
+ port: {{ .Values.hdfs.ports.namenode.rpc }}
+ - name: http
+ port: {{ .Values.hdfs.ports.namenode.http }}
+ serviceRefDeclarations:
+ - name: hadoopZookeeper
+ serviceRefDeclarationSpecs:
+ - serviceKind: zookeeper
+ serviceVersion: "^*"
+ runtime:
+ terminationGracePeriodSeconds: 300
+ initContainers:
+ - name: hadoop-common
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsUser: {{ .Values.securityContext.initRunAsUser }}
+ command:
+ - /bin/bash
+ args:
+ - -ec
+ - |
+ cp -r {{ .Values.runtime.hadoopSoftwareDir }}/* {{ .Values.runtime.hadoopHome }}
+ mkdir -p {{ .Values.hdfs.paths.namenodeMetadataDir }}
+ mkdir -p {{ .Values.hdfs.paths.namenodeJournalDir }}
+ chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} /hadoop
+ chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} {{ .Values.runtime.hadoopHome }}
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: metadata-dir
+ mountPath: /hadoop
+ - name: init-namenode-format
+ image: {{ include "hadoop.initNameNodeFormatImage" . | quote }}
+ imagePullPolicy: {{ default .Values.nameNode.image.pullPolicy .Values.nameNode.initImages.initNameNodeFormat.pullPolicy }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: HADOOP_HOME
+ value: {{ .Values.runtime.hadoopHome }}
+ - name: HADOOP_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/init-namenode-format.sh
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: metadata-dir
+ mountPath: /hadoop
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/hadoop-env.sh
+ subPath: hadoop-env.sh
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.include
+ subPath: dfs.include
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.exclude
+ subPath: dfs.exclude
+ - name: namenode-config
+ mountPath: {{ .Values.runtime.configDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: hadoop-logs
+ mountPath: {{ .Values.runtime.hadoopLogDir }}
+ - name: scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ - name: init-zkfc-format
+ image: {{ include "hadoop.initZkfcFormatImage" . | quote }}
+ imagePullPolicy: {{ default .Values.nameNode.image.pullPolicy .Values.nameNode.initImages.initZkfcFormat.pullPolicy }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ env:
+ - name: HADOOP_HOME
+ value: {{ .Values.runtime.hadoopHome }}
+ - name: HADOOP_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/init-zkfc-format.sh
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/hadoop-env.sh
+ subPath: hadoop-env.sh
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.include
+ subPath: dfs.include
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.exclude
+ subPath: dfs.exclude
+ - name: namenode-config
+ mountPath: {{ .Values.runtime.configDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: hadoop-logs
+ mountPath: {{ .Values.runtime.hadoopLogDir }}
+ - name: scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ containers:
+ - name: hdfs-namenode
+ image: {{ include "hadoop.nameNodeImage" . | quote }}
+ imagePullPolicy: {{ .Values.nameNode.image.pullPolicy }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/start-namenode.sh
+ env:
+ - name: DEBUG_MODEL
+ value: {{ .Values.runtime.debug | quote }}
+ - name: CURRENT_POD
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: HADOOP_HOME
+ value: {{ .Values.runtime.hadoopHome }}
+ - name: HADOOP_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ - name: HADOOP_LOG_DIR
+ value: {{ .Values.runtime.hadoopLogDir }}
+ ports:
+ - containerPort: {{ .Values.hdfs.ports.namenode.rpc }}
+ name: fs
+ - containerPort: {{ .Values.hdfs.ports.namenode.http }}
+ name: http
+ startupProbe:
+ failureThreshold: 60
+ initialDelaySeconds: 30
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-name-status.sh
+ livenessProbe:
+ failureThreshold: {{ .Values.probes.namenode.liveness.failureThreshold }}
+ initialDelaySeconds: {{ .Values.probes.namenode.liveness.initialDelaySeconds }}
+ periodSeconds: {{ .Values.probes.namenode.liveness.periodSeconds }}
+ successThreshold: 1
+ timeoutSeconds: {{ .Values.probes.namenode.liveness.timeoutSeconds }}
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-name-status.sh
+ readinessProbe:
+ failureThreshold: {{ .Values.probes.namenode.readiness.failureThreshold }}
+ initialDelaySeconds: {{ .Values.probes.namenode.readiness.initialDelaySeconds }}
+ periodSeconds: {{ .Values.probes.namenode.readiness.periodSeconds }}
+ successThreshold: 1
+ timeoutSeconds: {{ .Values.probes.namenode.readiness.timeoutSeconds }}
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-name-status.sh
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: metadata-dir
+ mountPath: /hadoop
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/hadoop-env.sh
+ subPath: hadoop-env.sh
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.include
+ subPath: dfs.include
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/dfs.exclude
+ subPath: dfs.exclude
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/log4j.properties
+ subPath: log4j.properties
+ - name: namenode-config
+ mountPath: {{ .Values.runtime.configDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: lifecycle
+ mountPath: /lifecycle
+ - name: hadoop-logs
+ mountPath: {{ .Values.runtime.hadoopLogDir }}
+ - name: scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ runAsNonRoot: {{ .Values.securityContext.runAsNonRoot }}
+ privileged: {{ .Values.securityContext.privileged }}
+ allowPrivilegeEscalation: {{ .Values.securityContext.allowPrivilegeEscalation }}
+ capabilities:
+{{ toYaml .Values.securityContext.capabilities | nindent 12 }}
+ seccompProfile:
+{{ toYaml .Values.securityContext.seccompProfile | nindent 12 }}
+ - name: hdfs-zkfc
+ image: {{ include "hadoop.nameNodeImage" . | quote }}
+ imagePullPolicy: {{ .Values.nameNode.image.pullPolicy }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/start-zkfc.sh
+ env:
+ - name: HADOOP_HOME
+ value: {{ .Values.runtime.hadoopHome }}
+ - name: HADOOP_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ - name: HADOOP_LOG_DIR
+ value: {{ .Values.runtime.hadoopLogDir }}
+ ports:
+ - containerPort: 8019
+ name: zkfc
+ startupProbe:
+ failureThreshold: 30
+ initialDelaySeconds: 30
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - -ec
+ - "jps | grep -q DFSZKFailoverController || pgrep -f DFSZKFailoverController > /dev/null"
+ livenessProbe:
+ failureThreshold: 6
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - -ec
+ - "jps | grep -q DFSZKFailoverController || pgrep -f DFSZKFailoverController > /dev/null"
+ readinessProbe:
+ failureThreshold: 6
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - -ec
+ - "jps | grep -q DFSZKFailoverController || pgrep -f DFSZKFailoverController > /dev/null"
+ volumeMounts:
+ - name: hadoop-common
+ mountPath: {{ .Values.runtime.hadoopHome }}
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/hadoop-env.sh
+ subPath: hadoop-env.sh
+ - name: hdfs-common-config
+ mountPath: {{ .Values.runtime.configDir }}/log4j.properties
+ subPath: log4j.properties
+ - name: namenode-config
+ mountPath: {{ .Values.runtime.configDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: lifecycle
+ mountPath: /lifecycle
+ - name: hadoop-logs
+ mountPath: {{ .Values.runtime.hadoopLogDir }}
+ - name: scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ runAsNonRoot: {{ .Values.securityContext.runAsNonRoot }}
+ privileged: {{ .Values.securityContext.privileged }}
+ allowPrivilegeEscalation: {{ .Values.securityContext.allowPrivilegeEscalation }}
+ capabilities:
+{{ toYaml .Values.securityContext.capabilities | nindent 12 }}
+ seccompProfile:
+{{ toYaml .Values.securityContext.seccompProfile | nindent 12 }}
+ - name: jmx-exporter
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsNonRoot: {{ .Values.exporter.securityContext.runAsNonRoot }}
+ runAsUser: {{ .Values.exporter.securityContext.runAsUser }}
+ command:
+ - java
+ args:
+ - -XX:MaxRAMPercentage=100
+ - -XshowSettings:vm
+ - -jar
+ - jmx_prometheus_httpserver.jar
+ - {{ .Values.jmxExporter.port | quote }}
+ - /etc/jmx-exporter/hdfs-jmx-exporter.yaml
+ ports:
+ - name: http-metrics
+ containerPort: {{ .Values.jmxExporter.port }}
+ volumeMounts:
+ - name: hdfs-common-config
+ mountPath: /etc/jmx-exporter/hdfs-jmx-exporter.yaml
+ subPath: hdfs-jmx-exporter.yaml
+ securityContext:
+ fsGroupChangePolicy: {{ .Values.securityContext.fsGroupChangePolicy }}
+ fsGroup: {{ .Values.securityContext.fsGroup }}
+ volumes:
+ - name: hadoop-common
+ emptyDir: {}
+ - name: lifecycle
+ emptyDir: {}
+ - name: hadoop-logs
+ emptyDir: {}
+ updateStrategy: {{ .Values.updateStrategy }}
+ vars:
+ - name: CLUSTER_NAME
+ valueFrom:
+ clusterVarRef:
+ clusterName: Required
+ - name: CLUSTER_UID
+ valueFrom:
+ clusterVarRef:
+ clusterUID: Required
+ - name: NAMESPACE
+ valueFrom:
+ clusterVarRef:
+ namespace: Required
+ - name: CLUSTER_DOMAIN
+ value: {{ .Values.extra.clusterDomain }}
+ - name: HDFS_CONF_DIR
+ value: {{ .Values.runtime.configDir }}
+ - name: HDFS_JMX_PORT
+ value: {{ .Values.hdfs.ports.namenode.jmx | quote }}
+ - name: HDFS_NAMENODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.namenode.jmx | quote }}
+ - name: HDFS_DATANODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.datanode.jmx | quote }}
+ - name: HDFS_JOURNALNODE_JMX_PORT
+ value: {{ .Values.hdfs.ports.journalnode.jmx | quote }}
+ - name: HDFS_ZKFC_JMX_PORT
+ value: {{ .Values.hdfs.ports.zkfc.jmx | quote }}
+ - name: JOURNALNODE_POD_FQDN_LIST
+ valueFrom:
+ componentVarRef:
+ compDef: hdfs-journalnode
+ optional: false
+ podFQDNs: Required
+ - name: ZOOKEEPER_ENDPOINTS
+ valueFrom:
+ serviceRefVarRef:
+ name: hadoopZookeeper
+ endpoint: Required
+ - name: HDFS_NAMENODE_NAME_DIR
+ value: {{ .Values.hdfs.paths.namenodeMetadataDir | quote }}
+ - name: HDFS_NAMENODE_RPC_PORT
+ value: {{ .Values.hdfs.ports.namenode.rpc | quote }}
+ - name: HDFS_NAMENODE_HTTP_PORT
+ value: {{ .Values.hdfs.ports.namenode.http | quote }}
+ - name: HDFS_JOURNALNODE_RPC_PORT
+ value: {{ .Values.hdfs.ports.journalnode.rpc | quote }}
+ - name: HDFS_HA_FENCING_METHODS
+ value: {{ .Values.hdfs.ha.fencingMethods | quote }}
+ - name: HDFS_HA_AUTOMATIC_FAILOVER_ENABLED
+ value: {{ .Values.hdfs.ha.automaticFailoverEnabled | quote }}
+ - name: HDFS_HA_ZOOKEEPER_OPERATION_RETRIES
+ value: {{ .Values.hdfs.ha.zookeeper.operationRetries | quote }}
+ - name: HDFS_PERMISSIONS_ENABLED
+ value: {{ .Values.hdfs.permissions.enabled | quote }}
+ - name: HDFS_REGISTRATION_IP_HOSTNAME_CHECK
+ value: {{ .Values.hdfs.registration.ipHostnameCheck | quote }}
+ - name: HDFS_REPLICATION
+ value: {{ .Values.hdfs.replication | quote }}
+ - name: HDFS_REPLICATION_MAX
+ value: {{ .Values.hdfs.replicationMax | quote }}
+ - name: HDFS_CLIENT_REPLACE_DATANODE_ON_FAILURE_POLICY
+ value: {{ .Values.hdfs.client.replaceDatanodeOnFailurePolicy | quote }}
+ - name: HDFS_NAMENODE_HANDLER_COUNT
+ value: {{ .Values.hdfs.namenode.handlerCount | quote }}
+ - name: POD_FQDN
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.annotations['kubeblocks.io/pod-fqdn']
+ apiVersion: v1
+ configs:
+ - name: hdfs-common-config
+ template: hdfs-common-config-template
+ volumeName: hdfs-common-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.config.defaultMode }}
+ - name: namenode-config
+ template: namenode-config-template
+ volumeName: namenode-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.config.defaultMode }}
+ scripts:
+ - name: hadoop-scripts
+ template: hadoop-scripts
+ volumeName: scripts
+ namespace: {{ .Release.Namespace }}
+ defaultMode: {{ .Values.scripts.defaultMode }}
diff --git a/addons/hadoop/templates/cmpv-hdfs-datanode.yaml b/addons/hadoop/templates/cmpv-hdfs-datanode.yaml
new file mode 100644
index 0000000000..82d934d8a7
--- /dev/null
+++ b/addons/hadoop/templates/cmpv-hdfs-datanode.yaml
@@ -0,0 +1,22 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentVersion
+metadata:
+ name: hdfs-datanode
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.apiVersion" . | nindent 4 }}
+spec:
+ compatibilityRules:
+ - releases:
+ - v3.3.4
+ compDefs:
+ - hdfs-datanode
+ - hdfs-datanode-standalone
+ releases:
+ - name: v3.3.4
+ serviceVersion: v3.3.4
+ images:
+ hadoop-common: {{ include "hadoop.commonImage" . | quote }}
+ hdfs-datanode: {{ include "hadoop.dataNodeImage" . | quote }}
+ jmx-exporter: {{ include "hadoop.jmxExporterImage" . | quote }}
diff --git a/addons/hadoop/templates/cmpv-hdfs-journalnode.yaml b/addons/hadoop/templates/cmpv-hdfs-journalnode.yaml
new file mode 100644
index 0000000000..6b0a67cc82
--- /dev/null
+++ b/addons/hadoop/templates/cmpv-hdfs-journalnode.yaml
@@ -0,0 +1,21 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentVersion
+metadata:
+ name: hdfs-journalnode
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.apiVersion" . | nindent 4 }}
+spec:
+ compatibilityRules:
+ - releases:
+ - v3.3.4
+ compDefs:
+ - hdfs-journalnode
+ releases:
+ - name: v3.3.4
+ serviceVersion: v3.3.4
+ images:
+ hadoop-common: {{ include "hadoop.commonImage" . | quote }}
+ hdfs-journalnode: {{ include "hadoop.journalNodeImage" . | quote }}
+ jmx-exporter: {{ include "hadoop.jmxExporterImage" . | quote }}
diff --git a/addons/hadoop/templates/cmpv-hdfs-namenode.yaml b/addons/hadoop/templates/cmpv-hdfs-namenode.yaml
new file mode 100644
index 0000000000..3f21f367ac
--- /dev/null
+++ b/addons/hadoop/templates/cmpv-hdfs-namenode.yaml
@@ -0,0 +1,25 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentVersion
+metadata:
+ name: hdfs-namenode
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.apiVersion" . | nindent 4 }}
+spec:
+ compatibilityRules:
+ - releases:
+ - v3.3.4
+ compDefs:
+ - hdfs-namenode
+ - hdfs-namenode-standalone
+ releases:
+ - name: v3.3.4
+ serviceVersion: v3.3.4
+ images:
+ hadoop-common: {{ include "hadoop.commonImage" . | quote }}
+ init-namenode-format: {{ include "hadoop.initNameNodeFormatImage" . | quote }}
+ init-zkfc-format: {{ include "hadoop.initZkfcFormatImage" . | quote }}
+ hdfs-namenode: {{ include "hadoop.nameNodeImage" . | quote }}
+ hdfs-zkfc: {{ include "hadoop.nameNodeImage" . | quote }}
+ jmx-exporter: {{ include "hadoop.jmxExporterImage" . | quote }}
diff --git a/addons/hadoop/templates/hdfs-common-config-template.yaml b/addons/hadoop/templates/hdfs-common-config-template.yaml
new file mode 100644
index 0000000000..f3e3d79a5e
--- /dev/null
+++ b/addons/hadoop/templates/hdfs-common-config-template.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: hdfs-common-config-template
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+data:
+ core-site.xml: |-
+ {{- .Files.Get "config/core-site.tpl" | nindent 4 }}
+ hadoop-env.sh: |-
+ {{- .Files.Get "config/hadoop-env.sh.tpl" | nindent 4 }}
+ hdfs-jmx-exporter.yaml: |-
+ {{- .Files.Get "config/hdfs-jmx-exporter.yaml.tpl" | nindent 4 }}
+ dfs.include: |
+ {{- .Files.Get "config/dfs.include" | nindent 4 }}
+ dfs.exclude: |
+ {{- .Files.Get "config/dfs.exclude" | nindent 4 }}
+ log4j.properties: |-
+ {{- .Files.Get "config/log4j.properties" | nindent 4 }}
diff --git a/addons/hadoop/templates/hdfs-common-standalone-config-template.yaml b/addons/hadoop/templates/hdfs-common-standalone-config-template.yaml
new file mode 100644
index 0000000000..ee34eefd33
--- /dev/null
+++ b/addons/hadoop/templates/hdfs-common-standalone-config-template.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: hdfs-common-standalone-config-template
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+data:
+ core-site.xml: |-
+ {{- .Files.Get "config/core-site-standalone.tpl" | nindent 4 }}
+ hadoop-env.sh: |-
+ {{- .Files.Get "config/hadoop-env.sh.tpl" | nindent 4 }}
+ hdfs-jmx-exporter.yaml: |-
+ {{- .Files.Get "config/hdfs-jmx-exporter.yaml.tpl" | nindent 4 }}
+ dfs.include: |
+ {{- .Files.Get "config/dfs.include" | nindent 4 }}
+ dfs.exclude: |
+ {{- .Files.Get "config/dfs.exclude" | nindent 4 }}
+ log4j.properties: |-
+ {{- .Files.Get "config/log4j.properties" | nindent 4 }}
diff --git a/addons/hadoop/templates/hdfs-datanode-config-template.yaml b/addons/hadoop/templates/hdfs-datanode-config-template.yaml
new file mode 100644
index 0000000000..797e265548
--- /dev/null
+++ b/addons/hadoop/templates/hdfs-datanode-config-template.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: datanode-config-template
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+data:
+ hdfs-site.xml: |-
+ {{- .Files.Get "config/hdfs-datanode.tpl" | nindent 4 }}
+ log4j.properties: |-
+ {{- .Files.Get "config/log4j.properties" | nindent 4 }}
\ No newline at end of file
diff --git a/addons/hadoop/templates/hdfs-datanode-standalone-config-template.yaml b/addons/hadoop/templates/hdfs-datanode-standalone-config-template.yaml
new file mode 100644
index 0000000000..eea7458e57
--- /dev/null
+++ b/addons/hadoop/templates/hdfs-datanode-standalone-config-template.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: datanode-standalone-config-template
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+data:
+ hdfs-site.xml: |-
+ {{- .Files.Get "config/hdfs-datanode-standalone.tpl" | nindent 4 }}
+ log4j.properties: |-
+ {{- .Files.Get "config/log4j.properties" | nindent 4 }}
diff --git a/addons/hadoop/templates/hdfs-journalnode-config-template.yaml b/addons/hadoop/templates/hdfs-journalnode-config-template.yaml
new file mode 100644
index 0000000000..256ef5d9ff
--- /dev/null
+++ b/addons/hadoop/templates/hdfs-journalnode-config-template.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: journalnode-config-template
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+data:
+ hdfs-site.xml: |-
+ {{- .Files.Get "config/hdfs-journalnode.tpl" | nindent 4 }}
+ log4j.properties: |-
+ {{- .Files.Get "config/log4j.properties" | nindent 4 }}
\ No newline at end of file
diff --git a/addons/hadoop/templates/hdfs-namenode-config-template.yaml b/addons/hadoop/templates/hdfs-namenode-config-template.yaml
new file mode 100644
index 0000000000..c5e754d0e4
--- /dev/null
+++ b/addons/hadoop/templates/hdfs-namenode-config-template.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: namenode-config-template
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+data:
+ hdfs-site.xml: |-
+ {{- .Files.Get "config/hdfs-namenode.tpl" | nindent 4 }}
+ log4j.properties: |-
+ {{- .Files.Get "config/log4j.properties" | nindent 4 }}
\ No newline at end of file
diff --git a/addons/hadoop/templates/hdfs-namenode-standalone-config-template.yaml b/addons/hadoop/templates/hdfs-namenode-standalone-config-template.yaml
new file mode 100644
index 0000000000..95f0fa19a5
--- /dev/null
+++ b/addons/hadoop/templates/hdfs-namenode-standalone-config-template.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: namenode-standalone-config-template
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+data:
+ hdfs-site.xml: |-
+ {{- .Files.Get "config/hdfs-namenode-standalone.tpl" | nindent 4 }}
+ log4j.properties: |-
+ {{- .Files.Get "config/log4j.properties" | nindent 4 }}
diff --git a/addons/hadoop/templates/hdfs-scripts-template.yaml b/addons/hadoop/templates/hdfs-scripts-template.yaml
new file mode 100644
index 0000000000..8a54223421
--- /dev/null
+++ b/addons/hadoop/templates/hdfs-scripts-template.yaml
@@ -0,0 +1,29 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: hadoop-scripts
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+data:
+ check-journal-status.sh: |-
+ {{- .Files.Get "scripts/check-journal-status.sh" | nindent 4 }}
+ check-name-status.sh: |-
+ {{- .Files.Get "scripts/check-name-status.sh" | nindent 4 }}
+ check-data-status.sh: |-
+ {{- .Files.Get "scripts/check-data-status.sh" | nindent 4 }}
+ start-namenode.sh: |-
+ {{- .Files.Get "scripts/start-namenode.sh" | nindent 4 }}
+ start-zkfc.sh: |-
+ {{- .Files.Get "scripts/start-zkfc.sh" | nindent 4 }}
+ start-journalnode.sh: |-
+ {{- .Files.Get "scripts/start-journalnode.sh" | nindent 4 }}
+ start-datanode.sh: |-
+ {{- .Files.Get "scripts/start-datanode.sh" | nindent 4 }}
+ init-namenode-format.sh: |-
+ {{- .Files.Get "scripts/init-namenode-format.sh" | nindent 4 }}
+ init-zkfc-format.sh: |-
+ {{- .Files.Get "scripts/init-zkfc-format.sh" | nindent 4 }}
+ init-refresh-nodes.sh: |-
+ {{- .Files.Get "scripts/init-refresh-nodes.sh" | nindent 4 }}
+ datanode-decommission.sh: |-
+ {{- .Files.Get "scripts/datanode-decommission.sh" | nindent 4 }}
diff --git a/addons/hadoop/templates/paramsdef-hdfs-common.yaml b/addons/hadoop/templates/paramsdef-hdfs-common.yaml
new file mode 100644
index 0000000000..f023028c54
--- /dev/null
+++ b/addons/hadoop/templates/paramsdef-hdfs-common.yaml
@@ -0,0 +1,12 @@
+apiVersion: parameters.kubeblocks.io/v1alpha1
+kind: ParametersDefinition
+metadata:
+ name: hdfs-common-config-constraints
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+spec:
+ fileName: core-site.xml
+ parametersSchema:
+ topLevelKey: HDFSCommonParameter
+ cue: |-
+ {{- .Files.Get "config/hdfs-common-config-constraint.cue" | nindent 6 }}
diff --git a/addons/hadoop/templates/paramsdef-hdfs-datanode.yaml b/addons/hadoop/templates/paramsdef-hdfs-datanode.yaml
new file mode 100644
index 0000000000..ae4099c95d
--- /dev/null
+++ b/addons/hadoop/templates/paramsdef-hdfs-datanode.yaml
@@ -0,0 +1,12 @@
+apiVersion: parameters.kubeblocks.io/v1alpha1
+kind: ParametersDefinition
+metadata:
+ name: datanode-config-constraints
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+spec:
+ fileName: hdfs-site.xml
+ parametersSchema:
+ topLevelKey: DataNodeParameter
+ cue: |-
+ {{- .Files.Get "config/hdfs-datanode-config-constraint.cue" | nindent 6 }}
\ No newline at end of file
diff --git a/addons/hadoop/templates/paramsdef-hdfs-journalnode.yaml b/addons/hadoop/templates/paramsdef-hdfs-journalnode.yaml
new file mode 100644
index 0000000000..008f34b93f
--- /dev/null
+++ b/addons/hadoop/templates/paramsdef-hdfs-journalnode.yaml
@@ -0,0 +1,12 @@
+apiVersion: parameters.kubeblocks.io/v1alpha1
+kind: ParametersDefinition
+metadata:
+ name: journalnode-config-constraints
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+spec:
+ fileName: hdfs-site.xml
+ parametersSchema:
+ topLevelKey: JournalNodeParameter
+ cue: |-
+ {{- .Files.Get "config/hdfs-journalnode-config-constraint.cue" | nindent 6 }}
\ No newline at end of file
diff --git a/addons/hadoop/templates/paramsdef-hdfs-namenode.yaml b/addons/hadoop/templates/paramsdef-hdfs-namenode.yaml
new file mode 100644
index 0000000000..e4702ff531
--- /dev/null
+++ b/addons/hadoop/templates/paramsdef-hdfs-namenode.yaml
@@ -0,0 +1,12 @@
+apiVersion: parameters.kubeblocks.io/v1alpha1
+kind: ParametersDefinition
+metadata:
+ name: namenode-config-constraints
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+spec:
+ fileName: hdfs-site.xml
+ parametersSchema:
+ topLevelKey: NameNodeParameter
+ cue: |-
+ {{- .Files.Get "config/hdfs-namenode-config-constraint.cue" | nindent 6 }}
\ No newline at end of file
diff --git a/addons/hadoop/templates/pcr-hdfs-datanode-standalone.yaml b/addons/hadoop/templates/pcr-hdfs-datanode-standalone.yaml
new file mode 100644
index 0000000000..cfcba9e101
--- /dev/null
+++ b/addons/hadoop/templates/pcr-hdfs-datanode-standalone.yaml
@@ -0,0 +1,20 @@
+apiVersion: parameters.kubeblocks.io/v1alpha1
+kind: ParamConfigRenderer
+metadata:
+ name: hdfs-datanode-standalone-config-renderer
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.annotations" . | nindent 4 }}
+spec:
+ componentDef: hdfs-datanode-standalone
+ parametersDefs:
+ - hdfs-common-config-constraints
+ - datanode-config-constraints
+ configs:
+ - name: core-site.xml
+ fileFormatConfig:
+ format: xml
+ - name: hdfs-site.xml
+ fileFormatConfig:
+ format: xml
diff --git a/addons/hadoop/templates/pcr-hdfs-datanode.yaml b/addons/hadoop/templates/pcr-hdfs-datanode.yaml
new file mode 100644
index 0000000000..4d830873f3
--- /dev/null
+++ b/addons/hadoop/templates/pcr-hdfs-datanode.yaml
@@ -0,0 +1,20 @@
+apiVersion: parameters.kubeblocks.io/v1alpha1
+kind: ParamConfigRenderer
+metadata:
+ name: hdfs-datanode-config-renderer
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.annotations" . | nindent 4 }}
+spec:
+ componentDef: hdfs-datanode
+ parametersDefs:
+ - hdfs-common-config-constraints
+ - datanode-config-constraints
+ configs:
+ - name: core-site.xml
+ fileFormatConfig:
+ format: xml
+ - name: hdfs-site.xml
+ fileFormatConfig:
+ format: xml
diff --git a/addons/hadoop/templates/pcr-hdfs-journalnode.yaml b/addons/hadoop/templates/pcr-hdfs-journalnode.yaml
new file mode 100644
index 0000000000..98479aaa1b
--- /dev/null
+++ b/addons/hadoop/templates/pcr-hdfs-journalnode.yaml
@@ -0,0 +1,20 @@
+apiVersion: parameters.kubeblocks.io/v1alpha1
+kind: ParamConfigRenderer
+metadata:
+ name: hdfs-journalnode-config-renderer
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.annotations" . | nindent 4 }}
+spec:
+ componentDef: hdfs-journalnode
+ parametersDefs:
+ - hdfs-common-config-constraints
+ - journalnode-config-constraints
+ configs:
+ - name: core-site.xml
+ fileFormatConfig:
+ format: xml
+ - name: hdfs-site.xml
+ fileFormatConfig:
+ format: xml
diff --git a/addons/hadoop/templates/pcr-hdfs-namenode-standalone.yaml b/addons/hadoop/templates/pcr-hdfs-namenode-standalone.yaml
new file mode 100644
index 0000000000..9bf03ab59c
--- /dev/null
+++ b/addons/hadoop/templates/pcr-hdfs-namenode-standalone.yaml
@@ -0,0 +1,20 @@
+apiVersion: parameters.kubeblocks.io/v1alpha1
+kind: ParamConfigRenderer
+metadata:
+ name: hdfs-namenode-standalone-config-renderer
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.annotations" . | nindent 4 }}
+spec:
+ componentDef: hdfs-namenode-standalone
+ parametersDefs:
+ - hdfs-common-config-constraints
+ - namenode-config-constraints
+ configs:
+ - name: core-site.xml
+ fileFormatConfig:
+ format: xml
+ - name: hdfs-site.xml
+ fileFormatConfig:
+ format: xml
diff --git a/addons/hadoop/templates/pcr-hdfs-namenode.yaml b/addons/hadoop/templates/pcr-hdfs-namenode.yaml
new file mode 100644
index 0000000000..59d8e9443f
--- /dev/null
+++ b/addons/hadoop/templates/pcr-hdfs-namenode.yaml
@@ -0,0 +1,20 @@
+apiVersion: parameters.kubeblocks.io/v1alpha1
+kind: ParamConfigRenderer
+metadata:
+ name: hdfs-namenode-config-renderer
+ labels:
+ {{- include "hadoop.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hadoop.annotations" . | nindent 4 }}
+spec:
+ componentDef: hdfs-namenode
+ parametersDefs:
+ - hdfs-common-config-constraints
+ - namenode-config-constraints
+ configs:
+ - name: core-site.xml
+ fileFormatConfig:
+ format: xml
+ - name: hdfs-site.xml
+ fileFormatConfig:
+ format: xml
diff --git a/addons/hadoop/templates/scripts.yaml b/addons/hadoop/templates/scripts.yaml
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/addons/hadoop/values.yaml b/addons/hadoop/values.yaml
new file mode 100644
index 0000000000..bf06c23f5a
--- /dev/null
+++ b/addons/hadoop/values.yaml
@@ -0,0 +1,186 @@
+# Hadoop common image (used by initContainers via ComponentVersion.hadoop-common)
+image:
+ common:
+ registry: docker.io
+ repository: apecloud/hdfs-journalnode
+ tag: "v3.3.4-1.0.0"
+ pullPolicy: IfNotPresent
+ jmxExporter:
+ registry: docker.io
+ repository: apecloud/jmx-exporter
+ tag: 0.18.0-debian-11-r20
+
+journalNode:
+ image:
+ registry: docker.io
+ repository: apecloud/hdfs-journalnode
+ tag: "v3.3.4-1.0.0"
+ pullPolicy: IfNotPresent
+
+nameNode:
+ image:
+ registry: docker.io
+ repository: apecloud/hdfs-namenode
+ tag: "v3.3.4-1.0.0"
+ pullPolicy: IfNotPresent
+ initImages:
+ initNameNodeFormat:
+ registry: ""
+ repository: ""
+ tag: ""
+ pullPolicy: ""
+ initZkfcFormat:
+ registry: ""
+ repository: ""
+ tag: ""
+ pullPolicy: ""
+
+dataNode:
+ image:
+ registry: docker.io
+ repository: apecloud/hdfs-datanode
+ tag: "v3.3.4-1.0.0"
+ pullPolicy: IfNotPresent
+
+# kblib extension config
+extra:
+ disableExporter: true
+ terminationPolicy: Delete
+ clusterDomain: cluster.local
+
+exporter:
+ securityContext:
+ runAsNonRoot: true
+ runAsUser: 1001
+
+jmxExporter:
+ port: 5556
+
+runtime:
+ debug: false
+ hadoopHome: /opt/kubeemr/hadoop/hadoop-3.3.4
+ hadoopSoftwareDir: /opt/software/hadoop-3.3.4
+ configDir: /hadoop/conf
+ scriptsDir: /kubeblocks/scripts
+ hadoopLogDir: /var/log/hadoop
+ datanode:
+ hostNetwork: true
+ hostPID: true
+ dnsPolicy: ClusterFirstWithHostNet
+ journalnode:
+ waitZkToReady: false
+
+hdfs:
+ replication: 3
+ replicationMax: 6
+ permissions:
+ enabled: false
+ superusergroup: supergroup
+ registration:
+ ipHostnameCheck: false
+ client:
+ replaceDatanodeOnFailurePolicy: DEFAULT
+ namenode:
+ handlerCount: 64
+ datanode:
+ handlerCount: 64
+ ha:
+ automaticFailoverEnabled: true
+ fencingMethods: "sshfence\nshell(/bin/true)"
+ zookeeper:
+ sessionTimeoutMs: 60000
+ operationRetries: 3
+ parentZnodePrefix: /hadoop-ha
+ trash:
+ interval: 1440
+ ipc:
+ clientConnectionMaxIdleTimeMs: 300000
+ clientConnectTimeoutMs: 20000
+ clientConnectionPoolSize: 8
+ clientConnectRetryIntervalMs: 1000
+ clientPing: true
+ pingIntervalMs: 30000
+ jvm:
+ namenodeHeapSize: "3g"
+ datanodeHeapSize: "1g"
+ journalnodeHeapSize: "1g"
+ zkfcHeapSize: "512m"
+ ports:
+ namenode:
+ rpc: 8020
+ http: 9870
+ jmx: 10101
+ journalnode:
+ rpc: 8485
+ http: 8480
+ jmx: 10103
+ datanode:
+ data: 9866
+ ipc: 9867
+ http: 9864
+ jmx: 10102
+ zkfc:
+ jmx: 10104
+ paths:
+ namenodeMetadataDir: /hadoop/dfs/metadata
+ namenodeJournalDir: /hadoop/dfs/journal
+ datanodeDataDir: /hadoop/dfs/data0
+ journalnodeEditsDir: /hadoop/dfs/journal
+
+securityContext:
+ initRunAsUser: 0
+ runAsUser: 10000
+ runAsGroup: 1000
+ fsGroup: 1000
+ fsGroupChangePolicy: Always
+ runAsNonRoot: true
+ privileged: false
+ allowPrivilegeEscalation: false
+ seccompProfile:
+ type: RuntimeDefault
+ capabilities:
+ drop:
+ - ALL
+
+probes:
+ namenode:
+ liveness:
+ failureThreshold: 6
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ readiness:
+ failureThreshold: 6
+ initialDelaySeconds: 30
+ periodSeconds: 10
+ timeoutSeconds: 5
+ journalnode:
+ liveness:
+ failureThreshold: 6
+ initialDelaySeconds: 30
+ periodSeconds: 10
+ timeoutSeconds: 5
+ readiness:
+ failureThreshold: 6
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ timeoutSeconds: 5
+ datanode:
+ liveness:
+ failureThreshold: 6
+ initialDelaySeconds: 30
+ periodSeconds: 10
+ timeoutSeconds: 5
+ readiness:
+ failureThreshold: 6
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ timeoutSeconds: 5
+
+config:
+ defaultMode: 0755
+
+scripts:
+ defaultMode: 0755
+
+updateStrategy: BestEffortParallel
diff --git a/addons/hbase/.helmignore b/addons/hbase/.helmignore
new file mode 100644
index 0000000000..691fa13d6a
--- /dev/null
+++ b/addons/hbase/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
\ No newline at end of file
diff --git a/addons/hbase/Chart.yaml b/addons/hbase/Chart.yaml
new file mode 100644
index 0000000000..a5c9b01d47
--- /dev/null
+++ b/addons/hbase/Chart.yaml
@@ -0,0 +1,27 @@
+annotations:
+ category: BigData
+ addon.kubeblocks.io/kubeblocks-version: ">=1.0.0"
+ addon.kubeblocks.io/model: "key-value"
+ addon.kubeblocks.io/provider: "community"
+apiVersion: v2
+name: hbase
+description: A Helm chart for HBase on KubeBlocks.
+type: application
+version: 1.1.0-alpha.0
+appVersion: "2.5.6"
+dependencies:
+ - name: kblib
+ version: 0.1.0
+ repository: file://../kblib
+ alias: extra
+keywords:
+ - hbase
+ - bigdata
+ - hadoop
+home: https://github.com/apecloud/kubeblocks/tree/main/deploy/hbase
+icon: https://kubeblocks.io/img/logo.png
+maintainers:
+ - name: ApeCloud
+ url: https://kubeblocks.io/
+sources:
+ - https://github.com/apecloud/kubeblocks/
\ No newline at end of file
diff --git a/addons/hbase/README.md b/addons/hbase/README.md
new file mode 100644
index 0000000000..ec91e0aacf
--- /dev/null
+++ b/addons/hbase/README.md
@@ -0,0 +1,319 @@
+# HBase
+
+[中文说明](./README.zh-CN.md)
+
+Apache HBase is an open-source, distributed, versioned, column-oriented store modeled after Google's Bigtable. This addon enables HBase deployment and lifecycle management on KubeBlocks.
+
+## Overview
+
+The HBase addon currently provides two topologies:
+
+| Topology | Components | Storage Backend | External Dependencies | Notes |
+|----------|------------|-----------------|-----------------------|-------|
+| `cluster` | `hmaster`, `hregionserver` | HDFS | ZooKeeper, HDFS NameNode | Recommended for production-like deployments |
+| `standalone` | `hbase-standalone` | Local filesystem | ZooKeeper | Good for development and functional verification |
+
+Supported service version:
+
+| Major Version | Description |
+|---------------|-------------|
+| 2.5 | 2.5.6 |
+
+## What This Addon Contains
+
+The addon package under `addons/hbase` defines:
+
+- `ClusterDefinition` named `hbase`
+- component definitions for `hbase-hmaster`, `hbase-hregionserver`, and `hbase-standalone`
+- config templates for:
+ - `hbase-site.xml`
+ - `core-site.xml`
+ - `hdfs-site.xml`
+ - `hbase-env.sh`
+- runtime scripts and image mappings
+
+The deployment chart under `addons-cluster/hbase` provides a ready-to-use Cluster chart with deploy-time configuration knobs for:
+
+- HBase runtime tuning
+- HDFS client retry / timeout / failover
+- ZooKeeper session and connection settings
+- security-related flags
+
+## Prerequisites
+
+- Kubernetes cluster >= v1.21
+- KubeBlocks >= 1.1 installed and running
+- HBase addon installed
+- ZooKeeper addon enabled
+- Hadoop HDFS addon enabled if you want to use `cluster` topology
+- a dedicated namespace for your test or deployment, for example:
+
+```bash
+kubectl create ns demo
+```
+
+## Topology Details
+
+### Cluster Topology
+
+Cluster topology uses:
+
+- `hmaster` for master coordination
+- `hregionserver` for serving data
+- external ZooKeeper for coordination
+- external HDFS NameNode service for `hbase.rootdir`
+
+Cluster topology name in `ClusterDefinition`:
+
+```yaml
+spec:
+ clusterDef: hbase
+ topology: cluster
+```
+
+### Standalone Topology
+
+Standalone topology uses:
+
+- a single `hbase-standalone` component
+- local filesystem for `hbase.rootdir`
+- ZooKeeper service reference only
+
+Standalone topology name in `ClusterDefinition`:
+
+```yaml
+spec:
+ clusterDef: hbase
+ topology: standalone
+```
+
+## Observability
+
+HBase metrics are now exposed through a `jmx-exporter` sidecar instead of the old `metrics2 JmxSink` path.
+
+- the old `hadoop-metrics2-hbase.properties` JmxSink path has been removed
+- `hmaster`, `hregionserver`, and `hbase-standalone` now include a `jmx-exporter` sidecar
+- the exporter scrapes local JVM JMX over loopback and exposes `/metrics`
+
+If you want Prometheus discovery metadata on the component service, set `spec.componentSpecs[*].disableExporter=false` in the deployed `Cluster`.
+
+Typical PodMonitor endpoint:
+
+```yaml
+podMetricsEndpoints:
+ - path: /metrics
+ port: http-metrics
+ scheme: http
+```
+
+## Quick Start
+
+### Install the Addon
+
+From the repository root:
+
+```bash
+helm install hbase-addon ./addons/hbase
+```
+
+### Deploy with the Cluster Chart
+
+Cluster topology:
+
+```bash
+helm install hbase-cluster ./addons-cluster/hbase \
+ -n demo \
+ --create-namespace \
+ --set topology=cluster \
+ --set serviceRefs.hbaseZookeeper.namespace=kubeblocks \
+ --set serviceRefs.hbaseZookeeper.clusterServiceSelector.cluster=zk \
+ --set serviceRefs.hdfsNamenode.namespace=kubeblocks \
+ --set serviceRefs.hdfsNamenode.clusterServiceSelector.cluster=hdfs
+```
+
+Standalone topology:
+
+```bash
+helm install hbase-standalone ./addons-cluster/hbase \
+ -n demo \
+ --create-namespace \
+ --set topology=standalone \
+ --set serviceRefs.hbaseZookeeper.namespace=kubeblocks \
+ --set serviceRefs.hbaseZookeeper.clusterServiceSelector.cluster=zk
+```
+
+## Raw Cluster Examples
+
+### Minimal Cluster Mode Example
+
+```yaml
+apiVersion: apps.kubeblocks.io/v1
+kind: Cluster
+metadata:
+ name: hbase-cluster
+ namespace: demo
+spec:
+ terminationPolicy: Delete
+ clusterDef: hbase
+ topology: cluster
+ componentSpecs:
+ - name: hmaster
+ componentDef: hbase-hmaster-2.5
+ serviceVersion: 2.5.6
+ replicas: 2
+ serviceRefs:
+ - name: hbase-zookeeper
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: zk
+ service:
+ component: zookeeper
+ service: headless
+ port: client
+ - name: hdfs-namenode
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: hdfs
+ service:
+ component: namenode
+ service: headless
+ port: fs
+ - name: hregionserver
+ componentDef: hbase-hregionserver-2.5
+ serviceVersion: 2.5.6
+ replicas: 2
+ serviceRefs:
+ - name: hbase-zookeeper
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: zk
+ service:
+ component: zookeeper
+ service: headless
+ port: client
+ - name: hdfs-namenode
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: hdfs
+ service:
+ component: namenode
+ service: headless
+ port: fs
+```
+
+### Minimal Standalone Mode Example
+
+```yaml
+apiVersion: apps.kubeblocks.io/v1
+kind: Cluster
+metadata:
+ name: hbase-standalone
+ namespace: demo
+spec:
+ terminationPolicy: Delete
+ clusterDef: hbase
+ topology: standalone
+ componentSpecs:
+ - name: hbase-standalone
+ componentDef: hbase-standalone-2.5
+ serviceVersion: 2.5.6
+ replicas: 1
+ serviceRefs:
+ - name: hbase-zookeeper
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: zk
+ service:
+ component: zookeeper
+ service: headless
+ port: client
+```
+
+## Configuration Files
+
+The addon renders different config files for different topologies:
+
+| Source Template | Rendered File | Used By | Purpose |
+|----------------|---------------|---------|---------|
+| `config/hbase-site-cluster.tpl` | `hbase-site.xml` | `hmaster`, `hregionserver` | Cluster-mode HBase configuration |
+| `config/hbase-site-standalone.tpl` | `hbase-site.xml` | `hbase-standalone` | Standalone-mode HBase configuration |
+| `config/hdfs-common-site.tpl` | `core-site.xml` | cluster topology | Hadoop common client settings |
+| `config/hdfs-client-site.tpl` | `hdfs-site.xml` | cluster topology | HDFS nameservice and failover client settings |
+| `config/hbase-env.sh.tpl` | `hbase-env.sh` | all components | runtime environment variables and JVM flags |
+
+## Deploy-Time Configuration Surface
+
+The cluster chart exposes deploy-time values through `addons-cluster/hbase/values.yaml`.
+
+### Main Value Groups
+
+| Value Prefix | Applies To | Example Keys |
+|-------------|------------|--------------|
+| `hbase.zk.*` | cluster and standalone | `sessionTimeout`, `maxClientCnxns` |
+| `hbase.security.*` | cluster and standalone | `authentication`, `authorization` |
+| `hbase.common.*` | cluster and standalone | `clientScannerCaching`, `regionMemstoreFlushSize` |
+| `hbase.cluster.*` | cluster only | `regionserverHandlerCount`, `masterWaitOnRegionserversTimeout`, `splitlogManagerTimeout` |
+| `hbase.standalone.*` | standalone only | `regionserverHandlerCount`, `hstoreFlusherCount`, `regionMaxFileSize` |
+| `hdfs.fs.*` | cluster only | `trashInterval` |
+| `hdfs.security.*` | cluster only | `authentication`, `authorization` |
+| `hdfs.ipc.*` | cluster only | `clientConnectionMaxIdleTime`, `clientConnectTimeout`, `pingInterval` |
+| `hdfs.client.*` | cluster only | `webhdfsEnabled`, `failoverMaxAttempts`, `retryPolicy.*`, `commonRetryPolicy.*` |
+| `hdfs.hbaseClient.*` | cluster only | `ipcClientConnectTimeout`, `ipcClientConnectMaxRetries` |
+
+### Example Overrides
+
+```yaml
+topology: cluster
+
+hbase:
+ zk:
+ sessionTimeout: 45000
+ cluster:
+ regionserverHandlerCount: 200
+ hstoreFlusherCount: 8
+ regionserverStartupRetries: 20
+
+hdfs:
+ fs:
+ trashInterval: 2880
+ client:
+ failoverMaxAttempts: 30
+ webhdfsEnabled: true
+```
+
+## Validation and Operations
+
+Check the generated Cluster:
+
+```bash
+kubectl get cluster -n demo
+kubectl describe cluster -n demo hbase-cluster
+```
+
+Check pods:
+
+```bash
+kubectl get pods -n demo -l app.kubernetes.io/instance=hbase-cluster
+```
+
+Inspect rendered config inside a pod:
+
+```bash
+kubectl exec -n demo hbase-cluster-hmaster-0 -- cat /opt/bitnami/hbase/conf/hbase-site.xml
+kubectl exec -n demo hbase-cluster-hmaster-0 -- cat /opt/bitnami/hbase/conf/core-site.xml
+kubectl exec -n demo hbase-cluster-hmaster-0 -- cat /opt/bitnami/hbase/conf/hdfs-site.xml
+```
+
+## Current Limitations
+
+- `cluster` topology requires external ZooKeeper and HDFS NameNode service references.
+- Deploy-time configuration is currently exposed through the cluster chart values and `configs.variables`.
+- The HBase addon does **not** yet provide the standard `ParametersDefinition` / `ParamConfigRenderer` / config-constraint based parameter reconfiguration chain.
+- Most HBase and Hadoop client settings here should be treated as deployment-time settings.
+
+## Delete
+
+```bash
+kubectl patch cluster -n demo hbase-cluster -p '{"spec":{"terminationPolicy":"WipeOut"}}' --type="merge"
+kubectl delete cluster -n demo hbase-cluster
+```
diff --git a/addons/hbase/README.zh-CN.md b/addons/hbase/README.zh-CN.md
new file mode 100644
index 0000000000..5b2d100588
--- /dev/null
+++ b/addons/hbase/README.zh-CN.md
@@ -0,0 +1,322 @@
+# HBase
+
+[English](./README.md)
+
+本文档介绍 KubeBlocks HBase addon 的结构、拓扑、依赖关系、部署方式以及当前可用的配置入口。
+
+## 概览
+
+当前 HBase addon 提供两种拓扑:
+
+| 拓扑 | 组件 | 存储后端 | 外部依赖 | 说明 |
+|------|------|----------|----------|------|
+| `cluster` | `hmaster`、`hregionserver` | HDFS | ZooKeeper、HDFS NameNode | 适合真实集群部署 |
+| `standalone` | `hbase-standalone` | 本地文件系统 | ZooKeeper | 适合开发、验证和轻量场景 |
+
+当前支持的服务版本:
+
+| 大版本 | 说明 |
+|--------|------|
+| 2.5 | 2.5.6 |
+
+## Addon 提供的内容
+
+`addons/hbase` 目录当前定义了:
+
+- `ClusterDefinition`:`hbase`
+- `ComponentDefinition`:
+ - `hbase-hmaster`
+ - `hbase-hregionserver`
+ - `hbase-standalone`
+- 配置模板:
+ - `hbase-site.xml`
+ - `core-site.xml`
+ - `hdfs-site.xml`
+ - `hbase-env.sh`
+- 运行脚本和镜像映射
+
+`addons-cluster/hbase` 目录提供了一个可直接部署的 cluster chart,并已经暴露出一批部署阶段可配置项,用于:
+
+- HBase 运行参数调优
+- HDFS 客户端超时、重试、failover 参数
+- ZooKeeper 会话和连接参数
+- 安全相关开关
+
+## 前置条件
+
+- Kubernetes >= v1.21
+- KubeBlocks >= 1.1 已安装并正常运行
+- HBase addon 已安装
+- ZooKeeper addon 已启用
+- 如果使用 `cluster` 拓扑,还需要 Hadoop HDFS addon 已启用
+- 建议准备独立 namespace,例如:
+
+```bash
+kubectl create ns demo
+```
+
+## 拓扑说明
+
+### Cluster 拓扑
+
+Cluster 拓扑包含:
+
+- `hmaster`
+- `hregionserver`
+- 外部 ZooKeeper
+- 外部 HDFS NameNode 服务引用
+
+对应的 Cluster 配置:
+
+```yaml
+spec:
+ clusterDef: hbase
+ topology: cluster
+```
+
+### Standalone 拓扑
+
+Standalone 拓扑包含:
+
+- 单个 `hbase-standalone` 组件
+- 本地文件系统 `hbase.rootdir`
+- 仅依赖 ZooKeeper serviceRef
+
+对应的 Cluster 配置:
+
+```yaml
+spec:
+ clusterDef: hbase
+ topology: standalone
+```
+
+## 监控说明
+
+HBase 当前的监控出口已经切到 `jmx-exporter` sidecar,不再依赖旧的 `metrics2 JmxSink`。
+
+- 旧的 `hadoop-metrics2-hbase.properties` JmxSink 路径已经移除
+- `hmaster`、`hregionserver` 和 `hbase-standalone` 现在都会带一个 `jmx-exporter` sidecar
+- sidecar 通过本地 loopback 抓取 JVM JMX,并对外暴露 `/metrics`
+
+如果希望组件 Service 上带 Prometheus 发现信息,需要在实际部署的 `Cluster` 里将 `spec.componentSpecs[*].disableExporter=false`。
+
+典型的 `PodMonitor` endpoint 如下:
+
+```yaml
+podMetricsEndpoints:
+ - path: /metrics
+ port: http-metrics
+ scheme: http
+```
+
+## 快速开始
+
+### 安装 Addon
+
+在仓库根目录执行:
+
+```bash
+helm install hbase-addon ./addons/hbase
+```
+
+### 使用 Cluster Chart 部署
+
+Cluster 模式:
+
+```bash
+helm install hbase-cluster ./addons-cluster/hbase \
+ -n demo \
+ --create-namespace \
+ --set topology=cluster \
+ --set serviceRefs.hbaseZookeeper.namespace=kubeblocks \
+ --set serviceRefs.hbaseZookeeper.clusterServiceSelector.cluster=zk \
+ --set serviceRefs.hdfsNamenode.namespace=kubeblocks \
+ --set serviceRefs.hdfsNamenode.clusterServiceSelector.cluster=hdfs
+```
+
+Standalone 模式:
+
+```bash
+helm install hbase-standalone ./addons-cluster/hbase \
+ -n demo \
+ --create-namespace \
+ --set topology=standalone \
+ --set serviceRefs.hbaseZookeeper.namespace=kubeblocks \
+ --set serviceRefs.hbaseZookeeper.clusterServiceSelector.cluster=zk
+```
+
+## 原生 Cluster API 示例
+
+### 最小 Cluster 模式示例
+
+```yaml
+apiVersion: apps.kubeblocks.io/v1
+kind: Cluster
+metadata:
+ name: hbase-cluster
+ namespace: demo
+spec:
+ terminationPolicy: Delete
+ clusterDef: hbase
+ topology: cluster
+ componentSpecs:
+ - name: hmaster
+ componentDef: hbase-hmaster-2.5
+ serviceVersion: 2.5.6
+ replicas: 2
+ serviceRefs:
+ - name: hbase-zookeeper
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: zk
+ service:
+ component: zookeeper
+ service: headless
+ port: client
+ - name: hdfs-namenode
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: hdfs
+ service:
+ component: namenode
+ service: headless
+ port: fs
+ - name: hregionserver
+ componentDef: hbase-hregionserver-2.5
+ serviceVersion: 2.5.6
+ replicas: 2
+ serviceRefs:
+ - name: hbase-zookeeper
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: zk
+ service:
+ component: zookeeper
+ service: headless
+ port: client
+ - name: hdfs-namenode
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: hdfs
+ service:
+ component: namenode
+ service: headless
+ port: fs
+```
+
+### 最小 Standalone 模式示例
+
+```yaml
+apiVersion: apps.kubeblocks.io/v1
+kind: Cluster
+metadata:
+ name: hbase-standalone
+ namespace: demo
+spec:
+ terminationPolicy: Delete
+ clusterDef: hbase
+ topology: standalone
+ componentSpecs:
+ - name: hbase-standalone
+ componentDef: hbase-standalone-2.5
+ serviceVersion: 2.5.6
+ replicas: 1
+ serviceRefs:
+ - name: hbase-zookeeper
+ namespace: kubeblocks
+ clusterServiceSelector:
+ cluster: zk
+ service:
+ component: zookeeper
+ service: headless
+ port: client
+```
+
+## 配置文件结构
+
+当前 addon 会根据不同拓扑渲染不同配置文件:
+
+| 模板文件 | 最终文件 | 使用组件 | 作用 |
+|----------|----------|----------|------|
+| `config/hbase-site-cluster.tpl` | `hbase-site.xml` | `hmaster`、`hregionserver` | cluster 模式 HBase 主配置 |
+| `config/hbase-site-standalone.tpl` | `hbase-site.xml` | `hbase-standalone` | standalone 模式 HBase 主配置 |
+| `config/hdfs-common-site.tpl` | `core-site.xml` | cluster 模式 | Hadoop 通用客户端配置 |
+| `config/hdfs-client-site.tpl` | `hdfs-site.xml` | cluster 模式 | HDFS nameservice / failover 客户端配置 |
+| `config/hbase-env.sh.tpl` | `hbase-env.sh` | 全部组件 | 运行时环境变量和 JVM 参数 |
+
+## 当前部署阶段配置入口
+
+当前 cluster chart 通过 `addons-cluster/hbase/values.yaml` 暴露部署阶段配置。
+
+### 主要参数分组
+
+| 参数前缀 | 适用范围 | 典型参数 |
+|----------|----------|----------|
+| `hbase.zk.*` | cluster + standalone | `sessionTimeout`、`maxClientCnxns` |
+| `hbase.security.*` | cluster + standalone | `authentication`、`authorization` |
+| `hbase.common.*` | cluster + standalone | `clientScannerCaching`、`regionMemstoreFlushSize` |
+| `hbase.cluster.*` | cluster | `regionserverHandlerCount`、`masterWaitOnRegionserversTimeout`、`splitlogManagerTimeout` |
+| `hbase.standalone.*` | standalone | `regionserverHandlerCount`、`hstoreFlusherCount`、`regionMaxFileSize` |
+| `hdfs.fs.*` | cluster | `trashInterval` |
+| `hdfs.security.*` | cluster | `authentication`、`authorization` |
+| `hdfs.ipc.*` | cluster | `clientConnectionMaxIdleTime`、`clientConnectTimeout`、`pingInterval` |
+| `hdfs.client.*` | cluster | `webhdfsEnabled`、`failoverMaxAttempts`、`retryPolicy.*`、`commonRetryPolicy.*` |
+| `hdfs.hbaseClient.*` | cluster | `ipcClientConnectTimeout`、`ipcClientConnectMaxRetries` |
+
+### 覆盖示例
+
+```yaml
+topology: cluster
+
+hbase:
+ zk:
+ sessionTimeout: 45000
+ cluster:
+ regionserverHandlerCount: 200
+ hstoreFlusherCount: 8
+ regionserverStartupRetries: 20
+
+hdfs:
+ fs:
+ trashInterval: 2880
+ client:
+ failoverMaxAttempts: 30
+ webhdfsEnabled: true
+```
+
+## 验证与排查
+
+检查生成的 Cluster:
+
+```bash
+kubectl get cluster -n demo
+kubectl describe cluster -n demo hbase-cluster
+```
+
+检查 Pod:
+
+```bash
+kubectl get pods -n demo -l app.kubernetes.io/instance=hbase-cluster
+```
+
+查看容器内最终渲染出的配置:
+
+```bash
+kubectl exec -n demo hbase-cluster-hmaster-0 -- cat /opt/bitnami/hbase/conf/hbase-site.xml
+kubectl exec -n demo hbase-cluster-hmaster-0 -- cat /opt/bitnami/hbase/conf/core-site.xml
+kubectl exec -n demo hbase-cluster-hmaster-0 -- cat /opt/bitnami/hbase/conf/hdfs-site.xml
+```
+
+## 当前限制
+
+- `cluster` 拓扑必须依赖外部 ZooKeeper 和 HDFS NameNode 的 serviceRef。
+- 当前这批参数是通过 cluster chart values 和 `configs.variables` 暴露的部署阶段能力。
+- HBase addon 目前**还没有**接入标准的 `ParametersDefinition` / `ParamConfigRenderer` / config-constraint 参数重配链路。
+- 因此当前这些参数应视为部署阶段参数,而不是统一参数管理入口。
+
+## 删除集群
+
+```bash
+kubectl patch cluster -n demo hbase-cluster -p '{"spec":{"terminationPolicy":"WipeOut"}}' --type="merge"
+kubectl delete cluster -n demo hbase-cluster
+```
diff --git a/addons/hbase/config/hbase-env.sh.tpl b/addons/hbase/config/hbase-env.sh.tpl
new file mode 100644
index 0000000000..d94f85e38d
--- /dev/null
+++ b/addons/hbase/config/hbase-env.sh.tpl
@@ -0,0 +1,16 @@
+export HBASE_CONF_DIR={{ .HBASE_CONF_DIR }}
+export HBASE_PID_DIR={{ .HBASE_PID_DIR }}
+export HBASE_LOG_DIR={{ .HBASE_LOG_DIR }}
+export HBASE_MANAGES_ZK=false
+
+export HBASE_OPTS="${HBASE_OPTS:-} -XX:+UseG1GC -XX:MaxGCPauseMillis=50 -XX:ParallelGCThreads=20 -Dsun.net.inetaddr.ttl=10 -Djava.net.preferIPv4Stack=true"
+export SERVER_GC_OPTS="-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:${HBASE_LOG_DIR}/gc-server.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=50M"
+export CLIENT_GC_OPTS="-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
+
+export HBASE_JMX_BASE="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=127.0.0.1"
+export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS $HBASE_JMX_BASE -Dcom.sun.management.jmxremote.port={{ .HBASE_MASTER_JMX_PORT }} -Dcom.sun.management.jmxremote.rmi.port={{ .HBASE_MASTER_JMX_PORT }} -Xms{{ .HBASE_MASTER_HEAP_SIZE }} -Xmx{{ .HBASE_MASTER_HEAP_SIZE }}"
+export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS $HBASE_JMX_BASE -Dcom.sun.management.jmxremote.port={{ .HBASE_REGIONSERVER_JMX_PORT }} -Dcom.sun.management.jmxremote.rmi.port={{ .HBASE_REGIONSERVER_JMX_PORT }} -Dhbase.regionserver.hostname=${POD_FQDN} -Xms{{ .HBASE_REGIONSERVER_HEAP_SIZE }} -Xmx{{ .HBASE_REGIONSERVER_HEAP_SIZE }}"
+export HBASE_HEAPSIZE={{ .HBASE_HEAP_SIZE }}
+
+export HBASE_DISABLE_HADOOP_CLASSPATH_LOOKUP=true
+export LD_LIBRARY_PATH={{ .HADOOP_NATIVE_LIB_PATH }}:${LD_LIBRARY_PATH:-}
diff --git a/addons/hbase/config/hbase-jmx-exporter.yaml.tpl b/addons/hbase/config/hbase-jmx-exporter.yaml.tpl
new file mode 100644
index 0000000000..050f7e28e7
--- /dev/null
+++ b/addons/hbase/config/hbase-jmx-exporter.yaml.tpl
@@ -0,0 +1,9 @@
+jmxUrl: service:jmx:rmi:///jndi/rmi://127.0.0.1:{{ .HBASE_JMX_PORT }}/jmxrmi
+ssl: false
+lowercaseOutputName: true
+lowercaseOutputLabelNames: true
+whitelistObjectNames:
+ - "Hadoop:*"
+ - "java.lang:*"
+rules:
+ - pattern: ".*"
diff --git a/addons/hbase/config/hbase-site-cluster.tpl b/addons/hbase/config/hbase-site-cluster.tpl
new file mode 100644
index 0000000000..a61443e4db
--- /dev/null
+++ b/addons/hbase/config/hbase-site-cluster.tpl
@@ -0,0 +1,294 @@
+
+
+
+
+ hbase.cluster.distributed
+ true
+
+
+
+ hbase.rootdir
+ hdfs://{{ .HDFS_NAMESERVICE }}/{{ .HBASE_ROOT_DIR }}
+
+
+
+ hbase.zookeeper.quorum
+ {{ .ZOOKEEPER_QUORUM }}
+
+
+
+ hbase.zookeeper.property.clientPort
+ {{ .ZOOKEEPER_CLIENT_PORT }}
+
+
+
+ zookeeper.znode.parent
+ {{ .HBASE_ZK_PARENT }}
+
+
+
+ zookeeper.session.timeout
+ {{ .HBASE_ZOOKEEPER_SESSION_TIMEOUT }}
+
+
+
+ hbase.zookeeper.property.tickTime
+ 6000
+
+
+
+ hbase.zookeeper.property.4lw.commands.whitelist
+ *
+
+
+
+ hbase.zookeeper.property.maxClientCnxns
+ {{ .HBASE_ZOOKEEPER_MAX_CLIENT_CNXNS }}
+
+
+
+ hbase.zookeeper.property.autopurge.purgeInterval
+ 1
+
+
+
+ hbase.zookeeper.property.autopurge.snapRetainCount
+ 3
+
+
+
+ hbase.master.port
+ {{ .HBASE_MASTER_PORT }}
+
+
+
+ hbase.master.info.port
+ {{ .HBASE_MASTER_INFO_PORT }}
+
+
+
+ hbase.regionserver.port
+ {{ .HBASE_REGIONSERVER_PORT }}
+
+
+
+ hbase.regionserver.info.port
+ {{ .HBASE_REGIONSERVER_INFO_PORT }}
+
+
+
+ hbase.regionserver.hostname.disable.master.reversedns
+ true
+
+
+
+ hbase.tmp.dir
+ {{ .HBASE_TMP_DIR }}
+
+
+
+ hbase.regionserver.handler.count
+ {{ .HBASE_REGIONSERVER_HANDLER_COUNT }}
+
+
+
+ hbase.hstore.flusher.count
+ {{ .HBASE_HSTORE_FLUSHER_COUNT }}
+
+
+
+ hbase.client.scanner.caching
+ {{ .HBASE_CLIENT_SCANNER_CACHING }}
+
+
+
+ hbase.hregion.max.filesize
+ {{ .HBASE_HREGION_MAX_FILESIZE }}
+
+
+
+ hbase.hregion.memstore.flush.size
+ {{ .HBASE_HREGION_MEMSTORE_FLUSH_SIZE }}
+
+
+
+ hbase.hregion.majorcompaction
+ {{ .HBASE_HREGION_MAJORCOMPACTION }}
+
+
+
+ hbase.storescanner.parallel.seek.enable
+ true
+
+
+
+ hbase.ipc.server.callqueue.type
+ plunger
+
+
+
+ hbase.master.wait.on.regionservers.timeout
+ {{ .HBASE_MASTER_WAIT_ON_REGIONSERVERS_TIMEOUT }}
+
+
+
+ hbase.master.startup.retainassign.timeout
+ {{ .HBASE_MASTER_STARTUP_RETAINASSIGN_TIMEOUT }}
+
+
+
+ hbase.assignment.usezk
+ false
+
+
+
+ hbase.oldwals.cleaner.thread.timeout.msec
+ {{ .HBASE_OLDWALS_CLEANER_THREAD_TIMEOUT_MSEC }}
+
+
+
+ hbase.master.logcleaner.ttl
+ {{ .HBASE_MASTER_LOGCLEANER_TTL }}
+
+
+
+ hbase.master.hfilecleaner.ttl
+ {{ .HBASE_MASTER_HFILECLEANER_TTL }}
+
+
+
+ hbase.balancer.period
+ {{ .HBASE_BALANCER_PERIOD }}
+
+
+
+ hbase.master.balancer.stochastic.runMaxSteps
+ true
+
+
+
+ hbase.master.loadbalancer.class
+ org.apache.hadoop.hbase.rsgroup.RSGroupBasedLoadBalancer
+
+
+
+ hbase.procedure.store.wal.use.hsync
+ {{ .HBASE_PROCEDURE_STORE_WAL_USE_HSYNC }}
+
+
+
+ hbase.regionserver.optionalcacheflushinterval
+ {{ .HBASE_REGIONSERVER_OPTIONALCACHEFLUSHINTERVAL }}
+
+
+
+ hbase.regionserver.startup.retries
+ {{ .HBASE_REGIONSERVER_STARTUP_RETRIES }}
+
+
+
+ hbase.regionserver.startup.retry.interval
+ {{ .HBASE_REGIONSERVER_STARTUP_RETRY_INTERVAL }}
+
+
+
+ hbase.wal.provider
+ filesystem
+
+
+
+ hbase.replication
+ {{ .HBASE_REPLICATION_ENABLED }}
+
+
+
+ hbase.security.authentication
+ {{ .HBASE_SECURITY_AUTHENTICATION }}
+
+
+
+ hbase.security.authorization
+ {{ .HBASE_SECURITY_AUTHORIZATION }}
+
+
+
+ hbase.unsafe.stream.capability.enforce
+ false
+
+
+
+ hbase.master.logcleaner.plugins
+
+ org.apache.hadoop.hbase.master.cleaner.TimeToLiveLogCleaner,org.apache.hadoop.hbase.master.cleaner.TimeToLiveProcedureWALCleaner,org.apache.hadoop.hbase.replication.master.ReplicationLogCleaner
+
+
+
+ hbase.master.hfilecleaner.plugins
+ org.apache.hadoop.hbase.master.cleaner.TimeToLiveHFileCleaner
+
+
+
+ hbase.master.procedure.tlogcleaner.plugins
+ org.apache.hadoop.hbase.master.cleaner.TimeToLiveProcedureWALCleaner
+
+
+
+ hbase.coprocessor.master.classes
+ org.apache.hadoop.hbase.rsgroup.RSGroupAdminEndpoint
+
+
+
+ hbase.coprocessor.region.classes
+ org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint
+
+
+
+ dfs.client.failover.max.attempts
+ {{ .HDFS_CLIENT_FAILOVER_MAX_ATTEMPTS }}
+
+
+
+ dfs.client.failover.sleep.base.millis
+ {{ .HDFS_CLIENT_FAILOVER_SLEEP_BASE_MILLIS }}
+
+
+
+ dfs.client.failover.sleep.max.millis
+ {{ .HDFS_CLIENT_FAILOVER_SLEEP_MAX_MILLIS }}
+
+
+
+ dfs.client.retry.policy.enabled
+ {{ .HBASE_HDFS_CLIENT_RETRY_POLICY_ENABLED }}
+
+
+
+ dfs.client.retry.policy.spec
+ {{ .HBASE_HDFS_CLIENT_RETRY_POLICY_SPEC }}
+
+
+
+ ipc.client.connect.timeout
+ {{ .HBASE_IPC_CLIENT_CONNECT_TIMEOUT }}
+
+
+
+ ipc.client.connect.max.retries
+ {{ .HBASE_IPC_CLIENT_CONNECT_MAX_RETRIES }}
+
+
+
+ hbase.regionserver.wal.rs.bulkload.enabled
+ true
+
+
+
+ hbase.io.compress.lz4.codec
+ org.apache.hadoop.hbase.io.compress.lz4.Lz4Codec
+
+
+
+ hbase.splitlog.manager.timeout
+ {{ .HBASE_SPLITLOG_MANAGER_TIMEOUT }}
+
+
diff --git a/addons/hbase/config/hbase-site-standalone.tpl b/addons/hbase/config/hbase-site-standalone.tpl
new file mode 100644
index 0000000000..e853614f6a
--- /dev/null
+++ b/addons/hbase/config/hbase-site-standalone.tpl
@@ -0,0 +1,143 @@
+
+
+
+
+ hbase.cluster.distributed
+ false
+
+
+
+ hbase.rootdir
+ file://{{ .HBASE_DATA_DIR }}/hbase
+
+
+
+ hbase.zookeeper.quorum
+ {{ .ZOOKEEPER_QUORUM }}
+
+
+
+ hbase.zookeeper.property.clientPort
+ {{ .ZOOKEEPER_CLIENT_PORT }}
+
+
+
+ zookeeper.znode.parent
+ {{ .HBASE_ZK_PARENT }}
+
+
+
+ zookeeper.session.timeout
+ {{ .HBASE_ZOOKEEPER_SESSION_TIMEOUT }}
+
+
+
+ hbase.zookeeper.property.tickTime
+ 6000
+
+
+
+ hbase.zookeeper.property.4lw.commands.whitelist
+ *
+
+
+
+ hbase.zookeeper.property.maxClientCnxns
+ {{ .HBASE_ZOOKEEPER_MAX_CLIENT_CNXNS }}
+
+
+
+ hbase.zookeeper.property.autopurge.purgeInterval
+ 1
+
+
+
+ hbase.zookeeper.property.autopurge.snapRetainCount
+ 3
+
+
+
+ hbase.master.port
+ {{ .HBASE_MASTER_PORT }}
+
+
+
+ hbase.master.info.port
+ {{ .HBASE_MASTER_INFO_PORT }}
+
+
+
+ hbase.regionserver.port
+ {{ .HBASE_REGIONSERVER_PORT }}
+
+
+
+ hbase.regionserver.info.port
+ {{ .HBASE_REGIONSERVER_INFO_PORT }}
+
+
+
+ hbase.tmp.dir
+ {{ .HBASE_TMP_DIR }}
+
+
+
+ hbase.regionserver.handler.count
+ {{ .HBASE_REGIONSERVER_HANDLER_COUNT }}
+
+
+
+ hbase.hstore.flusher.count
+ {{ .HBASE_HSTORE_FLUSHER_COUNT }}
+
+
+
+ hbase.client.scanner.caching
+ {{ .HBASE_CLIENT_SCANNER_CACHING }}
+
+
+
+ hbase.hregion.max.filesize
+ {{ .HBASE_HREGION_MAX_FILESIZE }}
+
+
+
+ hbase.hregion.memstore.flush.size
+ {{ .HBASE_HREGION_MEMSTORE_FLUSH_SIZE }}
+
+
+
+ hbase.unsafe.stream.capability.enforce
+ false
+
+
+
+ hbase.procedure.store.wal.use.hsync
+ {{ .HBASE_PROCEDURE_STORE_WAL_USE_HSYNC }}
+
+
+
+ hbase.wal.provider
+ filesystem
+
+
+
+ hbase.replication
+ {{ .HBASE_REPLICATION_ENABLED }}
+
+
+
+ hbase.io.compress.lz4.codec
+ org.apache.hadoop.hbase.io.compress.lz4.Lz4Codec
+
+
+
+ hbase.security.authentication
+ {{ .HBASE_SECURITY_AUTHENTICATION }}
+
+
+
+ hbase.security.authorization
+ {{ .HBASE_SECURITY_AUTHORIZATION }}
+
+
diff --git a/addons/hbase/config/hdfs-client-site.tpl b/addons/hbase/config/hdfs-client-site.tpl
new file mode 100644
index 0000000000..a18aebc40d
--- /dev/null
+++ b/addons/hbase/config/hdfs-client-site.tpl
@@ -0,0 +1,53 @@
+
+
+
+
+
+ dfs.nameservices
+ {{- .HDFS_NAMESERVICE }}
+
+
+
+ dfs.ha.namenodes.{{- .HDFS_NAMESERVICE }}
+ {{- .HDFS_NAMENODE_NODES }}
+
+
+{{- $nodes := splitList "," .HDFS_NAMENODE_NODES }}
+{{- $rpcPort := .HDFS_NAMENODE_RPC_PORT }}
+{{- $httpPort := .HDFS_NAMENODE_HTTP_PORT }}
+{{- $ns := .HDFS_NAMESERVICE }}
+{{- $clusterDomain := .CLUSTER_DOMAIN }}
+{{- $namespace := .NAMESPACE }}
+{{- $headlessSvc := printf "%s-namenode-headless" $ns }}
+{{- range $nn := $nodes }}
+{{- $ordinal := trimPrefix "nn" $nn }}
+
+ dfs.namenode.rpc-address.{{ $ns }}.{{ $nn }}
+ {{ $ns }}-namenode-{{ $ordinal }}.{{ $headlessSvc }}.{{ $namespace }}.svc.{{ $clusterDomain }}:{{ $rpcPort }}
+
+
+ dfs.namenode.http-address.{{ $ns }}.{{ $nn }}
+ {{ $ns }}-namenode-{{ $ordinal }}.{{ $headlessSvc }}.{{ $namespace }}.svc.{{ $clusterDomain }}:{{ $httpPort }}
+
+{{- end }}
+
+
+ dfs.client.failover.proxy.provider.{{- .HDFS_NAMESERVICE }}
+ org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
+
+
+
+ dfs.replication
+ {{- .HDFS_REPLICATION }}
+
+
+
+ dfs.webhdfs.enabled
+ {{- .HDFS_WEBHDFS_ENABLED }}
+
+
+
+ dfs.permissions.enabled
+ {{- .HDFS_PERMISSIONS_ENABLED }}
+
+
diff --git a/addons/hbase/config/hdfs-common-site.tpl b/addons/hbase/config/hdfs-common-site.tpl
new file mode 100644
index 0000000000..a84043543b
--- /dev/null
+++ b/addons/hbase/config/hdfs-common-site.tpl
@@ -0,0 +1,78 @@
+
+
+
+
+ fs.defaultFS
+ hdfs://{{ .HDFS_NAMESERVICE }}
+
+
+
+ fs.trash.interval
+ {{ .HDFS_FS_TRASH_INTERVAL }}
+
+
+
+ io.compression.codecs
+ org.apache.hadoop.io.compress.GzipCodec,org.apache.hadoop.io.compress.DefaultCodec,org.apache.hadoop.io.compress.BZip2Codec,org.apache.hadoop.io.compress.SnappyCodec,org.apache.hadoop.hbase.io.compress.lz4.Lz4Codec
+
+
+
+ ha.zookeeper.quorum
+ {{ .ZOOKEEPER_ENDPOINTS }}
+
+
+
+ ha.zookeeper.parent-znode
+ {{ .HDFS_HA_ZK_PARENT }}
+
+
+
+ hadoop.http.staticuser.user
+ hbase
+
+
+
+ hadoop.security.authentication
+ {{ .HADOOP_SECURITY_AUTHENTICATION }}
+
+
+
+ hadoop.security.authorization
+ {{ .HADOOP_SECURITY_AUTHORIZATION }}
+
+
+
+ ipc.client.connection.maxidletime
+ {{ .HADOOP_IPC_CLIENT_CONNECTION_MAXIDLETIME }}
+
+
+
+ ipc.client.connect.timeout
+ {{ .HADOOP_IPC_CLIENT_CONNECT_TIMEOUT }}
+
+
+
+ ipc.client.ping
+ true
+
+
+
+ ipc.ping.interval
+ {{ .HADOOP_IPC_PING_INTERVAL }}
+
+
+
+ hadoop.tmp.dir
+ {{ .HADOOP_TMP_DIR }}
+
+
+
+ dfs.client.retry.policy.enabled
+ {{ .HDFS_COMMON_CLIENT_RETRY_POLICY_ENABLED }}
+
+
+
+ dfs.client.retry.policy.spec
+ {{ .HDFS_COMMON_CLIENT_RETRY_POLICY_SPEC }}
+
+
diff --git a/addons/hbase/config/log4j.properties b/addons/hbase/config/log4j.properties
new file mode 100644
index 0000000000..8266ee95a5
--- /dev/null
+++ b/addons/hbase/config/log4j.properties
@@ -0,0 +1,69 @@
+# 根日志配置
+log4j.rootLogger=INFO, console, RFA
+
+# 禁用某些包的日志
+log4j.logger.org.apache.zookeeper=WARN
+log4j.logger.org.apache.hadoop.hbase.zookeeper.RecoverableZooKeeper=WARN
+log4j.logger.org.apache.hadoop.hbase.zookeeper.ZKUtil=WARN
+log4j.logger.org.apache.hadoop.hbase.HBaseConfiguration=INFO
+
+# 控制台输出配置
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n
+
+# 日志文件输出配置 (Daily Rolling File Appender)
+log4j.appender.DRFA=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.DRFA.File=${hbase.log.dir}/${hbase.log.file}
+log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
+log4j.appender.DRFA.layout=org.apache.log4j.PatternLayout
+log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n
+
+# 安全审计日志配置
+log4j.logger.SecurityLogger=INFO,RFAS
+log4j.appender.RFAS=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.RFAS.File=${hbase.log.dir}/security.log
+log4j.appender.RFAS.layout=org.apache.log4j.PatternLayout
+log4j.appender.RFAS.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
+log4j.appender.RFAS.DatePattern=.yyyy-MM-dd
+
+# HBase UI 访问日志配置
+log4j.logger.http.requests.hbase=INFO,HRFA
+log4j.appender.HRFA=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.HRFA.File=${hbase.log.dir}/http-access.log
+log4j.appender.HRFA.layout=org.apache.log4j.PatternLayout
+log4j.appender.HRFA.layout.ConversionPattern=%t %h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"
+log4j.appender.HRFA.DatePattern=.yyyy-MM-dd
+
+# 特定组件日志级别配置
+log4j.logger.org.apache.hadoop.hbase.master=INFO
+log4j.logger.org.apache.hadoop.hbase.regionserver=INFO
+log4j.logger.org.apache.hadoop.hbase.client=INFO
+log4j.logger.org.apache.hadoop.hbase.replication=INFO
+log4j.logger.org.apache.hadoop.hbase.metrics=INFO
+
+# 性能相关日志配置
+log4j.logger.org.apache.hadoop.hbase.regionserver.HRegionServer=INFO
+log4j.logger.org.apache.hadoop.hbase.regionserver.CompactSplitThread=INFO
+log4j.logger.org.apache.hadoop.hbase.regionserver.MemStoreFlusher=INFO
+
+# 添加异步 Appender(提高性能)
+log4j.appender.ASYNC=org.apache.log4j.AsyncAppender
+log4j.appender.ASYNC.Blocking=false
+log4j.appender.ASYNC.BufferSize=10000
+log4j.appender.ASYNC.appenders=DRFA
+
+# 日志大小滚动配置
+log4j.appender.RFA=org.apache.log4j.RollingFileAppender
+log4j.appender.RFA.File=${hbase.log.dir}/${hbase.log.file}
+log4j.appender.RFA.MaxFileSize=256MB
+log4j.appender.RFA.MaxBackupIndex=20
+log4j.appender.RFA.layout=org.apache.log4j.PatternLayout
+log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n
+
+# 添加额外的调试信息(需要时取消注释)
+#log4j.logger.org.apache.hadoop.hbase=DEBUG
+#log4j.logger.org.apache.hadoop.hbase.regionserver.StoreFile=DEBUG
+#log4j.logger.org.apache.hadoop.hbase.regionserver.Region=DEBUG
+#log4j.logger.org.apache.hadoop.hbase.regionserver.HStore=DEBUG
diff --git a/addons/hbase/releases_notes.yaml b/addons/hbase/releases_notes.yaml
new file mode 100644
index 0000000000..ea44d0becc
--- /dev/null
+++ b/addons/hbase/releases_notes.yaml
@@ -0,0 +1,9 @@
+releases:
+- version: 1.1.0
+ released_at: '2026-05-21'
+ status: stable
+ git_branch: release-1.1
+ git_tag: v1.1.0
+ commit_sha: ''
+- version: 0.9.0
+ git_branch: release-0.9
\ No newline at end of file
diff --git a/addons/hbase/scripts/check-hmaster-status.sh b/addons/hbase/scripts/check-hmaster-status.sh
new file mode 100644
index 0000000000..2405184e65
--- /dev/null
+++ b/addons/hbase/scripts/check-hmaster-status.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+set -e
+
+HMASTER_INFO_PORT=${HMASTER_INFO_PORT:-16010}
+
+if jps 2>/dev/null | grep -q HMaster; then
+ exit 0
+fi
+
+if pgrep -f "org.apache.hadoop.hbase.master.HMaster" > /dev/null 2>&1; then
+ exit 0
+fi
+
+if curl -sf -o /dev/null "http://127.0.0.1:${HMASTER_INFO_PORT}/master-status" 2>/dev/null; then
+ exit 0
+fi
+
+exit 1
diff --git a/addons/hbase/scripts/check-hregionserver-status.sh b/addons/hbase/scripts/check-hregionserver-status.sh
new file mode 100644
index 0000000000..63063c5654
--- /dev/null
+++ b/addons/hbase/scripts/check-hregionserver-status.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+set -e
+
+REGIONSERVER_INFO_PORT=${REGIONSERVER_INFO_PORT:-16030}
+
+if jps 2>/dev/null | grep -q HRegionServer; then
+ exit 0
+fi
+
+if pgrep -f "org.apache.hadoop.hbase.regionserver.HRegionServer" > /dev/null 2>&1; then
+ exit 0
+fi
+
+if curl -sf -o /dev/null "http://127.0.0.1:${REGIONSERVER_INFO_PORT}/rs-status" 2>/dev/null; then
+ exit 0
+fi
+
+exit 1
diff --git a/addons/hbase/scripts/init-hdfs-root-layout.sh b/addons/hbase/scripts/init-hdfs-root-layout.sh
new file mode 100644
index 0000000000..193357664d
--- /dev/null
+++ b/addons/hbase/scripts/init-hdfs-root-layout.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+set -e
+
+source ${HBASE_CONF_DIR}/hbase-env.sh 2>/dev/null || true
+mkdir -p ${HBASE_LOG_DIR}
+
+echo "[$(date)] Initializing HBase root layout in HDFS..."
+
+PATHS=(
+ "/${HBASE_ROOT_DIR}"
+ "/${HBASE_ROOT_DIR}/WALs"
+ "/${HBASE_ROOT_DIR}/data"
+ "/${HBASE_ROOT_DIR}/archive"
+ "/${HBASE_ROOT_DIR}/.tmp"
+ "/${HBASE_ROOT_DIR}/MasterData"
+ "/${HBASE_ROOT_DIR}/MasterData/WALs"
+)
+
+for p in "${PATHS[@]}"; do
+ if timeout 30 ${HBASE_HOME}/bin/hbase org.apache.hadoop.fs.FsShell -test -e "${p}" 2>/dev/null; then
+ echo "[$(date)] Path ${p} already exists, skipping."
+ else
+ echo "[$(date)] Creating ${p}..."
+ timeout 30 ${HBASE_HOME}/bin/hbase org.apache.hadoop.fs.FsShell -mkdir -p "${p}" || true
+ fi
+done
+
+echo "[$(date)] HBase root layout initialized."
diff --git a/addons/hbase/scripts/start-hmaster.sh b/addons/hbase/scripts/start-hmaster.sh
new file mode 100644
index 0000000000..a54a0f8c12
--- /dev/null
+++ b/addons/hbase/scripts/start-hmaster.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+
+source ${HBASE_CONF_DIR}/hbase-env.sh 2>/dev/null || true
+mkdir -p ${HBASE_LOG_DIR} ${HBASE_PID_DIR}
+
+function shutdown() {
+ echo "[$(date)] Stopping HMaster gracefully..."
+ ${HBASE_HOME}/bin/hbase-daemon.sh stop master || true
+ echo "[$(date)] HMaster stopped."
+}
+
+trap shutdown SIGTERM SIGINT
+
+${HBASE_HOME}/bin/hbase master start &
+master_pid=$!
+wait $master_pid
diff --git a/addons/hbase/scripts/start-hregionserver.sh b/addons/hbase/scripts/start-hregionserver.sh
new file mode 100644
index 0000000000..4b29f87ef7
--- /dev/null
+++ b/addons/hbase/scripts/start-hregionserver.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+set -e
+
+source ${HBASE_CONF_DIR}/hbase-env.sh 2>/dev/null || true
+mkdir -p ${HBASE_LOG_DIR} ${HBASE_PID_DIR}
+
+function shutdown() {
+ echo "[$(date)] Stopping RegionServer gracefully..."
+ host=$(hostname -f 2>/dev/null || hostname)
+ export HBASE_STOP_TIMEOUT=20
+
+ echo "[$(date)] Disabling balancer before region unload..."
+ echo "balance_switch false" | ${HBASE_HOME}/bin/hbase shell 2>/dev/null || true
+
+ echo "[$(date)] Unloading regions from ${host}..."
+ ${HBASE_HOME}/bin/hbase org.apache.hadoop.hbase.util.RegionMover -m 6 -r ${host} -o unload 2>&1 || true
+
+ sleep 5
+
+ echo "[$(date)] Re-enabling balancer..."
+ echo "balance_switch true" | ${HBASE_HOME}/bin/hbase shell 2>/dev/null || true
+
+ echo "[$(date)] Stopping RegionServer daemon..."
+ ${HBASE_HOME}/bin/hbase-daemon.sh stop regionserver || true
+ echo "[$(date)] RegionServer stopped."
+}
+
+trap shutdown SIGTERM SIGINT
+
+${HBASE_HOME}/bin/hbase regionserver start &
+rs_pid=$!
+wait $rs_pid
diff --git a/addons/hbase/templates/_helpers.tpl b/addons/hbase/templates/_helpers.tpl
new file mode 100644
index 0000000000..02c59b357d
--- /dev/null
+++ b/addons/hbase/templates/_helpers.tpl
@@ -0,0 +1,74 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "hbase.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "hbase.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "hbase.labels" -}}
+helm.sh/chart: {{ include "hbase.chart" . }}
+{{ include "hbase.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "hbase.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "hbase.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+API version annotation
+*/}}
+{{- define "hbase.apiVersion" -}}
+kubeblocks.io/crd-api-version: apps.kubeblocks.io/v1
+{{- end }}
+
+{{/*
+Component definition regex patterns
+*/}}
+{{- define "hbase.hmasterCmpdRegexPattern" -}}
+^hbase-hmaster-\d+\.?\d*$
+{{- end }}
+
+{{- define "hbase.hregionserverCmpdRegexPattern" -}}
+^hbase-hregionserver-\d+\.?\d*$
+{{- end }}
+
+{{- define "hbase.hbaseStandaloneCmpdRegexPattern" -}}
+^hbase-standalone-\d+\.?\d*$
+{{- end }}
+
+{{/*
+Image references
+*/}}
+{{- define "hbase.hmasterImage" -}}
+{{ .Values.hmaster.image.registry }}/{{ .Values.hmaster.image.repository }}:{{ .Values.hmaster.image.tag }}
+{{- end }}
+
+{{- define "hbase.hregionserverImage" -}}
+{{ .Values.hregionserver.image.registry }}/{{ .Values.hregionserver.image.repository }}:{{ .Values.hregionserver.image.tag }}
+{{- end }}
+
+{{- define "hbase.hbaseStandaloneImage" -}}
+{{ .Values.hbasestandalone.image.registry }}/{{ .Values.hbasestandalone.image.repository }}:{{ .Values.hbasestandalone.image.tag }}
+{{- end }}
+
+{{- define "hbase.jmxExporterImage" -}}
+{{ .Values.images.jmxExporter.registry }}/{{ .Values.images.jmxExporter.repository }}:{{ .Values.images.jmxExporter.tag }}
+{{- end }}
diff --git a/addons/hbase/templates/clusterdefinition.yaml b/addons/hbase/templates/clusterdefinition.yaml
new file mode 100644
index 0000000000..3b291e89c8
--- /dev/null
+++ b/addons/hbase/templates/clusterdefinition.yaml
@@ -0,0 +1,31 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ClusterDefinition
+metadata:
+ name: hbase
+ labels:
+ {{- include "hbase.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hbase.apiVersion" . | nindent 4 }}
+spec:
+ topologies:
+ - name: cluster
+ default: true
+ components:
+ - name: hmaster
+ compDef: {{ include "hbase.hmasterCmpdRegexPattern" . }}
+ - name: hregionserver
+ compDef: {{ include "hbase.hregionserverCmpdRegexPattern" . }}
+ orders:
+ provision:
+ - hmaster
+ - hregionserver
+ terminate:
+ - hregionserver
+ - hmaster
+ update:
+ - hregionserver
+ - hmaster
+ - name: standalone
+ components:
+ - name: hbase-standalone
+ compDef: {{ include "hbase.hbaseStandaloneCmpdRegexPattern" . }}
diff --git a/addons/hbase/templates/cmpd-hbase-standalone.yaml b/addons/hbase/templates/cmpd-hbase-standalone.yaml
new file mode 100644
index 0000000000..d626203931
--- /dev/null
+++ b/addons/hbase/templates/cmpd-hbase-standalone.yaml
@@ -0,0 +1,215 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentDefinition
+metadata:
+ name: hbase-standalone-2.5
+ labels:
+ {{- include "hbase.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hbase.apiVersion" . | nindent 4 }}
+spec:
+ provider: kubeblocks
+ description: {{ .Chart.Description }}
+ serviceKind: hbase-standalone
+ serviceVersion: 2.5.6
+ updateStrategy: BestEffortParallel
+ exporter:
+ containerName: jmx-exporter
+ scrapePath: /metrics
+ services:
+ - name: default
+ spec:
+ ports:
+ - name: hmaster
+ port: {{ .Values.ports.hmaster.rpc }}
+ - name: http
+ port: {{ .Values.ports.hmaster.info }}
+ - name: hregionserver
+ port: {{ .Values.ports.hregionserver.rpc }}
+ - name: rs-http
+ port: {{ .Values.ports.hregionserver.info }}
+ serviceRefDeclarations:
+ - name: hbase-zookeeper
+ serviceRefDeclarationSpecs:
+ - serviceKind: zookeeper
+ serviceVersion: "^*"
+ runtime:
+ terminationGracePeriodSeconds: 120
+ containers:
+ - name: hbase-standalone
+ imagePullPolicy: {{ default "IfNotPresent" .Values.hbasestandalone.image.pullPolicy }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/start-hmaster.sh
+ env:
+ - name: HBASE_CONF_DIR
+ value: {{ .Values.runtime.hbaseConfDir }}
+ - name: HBASE_HOME
+ value: {{ .Values.runtime.hbaseHome }}
+ - name: HBASE_LOG_DIR
+ value: {{ .Values.runtime.hbaseLogDir }}
+ - name: HBASE_PID_DIR
+ value: {{ .Values.runtime.hbasePidDir }}
+ - name: HMASTER_INFO_PORT
+ value: {{ .Values.ports.hmaster.info | quote }}
+ ports:
+ - containerPort: {{ .Values.ports.hmaster.rpc }}
+ name: hmaster
+ - containerPort: {{ .Values.ports.hmaster.info }}
+ name: http
+ - containerPort: {{ .Values.ports.hregionserver.rpc }}
+ name: hregionserver
+ - containerPort: {{ .Values.ports.hregionserver.info }}
+ name: rs-http
+ startupProbe:
+ failureThreshold: 30
+ initialDelaySeconds: 30
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-hmaster-status.sh
+ livenessProbe:
+ failureThreshold: 6
+ initialDelaySeconds: 60
+ periodSeconds: 30
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-hmaster-status.sh
+ readinessProbe:
+ failureThreshold: 6
+ initialDelaySeconds: 20
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-hmaster-status.sh
+ volumeMounts:
+ - name: hbase-standalone-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/hbase-site.xml
+ subPath: hbase-site.xml
+ - name: hbase-standalone-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/hbase-env.sh
+ subPath: hbase-env.sh
+ - name: hbase-standalone-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/log4j.properties
+ subPath: log4j.properties
+ - name: hbase-scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ - name: data
+ mountPath: {{ .Values.runtime.hbaseDataDir }}
+ - name: hbase-logs
+ mountPath: {{ .Values.runtime.hbaseLogDir }}
+ - name: hbase-tmp
+ mountPath: {{ .Values.runtime.hbaseTmpDir }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ runAsNonRoot: {{ .Values.securityContext.runAsNonRoot }}
+ privileged: false
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: [ "ALL" ]
+ seccompProfile:
+ type: "RuntimeDefault"
+ - name: jmx-exporter
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsNonRoot: {{ .Values.exporter.securityContext.runAsNonRoot }}
+ runAsUser: {{ .Values.exporter.securityContext.runAsUser }}
+ command:
+ - java
+ args:
+ - -XX:MaxRAMPercentage=100
+ - -XshowSettings:vm
+ - -jar
+ - jmx_prometheus_httpserver.jar
+ - {{ .Values.jmxExporter.port | quote }}
+ - /etc/jmx-exporter/hbase-jmx-exporter.yaml
+ ports:
+ - name: http-metrics
+ containerPort: {{ .Values.jmxExporter.port }}
+ volumeMounts:
+ - name: hbase-standalone-config
+ mountPath: /etc/jmx-exporter/hbase-jmx-exporter.yaml
+ subPath: hbase-jmx-exporter.yaml
+ securityContext:
+ fsGroupChangePolicy: Always
+ fsGroup: {{ .Values.securityContext.fsGroup }}
+ volumes:
+ - name: hbase-logs
+ emptyDir: {}
+ - name: hbase-tmp
+ emptyDir: {}
+ vars:
+ - name: CLUSTER_NAME
+ valueFrom:
+ clusterVarRef:
+ clusterName: Required
+ - name: NAMESPACE
+ valueFrom:
+ clusterVarRef:
+ namespace: Required
+ - name: CLUSTER_DOMAIN
+ value: {{ .Values.extra.clusterDomain }}
+ - name: HBASE_CONF_DIR
+ value: {{ .Values.runtime.hbaseConfDir }}
+ - name: HBASE_LOG_DIR
+ value: {{ .Values.runtime.hbaseLogDir }}
+ - name: HBASE_PID_DIR
+ value: {{ .Values.runtime.hbasePidDir }}
+ - name: HBASE_TMP_DIR
+ value: {{ .Values.runtime.hbaseTmpDir }}
+ - name: HBASE_DATA_DIR
+ value: {{ .Values.runtime.hbaseDataDir }}
+ - name: HADOOP_NATIVE_LIB_PATH
+ value: {{ .Values.runtime.hadoopNativeLibPath }}
+ - name: HBASE_MASTER_HEAP_SIZE
+ value: {{ .Values.jvm.hbasestandaloneHeapSize | quote }}
+ - name: HBASE_JMX_PORT
+ value: {{ .Values.ports.hmaster.jmx | quote }}
+ - name: HBASE_REGIONSERVER_HEAP_SIZE
+ value: {{ .Values.jvm.hbasestandaloneHeapSize | quote }}
+ - name: HBASE_MASTER_JMX_PORT
+ value: {{ .Values.ports.hmaster.jmx | quote }}
+ - name: HBASE_MASTER_PORT
+ value: {{ .Values.ports.hmaster.rpc | quote }}
+ - name: HBASE_MASTER_INFO_PORT
+ value: {{ .Values.ports.hmaster.info | quote }}
+ - name: HBASE_REGIONSERVER_PORT
+ value: {{ .Values.ports.hregionserver.rpc | quote }}
+ - name: HBASE_REGIONSERVER_INFO_PORT
+ value: {{ .Values.ports.hregionserver.info | quote }}
+ - name: HBASE_REGIONSERVER_JMX_PORT
+ value: {{ .Values.ports.hregionserver.jmx | quote }}
+ - name: HBASE_HEAP_SIZE
+ value: {{ .Values.jvm.hbasestandaloneHeapSize | quote }}
+ - name: ZOOKEEPER_QUORUM
+ valueFrom:
+ serviceRefVarRef:
+ name: hbase-zookeeper
+ host: Required
+ - name: ZOOKEEPER_CLIENT_PORT
+ value: {{ .Values.hbase.zkClientPort | quote }}
+ - name: ZOOKEEPER_ENDPOINTS
+ valueFrom:
+ serviceRefVarRef:
+ name: hbase-zookeeper
+ endpoint: Required
+ - name: HBASE_ZK_PARENT
+ value: {{ .Values.hbase.zkParent | quote }}
+ configs:
+ - name: hbase-standalone-config
+ template: hbase-standalone-config-template
+ volumeName: hbase-standalone-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: 0755
+ scripts:
+ - name: hbase-scripts
+ template: hbase-scripts
+ volumeName: hbase-scripts
+ namespace: {{ .Release.Namespace }}
+ defaultMode: 0755
diff --git a/addons/hbase/templates/cmpd-hmaster.yaml b/addons/hbase/templates/cmpd-hmaster.yaml
new file mode 100644
index 0000000000..c206f6ff8b
--- /dev/null
+++ b/addons/hbase/templates/cmpd-hmaster.yaml
@@ -0,0 +1,273 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentDefinition
+metadata:
+ name: hbase-hmaster-2.5
+ labels:
+ {{- include "hbase.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hbase.apiVersion" . | nindent 4 }}
+spec:
+ provider: kubeblocks
+ description: {{ .Chart.Description }}
+ serviceKind: hbase-hmaster
+ serviceVersion: 2.5.6
+ updateStrategy: BestEffortParallel
+ exporter:
+ containerName: jmx-exporter
+ scrapePath: /metrics
+ services:
+ - name: default
+ spec:
+ ports:
+ - name: hmaster
+ port: {{ .Values.ports.hmaster.rpc }}
+ - name: http
+ port: {{ .Values.ports.hmaster.info }}
+ serviceRefDeclarations:
+ - name: hbase-zookeeper
+ serviceRefDeclarationSpecs:
+ - serviceKind: zookeeper
+ serviceVersion: "^*"
+ - name: hdfs-namenode
+ serviceRefDeclarationSpecs:
+ - serviceKind: hdfs-namenode
+ serviceVersion: "^*"
+ runtime:
+ terminationGracePeriodSeconds: 120
+ initContainers:
+ - name: init-hdfs-root-layout
+ imagePullPolicy: {{ default "IfNotPresent" .Values.hmaster.image.pullPolicy }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ env:
+ - name: HBASE_CONF_DIR
+ value: {{ .Values.runtime.hbaseConfDir }}
+ - name: HBASE_HOME
+ value: {{ .Values.runtime.hbaseHome }}
+ - name: HBASE_LOG_DIR
+ value: {{ .Values.runtime.hbaseLogDir }}
+ - name: HBASE_ROOT_DIR
+ value: {{ .Values.hbase.rootDir }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/init-hdfs-root-layout.sh
+ volumeMounts:
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/hbase-site.xml
+ subPath: hbase-site.xml
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/hbase-env.sh
+ subPath: hbase-env.sh
+ - name: hbase-scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ - name: hbase-logs
+ mountPath: {{ .Values.runtime.hbaseLogDir }}
+ - name: hbase-tmp
+ mountPath: {{ .Values.runtime.hbaseTmpDir }}
+ containers:
+ - name: hbase-hmaster
+ imagePullPolicy: {{ default "IfNotPresent" .Values.hmaster.image.pullPolicy }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/start-hmaster.sh
+ env:
+ - name: HBASE_CONF_DIR
+ value: {{ .Values.runtime.hbaseConfDir }}
+ - name: HADOOP_CONF_DIR
+ value: {{ .Values.runtime.hbaseConfDir }}
+ - name: HBASE_HOME
+ value: {{ .Values.runtime.hbaseHome }}
+ - name: HBASE_LOG_DIR
+ value: {{ .Values.runtime.hbaseLogDir }}
+ - name: HBASE_PID_DIR
+ value: {{ .Values.runtime.hbasePidDir }}
+ - name: HMASTER_INFO_PORT
+ value: {{ .Values.ports.hmaster.info | quote }}
+ ports:
+ - containerPort: {{ .Values.ports.hmaster.rpc }}
+ name: hmaster
+ - containerPort: {{ .Values.ports.hmaster.info }}
+ name: http
+ startupProbe:
+ failureThreshold: 30
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-hmaster-status.sh
+ livenessProbe:
+ failureThreshold: 6
+ initialDelaySeconds: 120
+ periodSeconds: 30
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-hmaster-status.sh
+ readinessProbe:
+ failureThreshold: 6
+ initialDelaySeconds: 30
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-hmaster-status.sh
+ volumeMounts:
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/hbase-site.xml
+ subPath: hbase-site.xml
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/hbase-env.sh
+ subPath: hbase-env.sh
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/log4j.properties
+ subPath: log4j.properties
+ - name: hbase-scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ - name: hbase-logs
+ mountPath: {{ .Values.runtime.hbaseLogDir }}
+ - name: hbase-tmp
+ mountPath: {{ .Values.runtime.hbaseTmpDir }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ runAsNonRoot: {{ .Values.securityContext.runAsNonRoot }}
+ privileged: false
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: [ "ALL" ]
+ seccompProfile:
+ type: "RuntimeDefault"
+ - name: jmx-exporter
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsNonRoot: {{ .Values.exporter.securityContext.runAsNonRoot }}
+ runAsUser: {{ .Values.exporter.securityContext.runAsUser }}
+ command:
+ - java
+ args:
+ - -XX:MaxRAMPercentage=100
+ - -XshowSettings:vm
+ - -jar
+ - jmx_prometheus_httpserver.jar
+ - {{ .Values.jmxExporter.port | quote }}
+ - /etc/jmx-exporter/hbase-jmx-exporter.yaml
+ ports:
+ - name: http-metrics
+ containerPort: {{ .Values.jmxExporter.port }}
+ volumeMounts:
+ - name: hbase-config
+ mountPath: /etc/jmx-exporter/hbase-jmx-exporter.yaml
+ subPath: hbase-jmx-exporter.yaml
+ securityContext:
+ fsGroupChangePolicy: Always
+ fsGroup: {{ .Values.securityContext.fsGroup }}
+ volumes:
+ - name: hbase-logs
+ emptyDir: {}
+ - name: hbase-tmp
+ emptyDir: {}
+ vars:
+ - name: CLUSTER_NAME
+ valueFrom:
+ clusterVarRef:
+ clusterName: Required
+ - name: NAMESPACE
+ valueFrom:
+ clusterVarRef:
+ namespace: Required
+ - name: CLUSTER_DOMAIN
+ value: {{ .Values.extra.clusterDomain }}
+ - name: HBASE_CONF_DIR
+ value: {{ .Values.runtime.hbaseConfDir }}
+ - name: HBASE_LOG_DIR
+ value: {{ .Values.runtime.hbaseLogDir }}
+ - name: HBASE_PID_DIR
+ value: {{ .Values.runtime.hbasePidDir }}
+ - name: HBASE_TMP_DIR
+ value: {{ .Values.runtime.hbaseTmpDir }}
+ - name: HADOOP_NATIVE_LIB_PATH
+ value: {{ .Values.runtime.hadoopNativeLibPath }}
+ - name: HBASE_MASTER_HEAP_SIZE
+ value: {{ .Values.jvm.hmasterHeapSize | quote }}
+ - name: HBASE_JMX_PORT
+ value: {{ .Values.ports.hmaster.jmx | quote }}
+ - name: HBASE_REGIONSERVER_HEAP_SIZE
+ value: {{ .Values.jvm.hregionserverHeapSize | quote }}
+ - name: HBASE_MASTER_JMX_PORT
+ value: {{ .Values.ports.hmaster.jmx | quote }}
+ - name: HBASE_MASTER_PORT
+ value: {{ .Values.ports.hmaster.rpc | quote }}
+ - name: HBASE_MASTER_INFO_PORT
+ value: {{ .Values.ports.hmaster.info | quote }}
+ - name: HBASE_REGIONSERVER_PORT
+ value: {{ .Values.ports.hregionserver.rpc | quote }}
+ - name: HBASE_REGIONSERVER_INFO_PORT
+ value: {{ .Values.ports.hregionserver.info | quote }}
+ - name: HBASE_REGIONSERVER_JMX_PORT
+ value: {{ .Values.ports.hregionserver.jmx | quote }}
+ - name: HBASE_HEAP_SIZE
+ value: {{ .Values.jvm.hmasterHeapSize | quote }}
+ - name: ZOOKEEPER_QUORUM
+ valueFrom:
+ serviceRefVarRef:
+ name: hbase-zookeeper
+ host: Required
+ - name: ZOOKEEPER_CLIENT_PORT
+ value: {{ .Values.hbase.zkClientPort | quote }}
+ - name: ZOOKEEPER_ENDPOINTS
+ valueFrom:
+ serviceRefVarRef:
+ name: hbase-zookeeper
+ endpoint: Required
+ - name: HBASE_ROOT_DIR
+ value: {{ .Values.hbase.rootDir | quote }}
+ - name: HBASE_ZK_PARENT
+ value: {{ .Values.hbase.zkParent | quote }}
+ - name: HDFS_NAMESERVICE
+ value: {{ .Values.hdfs.nameservice | quote }}
+ - name: HDFS_NAMENODE_NODES
+ value: {{ .Values.hdfs.namenodeNodes | quote }}
+ - name: HDFS_NAMENODE_RPC_PORT
+ value: {{ .Values.hdfs.namenodeRpcPort | quote }}
+ - name: HDFS_NAMENODE_HTTP_PORT
+ value: {{ .Values.hdfs.namenodeHttpPort | quote }}
+ - name: HDFS_HA_ZK_PARENT
+ value: {{ .Values.hdfs.haZkParent | quote }}
+ - name: HDFS_REPLICATION
+ value: {{ .Values.hdfs.replication | quote }}
+ - name: HDFS_PERMISSIONS_ENABLED
+ value: "false"
+ - name: POD_FQDN
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.annotations['kubeblocks.io/pod-fqdn']
+ apiVersion: v1
+ configs:
+ - name: hbase-config
+ template: hbase-cluster-config-template
+ volumeName: hbase-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: 0755
+ scripts:
+ - name: hbase-scripts
+ template: hbase-scripts
+ volumeName: hbase-scripts
+ namespace: {{ .Release.Namespace }}
+ defaultMode: 0755
diff --git a/addons/hbase/templates/cmpd-hregionserver.yaml b/addons/hbase/templates/cmpd-hregionserver.yaml
new file mode 100644
index 0000000000..c7af573ca4
--- /dev/null
+++ b/addons/hbase/templates/cmpd-hregionserver.yaml
@@ -0,0 +1,236 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentDefinition
+metadata:
+ name: hbase-hregionserver-2.5
+ labels:
+ {{- include "hbase.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hbase.apiVersion" . | nindent 4 }}
+spec:
+ provider: kubeblocks
+ description: {{ .Chart.Description }}
+ serviceKind: hbase-hregionserver
+ serviceVersion: 2.5.6
+ updateStrategy: BestEffortParallel
+ exporter:
+ containerName: jmx-exporter
+ scrapePath: /metrics
+ services:
+ - name: default
+ spec:
+ ports:
+ - name: hregionserver
+ port: {{ .Values.ports.hregionserver.rpc }}
+ - name: http
+ port: {{ .Values.ports.hregionserver.info }}
+ serviceRefDeclarations:
+ - name: hbase-zookeeper
+ serviceRefDeclarationSpecs:
+ - serviceKind: zookeeper
+ serviceVersion: "^*"
+ - name: hdfs-namenode
+ serviceRefDeclarationSpecs:
+ - serviceKind: hdfs-namenode
+ serviceVersion: "^*"
+ runtime:
+ terminationGracePeriodSeconds: 300
+ containers:
+ - name: hbase-hregionserver
+ imagePullPolicy: {{ default "IfNotPresent" .Values.hregionserver.image.pullPolicy }}
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/start-hregionserver.sh
+ env:
+ - name: HBASE_CONF_DIR
+ value: {{ .Values.runtime.hbaseConfDir }}
+ - name: HADOOP_CONF_DIR
+ value: {{ .Values.runtime.hbaseConfDir }}
+ - name: HBASE_HOME
+ value: {{ .Values.runtime.hbaseHome }}
+ - name: HBASE_LOG_DIR
+ value: {{ .Values.runtime.hbaseLogDir }}
+ - name: HBASE_PID_DIR
+ value: {{ .Values.runtime.hbasePidDir }}
+ - name: REGIONSERVER_INFO_PORT
+ value: {{ .Values.ports.hregionserver.info | quote }}
+ ports:
+ - containerPort: {{ .Values.ports.hregionserver.rpc }}
+ name: hregionserver
+ - containerPort: {{ .Values.ports.hregionserver.info }}
+ name: http
+ startupProbe:
+ failureThreshold: 30
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-hregionserver-status.sh
+ livenessProbe:
+ failureThreshold: 6
+ initialDelaySeconds: 120
+ periodSeconds: 30
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-hregionserver-status.sh
+ readinessProbe:
+ failureThreshold: 6
+ initialDelaySeconds: 30
+ periodSeconds: 10
+ timeoutSeconds: 5
+ exec:
+ command:
+ - /bin/bash
+ - {{ .Values.runtime.scriptsDir }}/check-hregionserver-status.sh
+ volumeMounts:
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/hbase-site.xml
+ subPath: hbase-site.xml
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/core-site.xml
+ subPath: core-site.xml
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/hdfs-site.xml
+ subPath: hdfs-site.xml
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/hbase-env.sh
+ subPath: hbase-env.sh
+ - name: hbase-config
+ mountPath: {{ .Values.runtime.hbaseConfDir }}/log4j.properties
+ subPath: log4j.properties
+ - name: hbase-scripts
+ mountPath: {{ .Values.runtime.scriptsDir }}
+ - name: hbase-logs
+ mountPath: {{ .Values.runtime.hbaseLogDir }}
+ - name: hbase-tmp
+ mountPath: {{ .Values.runtime.hbaseTmpDir }}
+ securityContext:
+ runAsUser: {{ .Values.securityContext.runAsUser }}
+ runAsGroup: {{ .Values.securityContext.runAsGroup }}
+ runAsNonRoot: {{ .Values.securityContext.runAsNonRoot }}
+ privileged: false
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: [ "ALL" ]
+ seccompProfile:
+ type: "RuntimeDefault"
+ - name: jmx-exporter
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ runAsNonRoot: {{ .Values.exporter.securityContext.runAsNonRoot }}
+ runAsUser: {{ .Values.exporter.securityContext.runAsUser }}
+ command:
+ - java
+ args:
+ - -XX:MaxRAMPercentage=100
+ - -XshowSettings:vm
+ - -jar
+ - jmx_prometheus_httpserver.jar
+ - {{ .Values.jmxExporter.port | quote }}
+ - /etc/jmx-exporter/hbase-jmx-exporter.yaml
+ ports:
+ - name: http-metrics
+ containerPort: {{ .Values.jmxExporter.port }}
+ volumeMounts:
+ - name: hbase-config
+ mountPath: /etc/jmx-exporter/hbase-jmx-exporter.yaml
+ subPath: hbase-jmx-exporter.yaml
+ securityContext:
+ fsGroupChangePolicy: Always
+ fsGroup: {{ .Values.securityContext.fsGroup }}
+ volumes:
+ - name: hbase-logs
+ emptyDir: {}
+ - name: hbase-tmp
+ emptyDir: {}
+ vars:
+ - name: CLUSTER_NAME
+ valueFrom:
+ clusterVarRef:
+ clusterName: Required
+ - name: NAMESPACE
+ valueFrom:
+ clusterVarRef:
+ namespace: Required
+ - name: CLUSTER_DOMAIN
+ value: {{ .Values.extra.clusterDomain }}
+ - name: HBASE_CONF_DIR
+ value: {{ .Values.runtime.hbaseConfDir }}
+ - name: HBASE_LOG_DIR
+ value: {{ .Values.runtime.hbaseLogDir }}
+ - name: HBASE_PID_DIR
+ value: {{ .Values.runtime.hbasePidDir }}
+ - name: HBASE_TMP_DIR
+ value: {{ .Values.runtime.hbaseTmpDir }}
+ - name: HADOOP_NATIVE_LIB_PATH
+ value: {{ .Values.runtime.hadoopNativeLibPath }}
+ - name: HBASE_MASTER_HEAP_SIZE
+ value: {{ .Values.jvm.hmasterHeapSize | quote }}
+ - name: HBASE_JMX_PORT
+ value: {{ .Values.ports.hregionserver.jmx | quote }}
+ - name: HBASE_REGIONSERVER_HEAP_SIZE
+ value: {{ .Values.jvm.hregionserverHeapSize | quote }}
+ - name: HBASE_MASTER_JMX_PORT
+ value: {{ .Values.ports.hmaster.jmx | quote }}
+ - name: HBASE_MASTER_PORT
+ value: {{ .Values.ports.hmaster.rpc | quote }}
+ - name: HBASE_MASTER_INFO_PORT
+ value: {{ .Values.ports.hmaster.info | quote }}
+ - name: HBASE_REGIONSERVER_PORT
+ value: {{ .Values.ports.hregionserver.rpc | quote }}
+ - name: HBASE_REGIONSERVER_INFO_PORT
+ value: {{ .Values.ports.hregionserver.info | quote }}
+ - name: HBASE_REGIONSERVER_JMX_PORT
+ value: {{ .Values.ports.hregionserver.jmx | quote }}
+ - name: HBASE_HEAP_SIZE
+ value: {{ .Values.jvm.hregionserverHeapSize | quote }}
+ - name: ZOOKEEPER_QUORUM
+ valueFrom:
+ serviceRefVarRef:
+ name: hbase-zookeeper
+ host: Required
+ - name: ZOOKEEPER_CLIENT_PORT
+ value: {{ .Values.hbase.zkClientPort | quote }}
+ - name: ZOOKEEPER_ENDPOINTS
+ valueFrom:
+ serviceRefVarRef:
+ name: hbase-zookeeper
+ endpoint: Required
+ - name: HBASE_ROOT_DIR
+ value: {{ .Values.hbase.rootDir | quote }}
+ - name: HBASE_ZK_PARENT
+ value: {{ .Values.hbase.zkParent | quote }}
+ - name: HDFS_NAMESERVICE
+ value: {{ .Values.hdfs.nameservice | quote }}
+ - name: HDFS_NAMENODE_NODES
+ value: {{ .Values.hdfs.namenodeNodes | quote }}
+ - name: HDFS_NAMENODE_RPC_PORT
+ value: {{ .Values.hdfs.namenodeRpcPort | quote }}
+ - name: HDFS_NAMENODE_HTTP_PORT
+ value: {{ .Values.hdfs.namenodeHttpPort | quote }}
+ - name: HDFS_HA_ZK_PARENT
+ value: {{ .Values.hdfs.haZkParent | quote }}
+ - name: HDFS_REPLICATION
+ value: {{ .Values.hdfs.replication | quote }}
+ - name: HDFS_PERMISSIONS_ENABLED
+ value: "false"
+ - name: POD_FQDN
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.annotations['kubeblocks.io/pod-fqdn']
+ apiVersion: v1
+ configs:
+ - name: hbase-config
+ template: hbase-cluster-config-template
+ volumeName: hbase-config
+ namespace: {{ .Release.Namespace }}
+ defaultMode: 0755
+ scripts:
+ - name: hbase-scripts
+ template: hbase-scripts
+ volumeName: hbase-scripts
+ namespace: {{ .Release.Namespace }}
+ defaultMode: 0755
diff --git a/addons/hbase/templates/cmpv-hbase-standalone.yaml b/addons/hbase/templates/cmpv-hbase-standalone.yaml
new file mode 100644
index 0000000000..31eb225a42
--- /dev/null
+++ b/addons/hbase/templates/cmpv-hbase-standalone.yaml
@@ -0,0 +1,20 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentVersion
+metadata:
+ name: hbase-standalone
+ labels:
+ {{- include "hbase.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hbase.apiVersion" . | nindent 4 }}
+spec:
+ compatibilityRules:
+ - compDefs:
+ - hbase-standalone-2.5
+ releases:
+ - 2.5.6
+ releases:
+ - name: 2.5.6
+ serviceVersion: 2.5.6
+ images:
+ hbase-standalone: {{ include "hbase.hbaseStandaloneImage" . | quote }}
+ jmx-exporter: {{ include "hbase.jmxExporterImage" . | quote }}
diff --git a/addons/hbase/templates/cmpv-hmaster.yaml b/addons/hbase/templates/cmpv-hmaster.yaml
new file mode 100644
index 0000000000..e6c321c859
--- /dev/null
+++ b/addons/hbase/templates/cmpv-hmaster.yaml
@@ -0,0 +1,21 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentVersion
+metadata:
+ name: hbase-hmaster
+ labels:
+ {{- include "hbase.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hbase.apiVersion" . | nindent 4 }}
+spec:
+ compatibilityRules:
+ - compDefs:
+ - hbase-hmaster-2.5
+ releases:
+ - 2.5.6
+ releases:
+ - name: 2.5.6
+ serviceVersion: 2.5.6
+ images:
+ init-hdfs-root-layout: {{ include "hbase.hmasterImage" . | quote }}
+ hbase-hmaster: {{ include "hbase.hmasterImage" . | quote }}
+ jmx-exporter: {{ include "hbase.jmxExporterImage" . | quote }}
diff --git a/addons/hbase/templates/cmpv-hregionserver.yaml b/addons/hbase/templates/cmpv-hregionserver.yaml
new file mode 100644
index 0000000000..01970cc976
--- /dev/null
+++ b/addons/hbase/templates/cmpv-hregionserver.yaml
@@ -0,0 +1,20 @@
+apiVersion: apps.kubeblocks.io/v1
+kind: ComponentVersion
+metadata:
+ name: hbase-hregionserver
+ labels:
+ {{- include "hbase.labels" . | nindent 4 }}
+ annotations:
+ {{- include "hbase.apiVersion" . | nindent 4 }}
+spec:
+ compatibilityRules:
+ - compDefs:
+ - hbase-hregionserver-2.5
+ releases:
+ - 2.5.6
+ releases:
+ - name: 2.5.6
+ serviceVersion: 2.5.6
+ images:
+ hbase-hregionserver: {{ include "hbase.hregionserverImage" . | quote }}
+ jmx-exporter: {{ include "hbase.jmxExporterImage" . | quote }}
diff --git a/addons/hbase/templates/hbase-cluster-config-template.yaml b/addons/hbase/templates/hbase-cluster-config-template.yaml
new file mode 100644
index 0000000000..6409b7284f
--- /dev/null
+++ b/addons/hbase/templates/hbase-cluster-config-template.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: hbase-cluster-config-template
+ labels:
+ {{- include "hbase.labels" . | nindent 4 }}
+data:
+ hbase-site.xml: |-
+ {{- .Files.Get "config/hbase-site-cluster.tpl" | nindent 4 }}
+ core-site.xml: |-
+ {{- .Files.Get "config/hdfs-common-site.tpl" | nindent 4 }}
+ hdfs-site.xml: |-
+ {{- .Files.Get "config/hdfs-client-site.tpl" | nindent 4 }}
+ hbase-env.sh: |-
+ {{- .Files.Get "config/hbase-env.sh.tpl" | nindent 4 }}
+ hbase-jmx-exporter.yaml: |-
+ {{- .Files.Get "config/hbase-jmx-exporter.yaml.tpl" | nindent 4 }}
+ log4j.properties: |-
+ {{- .Files.Get "config/log4j.properties" | nindent 4 }}
diff --git a/addons/hbase/templates/hbase-scripts-template.yaml b/addons/hbase/templates/hbase-scripts-template.yaml
new file mode 100644
index 0000000000..4de69a179d
--- /dev/null
+++ b/addons/hbase/templates/hbase-scripts-template.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: hbase-scripts
+ labels:
+ {{- include "hbase.labels" . | nindent 4 }}
+data:
+ start-hmaster.sh: |-
+ {{- .Files.Get "scripts/start-hmaster.sh" | nindent 4 }}
+ start-hregionserver.sh: |-
+ {{- .Files.Get "scripts/start-hregionserver.sh" | nindent 4 }}
+ init-hdfs-root-layout.sh: |-
+ {{- .Files.Get "scripts/init-hdfs-root-layout.sh" | nindent 4 }}
+ check-hmaster-status.sh: |-
+ {{- .Files.Get "scripts/check-hmaster-status.sh" | nindent 4 }}
+ check-hregionserver-status.sh: |-
+ {{- .Files.Get "scripts/check-hregionserver-status.sh" | nindent 4 }}
diff --git a/addons/hbase/templates/hbase-standalone-config-template.yaml b/addons/hbase/templates/hbase-standalone-config-template.yaml
new file mode 100644
index 0000000000..cd673611ed
--- /dev/null
+++ b/addons/hbase/templates/hbase-standalone-config-template.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: hbase-standalone-config-template
+ labels:
+ {{- include "hbase.labels" . | nindent 4 }}
+data:
+ hbase-site.xml: |-
+ {{- .Files.Get "config/hbase-site-standalone.tpl" | nindent 4 }}
+ hbase-env.sh: |-
+ {{- .Files.Get "config/hbase-env.sh.tpl" | nindent 4 }}
+ hbase-jmx-exporter.yaml: |-
+ {{- .Files.Get "config/hbase-jmx-exporter.yaml.tpl" | nindent 4 }}
+ log4j.properties: |-
+ {{- .Files.Get "config/log4j.properties" | nindent 4 }}
diff --git a/addons/hbase/values.yaml b/addons/hbase/values.yaml
new file mode 100644
index 0000000000..d9d8f184e8
--- /dev/null
+++ b/addons/hbase/values.yaml
@@ -0,0 +1,85 @@
+hmaster:
+ image:
+ registry: docker.io
+ repository: apecloud/hbase-hmaster
+ tag: "v2.5.6-1.0.0"
+ pullPolicy: IfNotPresent
+
+hregionserver:
+ image:
+ registry: docker.io
+ repository: apecloud/hbase-hregionserver
+ tag: "v2.5.6-1.0.0"
+ pullPolicy: IfNotPresent
+
+hbasestandalone:
+ image:
+ registry: docker.io
+ repository: apecloud/hbase-hmaster
+ tag: "v2.5.6-1.0.0"
+ pullPolicy: IfNotPresent
+
+images:
+ jmxExporter:
+ registry: docker.io
+ repository: apecloud/jmx-exporter
+ tag: 0.18.0-debian-11-r20
+
+runtime:
+ hbaseHome: /opt/hbase-2.5.6
+ hbaseConfDir: /hbase/conf
+ hbaseLogDir: /var/log/hbase
+ hbasePidDir: /tmp/hbase
+ hbaseTmpDir: /hbase/tmp
+ hbaseDataDir: /data/hbase
+ scriptsDir: /hbase/scripts
+ hadoopConfDir: /hadoop/conf
+ hadoopHome: /opt/hadoop
+ hadoopNativeLibPath: /opt/hadoop/lib/native
+
+ports:
+ hmaster:
+ rpc: 16000
+ info: 16010
+ jmx: 10103
+ hregionserver:
+ rpc: 16020
+ info: 16030
+ jmx: 10104
+
+jvm:
+ hmasterHeapSize: 3g
+ hregionserverHeapSize: 4g
+ hbasestandaloneHeapSize: 512m
+
+hbase:
+ rootDir: hbase
+ zkParent: /hbase
+ zkClientPort: 2181
+
+hdfs:
+ nameservice: ""
+ namenodeNodes: nn0,nn1
+ namenodeRpcPort: 8020
+ namenodeHttpPort: 9870
+ haZkParent: /hadoop-ha
+ replication: "3"
+
+extra:
+ disableExporter: true
+ terminationPolicy: Delete
+ clusterDomain: cluster.local
+
+exporter:
+ securityContext:
+ runAsNonRoot: true
+ runAsUser: 1001
+
+jmxExporter:
+ port: 5556
+
+securityContext:
+ runAsUser: 10000
+ runAsGroup: 1000
+ runAsNonRoot: true
+ fsGroup: 1000