8000 StatefulSet support by haywoodsh · Pull Request #8159 · nginx/kubernetes-ingress · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
83f4a79
initial commit for statefulset
vepatel Jul 25, 2025
3b32076
support StatefulSet for integration test
haywoodsh Aug 19, 2025
4da3728
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 19, 2025
74c17bf
update pytest help and setting
haywoodsh Aug 20, 2025
8ebb07b
update rbac and pvc
haywoodsh Aug 28, 2025
2cb8bdd
update selector logic for headless svc
vepatel Aug 28, 2025
e3d5f70
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 28, 2025
2314a54
make format
vepatel Aug 28, 2025
cb0e524
update label selector logic for headless svc
vepatel Aug 28, 2025
9542d2b
add helm tests
haywoodsh Aug 29, 2025
1be8723
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 29, 2025
538c6be
update helm test
haywoodsh Aug 30, 2025
07f1147
remove helm test for shared pvc, create nginx-cache for statefulset b…
haywoodsh Sep 3, 2025
aaba782
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 3, 2025
e3f1ee0
edit helm value
haywoodsh Sep 4, 2025
f9c37e5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 4, 2025
8d965a6
update schema
haywoodsh Sep 4, 2025
a0f2270
add missing test data
haywoodsh Sep 4, 2025
877fe67
update helm test
haywoodsh Sep 4, 2025
06ecb27
update helm comments
haywoodsh Sep 4, 2025
2aa3d82
Fix default image version and replica count
haywoodsh Sep 5, 2025
6a15b48
remove redundant line
haywoodsh Sep 5, 2025
0c9fcd5
Merge branch 'main' into feat/statefulset-nic
haywoodsh Sep 5, 2025
a7cf6fb
return err
vepatel Sep 5, 2025
f21d154
Merge branch 'main' into feat/statefulset-nic
vepatel Sep 5, 2025
e33f47c
Merge branch 'main' into feat/statefulset-nic
haywoodsh Sep 5, 2025
54773c1
fix indentation
haywoodsh Sep 5, 2025
4f0fead
Merge branch 'main' into feat/statefulset-nic
vepatel Sep 5, 2025
90c1b9f
remove redundant logging
vepatel Sep 5, 2025
f54355f
Merge branch 'main' into feat/statefulset-nic
haywoodsh Sep 8, 2025
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
10 changes: 8 additions & 2 deletions charts/nginx-ingress/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -391,14 +391,17 @@ List of volumes for controller.
{{- if eq (include "nginx-ingress.readOnlyRootFilesystem" .) "true" }}
- name: nginx-etc
emptyDir: {}
- name: nginx-cache
emptyDir: {}
- name: nginx-lib
emptyDir: {}
- name: nginx-state
emptyDir: {}
- name: nginx-log
emptyDir: {}
{{- /* For StatefulSet, nginx-cache volume is always provided via volumeClaimTemplates */ -}}
{{- if ne .Values.controller.kind "statefulset" }}
- name: nginx-cache
emptyDir: {}
{{- end }}
{{- end }}
{{- if .Values.controller.appprotect.v5 }}
{{ toYaml .Values.controller.appprotect.volumes }}
Expand Down Expand Up @@ -458,6 +461,9 @@ volumeMounts:
name: nginx-state
- mountPath: /var/log/nginx
name: nginx-log
{{- else if eq .Values.controller.kind "statefulset" }}
- mountPath: /var/cache/nginx
name: nginx-cache
{{- end }}
{{- if .Values.controller.appprotect.v5 }}
- name: app-protect-bd-config
Expand Down
1 change: 1 addition & 0 deletions charts/nginx-ingress/templates/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ rules:
resources:
- replicasets
- daemonsets
- statefulsets
verbs:
- get
- apiGroups:
Expand Down
240 changes: 240 additions & 0 deletions charts/nginx-ingress/templates/controller-statefulset.yaml
CB5A
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
{{- if eq .Values.controller.kind "statefulset" }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "nginx-ingress.controller.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "nginx-ingress.labels" . | nindent 4 }}
{{- if .Values.controller.annotations }}
annotations: {{ toYaml .Values.controller.annotations | nindent 4 }}
{{- end }}
spec:
{{- if not .Values.controller.autoscaling.enabled }}
replicas: {{ .Values.controller.replicaCount }}
{{- end }}
serviceName: {{ include "nginx-ingress.controller.service.name" . }}
selector:
matchLabels:
{{- include "nginx-ingress.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "nginx-ingress.podLabels" . | nindent 8 }}
{{- if or .Values.prometheus.create .Values.controller.pod.annotations }}
annotations:
{{- if .Values.prometheus.create }}
prometheus.io/scrape: "true"
prometheus.io/port: "{{ .Values.prometheus.port }}"
prometheus.io/scheme: "{{ .Values.prometheus.scheme }}"
{{- end }}
{{- if .Values.controller.pod.annotations }}
{{ toYaml .Values.controller.pod.annotations | indent 8 }}
{{- end }}
{{- end }}
spec:
{{- if .Values.controller.nodeSelector }}
nodeSelector:
{{ toYaml .Values.controller.nodeSelector | indent 8 }}
{{- end }}
{{- if .Values.controller.tolerations }}
tolerations:
{{ toYaml .Values.controller.tolerations | indent 6 }}
{{- end }}
{{- if .Values.controller.affinity }}
affinity:
{{ toYaml .Values.controller.affinity | indent 8 }}
{{- end }}
{{- if .Values.controller.topologySpreadConstraints }}
topologySpreadConstraints:
{{ toYaml .Values.controller.topologySpreadConstraints | indent 8 }}
{{- end }}
{{- include "nginx-ingress.volumes" . | indent 6 }}
{{- if .Values.controller.priorityClassName }}
priorityClassName: {{ .Values.controller.priorityClassName }}
{{- end }}
serviceAccountName: {{ include "nginx-ingress.serviceAccountName" . }}
automountServiceAccountToken: true
securityContext:
{{ toYaml .Values.controller.podSecurityContext | indent 8 }}
terminationGracePeriodSeconds: {{ .Values.controller.terminationGracePeriodSeconds }}
hostNetwork: {{ .Values.controller.hostNetwork }}
dnsPolicy: {{ .Values.controller.dnsPolicy }}
{{- if .Values.controller.shareProcessNamespace }}
shareProcessNamespace: true
{{- end }}
containers:
- image: {{ include "nginx-ingress.image" . }}
name: {{ include "nginx-ingress.name" . }}
imagePullPolicy: "{{ .Values.controller.image.pullPolicy }}"
{{- if .Values.controller.lifecycle }}
lifecycle:
{{ toYaml .Values.controller.lifecycle | indent 10 }}
{{- end }}
ports:
{{- range $key, $value := .Values.controller.containerPort }}
- name: {{ $key }}
containerPort: {{ $value }}
protocol: TCP
{{- if and $.Values.controller.hostPort.enable (index $.Values.controller.hostPort $key) }}
hostPort: {{ index $.Values.controller.hostPort $key }}
{{- end }}
{{- end }}
{{- if .Values.controller.customPorts }}
{{ toYaml .Values.controller.customPorts | indent 8 }}
{{- end }}
{{- if .Values.prometheus.create }}
- name: prometheus
containerPort: {{ .Values.prometheus.port }}
{{- end }}
{{- if .Values.serviceInsight.create }}
- name: service-insight
containerPort: {{ .Values.serviceInsight.port }}
{{- end }}
{{- if .Values.controller.readyStatus.enable }}
- name: readiness-port
containerPort: {{ .Values.controller.readyStatus.port }}
{{- end }}
{{- if .Values.controller.startupStatus.enable }}
- name: startup-port
containerPort: {{ .Values.controller.startupStatus.port }}
{{- end }}
{{- if .Values.controller.readyStatus.enable }}
readinessProbe:
httpGet:
path: /nginx-ready
port: readiness-port
periodSeconds: 1
initialDelaySeconds: {{ .Values.controller.readyStatus.initialDelaySeconds }}
{{- end }}
{{- if .Values.controller.startupStatus.enable }}
startupProbe:
httpGet:
path: {{ .Values.controller.startupStatus.path }}
port: startup-port
initialDelaySeconds: {{ .Values.controller.startupStatus.initialDelaySeconds }}
periodSeconds: {{ .Values.controller.startupStatus.periodSeconds }}
timeoutSeconds: {{ .Values.controller.startupStatus.timeoutSeconds }}
successThreshold: {{ .Values.controller.startupStatus.successThreshold }}
failureThreshold: {{ .Values.controller.startupStatus.failureThreshold }}
{{- end }}
resources:
{{ toYaml .Values.controller.resources | indent 10 }}
{{- if .Values.controller.securityContext }}
securityContext:
{{ toYaml .Values.controller.securityContext | indent 10 }}
{{- else }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: {{ .Values.controller.readOnlyRootFilesystem }}
runAsUser: 101 #nginx
runAsNonRoot: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
{{- end }}
{{- include "nginx-ingress.volumeMounts" . | indent 8 }}
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
{{- if .Values.controller.env }}
{{ toYaml .Values.controller.env | indent 8 }}
{{- end }}
{{- if .Values.nginxServiceMesh.enable }}
- name: POD_SERVICEACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
{{- end }}
{{- if hasKey .Values.controller.mgmt "usageReport" -}}
{{- if hasKey .Values.controller.mgmt.usageReport "proxyCredentialsSecretName" }}
{{- if not (hasKey .Values.controller.mgmt.usageRep 4066 ort "proxyHost") -}}
{{- fail "Error: 'controller.mgmt.usageReport.proxyHost' must be set when using 'controller.mgmt.usageReport.proxyCredentialsSecretName'." }}
{{- end }}
- name: PROXY_USER
valueFrom:
secretKeyRef:
name: {{ .Values.controller.mgmt.usageReport.proxyCredentialsSecretName }}
key: username
- name: PROXY_PASS
valueFrom:
secretKeyRef:
name: {{ .Values.controller.mgmt.usageReport.proxyCredentialsSecretName }}
key: password
{{- end }}
{{- end }}
args:
{{- include "nginx-ingress.args" . | nindent 10 }}
{{- if .Values.controller.extraContainers }}
{{ toYaml .Values.controller.extraContainers | nindent 6 }}
{{- end }}

{{- include "nginx-ingress.appprotect.v5" . | nindent 6 }}

{{- if or ( eq (include "nginx-ingress.readOnlyRootFilesystem" .) "true" ) .Values.controller.initContainers }}
initContainers:
{{- end }}
{{- if eq (include "nginx-ingress.readOnlyRootFilesystem" .) "true" }}
- name: init-{{ include "nginx-ingress.name" . }}
image: {{ include "nginx-ingress.image" . }}
imagePullPolicy: "{{ .Values.controller.image.pullPolicy }}"
command: ['cp', '-vdR', '/etc/nginx/.', '/mnt/etc']
{{- if .Values.controller.initContainerResources }}
resources:
{{ toYaml .Values.controller.initContainerResources | indent 10 }}
{{- end }}
{{- if .Values.controller.initContainerSecurityContext }}
securityContext:
{{ toYaml .Values.controller.initContainerSecurityContext | indent 10 }}
{{- else }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 101 #nginx
runAsNonRoot: true
capabilities:
drop:
- ALL
{{- end }}
volumeMounts:
- mountPath: /mnt/etc
name: nginx-etc
{{- end }}
{{- if .Values.controller.initContainers }}
{{ toYaml .Values.controller.initContainers | indent 6 }}
{{- end }}
{{- if .Values.controller.strategy }}
updateStrategy:
{{ toYaml .Values.controller.strategy | indent 4 }}
{{- end }}
{{- if .Values.controller.minReadySeconds }}
minReadySeconds: {{ .Values.controller.minReadySeconds }}
{{- end }}
{{- if .Values.controller.statefulset.podManagementPolicy }}
podManagementPolicy: {{ .Values.controller.statefulset.podManagementPolicy }}
{{- end }}
{{- if .Values.controller.statefulset.persistentVolumeClaimRetentionPolicy }}
persistentVolumeClaimRetentionPolicy:
{{ toYaml .Values.controller.statefulset.persistentVolumeClaimRetentionPolicy | indent 4 }}
{{- end }}
volumeClaimTemplates:
- metadata:
name: nginx-cache
spec:
accessModes:
{{ toYaml .Values.controller.statefulset.nginxCachePVC.accessModes | indent 8 }}
{{- if .Values.controller.statefulset.nginxCachePVC.storageClass }}
storageClassName: {{ .Values.controller.statefulset.nginxCachePVC.storageClass | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.controller.statefulset.nginxCachePVC.size | quote }}
{{- end }}
55 changes: 53 additions & 2 deletions charts/nginx-ingress/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@
"title": "The kind of the Ingress Controller",
"enum": [
"deployment",
"daemonset"
"daemonset",
"statefulset"
],
"examples": [
"deployment",
"daemonset"
"daemonset",
"statefulset"
]
},
"selectorLabels": {
Expand Down Expand Up @@ -994,6 +996,55 @@
}
]
},
"statefulset": {
"type": "object",
"default": {},
"title": "The StatefulSet configuration Schema",
"properties": {
"podManagementPolicy": {
"type": "string",
"default": "OrderedReady",
"title": "The pod management policy",
"enum": [
"OrderedReady",
"Parallel"
]
},
"persistentVolumeClaimRetentionPolicy": {
"type": "object",
"default": {},
"title": "The persistentVolumeClaimRetentionPolicy Schema",
"$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.33.1/_definitions.json#/definitions/io.k8s.api.apps.v1.StatefulSetPersistentVolumeClaimRetentionPolicy"
},
"nginxCachePVC": {
"type": "object",
"default": {},
"title": "The nginxCachePVC Schema",
"properties": {
"size": {
"type": "string",
"default": "256Mi",
"title": "The size Schema",
"$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.33.1/_definitions.json#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity"
},
"storageClass": {
"type": "string",
"title": "The storageClass Schema",
"default": "",
"$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.33.1/_definitions.json#/definitions/io.k8s.api.core.v1.PersistentVolumeClaimSpec/properties/storageClassName"
},
"accessModes": {
"type": "array",
"default": [
"ReadWriteOnce"
],
"title": "The accessModes Schema",
"$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.33.1/_definitions.json#/definitions/io.k8s.api.core.v1.PersistentVolumeClaimSpec/properties/accessModes"
}
}
}
}
},
"extraContainers": {
"type": "array",
"default": [],
Expand Down
28 changes: 26 additions & 2 deletions charts/nginx-ingress/values.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
controller:
## The name of the Ingress Controller daemonset or deployment.
## The name of the Ingress Controller daemonset, deployment, or statefulset.
name: controller

## The kind of the Ingress Controller installation - deployment or daemonset.
## The kind of the Ingress Controller installation - deployment, daemonset, or statefulset.
kind: deployment

## The selectorLabels used to override the default values.
Expand Down Expand Up @@ -344,6 +344,30 @@ controller:
## Strategy used to replace old Pods by new ones. .spec.strategy.type can be "Recreate" or "RollingUpdate" for Deployments, and "OnDelete" or "RollingUpdate" for Daemonsets. "RollingUpdate" is the default value.
strategy: {}

## StatefulSet-specific configuration (only used when kind is "statefulset")
statefulset:
## Pod management policy for StatefulSet. Can be "OrderedReady" or "Parallel".
## OrderedReady will start pods one at a time in order, Parallel will start all pods at once.
podManagementPolicy: "OrderedReady"

## PersistentVolumeClaim retention policy for StatefulSet
## Determines when to delete PVCs when the StatefulSet is deleted or scaled down
persistentVolumeClaimRetentionPolicy:
## When to delete PVCs when the StatefulSet is deleted. Can be "Retain" or "Delete".
whenDeleted: "Retain"
## When to delete PVCs when the StatefulSet is scaled down. Can be "Retain" or "Delete".
whenScaled: "Retain"

## Configuration for StatefulSet nginx-cache PVC
nginxCachePVC:
## Storage size for the nginx-cache volume
size: "256Mi"
## Storage class for the nginx-cache volume. If empty, uses the cluster default.
storageClass: ""
## Access modes for the nginx-cache volume
accessModes:
- "ReadWriteOnce"

## Extra containers for the Ingress Controller pods.
extraContainers: []
# - name: container
Expand Down
Loading
Loading
0