Skip to content

Commit e455223

Browse files
authored
[helm] Add a helm chart for Fluss #779 (#1685)
* First helm draft with statefulset tablet, coordinator, configmap and svc for coordinator and headless svc for tablet * fix coordinator selector * changed coordinator to headless svc and adapted advertised listeners, tested with Flink inside the cluster * fixed license headers, minor typo fixes and comment cleanup * fixed license for helpers.tpl * minor fix to use dynamic namespace naming in the config of advertised listeners * added docker.io as registry so people can use other images besides official one * added PVC and README to the helm chart * changed storageClass to null to use default * used helm templating to dynamically set the namespace in zookeeper address * changed versions from 0.7.0 to 0.8-SNAPSHOT and included the Docker build step in the README
1 parent 3faa663 commit e455223

File tree

10 files changed

+604
-0
lines changed

10 files changed

+604
-0
lines changed

docker/helm/.helmignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Patterns to ignore when building packages.
2+
# This supports shell glob matching, relative path matching, and
3+
# negation (prefixed with !). Only one pattern per line.
4+
.DS_Store
5+
# Common VCS dirs
6+
.git/
7+
.gitignore
8+
.bzr/
9+
.bzrignore
10+
.hg/
11+
.hgignore
12+
.svn/
13+
# Common backup files
14+
*.swp
15+
*.bak
16+
*.tmp
17+
*.orig
18+
*~
19+
# Various IDEs
20+
.project
21+
.idea/
22+
*.tmproj
23+
.vscode/

docker/helm/Chart.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one
3+
# or more contributor license agreements. See the NOTICE file
4+
# distributed with this work for additional information
5+
# regarding copyright ownership. The ASF licenses this file
6+
# to you under the Apache License, Version 2.0 (the
7+
# "License"); you may not use this file except in compliance
8+
# with the License. You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
apiVersion: v2
20+
name: fluss
21+
description: A Helm chart for Kubernetes to deploy Apache Fluss CoordinatorServer and TabletServers.
22+
appVersion: "0.8-SNAPSHOT"
23+
type: application
24+
version: 0.1.0
25+
home: https://fluss.apache.org
26+
icon: https://fluss.apache.org/img/logo/svg/colored_logo.svg
27+
maintainers:
28+
- name: Apache Fluss Community
29+
url: https://github.com/apache/fluss

docker/helm/README.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
2+
# Fluss Helm Chart
3+
4+
This chart deploys an Apache Fluss cluster on Kubernetes, following Helm best practices.
5+
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.
6+
7+
8+
## Development environment
9+
10+
| component | version |
11+
| ------------------------------------------------------------------------------ | ------- |
12+
| [Docker](https://docs.docker.com/) | v28.3.2 |
13+
| [Minikube](https://minikube.sigs.k8s.io/docs/) | v1.36.0 |
14+
| [Kubernetes](https://kubernetes.io) | v1.25.3 |
15+
| [Helm](https://helm.sh) | v3.18.6 |
16+
| [Apache Fluss](https://fluss.apache.org/docs/) | v0.8-SNAPSHOT |
17+
18+
19+
## Image requirements
20+
21+
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.
22+
23+
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.
24+
25+
In minikube, you can use the local Docker daemon to build the image without pushing it to a registry:
26+
27+
```bash
28+
eval $(minikube -p minikube docker-env)
29+
docker build -t fluss/fluss:0.8-SNAPSHOT .
30+
```
31+
32+
## Overview
33+
34+
It creates:
35+
- 1x CoordinatorServer as a StatefulSet with a headless Service (stable per‑pod DNS)
36+
- 3x TabletServers as a StatefulSet with a headless Service (stable per‑pod DNS)
37+
- ConfigMap for server.yaml (CoordinatorServer and TabletServers) to override default Fluss configuration
38+
- Optional PersistentVolumes for data directories
39+
40+
## Quick start
41+
42+
1) ZooKeeper deployment:
43+
44+
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:
45+
46+
```bash
47+
helm repo add bitnami https://charts.bitnami.com/bitnami
48+
helm repo update
49+
helm install zk bitnami/zookeeper \
50+
--set replicaCount=3 \
51+
--set auth.enabled=false \
52+
--set persistence.size=5Gi
53+
```
54+
55+
2) Default (Zookeeper available in-cluster):
56+
57+
```bash
58+
helm install fluss ./fluss-helm
59+
```
60+
With an optional namespace flag `--namespace <your-namespace>` if you want to install it in a specific namespace.
61+
62+
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:
63+
64+
```bash
65+
helm install fluss ./fluss-helm \
66+
--set zookeeper.address=<your-zk-address>
67+
```
68+
69+
## Configuration reference
70+
71+
Important Fluss options surfaced by the chart:
72+
- zookeeper.address: CoordinatorServer and TabletServer point to your ZK ensemble.
73+
- 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.
74+
- bind.listeners: Where the server actually binds.
75+
- advertised.listeners: Externally advertised endpoints for clients and intra‑cluster communication. In K8s, advertise stable names.
76+
- internal.listener.name: Which listener is used for internal communication (defaults to INTERNAL).
77+
- tablet-server.id: Required to be unique per TabletServer. The chart auto‑derives this from the StatefulSet pod ordinal at runtime.
78+
79+
80+
### Zookeeper and storage
81+
- zookeeper.address must point to a reachable ensemble.
82+
- data.dir defaults to /tmp/fluss/data; use a PVC if persistence.enabled=true.
83+
84+
## Resource management
85+
86+
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.
87+
88+
## Troubleshooting
89+
- Image pull errors:
90+
- If using a private registry, configure image.pullSecrets and ensure the image repository/tag are correct.
91+
- Pods not ready: ensure ZooKeeper is reachable and ports 9123 are open.
92+
- 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).

docker/helm/templates/_helpers.tpl

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one
3+
# or more contributor license agreements. See the NOTICE file
4+
# distributed with this work for additional information
5+
# regarding copyright ownership. The ASF licenses this file
6+
# to you under the Apache License, Version 2.0 (the
7+
# "License"); you may not use this file except in compliance
8+
# with the License. You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
{{/*
20+
Expand the name of the chart.
21+
*/}}
22+
{{- define "fluss.name" -}}
23+
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
24+
{{- end }}
25+
26+
{{/*
27+
Create a default fully qualified app name.
28+
*/}}
29+
{{- define "fluss.fullname" -}}
30+
{{- if .Values.fullnameOverride -}}
31+
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
32+
{{- else -}}
33+
{{- $name := default .Chart.Name .Values.nameOverride -}}
34+
{{- if contains $name .Release.Name -}}
35+
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
36+
{{- else -}}
37+
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
38+
{{- end -}}
39+
{{- end -}}
40+
{{- end -}}
41+
42+
{{/*
43+
Create chart name and version as used by the chart label.
44+
*/}}
45+
{{- define "fluss.chart" -}}
46+
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
47+
{{- end }}
48+
49+
{{/*
50+
Common labels
51+
*/}}
52+
{{- define "fluss.labels" -}}
53+
helm.sh/chart: {{ printf "%s-%s" .Chart.Name (.Chart.Version | replace "+" "_") | quote }}
54+
app.kubernetes.io/name: {{ include "fluss.name" . | quote }}
55+
app.kubernetes.io/instance: {{ .Release.Name | quote }}
56+
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
57+
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
58+
{{- end -}}
59+
60+
{{/*
61+
Selector labels
62+
*/}}
63+
{{- define "fluss.selectorLabels" -}}
64+
app.kubernetes.io/name: {{ include "fluss.name" . }}
65+
app.kubernetes.io/instance: {{ .Release.Name }}
66+
{{- end }}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one
3+
# or more contributor license agreements. See the NOTICE file
4+
# distributed with this work for additional information
5+
# regarding copyright ownership. The ASF licenses this file
6+
# to you under the Apache License, Version 2.0 (the
7+
# "License"); you may not use this file except in compliance
8+
# with the License. You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
apiVersion: v1
20+
kind: ConfigMap
21+
metadata:
22+
name: fluss-conf-file
23+
labels:
24+
{{- include "fluss.labels" . | nindent 4 }}
25+
data:
26+
server.yaml: |
27+
{{- range $key, $val := .Values.configurationOverrides }}
28+
{{ $key }}: {{ tpl (printf "%v" $val) $ }}
29+
{{- end }}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one
3+
# or more contributor license agreements. See the NOTICE file
4+
# distributed with this work for additional information
5+
# regarding copyright ownership. The ASF licenses this file
6+
# to you under the Apache License, Version 2.0 (the
7+
# "License"); you may not use this file except in compliance
8+
# with the License. You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
apiVersion: apps/v1
20+
kind: StatefulSet
21+
metadata:
22+
name: coordinator-server
23+
labels:
24+
{{- include "fluss.labels" . | nindent 4 }}
25+
spec:
26+
serviceName: coordinator-server-hs
27+
replicas: 1 # can only be 1 for now
28+
selector:
29+
matchLabels:
30+
{{- include "fluss.selectorLabels" . | nindent 6 }}
31+
app.kubernetes.io/component: coordinator
32+
template:
33+
metadata:
34+
labels:
35+
{{- include "fluss.selectorLabels" . | nindent 8 }}
36+
app.kubernetes.io/component: coordinator
37+
spec:
38+
containers:
39+
- name: {{ .Chart.Name }}-coordinator
40+
image: "{{.Values.image.repository}}:{{ .Values.image.tag }}"
41+
imagePullPolicy: {{ .Values.image.pullPolicy }}
42+
env:
43+
- name: POD_NAME
44+
valueFrom:
45+
fieldRef:
46+
fieldPath: metadata.name
47+
- name: POD_IP
48+
valueFrom:
49+
fieldRef:
50+
fieldPath: status.podIP
51+
- name: POD_NAMESPACE
52+
valueFrom:
53+
fieldRef:
54+
fieldPath: metadata.namespace
55+
- name: NODE_IP
56+
valueFrom:
57+
fieldRef:
58+
fieldPath: status.hostIP
59+
command:
60+
- "/bin/sh"
61+
- "-c"
62+
- |
63+
export FLUSS_SERVER_ID=${POD_NAME##*-} && \
64+
cp /opt/conf/server.yaml $FLUSS_HOME/conf && \
65+
66+
echo "" >> $FLUSS_HOME/conf/server.yaml && \
67+
echo "tablet-server.id: ${FLUSS_SERVER_ID}" >> $FLUSS_HOME/conf/server.yaml && \
68+
echo "bind.listeners: INTERNAL://0.0.0.0:{{ .Values.appConfig.internalPort }}, CLIENT://0.0.0.0:{{ .Values.appConfig.externalPort }}" >> $FLUSS_HOME/conf/server.yaml && \
69+
echo "advertised.listeners: CLIENT://${POD_NAME}.coordinator-server-hs.${POD_NAMESPACE}.svc.cluster.local:{{ .Values.appConfig.externalPort }}" >> $FLUSS_HOME/conf/server.yaml && \
70+
71+
bin/coordinator-server.sh start-foreground
72+
livenessProbe:
73+
failureThreshold: 100
74+
timeoutSeconds: 1
75+
initialDelaySeconds: 10
76+
periodSeconds: 3
77+
tcpSocket:
78+
port: {{.Values.appConfig.externalPort}}
79+
readinessProbe:
80+
failureThreshold: 100
81+
timeoutSeconds: 1
82+
initialDelaySeconds: 10
83+
periodSeconds: 3
84+
tcpSocket:
85+
port: {{.Values.appConfig.externalPort}}
86+
resources:
87+
{{- toYaml .Values.resources.tabletServer | nindent 12 }}
88+
volumeMounts:
89+
- name: fluss-conf
90+
mountPath: /opt/conf
91+
- name: data
92+
mountPath: /tmp/fluss/data
93+
volumes:
94+
- name: fluss-conf
95+
configMap:
96+
name: fluss-conf-file
97+
{{- if not .Values.persistence.enabled }}
98+
- name: data
99+
emptyDir: {}
100+
{{- end }}
101+
{{- if .Values.persistence.enabled }}
102+
volumeClaimTemplates:
103+
- metadata:
104+
name: data
105+
spec:
106+
accessModes: [ "ReadWriteOnce" ]
107+
resources:
108+
requests:
109+
storage: {{ .Values.persistence.size }}
110+
storageClassName: {{ .Values.persistence.storageClass }}
111+
{{- end}}

0 commit comments

Comments
 (0)