Update documentation and example values

This commit is contained in:
Gitea Actions
2025-12-22 10:50:53 +00:00
parent 23c1e615b9
commit 2c0e27c488
5 changed files with 2569 additions and 2 deletions

408
README.md
View File

@@ -1,3 +1,407 @@
# Helm-Charts
# Flow Helm Chart
public helm chart repo from Entit AB
A Helm chart for deploying the Flow workflow engine platform to Kubernetes.
## Overview
Flow is a distributed workflow automation platform consisting of:
- **Core Services**: Workflow Engine, Activity Registry, Definition Store, Workflow Logging, Connection Store, Tenant Registry
- **Frontend**: Blazor WebAssembly web application
- **Activity Services**: 23+ activity implementations for various integrations (HTTP, SQL, Azure, AWS, etc.)
- **Infrastructure**: RabbitMQ for messaging, PostgreSQL/SQL Server for persistence
## Prerequisites
- Kubernetes 1.25+
- Helm 3.8+
- PV provisioner (if using built-in PostgreSQL/RabbitMQ)
## Quick Start
### Install from Gitea Helm Repository
The Flow Helm chart is published to the Gitea Package Registry at `https://git.kn.entit.eu`.
```bash
# Add the Helm repository (requires authentication for private repos)
helm repo add entit-flow https://git.kn.entit.eu/api/packages/EntitAB/helm \
--username YOUR_GITEA_USERNAME \
--password YOUR_GITEA_TOKEN
# Update repository cache
helm repo update
# Search for available versions
helm search repo entit-flow/flow --versions
# Install the chart
helm install flow entit-flow/flow \
--namespace flow \
--create-namespace \
-f values.yaml
```
### Install from Local Source
```bash
# Add Helm Dependencies
cd helm/flow
helm dependency update
# Install for Development
helm install flow ./helm/flow -f ./helm/flow/values-dev.yaml
# Install for Production
helm install flow ./helm/flow \
-f ./helm/flow/values-prod.yaml \
--set global.azureAd.tenantId=YOUR_TENANT_ID \
--set global.azureAd.clientId=YOUR_CLIENT_ID \
--set global.azureAd.clientSecret=YOUR_CLIENT_SECRET
```
## Helm Repository Setup
### Using in Kubernetes (from Gitea Registry)
After the chart is published to Gitea, you can install it in any Kubernetes cluster:
```bash
# 1. Add the Gitea Helm repository
helm repo add entit-flow https://git.kn.entit.eu/api/packages/EntitAB/helm \
--username $GITEA_USER \
--password $GITEA_TOKEN
# 2. Update repositories
helm repo update
# 3. Install the chart (development)
helm install flow entit-flow/flow \
--namespace flow \
--create-namespace \
-f values-dev.yaml
# 4. Install the chart (production)
helm install flow entit-flow/flow \
--namespace flow \
--create-namespace \
-f values-prod.yaml \
--set global.azureAd.tenantId=YOUR_TENANT_ID \
--set global.azureAd.clientId=YOUR_CLIENT_ID
```
### Using with ArgoCD
Create an ArgoCD Application that references the Gitea Helm repository:
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: flow
namespace: argocd
spec:
project: default
source:
repoURL: https://git.kn.entit.eu/api/packages/EntitAB/helm
chart: flow
targetRevision: 0.1.0
helm:
valueFiles:
- values-prod.yaml
parameters:
- name: global.azureAd.tenantId
value: YOUR_TENANT_ID
- name: global.azureAd.clientId
value: YOUR_CLIENT_ID
destination:
server: https://kubernetes.default.svc
namespace: flow
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
---
# Repository credentials secret for ArgoCD
apiVersion: v1
kind: Secret
metadata:
name: gitea-helm-repo
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
type: helm
url: https://git.kn.entit.eu/api/packages/EntitAB/helm
username: YOUR_GITEA_USER
password: YOUR_GITEA_TOKEN
```
### Using with Flux CD
```yaml
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
name: entit-flow
namespace: flux-system
spec:
interval: 1h
url: https://git.kn.entit.eu/api/packages/EntitAB/helm
secretRef:
name: gitea-helm-auth
---
apiVersion: v1
kind: Secret
metadata:
name: gitea-helm-auth
namespace: flux-system
stringData:
username: YOUR_GITEA_USER
password: YOUR_GITEA_TOKEN
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: flow
namespace: flow
spec:
interval: 5m
chart:
spec:
chart: flow
version: "0.1.0"
sourceRef:
kind: HelmRepository
name: entit-flow
namespace: flux-system
valuesFrom:
- kind: ConfigMap
name: flow-values
valuesKey: values.yaml
```
### Publishing Charts (CI/CD)
The chart is automatically published to Gitea when changes are pushed to the `main` branch. The CI pipeline:
1. Lints and validates the chart
2. Runs unit tests
3. Packages the chart
4. Pushes to Gitea Package Registry at `https://git.kn.entit.eu/api/packages/EntitAB/helm`
To publish manually:
```bash
# Set credentials
export GITEA_USER=your-username
export GITEA_TOKEN=your-token
# Package and push
make push-gitea
```
**Required GitHub Secrets for CI:**
- `GITEA_USER` - Gitea username
- `GITEA_TOKEN` - Gitea personal access token with `write:package` scope
## Configuration
### Global Configuration
| Parameter | Description | Default |
|-----------|-------------|---------|
| `global.imageRegistry` | Container registry for all images | `""` |
| `global.imagePullSecrets` | Image pull secrets | `[]` |
| `global.azureAd.enabled` | Enable Azure AD authentication | `true` |
| `global.azureAd.tenantId` | Azure AD tenant ID | `""` |
| `global.azureAd.clientId` | Azure AD application client ID | `""` |
| `global.database.provider` | Database provider (Postgres/SqlServer) | `Postgres` |
| `global.rabbitmq.host` | RabbitMQ host | `{{ .Release.Name }}-rabbitmq` |
### Core Services
Each core service supports the following configuration:
| Parameter | Description | Default |
|-----------|-------------|---------|
| `<service>.enabled` | Enable the service | `true` |
| `<service>.replicaCount` | Number of replicas | `1` |
| `<service>.image.repository` | Image repository | varies |
| `<service>.image.tag` | Image tag | `""` (uses appVersion) |
| `<service>.resources` | CPU/Memory resources | varies |
| `<service>.autoscaling.enabled` | Enable HPA | `false` |
| `<service>.ingress.enabled` | Enable ingress | `false` |
### Activity Services
Activity services can be enabled/disabled individually:
```yaml
httpRequestActivity:
enabled: true
replicaCount: 2
sqlActivity:
enabled: true
# Disable activities not needed
awsS3Activity:
enabled: false
```
### Database Configuration
#### Using Built-in PostgreSQL
```yaml
postgresql:
enabled: true
auth:
username: flow
password: your-password
database: flow
```
#### Using External PostgreSQL
```yaml
postgresql:
enabled: false
global:
database:
provider: Postgres
postgres:
host: your-postgres-host.postgres.database.azure.com
port: 5432
database: flow
username: flow
existingSecret: your-db-secret
existingSecretKey: password
```
#### Using SQL Server
```yaml
postgresql:
enabled: false
global:
database:
provider: SqlServer
sqlServer:
connectionString: "Server=your-server;Database=flow;User Id=flow;Password=xxx;"
```
### RabbitMQ Configuration
#### Using Built-in RabbitMQ
```yaml
rabbitmq:
enabled: true
auth:
username: flow
password: your-password
```
#### Using External RabbitMQ
```yaml
rabbitmq:
enabled: false
global:
rabbitmq:
host: your-rabbitmq-host
username: flow
existingSecret: rabbitmq-secret
existingSecretKey: password
```
## Ingress Configuration
### NGINX Ingress with TLS
```yaml
frontendWeb:
ingress:
enabled: true
className: nginx
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: flow.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: flow-tls
hosts:
- flow.example.com
```
## Security
### Pod Security
```yaml
podSecurityContext:
fsGroup: 1000
runAsNonRoot: true
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
```
### Network Policies
Enable network policies for production:
```yaml
networkPolicy:
enabled: true
```
## Upgrading
```bash
helm upgrade flow ./helm/flow -f values-prod.yaml
```
## Uninstalling
```bash
helm uninstall flow
```
**Note**: This will not delete PVCs. To completely remove data:
```bash
kubectl delete pvc -l app.kubernetes.io/instance=flow
```
## Building Docker Images
Each service has a Dockerfile. Build all images:
```bash
# Build all services
for service in WorkflowEngine ActivityRegistry DefinitionStore WorkflowLogging ConnectionStore TenantRegistry; do
docker build -t niblo/flow-${service}:latest -f $service/Dockerfile .
done
# Push to Docker Hub
for service in WorkflowEngine ActivityRegistry DefinitionStore WorkflowLogging ConnectionStore TenantRegistry; do
docker push niblo/flow-${service}:latest
done

161
examples/values-dev.yaml Normal file
View File

@@ -0,0 +1,161 @@
# Development environment values
# Use with: helm install flow ./helm/flow -f ./helm/flow/values-dev.yaml
#
# PREREQUISITES:
# Deploy RabbitMQ and PostgreSQL separately before installing this chart.
# Example using Helm:
# helm install rabbitmq oci://registry-1.docker.io/bitnamicharts/rabbitmq -n flow
# helm install postgresql oci://registry-1.docker.io/bitnamicharts/postgresql -n flow
#
# Or use your own deployments/operators.
global:
imageRegistry: "cr.kn.entit.eu"
imagePullSecrets:
- flow-registry-credentials
azureAd:
enabled: false # Disable auth for local development
database:
provider: "Postgres"
postgres:
host: "postgresql" # Update to match your PostgreSQL service name
database: "flow"
username: "flow"
password: "devpassword123"
# Or use existing secret:
# existingSecret: "postgresql-credentials"
# existingSecretKey: "password"
rabbitmq:
host: "rabbitmq" # Update to match your RabbitMQ service name
username: "flow"
password: "devpassword123"
# Or use existing secret:
# existingSecret: "rabbitmq-credentials"
# existingSecretKey: "password"
# Core services - minimal replicas for dev
workflowEngine:
replicaCount: 1
resources:
limits:
cpu: 250m
memory: 256Mi
requests:
cpu: 50m
memory: 128Mi
activityRegistry:
replicaCount: 1
definitionStore:
replicaCount: 1
workflowLogging:
replicaCount: 1
connectionStore:
replicaCount: 1
tenantRegistry:
replicaCount: 1
frontendWeb:
replicaCount: 1
ingress:
enabled: true
hosts:
- host: flow.local
paths:
- path: /
pathType: Prefix
# Enable only essential activities for dev
httpRequestActivity:
enabled: true
replicaCount: 1
sqlActivity:
enabled: true
replicaCount: 1
# Disable non-essential activities
redisActivity:
enabled: false
blobStorageActivity:
enabled: false
queueActivity:
enabled: false
cosmosDbActivity:
enabled: false
mongoDbActivity:
enabled: false
emailActivity:
enabled: false
slackActivity:
enabled: false
teamsActivity:
enabled: false
twilioActivity:
enabled: false
ftpActivity:
enabled: false
graphqlActivity:
enabled: false
soapActivity:
enabled: false
pdfActivity:
enabled: false
csvActivity:
enabled: false
excelActivity:
enabled: false
oauthActivity:
enabled: false
keyVaultActivity:
enabled: false
eventHubActivity:
enabled: false
eventGridActivity:
enabled: false
awsS3Activity:
enabled: false
awsSqsActivity:
enabled: false
# External infrastructure - not deployed by this chart
rabbitmq:
enabled: false
postgresql:
enabled: false
redis:
enabled: false
# Relaxed security for development
securityContext:
runAsNonRoot: false
readOnlyRootFilesystem: false

284
examples/values-prod.yaml Normal file
View File

@@ -0,0 +1,284 @@
# Production environment values
# Use with: helm install flow ./helm/flow -f ./helm/flow/values-prod.yaml
global:
imageRegistry: "cr.kn.entit.eu"
imagePullSecrets:
- flow-registry-credentials
azureAd:
enabled: true
instance: "https://login.microsoftonline.com/"
domain: "your-domain.com"
tenantId: "" # Set via --set or external secret
clientId: "" # Set via --set or external secret
clientSecret: "" # Set via --set or external secret
scopes: "access_as_user"
database:
provider: "Postgres"
postgres:
host: "your-postgres-host.postgres.database.azure.com"
port: 5432
database: "flow_prod"
username: "flow@your-postgres-host"
existingSecret: "flow-db-secret"
existingSecretKey: "postgres-password"
rabbitmq:
host: "your-rabbitmq-host"
username: "flow"
existingSecret: "flow-rabbitmq-secret"
existingSecretKey: "rabbitmq-password"
# Core services - production replicas with autoscaling
workflowEngine:
replicaCount: 3
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 70
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 250m
memory: 512Mi
ingress:
enabled: true
className: nginx
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: api.flow.your-domain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: flow-api-tls
hosts:
- api.flow.your-domain.com
activityRegistry:
replicaCount: 2
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 5
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
definitionStore:
replicaCount: 2
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 5
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
workflowLogging:
replicaCount: 2
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 5
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
connectionStore:
replicaCount: 2
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
tenantRegistry:
replicaCount: 2
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
frontendWeb:
replicaCount: 2
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 5
ingress:
enabled: true
className: nginx
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: flow.your-domain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: flow-frontend-tls
hosts:
- flow.your-domain.com
# Activity services - production resources
activities:
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
httpRequestActivity:
enabled: true
replicaCount: 2
sqlActivity:
enabled: true
replicaCount: 2
redisActivity:
enabled: true
replicaCount: 2
blobStorageActivity:
enabled: true
replicaCount: 2
queueActivity:
enabled: true
replicaCount: 2
cosmosDbActivity:
enabled: true
replicaCount: 2
mongoDbActivity:
enabled: true
replicaCount: 1
emailActivity:
enabled: true
replicaCount: 2
slackActivity:
enabled: true
replicaCount: 1
teamsActivity:
enabled: true
replicaCount: 1
twilioActivity:
enabled: true
replicaCount: 1
ftpActivity:
enabled: true
replicaCount: 1
graphqlActivity:
enabled: true
replicaCount: 1
soapActivity:
enabled: true
replicaCount: 1
pdfActivity:
enabled: true
replicaCount: 1
csvActivity:
enabled: true
replicaCount: 1
excelActivity:
enabled: true
replicaCount: 1
oauthActivity:
enabled: true
replicaCount: 1
keyVaultActivity:
enabled: true
replicaCount: 1
eventHubActivity:
enabled: true
replicaCount: 2
eventGridActivity:
enabled: true
replicaCount: 1
awsS3Activity:
enabled: true
replicaCount: 1
awsSqsActivity:
enabled: true
replicaCount: 1
# External infrastructure in production (managed services)
rabbitmq:
enabled: false # Use Azure Service Bus or managed RabbitMQ
postgresql:
enabled: false # Use Azure Database for PostgreSQL
redis:
enabled: false # Use Azure Cache for Redis if needed
# Production security
podSecurityContext:
fsGroup: 1000
runAsNonRoot: true
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
seccompProfile:
type: RuntimeDefault
# Network policies for production
networkPolicy:
enabled: true
# Pod Disruption Budgets
podDisruptionBudget:
enabled: true
minAvailable: 1

316
examples/values.schema.json Normal file
View File

@@ -0,0 +1,316 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"global": {
"type": "object",
"properties": {
"imageRegistry": {
"type": "string"
},
"imagePullSecrets": {
"type": "array",
"items": {
"type": "string"
}
},
"azureAd": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"instance": {
"type": "string"
},
"domain": {
"type": "string"
},
"tenantId": {
"type": "string"
},
"clientId": {
"type": "string"
},
"clientSecret": {
"type": "string"
},
"scopes": {
"type": "string"
}
}
},
"database": {
"type": "object",
"properties": {
"provider": {
"type": "string",
"enum": ["Postgres", "SqlServer"]
},
"postgres": {
"type": "object",
"properties": {
"host": {
"type": "string"
},
"port": {
"type": "integer",
"minimum": 1,
"maximum": 65535
},
"database": {
"type": "string"
},
"username": {
"type": "string"
},
"password": {
"type": "string"
},
"existingSecret": {
"type": "string"
},
"existingSecretKey": {
"type": "string"
}
}
},
"sqlServer": {
"type": "object",
"properties": {
"connectionString": {
"type": "string"
}
}
}
}
},
"rabbitmq": {
"type": "object",
"properties": {
"host": {
"type": "string"
},
"username": {
"type": "string"
},
"password": {
"type": "string"
},
"existingSecret": {
"type": "string"
},
"existingSecretKey": {
"type": "string"
},
"prefetch": {
"type": "integer",
"minimum": 1
},
"activityExchange": {
"type": "string"
},
"completedExchange": {
"type": "string"
},
"workflowEventsExchange": {
"type": "string"
}
}
}
}
},
"workflowEngine": {
"$ref": "#/definitions/service"
},
"activityRegistry": {
"$ref": "#/definitions/service"
},
"definitionStore": {
"$ref": "#/definitions/service"
},
"workflowLogging": {
"$ref": "#/definitions/service"
},
"connectionStore": {
"$ref": "#/definitions/service"
},
"tenantRegistry": {
"$ref": "#/definitions/service"
},
"frontendWeb": {
"$ref": "#/definitions/service"
}
},
"definitions": {
"service": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"replicaCount": {
"type": "integer",
"minimum": 0
},
"image": {
"type": "object",
"properties": {
"repository": {
"type": "string"
},
"tag": {
"type": "string"
},
"pullPolicy": {
"type": "string",
"enum": ["Always", "IfNotPresent", "Never"]
}
}
},
"service": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["ClusterIP", "NodePort", "LoadBalancer"]
},
"port": {
"type": "integer",
"minimum": 1,
"maximum": 65535
}
}
},
"ingress": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"className": {
"type": "string"
},
"annotations": {
"type": "object"
},
"hosts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"host": {
"type": "string"
},
"paths": {
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string"
},
"pathType": {
"type": "string",
"enum": ["Prefix", "Exact", "ImplementationSpecific"]
}
}
}
}
}
}
},
"tls": {
"type": "array",
"items": {
"type": "object",
"properties": {
"secretName": {
"type": "string"
},
"hosts": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
},
"resources": {
"type": "object",
"properties": {
"limits": {
"type": "object",
"properties": {
"cpu": {
"type": "string"
},
"memory": {
"type": "string"
}
}
},
"requests": {
"type": "object",
"properties": {
"cpu": {
"type": "string"
},
"memory": {
"type": "string"
}
}
}
}
},
"autoscaling": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"minReplicas": {
"type": "integer",
"minimum": 1
},
"maxReplicas": {
"type": "integer",
"minimum": 1
},
"targetCPUUtilizationPercentage": {
"type": "integer",
"minimum": 1,
"maximum": 100
},
"targetMemoryUtilizationPercentage": {
"type": "integer",
"minimum": 1,
"maximum": 100
}
}
},
"nodeSelector": {
"type": "object"
},
"tolerations": {
"type": "array"
},
"affinity": {
"type": "object"
},
"extraEnv": {
"type": "array"
},
"extraVolumeMounts": {
"type": "array"
},
"extraVolumes": {
"type": "array"
}
}
}
}
}

1402
examples/values.yaml Normal file

File diff suppressed because it is too large Load Diff