Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
imaustink committed Jun 13, 2024
0 parents commit 8792dd4
Show file tree
Hide file tree
Showing 26 changed files with 1,648 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
84 changes: 84 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: CI

on:
push:
branches: [main]
pull_request:
release:
types: [published]

jobs:
lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.22.3'
- name: Check out code
uses: actions/checkout@v3
- name: Check formatting
run: |
test -z $(gofmt -l .)
build-and-test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.22.3'
- name: Install dependencies
run: go get ./src
- name: Build
run: go build -o ./dist/bin ./src
- name: Test with the Go CLI
run: go test ./src

build-and-publish-image:
runs-on: ubuntu-latest
needs:
- lint
- build-and-test

steps:
- uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Tag the image
id: meta
uses: docker/metadata-action@v4
with:
images: |
bitovi/temporal-cloud-metrics-to-k8s
tags: |
type=raw,value=latest,enable=${{ github.ref_name == 'main' }}
type=semver,pattern={{version}},enable=${{ github.event_name == 'release' }}
-
name: Login to Docker Hub
uses: docker/login-action@v2
if: github.event_name != 'pull_request'
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
-
name: Build Docker image
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
-
name: Push Docker image
uses: docker/build-push-action@v4
if: ${{ (github.ref_name == 'main') || (github.event_name == 'release') }}
with:
context: .
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
push: true
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
certs
13 changes: 13 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM golang:1.22.3

WORKDIR /app

COPY go.mod go.sum ./

RUN go mod download

COPY src/*.go ./

RUN CGO_ENABLED=0 GOOS=linux go build -o ./temporal-cloud-metrics-adapter

CMD ["./temporal-cloud-metrics-adapter"]
21 changes: 21 additions & 0 deletions LISCENCE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Bitovi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
94 changes: 94 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Temporal Cloud Metrics to Kubernetes

Bring Temporal Cloud Metrics into your Kubernetes cluster to inform autoscaling of your workers.

![Metrics Dashboard Demo](./img/metrics-dashboard.jpg)

## Setup

### Prerequisites

1. A [Temporal Cloud account](https://temporal.io/)
- [An mTLS certificate provisioned](https://docs.temporal.io/cloud/certificates)
- [The metrics endpoint enabled](https://docs.temporal.io/production-deployment/cloud/metrics/general-setup)
1. A [Kubernetes](https://kubernetes.io/) compliant cluster (also tested on [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/))
1. The [Helm](https://helm.sh/docs/intro/install/) CLI

### Step 1: Copy mTLS Certificate

We need the client mTLS certificate for our Temporal Cloud namespace so that we can load it into our cluster for use in the metrics adapter and worker.

1. Copy the certificate into `./certs/client.crt`
1. Copy the key into `./certs/client.key`

### Step 2: Configuration

A YAML config file is used to define the connection parameters and the specific metrics you'd like to pull into Kubernetes from Temporal Cloud.

There is a complete example configuration in [`./chart/templates/configuration.yaml`](./chart/templates/configuration.yaml). You may use it as it or adjust it to fit your needs before installing the helm chart.

### Step 3: HPA

The HPA (Horizontal Pod Autoscaler) defines the desired scaling behavior and bounds, and manages our deployment replicas accordingly.

There is a complete example HPA in [`./chart/templates/hpa.yaml`](./chart/templates/hpa.yaml). You may use it as it or adjust it to fit your needs before installing the helm chart.

### Step 4: Install

__Install with Existing worker__

This allows you to setup autoscaling on an existing deployment.

```bash
helm install temporal-cloud-metrics-adapter ./chart --wait \
--namespace EXISTING_WORKER_DEPLOYMENT_NAMESPACE \
--set-file=temporal.tls.cert=$TEMPORAL_CERT \
--set-file=temporal.tls.key=$TEMPORAL_KEY \
--set temporal.namespace=$TEMPORAL_NAMESPACE \
--set temporal.metrics_endpoint=$TEMPORAL_METRICS_ENDPOINT \
--set worker.deployment=$EXISTING_WORKER_DEPLOYMENT_NAME
```

__Install with Demo worker__

This is intended for testing and demos and should never been used in a production environment.

```bash
helm install temporal-cloud-metrics-adapter ./chart --wait \
--namespace $NAMESPACE --create-namespace \
--set-file=temporal.tls.cert=$TEMPORAL_CERT \
--set-file=temporal.tls.key=$TEMPORAL_KEY \
--set temporal.namespace=$TEMPORAL_NAMESPACE \
--set temporal.address=$TEMPORAL_ADDRESS \
--set temporal.metrics_endpoint=$TEMPORAL_METRICS_ENDPOINT \
--set worker.demo=true
```

__Uninstall__

```bash
helm uninstall -n $NAMESPACE temporal-cloud-metrics-adapter
```

__Helm Values__

| Option | Type | Example Value | Description |
|---------------------------|---------|--------------------------------------|---------------------------------------------------|
| temporal.tls.cert | File | `certs/client.crt` | Path to the client certificate file |
| temporal.tls.key | File | `certs/client.key` | Path to the client key file |
| temporal.namespace | String | `xyz.123` | The target Temporal Cloud namespace |
| temporal.address | String | `xyz.123.tmprl.cloud:7233` | Address of the Temporal Cloud instance |
| temporal.metrics_endpoint | String | `https://123.tmprl.cloud/prometheus` | Endpoint for accessing Temporal metrics |
| worker.deployment | String | `temporal-worker` | Name of existing Temporal worker deployment |
| worker.demo | Boolean | `true` or `false` | Flag to determine whether to deploy a demo worker |

### Demo

This repo includes a script to create a burst of workflows to simulate load.

```bash
# Startup 50 demo workflows
TEMPORAL_ADDRESS=xyz.123.tmprl.cloud:7233 \
TEMPORAL_NAMESPACE=xyz.123 \
./scripts/execute-demo-workflows 50
```
23 changes: 23 additions & 0 deletions chart/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
9 changes: 9 additions & 0 deletions chart/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v2
name: temporal-cloud-metrics-to-k8s
description: A Helm chart to enable access to metrics from Temporal Cloud within your cluster.

type: application

version: 0.1.0

appVersion: "0.1.0"
13 changes: 13 additions & 0 deletions chart/templates/api-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1beta1.external.metrics.k8s.io
spec:
service:
name: temporal-cloud-metrics-adapter
namespace: {{ .Release.Namespace }}
group: external.metrics.k8s.io
version: v1beta1
insecureSkipTLSVerify: true
groupPriorityMinimum: 100
versionPriority: 100
47 changes: 47 additions & 0 deletions chart/templates/configuration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: adapter-configuration
namespace: {{ .Release.Namespace }}
data:
config.yaml: |
version: "1"
temporal_cloud:
metrics_endpoint: {{ .Values.temporal.metrics_endpoint }}
tls:
# ca: /app/certs/client.ca
cert: /app/certs/client.crt
key: /app/certs/client.key
metrics:
temporal_cloud_sync_match_rate:
query: >
abs(
clamp_max(
sum by(temporal_namespace) (
rate(
temporal_cloud_v0_poll_success_sync_count{temporal_namespace="{{ .Values.temporal.namespace }}"}[1m]
)
)
-
sum by(temporal_namespace) (
rate(
temporal_cloud_v0_poll_success_count{temporal_namespace="{{ .Values.temporal.namespace }}"}[1m]
)
),
0
)
) or on () label_replace(vector(0), "temporal_namespace", "{{ .Values.temporal.namespace }}", "", "")
temporal_cloud_service_latency:
query: >
abs(
clamp_max(
sum by(temporal_namespace) (
rate(temporal_cloud_v0_service_latency_sum{temporal_namespace="{{ .Values.temporal.namespace }}"}[1m])
)
-
sum by(temporal_namespace) (
rate(temporal_cloud_v0_service_latency_count{temporal_namespace="{{ .Values.temporal.namespace }}"}[1m])
),
0
)
) or on () label_replace(vector(0), "temporal_namespace", "{{ .Values.temporal.namespace }}", "", "")
43 changes: 43 additions & 0 deletions chart/templates/demo-worker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{{- if .Values.worker.demo }}
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: temporal-worker
name: temporal-worker
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: temporal-worker
template:
metadata:
labels:
app: temporal-worker
name: temporal-worker
spec:
containers:
- name: temporal-worker
image: bitovi/temporal-example-workers:golang-hello-world-latest
imagePullPolicy: Always
ports: []
volumeMounts:
- name: mtls-certs
mountPath: "/app/certs"
readOnly: true
env:
- name: TEMPORAL_NAMESPACE
value: "{{ .Values.temporal.namespace }}"
- name: TEMPORAL_CERT_PATH
value: "/app/certs/client.crt"
- name: TEMPORAL_KEY_PATH
value: "/app/certs/client.key"
- name: TEMPORAL_PORT
value: "{{ .Values.temporal.address }}"
- name: TEMPORAL_QUEUE
value: autoscaler_demo
volumes:
- name: mtls-certs
secret:
secretName: mtls-certs
{{- end }}
Loading

0 comments on commit 8792dd4

Please sign in to comment.