feat(temporal): install Temporal
This commit is contained in:
1
justfile
1
justfile
@@ -39,6 +39,7 @@ mod qdrant
|
|||||||
mod querybook
|
mod querybook
|
||||||
mod security
|
mod security
|
||||||
mod superset
|
mod superset
|
||||||
|
mod temporal
|
||||||
mod trino
|
mod trino
|
||||||
mod utils
|
mod utils
|
||||||
mod vault
|
mod vault
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ k3sup = "0.13.10"
|
|||||||
kubelogin = "1.34.0"
|
kubelogin = "1.34.0"
|
||||||
node = "22.18.0"
|
node = "22.18.0"
|
||||||
python = "3.12.11"
|
python = "3.12.11"
|
||||||
telepresence = "2.25.0"
|
telepresence = "2.25.1"
|
||||||
trivy = "0.67.2"
|
trivy = "0.67.2"
|
||||||
uv = "0.8.7"
|
uv = "0.8.7"
|
||||||
vault = "1.20.2"
|
vault = "1.20.2"
|
||||||
|
|||||||
1
temporal/.gitignore
vendored
Normal file
1
temporal/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
temporal-values.yaml
|
||||||
401
temporal/README.md
Normal file
401
temporal/README.md
Normal file
@@ -0,0 +1,401 @@
|
|||||||
|
# Temporal
|
||||||
|
|
||||||
|
Durable workflow execution platform for building reliable distributed applications:
|
||||||
|
|
||||||
|
- **Durable Execution**: Workflows survive process and infrastructure failures
|
||||||
|
- **Language Support**: SDKs for Go, Java, Python, TypeScript, .NET, PHP
|
||||||
|
- **Visibility**: Query and observe workflow state via Web UI and APIs
|
||||||
|
- **Scalability**: Horizontally scalable architecture
|
||||||
|
- **Multi-tenancy**: Namespace-based isolation for workflows
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Kubernetes cluster (k3s)
|
||||||
|
- PostgreSQL cluster (CloudNativePG)
|
||||||
|
- Keycloak installed and configured
|
||||||
|
- Vault for secrets management
|
||||||
|
- External Secrets Operator (optional, for Vault integration)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just temporal::install
|
||||||
|
```
|
||||||
|
|
||||||
|
You will be prompted for:
|
||||||
|
|
||||||
|
- **Temporal host (FQDN)**: e.g., `temporal.example.com`
|
||||||
|
- **Keycloak host (FQDN)**: e.g., `auth.example.com`
|
||||||
|
- **Enable Prometheus monitoring**: If kube-prometheus-stack is installed
|
||||||
|
|
||||||
|
### What Gets Installed
|
||||||
|
|
||||||
|
- Temporal Server (frontend, history, matching, worker services)
|
||||||
|
- Temporal Web UI with Keycloak OIDC authentication
|
||||||
|
- Temporal Admin Tools for cluster management
|
||||||
|
- PostgreSQL databases (`temporal`, `temporal_visibility`)
|
||||||
|
- Keycloak OAuth client (confidential client)
|
||||||
|
- Vault secrets (if External Secrets Operator is available)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Environment variables (set in `.env.local` or override):
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
| -------- | ------- | ----------- |
|
||||||
|
| `TEMPORAL_NAMESPACE` | `temporal` | Kubernetes namespace |
|
||||||
|
| `TEMPORAL_CHART_VERSION` | `0.52.0` | Helm chart version |
|
||||||
|
| `TEMPORAL_HOST` | (prompt) | External hostname (FQDN) |
|
||||||
|
| `TEMPORAL_OIDC_CLIENT_ID` | `temporal` | Keycloak client ID |
|
||||||
|
| `KEYCLOAK_HOST` | (prompt) | Keycloak hostname (FQDN) |
|
||||||
|
| `KEYCLOAK_REALM` | `buunstack` | Keycloak realm |
|
||||||
|
| `MONITORING_ENABLED` | (prompt) | Enable Prometheus ServiceMonitor |
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```plain
|
||||||
|
External Users
|
||||||
|
|
|
||||||
|
Cloudflare Tunnel (HTTPS)
|
||||||
|
|
|
||||||
|
Traefik Ingress (HTTPS)
|
||||||
|
|
|
||||||
|
Temporal Web UI (HTTP inside cluster)
|
||||||
|
|-- OAuth --> Keycloak (authentication)
|
||||||
|
|
|
||||||
|
Temporal Server
|
||||||
|
|-- Frontend Service (gRPC :7233)
|
||||||
|
| |-- Client connections
|
||||||
|
| |-- Workflow/Activity APIs
|
||||||
|
|
|
||||||
|
|-- History Service
|
||||||
|
| |-- Workflow state management
|
||||||
|
| |-- Event sourcing
|
||||||
|
|
|
||||||
|
|-- Matching Service
|
||||||
|
| |-- Task queue management
|
||||||
|
| |-- Worker polling
|
||||||
|
|
|
||||||
|
|-- Worker Service
|
||||||
|
| |-- System workflows
|
||||||
|
| |-- Archival
|
||||||
|
|
|
||||||
|
PostgreSQL (temporal, temporal_visibility)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Components**:
|
||||||
|
|
||||||
|
- **Frontend**: Entry point for all client requests (gRPC API)
|
||||||
|
- **History**: Maintains workflow execution history and state
|
||||||
|
- **Matching**: Routes tasks to appropriate workers
|
||||||
|
- **Worker**: Executes internal system workflows
|
||||||
|
- **Web UI**: Browser-based workflow monitoring and management
|
||||||
|
- **Admin Tools**: CLI tools for cluster administration
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Access Web UI
|
||||||
|
|
||||||
|
1. Navigate to `https://your-temporal-host/`
|
||||||
|
2. Authenticate via Keycloak SSO
|
||||||
|
3. Select a namespace to view workflows
|
||||||
|
|
||||||
|
### Temporal CLI Setup (Local Development)
|
||||||
|
|
||||||
|
The Temporal gRPC endpoint is only accessible within the cluster network. Use [Telepresence](https://www.telepresence.io/) to connect from your local machine.
|
||||||
|
|
||||||
|
#### Step 1: Connect to the Cluster
|
||||||
|
|
||||||
|
```bash
|
||||||
|
telepresence connect
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 2: Configure Temporal CLI
|
||||||
|
|
||||||
|
Set environment variables (add to `.bashrc`, `.zshrc`, or use direnv):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export TEMPORAL_ADDRESS="temporal-frontend.temporal:7233"
|
||||||
|
export TEMPORAL_NAMESPACE="default"
|
||||||
|
```
|
||||||
|
|
||||||
|
Or create a named environment for multiple clusters:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Configure named environment
|
||||||
|
temporal env set --env buun -k address -v temporal-frontend.temporal:7233
|
||||||
|
temporal env set --env buun -k namespace -v default
|
||||||
|
|
||||||
|
# Use with commands
|
||||||
|
temporal workflow list --env buun
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 3: Verify Connection
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check telepresence status
|
||||||
|
telepresence status
|
||||||
|
|
||||||
|
# Test Temporal connection
|
||||||
|
temporal operator namespace list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### CLI Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List workflows
|
||||||
|
temporal workflow list
|
||||||
|
|
||||||
|
# Describe a workflow
|
||||||
|
temporal workflow describe --workflow-id my-workflow-id
|
||||||
|
|
||||||
|
# Query workflow state
|
||||||
|
temporal workflow query --workflow-id my-workflow-id --type my-query
|
||||||
|
|
||||||
|
# Signal a workflow
|
||||||
|
temporal workflow signal --workflow-id my-workflow-id --name my-signal
|
||||||
|
|
||||||
|
# Terminate a workflow
|
||||||
|
temporal workflow terminate --workflow-id my-workflow-id --reason "manual termination"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create a Temporal Namespace
|
||||||
|
|
||||||
|
Before running workflows, create a namespace:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just temporal::create-temporal-namespace default
|
||||||
|
```
|
||||||
|
|
||||||
|
With custom retention period:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just temporal::create-temporal-namespace myapp 7d
|
||||||
|
```
|
||||||
|
|
||||||
|
### List Temporal Namespaces
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just temporal::list-temporal-namespaces
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cluster Health Check
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just temporal::cluster-info
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connect Workers
|
||||||
|
|
||||||
|
Workers connect to the Temporal Frontend service. From within the cluster:
|
||||||
|
|
||||||
|
```text
|
||||||
|
temporal-frontend.temporal:7233
|
||||||
|
```
|
||||||
|
|
||||||
|
Example Python worker:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from temporalio.client import Client
|
||||||
|
from temporalio.worker import Worker
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
client = await Client.connect("temporal-frontend.temporal:7233")
|
||||||
|
|
||||||
|
worker = Worker(
|
||||||
|
client,
|
||||||
|
task_queue="my-task-queue",
|
||||||
|
workflows=[MyWorkflow],
|
||||||
|
activities=[my_activity],
|
||||||
|
)
|
||||||
|
await worker.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
Example Go worker:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"go.temporal.io/sdk/client"
|
||||||
|
"go.temporal.io/sdk/worker"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c, _ := client.Dial(client.Options{
|
||||||
|
HostPort: "temporal-frontend.temporal:7233",
|
||||||
|
})
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
w := worker.New(c, "my-task-queue", worker.Options{})
|
||||||
|
w.RegisterWorkflow(MyWorkflow)
|
||||||
|
w.RegisterActivity(MyActivity)
|
||||||
|
w.Run(worker.InterruptCh())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
### Web UI (OIDC)
|
||||||
|
|
||||||
|
- Users authenticate via Keycloak
|
||||||
|
- Standard OIDC flow with Authorization Code grant
|
||||||
|
- Configured via environment variables in the Web UI deployment
|
||||||
|
|
||||||
|
### gRPC API
|
||||||
|
|
||||||
|
- By default, no authentication is required for gRPC connections within the cluster
|
||||||
|
- For production, configure mTLS or JWT-based authorization
|
||||||
|
|
||||||
|
## Management
|
||||||
|
|
||||||
|
### Upgrade Temporal
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just temporal::upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uninstall
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just temporal::uninstall
|
||||||
|
```
|
||||||
|
|
||||||
|
This removes:
|
||||||
|
|
||||||
|
- Helm release and all Kubernetes resources
|
||||||
|
- Namespace
|
||||||
|
- Keycloak client
|
||||||
|
|
||||||
|
**Note**: The following resources are NOT deleted:
|
||||||
|
|
||||||
|
- PostgreSQL databases (`temporal`, `temporal_visibility`)
|
||||||
|
- Vault secrets
|
||||||
|
|
||||||
|
### Full Cleanup
|
||||||
|
|
||||||
|
To remove everything including databases and Vault secrets:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just temporal::uninstall true
|
||||||
|
```
|
||||||
|
|
||||||
|
Or manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just temporal::delete-postgres-user-and-db
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Check Pod Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get pods -n temporal
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected pods:
|
||||||
|
|
||||||
|
- `temporal-frontend-*` - Frontend service
|
||||||
|
- `temporal-history-*` - History service
|
||||||
|
- `temporal-matching-*` - Matching service
|
||||||
|
- `temporal-worker-*` - Worker service
|
||||||
|
- `temporal-web-*` - Web UI
|
||||||
|
- `temporal-admintools-*` - Admin tools
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Frontend logs
|
||||||
|
kubectl logs -n temporal deployment/temporal-frontend --tail=100
|
||||||
|
|
||||||
|
# History logs
|
||||||
|
kubectl logs -n temporal deployment/temporal-history --tail=100
|
||||||
|
|
||||||
|
# Web UI logs
|
||||||
|
kubectl logs -n temporal deployment/temporal-web --tail=100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Connection Issues
|
||||||
|
|
||||||
|
Check PostgreSQL connectivity:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -n temporal deployment/temporal-admintools -- \
|
||||||
|
psql -h postgres-cluster-rw.postgres -U temporal -d temporal -c "SELECT 1"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schema Issues
|
||||||
|
|
||||||
|
If schema initialization fails, check the schema job:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl logs -n temporal -l app.kubernetes.io/component=schema --all-containers
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service Discovery Issues
|
||||||
|
|
||||||
|
Verify services are running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get svc -n temporal
|
||||||
|
```
|
||||||
|
|
||||||
|
Test frontend connectivity from admin tools:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -n temporal deployment/temporal-admintools -- \
|
||||||
|
tctl cluster health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Web UI Login Issues
|
||||||
|
|
||||||
|
Verify Keycloak client configuration:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just keycloak::get-client buunstack temporal
|
||||||
|
```
|
||||||
|
|
||||||
|
Check Web UI environment variables:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get deployment temporal-web -n temporal -o jsonpath='{.spec.template.spec.containers[0].env}' | jq
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Files
|
||||||
|
|
||||||
|
| File | Description |
|
||||||
|
| ---- | ----------- |
|
||||||
|
| `temporal-values.gomplate.yaml` | Helm values template |
|
||||||
|
| `postgres-external-secret.gomplate.yaml` | PostgreSQL credentials ExternalSecret |
|
||||||
|
| `keycloak-auth-external-secret.gomplate.yaml` | Keycloak OIDC credentials ExternalSecret |
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
- **Pod Security Standards**: Namespace configured with **baseline** enforcement
|
||||||
|
- **Server Security**: Temporal server components run with restricted-compliant security contexts
|
||||||
|
|
||||||
|
### Why Not Restricted?
|
||||||
|
|
||||||
|
The namespace cannot use `restricted` Pod Security Standards due to the Temporal Web UI image (`temporalio/ui`):
|
||||||
|
|
||||||
|
- The image writes configuration files to `./config/docker.yaml` at startup
|
||||||
|
- The container's filesystem is owned by root (UID 0)
|
||||||
|
- When running as non-root user (UID 1000), the container cannot write to these paths
|
||||||
|
- Error: `unable to create open ./config/docker.yaml: permission denied`
|
||||||
|
|
||||||
|
The Temporal server components (frontend, history, matching, worker) **do** meet `restricted` requirements and run with full security hardening. Only the Web UI component requires `baseline`.
|
||||||
|
|
||||||
|
### Server Security Context
|
||||||
|
|
||||||
|
Temporal server components (frontend, history, matching, worker) run with:
|
||||||
|
|
||||||
|
- `runAsNonRoot: true`
|
||||||
|
- `runAsUser: 1000`
|
||||||
|
- `allowPrivilegeEscalation: false`
|
||||||
|
- `seccompProfile.type: RuntimeDefault`
|
||||||
|
- `capabilities.drop: [ALL]`
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Temporal Documentation](https://docs.temporal.io/)
|
||||||
|
- [Temporal GitHub](https://github.com/temporalio/temporal)
|
||||||
|
- [Temporal Helm Charts](https://github.com/temporalio/helm-charts)
|
||||||
412
temporal/justfile
Normal file
412
temporal/justfile
Normal file
@@ -0,0 +1,412 @@
|
|||||||
|
set fallback := true
|
||||||
|
|
||||||
|
export TEMPORAL_NAMESPACE := env("TEMPORAL_NAMESPACE", "temporal")
|
||||||
|
export TEMPORAL_CHART_VERSION := env("TEMPORAL_CHART_VERSION", "0.52.0")
|
||||||
|
export TEMPORAL_HOST := env("TEMPORAL_HOST", "")
|
||||||
|
export TEMPORAL_OIDC_CLIENT_ID := env("TEMPORAL_OIDC_CLIENT_ID", "temporal")
|
||||||
|
export EXTERNAL_SECRETS_NAMESPACE := env("EXTERNAL_SECRETS_NAMESPACE", "external-secrets")
|
||||||
|
export PROMETHEUS_NAMESPACE := env("PROMETHEUS_NAMESPACE", "monitoring")
|
||||||
|
export MONITORING_ENABLED := env("MONITORING_ENABLED", "")
|
||||||
|
export KEYCLOAK_REALM := env("KEYCLOAK_REALM", "buunstack")
|
||||||
|
export KEYCLOAK_HOST := env("KEYCLOAK_HOST", "")
|
||||||
|
export K8S_VAULT_NAMESPACE := env("K8S_VAULT_NAMESPACE", "vault")
|
||||||
|
|
||||||
|
[private]
|
||||||
|
default:
|
||||||
|
@just --list --unsorted --list-submodules
|
||||||
|
|
||||||
|
# Add Helm repository
|
||||||
|
add-helm-repo:
|
||||||
|
helm repo add temporal https://go.temporal.io/helm-charts
|
||||||
|
helm repo update temporal
|
||||||
|
|
||||||
|
# Remove Helm repository
|
||||||
|
remove-helm-repo:
|
||||||
|
helm repo remove temporal
|
||||||
|
|
||||||
|
# Create Temporal namespace
|
||||||
|
create-namespace:
|
||||||
|
kubectl get namespace ${TEMPORAL_NAMESPACE} &>/dev/null || \
|
||||||
|
kubectl create namespace ${TEMPORAL_NAMESPACE}
|
||||||
|
|
||||||
|
# Delete Temporal namespace
|
||||||
|
delete-namespace:
|
||||||
|
kubectl delete namespace ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
|
||||||
|
# Create PostgreSQL user and databases for Temporal
|
||||||
|
create-postgres-user-and-db:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
if just postgres::user-exists temporal &>/dev/null; then
|
||||||
|
echo "PostgreSQL user 'temporal' already exists"
|
||||||
|
else
|
||||||
|
echo "Creating PostgreSQL user and databases..."
|
||||||
|
PG_PASSWORD=$(just utils::random-password)
|
||||||
|
just postgres::create-user-and-db temporal temporal "${PG_PASSWORD}"
|
||||||
|
just postgres::create-db temporal_visibility
|
||||||
|
just postgres::grant temporal_visibility temporal
|
||||||
|
just vault::put temporal/db username=temporal password="${PG_PASSWORD}"
|
||||||
|
echo "PostgreSQL user and databases created."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Delete PostgreSQL user and databases
|
||||||
|
delete-postgres-user-and-db:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
if gum confirm "Delete PostgreSQL user and databases for Temporal?"; then
|
||||||
|
just postgres::delete-db temporal || true
|
||||||
|
just postgres::delete-db temporal_visibility || true
|
||||||
|
just postgres::delete-user temporal || true
|
||||||
|
just vault::delete temporal/db || true
|
||||||
|
echo "PostgreSQL user and databases deleted."
|
||||||
|
else
|
||||||
|
echo "Cancelled."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create Postgres secret
|
||||||
|
create-postgres-secret:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
if kubectl get secret temporal-postgres-auth -n ${TEMPORAL_NAMESPACE} &>/dev/null; then
|
||||||
|
echo "Postgres auth secret already exists"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if helm status external-secrets -n ${EXTERNAL_SECRETS_NAMESPACE} &>/dev/null; then
|
||||||
|
echo "External Secrets Operator detected. Creating ExternalSecret..."
|
||||||
|
kubectl delete externalsecret temporal-postgres-auth -n ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
gomplate -f postgres-external-secret.gomplate.yaml | kubectl apply -f -
|
||||||
|
echo "Waiting for ExternalSecret to sync..."
|
||||||
|
kubectl wait --for=condition=Ready externalsecret/temporal-postgres-auth \
|
||||||
|
-n ${TEMPORAL_NAMESPACE} --timeout=60s
|
||||||
|
else
|
||||||
|
echo "Creating Kubernetes Secret directly..."
|
||||||
|
PG_USERNAME=$(just vault::get temporal/db username)
|
||||||
|
PG_PASSWORD=$(just vault::get temporal/db password)
|
||||||
|
kubectl create secret generic temporal-postgres-auth \
|
||||||
|
--from-literal=password="${PG_PASSWORD}" \
|
||||||
|
-n ${TEMPORAL_NAMESPACE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Delete Postgres secret
|
||||||
|
delete-postgres-secret:
|
||||||
|
kubectl delete externalsecret temporal-postgres-auth -n ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
kubectl delete secret temporal-postgres-auth -n ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
|
||||||
|
# Create Keycloak client for Temporal Web UI
|
||||||
|
create-keycloak-client:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
while [ -z "${TEMPORAL_HOST}" ]; do
|
||||||
|
TEMPORAL_HOST=$(
|
||||||
|
gum input --prompt="Temporal host (FQDN): " --width=100 \
|
||||||
|
--placeholder="e.g., temporal.example.com"
|
||||||
|
)
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Creating Keycloak client for Temporal..."
|
||||||
|
|
||||||
|
just keycloak::delete-client ${KEYCLOAK_REALM} ${TEMPORAL_OIDC_CLIENT_ID} || true
|
||||||
|
|
||||||
|
CLIENT_SECRET=$(just utils::random-password)
|
||||||
|
|
||||||
|
just keycloak::create-client \
|
||||||
|
realm=${KEYCLOAK_REALM} \
|
||||||
|
client_id=${TEMPORAL_OIDC_CLIENT_ID} \
|
||||||
|
redirect_url="https://${TEMPORAL_HOST}/*" \
|
||||||
|
client_secret="${CLIENT_SECRET}"
|
||||||
|
|
||||||
|
kubectl delete secret temporal-oauth-temp -n ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
kubectl create secret generic temporal-oauth-temp -n ${TEMPORAL_NAMESPACE} \
|
||||||
|
--from-literal=client_id="${TEMPORAL_OIDC_CLIENT_ID}" \
|
||||||
|
--from-literal=client_secret="${CLIENT_SECRET}"
|
||||||
|
|
||||||
|
echo "Keycloak client created successfully"
|
||||||
|
echo "Client ID: ${TEMPORAL_OIDC_CLIENT_ID}"
|
||||||
|
echo "Redirect URI: https://${TEMPORAL_HOST}/*"
|
||||||
|
|
||||||
|
# Delete Keycloak client
|
||||||
|
delete-keycloak-client:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
echo "Deleting Keycloak client for Temporal..."
|
||||||
|
just keycloak::delete-client ${KEYCLOAK_REALM} ${TEMPORAL_OIDC_CLIENT_ID} || true
|
||||||
|
kubectl delete secret temporal-oauth-temp -n ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
if just vault::exist keycloak/client/temporal &>/dev/null; then
|
||||||
|
just vault::delete keycloak/client/temporal
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create Keycloak auth secret
|
||||||
|
create-keycloak-auth-secret:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if kubectl get secret temporal-oauth-temp -n ${TEMPORAL_NAMESPACE} &>/dev/null; then
|
||||||
|
oauth_client_id=$(kubectl get secret temporal-oauth-temp -n ${TEMPORAL_NAMESPACE} \
|
||||||
|
-o jsonpath='{.data.client_id}' | base64 -d)
|
||||||
|
oauth_client_secret=$(kubectl get secret temporal-oauth-temp -n ${TEMPORAL_NAMESPACE} \
|
||||||
|
-o jsonpath='{.data.client_secret}' | base64 -d)
|
||||||
|
elif helm status vault -n ${K8S_VAULT_NAMESPACE} &>/dev/null && \
|
||||||
|
just vault::get keycloak/client/temporal client_secret &>/dev/null; then
|
||||||
|
oauth_client_id=$(just vault::get keycloak/client/temporal client_id)
|
||||||
|
oauth_client_secret=$(just vault::get keycloak/client/temporal client_secret)
|
||||||
|
else
|
||||||
|
echo "Error: Cannot retrieve OAuth client secret. Please run 'just temporal::create-keycloak-client' first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if helm status external-secrets -n ${EXTERNAL_SECRETS_NAMESPACE} &>/dev/null; then
|
||||||
|
echo "External Secrets Operator detected. Storing secrets in Vault..."
|
||||||
|
|
||||||
|
just vault::put keycloak/client/temporal \
|
||||||
|
client_id="${oauth_client_id}" \
|
||||||
|
client_secret="${oauth_client_secret}"
|
||||||
|
|
||||||
|
kubectl delete secret temporal-web-auth -n ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
kubectl delete externalsecret temporal-web-auth -n ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
|
||||||
|
gomplate -f keycloak-auth-external-secret.gomplate.yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
echo "Waiting for ExternalSecret to sync..."
|
||||||
|
kubectl wait --for=condition=Ready externalsecret/temporal-web-auth \
|
||||||
|
-n ${TEMPORAL_NAMESPACE} --timeout=60s
|
||||||
|
|
||||||
|
echo "ExternalSecret created successfully"
|
||||||
|
else
|
||||||
|
echo "External Secrets Operator not found. Creating Kubernetes Secret directly..."
|
||||||
|
|
||||||
|
kubectl delete secret temporal-web-auth -n ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
kubectl create secret generic temporal-web-auth -n ${TEMPORAL_NAMESPACE} \
|
||||||
|
--from-literal=TEMPORAL_AUTH_CLIENT_ID="${oauth_client_id}" \
|
||||||
|
--from-literal=TEMPORAL_AUTH_CLIENT_SECRET="${oauth_client_secret}"
|
||||||
|
|
||||||
|
if helm status vault -n ${K8S_VAULT_NAMESPACE} &>/dev/null; then
|
||||||
|
just vault::put keycloak/client/temporal \
|
||||||
|
client_id="${oauth_client_id}" \
|
||||||
|
client_secret="${oauth_client_secret}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Kubernetes Secret created successfully"
|
||||||
|
fi
|
||||||
|
|
||||||
|
kubectl delete secret temporal-oauth-temp -n ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
|
||||||
|
# Delete Keycloak auth secret
|
||||||
|
delete-keycloak-auth-secret:
|
||||||
|
kubectl delete externalsecret temporal-web-auth -n ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
kubectl delete secret temporal-web-auth -n ${TEMPORAL_NAMESPACE} --ignore-not-found
|
||||||
|
|
||||||
|
# Initialize Temporal database schema
|
||||||
|
init-schema:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
echo "Initializing Temporal database schema..."
|
||||||
|
|
||||||
|
PG_HOST="postgres-cluster-rw.postgres"
|
||||||
|
PG_PORT="5432"
|
||||||
|
PG_USER=$(just vault::get temporal/db username)
|
||||||
|
PG_PASSWORD=$(just vault::get temporal/db password)
|
||||||
|
|
||||||
|
POD_NAME=$(kubectl get pods -n ${TEMPORAL_NAMESPACE} -l app.kubernetes.io/name=temporal-admintools \
|
||||||
|
-o jsonpath='{.items[0].metadata.name}' 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
if [ -z "${POD_NAME}" ]; then
|
||||||
|
echo "Admin tools pod not found. Running schema setup job..."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Setting up main database schema..."
|
||||||
|
kubectl exec -n ${TEMPORAL_NAMESPACE} ${POD_NAME} -- \
|
||||||
|
temporal-sql-tool --plugin postgres12 \
|
||||||
|
--endpoint ${PG_HOST} --port ${PG_PORT} \
|
||||||
|
--user ${PG_USER} --password ${PG_PASSWORD} \
|
||||||
|
--database temporal \
|
||||||
|
setup-schema -v 0.0
|
||||||
|
|
||||||
|
kubectl exec -n ${TEMPORAL_NAMESPACE} ${POD_NAME} -- \
|
||||||
|
temporal-sql-tool --plugin postgres12 \
|
||||||
|
--endpoint ${PG_HOST} --port ${PG_PORT} \
|
||||||
|
--user ${PG_USER} --password ${PG_PASSWORD} \
|
||||||
|
--database temporal \
|
||||||
|
update-schema -d /etc/temporal/schema/postgresql/v12/temporal/versioned
|
||||||
|
|
||||||
|
echo "Setting up visibility database schema..."
|
||||||
|
kubectl exec -n ${TEMPORAL_NAMESPACE} ${POD_NAME} -- \
|
||||||
|
temporal-sql-tool --plugin postgres12 \
|
||||||
|
--endpoint ${PG_HOST} --port ${PG_PORT} \
|
||||||
|
--user ${PG_USER} --password ${PG_PASSWORD} \
|
||||||
|
--database temporal_visibility \
|
||||||
|
setup-schema -v 0.0
|
||||||
|
|
||||||
|
kubectl exec -n ${TEMPORAL_NAMESPACE} ${POD_NAME} -- \
|
||||||
|
temporal-sql-tool --plugin postgres12 \
|
||||||
|
--endpoint ${PG_HOST} --port ${PG_PORT} \
|
||||||
|
--user ${PG_USER} --password ${PG_PASSWORD} \
|
||||||
|
--database temporal_visibility \
|
||||||
|
update-schema -d /etc/temporal/schema/postgresql/v12/visibility/versioned
|
||||||
|
|
||||||
|
echo "Schema initialization complete."
|
||||||
|
|
||||||
|
# Install Temporal
|
||||||
|
install:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
while [ -z "${TEMPORAL_HOST}" ]; do
|
||||||
|
TEMPORAL_HOST=$(gum input --prompt="Temporal host (FQDN): " --width=80 \
|
||||||
|
--placeholder="e.g., temporal.example.com")
|
||||||
|
done
|
||||||
|
|
||||||
|
while [ -z "${KEYCLOAK_HOST}" ]; do
|
||||||
|
KEYCLOAK_HOST=$(gum input --prompt="Keycloak host (FQDN): " --width=80 \
|
||||||
|
--placeholder="e.g., auth.example.com")
|
||||||
|
done
|
||||||
|
|
||||||
|
if helm status kube-prometheus-stack -n ${PROMETHEUS_NAMESPACE} &>/dev/null; then
|
||||||
|
if [ -z "${MONITORING_ENABLED}" ]; then
|
||||||
|
if gum confirm "Enable Prometheus monitoring?"; then
|
||||||
|
MONITORING_ENABLED="true"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Installing Temporal..."
|
||||||
|
|
||||||
|
just create-namespace
|
||||||
|
|
||||||
|
kubectl label namespace ${TEMPORAL_NAMESPACE} \
|
||||||
|
pod-security.kubernetes.io/enforce=baseline --overwrite
|
||||||
|
|
||||||
|
if [ "${MONITORING_ENABLED}" = "true" ]; then
|
||||||
|
kubectl label namespace ${TEMPORAL_NAMESPACE} \
|
||||||
|
buun.channel/enable-monitoring=true --overwrite
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Setting up PostgreSQL database..."
|
||||||
|
just create-postgres-user-and-db
|
||||||
|
just create-postgres-secret
|
||||||
|
|
||||||
|
echo "Setting up Keycloak OIDC authentication..."
|
||||||
|
just create-keycloak-client
|
||||||
|
just create-keycloak-auth-secret
|
||||||
|
|
||||||
|
echo "Generating Helm values..."
|
||||||
|
just add-helm-repo
|
||||||
|
gomplate -f temporal-values.gomplate.yaml -o temporal-values.yaml
|
||||||
|
|
||||||
|
echo "Installing Temporal Helm chart..."
|
||||||
|
helm upgrade --cleanup-on-fail --install temporal temporal/temporal \
|
||||||
|
--version ${TEMPORAL_CHART_VERSION} -n ${TEMPORAL_NAMESPACE} --wait \
|
||||||
|
-f temporal-values.yaml --timeout 15m
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Temporal installed successfully!"
|
||||||
|
echo "Access Temporal Web UI at: https://${TEMPORAL_HOST}"
|
||||||
|
echo ""
|
||||||
|
echo "OIDC authentication is configured with Keycloak."
|
||||||
|
echo "Users can login with their Keycloak credentials."
|
||||||
|
|
||||||
|
# Upgrade Temporal
|
||||||
|
upgrade:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
while [ -z "${TEMPORAL_HOST}" ]; do
|
||||||
|
TEMPORAL_HOST=$(gum input --prompt="Temporal host (FQDN): " --width=80)
|
||||||
|
done
|
||||||
|
|
||||||
|
while [ -z "${KEYCLOAK_HOST}" ]; do
|
||||||
|
KEYCLOAK_HOST=$(gum input --prompt="Keycloak host (FQDN): " --width=80)
|
||||||
|
done
|
||||||
|
|
||||||
|
if helm status kube-prometheus-stack -n ${PROMETHEUS_NAMESPACE} &>/dev/null; then
|
||||||
|
if [ -z "${MONITORING_ENABLED}" ]; then
|
||||||
|
if gum confirm "Enable Prometheus monitoring?"; then
|
||||||
|
MONITORING_ENABLED="true"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${MONITORING_ENABLED}" = "true" ]; then
|
||||||
|
kubectl label namespace ${TEMPORAL_NAMESPACE} \
|
||||||
|
buun.channel/enable-monitoring=true --overwrite
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Upgrading Temporal..."
|
||||||
|
|
||||||
|
gomplate -f temporal-values.gomplate.yaml -o temporal-values.yaml
|
||||||
|
|
||||||
|
helm upgrade temporal temporal/temporal \
|
||||||
|
--version ${TEMPORAL_CHART_VERSION} -n ${TEMPORAL_NAMESPACE} --wait \
|
||||||
|
-f temporal-values.yaml --timeout 15m
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Temporal upgraded successfully!"
|
||||||
|
echo "Access Temporal Web UI at: https://${TEMPORAL_HOST}"
|
||||||
|
|
||||||
|
# Uninstall Temporal (delete-data: true to delete database and Vault secrets)
|
||||||
|
uninstall delete-data='false':
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
if ! gum confirm "Uninstall Temporal?"; then
|
||||||
|
echo "Cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Uninstalling Temporal..."
|
||||||
|
helm uninstall temporal -n ${TEMPORAL_NAMESPACE} --ignore-not-found --wait
|
||||||
|
|
||||||
|
just delete-keycloak-auth-secret || true
|
||||||
|
just delete-keycloak-client || true
|
||||||
|
just delete-postgres-secret
|
||||||
|
just delete-namespace
|
||||||
|
|
||||||
|
if [ "{{ delete-data }}" = "true" ]; then
|
||||||
|
echo "Deleting database and Vault secrets..."
|
||||||
|
just postgres::delete-db temporal || true
|
||||||
|
just postgres::delete-db temporal_visibility || true
|
||||||
|
just postgres::delete-user temporal || true
|
||||||
|
just vault::delete temporal/db || true
|
||||||
|
just vault::delete keycloak/client/temporal || true
|
||||||
|
echo "Temporal uninstalled with all data deleted."
|
||||||
|
else
|
||||||
|
echo "Temporal uninstalled."
|
||||||
|
echo ""
|
||||||
|
echo "Note: The following resources were NOT deleted:"
|
||||||
|
echo " - PostgreSQL user and databases (temporal, temporal_visibility)"
|
||||||
|
echo " - Vault secrets (temporal/db, keycloak/client/temporal)"
|
||||||
|
echo ""
|
||||||
|
echo "To delete all data, run:"
|
||||||
|
echo " just temporal::uninstall true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a Temporal namespace (workflow namespace, not Kubernetes)
|
||||||
|
create-temporal-namespace name='' retention='3d':
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
name="{{ name }}"
|
||||||
|
retention="{{ retention }}"
|
||||||
|
while [ -z "${name}" ]; do
|
||||||
|
name=$(gum input --prompt="Namespace name: " --width=80 --placeholder="e.g., default")
|
||||||
|
done
|
||||||
|
POD_NAME=$(kubectl get pods -n ${TEMPORAL_NAMESPACE} -l app.kubernetes.io/name=temporal-admintools \
|
||||||
|
-o jsonpath='{.items[0].metadata.name}')
|
||||||
|
kubectl exec -n ${TEMPORAL_NAMESPACE} ${POD_NAME} -- \
|
||||||
|
tctl --namespace "${name}" namespace register --retention "${retention}"
|
||||||
|
echo "Namespace '${name}' created with retention ${retention}."
|
||||||
|
|
||||||
|
# List Temporal namespaces
|
||||||
|
list-temporal-namespaces:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
POD_NAME=$(kubectl get pods -n ${TEMPORAL_NAMESPACE} -l app.kubernetes.io/name=temporal-admintools \
|
||||||
|
-o jsonpath='{.items[0].metadata.name}')
|
||||||
|
kubectl exec -n ${TEMPORAL_NAMESPACE} ${POD_NAME} -- tctl namespace list
|
||||||
|
|
||||||
|
# Get Temporal cluster info
|
||||||
|
cluster-info:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
POD_NAME=$(kubectl get pods -n ${TEMPORAL_NAMESPACE} -l app.kubernetes.io/name=temporal-admintools \
|
||||||
|
-o jsonpath='{.items[0].metadata.name}')
|
||||||
|
kubectl exec -n ${TEMPORAL_NAMESPACE} ${POD_NAME} -- tctl cluster health
|
||||||
22
temporal/keycloak-auth-external-secret.gomplate.yaml
Normal file
22
temporal/keycloak-auth-external-secret.gomplate.yaml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
apiVersion: external-secrets.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: temporal-web-auth
|
||||||
|
namespace: {{ .Env.TEMPORAL_NAMESPACE }}
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
secretStoreRef:
|
||||||
|
name: vault-secret-store
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
target:
|
||||||
|
name: temporal-web-auth
|
||||||
|
creationPolicy: Owner
|
||||||
|
data:
|
||||||
|
- secretKey: TEMPORAL_AUTH_CLIENT_ID
|
||||||
|
remoteRef:
|
||||||
|
key: keycloak/client/temporal
|
||||||
|
property: client_id
|
||||||
|
- secretKey: TEMPORAL_AUTH_CLIENT_SECRET
|
||||||
|
remoteRef:
|
||||||
|
key: keycloak/client/temporal
|
||||||
|
property: client_secret
|
||||||
18
temporal/postgres-external-secret.gomplate.yaml
Normal file
18
temporal/postgres-external-secret.gomplate.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: external-secrets.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: temporal-postgres-auth
|
||||||
|
namespace: {{ .Env.TEMPORAL_NAMESPACE }}
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
secretStoreRef:
|
||||||
|
name: vault-secret-store
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
target:
|
||||||
|
name: temporal-postgres-auth
|
||||||
|
creationPolicy: Owner
|
||||||
|
data:
|
||||||
|
- secretKey: password
|
||||||
|
remoteRef:
|
||||||
|
key: temporal/db
|
||||||
|
property: password
|
||||||
204
temporal/temporal-values.gomplate.yaml
Normal file
204
temporal/temporal-values.gomplate.yaml
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
server:
|
||||||
|
replicaCount: 1
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
runAsNonRoot: true
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
config:
|
||||||
|
persistence:
|
||||||
|
default:
|
||||||
|
driver: "sql"
|
||||||
|
sql:
|
||||||
|
driver: "postgres12"
|
||||||
|
host: "postgres-cluster-rw.postgres"
|
||||||
|
port: 5432
|
||||||
|
database: temporal
|
||||||
|
user: temporal
|
||||||
|
existingSecret: temporal-postgres-auth
|
||||||
|
maxConns: 20
|
||||||
|
maxIdleConns: 20
|
||||||
|
maxConnLifetime: "1h"
|
||||||
|
|
||||||
|
visibility:
|
||||||
|
driver: "sql"
|
||||||
|
sql:
|
||||||
|
driver: "postgres12"
|
||||||
|
host: "postgres-cluster-rw.postgres"
|
||||||
|
port: 5432
|
||||||
|
database: temporal_visibility
|
||||||
|
user: temporal
|
||||||
|
existingSecret: temporal-postgres-auth
|
||||||
|
maxConns: 20
|
||||||
|
maxIdleConns: 20
|
||||||
|
maxConnLifetime: "1h"
|
||||||
|
|
||||||
|
{{- if .Env.MONITORING_ENABLED }}
|
||||||
|
metrics:
|
||||||
|
serviceMonitor:
|
||||||
|
enabled: true
|
||||||
|
additionalLabels:
|
||||||
|
release: kube-prometheus-stack
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
containerSecurityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
|
||||||
|
history:
|
||||||
|
containerSecurityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
|
||||||
|
matching:
|
||||||
|
containerSecurityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
|
||||||
|
worker:
|
||||||
|
containerSecurityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
|
||||||
|
admintools:
|
||||||
|
enabled: true
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
runAsNonRoot: true
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
containerSecurityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 256Mi
|
||||||
|
|
||||||
|
web:
|
||||||
|
enabled: true
|
||||||
|
replicaCount: 1
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 8080
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: traefik
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
hosts:
|
||||||
|
- {{ .Env.TEMPORAL_HOST }}
|
||||||
|
tls:
|
||||||
|
- secretName: temporal-web-tls
|
||||||
|
hosts:
|
||||||
|
- {{ .Env.TEMPORAL_HOST }}
|
||||||
|
additionalEnv:
|
||||||
|
- name: TEMPORAL_AUTH_ENABLED
|
||||||
|
value: "true"
|
||||||
|
- name: TEMPORAL_AUTH_PROVIDER_URL
|
||||||
|
value: "https://{{ .Env.KEYCLOAK_HOST }}/realms/{{ .Env.KEYCLOAK_REALM }}"
|
||||||
|
- name: TEMPORAL_AUTH_SCOPES
|
||||||
|
value: "openid,profile,email"
|
||||||
|
- name: TEMPORAL_AUTH_CALLBACK_URL
|
||||||
|
value: "https://{{ .Env.TEMPORAL_HOST }}/auth/sso/callback"
|
||||||
|
additionalEnvSecretName: temporal-web-auth
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 256Mi
|
||||||
|
|
||||||
|
cassandra:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
mysql:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
postgresql:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
elasticsearch:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
prometheus:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
schema:
|
||||||
|
createDatabase:
|
||||||
|
enabled: false
|
||||||
|
setup:
|
||||||
|
enabled: true
|
||||||
|
backoffLimit: 100
|
||||||
|
update:
|
||||||
|
enabled: true
|
||||||
|
backoffLimit: 100
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
runAsNonRoot: true
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
containerSecurityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false
|
||||||
Reference in New Issue
Block a user