Skip to content

Commit 2708c59

Browse files
Merge pull request #27 from ls1intum/26-switch-to-redis
26 switch to redis
2 parents d896ba7 + 543a02b commit 2708c59

28 files changed

Lines changed: 1229 additions & 704 deletions

README.md

Lines changed: 224 additions & 203 deletions
Large diffs are not rendered by default.

chart/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
apiVersion: v2
22
name: theia-shared-cache
3-
description: A Gradle Build Cache server with MinIO backend for Theia IDE deployments in Kubernetes
3+
description: A Gradle Build Cache server with Redis backend for Theia IDE deployments in Kubernetes
44

55
type: application
66

77
# Chart version - bump for breaking changes
8-
version: 0.2.3
8+
version: 0.3.0
99

1010
# Application version - matches the cache server version
1111
appVersion: "0.1.0"

chart/README.md

Lines changed: 101 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,44 @@
11
# theia-shared-cache Helm Chart
22

3-
Helm chart to deploy a custom Gradle Build Cache server with MinIO backend for Theia IDE deployments in Kubernetes.
3+
Helm chart to deploy a Gradle Build Cache server with Redis backend for Kubernetes.
44

55
## Architecture
66

7-
This chart deploys two components:
7+
This chart deploys the following components:
88

9-
1. **Cache Server** - A custom Go-based Gradle build cache server
10-
2. **MinIO** - S3-compatible object storage for cache data
9+
1. **Cache Server** - A Go-based Gradle build cache server
10+
2. **Redis** - In-memory storage for cache artifacts (with optional redis-exporter sidecar)
11+
3. **Reposilite** (optional) - Maven/Gradle dependency proxy
1112

1213
```
13-
┌─────────────────────────────────────────────────────┐
14-
│ Kubernetes Cluster │
15-
│ │
16-
│ ┌─────────────────┐ ┌─────────────────────┐ │
17-
│ │ Cache Server │──────▶│ MinIO │ │
18-
│ │ (Deployment) │ │ (StatefulSet) │ │
19-
│ │ Port: 8080 │ │ Port: 9000 │ │
20-
│ └────────┬────────┘ └─────────────────────┘ │
21-
│ │ │
22-
│ ┌────────▼────────┐ │
23-
│ │ Service │◀──── Gradle Builds │
24-
│ │ Port: 8080 │ │
25-
│ └─────────────────┘ │
26-
└─────────────────────────────────────────────────────┘
14+
┌──────────────────────────────────────────────────────────┐
15+
│ Kubernetes Cluster │
16+
│ │
17+
│ ┌─────────────────┐ ┌─────────────────────────┐ │
18+
│ │ Cache Server │──────▶│ Redis (Deployment) │ │
19+
│ │ (Deployment) │ │ Port: 6379 │ │
20+
│ │ Port: 8080 │ │ + Exporter :9121 │ │
21+
│ └────────┬─────────┘ └─────────────────────────┘ │
22+
│ │ │
23+
│ ┌────────▼─────────┐ ┌─────────────────────────┐ │
24+
│ │ Service │ │ Reposilite (optional) │ │
25+
│ │ Port: 8080 │ │ Dependency proxy │ │
26+
│ └──────────────────┘ └─────────────────────────┘ │
27+
│ ▲ │
28+
│ Gradle Builds │
29+
└──────────────────────────────────────────────────────────┘
2730
```
2831

2932
## Features
3033

31-
- Custom Go-based cache server with MinIO storage backend
34+
- Go-based cache server with Redis storage backend
35+
- Auto-generated Redis password (stored in Kubernetes Secret)
3236
- Prometheus metrics endpoint (`/metrics`)
37+
- Redis metrics via redis-exporter sidecar
38+
- Optional ServiceMonitor for Prometheus Operator
3339
- Health checks (`/ping`, `/health`)
34-
- Basic authentication for cache operations
35-
- Persistent storage for MinIO data
36-
- Configurable resource limits
40+
- Optional Reposilite dependency proxy
41+
- Kubernetes recommended labels (`app.kubernetes.io/*`)
3742

3843
## Quick Start
3944

@@ -47,10 +52,8 @@ helm install gradle-cache ./chart
4752

4853
```bash
4954
helm install gradle-cache ./chart \
50-
--set cacheServer.auth.password=mysecretpassword \
51-
--set minio.auth.accessKey=myaccesskey \
52-
--set minio.auth.secretKey=mysecretkey \
53-
--set minio.persistence.size=100Gi
55+
--set auth.password=mysecretpassword \
56+
--set metrics.serviceMonitor.enabled=true
5457
```
5558

5659
## Configuration
@@ -59,47 +62,53 @@ helm install gradle-cache ./chart \
5962

6063
| Parameter | Description | Default |
6164
|-----------|-------------|---------|
62-
| `cacheServer.replicaCount` | Number of cache server replicas | `1` |
63-
| `cacheServer.image.repository` | Cache server image repository | `ghcr.io/kevingruber/theia-shared-cache/gradle-cache` |
64-
| `cacheServer.image.tag` | Cache server image tag | `latest` |
65-
| `cacheServer.port` | Cache server port | `8080` |
66-
| `cacheServer.auth.enabled` | Enable authentication | `true` |
67-
| `cacheServer.auth.username` | Cache username | `gradle` |
68-
| `cacheServer.auth.password` | Cache password | `changeme` |
69-
| `cacheServer.config.maxEntrySizeMB` | Max cache entry size in MB | `100` |
70-
| `cacheServer.resources` | Resource limits/requests | See values.yaml |
71-
72-
### MinIO
65+
| `enabled` | Enable/disable the entire deployment | `true` |
66+
| `image.repository` | Cache server image repository | `ghcr.io/ls1intum/theia-shared-cache/gradle-cache` |
67+
| `image.tag` | Cache server image tag | `main` |
68+
| `image.pullPolicy` | Image pull policy | `IfNotPresent` |
69+
| `auth.enabled` | Enable authentication | `true` |
70+
| `auth.username` | Cache username | `gradle` |
71+
| `auth.password` | Cache password | `changeme` |
72+
| `resources.cacheServer.requests.memory` | Memory request | `256Mi` |
73+
| `resources.cacheServer.requests.cpu` | CPU request | `100m` |
74+
| `resources.cacheServer.limits.memory` | Memory limit | `1Gi` |
75+
| `resources.cacheServer.limits.cpu` | CPU limit | `500m` |
76+
77+
### Redis
7378

7479
| Parameter | Description | Default |
7580
|-----------|-------------|---------|
76-
| `minio.enabled` | Deploy MinIO alongside cache server | `true` |
77-
| `minio.image.repository` | MinIO image repository | `minio/minio` |
78-
| `minio.image.tag` | MinIO image tag | `latest` |
79-
| `minio.auth.accessKey` | MinIO access key | `minioadmin` |
80-
| `minio.auth.secretKey` | MinIO secret key | `minioadmin` |
81-
| `minio.persistence.enabled` | Enable persistent storage | `true` |
82-
| `minio.persistence.size` | Storage size | `50Gi` |
83-
| `minio.persistence.storageClass` | Storage class | `""` (default) |
84-
| `minio.resources` | Resource limits/requests | See values.yaml |
81+
| `resources.redis.requests.memory` | Memory request | `128Mi` |
82+
| `resources.redis.requests.cpu` | CPU request | `100m` |
83+
| `resources.redis.limits.memory` | Memory limit | `2Gi` |
84+
| `resources.redis.limits.cpu` | CPU limit | `1000m` |
8585

86-
### Metrics
86+
The Redis password is auto-generated on first install and persisted across `helm upgrade`. Both Redis and the cache server read it from the same Kubernetes Secret.
87+
88+
### TLS
8789

8890
| Parameter | Description | Default |
8991
|-----------|-------------|---------|
90-
| `metrics.enabled` | Enable Prometheus metrics | `true` |
91-
| `metrics.serviceMonitor.enabled` | Create ServiceMonitor (Prometheus Operator) | `false` |
92+
| `tls.enabled` | Enable TLS for the cache server | `false` |
93+
| `tls.secretName` | Kubernetes TLS Secret name | `""` |
9294

93-
### External Secret
95+
### Metrics
9496

9597
| Parameter | Description | Default |
9698
|-----------|-------------|---------|
97-
| `existingSecret` | Use existing secret for credentials | `""` |
99+
| `metrics.serviceMonitor.enabled` | Create ServiceMonitor for Prometheus Operator | `false` |
100+
| `metrics.serviceMonitor.interval` | Scrape interval | `15s` |
101+
102+
Prometheus pod annotations (`prometheus.io/scrape`, `prometheus.io/port`) are always included on pod templates for annotation-based discovery.
98103

99-
If using `existingSecret`, the secret must contain these keys:
100-
- `minio-access-key`
101-
- `minio-secret-key`
102-
- `cache-password`
104+
### Reposilite
105+
106+
| Parameter | Description | Default |
107+
|-----------|-------------|---------|
108+
| `reposilite.enabled` | Deploy Reposilite dependency proxy | `true` |
109+
| `reposilite.persistence.enabled` | Enable persistent storage | `true` |
110+
| `reposilite.persistence.size` | Storage size | `20Gi` |
111+
| `reposilite.persistence.storageClass` | Storage class | `csi-rbd-sc` |
103112

104113
## Gradle Configuration
105114

@@ -111,20 +120,17 @@ buildCache {
111120
remote<HttpBuildCache> {
112121
url = uri("http://<release-name>-cache:8080/cache/")
113122
credentials {
114-
username = "gradle"
115-
password = "your-password"
123+
username = "writer"
124+
password = "changeme-writer"
116125
}
117126
isPush = true
118127
}
119128
}
120129
```
121130

122-
Or via environment variables:
123-
124-
```bash
125-
export GRADLE_CACHE_URL=http://<release-name>-cache:8080/cache/
126-
export GRADLE_CACHE_USERNAME=gradle
127-
export GRADLE_CACHE_PASSWORD=your-password
131+
Enable caching in `gradle.properties`:
132+
```properties
133+
org.gradle.caching=true
128134
```
129135

130136
## Port Forwarding (Development)
@@ -141,33 +147,46 @@ curl http://localhost:8080/health
141147

142148
## Monitoring
143149

144-
If `metrics.enabled` is true, Prometheus metrics are available at `/metrics`:
150+
### Prometheus Metrics
145151

146-
```bash
147-
curl http://<release-name>-cache:8080/metrics
148-
```
152+
Cache server metrics at `/metrics`:
153+
154+
| Metric | Type | Description |
155+
|--------|------|-------------|
156+
| `gradle_cache_requests_total` | Counter | Total requests by method and status |
157+
| `gradle_cache_cache_hits_total` | Counter | Cache hit count |
158+
| `gradle_cache_cache_misses_total` | Counter | Cache miss count |
159+
| `gradle_cache_request_duration_seconds` | Histogram | Request latency |
160+
| `gradle_cache_entry_size` | Histogram | Cache entry sizes |
161+
162+
Redis metrics via redis-exporter sidecar at `:9121/metrics`:
163+
164+
| Metric | Type | Description |
165+
|--------|------|-------------|
166+
| `redis_memory_used_bytes` | Gauge | Redis memory consumption |
167+
| `redis_db_keys` | Gauge | Number of cached entries |
168+
| `redis_keyspace_hits_total` | Counter | Redis-level cache hits |
169+
| `redis_keyspace_misses_total` | Counter | Redis-level cache misses |
170+
171+
### Grafana Dashboard
149172

150-
Available metrics:
151-
- `cache_requests_total` - Total cache requests by method and status
152-
- `cache_hits_total` - Cache hit count
153-
- `cache_misses_total` - Cache miss count
154-
- `cache_request_duration_seconds` - Request duration histogram
155-
- `cache_entry_size_bytes` - Cache entry size histogram
173+
A pre-built dashboard is available at `src/deployments/grafana/dashboards/gradle-build-cache.json`. Import it into your Grafana instance for cache hit rate, latency, Redis memory, and error monitoring.
156174

157175
## Upgrading
158176

159-
### From 0.1.x to 0.2.0
177+
### From 0.2.x to 0.3.0
160178

161-
Version 0.2.0 is a breaking change that replaces the official Gradle cache node with a custom implementation.
179+
Version 0.3.0 is a breaking change that replaces MinIO with Redis.
162180

163181
Changes:
164-
- New image: custom Go-based cache server instead of `gradle/build-cache-node`
165-
- New storage: MinIO backend instead of local PersistentVolume
166-
- New port: 8080 instead of 5071
167-
- New authentication: Basic auth built into cache server
182+
- Storage backend: MinIO (S3-compatible) replaced with Redis (in-memory)
183+
- Redis password auto-generated (no manual credential config)
184+
- MinIO StatefulSet replaced with Redis Deployment
185+
- Redis exporter sidecar for Prometheus metrics
186+
- Helm labels updated to `app.kubernetes.io/*` standard
168187

169188
Migration steps:
170-
1. Back up any important cache data (usually safe to lose)
189+
1. Cache data cannot be migrated — the cache will start cold
171190
2. Uninstall the old release: `helm uninstall <release-name>`
172-
3. Install the new version with updated values
173-
4. Update Gradle configuration to use new port and credentials
191+
3. Install the new version: `helm install <release-name> ./chart`
192+
4. Gradle builds repopulate the cache automatically

chart/templates/_helpers.tpl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{{/*
2+
Standard labels for theia-shared-cache resources
3+
*/}}
4+
{{- define "theia-shared-cache.labels" -}}
5+
app.kubernetes.io/name: {{ .Chart.Name }}
6+
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
7+
app.kubernetes.io/instance: {{ .Release.Name }}
8+
app.kubernetes.io/managed-by: {{ .Release.Service }}
9+
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
10+
{{- end -}}
11+
12+
{{- define "theia-shared-cache.selectorLabels" -}}
13+
app.kubernetes.io/name: {{ .Chart.Name }}
14+
app.kubernetes.io/instance: {{ .Release.Name }}
15+
{{- end }}

chart/templates/configmap.yaml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ kind: ConfigMap
44
metadata:
55
name: {{ .Release.Name }}-config
66
labels:
7-
app: {{ .Release.Name }}
8-
component: cache-server
7+
{{- include "theia-shared-cache.labels" . | nindent 4 }}
8+
app.kubernetes.io/component: cache-server
99
data:
1010
config.yaml: |
1111
server:
@@ -14,15 +14,13 @@ data:
1414
write_timeout: 120s
1515
{{- if .Values.tls.enabled }}
1616
tls:
17-
enabled: true
17+
enabled: true
1818
cert_file: /etc/certs/tls.crt
1919
key_file: /etc/certs/tls.key
2020
{{- end}}
2121
2222
storage:
23-
endpoint: "{{ .Release.Name }}-minio:9000"
24-
bucket: "gradle-cache"
25-
use_ssl: false
23+
addr: "{{ .Release.Name }}-redis:6379"
2624
2725
cache:
2826
max_entry_size_mb: 100

0 commit comments

Comments
 (0)