Skip to content

Commit dead240

Browse files
authored
chore: fix local setup with k3d (#670)
Add docker deployments into a common service and make it accessible to k3d load balancer exposing kubernetes cluster
1 parent ce758ad commit dead240

File tree

8 files changed

+184
-53
lines changed

8 files changed

+184
-53
lines changed

Makefile

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ SOURCES := $(shell \
44

55
BUF := github.com/bufbuild/buf/cmd/buf@v1.32.1
66

7+
# Detect Docker Compose command - prefer 'docker compose' over 'docker-compose'
8+
DOCKER_COMPOSE := $(shell if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then echo "docker compose"; elif command -v docker-compose >/dev/null 2>&1; then echo "docker-compose"; else echo "docker-compose"; fi)
9+
710
.PHONY: help
811
help: Makefile ## Show list of commands.
912
@echo "Choose a command to run in "$(APP_NAME)":"
@@ -152,25 +155,25 @@ migrate: ## Execute migration.
152155
.PHONY: deps/up
153156
deps/up: ## Create containers dependencies.
154157
@echo "Creating dependencies "
155-
@docker-compose up -d --build
158+
@$(DOCKER_COMPOSE) up -d --build
156159
@echo "Dependencies created successfully."
157160

158161
.PHONY: deps/start
159162
deps/start: ## Start containers dependencies.
160163
@echo "Starting dependencies "
161-
@docker-compose start
164+
@$(DOCKER_COMPOSE) start
162165
@echo "Dependencies started successfully."
163166

164167
.PHONY: deps/stop
165168
deps/stop: ## Stop containers dependencies.
166169
@echo "Stopping dependencies "
167-
@docker-compose stop
170+
@$(DOCKER_COMPOSE) stop
168171
@echo "Dependencies stopped successfully."
169172

170173
.PHONY: deps/down
171174
deps/down: ## Delete containers dependencies.
172175
@echo "Deleting dependencies "
173-
@docker-compose down
176+
@$(DOCKER_COMPOSE) down
174177
@echo "Dependencies deleted successfully."
175178

176179

@@ -179,16 +182,18 @@ deps/down: ## Delete containers dependencies.
179182
#-------------------------------------------------------------------------------
180183
.PHONY: maestro/start
181184
maestro/start: k3d/up build ## Start Maestro with all of its dependencies.
182-
@echo "Starting maestro..."
183-
@cd ./e2e/framework/maestro; docker compose up --build -d
185+
@echo "Starting maestro dependencies (postgres, redis)..."
186+
@cd ./e2e/framework/maestro; $(DOCKER_COMPOSE) up -d postgres redis
187+
@echo "Running database migrations..."
184188
@MAESTRO_MIGRATION_PATH="file://internal/service/migrations" go run main.go migrate;
185-
@cd ./e2e/framework/maestro; docker compose up --build -d worker runtime-watcher #Worker and watcher do not work before migration, so we start them after it.
189+
@echo "Starting maestro application services..."
190+
@cd ./e2e/framework/maestro; $(DOCKER_COMPOSE) up --build -d
186191
@echo "Maestro is up and running!"
187192

188193
.PHONY: maestro/down
189194
maestro/down: k3d/down ## Delete Maestro and all of its dependencies.
190195
@echo "Deleting maestro..."
191-
@cd ./e2e/framework/maestro; docker compose down
196+
@cd ./e2e/framework/maestro; $(DOCKER_COMPOSE) down
192197
@$(MAKE) k3d/down
193198
@echo "Maestro was deleted with success!"
194199

@@ -201,7 +206,7 @@ K3D_CLUSTER_NAME ?= maestro-dev
201206
.PHONY: k3d/up
202207
k3d/up: ## Create/Start the k3d cluster via docker-compose.
203208
@echo "INFO: Ensuring k3d service is up and cluster '$(K3D_CLUSTER_NAME)' is created via docker-compose..."
204-
@docker-compose up -d k3d
209+
@$(DOCKER_COMPOSE) up -d k3d
205210
@echo "INFO: Waiting for k3d cluster and kubeconfig file at ./e2e/framework/maestro/.k3d-kubeconfig.yaml..."
206211
@timeout=120; \
207212
interval=5; \
@@ -221,13 +226,13 @@ k3d/up: ## Create/Start the k3d cluster via docker-compose.
221226
.PHONY: k3d/down
222227
k3d/down: ## Delete the local k3d cluster and stop the k3d docker-compose service.
223228
@echo "INFO: Attempting to delete k3d cluster '$(K3D_CLUSTER_NAME)' via k3d service (if running)..."
224-
@if docker-compose ps k3d | grep -q "k3d"; then \
225-
docker-compose exec k3d k3d cluster delete $(K3D_CLUSTER_NAME) || echo "INFO: k3d cluster delete command failed or cluster was not found."; \
229+
@if $(DOCKER_COMPOSE) ps k3d | grep -q "k3d"; then \
230+
$(DOCKER_COMPOSE) exec k3d k3d cluster delete $(K3D_CLUSTER_NAME) || echo "INFO: k3d cluster delete command failed or cluster was not found."; \
226231
else \
227232
echo "INFO: k3d service not running, skipping cluster deletion command."; \
228233
fi
229234
@echo "INFO: Stopping and removing k3d service..."
230-
@docker-compose rm -sf k3d
235+
@$(DOCKER_COMPOSE) rm -sf k3d
231236
@echo "INFO: Removing k3d kubeconfig file..."
232237
@rm -f ./e2e/framework/maestro/.k3d-kubeconfig.yaml
233238
@echo "INFO: k3d cluster and service are down."

cmd/k3d/start.sh

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2021 TFG Co
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
#!/bin/sh
24+
25+
set -e
26+
27+
K3D_CLUSTER_NAME=${K3D_CLUSTER_NAME:-maestro-dev}
28+
KUBECONFIG_OUT_DIR="/kubeconfig-out"
29+
KUBECONFIG_FILE_PATH="$KUBECONFIG_OUT_DIR/.k3d-kubeconfig.yaml"
30+
KUBECONFIG_TMP_FILE_PATH="$KUBECONFIG_FILE_PATH.tmp"
31+
32+
# Check if cluster exists
33+
if ! k3d cluster get $K3D_CLUSTER_NAME > /dev/null 2>&1; then
34+
echo "INFO: k3d cluster '$K3D_CLUSTER_NAME' not found. Creating it now..."
35+
k3d cluster create $K3D_CLUSTER_NAME \
36+
--agents 1 \
37+
--port '38080:80@loadbalancer' \
38+
--api-port '127.0.0.1:6443' \
39+
--network 'k3d-maestro-dev' \
40+
--wait
41+
echo "INFO: k3d cluster '$K3D_CLUSTER_NAME' created successfully."
42+
else
43+
# Check if running, start if not
44+
if ! k3d cluster get $K3D_CLUSTER_NAME --no-headers 2>/dev/null | grep -q 'running'; then
45+
echo "INFO: k3d cluster '$K3D_CLUSTER_NAME' exists but is not running. Starting it..."
46+
k3d cluster start $K3D_CLUSTER_NAME --wait
47+
else
48+
echo "INFO: k3d cluster '$K3D_CLUSTER_NAME' already exists and is running."
49+
fi
50+
fi
51+
52+
echo "INFO: Exporting kubeconfig for cluster '$K3D_CLUSTER_NAME'..."
53+
mkdir -p $KUBECONFIG_OUT_DIR
54+
55+
# Get the kubeconfig and create two versions:
56+
# 1. Host-accessible version (for external tools)
57+
# 2. Container-internal version (for kubectl inside the container)
58+
k3d kubeconfig get $K3D_CLUSTER_NAME > $KUBECONFIG_TMP_FILE_PATH
59+
60+
# Create host-accessible version (external tools can use this)
61+
sed 's/server: https:\/\/127.0.0.1:6443/server: https:\/\/k3d-maestro-dev-serverlb:6443/g' $KUBECONFIG_TMP_FILE_PATH > $KUBECONFIG_FILE_PATH
62+
63+
# Create container-internal version (for kubectl inside the container)
64+
# This should point to the load balancer from within the k3d network
65+
cp $KUBECONFIG_TMP_FILE_PATH /root/.kube/config
66+
sed -i 's/server: https:\/\/127.0.0.1:6443/server: https:\/\/k3d-maestro-dev-serverlb:6443/g' /root/.kube/config
67+
68+
rm $KUBECONFIG_TMP_FILE_PATH
69+
70+
echo "INFO: Kubeconfig exported. k3d service ready and will keep running."
71+
echo "INFO: Container-internal kubeconfig configured at /root/.kube/config for kubectl access"
72+
echo " ---- KUBECONFIG START ---- "
73+
cat $KUBECONFIG_FILE_PATH
74+
echo " ---- KUBECONFIG END ---- "
75+
76+
# Keep container running
77+
tail -f /dev/null

docker-compose.yaml

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ services:
1111
- POSTGRES_USER=maestro
1212
- POSTGRES_PASSWORD=maestro
1313
healthcheck:
14-
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
14+
test: [ "CMD-SHELL", "pg_isready -U maestro" ]
1515
interval: 10s
1616
timeout: 10s
1717
retries: 5
@@ -28,42 +28,21 @@ services:
2828

2929
k3d:
3030
image: rancher/k3d:5.3.0
31-
command: >
32-
sh -c "
33-
K3D_CLUSTER_NAME=$${K3D_CLUSTER_NAME:-maestro-dev};
34-
if ! k3d cluster get $$K3D_CLUSTER_NAME > /dev/null 2>&1; then
35-
echo 'INFO: k3d cluster '$$K3D_CLUSTER_NAME' not found. Creating it now...';
36-
k3d cluster create $$K3D_CLUSTER_NAME \\
37-
--agents 1 \\
38-
--port '38080:80@loadbalancer' \\
39-
--api-port '127.0.0.1:6443' \\
40-
--wait;
41-
echo 'INFO: k3d cluster '$$K3D_CLUSTER_NAME' created successfully.';
42-
else
43-
# Check if running, start if not
44-
# Redirecting stderr for grep to avoid issues if cluster doesn't exist during check
45-
if ! k3d cluster get $$K3D_CLUSTER_NAME --no-headers 2>/dev/null | grep -q 'running'; then
46-
echo 'INFO: k3d cluster '$$K3D_CLUSTER_NAME' exists but is not running. Starting it...';
47-
k3d cluster start $$K3D_CLUSTER_NAME --wait;
48-
else
49-
echo 'INFO: k3d cluster '$$K3D_CLUSTER_NAME' already exists and is running.';
50-
fi
51-
fi &&
52-
echo 'INFO: Exporting kubeconfig for cluster '$$K3D_CLUSTER_NAME'...';
53-
mkdir -p /kubeconfig-out &&
54-
k3d kubeconfig get $$K3D_CLUSTER_NAME > /kubeconfig-out/.k3d-kubeconfig.yaml &&
55-
echo 'INFO: Kubeconfig exported. k3d service ready and will keep running.' &&
56-
echo ' ---- KUBECONFIG START ---- ' &&
57-
cat /kubeconfig-out/.k3d-kubeconfig.yaml &&
58-
echo ' ---- KUBECONFIG END ---- ' &&
59-
tail -f /dev/null
60-
"
31+
command: [ "/bin/sh", "/app/start.sh" ]
6132
volumes:
6233
- /var/run/docker.sock:/var/run/docker.sock
63-
- ./e2e/framework/maestro:/kubeconfig-out
34+
- ${PWD}/e2e/framework/maestro:/kubeconfig-out
35+
- ./cmd/k3d/start.sh:/app/start.sh
6436
environment:
6537
- K3D_CLUSTER_NAME=maestro-dev
38+
networks:
39+
- default
40+
- k3d
6641

6742
volumes:
6843
k3s-server: {}
6944
postgres: {}
45+
46+
networks:
47+
k3d:
48+
name: k3d-maestro-dev

docs/reference/Kubernetes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,11 @@ Maestro needs the following permissions for managing resources in a kubernetes c
9393
Maestro provides two ways for configuring kubernetes cluster access.
9494

9595
### Using inCluster mode
96-
Set `adapters.runtime.kubernetes.inCluster` config value to true or use its env var equivalent, the kubernetes client will be configured
96+
Set `adapters.runtime.kubernetes.inCluster` config value to true or use its env var equivalent, the kubernetes client will be configured
9797
automatically using the same _service account_ of the maestro component running pod.
9898

9999
The kubernetes client has a default rate limiter which implements a token bucket approach.
100-
The inCluster mode allows rate limit changes via `adapters.runtime.kubernetes.qps`
100+
The inCluster mode allows rate limit changes via `adapters.runtime.kubernetes.qps`
101101
and `adapters.runtime.kubernetes.burst` configs.
102102

103103
This mode is recommended to be used when running maestro components in the same cluster

e2e/framework/maestro/Dockerfile

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,32 @@
1919
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2020
#
2121

22-
FROM alpine:3
22+
FROM golang:1.23-alpine as builder
2323

24-
MAINTAINER TFG Co <backend@tfgco.com>
24+
WORKDIR /app
25+
26+
# Copy go.mod and go.sum files to download dependencies
27+
COPY go.mod ./
28+
COPY go.sum ./
29+
RUN go get ./...
30+
RUN go mod download
31+
32+
# Copy the entire source code
33+
COPY . .
34+
35+
# Build the binary statically, ensuring it includes our latest changes
36+
# The -a flag forces rebuilding of packages that are already up-to-date.
37+
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o ./maestro ./
38+
39+
# Stage 2: Create the final, minimal image
40+
FROM alpine:3.15
2541

2642
WORKDIR /app
2743

28-
COPY ./bin/maestro-linux-x86_64 /app/maestro
29-
COPY ./config /app/config
44+
# Copy only the compiled binary from the builder stage
45+
COPY --from=builder /app/maestro .
46+
# Copy the static configuration files
47+
COPY ./config ./config
3048

3149
ENTRYPOINT ["/app/maestro"]
3250
CMD ["--help"]

e2e/framework/maestro/docker-compose.yml

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ services:
44
build:
55
context: ../../..
66
dockerfile: ./e2e/framework/maestro/Dockerfile
7+
no_cache: true
78
environment:
89
- MAESTRO_ADAPTERS_ROOMSTORAGE_REDIS_URL=redis://redis:6379/0
910
- MAESTRO_ADAPTERS_SCHEDULERSTORAGE_POSTGRES_URL=postgres://maestro:maestro@postgres:5432/maestro?sslmode=disable
1011
- MAESTRO_ADAPTERS_OPERATIONFLOW_REDIS_URL=redis://redis:6379/0
1112
- MAESTRO_ADAPTERS_OPERATIONSTORAGE_REDIS_URL=redis://redis:6379/0
1213
- MAESTRO_ADAPTERS_OPERATIONLEASESTORAGE_REDIS_URL=redis://redis:6379/0
14+
- MAESTRO_ADAPTERS_RUNTIME_KUBERNETES_MASTERURL=
1315
- MAESTRO_INTERNALAPI_PORT=8081
1416
- MAESTRO_API_PORT=8080
1517
ports:
@@ -21,14 +23,19 @@ services:
2123
condition: service_healthy
2224
redis:
2325
condition: service_healthy
26+
networks:
27+
- default
28+
- k3d
2429

2530
rooms-api:
2631
build:
2732
context: ../../..
2833
dockerfile: ./e2e/framework/maestro/Dockerfile
34+
no_cache: true
2935
environment:
3036
- MAESTRO_ADAPTERS_ROOMSTORAGE_REDIS_URL=redis://redis:6379/0
3137
- MAESTRO_ADAPTERS_INSTANCESTORAGE_REDIS_URL=redis://redis:6379/0
38+
- MAESTRO_ADAPTERS_RUNTIME_KUBERNETES_MASTERURL=k3d-maestro-dev-serverlb:6443
3239
- MAESTRO_ADAPTERS_RUNTIME_KUBERNETES_KUBECONFIG=/kubeconfig/config
3340
- MAESTRO_ADAPTERS_SCHEDULERCACHE_REDIS_URL=redis://redis:6379/0
3441
- MAESTRO_ADAPTERS_SCHEDULERSTORAGE_POSTGRES_URL=postgres://maestro:maestro@postgres:5432/maestro?sslmode=disable
@@ -45,15 +52,20 @@ services:
4552
condition: service_healthy
4653
redis:
4754
condition: service_healthy
55+
networks:
56+
- default
57+
- k3d
4858

4959
runtime-watcher:
5060
build:
5161
context: ../../..
5262
dockerfile: ./e2e/framework/maestro/Dockerfile
63+
no_cache: true
5364
environment:
5465
- MAESTRO_ADAPTERS_SCHEDULERSTORAGE_POSTGRES_URL=postgres://maestro:maestro@postgres:5432/maestro?sslmode=disable
5566
- MAESTRO_ADAPTERS_ROOMSTORAGE_REDIS_URL=redis://redis:6379/0
5667
- MAESTRO_ADAPTERS_INSTANCESTORAGE_REDIS_URL=redis://redis:6379/0
68+
- MAESTRO_ADAPTERS_RUNTIME_KUBERNETES_MASTERURL=
5769
- MAESTRO_ADAPTERS_RUNTIME_KUBERNETES_KUBECONFIG=/kubeconfig/config
5870
- MAESTRO_ADAPTERS_SCHEDULERCACHE_REDIS_URL=redis://redis:6379/0
5971
- MAESTRO_INTERNALAPI_PORT=8061
@@ -62,18 +74,23 @@ services:
6274
volumes:
6375
- ./.k3d-kubeconfig.yaml:/kubeconfig/config:ro
6476
command: [start, runtime-watcher, -l, development]
77+
networks:
78+
- default
79+
- k3d
6580

6681
worker:
6782
build:
6883
context: ../../..
6984
dockerfile: ./e2e/framework/maestro/Dockerfile
85+
no_cache: true
7086
environment:
7187
- MAESTRO_ADAPTERS_SCHEDULERSTORAGE_POSTGRES_URL=postgres://maestro:maestro@postgres:5432/maestro?sslmode=disable
7288
- MAESTRO_ADAPTERS_OPERATIONFLOW_REDIS_URL=redis://redis:6379/0
7389
- MAESTRO_ADAPTERS_OPERATIONSTORAGE_REDIS_URL=redis://redis:6379/0
7490
- MAESTRO_ADAPTERS_ROOMSTORAGE_REDIS_URL=redis://redis:6379/0
7591
- MAESTRO_ADAPTERS_OPERATIONLEASESTORAGE_REDIS_URL=redis://redis:6379/0
7692
- MAESTRO_ADAPTERS_INSTANCESTORAGE_REDIS_URL=redis://redis:6379/0
93+
- MAESTRO_ADAPTERS_RUNTIME_KUBERNETES_MASTERURL=
7794
- MAESTRO_ADAPTERS_RUNTIME_KUBERNETES_KUBECONFIG=/kubeconfig/config
7895
- MAESTRO_ADAPTERS_RUNTIME_KUBERNETES_TOPOLOGYSPREADCONSTRAINT_ENABLED=false
7996
- MAESTRO_ADAPTERS_SCHEDULERCACHE_REDIS_URL=redis://redis:6379/0
@@ -90,6 +107,9 @@ services:
90107
condition: service_healthy
91108
redis:
92109
condition: service_healthy
110+
networks:
111+
- default
112+
- k3d
93113

94114
postgres:
95115
image: postgres:17-alpine
@@ -100,10 +120,12 @@ services:
100120
- POSTGRES_USER=maestro
101121
- POSTGRES_PASSWORD=maestro
102122
healthcheck:
103-
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
123+
test: [ "CMD-SHELL", "pg_isready -U maestro" ]
104124
interval: 10s
105125
timeout: 10s
106126
retries: 5
127+
networks:
128+
- default
107129

108130
redis:
109131
image: redis:8.0-alpine
@@ -114,6 +136,14 @@ services:
114136
interval: 10s
115137
timeout: 10s
116138
retries: 5
139+
networks:
140+
- default
117141

118142
volumes:
119143
eventsproto: {}
144+
145+
networks:
146+
default:
147+
k3d:
148+
name: k3d-maestro-dev
149+
external: true

0 commit comments

Comments
 (0)