diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl index 79ae9d3106..4dd135cc50 100644 --- a/helm/templates/_helpers.tpl +++ b/helm/templates/_helpers.tpl @@ -63,4 +63,27 @@ Selector labels {{- define "fluss.selectorLabels" -}} app.kubernetes.io/name: {{ include "fluss.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} \ No newline at end of file +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "fluss.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "fluss.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Generate JAAS configuration for SASL +*/}} +{{- define "fluss.sasl.jaasConfig" -}} +FlussServer { + org.apache.fluss.security.auth.sasl.plain.PlainLoginModule required + {{- range .Values.sasl.users }} + user_{{ .username }}="{{ .password }}" + {{- end }}; +}; +{{- end }} diff --git a/helm/templates/rbac.yaml b/helm/templates/rbac.yaml new file mode 100644 index 0000000000..0b44bf0309 --- /dev/null +++ b/helm/templates/rbac.yaml @@ -0,0 +1,35 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "fluss.fullname" . }}-metadata-reader + namespace: {{ .Release.Namespace }} + labels: + {{- include "fluss.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["services"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["get", "list", "watch"] + - apiGroups: ["discovery.k8s.io"] + resources: ["endpointslices"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "fluss.fullname" . }}-metadata-reader + namespace: {{ .Release.Namespace }} + labels: + {{- include "fluss.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "fluss.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "fluss.fullname" . }}-metadata-reader +{{- end -}} diff --git a/helm/templates/secret-sasl.yaml b/helm/templates/secret-sasl.yaml new file mode 100644 index 0000000000..eca4f7a2cf --- /dev/null +++ b/helm/templates/secret-sasl.yaml @@ -0,0 +1,13 @@ +{{- if .Values.sasl.enabled -}} +{{- if not .Values.sasl.existingSecret -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "fluss.fullname" . }}-sasl-jaas-config + labels: + {{- include "fluss.labels" . | nindent 4 }} +type: Opaque +data: + jaas.conf: {{ include "fluss.sasl.jaasConfig" . | b64enc | quote }} +{{- end -}} +{{- end -}} diff --git a/helm/templates/sts-coordinator.yaml b/helm/templates/sts-coordinator.yaml index 3caa783957..3e157f38a4 100644 --- a/helm/templates/sts-coordinator.yaml +++ b/helm/templates/sts-coordinator.yaml @@ -35,8 +35,39 @@ spec: {{- include "fluss.selectorLabels" . | nindent 8 }} app.kubernetes.io/component: coordinator spec: - {{- if .Values.serviceAccount.create }} - serviceAccountName: {{ .Values.serviceAccount.name | default (include "fluss.fullname" .) }} + serviceAccountName: {{ include "fluss.serviceAccountName" . }} + {{- if .Values.externalAccess.enabled }} + initContainers: + - name: auto-discovery + image: "{{ .Values.externalAccess.initContainer.image.registry }}/{{ .Values.externalAccess.initContainer.image.repository }}:{{ .Values.externalAccess.initContainer.image.tag }}" + imagePullPolicy: {{ .Values.externalAccess.initContainer.image.pullPolicy }} + command: + - "/bin/bash" + - "-c" + - | + SVC_NAME="coordinator-server-external" + echo "Waiting for service $SVC_NAME external IP..." + EXTERNAL_HOST="" + while [ -z "$EXTERNAL_HOST" ]; do + EXTERNAL_HOST=$(kubectl get svc $SVC_NAME -n $POD_NAMESPACE -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') + if [ -z "$EXTERNAL_HOST" ]; then + sleep 5 + fi + done + echo "Found external hostname: $EXTERNAL_HOST" + echo "$EXTERNAL_HOST" > /shared/external.host + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + volumeMounts: + - name: shared + mountPath: /shared {{- end }} containers: - name: {{ .Chart.Name }}-coordinator @@ -44,21 +75,30 @@ spec: imagePullPolicy: {{ .Values.image.pullPolicy }} env: - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name + valueFrom: + fieldRef: + fieldPath: metadata.name - name: POD_IP - valueFrom: - fieldRef: + valueFrom: + fieldRef: fieldPath: status.podIP - name: POD_NAMESPACE - valueFrom: - fieldRef: + valueFrom: + fieldRef: fieldPath: metadata.namespace - name: NODE_IP valueFrom: fieldRef: fieldPath: status.hostIP + ports: + - name: internal + containerPort: {{ .Values.listeners.internal.port }} + - name: client + containerPort: {{ .Values.listeners.client.port }} + {{- if .Values.externalAccess.enabled }} + - name: external + containerPort: {{ .Values.listeners.external.port }} + {{- end }} command: - "/bin/sh" - "-c" @@ -66,10 +106,35 @@ spec: export FLUSS_SERVER_ID=${POD_NAME##*-} && \ cp /opt/conf/server.yaml $FLUSS_HOME/conf && \ + BIND_LISTENERS="INTERNAL://${POD_IP}:{{ .Values.listeners.internal.port }}, CLIENT://${POD_IP}:{{ .Values.listeners.client.port }}" && \ + ADVERTISED_LISTENERS="CLIENT://${POD_NAME}.coordinator-server-hs.${POD_NAMESPACE}.svc.cluster.local:{{ .Values.listeners.client.port }}" && \ + + {{- if .Values.externalAccess.enabled }} + if [ -f /shared/external.host ]; then + EXTERNAL_HOST=$(cat /shared/external.host) && \ + ADVERTISED_LISTENERS="${ADVERTISED_LISTENERS}, EXTERNAL://${EXTERNAL_HOST}:{{ .Values.listeners.external.port }}" && \ + BIND_LISTENERS="${BIND_LISTENERS}, EXTERNAL://${POD_IP}:{{ .Values.listeners.external.port }}" + fi && \ + {{- end }} + 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 && \ + echo "bind.listeners: ${BIND_LISTENERS}" >> $FLUSS_HOME/conf/server.yaml && \ + echo "advertised.listeners: ${ADVERTISED_LISTENERS}" >> $FLUSS_HOME/conf/server.yaml && \ + + {{- if .Values.sasl.enabled }} + {{- $jaasUsers := list -}} + {{- range .Values.sasl.users }} + {{- $jaasUsers = append $jaasUsers (printf "user_%s=\\\"%s\\\"" .username .password) -}} + {{- end }} + echo "security.sasl.enabled.mechanisms: {{ .Values.sasl.mechanism }}" >> $FLUSS_HOME/conf/server.yaml && \ + echo "security.sasl.plain.jaas.config: org.apache.fluss.security.auth.sasl.plain.PlainLoginModule required {{ join " " $jaasUsers }};" >> $FLUSS_HOME/conf/server.yaml && \ + echo "security.protocol.map: INTERNAL:sasl,CLIENT:sasl{{ if .Values.externalAccess.enabled }},EXTERNAL:sasl{{ end }}" >> $FLUSS_HOME/conf/server.yaml && \ + + echo "client.security.protocol: SASL" >> conf/server.yaml && \ + echo "client.security.sasl.mechanism: {{ .Values.sasl.mechanism }}" >> conf/server.yaml && \ + echo "client.security.sasl.username: {{ (first .Values.sasl.users).username }}" >> conf/server.yaml && \ + echo "client.security.sasl.password: {{ (first .Values.sasl.users).password }}" >> conf/server.yaml && \ + {{- end }} bin/coordinator-server.sh start-foreground livenessProbe: @@ -78,14 +143,14 @@ spec: initialDelaySeconds: 10 periodSeconds: 3 tcpSocket: - port: {{.Values.appConfig.externalPort}} + port: {{ .Values.listeners.client.port }} readinessProbe: failureThreshold: 100 timeoutSeconds: 1 initialDelaySeconds: 10 periodSeconds: 3 tcpSocket: - port: {{.Values.appConfig.externalPort}} + port: {{ .Values.listeners.client.port }} resources: {{- toYaml .Values.resources.tabletServer | nindent 12 }} volumeMounts: @@ -93,6 +158,15 @@ spec: mountPath: /opt/conf - name: data mountPath: /tmp/fluss/data + {{- if .Values.sasl.enabled }} + - name: sasl-config + mountPath: /etc/fluss/conf + readOnly: true + {{- end }} + {{- if .Values.externalAccess.enabled }} + - name: shared + mountPath: /shared + {{- end }} volumes: - name: fluss-conf configMap: @@ -101,6 +175,15 @@ spec: - name: data emptyDir: {} {{- end }} + {{- if .Values.sasl.enabled }} + - name: sasl-config + secret: + secretName: {{ if .Values.sasl.existingSecret }}{{ .Values.sasl.existingSecret }}{{ else }}{{ include "fluss.fullname" . }}-sasl-jaas-config{{ end }} + {{- end }} + {{- if .Values.externalAccess.enabled }} + - name: shared + emptyDir: {} + {{- end }} {{- if .Values.persistence.enabled }} volumeClaimTemplates: - metadata: @@ -111,4 +194,4 @@ spec: requests: storage: {{ .Values.persistence.size }} storageClassName: {{ .Values.persistence.storageClass }} - {{- end}} \ No newline at end of file + {{- end}} diff --git a/helm/templates/sts-tablet.yaml b/helm/templates/sts-tablet.yaml index f13dce9b1b..098c7e4de1 100644 --- a/helm/templates/sts-tablet.yaml +++ b/helm/templates/sts-tablet.yaml @@ -24,7 +24,7 @@ metadata: {{- include "fluss.labels" . | nindent 4 }} spec: serviceName: tablet-server-hs - replicas: 3 + replicas: {{ .Values.tablet.count }} selector: matchLabels: {{- include "fluss.selectorLabels" . | nindent 6 }} @@ -35,8 +35,39 @@ spec: {{- include "fluss.selectorLabels" . | nindent 8 }} app.kubernetes.io/component: tablet spec: - {{- if .Values.serviceAccount.create }} - serviceAccountName: {{ .Values.serviceAccount.name | default (include "fluss.fullname" .) }} + serviceAccountName: {{ include "fluss.serviceAccountName" . }} + {{- if .Values.externalAccess.enabled }} + initContainers: + - name: auto-discovery + image: "{{ .Values.externalAccess.initContainer.image.registry }}/{{ .Values.externalAccess.initContainer.image.repository }}:{{ .Values.externalAccess.initContainer.image.tag }}" + imagePullPolicy: {{ .Values.externalAccess.initContainer.image.pullPolicy }} + command: + - "/bin/bash" + - "-c" + - | + SVC_NAME="tablet-server-${POD_NAME##*-}-external" + echo "Waiting for service $SVC_NAME external IP..." + EXTERNAL_HOST="" + while [ -z "$EXTERNAL_HOST" ]; do + EXTERNAL_HOST=$(kubectl get svc $SVC_NAME -n $POD_NAMESPACE -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') + if [ -z "$EXTERNAL_HOST" ]; then + sleep 5 + fi + done + echo "Found external hostname: $EXTERNAL_HOST" + echo "$EXTERNAL_HOST" > /shared/external.host + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + volumeMounts: + - name: shared + mountPath: /shared {{- end }} containers: - name: {{ .Chart.Name }}-tablet @@ -44,28 +75,64 @@ spec: imagePullPolicy: {{ .Values.image.pullPolicy }} env: - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name + valueFrom: + fieldRef: + fieldPath: metadata.name - name: POD_IP - valueFrom: - fieldRef: + valueFrom: + fieldRef: fieldPath: status.podIP - name: POD_NAMESPACE - valueFrom: - fieldRef: + valueFrom: + fieldRef: fieldPath: metadata.namespace + ports: + - name: internal + containerPort: {{ .Values.listeners.internal.port }} + - name: client + containerPort: {{ .Values.listeners.client.port }} + {{- if .Values.externalAccess.enabled }} + - name: external + containerPort: {{ .Values.listeners.external.port }} + {{- end }} command: - "/bin/sh" - "-c" - | export FLUSS_SERVER_ID=${POD_NAME##*-} && \ cp /opt/conf/server.yaml $FLUSS_HOME/conf && \ - export PORT=$((9125 + ${FLUSS_SERVER_ID})) && \ + + BIND_LISTENERS="INTERNAL://${POD_IP}:{{ .Values.listeners.internal.port }}, CLIENT://${POD_IP}:{{ .Values.listeners.client.port }}" && \ + ADVERTISED_LISTENERS="CLIENT://${POD_NAME}.tablet-server-hs.${POD_NAMESPACE}.svc.cluster.local:{{ .Values.listeners.client.port }}" && \ + + {{- if .Values.externalAccess.enabled }} + if [ -f /shared/external.host ]; then + EXTERNAL_HOST=$(cat /shared/external.host) && \ + ADVERTISED_LISTENERS="${ADVERTISED_LISTENERS}, EXTERNAL://${EXTERNAL_HOST}:{{ .Values.listeners.external.port }}" && \ + BIND_LISTENERS="${BIND_LISTENERS}, EXTERNAL://${POD_IP}:{{ .Values.listeners.external.port }}" + fi && \ + {{- end }} + echo "" >> $FLUSS_HOME/conf/server.yaml && \ echo "tablet-server.id: ${FLUSS_SERVER_ID}" >> $FLUSS_HOME/conf/server.yaml && \ - echo "bind.listeners: INTERNAL://${POD_IP}:{{ .Values.appConfig.internalPort }}, CLIENT://0.0.0.0:{{ .Values.appConfig.externalPort }}" >> $FLUSS_HOME/conf/server.yaml && \ - echo "advertised.listeners: CLIENT://${POD_NAME}.tablet-server-hs.${POD_NAMESPACE}.svc.cluster.local:{{ .Values.appConfig.externalPort }}" >> $FLUSS_HOME/conf/server.yaml && \ + echo "bind.listeners: ${BIND_LISTENERS}" >> $FLUSS_HOME/conf/server.yaml && \ + echo "advertised.listeners: ${ADVERTISED_LISTENERS}" >> $FLUSS_HOME/conf/server.yaml && \ + + {{- if .Values.sasl.enabled }} + {{- $jaasUsers := list -}} + {{- range .Values.sasl.users }} + {{- $jaasUsers = append $jaasUsers (printf "user_%s=\\\"%s\\\"" .username .password) -}} + {{- end }} + echo "security.sasl.enabled.mechanisms: {{ .Values.sasl.mechanism }}" >> $FLUSS_HOME/conf/server.yaml && \ + echo "security.sasl.plain.jaas.config: org.apache.fluss.security.auth.sasl.plain.PlainLoginModule required {{ join " " $jaasUsers }};" >> $FLUSS_HOME/conf/server.yaml && \ + echo "security.protocol.map: INTERNAL:sasl,CLIENT:sasl{{ if .Values.externalAccess.enabled }},EXTERNAL:sasl{{ end }}" >> $FLUSS_HOME/conf/server.yaml && \ + + echo "client.security.protocol: SASL" >> conf/server.yaml && \ + echo "client.security.sasl.mechanism: {{ .Values.sasl.mechanism }}" >> conf/server.yaml && \ + echo "client.security.sasl.username: {{ (first .Values.sasl.users).username }}" >> conf/server.yaml && \ + echo "client.security.sasl.password: {{ (first .Values.sasl.users).password }}" >> conf/server.yaml && \ + {{- end }} + bin/tablet-server.sh start-foreground livenessProbe: failureThreshold: 100 @@ -73,14 +140,14 @@ spec: initialDelaySeconds: 10 periodSeconds: 3 tcpSocket: - port: {{.Values.appConfig.externalPort}} + port: {{ .Values.listeners.client.port }} readinessProbe: failureThreshold: 100 timeoutSeconds: 1 initialDelaySeconds: 10 periodSeconds: 3 tcpSocket: - port: {{.Values.appConfig.externalPort}} + port: {{ .Values.listeners.client.port }} resources: {{- toYaml .Values.resources.tabletServer | nindent 12 }} volumeMounts: @@ -88,6 +155,15 @@ spec: mountPath: /opt/conf - name: data mountPath: /tmp/fluss/data + {{- if .Values.sasl.enabled }} + - name: sasl-config + mountPath: /etc/fluss/conf + readOnly: true + {{- end }} + {{- if .Values.externalAccess.enabled }} + - name: shared + mountPath: /shared + {{- end }} volumes: - name: fluss-conf configMap: @@ -96,6 +172,15 @@ spec: - name: data emptyDir: {} {{- end }} + {{- if .Values.sasl.enabled }} + - name: sasl-config + secret: + secretName: {{ if .Values.sasl.existingSecret }}{{ .Values.sasl.existingSecret }}{{ else }}{{ include "fluss.fullname" . }}-sasl-jaas-config{{ end }} + {{- end }} + {{- if .Values.externalAccess.enabled }} + - name: shared + emptyDir: {} + {{- end }} {{- if .Values.persistence.enabled }} volumeClaimTemplates: - metadata: @@ -106,4 +191,4 @@ spec: requests: storage: {{ .Values.persistence.size }} storageClassName: {{ .Values.persistence.storageClass }} - {{- end}} \ No newline at end of file + {{- end}} diff --git a/helm/templates/svc-coordinator-external.yaml b/helm/templates/svc-coordinator-external.yaml new file mode 100644 index 0000000000..1e32b24e33 --- /dev/null +++ b/helm/templates/svc-coordinator-external.yaml @@ -0,0 +1,46 @@ +# +# 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. +# + +{{- if .Values.externalAccess.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: coordinator-server-external + labels: + {{- include "fluss.labels" . | nindent 4 }} + app.kubernetes.io/component: coordinator + {{- with .Values.externalAccess.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ default "LoadBalancer" .Values.externalAccess.service.type }} + {{- if .Values.externalAccess.service.allowedSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml .Values.externalAccess.service.allowedSourceRanges | nindent 4 }} + {{- end }} + ports: + - name: fluss-external + protocol: TCP + port: {{ .Values.listeners.external.port }} + targetPort: external + selector: + {{- include "fluss.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: coordinator + statefulset.kubernetes.io/pod-name: coordinator-server-0 +{{- end }} diff --git a/helm/templates/svc-coordinator.yaml b/helm/templates/svc-coordinator.yaml index 8cc74728fb..64a622ae28 100644 --- a/helm/templates/svc-coordinator.yaml +++ b/helm/templates/svc-coordinator.yaml @@ -29,12 +29,12 @@ spec: ports: - name: internal protocol: TCP - port: {{ .Values.appConfig.internalPort }} - targetPort: {{ .Values.appConfig.internalPort }} + port: {{ .Values.listeners.internal.port }} + targetPort: internal - name: client protocol: TCP - port: {{ .Values.appConfig.externalPort }} - targetPort: {{ .Values.appConfig.externalPort }} + port: {{ .Values.listeners.client.port }} + targetPort: client selector: {{- include "fluss.selectorLabels" . | nindent 4 }} - app.kubernetes.io/component: coordinator \ No newline at end of file + app.kubernetes.io/component: coordinator diff --git a/helm/templates/svc-tablet-external.yaml b/helm/templates/svc-tablet-external.yaml new file mode 100644 index 0000000000..4794a4124a --- /dev/null +++ b/helm/templates/svc-tablet-external.yaml @@ -0,0 +1,52 @@ +# +# 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. +# + +{{- if .Values.externalAccess.enabled }} +{{- $tabletCount := .Values.tablet.count | int }} +{{- $servicePort := .Values.listeners.external.port }} +{{- range $i, $_ := until $tabletCount }} +--- +apiVersion: v1 +kind: Service +metadata: + name: tablet-server-{{ $i }}-external + labels: + {{- include "fluss.labels" $ | nindent 4 }} + app.kubernetes.io/component: tablet + statefulset.kubernetes.io/pod-name: tablet-server-{{ $i }} + {{- with $.Values.externalAccess.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ default "LoadBalancer" $.Values.externalAccess.service.type }} + {{- if $.Values.externalAccess.service.allowedSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml $.Values.externalAccess.service.allowedSourceRanges | nindent 4 }} + {{- end }} + ports: + - name: fluss-external + protocol: TCP + port: {{ $servicePort }} + targetPort: external + selector: + {{- include "fluss.selectorLabels" $ | nindent 4 }} + app.kubernetes.io/component: tablet + statefulset.kubernetes.io/pod-name: tablet-server-{{ $i }} +{{- end }} +{{- end }} diff --git a/helm/templates/svc-tablet.yaml b/helm/templates/svc-tablet.yaml index ca74b6d80f..517653e87f 100644 --- a/helm/templates/svc-tablet.yaml +++ b/helm/templates/svc-tablet.yaml @@ -29,12 +29,12 @@ spec: ports: - name: internal protocol: TCP - port: {{ .Values.appConfig.internalPort }} - targetPort: {{ .Values.appConfig.internalPort }} + port: {{ .Values.listeners.internal.port }} + targetPort: internal - name: client protocol: TCP - port: {{ .Values.appConfig.externalPort }} - targetPort: {{ .Values.appConfig.externalPort }} + port: {{ .Values.listeners.client.port }} + targetPort: client selector: {{- include "fluss.selectorLabels" . | nindent 4 }} - app.kubernetes.io/component: tablet \ No newline at end of file + app.kubernetes.io/component: tablet diff --git a/helm/values.yaml b/helm/values.yaml index 9a17124759..76d3f1a0d2 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -27,11 +27,6 @@ image: pullPolicy: IfNotPresent pullSecrets: [] -appConfig: - internalPort: 9123 - externalPort: 9124 - - # Fluss server configuration options configurationOverrides: default.bucket.number: 3 @@ -47,6 +42,41 @@ persistence: size: 1Gi storageClass: +# Tablet server only configuration options +tablet: + count: 3 + +# Fluss listener configurations +listeners: + internal: + name: INTERNAL + port: 9123 + client: + name: CLIENT + port: 9124 + ## Activated only when @param externalAccess.enabled is true + external: + name: EXTERNAL + port: 9125 + +# Fluss cluster external access +externalAccess: + enabled: false + ## Image used for the init container + initContainer: + image: + registry: docker.io + repository: bitnami/kubectl + tag: latest + pullPolicy: IfNotPresent + service: + ## Service type (only LoadBalancer is supported for now) + type: LoadBalancer + ## Allowed source IP address ranges for external access + allowedSourceRanges: + ## Load balancer annotations + annotations: + resources: {} # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little @@ -69,8 +99,20 @@ resources: {} serviceAccount: create: false - # If not set and create is true, a name is generated using the fullname template + # If not set and create is true, a name is generated using the `fullname` template name: "" - # Additional annotations to apply to the ServiceAccount. - # These can be useful, for example, to support integrations like workload identity. + # Additional annotations to apply to the ServiceAccount annotations: {} + +rbac: + create: false + +sasl: + enabled: false + mechanism: PLAIN + # List of client users for authentication + users: + - username: admin + password: password + # If specified, the existing secret must contain a key `jaas.conf` with the JAAS configuration + existingSecret: "" diff --git a/website/docs/install-deploy/deploying-with-helm.md b/website/docs/install-deploy/deploying-with-helm.md index a331343639..5efa7c1be9 100644 --- a/website/docs/install-deploy/deploying-with-helm.md +++ b/website/docs/install-deploy/deploying-with-helm.md @@ -184,8 +184,9 @@ The following table lists the configurable parameters of the Fluss chart and the | Parameter | Description | Default | |-----------|-------------|---------| -| `appConfig.internalPort` | Internal communication port | `9123` | -| `appConfig.externalPort` | External client port | `9124` | +| `listeners.internal.port` | Internal communication port | `9123` | +| `listeners.client.port` | Client port (intra-cluster) | `9124` | +| `listeners.external.port` | External access port | `9125` | ### Fluss Configuration Overrides @@ -199,6 +200,28 @@ The following table lists the configurable parameters of the Fluss chart and the | `configurationOverrides.data.dir` | Local data directory | `/tmp/fluss/data` | | `configurationOverrides.internal.listener.name` | Internal listener name | `INTERNAL` | +### SASL Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `sasl.enabled` | Enable SASL authentication | `false` | +| `sasl.mechanism` | SASL mechanism | `PLAIN` | +| `sasl.users` | User list for PLAIN authentication | `[{username: admin, password: password}]` | +| `sasl.existingSecret` | Use existing secret containing `jaas.conf` | `""` | + +### External Access Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `externalAccess.enabled` | Enable external access | `false` | +| `externalAccess.service.type` | Service type (only `LoadBalancer` supported) | `LoadBalancer` | +| `externalAccess.service.allowedSourceRanges` | Allowed source IP ranges | `nil` | +| `externalAccess.service.annotations` | Service annotations | `{}` | +| `externalAccess.initContainer.image.registry` | Init container image registry | `docker.io` | +| `externalAccess.initContainer.image.repository` | Init container image repository | `bitnami/kubectl` | +| `externalAccess.initContainer.image.tag` | Init container image tag | `latest` | +| `externalAccess.initContainer.image.pullPolicy` | Init container image pull policy | `IfNotPresent` | + ### Persistence Parameters | Parameter | Description | Default | @@ -220,6 +243,14 @@ The following table lists the configurable parameters of the Fluss chart and the | `resources.tabletServer.limits.cpu` | CPU limits for tablet servers | Not set | | `resources.tabletServer.limits.memory` | Memory limits for tablet servers | Not set | +### RBAC and Service Account + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `serviceAccount.create` | Create a service account for the chart | `false` | +| `serviceAccount.name` | Service account name (auto-generated if empty and create=true) | `""` | +| `serviceAccount.annotations` | Extra annotations for the service account | `{}` | +| `rbac.create` | Create RBAC resources required for external access discovery | `false` | ## Advanced Configuration @@ -237,21 +268,77 @@ configurationOverrides: The chart automatically configures listeners for internal cluster communication and external client access: -- **Internal Port (9123)**: Used for inter-service communication within the cluster -- **External Port (9124)**: Used for client connections +- **Internal Port (9123)**: Used for internal communication within the cluster +- **Client Port (9124)**: Used for client connections +- **External Port (9125)**: Used for external access if enabled -Custom listener configuration: +Listeners configuration: ```yaml -appConfig: - internalPort: 9123 - externalPort: 9124 +listeners: + internal: + port: 9123 + client: + port: 9124 + external: + port: 9125 + +externalAccess: + enabled: true + service: + type: LoadBalancer + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: "nlb" +``` -configurationOverrides: - bind.listeners: "INTERNAL://0.0.0.0:9123,CLIENT://0.0.0.0:9124" - advertised.listeners: "CLIENT://my-cluster.example.com:9124" +### External Access to Fluss Cluster + +To enable the external access to the Fluss clusters an additional service should be enabled. + +At the moment, only the `LoadBalancer` service is supported. + +To enable external access, add the following values: + +```yaml +externalAccess: + enabled: true + service: + type: LoadBalancer + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: "external" + +rbac: + create: true ``` +For this option we need to create `RBAC` so that the service metadata could be obtained before starting the stateful sets. + +### Enable Secure Connection to Fluss + +With the helm deployment, you can specify authentication protocols when connecting to the Fluss cluster. + +The following table shows the currently supported protocols and security they provide: + +| Method | Authentication | TLS Encryption | +|-------------|:--------------:|:------------------:| +| `PLAINTEXT` | No | No | +| `SASL` | Yes | No | + +By default the `PLAINTEXT` protocol is used. + +To enable SASL protocol with `PLAIN` authentication, add the following values: + +```yaml +sasl: + enabled: true + mechanism: PLAIN + users: + - username: admin + password: password +``` + +The `users` defines comma-separated list of usernames and passwords for client communications when SASL is enabled. + ### Storage Configuration Configure different storage backends: