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