jina verze

This commit is contained in:
2026-08-12 11:08:28 +02:00
parent afdc3e9013
commit 9ccebe4a59
109 changed files with 0 additions and 19938 deletions
-4
View File
@@ -1,4 +0,0 @@
apiVersion: v2
name: stack
version: 0.1.0
type: application
@@ -1,16 +0,0 @@
profiles:
mariadbMaster:
cpuRequest: 1000m
cpuLimit: 4000m
threadPoolSize: 4
mariadbSlave:
cpuRequest: 250m
cpuLimit: 1000m
threadPoolSize: 1
redis:
cpuRequest: 250m
cpuLimit: 1000m
maxClients: 20000
openlitespeed:
cpuRequest: 3000m
cpuLimit: 7000m
@@ -1,16 +0,0 @@
profiles:
mariadbMaster:
cpuRequest: 2000m
cpuLimit: 8000m
threadPoolSize: 6
mariadbSlave:
cpuRequest: 500m
cpuLimit: 2000m
threadPoolSize: 1
redis:
cpuRequest: 750m
cpuLimit: 4000m
maxClients: 30000
openlitespeed:
cpuRequest: 5000m
cpuLimit: 12000m
@@ -1,16 +0,0 @@
profiles:
mariadbMaster:
cpuRequest: 500m
cpuLimit: 1500m
threadPoolSize: 2
mariadbSlave:
cpuRequest: 100m
cpuLimit: 500m
threadPoolSize: 1
redis:
cpuRequest: 100m
cpuLimit: 500m
maxClients: 8000
openlitespeed:
cpuRequest: 750m
cpuLimit: 2000m
@@ -1,16 +0,0 @@
profiles:
mariadbMaster:
cpuRequest: 750m
cpuLimit: 2500m
threadPoolSize: 3
mariadbSlave:
cpuRequest: 200m
cpuLimit: 750m
threadPoolSize: 1
redis:
cpuRequest: 150m
cpuLimit: 750m
maxClients: 12000
openlitespeed:
cpuRequest: 1250m
cpuLimit: 3000m
@@ -1,26 +0,0 @@
profiles:
mariadbMaster:
memoryRequest: 28Gi
memoryLimit: 40Gi
maxConnections: 600
innodbBufferPoolSize: 30G
innodbBufferPoolInstances: 16
tableOpenCache: 16000
tableOpenCacheInstances: 16
tmpTableSize: 64M
mariadbSlave:
memoryRequest: 8Gi
memoryLimit: 12Gi
maxConnections: 50
innodbBufferPoolSize: 8G
innodbBufferPoolInstances: 8
tableOpenCache: 8000
tableOpenCacheInstances: 8
tmpTableSize: 64M
redis:
memoryRequest: 2Gi
memoryLimit: 5Gi
maxmemory: 3500mb
openlitespeed:
memoryRequest: 8Gi
memoryLimit: 24Gi
@@ -1,26 +0,0 @@
profiles:
mariadbMaster:
memoryRequest: 2Gi
memoryLimit: 4Gi
maxConnections: 80
innodbBufferPoolSize: 2G
innodbBufferPoolInstances: 2
tableOpenCache: 2000
tableOpenCacheInstances: 4
tmpTableSize: 8M
mariadbSlave:
memoryRequest: 512Mi
memoryLimit: 1Gi
maxConnections: 30
innodbBufferPoolSize: 512M
innodbBufferPoolInstances: 1
tableOpenCache: 1000
tableOpenCacheInstances: 2
tmpTableSize: 8M
redis:
memoryRequest: 128Mi
memoryLimit: 512Mi
maxmemory: 350mb
openlitespeed:
memoryRequest: 2Gi
memoryLimit: 4Gi
@@ -1,26 +0,0 @@
profiles:
mariadbMaster:
memoryRequest: 4Gi
memoryLimit: 8Gi
maxConnections: 150
innodbBufferPoolSize: 5G
innodbBufferPoolInstances: 5
tableOpenCache: 4000
tableOpenCacheInstances: 8
tmpTableSize: 16M
mariadbSlave:
memoryRequest: 1Gi
memoryLimit: 2Gi
maxConnections: 50
innodbBufferPoolSize: 1G
innodbBufferPoolInstances: 1
tableOpenCache: 2000
tableOpenCacheInstances: 4
tmpTableSize: 16M
redis:
memoryRequest: 256Mi
memoryLimit: 1Gi
maxmemory: 700mb
openlitespeed:
memoryRequest: 3Gi
memoryLimit: 6Gi
@@ -1,26 +0,0 @@
profiles:
mariadbMaster:
memoryRequest: 8Gi
memoryLimit: 16Gi
maxConnections: 250
innodbBufferPoolSize: 10G
innodbBufferPoolInstances: 10
tableOpenCache: 8000
tableOpenCacheInstances: 16
tmpTableSize: 32M
mariadbSlave:
memoryRequest: 2Gi
memoryLimit: 4Gi
maxConnections: 50
innodbBufferPoolSize: 2G
innodbBufferPoolInstances: 2
tableOpenCache: 4000
tableOpenCacheInstances: 8
tmpTableSize: 32M
redis:
memoryRequest: 512Mi
memoryLimit: 2Gi
maxmemory: 1500mb
openlitespeed:
memoryRequest: 8Gi
memoryLimit: 16Gi
@@ -1,19 +0,0 @@
{{- if .Values.debugHelm }}
---
apiVersion: v1
kind: Pod
metadata: { name: debug, namespace: "{{ .Values.namespace }}" }
spec:
containers:
- name: debug
image: nicolaka/netshoot:latest
command: ["sh","-c","sleep infinity"]
stdin: true
tty: true
securityContext:
capabilities:
add: ["NET_RAW","NET_ADMIN"] # for tcpdump/mtr
restartPolicy: Never
{{- end }}
@@ -1,299 +0,0 @@
{{- if .Values.mariadbHelm }}
---
apiVersion: v1
kind: ConfigMap
metadata: { name: "{{ .Values.mariadbMaster }}-config", namespace: "{{ .Values.namespace }}" }
data:
replication.cnf: |
[mysqld]
skip_name_resolve=1
server-id=1
# --- log ---
log_bin=mysql-bin
binlog_format=ROW
binlog_expire_logs_seconds=604800
max_binlog_total_size=32212254720
# --- durability ---
innodb_flush_log_at_trx_commit=1
sync_binlog=1
# --- connection / thread pool ---
max_connections={{ .Values.profiles.mariadbMaster.maxConnections }}
thread_handling=pool-of-threads
thread_pool_size={{ .Values.profiles.mariadbMaster.threadPoolSize }}
thread_pool_max_threads=128
thread_pool_stall_limit=500
innodb_buffer_pool_size={{ .Values.profiles.mariadbMaster.innodbBufferPoolSize }}
innodb_buffer_pool_instances={{ .Values.profiles.mariadbMaster.innodbBufferPoolInstances }}
innodb_flush_method=O_DIRECT
innodb_flush_neighbors=0
innodb_io_capacity=2000
innodb_io_capacity_max=4000
innodb_log_file_size=1G
innodb_log_buffer_size=64M
# --- cache ---
query_cache_type=0
query_cache_size=0
table_open_cache={{ .Values.profiles.mariadbMaster.tableOpenCache }}
table_open_cache_instances={{ .Values.profiles.mariadbMaster.tableOpenCacheInstances }}
table_definition_cache={{ .Values.profiles.mariadbMaster.tableOpenCache }}
open_files_limit=65535
# --- buffers ---
tmp_table_size={{ .Values.profiles.mariadbMaster.tmpTableSize }}
max_heap_table_size={{ .Values.profiles.mariadbMaster.tmpTableSize }}
sort_buffer_size=2M
join_buffer_size=2M
read_buffer_size=256K
read_rnd_buffer_size=512K
# --- timeouts ---
wait_timeout=60
interactive_timeout=300
max_allowed_packet=64M
slow_query_log=1
long_query_time=1
slow_query_log_file=/var/lib/mysql/slow.log
log_error=/var/lib/mysql/error.log
---
apiVersion: v1
kind: ConfigMap
metadata: { name: "{{ .Values.mariadbSlave }}-config", namespace: "{{ .Values.namespace }}" }
data:
replication.cnf: |
[mysqld]
skip_name_resolve=1
server-id=2
read_only=1
# --- log ---
relay-log=relay-log
relay_log_purge=1
relay_log_recovery=1
# --- connection / thread pool ---
max_connections={{ .Values.profiles.mariadbSlave.maxConnections }}
thread_handling=pool-of-threads
thread_pool_size={{ .Values.profiles.mariadbSlave.threadPoolSize }}
thread_pool_max_threads=32
thread_pool_stall_limit=500
# --- InnoDB ---
innodb_buffer_pool_size={{ .Values.profiles.mariadbSlave.innodbBufferPoolSize }}
innodb_buffer_pool_instances={{ .Values.profiles.mariadbSlave.innodbBufferPoolInstances }}
innodb_flush_method=O_DIRECT
innodb_flush_neighbors=0
innodb_io_capacity=1000
innodb_io_capacity_max=2000
innodb_log_file_size=512M
innodb_log_buffer_size=32M
# --- durability (for standby recovery replica) ---
innodb_flush_log_at_trx_commit=1
sync_binlog=1
# --- cache ---
query_cache_type=0
query_cache_size=0
table_open_cache={{ .Values.profiles.mariadbSlave.tableOpenCache }}
table_open_cache_instances={{ .Values.profiles.mariadbSlave.tableOpenCacheInstances }}
table_definition_cache={{ .Values.profiles.mariadbSlave.tableOpenCache }}
open_files_limit=65535
# --- buffers ---
tmp_table_size={{ .Values.profiles.mariadbSlave.tmpTableSize }}
max_heap_table_size={{ .Values.profiles.mariadbSlave.tmpTableSize }}
sort_buffer_size=1M
join_buffer_size=1M
read_buffer_size=256K
read_rnd_buffer_size=512K
# --- timeouts ---
wait_timeout=60
interactive_timeout=300
max_allowed_packet=64M
# --- logs ---
slow_query_log=0
log_error=/var/lib/mysql/error.log
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.mariadbMaster }}-pv" }
spec:
capacity: { storage: 100Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteOnce ]
persistentVolumeReclaimPolicy: Retain
hostPath: { path: "{{ .Values.mariadbMasterPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.mariadbMaster }}-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.mariadbMaster }}-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteOnce ]
resources: { requests: { storage: 100Gi } }
storageClassName: ""
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.mariadbSlave }}-pv" }
spec:
capacity: { storage: 100Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteOnce ]
persistentVolumeReclaimPolicy: Retain
hostPath: { path: "{{ .Values.mariadbSlavePath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.mariadbSlave }}-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.mariadbSlave }}-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteOnce ]
resources: { requests: { storage: 100Gi } }
storageClassName: ""
---
apiVersion: apps/v1
kind: StatefulSet
metadata: { name: "{{ .Values.mariadbMaster }}", namespace: "{{ .Values.namespace }}" }
spec:
serviceName: "{{ .Values.mariadbMaster }}-headless"
replicas: 1
selector: { matchLabels: { app: "{{ .Values.mariadbMaster }}" } }
template:
metadata: { labels: { app: "{{ .Values.mariadbMaster }}" } }
spec:
terminationGracePeriodSeconds: 60
containers:
- name: "{{ .Values.mariadbMaster }}"
image: mariadb:12.2
resources:
requests: { cpu: "{{ .Values.profiles.mariadbMaster.cpuRequest }}", memory: "{{ .Values.profiles.mariadbMaster.memoryRequest }}" }
limits: { cpu: "{{ .Values.profiles.mariadbMaster.cpuLimit }}", memory: "{{ .Values.profiles.mariadbMaster.memoryLimit }}" }
ports:
- { containerPort: 3306 }
env:
- { name: MARIADB_ROOT_PASSWORD, valueFrom: { secretKeyRef: { name: "{{ .Values.mariadb }}-secret", key: root-password } } }
readinessProbe:
exec:
command: ["sh","-lc",'mariadb-admin ping -h 127.0.0.1 -uroot -p"$MARIADB_ROOT_PASSWORD" --silent']
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 6
livenessProbe:
exec:
command: ["sh","-lc",'mariadb-admin ping -h 127.0.0.1 -uroot -p"$MARIADB_ROOT_PASSWORD" --silent']
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
volumeMounts:
- { name: "{{ .Values.mariadbMaster }}-volume", mountPath: /var/lib/mysql }
- { name: "{{ .Values.mariadbMaster }}-config-volume", mountPath: /etc/mysql/conf.d/replication.cnf, subPath: replication.cnf }
volumes:
- name: "{{ .Values.mariadbMaster }}-volume"
persistentVolumeClaim: { claimName: "{{ .Values.mariadbMaster }}-pvc" }
- name: "{{ .Values.mariadbMaster }}-config-volume"
configMap: { name: "{{ .Values.mariadbMaster }}-config" }
---
apiVersion: apps/v1
kind: StatefulSet
metadata: { name: "{{ .Values.mariadbSlave }}", namespace: "{{ .Values.namespace }}" }
spec:
serviceName: "{{ .Values.mariadbSlave }}-headless"
replicas: 1
selector: { matchLabels: { app: "{{ .Values.mariadbSlave }}" } }
template:
metadata: { labels: { app: "{{ .Values.mariadbSlave }}" } }
spec:
terminationGracePeriodSeconds: 60
containers:
- name: "{{ .Values.mariadbSlave }}"
image: mariadb:12.2
resources:
requests: { cpu: "{{ .Values.profiles.mariadbSlave.cpuRequest }}", memory: "{{ .Values.profiles.mariadbSlave.memoryRequest }}" }
limits: { cpu: "{{ .Values.profiles.mariadbSlave.cpuLimit }}", memory: "{{ .Values.profiles.mariadbSlave.memoryLimit }}" }
ports:
- { containerPort: 3306 }
env:
- { name: MARIADB_ROOT_PASSWORD, valueFrom: { secretKeyRef: { name: "{{ .Values.mariadb }}-secret", key: root-password } } }
readinessProbe:
exec:
command: ["sh","-lc",'mariadb-admin ping -h 127.0.0.1 -uroot -p"$MARIADB_ROOT_PASSWORD" --silent']
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 6
livenessProbe:
exec:
command: ["sh","-lc",'mariadb-admin ping -h 127.0.0.1 -uroot -p"$MARIADB_ROOT_PASSWORD" --silent']
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
volumeMounts:
- { name: "{{ .Values.mariadbSlave }}-volume", mountPath: /var/lib/mysql }
- { name: "{{ .Values.mariadbSlave }}-config-volume", mountPath: /etc/mysql/conf.d/replication.cnf, subPath: replication.cnf }
volumes:
- name: "{{ .Values.mariadbSlave }}-volume"
persistentVolumeClaim: { claimName: "{{ .Values.mariadbSlave }}-pvc" }
- name: "{{ .Values.mariadbSlave }}-config-volume"
configMap: { name: "{{ .Values.mariadbSlave }}-config" }
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.mariadbMaster }}", namespace: "{{ .Values.namespace }}" }
spec:
selector: { app: "{{ .Values.mariadbMaster }}" }
ports: [ { name: mysql, protocol: TCP, port: 3306, targetPort: 3306 } ]
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.mariadbSlave }}", namespace: "{{ .Values.namespace }}" }
spec:
selector: { app: "{{ .Values.mariadbSlave }}" }
ports: [ { name: mysql, protocol: TCP, port: 3306, targetPort: 3306 } ]
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.mariadbMaster }}-headless", namespace: "{{ .Values.namespace }}" }
spec:
clusterIP: None
selector: { app: "{{ .Values.mariadbMaster }}" }
ports:
- { name: mysql, protocol: TCP, port: 3306, targetPort: 3306 }
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.mariadbSlave }}-headless", namespace: "{{ .Values.namespace }}" }
spec:
clusterIP: None
selector: { app: "{{ .Values.mariadbSlave }}" }
ports:
- { name: mysql, protocol: TCP, port: 3306, targetPort: 3306 }
{{- end }}
@@ -1,128 +0,0 @@
{{- if .Values.metricHelm }}
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.metric }}-node-exporter", namespace: "{{ .Values.namespace }}" }
spec:
selector: { app: "{{ .Values.metric }}-node-exporter" }
ports: [ { name: metrics, protocol: TCP, port: 9100, targetPort: 9100 } ]
---
apiVersion: apps/v1
kind: DaemonSet
metadata: { name: "{{ .Values.metric }}-node-exporter", namespace: "{{ .Values.namespace }}" }
spec:
selector:
matchLabels: { app: "{{ .Values.metric }}-node-exporter" }
template:
metadata:
labels: { app: "{{ .Values.metric }}-node-exporter" }
spec:
hostNetwork: true
hostPID: true
dnsPolicy: ClusterFirstWithHostNet
tolerations:
- operator: "Exists"
containers:
- name: "{{ .Values.metric }}-node-exporter"
image: quay.io/prometheus/node-exporter:v1.8.2
args:
- --web.listen-address=:9100
- --path.procfs=/host/proc
- --path.sysfs=/host/sys
- --path.rootfs=/host/root
- --collector.textfile.directory={{ .Values.metricPromPath }}
ports: [ { containerPort: 9100, hostPort: 9100, name: metrics } ]
resources:
requests: { cpu: "10m", memory: "32Mi" }
limits: { cpu: "150m", memory: "200Mi" }
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
volumeMounts:
- { name: proc, mountPath: /host/proc, readOnly: true }
- { name: sys, mountPath: /host/sys, readOnly: true }
- { name: root, mountPath: /host/root, readOnly: true }
- { name: textfile, mountPath: "{{ .Values.metricPromPath }}", readOnly: true }
volumes:
- name: proc
hostPath: { path: /proc, type: Directory }
- name: sys
hostPath: { path: /sys, type: Directory }
- name: root
hostPath: { path: /, type: Directory }
- name: textfile
hostPath: { path: "{{ .Values.metricPromPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: ServiceAccount
metadata: { name: "{{ .Values.metric }}-vmagent", namespace: "{{ .Values.namespace }}" }
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata: { name: "{{ .Values.metric }}-vmagent" }
rules:
- apiGroups: [""]
resources: ["nodes", "nodes/proxy", "services", "endpoints", "pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["discovery.k8s.io"]
resources: ["endpointslices"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata: { name: "{{ .Values.metric }}-vmagent" }
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: "{{ .Values.metric }}-vmagent"
subjects:
- kind: ServiceAccount
name: "{{ .Values.metric }}-vmagent"
namespace: "{{ .Values.namespace }}"
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.metric }}-vmagent", namespace: "{{ .Values.namespace }}" }
spec:
selector: { app: "{{ .Values.metric }}-vmagent" }
ports: [ { name: http, protocol: TCP, port: 8429, targetPort: 8429 } ]
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: "{{ .Values.metric }}-vmagent", namespace: "{{ .Values.namespace }}" }
spec:
replicas: 1
selector:
matchLabels: { app: "{{ .Values.metric }}-vmagent" }
template:
metadata:
labels: { app: "{{ .Values.metric }}-vmagent" }
spec:
serviceAccountName: "{{ .Values.metric }}-vmagent"
containers:
- name: "{{ .Values.metric }}-vmagent"
image: victoriametrics/vmagent:v1.112.0
args:
- -promscrape.config=/etc/vmagent/vmagent.yml
- -httpListenAddr=:8429
- -loggerLevel=INFO
- -remoteWrite.url={{ .Values.metricApiUrl }}
- -remoteWrite.label=server={{ .Values.namespace }}
ports: [ { containerPort: 8429, name: http } ]
resources:
requests: { cpu: "30m", memory: "128Mi" }
limits: { cpu: "300m", memory: "512Mi" }
volumeMounts:
- { name: "{{ .Values.metric }}-vmagent-config-volume", mountPath: /etc/vmagent/vmagent.yml, subPath: vmagent.yml, readOnly: true }
volumes:
- name: "{{ .Values.metric }}-vmagent-config-volume"
hostPath: { path: "{{ .Values.metricVmagentPath }}", type: DirectoryOrCreate }
{{- end }}
@@ -1,301 +0,0 @@
{{- if .Values.openlitespeedHelm }}
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.openlitespeed }}-vhosts-pv" }
spec:
capacity: { storage: 500Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
persistentVolumeReclaimPolicy: Retain
hostPath: { path: "{{ .Values.vhostsPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.openlitespeed }}-vhosts-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.openlitespeed }}-vhosts-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
resources: { requests: { storage: 500Gi } }
storageClassName: ""
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.openlitespeed }}-config-pv" }
spec:
capacity: { storage: 1Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
persistentVolumeReclaimPolicy: Retain
hostPath: { path: "{{ .Values.openlitespeedConfigPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.openlitespeed }}-config-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.openlitespeed }}-config-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
resources: { requests: { storage: 1Gi } }
storageClassName: ""
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.openlitespeed }}-admin-pv" }
spec:
capacity: { storage: 1Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
persistentVolumeReclaimPolicy: Retain
hostPath: { path: "{{ .Values.openlitespeedAdminPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.openlitespeed }}-admin-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.openlitespeed }}-admin-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
resources: { requests: { storage: 1Gi } }
storageClassName: ""
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.openlitespeed }}-phpini-pv" }
spec:
capacity: { storage: 1Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
persistentVolumeReclaimPolicy: Retain
hostPath: { path: "{{ .Values.openlitespeedPhpIniPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.openlitespeed }}-phpini-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.openlitespeed }}-phpini-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
resources: { requests: { storage: 1Gi } }
storageClassName: ""
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.openlitespeed }}-logs-pv" }
spec:
capacity: { storage: 10Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
hostPath: { path: "{{ .Values.openlitespeedLogsPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.openlitespeed }}-logs-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.openlitespeed }}-logs-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
resources: { requests: { storage: 10Gi } }
storageClassName: ""
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.openlitespeed }}-vhost-data-pv" }
spec:
capacity: { storage: 5Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
persistentVolumeReclaimPolicy: Retain
hostPath: { path: "{{ .Values.openlitespeedVhostDataPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.openlitespeed }}-vhost-data-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.openlitespeed }}-vhost-data-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
resources: { requests: { storage: 5Gi } }
storageClassName: ""
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.openlitespeed }}-vhost-shared-pv" }
spec:
capacity: { storage: 1Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
persistentVolumeReclaimPolicy: Retain
hostPath: { path: "{{ .Values.openlitespeedVhostSharedPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.openlitespeed }}-vhost-shared-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.openlitespeed }}-vhost-shared-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
resources: { requests: { storage: 1Gi } }
storageClassName: ""
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: "{{ .Values.openlitespeed }}", namespace: "{{ .Values.namespace }}" }
spec:
replicas: 2
strategy: { type: RollingUpdate, rollingUpdate: { maxSurge: 0, maxUnavailable: 1 } }
selector: { matchLabels: { app: "{{ .Values.openlitespeed }}" } }
template:
metadata: { labels: { app: "{{ .Values.openlitespeed }}" } }
spec:
initContainers:
- name: "{{ .Values.openlitespeed }}-init"
image: litespeedtech/openlitespeed:1.8.5-lsphp85
command: ["sh", "-c"]
args:
- |
if [ ! -f /mnt/config/httpd_config.conf ]; then
cp -a /usr/local/lsws/conf/. /mnt/config/
fi
if [ ! -f /mnt/admin/admin_config.conf ]; then
cp -a /usr/local/lsws/admin/conf/. /mnt/admin/
fi
volumeMounts:
- { name: "{{ .Values.openlitespeed }}-config-volume", mountPath: /mnt/config }
- { name: "{{ .Values.openlitespeed }}-admin-volume", mountPath: /mnt/admin }
shareProcessNamespace: true
containers:
- name: "{{ .Values.openlitespeed }}"
image: litespeedtech/openlitespeed:1.8.5-lsphp85
ports:
- { containerPort: 80 }
- { containerPort: 7080 }
resources:
requests: { cpu: "{{ .Values.profiles.openlitespeed.cpuRequest }}", memory: "{{ .Values.profiles.openlitespeed.memoryRequest }}" }
limits: { cpu: "{{ .Values.profiles.openlitespeed.cpuLimit }}", memory: "{{ .Values.profiles.openlitespeed.memoryLimit }}" }
readinessProbe: { tcpSocket: { port: 80 }, initialDelaySeconds: 5, periodSeconds: 5, failureThreshold: 3 }
livenessProbe: { tcpSocket: { port: 80 }, initialDelaySeconds: 10, periodSeconds: 10, failureThreshold: 5 }
volumeMounts:
- { name: "{{ .Values.openlitespeed }}-vhosts-volume", mountPath: /var/www/vhosts }
- { name: "{{ .Values.openlitespeed }}-config-volume", mountPath: /usr/local/lsws/conf }
- { name: "{{ .Values.openlitespeed }}-admin-volume", mountPath: /usr/local/lsws/admin/conf }
- { name: "{{ .Values.openlitespeed }}-phpini-volume", mountPath: /etc/ols-php-ini }
- { name: "{{ .Values.openlitespeed }}-logs-volume", mountPath: /usr/local/lsws/logs }
- { name: "{{ .Values.openlitespeed }}-cache-volume", mountPath: /usr/local/lsws/cachedata }
- { name: "{{ .Values.openlitespeed }}-tmp-volume", mountPath: /tmp/lshttpd }
- { name: "{{ .Values.openlitespeed }}-vhost-data-volume", mountPath: /var/www/data, readOnly: true }
- { name: "{{ .Values.openlitespeed }}-vhost-shared-volume", mountPath: /var/www/shared, readOnly: true }
volumes:
- name: "{{ .Values.openlitespeed }}-vhosts-volume"
persistentVolumeClaim: { claimName: "{{ .Values.openlitespeed }}-vhosts-pvc" }
- name: "{{ .Values.openlitespeed }}-config-volume"
persistentVolumeClaim: { claimName: "{{ .Values.openlitespeed }}-config-pvc" }
- name: "{{ .Values.openlitespeed }}-admin-volume"
persistentVolumeClaim: { claimName: "{{ .Values.openlitespeed }}-admin-pvc" }
- name: "{{ .Values.openlitespeed }}-phpini-volume"
persistentVolumeClaim: { claimName: "{{ .Values.openlitespeed }}-phpini-pvc" }
- name: "{{ .Values.openlitespeed }}-logs-volume"
persistentVolumeClaim: { claimName: "{{ .Values.openlitespeed }}-logs-pvc" }
- name: "{{ .Values.openlitespeed }}-cache-volume"
emptyDir: { sizeLimit: 100Gi }
- name: "{{ .Values.openlitespeed }}-tmp-volume"
emptyDir: { sizeLimit: 100Gi }
- name: "{{ .Values.openlitespeed }}-vhost-data-volume"
persistentVolumeClaim: { claimName: "{{ .Values.openlitespeed }}-vhost-data-pvc" }
- name: "{{ .Values.openlitespeed }}-vhost-shared-volume"
persistentVolumeClaim: { claimName: "{{ .Values.openlitespeed }}-vhost-shared-pvc" }
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.openlitespeed }}", namespace: "{{ .Values.namespace }}" }
spec:
selector: { app: "{{ .Values.openlitespeed }}" }
ports:
- { name: http, protocol: TCP, port: 80, targetPort: 80 }
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: { name: "{{ .Values.openlitespeed }}-ingress", namespace: "{{ .Values.namespace }}" }
spec:
ingressClassName: traefik
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service: { name: "{{ .Values.openlitespeed }}", port: { number: 80 } }
# -------------------------
# Admin panel
# -------------------------
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.openlitespeed }}-admin", namespace: "{{ .Values.namespace }}" }
spec:
selector: { app: "{{ .Values.openlitespeed }}" }
type: ClusterIP
ports:
- { name: admin, protocol: TCP, port: 7080, targetPort: 7080 }
---
apiVersion: traefik.io/v1alpha1
kind: MiddlewareTCP
metadata: { name: "{{ .Values.openlitespeed }}-admin-allowlist", namespace: "{{ .Values.namespace }}" }
spec:
ipAllowList: { sourceRange: [ {{ .Values.openlitespeedAdminWhiteList }} ] }
---
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata: { name: "{{ .Values.openlitespeed }}-admin", namespace: "{{ .Values.namespace }}" }
spec:
entryPoints: [ "olsadmin" ]
routes:
- match: HostSNI(`*`)
middlewares:
- name: "{{ .Values.openlitespeed }}-admin-allowlist"
services:
- name: "{{ .Values.openlitespeed }}-admin"
port: 7080
tls:
passthrough: true
---
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata: { name: traefik, namespace: kube-system }
spec:
valuesContent: |-
ports:
olsadmin:
port: 9443
expose:
default: true
exposedPort: 9443
protocol: TCP
additionalArguments:
- "--entryPoints.olsadmin.address=:9443/tcp"
{{- end }}
@@ -1,188 +0,0 @@
{{- if .Values.postfixHelm }}
---
apiVersion: v1
kind: Secret
metadata: { name: "{{ .Values.postfix }}-tls", namespace: "{{ .Values.namespace }}" }
type: kubernetes.io/tls
data:
tls.crt: {{ .Values.postfixTlsCrtB64 }}
tls.key: {{ .Values.postfixTlsKeyB64 }}
---
apiVersion: v1
kind: ConfigMap
metadata: { name: "{{ .Values.postfix }}-sasl", namespace: "{{ .Values.namespace }}" }
data:
smtpd.conf: |
pwcheck_method: auxprop
auxprop_plugin: sasldb
sasldb_path: /config/sasldb2
mech_list: PLAIN LOGIN
default_realm: {{ .Values.postfixDefaultRealm }}
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.postfix }}-config-pv" }
spec:
capacity: { storage: 1Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteOnce ]
persistentVolumeReclaimPolicy: Retain
hostPath: { path: "{{ .Values.postfixConfigPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.postfix }}-dkim-pv" }
spec:
capacity: { storage: 1Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteOnce ]
persistentVolumeReclaimPolicy: Retain
hostPath: { path: "{{ .Values.postfixDkimPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.postfix }}-config-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.postfix }}-config-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteOnce ]
resources: { requests: { storage: 1Gi } }
storageClassName: ""
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.postfix }}-dkim-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.postfix }}-dkim-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteOnce ]
resources: { requests: { storage: 1Gi } }
storageClassName: ""
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.postfix }}-queue-pvc", namespace: "{{ .Values.namespace }}" }
spec:
accessModes: ["ReadWriteOnce"]
resources: { requests: { storage: 5Gi } }
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: "{{ .Values.postfix }}", namespace: "{{ .Values.namespace }}" }
spec:
replicas: 1
selector: { matchLabels: { app: "{{ .Values.postfix }}" } }
template:
metadata: { labels: { app: "{{ .Values.postfix }}" } }
spec:
enableServiceLinks: false
initContainers:
- name: "{{ .Values.postfix }}-dkim-init"
image: boky/postfix:4.4.0-alpine
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-lc"]
args:
- |
set -e
if [ ! -f /dkim/opendkim.conf ]; then
cp -a /etc/opendkim/* /dkim/
fi
touch /dkim/TrustedHosts /dkim/SigningTable /dkim/KeyTable
chown opendkim:opendkim /dkim/TrustedHosts /dkim/KeyTable /dkim/SigningTable
chmod 0644 /dkim/TrustedHosts /dkim/KeyTable /dkim/SigningTable
printf '%s\n' 127.0.0.1 localhost 10.42.0.0/16 10.43.0.0/16 > /dkim/TrustedHosts
volumeMounts:
- name: "{{ .Values.postfix }}-dkim-volume"
mountPath: /dkim
containers:
- name: "{{ .Values.postfix }}"
image: boky/postfix:4.4.0-alpine
ports:
- { containerPort: 25, name: smtp }
- { containerPort: 587, name: submission }
env:
- { name: POSTFIX_myhostname, value: "{{ .Values.postfixHost }}" }
- { name: POSTFIX_smtpd_banner, value: "$myhostname ESMTP" }
- { name: POSTFIX_mynetworks, value: "127.0.0.0/8" }
- { name: POSTFIX_inet_interfaces, value: "all" }
# Rules
- { name: POSTFIX_smtpd_client_restrictions, value: "permit_mynetworks, permit_sasl_authenticated, reject" }
- { name: POSTFIX_smtpd_relay_restrictions, value: "permit_sasl_authenticated, reject_unauth_destination" }
- { name: POSTFIX_smtpd_sender_restrictions, value: "reject_non_fqdn_sender,reject_unknown_sender_domain,reject_sender_login_mismatch,permit_sasl_authenticated,reject_unauth_destination" }
# TLS
- { name: POSTFIX_smtpd_tls_cert_file, value: "/etc/ssl/mail/tls.crt" }
- { name: POSTFIX_smtpd_tls_key_file, value: "/etc/ssl/mail/tls.key" }
- { name: POSTFIX_smtpd_tls_security_level, value: "may" }
- { name: POSTFIX_smtp_tls_security_level, value: "may" }
# SASL (Cyrus, sasldb2)
- { name: POSTFIX_smtpd_sasl_auth_enable, value: "yes" }
- { name: POSTFIX_smtpd_sasl_type, value: "cyrus" }
- { name: POSTFIX_smtpd_sasl_path, value: "smtpd" }
- { name: POSTFIX_cyrus_sasl_config_path, value: "/etc/sasl2" }
# Maps (Virtual domain/alias and senders)
- { name: POSTFIX_virtual_alias_domains, value: "lmdb:/config/{{ .Values.postfixDomainsFile }}" }
- { name: POSTFIX_virtual_alias_maps, value: "lmdb:/config/{{ .Values.postfixAliasesFile }}" }
- { name: POSTFIX_smtpd_sender_login_maps, value: "lmdb:/config/{{ .Values.postfixSendersFile }}" }
# DKIM
- { name: DKIM_SELECTOR, value: "{{ .Values.postfixDkimSelector }}" }
- { name: POSTFIX_smtpd_milters, value: "inet:localhost:8891" }
- { name: POSTFIX_non_smtpd_milters, value: "$smtpd_milters" }
- { name: POSTFIX_milter_default_action, value: "accept" }
- { name: POSTFIX_milter_protocol, value: "6" }
# Other
- { name: ALLOW_EMPTY_SENDER_DOMAINS, value: "true" }
- { name: ALLOWED_SENDER_DOMAINS, value: "" }
volumeMounts:
- { name: "{{ .Values.postfix }}-tls-volume", mountPath: /etc/ssl/mail, readOnly: true }
- { name: "{{ .Values.postfix }}-sasl-volume", mountPath: /etc/sasl2 }
- { name: "{{ .Values.postfix }}-config-volume", mountPath: /config }
- { name: "{{ .Values.postfix }}-dkim-volume", mountPath: /etc/opendkim }
- { name: "{{ .Values.postfix }}-dkim-volume", mountPath: /etc/opendkim/keys, subPath: keys }
- { name: "{{ .Values.postfix }}-queue-volume", mountPath: /var/spool/postfix }
volumes:
- name: "{{ .Values.postfix }}-tls-volume"
secret: { secretName: "{{ .Values.postfix }}-tls" }
- name: "{{ .Values.postfix }}-sasl-volume"
configMap: { name: "{{ .Values.postfix }}-sasl" }
- name: "{{ .Values.postfix }}-config-volume"
persistentVolumeClaim: { claimName: "{{ .Values.postfix }}-config-pvc" }
- name: "{{ .Values.postfix }}-dkim-volume"
persistentVolumeClaim: { claimName: "{{ .Values.postfix }}-dkim-pvc" }
- name: "{{ .Values.postfix }}-queue-volume"
persistentVolumeClaim: { claimName: "{{ .Values.postfix }}-queue-pvc" }
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.postfix }}-public", namespace: "{{ .Values.namespace }}" }
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector: { app: "{{ .Values.postfix }}" }
ports: [ { name: smtp, port: 25, targetPort: 25 } ]
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.postfix }}", namespace: "{{ .Values.namespace }}" }
spec:
selector: { app: "{{ .Values.postfix }}" }
ports: [ { name: submission, port: 587, targetPort: 587 } ]
{{- end }}
@@ -1,416 +0,0 @@
{{- if .Values.redisHelm }}
---
apiVersion: v1
kind: ConfigMap
metadata: { name: "{{ .Values.redis }}-config", namespace: "{{ .Values.namespace }}" }
data:
redis.conf: |
bind 0.0.0.0
port 6379
dir /data
# --- ACL ---
aclfile /data-acl/{{ .Values.redisFileUsersAcl }}
# --- all in one DB ---
databases 1
# --- network ---
protected-mode yes
tcp-backlog 1024
tcp-keepalive 300
timeout 0
# --- connections ---
maxclients {{ .Values.profiles.redis.maxClients }}
# --- memory (tune) ---
maxmemory {{ .Values.profiles.redis.maxmemory }}
maxmemory-policy allkeys-lfu
maxmemory-samples 5
maxmemory-eviction-tenacity 10
maxmemory-clients 5%
client-query-buffer-limit 256mb
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
# --- replication ---
replica-serve-stale-data yes
replica-read-only yes
repl-backlog-size 64mb
repl-backlog-ttl 3600
min-replicas-to-write 0
#min-replicas-max-lag 10
# --- persistence ---
appendonly yes
appendfsync everysec
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
save ""
# --- log ---
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
---
apiVersion: v1
kind: PersistentVolume
metadata: { name: "{{ .Values.redis }}-users-pv" }
spec:
capacity: { storage: 1Gi }
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
persistentVolumeReclaimPolicy: Retain
hostPath: { path: "{{ .Values.redisPath }}", type: DirectoryOrCreate }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: "{{ .Values.redis }}-users-pvc", namespace: "{{ .Values.namespace }}" }
spec:
volumeName: "{{ .Values.redis }}-users-pv"
volumeMode: Filesystem
accessModes: [ ReadWriteMany ]
resources: { requests: { storage: 1Gi } }
storageClassName: ""
---
apiVersion: apps/v1
kind: StatefulSet
metadata: { name: "{{ .Values.redis }}", namespace: "{{ .Values.namespace }}" }
spec:
serviceName: "{{ .Values.redis }}"
replicas: 2
selector: { matchLabels: { app: "{{ .Values.redis }}" } }
persistentVolumeClaimRetentionPolicy: { whenDeleted: Delete, whenScaled: Retain }
template:
metadata: { labels: { app: "{{ .Values.redis }}" } }
spec:
terminationGracePeriodSeconds: 30
initContainers:
- name: init-redis-acl
image: redis:8.6-alpine
resources:
requests: { cpu: "10m", memory: "32Mi" }
limits: { cpu: "100m", memory: "128Mi" }
env:
- { name: POD_NAME, valueFrom: { fieldRef: { fieldPath: metadata.name } } }
- { name: REDIS_PASSWORD, valueFrom: { secretKeyRef: { name: "{{ .Values.redis }}-secret", key: root-password } } }
command: ["/bin/sh","-c"]
args:
- |
set -eu
ACL="/data-acl/{{ .Values.redisFileUsersAcl }}"
HASH=$(printf '%s' "$REDIS_PASSWORD" | sha256sum | awk '{print $1}')
mkdir -p /data-acl
if [ "$POD_NAME" = "{{ .Values.redis }}-0" ]; then
tmp="${ACL}.tmp"
if [ -f "$ACL" ]; then
awk '!(tolower($1)=="user" && $2=="default")' "$ACL" > "$tmp"
else
: > "$tmp"
fi
# default user is used by replication auth and HAProxy health checks
printf 'user default on sanitize-payload #%s ~* &* +@all\n' "$HASH" >> "$tmp"
mv "$tmp" "$ACL"
chmod 600 "$ACL"
else
i=0
while [ ! -f "$ACL" ] && [ $i -lt 300 ]; do
sleep 1
i=$((i+1))
done
[ -f "$ACL" ] || exit 1
fi
volumeMounts:
- { name: "{{ .Values.redis }}-users-volume", mountPath: /data-acl }
containers:
- name: "{{ .Values.redis }}"
image: redis:8.6-alpine
resources:
requests: { cpu: "{{ .Values.profiles.redis.cpuRequest }}", memory: "{{ .Values.profiles.redis.memoryRequest }}" }
limits: { cpu: "{{ .Values.profiles.redis.cpuLimit }}", memory: "{{ .Values.profiles.redis.memoryLimit }}" }
ports:
- { name: redis, containerPort: 6379 }
env:
- { name: POD_NAME, valueFrom: { fieldRef: { fieldPath: metadata.name } } }
- { name: POD_IP, valueFrom: { fieldRef: { fieldPath: status.podIP } } }
- { name: REDIS_PASSWORD, valueFrom: { secretKeyRef: { name: "{{ .Values.redis }}-secret", key: root-password } } }
- { name: SENTINEL_HOST, value: "{{ .Values.redisSentinel }}" }
- { name: SENTINEL_PORT, value: "26379" }
- { name: MASTER_NAME, value: "mymaster" }
command: ["/bin/sh","-c"]
args:
- |
set -eu
POD_DNS_SHORT="${POD_NAME}.{{ .Values.redis }}"
POD_DNS_FQDN="${POD_NAME}.{{ .Values.redis }}.{{ .Values.namespace }}.svc.cluster.local"
get_master() {
REDISCLI_AUTH="$REDIS_PASSWORD" \
redis-cli -h "$SENTINEL_HOST" -p "$SENTINEL_PORT" \
SENTINEL get-master-addr-by-name "$MASTER_NAME" 2>/dev/null | tr -d '\r'
}
out=""
i=0
while [ $i -lt 20 ]; do
out="$(get_master || true)"
[ -n "$out" ] && break
i=$((i+1))
sleep 1
done
master_host="$(printf '%s\n' "$out" | sed -n '1p')"
master_port="$(printf '%s\n' "$out" | sed -n '2p')"
[ -n "$master_port" ] || master_port="6379"
is_me_master() {
[ "$master_host" = "$POD_IP" ] || [ "$master_host" = "$POD_DNS_SHORT" ] || [ "$master_host" = "$POD_DNS_FQDN" ]
}
if [ -n "$master_host" ]; then
if is_me_master; then
exec redis-server /etc/redis/redis.conf --masteruser default --masterauth "$REDIS_PASSWORD"
else
exec redis-server /etc/redis/redis.conf --replicaof "$master_host" "$master_port" --masteruser default --masterauth "$REDIS_PASSWORD"
fi
else
# bootstrap if sentinel is not ready yet
if [ "$POD_NAME" = "{{ .Values.redis }}-0" ]; then
exec redis-server /etc/redis/redis.conf
else
exec redis-server /etc/redis/redis.conf --replicaof {{ .Values.redis }}-0.{{ .Values.redis }} 6379 --masteruser default --masterauth "$REDIS_PASSWORD"
fi
fi
volumeMounts:
- { name: "{{ .Values.redis }}-data-volume", mountPath: /data }
- { name: "{{ .Values.redis }}-config-volume", mountPath: /etc/redis }
- { name: "{{ .Values.redis }}-users-volume", mountPath: /data-acl }
volumes:
- name: "{{ .Values.redis }}-config-volume"
configMap: { name: "{{ .Values.redis }}-config" }
- name: "{{ .Values.redis }}-users-volume"
persistentVolumeClaim: { claimName: "{{ .Values.redis }}-users-pvc" }
volumeClaimTemplates:
- metadata: { name: "{{ .Values.redis }}-data-volume" }
spec:
accessModes: [ ReadWriteOnce ]
resources: { requests: { storage: 10Gi } }
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.redis }}", namespace: "{{ .Values.namespace }}" }
spec:
clusterIP: None
selector: { app: "{{ .Values.redis }}" }
ports:
- { name: redis, protocol: TCP, port: 6379, targetPort: 6379 }
# -------------------------
# Sentinel (1) with PVC
# -------------------------
---
apiVersion: v1
kind: ConfigMap
metadata: { name: "{{ .Values.redisSentinel }}-config", namespace: "{{ .Values.namespace }}" }
data:
sentinel.conf.tmpl: |
bind 0.0.0.0
port 26379
dir /data
sentinel deny-scripts-reconfig yes
sentinel resolve-hostnames yes
sentinel announce-hostnames yes
# quorum=1 (single sentinel)
sentinel monitor mymaster {{ .Values.redis }}-0.{{ .Values.redis }} 6379 1
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
sentinel auth-user mymaster default
sentinel auth-pass mymaster __PASSWORD__
requirepass __PASSWORD__
---
apiVersion: apps/v1
kind: StatefulSet
metadata: { name: "{{ .Values.redisSentinel }}", namespace: "{{ .Values.namespace }}" }
spec:
replicas: 1
serviceName: "{{ .Values.redisSentinel }}"
selector: { matchLabels: { app: "{{ .Values.redisSentinel }}" } }
persistentVolumeClaimRetentionPolicy: { whenDeleted: Delete, whenScaled: Retain }
template:
metadata: { labels: { app: "{{ .Values.redisSentinel }}" } }
spec:
containers:
- name: "{{ .Values.redisSentinel }}"
image: redis:8.6-alpine
resources:
requests: { cpu: "50m", memory: "128Mi" }
limits: { cpu: "200m", memory: "256Mi" }
ports:
- { name: sentinel, containerPort: 26379 }
env:
- { name: REDIS_PASSWORD, valueFrom: { secretKeyRef: { name: "{{ .Values.redis }}-secret", key: root-password } } }
command: ["/bin/sh","-c"]
args:
- |
set -eu
CONF=/data/sentinel.conf
if [ ! -f "$CONF" ]; then
pwd_escaped=$(printf '%s' "$REDIS_PASSWORD" | sed -e 's/[\/&]/\\&/g')
sed "s/__PASSWORD__/${pwd_escaped}/g" /tmpl/sentinel.conf.tmpl > "$CONF"
chmod 600 "$CONF"
fi
exec redis-server "$CONF" --sentinel
volumeMounts:
- { name: "{{ .Values.redisSentinel }}-tmpl", mountPath: /tmpl }
- { name: "{{ .Values.redisSentinel }}-data", mountPath: /data }
volumes:
- name: "{{ .Values.redisSentinel }}-tmpl"
configMap: { name: "{{ .Values.redisSentinel }}-config" }
volumeClaimTemplates:
- metadata: { name: "{{ .Values.redisSentinel }}-data" }
spec:
accessModes: [ ReadWriteOnce ]
resources: { requests: { storage: 1Gi } }
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.redisSentinel }}", namespace: "{{ .Values.namespace }}" }
spec:
selector: { app: "{{ .Values.redisSentinel }}" }
ports:
- { name: sentinel, port: 26379, targetPort: 26379 }
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: "{{ .Values.redisSentinel }}-allow-only-checker", namespace: "{{ .Values.namespace }}" }
spec:
podSelector: { matchLabels: { app: "{{ .Values.redisSentinel }}" } }
policyTypes:
- Ingress
ingress:
- from:
- podSelector: { matchLabels: { app: "{{ .Values.redis }}" } }
- podSelector: { matchLabels: { app: "{{ .Values.redisSentinel }}" } }
ports:
- { protocol: TCP, port: 26379 }
# -------------------------
# HAProxy: single master endpoint
# -------------------------
---
apiVersion: v1
kind: ConfigMap
metadata: { name: "{{ .Values.redis }}-haproxy-config", namespace: "{{ .Values.namespace }}" }
data:
haproxy.cfg: |
global
log stdout format raw local0
maxconn 20000
resolvers kubedns
nameserver dns1 10.43.0.10:53
accepted_payload_size 8192
resolve_retries 3
timeout resolve 1s
timeout retry 1s
hold valid 10s
hold obsolete 30s
defaults
mode tcp
log global
option tcplog
option log-health-checks
timeout connect 5s
timeout client 1m
timeout server 1m
timeout check 1s
frontend fe_redis_master
bind *:6379
default_backend be_redis_master
backend be_redis_master
mode tcp
balance first
option tcp-check
option srvtcpka
timeout queue 2s
timeout connect 2s
timeout check 3s
timeout server 10m
tcp-check connect
tcp-check send-lf "AUTH default $REDIS_PASSWORD\r\n"
tcp-check expect string +OK
tcp-check send INFO\ replication\r\n
tcp-check expect string role:master
tcp-check send QUIT\r\n
tcp-check expect string +OK
server redis0 {{ .Values.redis }}-0.{{ .Values.redis }}.{{ .Values.namespace }}.svc.cluster.local:6379 check resolvers kubedns resolve-prefer ipv4 init-addr libc,none inter 5s fall 2 rise 2
server redis1 {{ .Values.redis }}-1.{{ .Values.redis }}.{{ .Values.namespace }}.svc.cluster.local:6379 check resolvers kubedns resolve-prefer ipv4 init-addr libc,none inter 5s fall 2 rise 2
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: "{{ .Values.redis }}-haproxy", namespace: "{{ .Values.namespace }}" }
spec:
replicas: 1
selector: { matchLabels: { app: "{{ .Values.redis }}-haproxy" } }
template:
metadata:
labels: { app: "{{ .Values.redis }}-haproxy" }
spec:
containers:
- name: "{{ .Values.redis }}-haproxy"
image: haproxy:2.9-alpine
resources:
requests: { cpu: "50m", memory: "64Mi" }
limits: { cpu: "500m", memory: "256Mi" }
ports:
- { name: redis, containerPort: 6379 }
env:
- { name: REDIS_PASSWORD, valueFrom: { secretKeyRef: { name: "{{ .Values.redis }}-secret", key: root-password } } }
command: ["/bin/sh","-c"]
args:
- |
set -eu
haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg
exec haproxy -f /usr/local/etc/haproxy/haproxy.cfg -db
readinessProbe: { tcpSocket: { port: 6379 }, initialDelaySeconds: 1, periodSeconds: 2, failureThreshold: 3 }
livenessProbe: { tcpSocket: { port: 6379 }, initialDelaySeconds: 10, periodSeconds: 10, failureThreshold: 3 }
volumeMounts:
# - { name: cfg, mountPath: /usr/local/etc/haproxy/haproxy.cfg, subPath: haproxy.cfg }
- { name: cfg, mountPath: /usr/local/etc/haproxy }
volumes:
- name: cfg
configMap: { name: "{{ .Values.redis }}-haproxy-config" }
---
apiVersion: v1
kind: Service
metadata: { name: "{{ .Values.redis }}-master", namespace: "{{ .Values.namespace }}" }
spec:
selector: { app: "{{ .Values.redis }}-haproxy" }
ports:
- { name: redis, port: 6379, targetPort: 6379 }
{{- end }}
@@ -1,52 +0,0 @@
{{- if .Values.workerHelm }}
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: "{{ .Values.worker }}", namespace: "{{ .Values.namespace }}" }
spec:
replicas: 1
selector: { matchLabels: { app: "{{ .Values.worker }}" } }
template:
metadata: { labels: { app: "{{ .Values.worker }}" } }
spec:
containers:
- name: "{{ .Values.worker }}"
image: python:3.12-slim
imagePullPolicy: IfNotPresent
resources:
requests: { cpu: "50m", memory: "64Mi" }
limits: { cpu: "200m", memory: "256Mi" }
ports:
- { containerPort: 8080 }
workingDir: /app/agent
command: ["/bin/sh","-c"]
args:
- |
set -e
if [ ! -f /app/agent/worker.py ]; then
echo "ERROR: /app/agent/worker.py not found" >&2
ls -la /app/agent >&2 || true
exit 1
fi
exec python -u /app/agent/worker.py
env:
- { name: WORKER_UUID, value: "{{ .Values.workerUuid }}" }
- { name: WORKER_NAME, value: "{{ .Values.workerName }}" }
- { name: WORKER_POOL, value: "{{ .Values.workerPool }}" }
- { name: API_URL, value: "{{ .Values.workerApiUrl }}" }
- { name: GETTING_PAUSE, value: "{{ .Values.workerApiGettingPause }}" }
- { name: SENDING_PAUSE, value: "{{ .Values.workerApiSendingPause }}" }
volumeMounts:
- { name: "{{ .Values.worker }}-agent-volume", mountPath: /app/agent }
- { name: "{{ .Values.worker }}-tasks-volume", mountPath: /app/tasks }
readinessProbe: { httpGet: { path: /healthz, port: 8080 }, periodSeconds: 5, timeoutSeconds: 2 }
livenessProbe: { httpGet: { path: /healthz, port: 8080 }, periodSeconds: 10, timeoutSeconds: 2, failureThreshold: 3 }
startupProbe: { httpGet: { path: /healthz, port: 8080 }, periodSeconds: 2, timeoutSeconds: 2, failureThreshold: 30 }
volumes:
- name: "{{ .Values.worker }}-agent-volume"
hostPath: { path: "{{ .Values.workerAgentPath }}", type: DirectoryOrCreate }
- name: "{{ .Values.worker }}-tasks-volume"
hostPath: { path: "{{ .Values.workerTasksPath }}", type: DirectoryOrCreate }
{{- end }}