Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docker/helm/.helmignore
Original file line number Diff line number Diff line change
@@ -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/
29 changes: 29 additions & 0 deletions docker/helm/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

apiVersion: v2
name: fluss
description: A Helm chart for Kubernetes to deploy Apache Fluss CoordinatorServer and TabletServers.
appVersion: "0.8-SNAPSHOT"
type: application
version: 0.1.0
home: https://fluss.apache.org
icon: https://fluss.apache.org/img/logo/svg/colored_logo.svg
maintainers:
- name: Apache Fluss Community
url: https://github.com/apache/fluss
92 changes: 92 additions & 0 deletions docker/helm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@

# Fluss Helm Chart

This chart deploys an Apache Fluss cluster on Kubernetes, following Helm best practices.
It requires a Zookeeper ensemble to be running in the same Kubernetes cluster. In future releases, we may add support for an embedded Zookeeper cluster.


## Development environment

| component | version |
| ------------------------------------------------------------------------------ | ------- |
| [Docker](https://docs.docker.com/) | v28.3.2 |
| [Minikube](https://minikube.sigs.k8s.io/docs/) | v1.36.0 |
| [Kubernetes](https://kubernetes.io) | v1.25.3 |
| [Helm](https://helm.sh) | v3.18.6 |
| [Apache Fluss](https://fluss.apache.org/docs/) | v0.8-SNAPSHOT |


## Image requirements

A container image for Fluss is available on DockerHub as `fluss/fluss`. You can use it directly or build your own from this repo. To use your own image you need to build the project with [Maven](https://fluss.apache.org/community/dev/building/) and build it with Docker.

The Maven build will create all required artifacts in the `build-target` directory. You need to copy it into the `docker` directory. The Dockerfile in this directory will copy these artifacts into the image.

In minikube, you can use the local Docker daemon to build the image without pushing it to a registry:

```bash
eval $(minikube -p minikube docker-env)
docker build -t fluss/fluss:0.8-SNAPSHOT .
```

## Overview

It creates:
- 1x CoordinatorServer as a StatefulSet with a headless Service (stable per‑pod DNS)
- 3x TabletServers as a StatefulSet with a headless Service (stable per‑pod DNS)
- ConfigMap for server.yaml (CoordinatorServer and TabletServers) to override default Fluss configuration
- Optional PersistentVolumes for data directories

## Quick start

1) ZooKeeper deployment:

To start Zookeeper use Bitnami’s chart or your own deployment. If you have an existing Zookeeper cluster, you can skip this step. Example with Bitnami’s chart:

```bash
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install zk bitnami/zookeeper \
--set replicaCount=3 \
--set auth.enabled=false \
--set persistence.size=5Gi
```

2) Default (Zookeeper available in-cluster):

```bash
helm install fluss ./fluss-helm
```
With an optional namespace flag `--namespace <your-namespace>` if you want to install it in a specific namespace.

This assumes, that Zookeeper is reachable at `zk-zookeeper.<your-namespace>.svc.cluster.local:2181`. If your Zookeeper address is different, you can override it with:

```bash
helm install fluss ./fluss-helm \
--set zookeeper.address=<your-zk-address>
```

## Configuration reference

Important Fluss options surfaced by the chart:
- zookeeper.address: CoordinatorServer and TabletServer point to your ZK ensemble.
- data.dir, remote.data.dir: Local persistent path for data; remote path for snapshots (OSS/HDFS). TabletServers default to a PVC mounted at data.dir.
- bind.listeners: Where the server actually binds.
- advertised.listeners: Externally advertised endpoints for clients and intra‑cluster communication. In K8s, advertise stable names.
- internal.listener.name: Which listener is used for internal communication (defaults to INTERNAL).
- tablet-server.id: Required to be unique per TabletServer. The chart auto‑derives this from the StatefulSet pod ordinal at runtime.


### Zookeeper and storage
- zookeeper.address must point to a reachable ensemble.
- data.dir defaults to /tmp/fluss/data; use a PVC if persistence.enabled=true.

## Resource management

Set resources with requests/limits as appropriate for production. There are no defaults to make it also run on environments with little resources such as Minikube.

## Troubleshooting
- Image pull errors:
- If using a private registry, configure image.pullSecrets and ensure the image repository/tag are correct.
- Pods not ready: ensure ZooKeeper is reachable and ports 9123 are open.
- Connection failures: check advertised.listeners configuration and DNS resolution within the cluster by using kubectl exec to get a shell in a pod and test connectivity (using nc).
66 changes: 66 additions & 0 deletions docker/helm/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

{{/*
Expand the name of the chart.
*/}}
{{- define "fluss.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
*/}}
{{- define "fluss.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "fluss.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "fluss.labels" -}}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name (.Chart.Version | replace "+" "_") | quote }}
app.kubernetes.io/name: {{ include "fluss.name" . | quote }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
{{- end -}}

{{/*
Selector labels
*/}}
{{- define "fluss.selectorLabels" -}}
app.kubernetes.io/name: {{ include "fluss.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
29 changes: 29 additions & 0 deletions docker/helm/templates/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

apiVersion: v1
kind: ConfigMap
metadata:
name: fluss-conf-file
labels:
{{- include "fluss.labels" . | nindent 4 }}
data:
server.yaml: |
{{- range $key, $val := .Values.configurationOverrides }}
{{ $key }}: {{ tpl (printf "%v" $val) $ }}
{{- end }}
111 changes: 111 additions & 0 deletions docker/helm/templates/sts-coordinator.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: coordinator-server
labels:
{{- include "fluss.labels" . | nindent 4 }}
spec:
serviceName: coordinator-server-hs
replicas: 1 # can only be 1 for now
selector:
matchLabels:
{{- include "fluss.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: coordinator
template:
metadata:
labels:
{{- include "fluss.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: coordinator
spec:
containers:
- name: {{ .Chart.Name }}-coordinator
image: "{{.Values.image.repository}}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
command:
- "/bin/sh"
- "-c"
- |
export FLUSS_SERVER_ID=${POD_NAME##*-} && \
cp /opt/conf/server.yaml $FLUSS_HOME/conf && \

echo "" >> $FLUSS_HOME/conf/server.yaml && \
echo "tablet-server.id: ${FLUSS_SERVER_ID}" >> $FLUSS_HOME/conf/server.yaml && \
echo "bind.listeners: INTERNAL://0.0.0.0:{{ .Values.appConfig.internalPort }}, CLIENT://0.0.0.0:{{ .Values.appConfig.externalPort }}" >> $FLUSS_HOME/conf/server.yaml && \
echo "advertised.listeners: CLIENT://${POD_NAME}.coordinator-server-hs.${POD_NAMESPACE}.svc.cluster.local:{{ .Values.appConfig.externalPort }}" >> $FLUSS_HOME/conf/server.yaml && \

bin/coordinator-server.sh start-foreground
livenessProbe:
failureThreshold: 100
timeoutSeconds: 1
initialDelaySeconds: 10
periodSeconds: 3
tcpSocket:
port: {{.Values.appConfig.externalPort}}
readinessProbe:
failureThreshold: 100
timeoutSeconds: 1
initialDelaySeconds: 10
periodSeconds: 3
tcpSocket:
port: {{.Values.appConfig.externalPort}}
resources:
{{- toYaml .Values.resources.tabletServer | nindent 12 }}
volumeMounts:
- name: fluss-conf
mountPath: /opt/conf
- name: data
mountPath: /tmp/fluss/data
volumes:
- name: fluss-conf
configMap:
name: fluss-conf-file
{{- if not .Values.persistence.enabled }}
- name: data
emptyDir: {}
{{- end }}
{{- if .Values.persistence.enabled }}
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: {{ .Values.persistence.size }}
storageClassName: {{ .Values.persistence.storageClass }}
{{- end}}
Loading