dev-tools/charts/nifi/templates/statefulset.yaml
2026-06-04 11:46:59 +03:00

389 lines
15 KiB
YAML

{{- $nifiHome := "/opt/nifi/nifi-current" }}
{{- /* Validate that basic auth is only used with single node */ -}}
{{- if and (not .Values.global.oidc.enabled) (not .Values.global.ldap.enabled) (gt (.Values.global.nifi.nodeCount | int) 1) }}
{{- fail "Basic authentication (Single User Authentication) only supports single-node deployment. Please set global.nifi.nodeCount to 1, or enable OIDC/LDAP authentication for clustering." }}
{{- end }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "nifi.fullname" . }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
spec:
podManagementPolicy: Parallel
replicas: {{ .Values.global.nifi.nodeCount }}
selector:
matchLabels:
{{- include "nifi.selectorLabels" . | nindent 6 }}
serviceName: {{ include "nifi.fullname" . }}
template:
metadata:
labels:
{{- include "nifi.selectorLabels" . | nindent 8 }}
spec:
terminationGracePeriodSeconds: {{ .Values.shutdown.podTerminationGracePeriodSeconds }}
{{- if or .Values.persistence.takeOwnershipOnStartup .Values.extraTakeOwnershipPaths }}
initContainers:
{{- if eq (include "nifi.useZooKeeper" .) "true" }}
- name: wait-for-zookeeper
image: {{ .Values.global.busybox.repository }}
command:
- sh
- -c
- |
{{- if .Values.zookeeper.enabled }}
echo "Connecting to embedded ZooKeeper {{ .Release.Name }}-zookeeper"
until nc -vzw 1 {{ .Release.Name }}-zookeeper {{ .Values.zookeeper.external.port | default 2181 }} ; do
echo "Waiting for zookeeper to start"
sleep 3
done
{{- else }}
echo "Connecting to external ZooKeeper {{ .Values.zookeeper.external.url }}"
{{- if .Values.zookeeper.external.url }}
{{- range $url := splitList "," .Values.zookeeper.external.url }}
{{- $hostPort := splitList ":" $url }}
{{- if gt (len $hostPort) 1 }}
until nc -vzw 1 {{ index $hostPort 0 }} {{ index $hostPort 1 }} ; do
echo "Waiting for zookeeper {{ $url }} to start"
sleep 3
done
{{- else }}
until nc -vzw 1 {{ index $hostPort 0 }} 2181 ; do
echo "Waiting for zookeeper {{ $url }}:2181 to start"
sleep 3
done
{{- end }}
{{- end }}
{{- else }}
echo "No external ZooKeeper URL configured"
{{- end }}
{{- end }}
resources:
requests:
cpu: 20m
memory: 10Mi
limits:
cpu: 20m
memory: 10Mi
{{- else }}
- name: check-kubernetes-permissions
image: {{ .Values.global.busybox.repository }}
command:
- sh
- -c
- |
echo "Using Kubernetes state management for NiFi {{ .Chart.AppVersion }}"
echo "Checking Kubernetes API permissions..."
echo "Namespace: {{ include "nifi.stateManagementNamespace" . }}"
echo "Lease prefix: {{ .Values.stateManagement.kubernetes.leasePrefix }}"
echo "State prefix: {{ .Values.stateManagement.kubernetes.statePrefix }}"
echo "✅ Kubernetes state management configured"
resources:
requests:
cpu: 20m
memory: 10Mi
limits:
cpu: 20m
memory: 10Mi
{{- end }}
securityContext:
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
- name: take-ownership
image: {{ .Values.global.busybox.repository }}
command:
- sh
- -c
- |
{{- if .Values.persistence.takeOwnershipOnStartup }}
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/persistent_conf
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/state
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/logs
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/flowfile_repo
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/content_repo
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/provenance_repo
{{- end }}
{{- range .Values.extraTakeOwnershipPaths }}
chown {{ $.Values.securityContext.runAsUser | int64 }}:{{ $.Values.securityContext.runAsGroup | int64 }} {{ . | quote }}
{{- end }}
securityContext:
runAsUser: 0
runAsNonRoot: false
volumeMounts:
- name: config
mountPath: {{ $nifiHome }}/persistent_conf
- name: state
mountPath: {{ $nifiHome }}/state
- name: logs
mountPath: {{ $nifiHome }}/logs
{{- if .Values.persistence.takeOwnershipOnStartup }}
- name: flowfile
mountPath: {{ $nifiHome }}/flowfile_repo
- name: content
mountPath: {{ $nifiHome }}/content_repo
- name: provenance
mountPath: {{ $nifiHome }}/provenance_repo
{{- end }}
{{- with .Values.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: [ "../scripts/k8s/custom-startup.sh" ]
lifecycle:
preStop:
exec:
command: [ "../scripts/k8s/pre-stop.sh" ]
env:
- name: NIFI_SENSITIVE_PROPS_KEY
valueFrom:
secretKeyRef:
name: {{ default "encryption-sensitive-key" .Values.global.encryption.sensitivePropertiesKey.secretRef.name | quote }}
key: {{ default "sensitivekey" .Values.global.encryption.sensitivePropertiesKey.secretRef.key | quote }}
- name: NIFI_JVM_HEAP_INIT
value: {{ .Values.jvmHeap.min | quote }}
- name: NIFI_JVM_HEAP_MAX
value: {{ .Values.jvmHeap.max | quote }}
- name: NIFI_WEB_HTTPS_PORT
value: {{ .Values.ports.https | quote }}
- name: NIFI_REMOTE_INPUT_SOCKET_PORT
value: {{ .Values.ports.remoteinput | quote }}
- name: NIFI_CLUSTER_NODE_PROTOCOL_PORT
value: {{ .Values.ports.cluster | quote }}
- name: NIFI_CLUSTER_IS_NODE
value: "true"
- name: NIFI_ELECTION_MAX_CANDIDATES
value: {{ .Values.global.nifi.nodeCount | quote }}
{{- /* Common cluster environment variables (required for both state management strategies) */}}
{{- include "nifi.clusterEnvironment" . | nindent 12 }}
{{- if eq (include "nifi.useZooKeeper" .) "true" }}
{{- include "nifi.zookeeperStateEnvironment" . | nindent 12 }}
{{- else }}
{{- include "nifi.kubernetesStateEnvironment" . | nindent 12 }}
{{- end }}
{{- include "nifi.keystoreEnvironment" . | nindent 12 }}
{{- /* Authentication environment variables with priority: OIDC > LDAP > Basic Auth */}}
{{- if .Values.global.oidc.enabled }}
{{- /* OIDC has highest priority */}}
{{- include "nifi.oidcEnvironment" . | nindent 12 }}
{{- else if .Values.global.ldap.enabled }}
{{- /* LDAP is second priority (only if OIDC is disabled) */}}
{{- include "nifi.ldapEnvironment" . | nindent 12 }}
{{- else }}
{{- /* Basic auth is the default fallback (when both OIDC and LDAP are disabled) */}}
{{- include "nifi.basicAuthEnvironment" . | nindent 12 }}
{{- end }}
{{- with .Values.extraEnv }}
{{ toYaml . | nindent 12 }}
{{- end }}
ports:
{{- range $name, $number := .Values.ports }}
- name: {{ $name }}
containerPort: {{ $number }}
protocol: TCP
{{- end }}
{{- if .Values.extraPorts }}
{{- range $name, $port := .Values.extraPorts }}
- name: {{ $name }}
containerPort: {{ $port.containerPort }}
protocol: {{ $port.protocol | default "TCP" }}
{{- end }}
{{- end }}
volumeMounts:
- mountPath: {{ include "nifi.certPath" . }}
name: certs
readOnly: true
- mountPath: {{ include "nifi.tlsPath" . }}
name: tls
- mountPath: /opt/nifi/scripts/k8s
name: config-script
readOnly: true
- name: config
mountPath: {{ $nifiHome }}/persistent_conf
- name: state
mountPath: {{ $nifiHome }}/state
- name: logs
mountPath: {{ $nifiHome }}/logs
- name: flowfile
mountPath: {{ $nifiHome }}/flowfile_repo
- name: content
mountPath: {{ $nifiHome }}/content_repo
- name: provenance
mountPath: {{ $nifiHome }}/provenance_repo
{{- with .Values.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- if not .Values.debugStartup }}
startupProbe:
tcpSocket:
port: https
{{- toYaml .Values.probeTimings.startup | nindent 12 }}
readinessProbe:
exec:
command:
- sh
- -c
- curl -k -s https://${HOSTNAME}.{{ include "nifi.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.ports.https }}/nifi
{{- toYaml .Values.probeTimings.readiness | nindent 12 }}
livenessProbe:
exec:
command:
- sh
- -c
- curl -k -s https://${HOSTNAME}.{{ include "nifi.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.ports.https }}/nifi
{{- toYaml .Values.probeTimings.liveness | nindent 12 }}
{{- end }}
{{- if .Values.filebeat.enabled }}
- name: filebeat
image: {{ .Values.filebeat.image.repository }}:{{ .Values.filebeat.image.tag | default "latest" }}
args:
- -e
- -E
- http.enabled=true
volumeMounts:
- mountPath: /usr/share/filebeat/filebeat.yml
subPath: filebeat.yml
name: filebeat-config
readOnly: true
- mountPath: /nifi/logs
{{- with .Values.persistence.logs.volumeMount }}
name: {{ .name | default "logs" }}
{{- if .subPath }}
subPath: {{ .subPath }}
{{- end }}
{{- end }}
{{- with .Values.filebeat.volumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.filebeat.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
startupProbe:
exec:
command:
- sh
- -c
- |
#!/usr/bin/env bash -e
filebeat test input
{{- toYaml .Values.probeTimings.startup | nindent 12 }}
readinessProbe:
exec:
command:
- sh
- -c
- |
#!/usr/bin/env bash -e
filebeat test output
{{- toYaml .Values.probeTimings.readiness | nindent 12 }}
livenessProbe:
exec:
command:
- sh
- -c
- |
#!/usr/bin/env bash -e
curl --fail 127.0.0.1:5066
{{- toYaml .Values.probeTimings.liveness | nindent 12 }}
{{- end }}
volumes:
- name: certs
secret:
secretName: {{ include "nifi.fullname" . }}-tls # The secret created by cert-manager
optional: false # Secret must be present
- name: tls
emptyDir: { }
- name: config-script
configMap:
name: {{ include "nifi.fullname" . }}
defaultMode: 0554
{{- with .Values.persistence.logs.volumeMount }}
{{- /* Use an emptyDir volume if no persistence is configured */}}
{{- if not .name }}
- name: logs
emptyDir: { }
{{- end }}
{{- end }}
{{- with .Values.extraVolumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.filebeat }}
{{- if .enabled }}
- name: filebeat-config
configMap:
name: {{ include "nifi.fullname" $ }}-filebeat
{{- end }}
{{- end }}
{{- with .Values.global.serviceAccount }}
serviceAccountName: {{ .name | default (include "nifi.fullname" $) }}
{{- end }}
securityContext:
{{- toYaml .Values.securityContext | nindent 8 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
affinity:
{{- if .Values.affinity }}
{{- toYaml . | nindent 8 }}
{{- else }}
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchLabels:
{{- include "nifi.selectorLabels" . | nindent 20 }}
topologyKey: kubernetes.io/hostname
weight: 100
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.volumeClaims }}
volumeClaimTemplates:
{{- range $name, $volumeClaim := . }}
- metadata:
name: {{ $name }}
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: {{ $volumeClaim.size }}
storageClassName: {{ $volumeClaim.storageClass }}
{{- end }}
{{- end }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "nifi.fullname" . }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
spec:
type: ClusterIP
clusterIP: None
publishNotReadyAddresses: true
ports:
{{- range $name, $number := .Values.ports }}
- name: {{ $name }}
port: {{ $number }}
protocol: TCP
{{- end }}
selector:
{{- include "nifi.selectorLabels" . | nindent 4 }}