chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:32:57 +08:00
commit cd420f9332
4811 changed files with 884702 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
values-*.yaml
!values-production-example.yaml
*.tgz
/charts
+17
View File
@@ -0,0 +1,17 @@
# Exclude version control
.git/
.gitignore
.helmignore
# Exclude OS files
.DS_Store
# Exclude CI/CD and scripts
.github/
scripts/
# Exclude package files
*.tgz
# Exclude additional values files
values-*.yaml
+15
View File
@@ -0,0 +1,15 @@
dependencies:
- name: postgresql
repository: oci://registry-1.docker.io/bitnamicharts
version: 16.7.14
- name: redis
repository: oci://registry-1.docker.io/bitnamicharts
version: 21.2.6
- name: clickhouse
repository: oci://registry-1.docker.io/bitnamicharts
version: 9.4.4
- name: minio
repository: oci://registry-1.docker.io/bitnamicharts
version: 17.0.9
digest: sha256:e1b572ab8eca0cc376311398c27b1734d8a598095fccc81dd9c32b2c8b9c1149
generated: "2026-05-05T10:31:58.493590751+01:00"
+37
View File
@@ -0,0 +1,37 @@
apiVersion: v2
name: trigger
description: The official Trigger.dev Helm chart
type: application
version: 4.5.3
appVersion: v4.5.3
home: https://trigger.dev
sources:
- https://github.com/triggerdotdev/trigger.dev
keywords:
- trigger
- workflow
- background-jobs
- job-scheduler
- task-queue
- automation
annotations:
category: Development
dependencies:
- name: postgresql
version: "16.7.14"
repository: "oci://registry-1.docker.io/bitnamicharts"
condition: postgres.deploy
alias: postgres
- name: redis
version: "21.2.6"
repository: "oci://registry-1.docker.io/bitnamicharts"
condition: redis.deploy
- name: clickhouse
version: "9.4.4"
repository: "oci://registry-1.docker.io/bitnamicharts"
condition: clickhouse.deploy
- name: minio
version: "17.0.9"
repository: "oci://registry-1.docker.io/bitnamicharts"
condition: s3.deploy
alias: s3
+739
View File
@@ -0,0 +1,739 @@
# Trigger.dev v4 Helm Chart
This Helm chart deploys Trigger.dev v4 self-hosting stack to Kubernetes.
## Quick Start
### Prerequisites
```bash
# Build Helm dependencies (required for Bitnami charts)
helm dependency build
# Extract dependency charts for local template testing
for file in ./charts/*.tgz; do echo "Extracting $file"; tar -xzf "$file" -C ./charts; done
# Alternative: Use --dependency-update flag for template testing
helm template trigger . --dependency-update
```
### Installation
```bash
# Deploy with default values (testing/development only)
helm install trigger .
# Deploy to specific namespace
helm install trigger . -n trigger --create-namespace
# Deploy with custom values for production
helm install trigger . -f values-production.yaml -n trigger --create-namespace
```
### Upgrading
```bash
# Upgrade existing release
helm upgrade trigger .
# Upgrade with new values
helm upgrade trigger . -f values-production.yaml
```
### Access the dashboard
```bash
kubectl port-forward svc/trigger-webapp 3040:3030 --address 0.0.0.0
```
Dashboard: http://localhost:3040/
### Deploying your tasks
```bash
# The --push arg is required when testing locally
npx trigger.dev@latest deploy --push
```
## ⚠️ Security Requirements
### Secrets Configuration
**IMPORTANT**: The default secrets are for **TESTING ONLY** and must be changed for production.
#### Required Secrets
All secrets must be exactly **32 hexadecimal characters** (16 bytes):
- `sessionSecret` - User authentication sessions
- `magicLinkSecret` - Passwordless login tokens
- `encryptionKey` - Sensitive data encryption
- `managedWorkerSecret` - Worker authentication
#### Generate Production Secrets
```bash
for i in {1..4}; do openssl rand -hex 16; done
```
#### Configure Production Secrets
```yaml
# values-production.yaml
secrets:
sessionSecret: "your-generated-secret-1"
magicLinkSecret: "your-generated-secret-2"
encryptionKey: "your-generated-secret-3"
managedWorkerSecret: "your-generated-secret-4"
objectStore:
accessKeyId: "your-s3-access-key"
secretAccessKey: "your-s3-secret-key"
```
## Architecture
This chart deploys the following components:
### Core Services
- **Webapp** - Main Trigger.dev application (port 3030)
- **PostgreSQL** - Primary database with logical replication
- **Redis** - Cache and job queue
- **Electric** - Real-time sync service (ElectricSQL)
### Worker Services
- **Supervisor** - Kubernetes worker orchestrator for executing runs
### Supporting Services
- **ClickHouse** - Analytics database
- **MinIO** - S3-compatible object storage
- **Registry** - Private Docker registry for deployed code (EXPERIMENTAL - disabled by default)
## Configuration
### Basic Configuration
```yaml
webapp:
# Application URLs
appOrigin: "https://trigger.example.com"
loginOrigin: "https://trigger.example.com"
apiOrigin: "https://trigger.example.com"
# Bootstrap mode (auto-creates worker group)
bootstrap:
enabled: true # Enable for combined setups
workerGroupName: "bootstrap"
```
### External Services
Use external managed services instead of bundled components:
```yaml
# External PostgreSQL
postgres:
deploy: false
external:
host: "your-postgres.rds.amazonaws.com"
port: 5432
database: "trigger"
username: "trigger_user"
password: "your-password"
# External Redis
redis:
deploy: false
external:
host: "your-redis.cache.amazonaws.com"
port: 6379
password: "your-password"
# External Docker Registry (e.g., Kind local registry)
registry:
deploy: true
external:
host: "localhost"
port: 5001
username: ""
password: ""
```
### Ingress Configuration
```yaml
# Webapp ingress
webapp:
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: trigger.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: trigger-tls
hosts:
- trigger.example.com
# Registry ingress
registry:
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: registry.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: registry-tls
hosts:
- registry.example.com
```
### Resource Configuration
```yaml
resources:
webapp:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 1000m
memory: 2Gi
postgres:
primary:
resources:
limits:
cpu: 1000m
memory: 2Gi
```
## Deployment Modes
### Testing/Development
- Use default values
- Single replica
- Lower resource limits
- Bootstrap mode enabled
### Production
- Custom secrets (required)
- Multiple replicas with anti-affinity
- Production resource limits
- External services recommended
- Ingress with TLS
- Persistent storage
## Persistence
All services support persistent storage and allow you to control the storage class globally or per service. Our internal services (Registry) now support the full Bitnami persistence configuration pattern:
### Basic Persistence Configuration
```yaml
global:
storageClass: "fast-ssd" # Default for all services
# Bitnami chart services (simplified configuration)
postgres:
primary:
persistence:
enabled: true
size: 10Gi
storageClass: "postgres-nvme" # Optional: override for PostgreSQL
redis:
master:
persistence:
enabled: true
size: 5Gi
storageClass: "redis-ssd" # Optional: override for Redis
clickhouse:
persistence:
enabled: true
size: 10Gi
storageClass: "analytics-hdd" # Optional: override for ClickHouse
s3:
persistence:
enabled: true
size: 10Gi
storageClass: "objectstore-ssd" # Optional: override for S3
```
### Internal Services - Full Bitnami-Style Configuration
Our internal services (Registry) support the complete Bitnami persistence configuration pattern:
```yaml
# Registry - Full persistence configuration options
registry:
persistence:
enabled: true
# Name to assign the volume
volumeName: "data"
# Name of an existing PVC to use
existingClaim: ""
# The path the volume will be mounted at
mountPath: "/var/lib/registry"
# The subdirectory of the volume to mount to
subPath: ""
# PVC Storage Class for Registry data volume
storageClass: "registry-ssd"
# PVC Access Mode for Registry volume
accessModes:
- "ReadWriteOnce"
# PVC Storage Request for Registry volume
size: 10Gi
# Annotations for the PVC
annotations:
backup.velero.io/backup-volumes: "data"
# Labels for the PVC
labels:
app.kubernetes.io/component: "storage"
# Selector to match an existing Persistent Volume
selector:
matchLabels:
tier: "registry"
# Custom PVC data source
dataSource:
name: "registry-snapshot"
kind: "VolumeSnapshot"
apiGroup: "snapshot.storage.k8s.io"
# Shared persistent volume for worker token file
persistence:
shared:
enabled: true
size: 5Mi
accessMode: ReadWriteOnce
# accessMode: ReadWriteMany # Use for cross-node deployment
storageClass: ""
retain: true # Prevents deletion on uninstall
```
### Persistence Configuration Rules
- **Service-level storageClass** overrides the global value for that service only
- **Global storageClass** applies to all services that don't specify their own
- **Cluster default** is used if neither global nor service-level storageClass is set
- **Internal services** (Registry) support full Bitnami-style configuration
- **Bitnami chart services** use their respective chart's configuration patterns
## Monitoring
### Health Checks
Health checks are configured for all services:
- HTTP endpoints for web services
- Database connection tests
- Readiness and liveness probes
### Health Probe Configuration
All non-Bitnami services support configurable health probes:
```yaml
# Webapp health probes
webapp:
livenessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 5
successThreshold: 1
readinessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 5
successThreshold: 1
startupProbe:
enabled: false
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 60
successThreshold: 1
# Supervisor health probes
supervisor:
livenessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 5
successThreshold: 1
readinessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 5
successThreshold: 1
startupProbe:
enabled: false
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 60
successThreshold: 1
# Electric health probes
electric:
livenessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 5
successThreshold: 1
readinessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 5
successThreshold: 1
startupProbe:
enabled: false
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 60
successThreshold: 1
# Registry health probes
registry:
livenessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 5
successThreshold: 1
readinessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 5
successThreshold: 1
startupProbe:
enabled: false
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 60
successThreshold: 1
```
### Prometheus Integration
ServiceMonitors are available for webapp and supervisor services:
```yaml
webapp:
serviceMonitor:
enabled: true
interval: "30s"
path: "/metrics"
labels:
release: prometheus-stack
supervisor:
serviceMonitor:
enabled: true
interval: "30s"
path: "/metrics"
labels:
release: prometheus-stack
```
## Operations
### Force Pod Restart
When you need to force all pods to restart (e.g., to pick up updated secrets or config):
```bash
# Force restart using timestamp annotation (Helm-native approach)
helm upgrade <release-name> . --set-string podAnnotations.restartedAt="$(date +%s)"
# Example
helm upgrade trigger . --set-string podAnnotations.restartedAt="$(date +%s)"
```
This approach:
- ✅ Uses Helm's built-in annotation mechanism
- ✅ Safe - doesn't recreate immutable resources like PVCs
- ✅ Targeted - only restarts pods that need updates
- ✅ Trackable - increments Helm revision number
### Configuration Updates
After changing secrets or ConfigMaps in your values file:
```bash
# 1. Upgrade with new values
helm upgrade trigger . -f values-production.yaml
# 2. Force pod restart to pick up changes
helm upgrade trigger . -f values-production.yaml \
--set-string podAnnotations.restartedAt="$(date +%s)"
```
## Troubleshooting
### Check Pod Status
```bash
kubectl get pods -l app.kubernetes.io/name=trigger.dev
```
### View Logs
```bash
# Webapp logs
kubectl logs -l app.kubernetes.io/component=webapp
# Database logs
kubectl logs -l app.kubernetes.io/component=postgres
```
### Run Tests
```bash
helm test trigger.dev
```
## Testing
### Validate Deployment
```bash
# Check Helm template syntax
helm template trigger.dev . --dry-run > /dev/null && echo "Template validation successful"
# Test webapp health endpoint (requires port forwarding)
curl -s -o /dev/null -w "%{http_code}" http://localhost:3040/healthcheck || echo "Connection failed"
# Port forward to access webapp locally
kubectl port-forward svc/trigger.dev-webapp 3040:3030 --address 0.0.0.0
```
### Common Issues
1. **Secrets errors**: Ensure all secrets are exactly 32 hex characters
2. **Database connection**: Check PostgreSQL is ready before webapp starts
3. **Resource limits**: Increase limits for ClickHouse in constrained environments
4. **Config not applying**: Use the pod restart technique above to force config reload
5. **Image pull errors**: When testing locally, deploy with `npx trigger.dev@latest deploy --push`
## Examples
See `values-production-example.yaml` for a complete production configuration example.
## Version Management
### Understanding Versions
The Helm chart uses three types of versions:
1. **Chart Version** (`Chart.yaml:version`) - Helm chart packaging version
2. **App Version** (`Chart.yaml:appVersion`) - Trigger.dev application version
3. **Component Versions** (`values.yaml`) - Individual service versions (Electric, ClickHouse, etc.)
### Release Process
#### For Chart Maintainers
1. **Update Chart Version** for chart changes:
```bash
# Edit Chart.yaml
version: 4.1.0 # Increment for chart changes (semver)
```
2. **Update App Version** when Trigger.dev releases new version:
```bash
# Edit Chart.yaml
appVersion: "v4.1.0" # Match Trigger.dev release (v-prefixed image tag)
```
3. **Release via GitHub**:
```bash
# Tag and push
git tag helm-v4.1.0
git push origin helm-v4.1.0
# GitHub Actions will automatically build and publish to GHCR
```
#### For Users
```bash
# Install specific chart version
helm upgrade --install trigger \
oci://ghcr.io/triggerdotdev/charts/trigger.dev \
--version 4.1.0
# Install latest chart version
helm upgrade --install trigger \
oci://ghcr.io/triggerdotdev/charts/trigger.dev
# Override app version (advanced)
helm upgrade --install trigger . \
--set webapp.image.tag=v4.0.1
```
## Production Readiness Checklist
### 🔒 Security (REQUIRED)
- [ ] **Generate unique secrets** (never use defaults):
```bash
# Generate 4 secrets
for i in {1..4}; do openssl rand -hex 16; done
```
- [ ] **Configure security contexts**:
```yaml
webapp:
podSecurityContext:
fsGroup: 1000
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
```
- [ ] **Enable network policies** (if supported by cluster)
- [ ] **Configure proper RBAC** for supervisor
- [ ] **Use TLS ingress** with cert-manager
### 📊 Resource Management (REQUIRED)
- [ ] **Set resource limits and requests** - for example:
```yaml
webapp:
resources:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 1000m
memory: 2Gi
postgres:
primary:
resources:
limits:
cpu: 1000m
memory: 2Gi
requests:
cpu: 500m
memory: 1Gi
redis:
master:
resources:
limits:
cpu: 500m
memory: 1Gi
requests:
cpu: 250m
memory: 512Mi
# ClickHouse can be very resource intensive, so we recommend setting limits and requests accordingly
# Note: not doing this can cause OOM crashes which will cause issues across many different features
clickhouse:
resources:
limits:
cpu: 4000m
memory: 16Gi
requests:
cpu: 2000m
memory: 8Gi
supervisor:
resources:
limits:
cpu: 500m
memory: 1Gi
requests:
cpu: 250m
memory: 512Mi
```
- [ ] **Configure persistent storage for all services** - for example:
```yaml
global:
storageClass: "fast-nvme" # Default for all services
postgres:
primary:
persistence:
size: 500Gi
redis:
master:
persistence:
size: 20Gi
clickhouse:
persistence:
size: 100Gi
s3:
persistence:
size: 200Gi
# Internal services support full Bitnami-style configuration
registry:
persistence:
enabled: true
size: 100Gi
storageClass: "registry-ssd"
annotations:
backup.velero.io/backup-volumes: "data"
```
### 🏗️ High Availability (RECOMMENDED)
- [ ] **Multiple replicas** with pod anti-affinity
- [ ] **Pod disruption budgets**
- [ ] **External managed services** (RDS, ElastiCache, etc.)
- [ ] **Multi-AZ storage classes**
- [ ] **Backup strategies** for databases
### 📈 Monitoring (RECOMMENDED)
- [ ] **Enable ServiceMonitors** for Prometheus
- [ ] **Configure alerting** for critical services
- [ ] **Set up log aggregation**
- [ ] **Monitor resource usage** and adjust limits
### 🚀 Performance (OPTIONAL)
- [ ] **Horizontal Pod Autoscaler** for webapp
- [ ] **Vertical Pod Autoscaler** for data services
- [ ] **Node affinity** for data services
- [ ] **Separate storage classes** for different workloads
## Support
- Documentation: https://trigger.dev/docs/self-hosting
- GitHub Issues: https://github.com/triggerdotdev/trigger.dev/issues
- Discord: https://discord.gg/untWVke9aH
+96
View File
@@ -0,0 +1,96 @@
Thank you for installing {{ .Chart.Name }}.
Your release is named {{ .Release.Name }}.
🔐 SECURITY WARNING:
{{- if or (eq .Values.secrets.sessionSecret "2818143646516f6fffd707b36f334bbb") (eq .Values.secrets.magicLinkSecret "44da78b7bbb0dfe709cf38931d25dcdd") (eq .Values.secrets.encryptionKey "f686147ab967943ebbe9ed3b496e465a") (eq .Values.secrets.managedWorkerSecret "447c29678f9eaf289e9c4b70d3dd8a7f") }}
You are using DEFAULT SECRETS which are NOT SECURE for production!
For production deployments, generate new secrets:
1. Run: openssl rand -hex 16 (repeat for each secret)
2. Override in your values.yaml:
secrets:
sessionSecret: "your-new-32-char-hex-secret"
magicLinkSecret: "your-new-32-char-hex-secret"
encryptionKey: "your-new-32-char-hex-secret"
managedWorkerSecret: "your-new-32-char-hex-secret"
{{- else }}
Custom secrets detected - good for production deployment!
{{- end }}
To get started:
1. Wait for all pods to be ready:
kubectl get pods --namespace {{ .Release.Namespace }} -w
2. Access the webapp:
{{- if .Values.webapp.ingress.enabled }}
{{- range $host := .Values.webapp.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.webapp.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.webapp.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "trigger-v4.fullname" . }}-webapp)
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.webapp.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "trigger-v4.fullname" . }}-webapp'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "trigger-v4.fullname" . }}-webapp --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.webapp.service.port }}
{{- else if contains "ClusterIP" .Values.webapp.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "{{ include "trigger-v4.selectorLabels" . }},app.kubernetes.io/component=webapp" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8030:$CONTAINER_PORT
The application will be available at http://localhost:8030
{{- end }}
For more information about the deployment, run:
kubectl --namespace {{ .Release.Namespace }} get all -l "{{ include "trigger-v4.selectorLabels" . }}"
{{- if .Values.webapp.bootstrap.enabled }}
Bootstrap Mode is enabled:
- Worker group "{{ .Values.webapp.bootstrap.workerGroupName }}" will be automatically created
- Worker token will be available at {{ .Values.webapp.bootstrap.workerTokenPath }}
{{- end }}
Configuration:
{{- if .Values.postgres.deploy }}
- Using internal PostgreSQL
{{- else }}
- Using external PostgreSQL at {{ .Values.postgres.external.host }}:{{ .Values.postgres.external.port | default 5432 }}
{{- end }}
{{- if .Values.redis.deploy }}
- Using internal Redis
{{- else }}
- Using external Redis at {{ .Values.redis.external.host }}:{{ .Values.redis.external.port | default 6379 }}
{{- end }}
{{- if .Values.electric.deploy }}
- Using internal Electric sync service
{{- else }}
- Using external Electric sync service at {{ .Values.electric.external.url }}
{{- end }}
{{- if .Values.clickhouse.deploy }}
- Using internal ClickHouse
{{- else }}
- Using external ClickHouse at {{ .Values.clickhouse.external.host }}:{{ .Values.clickhouse.external.httpPort | default 8123 }}
{{- end }}
{{- if .Values.s3.deploy }}
- Using internal S3-compatible object storage (MinIO)
{{- else }}
- Using external S3-compatible object storage at {{ .Values.s3.external.endpoint }}
{{- end }}
{{- if .Values.registry.deploy }}
- Using internal Docker registry
{{- else }}
- Using external Docker registry at {{ .Values.registry.external.host }}
{{- if hasPrefix "localhost" .Values.registry.external.host }}
⚠️ Registry Warning:
Using localhost for registry. Deployments will only work when testing locally in kind or minikube.
Please ensure registry.external is properly configured to point at an external registry.
{{- end }}
{{- end }}
+654
View File
@@ -0,0 +1,654 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "trigger-v4.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "trigger-v4.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "trigger-v4.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "trigger-v4.labels" -}}
helm.sh/chart: {{ include "trigger-v4.chart" . }}
{{ include "trigger-v4.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "trigger-v4.selectorLabels" -}}
app.kubernetes.io/name: {{ include "trigger-v4.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Component labels
*/}}
{{- define "trigger-v4.componentLabels" -}}
{{ include "trigger-v4.labels" . }}
app.kubernetes.io/component: {{ .component }}
{{- end }}
{{/*
Component selector labels
*/}}
{{- define "trigger-v4.componentSelectorLabels" -}}
{{ include "trigger-v4.selectorLabels" . }}
app.kubernetes.io/component: {{ .component }}
{{- end }}
{{/*
Get the full image name for webapp
*/}}
{{- define "trigger-v4.image" -}}
{{- $registry := .Values.global.imageRegistry | default .Values.webapp.image.registry -}}
{{- $repository := .Values.webapp.image.repository -}}
{{- $tag := .Values.webapp.image.tag | default .Chart.AppVersion -}}
{{- if $registry }}
{{- printf "%s/%s:%s" $registry $repository $tag }}
{{- else }}
{{- printf "%s:%s" $repository $tag }}
{{- end }}
{{- end }}
{{/*
Get the full image name for supervisor
*/}}
{{- define "trigger-v4.supervisor.image" -}}
{{- $registry := .Values.global.imageRegistry | default .Values.supervisor.image.registry -}}
{{- $repository := .Values.supervisor.image.repository -}}
{{- $tag := .Values.supervisor.image.tag | default .Chart.AppVersion -}}
{{- if $registry }}
{{- printf "%s/%s:%s" $registry $repository $tag }}
{{- else }}
{{- printf "%s:%s" $repository $tag }}
{{- end }}
{{- end }}
{{/*
Get the full image name for webapp volumePermissions init container
*/}}
{{- define "trigger-v4.webapp.volumePermissions.image" -}}
{{- $registry := .Values.global.imageRegistry | default .Values.webapp.volumePermissions.image.registry -}}
{{- $repository := .Values.webapp.volumePermissions.image.repository -}}
{{- $tag := .Values.webapp.volumePermissions.image.tag -}}
{{- if $registry }}
{{- printf "%s/%s:%s" $registry $repository $tag }}
{{- else }}
{{- printf "%s:%s" $repository $tag }}
{{- end }}
{{- end }}
{{/*
Get the full image name for webapp tokenSyncer sidecar
*/}}
{{- define "trigger-v4.webapp.tokenSyncer.image" -}}
{{- $registry := .Values.global.imageRegistry | default .Values.webapp.tokenSyncer.image.registry -}}
{{- $repository := .Values.webapp.tokenSyncer.image.repository -}}
{{- $tag := .Values.webapp.tokenSyncer.image.tag -}}
{{- if $registry }}
{{- printf "%s/%s:%s" $registry $repository $tag }}
{{- else }}
{{- printf "%s:%s" $repository $tag }}
{{- end }}
{{- end }}
{{/*
PostgreSQL hostname (deprecated - used only for legacy DATABASE_HOST env var)
*/}}
{{- define "trigger-v4.postgres.hostname" -}}
{{- if .Values.postgres.deploy }}
{{- printf "%s-postgres" .Release.Name }}
{{- else }}
{{- "external-postgres" }}
{{- end }}
{{- end }}
{{/*
PostgreSQL connection string (fallback when not using secrets)
*/}}
{{- define "trigger-v4.postgres.connectionString" -}}
{{- if .Values.postgres.external.databaseUrl -}}
{{ .Values.postgres.external.databaseUrl }}
{{- else if .Values.postgres.deploy -}}
postgresql://{{ .Values.postgres.auth.username }}:{{ .Values.postgres.auth.password }}@{{ include "trigger-v4.postgres.hostname" . }}:5432/{{ .Values.postgres.auth.database }}?schema={{ .Values.postgres.connection.schema | default "public" }}&sslmode={{ .Values.postgres.connection.sslMode | default "prefer" }}
{{- end -}}
{{- end }}
{{/*
Check if we should use DATABASE_URL from secret
*/}}
{{- define "trigger-v4.postgres.useSecretUrl" -}}
{{- and .Values.postgres.external.existingSecret -}}
{{- end }}
{{/*
Redis hostname
*/}}
{{- define "trigger-v4.redis.hostname" -}}
{{- if .Values.redis.external.host }}
{{- .Values.redis.external.host }}
{{- else if .Values.redis.deploy }}
{{- printf "%s-redis-master" .Release.Name }}
{{- end }}
{{- end }}
{{/*
Redis connection details
*/}}
{{- define "trigger-v4.redis.host" -}}
{{- include "trigger-v4.redis.hostname" . }}
{{- end }}
{{- define "trigger-v4.redis.port" -}}
{{- if .Values.redis.external.host -}}
{{ .Values.redis.external.port | default 6379 }}
{{- else if .Values.redis.deploy -}}
6379
{{- end -}}
{{- end }}
{{/*
Redis password
*/}}
{{- define "trigger-v4.redis.password" -}}
{{- if .Values.redis.external.host -}}
{{ .Values.redis.external.password }}
{{- else if .Values.redis.deploy -}}
{{ .Values.redis.auth.password }}
{{- end -}}
{{- end }}
{{/*
Redis TLS disabled setting
*/}}
{{- define "trigger-v4.redis.tlsDisabled" -}}
{{- if .Values.redis.external.host -}}
{{ not (.Values.redis.external.tls.enabled | default false) }}
{{- else -}}
{{- true -}}
{{- end -}}
{{- end }}
{{/*
PostgreSQL external secret name
*/}}
{{- define "trigger-v4.postgres.external.secretName" -}}
{{- if .Values.postgres.external.existingSecret -}}
{{ .Values.postgres.external.existingSecret }}
{{- else -}}
{{ include "trigger-v4.secretsName" . }}
{{- end -}}
{{- end }}
{{/*
PostgreSQL external secret database URL key
*/}}
{{- define "trigger-v4.postgres.external.databaseUrlKey" -}}
{{- if .Values.postgres.external.existingSecret -}}
{{ .Values.postgres.external.secretKeys.databaseUrlKey }}
{{- else -}}
postgres-database-url
{{- end -}}
{{- end }}
{{/*
PostgreSQL external secret direct URL key
*/}}
{{- define "trigger-v4.postgres.external.directUrlKey" -}}
{{- if .Values.postgres.external.existingSecret -}}
{{ .Values.postgres.external.secretKeys.directUrlKey | default .Values.postgres.external.secretKeys.databaseUrlKey }}
{{- else -}}
postgres-direct-url
{{- end -}}
{{- end }}
{{/*
PostgreSQL direct URL (fallback to database URL if not set)
*/}}
{{- define "trigger-v4.postgres.directUrl" -}}
{{- if .Values.postgres.external.directUrl -}}
{{ .Values.postgres.external.directUrl }}
{{- else -}}
{{ include "trigger-v4.postgres.connectionString" . }}
{{- end -}}
{{- end }}
{{/*
Redis external secret name
*/}}
{{- define "trigger-v4.redis.external.secretName" -}}
{{- if .Values.redis.external.existingSecret -}}
{{ .Values.redis.external.existingSecret }}
{{- else -}}
{{ include "trigger-v4.secretsName" . }}
{{- end -}}
{{- end }}
{{/*
Redis external secret password key
*/}}
{{- define "trigger-v4.redis.external.passwordKey" -}}
{{- if .Values.redis.external.existingSecret -}}
{{ .Values.redis.external.existingSecretPasswordKey }}
{{- else -}}
redis-password
{{- end -}}
{{- end }}
{{/*
ClickHouse external secret name
*/}}
{{- define "trigger-v4.clickhouse.external.secretName" -}}
{{- if .Values.clickhouse.external.existingSecret -}}
{{ .Values.clickhouse.external.existingSecret }}
{{- else -}}
{{ include "trigger-v4.secretsName" . }}
{{- end -}}
{{- end }}
{{/*
ClickHouse external secret password key
*/}}
{{- define "trigger-v4.clickhouse.external.passwordKey" -}}
{{- if .Values.clickhouse.external.existingSecret -}}
{{ .Values.clickhouse.external.existingSecretKey }}
{{- else -}}
clickhouse-password
{{- end -}}
{{- end }}
{{/*
S3 external secret name
*/}}
{{- define "trigger-v4.s3.external.secretName" -}}
{{- if .Values.s3.external.existingSecret -}}
{{ .Values.s3.external.existingSecret }}
{{- else -}}
{{ include "trigger-v4.secretsName" . }}
{{- end -}}
{{- end }}
{{/*
S3 external secret access key ID key
*/}}
{{- define "trigger-v4.s3.external.accessKeyIdKey" -}}
{{- if .Values.s3.external.existingSecret -}}
{{ .Values.s3.external.existingSecretAccessKeyIdKey }}
{{- else -}}
s3-access-key-id
{{- end -}}
{{- end }}
{{/*
S3 external secret secret access key key
*/}}
{{- define "trigger-v4.s3.external.secretAccessKeyKey" -}}
{{- if .Values.s3.external.existingSecret -}}
{{ .Values.s3.external.existingSecretSecretAccessKeyKey }}
{{- else -}}
s3-secret-access-key
{{- end -}}
{{- end }}
{{/*
S3 auth secret name
*/}}
{{- define "trigger-v4.s3.auth.secretName" -}}
{{- if .Values.s3.auth.existingSecret -}}
{{ .Values.s3.auth.existingSecret }}
{{- else -}}
{{ include "trigger-v4.secretsName" . }}
{{- end -}}
{{- end }}
{{/*
S3 auth secret access key ID key
*/}}
{{- define "trigger-v4.s3.auth.accessKeyIdKey" -}}
{{- if .Values.s3.auth.existingSecret -}}
{{ .Values.s3.auth.accessKeyIdSecretKey }}
{{- else -}}
s3-auth-access-key-id
{{- end -}}
{{- end }}
{{/*
S3 auth secret secret access key key
*/}}
{{- define "trigger-v4.s3.auth.secretAccessKeyKey" -}}
{{- if .Values.s3.auth.existingSecret -}}
{{ .Values.s3.auth.secretAccessKeySecretKey }}
{{- else -}}
s3-auth-secret-access-key
{{- end -}}
{{- end }}
{{/*
S3 auth effective access key ID (with fallback to rootUser)
*/}}
{{- define "trigger-v4.s3.auth.effectiveAccessKeyId" -}}
{{- if .Values.s3.auth.accessKeyId -}}
{{ .Values.s3.auth.accessKeyId }}
{{- else -}}
{{ .Values.s3.auth.rootUser }}
{{- end -}}
{{- end }}
{{/*
S3 auth effective secret access key (with fallback to rootPassword)
*/}}
{{- define "trigger-v4.s3.auth.effectiveSecretAccessKey" -}}
{{- if .Values.s3.auth.secretAccessKey -}}
{{ .Values.s3.auth.secretAccessKey }}
{{- else -}}
{{ .Values.s3.auth.rootPassword }}
{{- end -}}
{{- end }}
{{/*
Electric service URL
*/}}
{{- define "trigger-v4.electric.url" -}}
{{- if .Values.electric.deploy -}}
http://{{ include "trigger-v4.fullname" . }}-electric:{{ .Values.electric.service.port }}
{{- else -}}
{{ .Values.electric.external.url }}
{{- end -}}
{{- end }}
{{/*
Whether realtime streams v2 (S2) is wired up: either the bundled s2-lite is
deployed, or an external S2 endpoint has been configured.
*/}}
{{- define "trigger-v4.s2.enabled" -}}
{{- if or .Values.s2.deploy .Values.s2.external.endpoint -}}
true
{{- end -}}
{{- end }}
{{/*
S2 API endpoint URL, including the /v1 suffix expected by the client.
*/}}
{{- define "trigger-v4.s2.url" -}}
{{- if .Values.s2.deploy -}}
http://{{ include "trigger-v4.fullname" . }}-s2:{{ .Values.s2.service.port }}/v1
{{- else -}}
{{ .Values.s2.external.endpoint }}
{{- end -}}
{{- end }}
{{/*
ClickHouse hostname
*/}}
{{- define "trigger-v4.clickhouse.hostname" -}}
{{- if .Values.clickhouse.host }}
{{- .Values.clickhouse.host }}
{{- else if .Values.clickhouse.deploy }}
{{- printf "%s-clickhouse" .Release.Name }}
{{- end }}
{{- end }}
{{/*
ClickHouse URL for application (with secure parameter)
Note on the external+existingSecret branch: the password is expanded via
Kubernetes' `$(VAR)` syntax, not shell `${VAR}`. Kubelet substitutes
`$(CLICKHOUSE_PASSWORD)` at container-creation time from the
CLICKHOUSE_PASSWORD env var declared just before CLICKHOUSE_URL in
webapp.yaml. Shell-style `${...}` does not work here because
`docker/scripts/entrypoint.sh` assigns CLICKHOUSE_URL to GOOSE_DBSTRING
with a single-pass expansion (`export GOOSE_DBSTRING="$CLICKHOUSE_URL"`),
so any inner `${...}` reaches goose verbatim and fails URL parsing.
CLICKHOUSE_PASSWORD must contain only URL-userinfo-safe characters — the
value is substituted verbatim, so `@ : / ? # [ ] %` break the URL. Use a
hex-encoded password or percent-encode before storing in the Secret.
*/}}
{{- define "trigger-v4.clickhouse.url" -}}
{{- if .Values.clickhouse.deploy -}}
{{- $protocol := ternary "https" "http" .Values.clickhouse.secure -}}
{{- $secure := ternary "true" "false" .Values.clickhouse.secure -}}
{{ $protocol }}://{{ .Values.clickhouse.auth.username }}:{{ .Values.clickhouse.auth.password }}@{{ include "trigger-v4.clickhouse.hostname" . }}:8123?secure={{ $secure }}
{{- else if .Values.clickhouse.external.host -}}
{{- $protocol := ternary "https" "http" .Values.clickhouse.external.secure -}}
{{- $secure := ternary "true" "false" .Values.clickhouse.external.secure -}}
{{- if .Values.clickhouse.external.existingSecret -}}
{{ $protocol }}://{{ .Values.clickhouse.external.username }}:$(CLICKHOUSE_PASSWORD)@{{ .Values.clickhouse.external.host }}:{{ .Values.clickhouse.external.httpPort | default 8123 }}?secure={{ $secure }}
{{- else -}}
{{ $protocol }}://{{ .Values.clickhouse.external.username }}:{{ .Values.clickhouse.external.password }}@{{ .Values.clickhouse.external.host }}:{{ .Values.clickhouse.external.httpPort | default 8123 }}?secure={{ $secure }}
{{- end -}}
{{- end -}}
{{- end }}
{{/*
ClickHouse URL for replication (without secure parameter)
See the note on clickhouse.url above — same `$(VAR)` vs `${VAR}` rationale
applies to the replication URL.
*/}}
{{- define "trigger-v4.clickhouse.replication.url" -}}
{{- if .Values.clickhouse.deploy -}}
{{- $protocol := ternary "https" "http" .Values.clickhouse.secure -}}
{{ $protocol }}://{{ .Values.clickhouse.auth.username }}:{{ .Values.clickhouse.auth.password }}@{{ include "trigger-v4.clickhouse.hostname" . }}:8123
{{- else if .Values.clickhouse.external.host -}}
{{- $protocol := ternary "https" "http" .Values.clickhouse.external.secure -}}
{{- if .Values.clickhouse.external.existingSecret -}}
{{ $protocol }}://{{ .Values.clickhouse.external.username }}:$(CLICKHOUSE_PASSWORD)@{{ .Values.clickhouse.external.host }}:{{ .Values.clickhouse.external.httpPort | default 8123 }}
{{- else -}}
{{ $protocol }}://{{ .Values.clickhouse.external.username }}:{{ .Values.clickhouse.external.password }}@{{ .Values.clickhouse.external.host }}:{{ .Values.clickhouse.external.httpPort | default 8123 }}
{{- end -}}
{{- end -}}
{{- end }}
{{/*
S3 hostname
*/}}
{{- define "trigger-v4.s3.hostname" -}}
{{- if .Values.s3.external.endpoint }}
{{- .Values.s3.external.endpoint }}
{{- else if .Values.s3.deploy }}
{{- printf "http://%s-minio:9000" .Release.Name }}
{{- end }}
{{- end }}
{{/*
S3 connection details
*/}}
{{- define "trigger-v4.s3.url" -}}
{{- include "trigger-v4.s3.hostname" . }}
{{- end }}
{{/*
Backward compatibility - MinIO helpers (deprecated)
*/}}
{{- define "trigger-v4.minio.hostname" -}}
{{- include "trigger-v4.s3.hostname" . }}
{{- end }}
{{- define "trigger-v4.minio.url" -}}
{{- include "trigger-v4.s3.url" . }}
{{- end }}
{{/*
Get the secrets name - either existing secret or generated name
*/}}
{{- define "trigger-v4.secretsName" -}}
{{- if .Values.secrets.existingSecret -}}
{{ .Values.secrets.existingSecret }}
{{- else -}}
{{ include "trigger-v4.fullname" . }}-secrets
{{- end -}}
{{- end }}
{{/*
Registry connection details
*/}}
{{- define "trigger-v4.registry.host" -}}
{{- if .Values.registry.deploy -}}
{{ .Values.registry.host }}
{{- else -}}
{{ .Values.registry.external.host }}
{{- end -}}
{{- end }}
{{/*
Webapp connectivity check enabled
*/}}
{{- define "trigger-v4.webapp.connectivityCheckEnabled" -}}
{{- $connectivityCheckEnabled := true -}}
{{- if hasKey .Values.webapp "connectivityCheck" -}}
{{- if hasKey .Values.webapp.connectivityCheck "postgres" -}}
{{- $connectivityCheckEnabled = .Values.webapp.connectivityCheck.postgres -}}
{{- end -}}
{{- end -}}
{{- $connectivityCheckEnabled -}}
{{- end }}
{{/*
PostgreSQL host (for wait-for-it script)
*/}}
{{- define "trigger-v4.postgres.host" -}}
{{- if .Values.postgres.deploy -}}
{{ include "trigger-v4.postgres.hostname" . }}:5432
{{- else if .Values.postgres.external.connectivityCheck.host -}}
{{ .Values.postgres.external.connectivityCheck.host }}
{{- end -}}
{{- end }}
{{/*
Supervisor connection details
*/}}
{{- define "trigger-v4.supervisor.url" -}}
{{- if .Values.supervisor.enabled -}}
http://{{ include "trigger-v4.fullname" . }}-supervisor:{{ .Values.supervisor.service.ports.workload }}
{{- else -}}
""
{{- end -}}
{{- end }}
{{/*
Create the name of the supervisor service account to use.
When create is false, name must be set explicitly - falling back to the namespace's
default ServiceAccount would silently grant it the RoleBinding's permissions.
*/}}
{{- define "trigger-v4.supervisorServiceAccountName" -}}
{{- if .Values.supervisor.serviceAccount.create }}
{{- default (printf "%s-supervisor" (include "trigger-v4.fullname" .)) .Values.supervisor.serviceAccount.name }}
{{- else }}
{{- if not .Values.supervisor.serviceAccount.name }}
{{- fail "supervisor.serviceAccount.name must be set when supervisor.serviceAccount.create is false" }}
{{- end }}
{{- .Values.supervisor.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Create the name of the webapp service account to use.
When create is false, name must be set explicitly - falling back to the namespace's
default ServiceAccount would silently grant it the token-syncer RoleBinding's permissions.
*/}}
{{- define "trigger-v4.webappServiceAccountName" -}}
{{- if .Values.webapp.serviceAccount.create }}
{{- default (printf "%s-webapp" (include "trigger-v4.fullname" .)) .Values.webapp.serviceAccount.name }}
{{- else }}
{{- if not .Values.webapp.serviceAccount.name }}
{{- fail "webapp.serviceAccount.name must be set when webapp.serviceAccount.create is false" }}
{{- end }}
{{- .Values.webapp.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Create the name of the supervisor role to use
*/}}
{{- define "trigger-v4.supervisorRoleName" -}}
{{- default (printf "%s-supervisor-%s" (include "trigger-v4.fullname" .) .Release.Namespace) .Values.supervisor.rbac.role.name }}
{{- end }}
{{/*
Generate docker config for image pull secret
*/}}
{{- define "trigger-v4.imagePullSecret" }}
{{- if and .Values.registry.deploy .Values.registry.auth.enabled }}
{{- $registryHost := include "trigger-v4.registry.host" . }}
{{- $username := .Values.registry.auth.username }}
{{- $password := .Values.registry.auth.password }}
{{- $auth := printf "%s:%s" $username $password | b64enc }}
{{- $config := dict "auths" (dict $registryHost (dict "username" $username "password" $password "auth" $auth)) }}
{{- $config | toJson }}
{{- else if and (not .Values.registry.deploy) .Values.registry.external.auth.enabled }}
{{- $registryHost := .Values.registry.external.host }}
{{- $username := .Values.registry.external.auth.username }}
{{- $password := .Values.registry.external.auth.password }}
{{- $auth := printf "%s:%s" $username $password | b64enc }}
{{- $config := dict "auths" (dict $registryHost (dict "username" $username "password" $password "auth" $auth)) }}
{{- $config | toJson }}
{{- end }}
{{- end }}
{{/*
Merge webapp ingress annotations to avoid duplicates
*/}}
{{- define "trigger-v4.webapp.ingress.annotations" -}}
{{- $annotations := dict -}}
{{- if .Values.webapp.ingress.annotations -}}
{{- $annotations = .Values.webapp.ingress.annotations -}}
{{- end -}}
{{- if .Values.webapp.ingress.certManager.enabled -}}
{{- $_ := set $annotations "cert-manager.io/cluster-issuer" .Values.webapp.ingress.certManager.clusterIssuer -}}
{{- end -}}
{{- if .Values.webapp.ingress.externalDns.enabled -}}
{{- $_ := set $annotations "external-dns.alpha.kubernetes.io/hostname" .Values.webapp.ingress.externalDns.hostname -}}
{{- $_ := set $annotations "external-dns.alpha.kubernetes.io/ttl" (.Values.webapp.ingress.externalDns.ttl | toString) -}}
{{- end -}}
{{- toYaml $annotations -}}
{{- end }}
{{/*
Merge registry ingress annotations to avoid duplicates
*/}}
{{- define "trigger-v4.registry.ingress.annotations" -}}
{{- $annotations := dict -}}
{{- if .Values.registry.ingress.annotations -}}
{{- $annotations = .Values.registry.ingress.annotations -}}
{{- end -}}
{{- if .Values.registry.ingress.certManager.enabled -}}
{{- $_ := set $annotations "cert-manager.io/cluster-issuer" .Values.registry.ingress.certManager.clusterIssuer -}}
{{- end -}}
{{- if .Values.registry.ingress.externalDns.enabled -}}
{{- $_ := set $annotations "external-dns.alpha.kubernetes.io/hostname" .Values.registry.ingress.externalDns.hostname -}}
{{- $_ := set $annotations "external-dns.alpha.kubernetes.io/ttl" (.Values.registry.ingress.externalDns.ttl | toString) -}}
{{- end -}}
{{- toYaml $annotations -}}
{{- end }}
+109
View File
@@ -0,0 +1,109 @@
{{- if .Values.electric.deploy }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "trigger-v4.fullname" . }}-electric
labels:
{{- $component := "electric" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
spec:
replicas: 1
selector:
matchLabels:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 6 }}
template:
metadata:
{{- with .Values.electric.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 8 }}
spec:
{{- with .Values.electric.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: electric
{{- with .Values.electric.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.electric.image.registry }}/{{ .Values.electric.image.repository }}:{{ .Values.electric.image.tag }}"
imagePullPolicy: {{ .Values.electric.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.electric.service.targetPort }}
protocol: TCP
env:
{{- if include "trigger-v4.postgres.useSecretUrl" . }}
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.postgres.external.secretName" . }}
key: {{ include "trigger-v4.postgres.external.databaseUrlKey" . }}
{{- else }}
- name: DATABASE_URL
value: {{ include "trigger-v4.postgres.connectionString" . | quote }}
{{- end }}
- name: ELECTRIC_INSECURE
value: {{ .Values.electric.config.insecure | quote }}
- name: ELECTRIC_USAGE_REPORTING
value: {{ .Values.electric.config.usageReporting | quote }}
{{- with .Values.electric.extraEnvVars }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.electric.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: /v1/health
port: http
initialDelaySeconds: {{ .Values.electric.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.electric.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.electric.livenessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.electric.livenessProbe.failureThreshold }}
successThreshold: {{ .Values.electric.livenessProbe.successThreshold }}
{{- end }}
{{- if .Values.electric.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: /v1/health
port: http
initialDelaySeconds: {{ .Values.electric.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.electric.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.electric.readinessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.electric.readinessProbe.failureThreshold }}
successThreshold: {{ .Values.electric.readinessProbe.successThreshold }}
{{- end }}
{{- if .Values.electric.startupProbe.enabled }}
startupProbe:
httpGet:
path: /v1/health
port: http
initialDelaySeconds: {{ .Values.electric.startupProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.electric.startupProbe.periodSeconds }}
timeoutSeconds: {{ .Values.electric.startupProbe.timeoutSeconds }}
failureThreshold: {{ .Values.electric.startupProbe.failureThreshold }}
successThreshold: {{ .Values.electric.startupProbe.successThreshold }}
{{- end }}
resources:
{{- toYaml .Values.electric.resources | nindent 12 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "trigger-v4.fullname" . }}-electric
labels:
{{- $component := "electric" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
spec:
type: {{ .Values.electric.service.type }}
ports:
- port: {{ .Values.electric.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
{{- end }}
@@ -0,0 +1,4 @@
{{- range .Values.extraManifests }}
---
{{ toYaml . }}
{{- end }}
@@ -0,0 +1,52 @@
{{- if and .Values.registry.deploy .Values.registry.ingress.enabled -}}
{{- $fullName := include "trigger-v4.fullname" . -}}
{{- $svcPort := .Values.registry.service.port -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}-registry
labels:
{{- $component := "registry" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
annotations:
{{- include "trigger-v4.registry.ingress.annotations" . | nindent 4 }}
spec:
{{- if .Values.registry.ingress.className }}
ingressClassName: {{ .Values.registry.ingress.className }}
{{- end }}
{{- if .Values.registry.ingress.tls }}
tls:
{{- range .Values.registry.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.registry.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- if .paths }}
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType | default "Prefix" }}
backend:
service:
name: {{ $fullName }}-registry
port:
number: {{ $svcPort }}
{{- end }}
{{- else }}
- path: /
pathType: Prefix
backend:
service:
name: {{ $fullName }}-registry
port:
number: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
+182
View File
@@ -0,0 +1,182 @@
{{- if .Values.registry.deploy }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "trigger-v4.fullname" . }}-registry
labels:
{{- $component := "registry" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
spec:
replicas: 1
serviceName: {{ include "trigger-v4.fullname" . }}-registry-headless
selector:
matchLabels:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 6 }}
template:
metadata:
{{- with .Values.registry.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 8 }}
spec:
{{- with .Values.registry.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: registry
{{- with .Values.registry.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.registry.image.registry }}/{{ .Values.registry.image.repository }}:{{ .Values.registry.image.tag }}"
imagePullPolicy: {{ .Values.registry.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.registry.service.targetPort }}
protocol: TCP
{{- if or .Values.registry.auth.enabled .Values.registry.extraEnvVars }}
env:
{{- if .Values.registry.auth.enabled }}
- name: REGISTRY_AUTH
value: "htpasswd"
- name: REGISTRY_AUTH_HTPASSWD_REALM
value: "Registry Realm"
- name: REGISTRY_AUTH_HTPASSWD_PATH
value: "/auth/htpasswd"
{{- end }}
{{- with .Values.registry.extraEnvVars }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
{{- if .Values.registry.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: {{ .Values.registry.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.registry.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.registry.livenessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.registry.livenessProbe.failureThreshold }}
successThreshold: {{ .Values.registry.livenessProbe.successThreshold }}
{{- end }}
{{- if .Values.registry.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: {{ .Values.registry.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.registry.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.registry.readinessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.registry.readinessProbe.failureThreshold }}
successThreshold: {{ .Values.registry.readinessProbe.successThreshold }}
{{- end }}
{{- if .Values.registry.startupProbe.enabled }}
startupProbe:
httpGet:
path: /
port: http
initialDelaySeconds: {{ .Values.registry.startupProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.registry.startupProbe.periodSeconds }}
timeoutSeconds: {{ .Values.registry.startupProbe.timeoutSeconds }}
failureThreshold: {{ .Values.registry.startupProbe.failureThreshold }}
successThreshold: {{ .Values.registry.startupProbe.successThreshold }}
{{- end }}
resources:
{{- toYaml .Values.registry.resources | nindent 12 }}
volumeMounts:
- name: {{ .Values.registry.persistence.volumeName }}
mountPath: {{ .Values.registry.persistence.mountPath }}
{{- if .Values.registry.persistence.subPath }}
subPath: {{ .Values.registry.persistence.subPath }}
{{- end }}
{{- if .Values.registry.auth.enabled }}
- name: registry-auth
mountPath: /auth
readOnly: true
{{- end }}
volumes:
{{- if .Values.registry.auth.enabled }}
- name: registry-auth
secret:
secretName: {{ include "trigger-v4.fullname" . }}-registry-auth
{{- end }}
{{- if not .Values.registry.persistence.enabled }}
- name: {{ .Values.registry.persistence.volumeName }}
emptyDir: {}
{{- else if .Values.registry.persistence.existingClaim }}
- name: {{ .Values.registry.persistence.volumeName }}
persistentVolumeClaim:
claimName: {{ .Values.registry.persistence.existingClaim }}
{{- end }}
{{- if .Values.registry.persistence.enabled }}
volumeClaimTemplates:
- metadata:
name: {{ .Values.registry.persistence.volumeName }}
{{- with .Values.registry.persistence.annotations }}
annotations:
{{- toYaml . | nindent 10 }}
{{- end }}
labels:
{{- $component := "registry" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 10 }}
{{- with .Values.registry.persistence.labels }}
{{- toYaml . | nindent 10 }}
{{- end }}
spec:
accessModes:
{{- toYaml .Values.registry.persistence.accessModes | nindent 10 }}
resources:
requests:
storage: {{ .Values.registry.persistence.size }}
{{- $storageClass := .Values.registry.persistence.storageClass | default .Values.global.storageClass }}
{{- if $storageClass }}
storageClassName: {{ $storageClass | quote }}
{{- end }}
{{- with .Values.registry.persistence.selector }}
selector:
{{- toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.registry.persistence.dataSource }}
dataSource:
{{- toYaml . | nindent 10 }}
{{- end }}
{{- end }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "trigger-v4.fullname" . }}-registry-headless
labels:
{{- $component := "registry" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
spec:
type: ClusterIP
clusterIP: None
ports:
- name: http
port: {{ .Values.registry.service.port }}
targetPort: http
protocol: TCP
selector:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "trigger-v4.fullname" . }}-registry
labels:
{{- $component := "registry" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
spec:
type: {{ .Values.registry.service.type }}
ports:
- name: http
port: {{ .Values.registry.service.port }}
targetPort: http
protocol: TCP
selector:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
{{- end }}
+142
View File
@@ -0,0 +1,142 @@
{{- if .Values.s2.deploy }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "trigger-v4.fullname" . }}-s2-spec
labels:
{{- $component := "s2" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
data:
s2-spec.json: |
{
"$schema": "https://raw.githubusercontent.com/s2-streamstore/s2/main/cli/schema.json",
"basins": [
{
"name": {{ .Values.s2.basin | quote }},
"config": {
"create_stream_on_append": true,
"create_stream_on_read": true
}
}
]
}
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "trigger-v4.fullname" . }}-s2
labels:
{{- $component := "s2" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
spec:
replicas: 1
serviceName: {{ include "trigger-v4.fullname" . }}-s2
selector:
matchLabels:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 6 }}
template:
metadata:
annotations:
checksum/spec: {{ .Values.s2.basin | sha256sum }}
{{- with .Values.s2.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 8 }}
spec:
{{- with .Values.s2.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: s2
{{- with .Values.s2.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.s2.image.registry }}/{{ .Values.s2.image.repository }}:{{ .Values.s2.image.tag }}{{ with .Values.s2.image.digest }}@{{ . }}{{ end }}"
imagePullPolicy: {{ .Values.s2.image.pullPolicy }}
command:
- "lite"
- "--init-file"
- "/config/s2-spec.json"
- "--local-root"
- "/data"
- "--port"
- {{ .Values.s2.service.targetPort | quote }}
ports:
- name: http
containerPort: {{ .Values.s2.service.targetPort }}
protocol: TCP
{{- if .Values.s2.livenessProbe.enabled }}
livenessProbe:
tcpSocket:
port: http
initialDelaySeconds: {{ .Values.s2.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.s2.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.s2.livenessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.s2.livenessProbe.failureThreshold }}
successThreshold: {{ .Values.s2.livenessProbe.successThreshold }}
{{- end }}
{{- if .Values.s2.readinessProbe.enabled }}
readinessProbe:
tcpSocket:
port: http
initialDelaySeconds: {{ .Values.s2.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.s2.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.s2.readinessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.s2.readinessProbe.failureThreshold }}
successThreshold: {{ .Values.s2.readinessProbe.successThreshold }}
{{- end }}
resources:
{{- toYaml .Values.s2.resources | nindent 12 }}
volumeMounts:
- name: spec
mountPath: /config
readOnly: true
- name: data
mountPath: /data
volumes:
- name: spec
configMap:
name: {{ include "trigger-v4.fullname" . }}-s2-spec
{{- if not .Values.s2.persistence.enabled }}
- name: data
emptyDir: {}
{{- end }}
{{- if .Values.s2.persistence.enabled }}
volumeClaimTemplates:
- metadata:
name: data
{{- if .Values.s2.persistence.retain }}
annotations:
helm.sh/resource-policy: keep
{{- end }}
spec:
accessModes:
- {{ .Values.s2.persistence.accessMode }}
resources:
requests:
storage: {{ .Values.s2.persistence.size }}
{{- if .Values.s2.persistence.storageClass }}
storageClassName: {{ .Values.s2.persistence.storageClass }}
{{- end }}
{{- end }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "trigger-v4.fullname" . }}-s2
labels:
{{- $component := "s2" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
spec:
type: {{ .Values.s2.service.type }}
ports:
- port: {{ .Values.s2.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
{{- end }}
+68
View File
@@ -0,0 +1,68 @@
{{- if and .Values.secrets.enabled (not .Values.secrets.existingSecret) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "trigger-v4.fullname" . }}-secrets
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
type: Opaque
data:
SESSION_SECRET: {{ .Values.secrets.sessionSecret | b64enc | quote }}
MAGIC_LINK_SECRET: {{ .Values.secrets.magicLinkSecret | b64enc | quote }}
ENCRYPTION_KEY: {{ .Values.secrets.encryptionKey | b64enc | quote }}
MANAGED_WORKER_SECRET: {{ .Values.secrets.managedWorkerSecret | b64enc | quote }}
{{- if and .Values.s3.external.accessKeyId (not .Values.s3.external.existingSecret) }}
s3-access-key-id: {{ .Values.s3.external.accessKeyId | b64enc | quote }}
s3-secret-access-key: {{ .Values.s3.external.secretAccessKey | b64enc | quote }}
{{- end }}
{{- if and .Values.s3.deploy (not .Values.s3.auth.existingSecret) }}
s3-auth-access-key-id: {{ include "trigger-v4.s3.auth.effectiveAccessKeyId" . | b64enc | quote }}
s3-auth-secret-access-key: {{ include "trigger-v4.s3.auth.effectiveSecretAccessKey" . | b64enc | quote }}
{{- end }}
{{- if and .Values.postgres.external.databaseUrl (not .Values.postgres.external.existingSecret) }}
postgres-database-url: {{ .Values.postgres.external.databaseUrl | b64enc | quote }}
{{- if .Values.postgres.external.directUrl }}
postgres-direct-url: {{ .Values.postgres.external.directUrl | b64enc | quote }}
{{- else }}
postgres-direct-url: {{ .Values.postgres.external.databaseUrl | b64enc | quote }}
{{- end }}
{{- end }}
{{- if and .Values.redis.external.host (not .Values.redis.external.existingSecret) .Values.redis.external.password }}
redis-password: {{ .Values.redis.external.password | b64enc | quote }}
{{- end }}
{{- if and .Values.clickhouse.external.host (not .Values.clickhouse.external.existingSecret) .Values.clickhouse.external.password }}
clickhouse-password: {{ .Values.clickhouse.external.password | b64enc | quote }}
{{- end }}
{{- end }}
---
{{- if and .Values.registry.deploy .Values.registry.auth.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "trigger-v4.fullname" . }}-registry-auth
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
type: Opaque
data:
htpasswd: {{ htpasswd .Values.registry.auth.username .Values.registry.auth.password | trim | b64enc | quote }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ include "trigger-v4.fullname" . }}-registry-secret
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: {{ include "trigger-v4.imagePullSecret" . | b64enc }}
{{- else if and (not .Values.registry.deploy) .Values.registry.external.auth.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "trigger-v4.fullname" . }}-registry-secret
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: {{ include "trigger-v4.imagePullSecret" . | b64enc }}
{{- end }}
@@ -0,0 +1,55 @@
{{- if .Values.webapp.serviceMonitor.enabled }}
---
# Webapp ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "trigger-v4.fullname" . }}-webapp
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
app.kubernetes.io/component: webapp
{{- with .Values.webapp.serviceMonitor.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
selector:
matchLabels:
{{- include "trigger-v4.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: webapp
endpoints:
- port: http
path: {{ .Values.webapp.serviceMonitor.path }}
interval: {{ .Values.webapp.serviceMonitor.interval }}
{{- with .Values.webapp.serviceMonitor.basicAuth }}
basicAuth:
{{- toYaml . | nindent 6 }}
{{- end }}
{{- end }}
{{- if .Values.supervisor.serviceMonitor.enabled }}
---
# Supervisor ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "trigger-v4.fullname" . }}-supervisor
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
app.kubernetes.io/component: supervisor
{{- with .Values.supervisor.serviceMonitor.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
selector:
matchLabels:
{{- include "trigger-v4.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: supervisor
endpoints:
- port: metrics
path: {{ .Values.supervisor.serviceMonitor.path }}
interval: {{ .Values.supervisor.serviceMonitor.interval }}
{{- with .Values.supervisor.serviceMonitor.basicAuth }}
basicAuth:
{{- toYaml . | nindent 6 }}
{{- end }}
{{- end }}
+295
View File
@@ -0,0 +1,295 @@
{{- if .Values.supervisor.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "trigger-v4.supervisorServiceAccountName" . }}
labels:
{{- $component := "supervisor" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
{{- with .Values.supervisor.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- if .Values.supervisor.rbac.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "trigger-v4.supervisorRoleName" . }}
namespace: {{ default .Release.Namespace .Values.supervisor.config.kubernetes.namespace }}
labels:
{{- $component := "supervisor" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "delete", "deletecollection", "get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "trigger-v4.supervisorRoleName" . }}-binding
namespace: {{ default .Release.Namespace .Values.supervisor.config.kubernetes.namespace }}
labels:
{{- $component := "supervisor" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
subjects:
- kind: ServiceAccount
name: {{ include "trigger-v4.supervisorServiceAccountName" . }}
namespace: {{ default .Release.Namespace }}
roleRef:
kind: Role
name: {{ include "trigger-v4.supervisorRoleName" . }}
apiGroup: rbac.authorization.k8s.io
{{- end }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "trigger-v4.fullname" . }}-supervisor
labels:
{{- $component := "supervisor" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 6 }}
template:
metadata:
labels:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 8 }}
{{- with .Values.supervisor.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
serviceAccountName: {{ include "trigger-v4.supervisorServiceAccountName" . }}
securityContext:
fsGroup: 1000
{{- with .Values.supervisor.podSecurityContext }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if not .Values.webapp.bootstrap.enabled }}
initContainers:
- name: init-shared
image: busybox:1.35
command: ['sh', '-c', 'mkdir -p /home/node/shared']
securityContext:
runAsUser: 1000
volumeMounts:
- name: shared
mountPath: /home/node/shared
{{- end }}
containers:
- name: supervisor
image: {{ include "trigger-v4.supervisor.image" . }}
imagePullPolicy: {{ .Values.supervisor.image.pullPolicy }}
ports:
- name: workload
containerPort: {{ .Values.supervisor.service.ports.workload }}
protocol: TCP
- name: metrics
containerPort: {{ .Values.supervisor.service.ports.metrics }}
protocol: TCP
{{- if .Values.supervisor.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: /health
port: workload
initialDelaySeconds: {{ .Values.supervisor.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.supervisor.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.supervisor.livenessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.supervisor.livenessProbe.failureThreshold }}
successThreshold: {{ .Values.supervisor.livenessProbe.successThreshold }}
{{- end }}
{{- if .Values.supervisor.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: /health
port: workload
initialDelaySeconds: {{ .Values.supervisor.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.supervisor.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.supervisor.readinessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.supervisor.readinessProbe.failureThreshold }}
successThreshold: {{ .Values.supervisor.readinessProbe.successThreshold }}
{{- end }}
{{- if .Values.supervisor.startupProbe.enabled }}
startupProbe:
httpGet:
path: /health
port: workload
initialDelaySeconds: {{ .Values.supervisor.startupProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.supervisor.startupProbe.periodSeconds }}
timeoutSeconds: {{ .Values.supervisor.startupProbe.timeoutSeconds }}
failureThreshold: {{ .Values.supervisor.startupProbe.failureThreshold }}
successThreshold: {{ .Values.supervisor.startupProbe.successThreshold }}
{{- end }}
resources:
{{- toYaml .Values.supervisor.resources | nindent 12 }}
env:
# Core configuration
- name: TRIGGER_API_URL
value: "http://{{ include "trigger-v4.fullname" . }}-webapp:{{ .Values.webapp.service.port }}"
- name: TRIGGER_WORKER_TOKEN
{{- if .Values.webapp.bootstrap.enabled }}
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.fullname" . }}-worker-token
key: token
{{- else if .Values.supervisor.bootstrap.workerToken.secret.name }}
valueFrom:
secretKeyRef:
name: {{ .Values.supervisor.bootstrap.workerToken.secret.name }}
key: {{ .Values.supervisor.bootstrap.workerToken.secret.key }}
{{- else }}
value: {{ .Values.supervisor.bootstrap.workerToken.value | quote }}
{{- end }}
{{- if or .Values.secrets.enabled .Values.secrets.existingSecret }}
- name: MANAGED_WORKER_SECRET
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.secretsName" . }}
key: MANAGED_WORKER_SECRET
{{- end }}
# Worker instance configuration
- name: TRIGGER_WORKER_INSTANCE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
# Kubernetes configuration
- name: KUBERNETES_NAMESPACE
value: {{ default .Release.Namespace .Values.supervisor.config.kubernetes.namespace | quote }}
- name: KUBERNETES_FORCE_ENABLED
value: {{ .Values.supervisor.config.kubernetes.forceEnabled | quote }}
- name: KUBERNETES_WORKER_NODETYPE_LABEL
value: {{ .Values.supervisor.config.kubernetes.workerNodetypeLabel | quote }}
{{- $registryAuthEnabled := false }}
{{- if .Values.registry.deploy }}
{{- $registryAuthEnabled = .Values.registry.auth.enabled }}
{{- else }}
{{- $registryAuthEnabled = .Values.registry.external.auth.enabled }}
{{- end }}
{{- if $registryAuthEnabled }}
- name: KUBERNETES_IMAGE_PULL_SECRETS
value: "{{ include "trigger-v4.fullname" . }}-registry-secret"
{{- end }}
- name: KUBERNETES_EPHEMERAL_STORAGE_SIZE_LIMIT
value: {{ default "10Gi" .Values.supervisor.config.kubernetes.ephemeralStorageSizeLimit | quote }}
- name: KUBERNETES_EPHEMERAL_STORAGE_SIZE_REQUEST
value: {{ default "2Gi" .Values.supervisor.config.kubernetes.ephemeralStorageSizeRequest | quote }}
# Pod cleaner configuration
- name: POD_CLEANER_ENABLED
value: {{ .Values.supervisor.config.podCleaner.enabled | quote }}
- name: POD_CLEANER_BATCH_SIZE
value: {{ .Values.supervisor.config.podCleaner.batchSize | quote }}
- name: POD_CLEANER_INTERVAL_MS
value: {{ .Values.supervisor.config.podCleaner.intervalMs | quote }}
# Failed pod handler
- name: FAILED_POD_HANDLER_ENABLED
value: {{ .Values.supervisor.config.failedPodHandler.enabled | quote }}
- name: FAILED_POD_HANDLER_RECONNECT_INTERVAL_MS
value: {{ .Values.supervisor.config.failedPodHandler.reconnectIntervalMs | quote }}
# Workload API configuration
- name: TRIGGER_WORKLOAD_API_PROTOCOL
value: {{ .Values.supervisor.config.workloadApi.protocol | quote }}
- name: TRIGGER_WORKLOAD_API_DOMAIN
value: "{{ include "trigger-v4.fullname" . }}-supervisor.{{ .Release.Namespace }}.svc.cluster.local"
- name: TRIGGER_WORKLOAD_API_PORT_EXTERNAL
value: {{ .Values.supervisor.config.workloadApi.portExternal | quote }}
- name: TRIGGER_WORKLOAD_API_PORT_INTERNAL
value: {{ .Values.supervisor.config.workloadApi.portInternal | quote }}
- name: TRIGGER_WORKLOAD_API_HOST_INTERNAL
value: {{ .Values.supervisor.config.workloadApi.hostInternal | quote }}
- name: TRIGGER_WORKLOAD_API_ENABLED
value: {{ .Values.supervisor.config.workloadApi.enabled | quote }}
# Dequeue configuration
- name: TRIGGER_DEQUEUE_ENABLED
value: {{ .Values.supervisor.config.dequeue.enabled | quote }}
- name: TRIGGER_DEQUEUE_INTERVAL_MS
value: {{ .Values.supervisor.config.dequeue.intervalMs | quote }}
- name: TRIGGER_DEQUEUE_MAX_RUN_COUNT
value: {{ .Values.supervisor.config.dequeue.maxRunCount | quote }}
- name: TRIGGER_DEQUEUE_IDLE_INTERVAL_MS
value: {{ .Values.supervisor.config.dequeue.idleIntervalMs | quote }}
# Heartbeat configuration
- name: RUNNER_HEARTBEAT_INTERVAL_SECONDS
value: {{ .Values.supervisor.config.runner.heartbeatIntervalSeconds | quote }}
- name: RUNNER_SNAPSHOT_POLL_INTERVAL_SECONDS
value: {{ .Values.supervisor.config.runner.snapshotPollIntervalSeconds | quote }}
# Metrics configuration
- name: METRICS_ENABLED
value: {{ .Values.supervisor.config.metrics.enabled | quote }}
- name: METRICS_COLLECT_DEFAULTS
value: {{ .Values.supervisor.config.metrics.collectDefaults | quote }}
- name: METRICS_HOST
value: {{ .Values.supervisor.config.metrics.host | quote }}
- name: METRICS_PORT
value: {{ .Values.supervisor.config.metrics.port | quote }}
# Debug
- name: DEBUG
value: {{ .Values.supervisor.config.debug | quote }}
# OTEL
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://{{ include "trigger-v4.fullname" . }}-webapp.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.webapp.service.port }}/otel"
{{- with .Values.supervisor.extraEnvVars }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if not .Values.webapp.bootstrap.enabled }}
volumeMounts:
- name: shared
mountPath: /home/node/shared
{{- end }}
{{- with .Values.supervisor.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if not .Values.webapp.bootstrap.enabled }}
volumes:
- name: shared
{{- if .Values.persistence.shared.enabled }}
persistentVolumeClaim:
claimName: {{ include "trigger-v4.fullname" . }}-shared
{{- else }}
emptyDir: {}
{{- end }}
{{- end }}
{{- with .Values.supervisor.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.supervisor.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.supervisor.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "trigger-v4.fullname" . }}-supervisor
labels:
{{- $component := "supervisor" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
spec:
type: {{ .Values.supervisor.service.type }}
ports:
- port: {{ .Values.supervisor.service.ports.workload }}
targetPort: workload
protocol: TCP
name: workload
- port: {{ .Values.supervisor.service.ports.metrics }}
targetPort: metrics
protocol: TCP
name: metrics
selector:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
@@ -0,0 +1,21 @@
{{- if .Values.clickhouse.deploy }}
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "trigger-v4.fullname" . }}-test-clickhouse"
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
restartPolicy: Never
containers:
- name: test-clickhouse
image: curlimages/curl:8.14.1
command: ['sh', '-c']
args:
- |
echo "Testing ClickHouse HTTP interface..."
curl -f --user "{{ .Values.clickhouse.auth.adminUser }}:{{ .Values.clickhouse.auth.adminPassword }}" "http://{{ include "trigger-v4.fullname" . }}-clickhouse:{{ .Values.clickhouse.service.ports.http }}/ping"
echo "ClickHouse test completed successfully"
{{- end }}
@@ -0,0 +1,21 @@
{{- if .Values.electric.deploy }}
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "trigger-v4.fullname" . }}-test-electric"
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
restartPolicy: Never
containers:
- name: test-electric
image: curlimages/curl:8.14.1
command: ['sh', '-c']
args:
- |
echo "Testing Electric health endpoint..."
curl -f http://{{ include "trigger-v4.fullname" . }}-electric:{{ .Values.electric.service.port }}/api/status
echo "Electric test completed successfully"
{{- end }}
@@ -0,0 +1,21 @@
{{- if .Values.postgres.deploy }}
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "trigger-v4.fullname" . }}-test-postgres"
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
restartPolicy: Never
containers:
- name: test-postgres
image: {{ .Values.postgres.image.registry }}/{{ .Values.postgres.image.repository }}:{{ .Values.postgres.image.tag }}
command: ['sh', '-c']
args:
- |
echo "Testing PostgreSQL connection..."
pg_isready -h {{ include "trigger-v4.fullname" . }}-postgres -p {{ .Values.postgres.primary.service.ports.postgres }} -U {{ .Values.postgres.auth.username }}
echo "PostgreSQL test completed successfully"
{{- end }}
@@ -0,0 +1,21 @@
{{- if .Values.redis.deploy }}
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "trigger-v4.fullname" . }}-test-redis"
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
restartPolicy: Never
containers:
- name: test-redis
image: {{ .Values.redis.image.registry }}/{{ .Values.redis.image.repository }}:{{ .Values.redis.image.tag }}
command: ['sh', '-c']
args:
- |
echo "Testing Redis connection..."
redis-cli -h {{ include "trigger-v4.fullname" . }}-redis-master -p {{ .Values.redis.master.service.ports.redis }} ping
echo "Redis test completed successfully"
{{- end }}
@@ -0,0 +1,21 @@
{{- if .Values.s3.deploy }}
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "trigger-v4.fullname" . }}-test-s3"
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
restartPolicy: Never
containers:
- name: test-s3
image: curlimages/curl:8.14.1
command: ['sh', '-c']
args:
- |
echo "Testing S3 (MinIO) health endpoint..."
curl -f http://{{ include "trigger-v4.fullname" . }}-minio:9000/minio/health/live
echo "S3 test completed successfully"
{{- end }}
@@ -0,0 +1,21 @@
{{- if .Values.supervisor.deploy }}
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "trigger-v4.fullname" . }}-test-supervisor"
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
restartPolicy: Never
containers:
- name: test-supervisor
image: curlimages/curl:8.14.1
command: ['sh', '-c']
args:
- |
echo "Testing Supervisor metrics endpoint..."
curl -f http://{{ include "trigger-v4.fullname" . }}-supervisor:{{ .Values.supervisor.service.ports.metrics }}/metrics
echo "Supervisor test completed successfully"
{{- end }}
@@ -0,0 +1,19 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "trigger-v4.fullname" . }}-test-webapp"
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
restartPolicy: Never
containers:
- name: test-webapp
image: curlimages/curl:8.14.1
command: ['sh', '-c']
args:
- |
echo "Testing webapp health endpoint..."
curl -f http://{{ include "trigger-v4.fullname" . }}-webapp:{{ .Values.webapp.service.port }}/healthcheck
echo "Webapp test completed successfully"
@@ -0,0 +1,67 @@
{{/*
Validation template to ensure external service configurations are provided when deploy: false
This template will fail the Helm deployment if external config is missing for required services
*/}}
{{- if not .Values.postgres.deploy }}
{{- if and (not .Values.postgres.external.databaseUrl) (not .Values.postgres.external.existingSecret) }}
{{- fail "PostgreSQL external configuration is required when postgres.deploy=false. Please provide either postgres.external.databaseUrl or postgres.external.existingSecret" }}
{{- end }}
{{- end }}
{{- if not .Values.redis.deploy }}
{{- if not .Values.redis.external.host }}
{{- fail "Redis external configuration is required when redis.deploy=false. Please provide redis.external.host" }}
{{- end }}
{{- end }}
{{- if not .Values.clickhouse.deploy }}
{{- if or (not .Values.clickhouse.external.host) (not .Values.clickhouse.external.username) }}
{{- fail "ClickHouse external configuration is required when clickhouse.deploy=false. Please provide clickhouse.external.host and clickhouse.external.username" }}
{{- end }}
{{- end }}
{{- if .Values.s3.deploy }}
{{- if and (not .Values.s3.auth.existingSecret) (not .Values.s3.auth.accessKeyId) (not .Values.s3.auth.rootUser) }}
{{- fail "S3 auth credentials are required when s3.deploy=true. Please provide either s3.auth.accessKeyId, s3.auth.existingSecret, or s3.auth.rootUser" }}
{{- end }}
{{- else }}
{{- if not .Values.s3.external.endpoint }}
{{- fail "S3 external configuration is required when s3.deploy=false. Please provide s3.external.endpoint" }}
{{- end }}
{{- if and (not .Values.s3.external.existingSecret) (or (not .Values.s3.external.accessKeyId) (not .Values.s3.external.secretAccessKey)) }}
{{- fail "S3 credentials are required when s3.deploy=false. Please provide either s3.external.existingSecret or both s3.external.accessKeyId and s3.external.secretAccessKey" }}
{{- end }}
{{- end }}
{{- if not .Values.electric.deploy }}
{{- if not .Values.electric.external.url }}
{{- fail "Electric external configuration is required when electric.deploy=false. Please provide electric.external.url" }}
{{- end }}
{{- end }}
{{- if and .Values.s2.deploy .Values.s2.external.endpoint }}
{{- fail "S2 configuration conflict: s2.external.endpoint is set but s2.deploy=true, so the external endpoint would be ignored. Set s2.deploy=false to use an external S2 endpoint, or clear s2.external.endpoint to use the bundled s2-lite." }}
{{- end }}
{{- if not .Values.registry.deploy }}
{{- if or (not .Values.registry.external.host) }}
{{- fail "Registry external configuration is required when registry.deploy=false. Please provide registry.external.host" }}
{{- end }}
{{- end }}
{{/*
This template produces no output but will fail the deployment if validation fails
*/}}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "trigger-v4.fullname" . }}-external-config-validation
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-weight: "-10"
helm.sh/hook-delete-policy: before-hook-creation
data:
validation: "completed"
@@ -0,0 +1,52 @@
{{- if .Values.webapp.ingress.enabled -}}
{{- $fullName := include "trigger-v4.fullname" . -}}
{{- $svcPort := .Values.webapp.service.port -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}-webapp
labels:
{{- $component := "webapp" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
annotations:
{{- include "trigger-v4.webapp.ingress.annotations" . | nindent 4 }}
spec:
{{- if .Values.webapp.ingress.className }}
ingressClassName: {{ .Values.webapp.ingress.className }}
{{- end }}
{{- if .Values.webapp.ingress.tls }}
tls:
{{- range .Values.webapp.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.webapp.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- if .paths }}
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType | default "Prefix" }}
backend:
service:
name: {{ $fullName }}-webapp
port:
number: {{ $svcPort }}
{{- end }}
{{- else }}
- path: /
pathType: Prefix
backend:
service:
name: {{ $fullName }}-webapp
port:
number: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
+494
View File
@@ -0,0 +1,494 @@
{{- if .Values.webapp.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "trigger-v4.webappServiceAccountName" . }}
labels:
{{- $component := "webapp" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
{{- with .Values.webapp.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "trigger-v4.fullname" . }}-webapp-token-syncer
labels:
{{- $component := "webapp" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create", "get", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "trigger-v4.fullname" . }}-webapp-token-syncer
labels:
{{- $component := "webapp" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
subjects:
- kind: ServiceAccount
name: {{ include "trigger-v4.webappServiceAccountName" . }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: Role
name: {{ include "trigger-v4.fullname" . }}-webapp-token-syncer
apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "trigger-v4.fullname" . }}-webapp
labels:
{{- $component := "webapp" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
spec:
replicas: {{ .Values.webapp.replicaCount }}
selector:
matchLabels:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 6 }}
template:
metadata:
annotations:
kubectl.kubernetes.io/default-container: webapp
{{- with .Values.webapp.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 8 }}
spec:
serviceAccountName: {{ include "trigger-v4.webappServiceAccountName" . }}
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
fsGroup: 1000
{{- with .Values.webapp.podSecurityContext }}
{{- toYaml . | nindent 8 }}
{{- end }}
initContainers:
- name: volume-permissions
image: {{ include "trigger-v4.webapp.volumePermissions.image" . }}
imagePullPolicy: {{ .Values.webapp.volumePermissions.image.pullPolicy }}
command: ['sh', '-c', 'mkdir -p /home/node/shared']
securityContext:
runAsUser: 1000
volumeMounts:
- name: shared
mountPath: /home/node/shared
containers:
- name: token-syncer
image: {{ include "trigger-v4.webapp.tokenSyncer.image" . }}
imagePullPolicy: {{ .Values.webapp.tokenSyncer.image.pullPolicy }}
securityContext:
runAsUser: 1000
runAsNonRoot: true
command:
- /bin/bash
- -c
- |
TOKEN_FILE="/home/node/shared/worker_token"
SECRET_NAME="{{ include "trigger-v4.fullname" . }}-worker-token"
NAMESPACE="{{ .Release.Namespace }}"
echo "Token syncer starting..."
echo "Monitoring: $TOKEN_FILE"
echo "Target secret: $SECRET_NAME"
while true; do
if [ -f "$TOKEN_FILE" ]; then
TOKEN=$(cat "$TOKEN_FILE")
if [ ! -z "$TOKEN" ]; then
echo "Token file found, creating/updating secret..."
# Create or update the secret
kubectl create secret generic "$SECRET_NAME" \
--from-literal=token="$TOKEN" \
--namespace="$NAMESPACE" \
--dry-run=client -o yaml | kubectl apply -f -
if [ $? -eq 0 ]; then
echo "Secret successfully created/updated"
# Continue monitoring for updates
sleep 30
else
echo "Failed to create/update secret, retrying in 5s..."
sleep 5
fi
else
echo "Token file exists but is empty, waiting..."
sleep 2
fi
else
echo "Waiting for token file..."
sleep 2
fi
done
volumeMounts:
- name: shared
mountPath: /home/node/shared
- name: webapp
securityContext:
{{- toYaml .Values.webapp.securityContext | nindent 12 }}
image: {{ include "trigger-v4.image" . }}
imagePullPolicy: {{ .Values.webapp.image.pullPolicy }}
command:
- ./scripts/entrypoint.sh
ports:
- name: http
containerPort: {{ .Values.webapp.service.targetPort }}
protocol: TCP
{{- if .Values.webapp.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: /healthcheck
port: http
initialDelaySeconds: {{ .Values.webapp.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.webapp.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.webapp.livenessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.webapp.livenessProbe.failureThreshold }}
successThreshold: {{ .Values.webapp.livenessProbe.successThreshold }}
{{- end }}
{{- if .Values.webapp.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: /healthcheck
port: http
initialDelaySeconds: {{ .Values.webapp.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.webapp.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.webapp.readinessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.webapp.readinessProbe.failureThreshold }}
successThreshold: {{ .Values.webapp.readinessProbe.successThreshold }}
{{- end }}
{{- if .Values.webapp.startupProbe.enabled }}
startupProbe:
httpGet:
path: /healthcheck
port: http
initialDelaySeconds: {{ .Values.webapp.startupProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.webapp.startupProbe.periodSeconds }}
timeoutSeconds: {{ .Values.webapp.startupProbe.timeoutSeconds }}
failureThreshold: {{ .Values.webapp.startupProbe.failureThreshold }}
successThreshold: {{ .Values.webapp.startupProbe.successThreshold }}
{{- end }}
resources:
{{- toYaml .Values.webapp.resources | nindent 12 }}
env:
- name: APP_ORIGIN
value: {{ .Values.webapp.appOrigin | quote }}
- name: LOGIN_ORIGIN
value: {{ .Values.webapp.loginOrigin | quote }}
- name: API_ORIGIN
value: {{ .Values.webapp.apiOrigin | quote }}
- name: ELECTRIC_ORIGIN
value: {{ include "trigger-v4.electric.url" . | quote }}
{{- if include "trigger-v4.s2.enabled" . }}
# Realtime streams v2, backed by S2 (bundled s2-lite or an external endpoint)
- name: REALTIME_STREAMS_DEFAULT_VERSION
value: {{ .Values.s2.defaultStreamVersion | quote }}
- name: REALTIME_STREAMS_S2_ENDPOINT
value: {{ include "trigger-v4.s2.url" . | quote }}
- name: REALTIME_STREAMS_S2_BASIN
value: {{ .Values.s2.basin | quote }}
- name: REALTIME_STREAMS_S2_SKIP_ACCESS_TOKENS
value: {{ .Values.s2.skipAccessTokens | quote }}
{{- if and .Values.s2.external.endpoint .Values.s2.external.existingSecret }}
- name: REALTIME_STREAMS_S2_ACCESS_TOKEN
valueFrom:
secretKeyRef:
name: {{ .Values.s2.external.existingSecret }}
key: {{ .Values.s2.external.existingSecretAccessTokenKey }}
{{- else if .Values.s2.external.accessToken }}
- name: REALTIME_STREAMS_S2_ACCESS_TOKEN
value: {{ .Values.s2.external.accessToken | quote }}
{{- end }}
{{- end }}
{{- if include "trigger-v4.postgres.useSecretUrl" . }}
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.postgres.external.secretName" . }}
key: {{ include "trigger-v4.postgres.external.databaseUrlKey" . }}
- name: DIRECT_URL
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.postgres.external.secretName" . }}
key: {{ include "trigger-v4.postgres.external.directUrlKey" . }}
{{- else }}
- name: DATABASE_URL
value: {{ include "trigger-v4.postgres.connectionString" . | quote }}
- name: DIRECT_URL
value: {{ include "trigger-v4.postgres.directUrl" . | quote }}
{{- end }}
{{- if and (include "trigger-v4.webapp.connectivityCheckEnabled" .) (include "trigger-v4.postgres.host" .) }}
- name: DATABASE_HOST
value: {{ include "trigger-v4.postgres.host" . | quote }}
{{- end }}
- name: REDIS_HOST
value: {{ include "trigger-v4.redis.host" . | quote }}
- name: REDIS_PORT
value: {{ include "trigger-v4.redis.port" . | quote }}
{{- if and .Values.redis.external.host .Values.redis.external.existingSecret }}
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.redis.external.secretName" . }}
key: {{ include "trigger-v4.redis.external.passwordKey" . }}
{{- else if include "trigger-v4.redis.password" . }}
- name: REDIS_PASSWORD
value: {{ include "trigger-v4.redis.password" . | quote }}
{{- end }}
- name: REDIS_TLS_DISABLED
value: {{ include "trigger-v4.redis.tlsDisabled" . | quote }}
- name: APP_LOG_LEVEL
value: {{ .Values.webapp.logLevel | quote }}
- name: DEV_OTEL_EXPORTER_OTLP_ENDPOINT
value: "{{ .Values.webapp.appOrigin }}/otel"
- name: DEPLOY_REGISTRY_HOST
value: {{ include "trigger-v4.registry.host" . | quote }}
- name: DEPLOY_REGISTRY_NAMESPACE
value: {{ .Values.registry.repositoryNamespace | quote }}
- name: OBJECT_STORE_BASE_URL
value: {{ include "trigger-v4.s3.url" . | quote }}
- name: GRACEFUL_SHUTDOWN_TIMEOUT
value: {{ .Values.webapp.gracefulShutdownTimeout | quote }}
{{- if .Values.webapp.bootstrap.enabled }}
- name: TRIGGER_BOOTSTRAP_ENABLED
value: "1"
- name: TRIGGER_BOOTSTRAP_WORKER_GROUP_NAME
value: {{ .Values.webapp.bootstrap.workerGroupName | quote }}
- name: TRIGGER_BOOTSTRAP_WORKER_TOKEN_PATH
value: {{ .Values.webapp.bootstrap.workerTokenPath | quote }}
{{- end }}
{{- if .Values.webapp.limits.taskPayloadOffloadThreshold }}
- name: TASK_PAYLOAD_OFFLOAD_THRESHOLD
value: {{ .Values.webapp.limits.taskPayloadOffloadThreshold | quote }}
{{- end }}
{{- if .Values.webapp.limits.taskPayloadMaximumSize }}
- name: TASK_PAYLOAD_MAXIMUM_SIZE
value: {{ .Values.webapp.limits.taskPayloadMaximumSize | quote }}
{{- end }}
{{- if .Values.webapp.limits.batchTaskPayloadMaximumSize }}
- name: BATCH_TASK_PAYLOAD_MAXIMUM_SIZE
value: {{ .Values.webapp.limits.batchTaskPayloadMaximumSize | quote }}
{{- end }}
{{- if .Values.webapp.limits.taskRunMetadataMaximumSize }}
- name: TASK_RUN_METADATA_MAXIMUM_SIZE
value: {{ .Values.webapp.limits.taskRunMetadataMaximumSize | quote }}
{{- end }}
{{- if .Values.webapp.limits.defaultEnvExecutionConcurrencyLimit }}
- name: DEFAULT_ENV_EXECUTION_CONCURRENCY_LIMIT
value: {{ .Values.webapp.limits.defaultEnvExecutionConcurrencyLimit | quote }}
{{- end }}
{{- if .Values.webapp.limits.defaultOrgExecutionConcurrencyLimit }}
- name: DEFAULT_ORG_EXECUTION_CONCURRENCY_LIMIT
value: {{ .Values.webapp.limits.defaultOrgExecutionConcurrencyLimit | quote }}
{{- end }}
{{- if or .Values.secrets.enabled .Values.secrets.existingSecret }}
- name: SESSION_SECRET
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.secretsName" . }}
key: SESSION_SECRET
- name: MAGIC_LINK_SECRET
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.secretsName" . }}
key: MAGIC_LINK_SECRET
- name: ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.secretsName" . }}
key: ENCRYPTION_KEY
- name: MANAGED_WORKER_SECRET
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.secretsName" . }}
key: MANAGED_WORKER_SECRET
{{- if .Values.s3.deploy }}
{{- if .Values.s3.auth.existingSecret }}
- name: OBJECT_STORE_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.s3.auth.secretName" . }}
key: {{ include "trigger-v4.s3.auth.accessKeyIdKey" . }}
- name: OBJECT_STORE_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.s3.auth.secretName" . }}
key: {{ include "trigger-v4.s3.auth.secretAccessKeyKey" . }}
{{- else }}
- name: OBJECT_STORE_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.secretsName" . }}
key: s3-auth-access-key-id
- name: OBJECT_STORE_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.secretsName" . }}
key: s3-auth-secret-access-key
{{- end }}
{{- else }}
{{- if .Values.s3.external.existingSecret }}
- name: OBJECT_STORE_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.s3.external.secretName" . }}
key: {{ include "trigger-v4.s3.external.accessKeyIdKey" . }}
- name: OBJECT_STORE_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.s3.external.secretName" . }}
key: {{ include "trigger-v4.s3.external.secretAccessKeyKey" . }}
{{- else if .Values.s3.external.accessKeyId }}
- name: OBJECT_STORE_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.secretsName" . }}
key: s3-access-key-id
- name: OBJECT_STORE_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.secretsName" . }}
key: s3-secret-access-key
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.webapp.observability }}
{{- if .Values.webapp.observability.tracing.exporterUrl }}
- name: INTERNAL_OTEL_TRACE_EXPORTER_URL
value: {{ .Values.webapp.observability.tracing.exporterUrl | quote }}
{{- end }}
{{- if .Values.webapp.observability.tracing.exporterAuthHeaders }}
- name: INTERNAL_OTEL_TRACE_EXPORTER_AUTH_HEADERS
value: {{ .Values.webapp.observability.tracing.exporterAuthHeaders | quote }}
{{- end }}
- name: INTERNAL_OTEL_TRACE_LOGGING_ENABLED
value: {{ .Values.webapp.observability.tracing.loggingEnabled | quote }}
- name: INTERNAL_OTEL_TRACE_SAMPLING_RATE
value: {{ .Values.webapp.observability.tracing.samplingRate | quote }}
- name: INTERNAL_OTEL_TRACE_INSTRUMENT_PRISMA_ENABLED
value: {{ .Values.webapp.observability.tracing.instrumentPrismaEnabled | quote }}
- name: INTERNAL_OTEL_TRACE_DISABLED
value: {{ .Values.webapp.observability.tracing.disabled | quote }}
{{- if .Values.webapp.observability.logging.exporterUrl }}
- name: INTERNAL_OTEL_LOG_EXPORTER_URL
value: {{ .Values.webapp.observability.logging.exporterUrl | quote }}
{{- end }}
{{- if .Values.webapp.observability.metrics.exporterUrl }}
- name: INTERNAL_OTEL_METRIC_EXPORTER_URL
value: {{ .Values.webapp.observability.metrics.exporterUrl | quote }}
{{- end }}
{{- if .Values.webapp.observability.metrics.exporterAuthHeaders }}
- name: INTERNAL_OTEL_METRIC_EXPORTER_AUTH_HEADERS
value: {{ .Values.webapp.observability.metrics.exporterAuthHeaders | quote }}
{{- end }}
- name: INTERNAL_OTEL_METRIC_EXPORTER_ENABLED
value: {{ .Values.webapp.observability.metrics.exporterEnabled | quote }}
- name: INTERNAL_OTEL_METRIC_EXPORTER_INTERVAL_MS
value: {{ .Values.webapp.observability.metrics.exporterIntervalMs | quote }}
{{- end }}
{{- if and .Values.clickhouse.external.host .Values.clickhouse.external.existingSecret }}
- name: CLICKHOUSE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "trigger-v4.clickhouse.external.secretName" . }}
key: {{ include "trigger-v4.clickhouse.external.passwordKey" . }}
{{- end }}
- name: CLICKHOUSE_URL
value: {{ include "trigger-v4.clickhouse.url" . | quote }}
- name: CLICKHOUSE_LOG_LEVEL
value: {{ .Values.webapp.clickhouse.logLevel | quote }}
- name: RUN_REPLICATION_ENABLED
value: "1"
- name: RUN_REPLICATION_CLICKHOUSE_URL
value: {{ include "trigger-v4.clickhouse.replication.url" . | quote }}
- name: RUN_REPLICATION_LOG_LEVEL
value: {{ .Values.webapp.runReplication.logLevel | quote }}
{{- if not .Values.telemetry.enabled }}
- name: TRIGGER_TELEMETRY_DISABLED
value: "1"
{{- end }}
{{- with .Values.webapp.extraEnvVars }}
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- name: shared
mountPath: /home/node/shared
{{- with .Values.webapp.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
volumes:
- name: shared
{{- if .Values.persistence.shared.enabled }}
persistentVolumeClaim:
claimName: {{ include "trigger-v4.fullname" . }}-shared
{{- else }}
emptyDir: {}
{{- end }}
{{- with .Values.webapp.extraVolumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.webapp.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.webapp.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.webapp.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.webapp.topologySpreadConstraints }}
topologySpreadConstraints:
{{- tpl (toYaml .) $ | nindent 8 }}
{{- end }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "trigger-v4.fullname" . }}-webapp
labels:
{{- $component := "webapp" }}
{{- include "trigger-v4.componentLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
spec:
type: {{ .Values.webapp.service.type }}
ports:
- port: {{ .Values.webapp.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "trigger-v4.componentSelectorLabels" (dict "Chart" .Chart "Release" .Release "Values" .Values "component" $component) | nindent 4 }}
---
{{- if .Values.persistence.shared.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "trigger-v4.fullname" . }}-shared
{{- if .Values.persistence.shared.retain }}
annotations:
"helm.sh/resource-policy": keep
{{- end }}
labels:
{{- include "trigger-v4.labels" . | nindent 4 }}
spec:
accessModes:
- {{ .Values.persistence.shared.accessMode }}
resources:
requests:
storage: {{ .Values.persistence.shared.size }}
{{- $storageClass := .Values.persistence.shared.storageClass | default .Values.global.storageClass }}
{{- if $storageClass }}
storageClassName: {{ $storageClass | quote }}
{{- end }}
{{- end }}
@@ -0,0 +1,201 @@
# Production values example for Trigger.dev v4 Helm chart
# Copy this file and customize for your production deployment
# REQUIRED: Generate your own secrets using: openssl rand -hex 16
secrets:
sessionSecret: "YOUR_32_CHAR_HEX_SECRET_HERE_001"
magicLinkSecret: "YOUR_32_CHAR_HEX_SECRET_HERE_002"
encryptionKey: "YOUR_32_CHAR_HEX_SECRET_HERE_003"
managedWorkerSecret: "YOUR_32_CHAR_HEX_SECRET_HERE_004"
# Production webapp configuration
webapp:
# Origin configuration
appOrigin: "https://trigger.example.com"
loginOrigin: "https://trigger.example.com"
apiOrigin: "https://trigger.example.com"
# Production ingress
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
hosts:
- host: trigger.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: trigger-tls
hosts:
- trigger.example.com
resources:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 1000m
memory: 2Gi
# Production PostgreSQL (or use external)
postgres:
primary:
persistence:
enabled: true
size: 100Gi
storageClass: "fast-ssd"
resources:
limits:
cpu: 1000m
memory: 2Gi
requests:
cpu: 500m
memory: 1Gi
# Production Redis (or use external)
redis:
master:
persistence:
enabled: true
size: 20Gi
storageClass: "fast-ssd"
resources:
limits:
cpu: 500m
memory: 1Gi
requests:
cpu: 250m
memory: 512Mi
# Production ClickHouse
clickhouse:
# Set to true to enable TLS/secure connections in production
secure: true
persistence:
enabled: true
size: 100Gi
storageClass: "fast-ssd"
# ClickHouse can be very resource intensive, so we recommend setting limits and requests accordingly
# Note: not doing this can cause OOM crashes which will cause issues across many different
resources:
limits:
cpu: 4000m
memory: 16Gi
requests:
cpu: 2000m
memory: 8Gi
# Production S3-compatible object storage
s3:
auth:
rootUser: "admin"
rootPassword: "your-strong-s3-password"
# Webapp credentials for S3 access (can be different from root)
accessKeyId: "your-access-key"
secretAccessKey: "your-secret-key"
persistence:
enabled: true
size: 500Gi
storageClass: "standard"
# Production Registry
registry:
repositoryNamespace: "mycompany" # Docker repository namespace for deployed images, will be part of the image ref
auth:
username: "registry-user"
password: "your-strong-registry-password"
persistence:
enabled: true
size: 100Gi
storageClass: "standard"
# Production ingress
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
hosts:
- host: registry.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: registry-tls
hosts:
- registry.example.com
# Production Supervisor (Kubernetes worker orchestrator)
supervisor:
resources:
limits:
cpu: 500m
memory: 1Gi
requests:
cpu: 250m
memory: 512Mi
# Example: Use external PostgreSQL instead
# postgres:
# deploy: false
# connection:
# sslMode: "require" # Use 'require' or 'verify-full' for production
# external:
# # Database URL configuration - simplified approach using URLs
# databaseUrl: "postgresql://trigger_user:your-db-password@your-postgres-host.rds.amazonaws.com:5432/trigger?schema=public&sslmode=require"
# directUrl: "" # Optional: Direct URL for migrations (if not set, databaseUrl will be used)
# #
# # Optional: Connectivity check configuration during webapp startup
# connectivityCheck:
# host: "your-postgres-host.rds.amazonaws.com:5432"
# #
# # Secure credential management (recommended for production)
# # existingSecret: "postgres-credentials" # Name of existing secret containing DATABASE_URL
# # secretKeys:
# # databaseUrlKey: "postgres-database-url" # Key in existing secret
# # directUrlKey: "postgres-direct-url" # Key in existing secret (optional)
# Example: Use external Redis instead
# redis:
# deploy: false
# external:
# host: "your-redis-cluster.cache.amazonaws.com"
# port: 6379
# password: "your-redis-password" # Optional - ignored if existingSecret is set
# tls:
# enabled: true # Set to true for Redis instances requiring TLS (e.g., AWS ElastiCache)
# #
# # Secure credential management (recommended for production)
# # existingSecret: "redis-credentials" # Name of existing secret containing password
# # existingSecretPasswordKey: "redis-password" # Key in existing secret containing password
# Example: Use external ClickHouse instead
# clickhouse:
# deploy: false
# external:
# host: "your-clickhouse-host.cloud.provider.com"
# httpPort: 8443 # Use 8443 for HTTPS
# nativePort: 9440 # Use 9440 for secure native connections
# username: "trigger_user"
# password: "your-clickhouse-password" # Optional - ignored if existingSecret is set
# secure: true # Use true for TLS/secure connections
# #
# # Secure credential management (recommended for production)
# # existingSecret: "clickhouse-credentials" # Name of existing secret containing password
# # existingSecretKey: "clickhouse-password" # Key in existing secret containing password
# Example: Use external S3-compatible storage instead
# s3:
# deploy: false
# external:
# endpoint: "https://s3.amazonaws.com" # or your S3-compatible endpoint
# accessKeyId: "your-access-key"
# secretAccessKey: "your-secret-key"
# #
# # Secure credential management (recommended for production)
# # existingSecret: "s3-credentials" # Name of existing secret containing S3 credentials
# # existingSecretAccessKeyIdKey: "access-key-id" # Key in existing secret containing access key ID
# # existingSecretSecretAccessKeyKey: "secret-access-key" # Key in existing secret containing secret access key
+922
View File
@@ -0,0 +1,922 @@
global:
imageRegistry: ""
imagePullSecrets: []
storageClass: ""
security:
# Required when using bitnami legacy images
allowInsecureImages: true
nameOverride: ""
fullnameOverride: ""
# Secrets configuration
# IMPORTANT: The default values below are for TESTING ONLY and should NOT be used in production
# For production deployments:
# 1. Generate new secrets using: openssl rand -hex 16
# 2. Override these values in your values.yaml or use external secret management
# 3. Each secret must be exactly 32 hex characters (16 bytes)
secrets:
# Enable/disable creation of secrets
# Set to false to use external secret management (Vault, Infisical, External Secrets, etc.)
# When disabled, you can also use extraEnvVars and podAnnotations for secret injection
enabled: true
# Name of existing secret to use instead of creating one
# If empty, a secret will be created with the values below
# The secret must contain the following keys:
# - SESSION_SECRET
# - MAGIC_LINK_SECRET
# - ENCRYPTION_KEY
# - MANAGED_WORKER_SECRET
existingSecret: ""
# Session secret for user authentication (32 hex chars)
sessionSecret: "2818143646516f6fffd707b36f334bbb"
# Magic link secret for passwordless login (32 hex chars)
magicLinkSecret: "44da78b7bbb0dfe709cf38931d25dcdd"
# Encryption key for sensitive data (32 hex chars)
encryptionKey: "f686147ab967943ebbe9ed3b496e465a"
# Worker secret for managed worker authentication (32 hex chars)
managedWorkerSecret: "447c29678f9eaf289e9c4b70d3dd8a7f"
# Object store credentials moved to s3.auth and s3.external section
# Webapp configuration
webapp:
image:
registry: ghcr.io
repository: triggerdotdev/trigger.dev
tag: "" # Defaults to Chart.appVersion when empty
pullPolicy: IfNotPresent
# Init container for shared directory setup
volumePermissions:
image:
registry: docker.io
repository: busybox
tag: "1.35"
pullPolicy: IfNotPresent
# Sidecar for token syncing
tokenSyncer:
image:
registry: docker.io
repository: bitnamilegacy/kubectl
tag: "1.28"
pullPolicy: IfNotPresent
# Origin configuration
appOrigin: "http://localhost:3040"
loginOrigin: "http://localhost:3040"
apiOrigin: "http://localhost:3040"
replicaCount: 1
service:
type: ClusterIP
port: 3030
targetPort: 3000
podAnnotations: {}
# podSecurityContext:
# fsGroup: 1000
# securityContext:
# runAsNonRoot: true
# runAsUser: 1000
nodeSelector: {}
tolerations: []
affinity: {}
# Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template
topologySpreadConstraints: []
logLevel: "info"
gracefulShutdownTimeout: 1000
# Bootstrap configuration
bootstrap:
enabled: true
workerGroupName: "bootstrap"
workerTokenPath: "/home/node/shared/worker_token"
# Limits
limits:
taskPayloadOffloadThreshold: 524288 # 512KB
taskPayloadMaximumSize: 3145728 # 3MB
batchTaskPayloadMaximumSize: 1000000 # 1MB
taskRunMetadataMaximumSize: 262144 # 256KB
defaultEnvExecutionConcurrencyLimit: 100
defaultOrgExecutionConcurrencyLimit: 300
# Resources
resources:
{}
# Example resource configuration:
# limits:
# cpu: 1000m
# memory: 2Gi
# requests:
# cpu: 500m
# memory: 1Gi
# Connectivity check configuration
connectivityCheck:
postgres: true # Set to false to disable DATABASE_HOST env var (overrides postgres.external.connectivityCheck)
# Extra environment variables for webapp
extraEnvVars:
[]
# - name: CUSTOM_VAR
# value: "custom-value"
# - name: SECRET_VAR
# valueFrom:
# secretKeyRef:
# name: my-secret
# key: secret-key
#
# Example: PostgreSQL SSL with custom CA certificate
# - name: NODE_EXTRA_CA_CERTS
# value: "/etc/ssl/certs/postgres-ca.crt"
# Extra volumes for the webapp pod
extraVolumes:
[]
# - name: config-volume
# configMap:
# name: my-config
# - name: secret-volume
# secret:
# secretName: my-secret
#
# Example: PostgreSQL SSL CA certificate volume
# - name: postgres-ca-cert
# secret:
# secretName: postgres-ca-secret
# items:
# - key: ca.crt
# path: postgres-ca.crt
# Extra volume mounts for the webapp container
extraVolumeMounts:
[]
# - name: config-volume
# mountPath: /etc/config
# readOnly: true
# - name: secret-volume
# mountPath: /etc/secrets
# readOnly: true
#
# Example: PostgreSQL SSL CA certificate mount
# - name: postgres-ca-cert
# mountPath: /etc/ssl/certs
# readOnly: true
# ServiceMonitor for Prometheus monitoring
serviceMonitor:
enabled: false
interval: "30s"
path: "/metrics"
labels: {}
basicAuth: {}
# Health probe configuration
livenessProbe:
enabled: true
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 5
successThreshold: 1
readinessProbe:
enabled: true
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 5
successThreshold: 1
startupProbe:
enabled: false
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 60
successThreshold: 1
clickhouse:
logLevel: "info" # one of: log, error, warn, info, debug
runReplication:
logLevel: "info" # one of: log, error, warn, info, debug
# ServiceAccount configuration
serviceAccount:
create: true
# Name of the ServiceAccount to use. Required when create is false - otherwise
# the token-syncer RoleBinding would bind to the namespace's "default" SA.
name: ""
# Annotations to add to the ServiceAccount (e.g. eks.amazonaws.com/role-arn for IRSA)
annotations: {}
# Observability configuration (OTel)
observability:
tracing:
exporterUrl: ""
exporterAuthHeaders: ""
loggingEnabled: "0"
samplingRate: "20"
instrumentPrismaEnabled: "0"
disabled: "0"
logging:
exporterUrl: ""
# Log auth headers are currently set to tracing.exporterAuthHeaders
metrics:
exporterUrl: ""
exporterAuthHeaders: ""
exporterEnabled: "0"
exporterIntervalMs: 30000
# Webapp ingress configuration
ingress:
enabled: false
className: "traefik"
# Custom annotations for the ingress resource
# Note: The following annotation keys are reserved and will be automatically set:
# - cert-manager.io/cluster-issuer (when certManager.enabled is true)
# - external-dns.alpha.kubernetes.io/hostname (when externalDns.enabled is true)
# - external-dns.alpha.kubernetes.io/ttl (when externalDns.enabled is true)
annotations: {}
certManager:
enabled: false
clusterIssuer: "letsencrypt-prod"
externalDns:
enabled: false
hostname: ""
ttl: "300"
hosts:
- host: trigger.local
paths:
- path: /
pathType: Prefix
tls:
[]
# - secretName: trigger-tls
# hosts:
# - trigger.local
# Supervisor configuration
supervisor:
image:
registry: ghcr.io
repository: triggerdotdev/supervisor
tag: "" # Defaults to Chart.appVersion when empty
pullPolicy: IfNotPresent
podAnnotations: {}
# podSecurityContext:
# fsGroup: 1000
# securityContext:
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
ports:
workload: 3000
metrics: 9088
resources: {}
config:
kubernetes:
forceEnabled: true
namespace: "" # Default: uses release namespace
workerNodetypeLabel: "" # When set, runs will only be scheduled on nodes with "nodetype=<label>"
ephemeralStorageSizeLimit: "" # Default: 10Gi
ephemeralStorageSizeRequest: "" # Default: 2Gi´
podCleaner:
enabled: true
batchSize: 100
intervalMs: 10000 # 10 seconds´
failedPodHandler:
enabled: true
reconnectIntervalMs: 1000
workloadApi:
enabled: true
protocol: "http"
portExternal: 3000
portInternal: 3000
hostInternal: "0.0.0.0"
dequeue:
enabled: true
intervalMs: 250
maxRunCount: 100
idleIntervalMs: 500
runner:
heartbeatIntervalSeconds: 30
snapshotPollIntervalSeconds: 30
metrics:
enabled: true
collectDefaults: true
host: "0.0.0.0"
port: 9088
debug: false
# RBAC configuration
serviceAccount:
create: true
name: ""
annotations: {}
rbac:
create: true
# Namespace-scoped permissions for pod management
role:
name: ""
# Extra environment variables for Supervisor
extraEnvVars:
[]
# - name: CUSTOM_VAR
# value: "custom-value"
# ServiceMonitor for Prometheus monitoring
serviceMonitor:
enabled: false
interval: "30s"
path: "/metrics"
labels: {}
basicAuth: {}
# Health probe configuration
livenessProbe:
enabled: true
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
readinessProbe:
enabled: true
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
startupProbe:
enabled: false
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 60
successThreshold: 1
# Bootstrap configuration
# When enabled: reads token from shared file, otherwise uses workerToken config
bootstrap:
enabled: true
workerTokenPath: "/home/node/shared/worker_token"
workerToken:
# Direct value (not recommended for production)
value: ""
# Secret reference
secret:
name: ""
key: ""
nodeSelector: {}
tolerations: []
affinity: {}
# PostgreSQL configuration
# Subchart: https://github.com/bitnami/charts/tree/main/bitnami/postgresql
postgres:
deploy: true
image:
# Use bitnami legacy repo
repository: bitnamilegacy/postgresql
# image: docker.io/bitnamilegacy/postgresql:17.5.0-debian-12-r12
# Bitnami PostgreSQL chart configuration (when deploy: true)
auth:
enablePostgresUser: true
postgresPassword: "postgres"
username: "postgres"
password: "postgres"
database: "main"
primary:
persistence:
enabled: true
size: 10Gi
resourcesPreset: "small"
resources: {}
configuration: |
listen_addresses = '*'
wal_level = logical
# Custom connection settings
connection:
schema: "public"
sslMode: "disable" # Use "require" or "verify-full" for production with custom CA
# External PostgreSQL connection (when deploy: false)
external:
# Database URL configuration - simplified approach using URLs instead of individual parameters
databaseUrl: "" # Full PostgreSQL connection URL (e.g., postgresql://user:pass@host:port/db?schema=public&sslmode=prefer)
directUrl: "" # Optional: Direct URL for migrations (if not set, databaseUrl will be used)
#
# Optional: Connectivity check configuration during webapp startup
connectivityCheck:
host: "" # Optional: hostname:port for wait-for-it script (e.g., "postgres.example.com:5432")
#
# Secure credential management
existingSecret: "" # Name of existing secret containing DATABASE_URL
secretKeys:
databaseUrlKey: "postgres-database-url" # Key in existing secret containing complete DATABASE_URL
directUrlKey: "postgres-direct-url" # Key in existing secret containing direct URL (optional)
#
# Example: For SSL connections with custom CA (e.g., AWS RDS):
# 1. Set connection.sslMode to "require" or "verify-full"
# 2. Create a secret with your CA certificate:
# kubectl create secret generic postgres-ca-secret --from-file=ca.crt=/path/to/rds-ca-cert.pem
# 3. Configure extraVolumes, extraVolumeMounts, and extraEnvVars (see webapp section above)
# Redis configuration
# Subchart: https://github.com/bitnami/charts/tree/main/bitnami/redis
redis:
deploy: true
image:
# Use bitnami legacy repo
repository: bitnamilegacy/redis
# image: docker.io/bitnamilegacy/redis:8.0.2-debian-12-r4
# Bitnami Redis chart configuration (when deploy: true)
auth:
enabled: false
# Single-node configuration (disable replica)
architecture: standalone
master:
persistence:
enabled: true
size: 5Gi
resources: {}
# External Redis connection (when deploy: false)
external:
host: ""
port: 6379
password: "" # Optional - ignored if existingSecret is set
tls:
enabled: false # Set to true for Redis instances requiring TLS (e.g., AWS ElastiCache)
#
# Secure credential management
existingSecret: "" # Name of existing secret containing password
existingSecretPasswordKey: "redis-password" # Key in existing secret containing password
# Electric configuration
electric:
deploy: true
image:
registry: docker.io
repository: electricsql/electric
tag: "1.2.4"
pullPolicy: IfNotPresent
config:
insecure: true
usageReporting: false
podAnnotations: {}
# podSecurityContext:
# fsGroup: 1000
# securityContext:
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
port: 3000
targetPort: 3000
resources: {}
# Health probe configuration
livenessProbe:
enabled: true
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
successThreshold: 1
readinessProbe:
enabled: true
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
successThreshold: 1
startupProbe:
enabled: false
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 60
successThreshold: 1
# External Electric connection (when deploy: false)
external:
url: "" # For example: "http://electric:3000"
# Extra environment variables for Electric
extraEnvVars:
[]
# - name: CUSTOM_VAR
# value: "custom-value"
# S2 (realtime streams v2)
# s2-lite is the open-source, self-hostable S2 server (https://s2.dev). It backs
# realtime streams v2, which power AI-agent token streaming and run streams. When
# enabled, the webapp defaults to v2; set `defaultStreamVersion: v1` to fall back
# to the Redis-backed v1 streams. Disable entirely with `deploy: false` and no
# external endpoint.
s2:
deploy: true
image:
registry: ghcr.io
repository: s2-streamstore/s2
tag: "latest"
# Pinning by digest is strongly recommended for reproducible deployments
digest: "sha256:d6ded5ca7dd619fa7c946f06e39a98f9c95c6883c8bb884e5eaa129f232c920c"
pullPolicy: IfNotPresent
# Which stream protocol version the webapp defaults to when a client doesn't pin one.
# Only takes effect while S2 is enabled (deploy: true or an external endpoint set);
# with S2 fully disabled the webapp always falls back to v1.
defaultStreamVersion: "v2"
# Basin that holds realtime streams. Created on startup from the init config.
# Must be at least 8 characters.
basin: "trigger-realtime"
# s2-lite needs no authentication; skip minting per-stream access tokens.
# Set to false when pointing at a hosted S2 that requires a token.
skipAccessTokens: true
podAnnotations: {}
# s2-lite is distroless and runs as uid 65532. fsGroup makes the persistent
# volume writable by that user without running the container as root.
podSecurityContext:
fsGroup: 65532
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
service:
type: ClusterIP
port: 80
# High container port so s2-lite can bind as the non-root image user (65532)
# without needing CAP_NET_BIND_SERVICE for a privileged port
targetPort: 8080
# Persistent storage for the SlateDB-backed stream data
persistence:
enabled: true
size: 5Gi
accessMode: ReadWriteOnce
storageClass: ""
retain: false
resources: {}
# Health probe configuration (distroless image → TCP probes, no shell/HTTP tooling)
livenessProbe:
enabled: true
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
successThreshold: 1
readinessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
successThreshold: 1
# External S2 connection (when deploy: false). Point at a hosted S2 basin, e.g.
# "https://<basin>.b.aws.s2.dev/v1", set skipAccessTokens: false above, and
# supply an access token either inline or via an existing secret.
external:
endpoint: ""
accessToken: ""
existingSecret: ""
existingSecretAccessTokenKey: "access-token"
# ClickHouse configuration
# Subchart: https://github.com/bitnami/charts/tree/main/bitnami/clickhouse
clickhouse:
deploy: true
image:
# Use bitnami legacy repo
repository: bitnamilegacy/clickhouse
# image: docker.io/bitnamilegacy/clickhouse:25.7.5-debian-12-r0
# TLS/Secure connection configuration
secure: false # Set to true to use HTTPS and secure connections
# Bitnami ClickHouse chart configuration (when deploy: true)
auth:
username: "default"
password: "password"
# Single-node configuration (disable clustering for dev/test)
keeper:
enabled: false
shards: 1
replicaCount: 1
persistence:
enabled: true
size: 10Gi
## ClickHouse resource requests and limits
## ref: http://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
## @param resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).
## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15
resourcesPreset: "xlarge"
resources: {}
# External ClickHouse connection (when deploy: false)
external:
host: ""
httpPort: 8123
nativePort: 9000
username: ""
password: "" # Optional - ignored if existingSecret is set
secure: false # Set to true for external secure connections
#
# Secure credential management
existingSecret: "" # Name of existing secret containing password
existingSecretKey: "clickhouse-password" # Key in existing secret containing password
# ClickHouse configuration override
# These defaults are based on official recommendations for systems with <16GB RAM:
# https://clickhouse.com/docs/operations/tips
configdFiles:
override.xml: |
<clickhouse>
<logger>
<level>warning</level>
</logger>
<!-- Official recommendations for systems with <16GB RAM -->
<mark_cache_size>524288000</mark_cache_size> <!-- 500MB -->
<concurrent_threads_soft_limit_num>1</concurrent_threads_soft_limit_num>
<profiles>
<default>
<max_block_size>8192</max_block_size>
<max_download_threads>1</max_download_threads>
<input_format_parallel_parsing>0</input_format_parallel_parsing>
<output_format_parallel_formatting>0</output_format_parallel_formatting>
</default>
</profiles>
</clickhouse>
# S3-compatible object storage configuration
# Subchart: https://github.com/bitnami/charts/tree/main/bitnami/minio
s3:
# Set to false to use external S3-compatible storage
# Set to true to deploy internal MinIO (default)
deploy: true
image:
# Use bitnami legacy repo
repository: bitnamilegacy/minio
# image: docker.io/bitnamilegacy/minio:2025.6.13-debian-12-r0
# MinIO Console (Browser UI) configuration
console:
image:
repository: bitnamilegacy/minio-object-browser
# image: docker.io/bitnamilegacy/minio-object-browser:2025.1.10-debian-12-r1
# Bitnami MinIO chart configuration (when deploy: true)
# MinIO provides S3-compatible storage when deployed internally
auth:
rootUser: "admin"
rootPassword: "very-safe-password"
# Webapp credentials for S3 access (defaults to root credentials if not specified)
accessKeyId: "" # Defaults to rootUser if empty
secretAccessKey: "" # Defaults to rootPassword if empty
# Existing secret support for webapp credentials
existingSecret: "" # If set, accessKeyId/secretAccessKey will be ignored
accessKeyIdSecretKey: "access-key-id" # Key in existingSecret containing access key ID
secretAccessKeySecretKey: "secret-access-key" # Key in existingSecret containing secret access key
# The required "packets" bucket is created by default.
defaultBuckets: "packets"
persistence:
enabled: true
size: 10Gi
resources: {}
# External S3 connection (when deploy: false)
external:
endpoint: "" # e.g., "https://s3.amazonaws.com" or "https://your-minio.com:9000"
accessKeyId: "admin" # Default for internal MinIO - change for production
secretAccessKey: "very-safe-password" # Default for internal MinIO - change for production
#
# Secure credential management
existingSecret: "" # Name of existing secret containing S3 credentials
existingSecretAccessKeyIdKey: "access-key-id" # Key in existing secret containing access key ID
existingSecretSecretAccessKeyKey: "secret-access-key" # Key in existing secret containing secret access key
#
# Multi-provider support (optional)
# To use multiple S3-compatible providers (e.g., S3 + R2), set defaultProtocol and configure named providers
# via extraEnvVars. For example:
# - OBJECT_STORE_DEFAULT_PROTOCOL=s3 # Protocol to use for new uploads
# - OBJECT_STORE_S3_BASE_URL=https://s3.amazonaws.com
# - OBJECT_STORE_S3_ACCESS_KEY_ID=...
# - OBJECT_STORE_S3_SECRET_ACCESS_KEY=...
# - OBJECT_STORE_R2_BASE_URL=https://...r2.cloudflarestorage.com
# - OBJECT_STORE_R2_ACCESS_KEY_ID=...
# - OBJECT_STORE_R2_SECRET_ACCESS_KEY=...
# See documentation for migration guide: https://trigger.dev/docs/self-hosting/env/webapp
# Docker Registry configuration
registry:
# EXPERIMENTAL - requires ingress/TLS setup or additional cluster configuration. Configure `external` details instead.
deploy: false
# This will be used when deploy: true
host: "registry.example.com"
# Docker repository namespace for deployed images, will be part of the image ref
repositoryNamespace: "trigger"
image:
registry: docker.io
repository: registry
tag: "2"
pullPolicy: IfNotPresent
auth:
enabled: true
username: "registry-user"
password: "very-secure-indeed"
# External Registry connection (when deploy: false)
external:
host: "localhost:5001"
auth:
enabled: false
username: ""
password: ""
podAnnotations: {}
# podSecurityContext:
# fsGroup: 1000
# securityContext:
# runAsNonRoot: true
# runAsUser: 1000
# Persistence configuration (Bitnami-style)
persistence:
enabled: true
# Name to assign the volume
volumeName: "data"
# Name of an existing PVC to use
existingClaim: ""
# The path the volume will be mounted at
mountPath: "/var/lib/registry"
# The subdirectory of the volume to mount to
subPath: ""
# PVC Storage Class for Registry data volume
storageClass: ""
# PVC Access Mode for Registry volume
accessModes:
- "ReadWriteOnce"
# PVC Storage Request for Registry volume
size: 10Gi
# Annotations for the PVC
annotations: {}
# Labels for the PVC
labels: {}
# Selector to match an existing Persistent Volume
selector: {}
# Custom PVC data source
dataSource: {}
service:
type: ClusterIP
port: 5000
targetPort: 5000
resources: {}
# Health probe configuration
livenessProbe:
enabled: true
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
successThreshold: 1
readinessProbe:
enabled: true
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
successThreshold: 1
startupProbe:
enabled: false
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 60
successThreshold: 1
# Extra environment variables for Registry
extraEnvVars:
[]
# - name: CUSTOM_VAR
# value: "custom-value"
# Registry ingress configuration
ingress:
enabled: false
className: "traefik"
# Custom annotations for the ingress resource
# Note: The following annotation keys are reserved and will be automatically set:
# - cert-manager.io/cluster-issuer (when certManager.enabled is true)
# - external-dns.alpha.kubernetes.io/hostname (when externalDns.enabled is true)
# - external-dns.alpha.kubernetes.io/ttl (when externalDns.enabled is true)
annotations: {}
certManager:
enabled: false
clusterIssuer: "letsencrypt-prod"
externalDns:
enabled: false
hostname: ""
ttl: "300"
hosts:
- host: registry.local
paths:
- path: /
pathType: Prefix
tls:
[]
# - secretName: registry-tls
# hosts:
# - registry.local
# Shared persistent volumes
persistence:
# This is used for the worker token file
shared:
enabled: true
size: 5Mi
accessMode: ReadWriteOnce
# accessMode: ReadWriteMany # Use for cross-node deployment (requires compatible storage class)
storageClass: ""
retain: true # Prevents deletion on uninstall
# Telemetry configuration
telemetry:
enabled: true
# Extra Kubernetes manifests
# This allows you to add additional Kubernetes resources that will be deployed with the chart
extraManifests:
[]
# - apiVersion: v1
# kind: ConfigMap
# metadata:
# name: my-config
# data:
# key: value
# - apiVersion: apps/v1
# kind: Deployment
# metadata:
# name: my-app
# spec:
# replicas: 1
# selector:
# matchLabels:
# app: my-app
# template:
# metadata:
# labels:
# app: my-app
# spec:
# containers:
# - name: my-container
# image: nginx:latest
+75
View File
@@ -0,0 +1,75 @@
#!/bin/sh
set -o errexit
cluster_name="${1:-trigger-test}"
# 1. Create registry container unless it already exists
reg_name='kind-registry'
reg_port='5001'
if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then
docker run \
-d --restart=always -p "127.0.0.1:${reg_port}:5000" --network bridge --name "${reg_name}" \
registry:2
fi
# 2. Create kind cluster with containerd registry config dir enabled
#
# NOTE: the containerd config patch is not necessary with images from kind v0.27.0+
# It may enable some older images to work similarly.
# If you're only supporting newer relases, you can just use `kind create cluster` here.
#
# See:
# https://github.com/kubernetes-sigs/kind/issues/2875
# https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration
# See: https://github.com/containerd/containerd/blob/main/docs/hosts.md
cat <<EOF | kind create cluster --name "${cluster_name}" --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
labels:
nodetype: v4-worker
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
EOF
# 3. Add the registry config to the nodes
#
# This is necessary because localhost resolves to loopback addresses that are
# network-namespace local.
# In other words: localhost in the container is not localhost on the host.
#
# We want a consistent name that works from both ends, so we tell containerd to
# alias localhost:${reg_port} to the registry container when pulling images
REGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}"
for node in $(kind get nodes --name ${cluster_name}); do
docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
[host."http://${reg_name}:5000"]
EOF
done
# 4. Connect the registry to the cluster network if not already connected
# This allows kind to bootstrap the network but ensures they're on the same network
if [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}' "${reg_name}")" = 'null' ]; then
docker network connect "kind" "${reg_name}"
fi
# 5. Document the local registry
# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: local-registry-hosting
namespace: kube-public
data:
localRegistryHosting.v1: |
host: "localhost:${reg_port}"
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
EOF
echo "Kind cluster ${cluster_name} with local registry is ready!"
echo "You can now push images to localhost:${reg_port}"