mirror of
https://github.com/OpenStaticFish/MicroServices.git
synced 2026-10-13 06:35:12 +00:00
Initialize Tilt-based local dev setup
This commit is contained in:
+31
@@ -0,0 +1,31 @@
|
||||
# Local environment
|
||||
.direnv/
|
||||
.envrc
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Nix build outputs
|
||||
result
|
||||
result-*
|
||||
|
||||
# Tilt local state
|
||||
.tiltbuild/
|
||||
.tiltignore.local
|
||||
|
||||
# Kubernetes local config dumps
|
||||
kubeconfig
|
||||
*.kubeconfig
|
||||
|
||||
# Go build/test artifacts
|
||||
bin/
|
||||
dist/
|
||||
*.test
|
||||
*.out
|
||||
coverage.out
|
||||
|
||||
# Editor and OS noise
|
||||
.DS_Store
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
@@ -0,0 +1,29 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Repo Shape
|
||||
|
||||
- This repo is a minimal Nix + Kind + Tilt local Kubernetes setup, not a general Go monorepo yet.
|
||||
- The only app is `services/hello-world`, a Go 1.22 HTTP service built by `services/hello-world/Dockerfile` and deployed by `k8s/hello-world.yaml`.
|
||||
- `Tiltfile` is the wiring source of truth for dev orchestration; `flake.nix` is the source of truth for available CLI dependencies.
|
||||
|
||||
## Commands
|
||||
|
||||
- Use `nix run .#setup-kind` before Tilt if the cluster/context may not exist; it creates/selects the `kind-openstaticfish` context.
|
||||
- Use `nix run .#tilt -- up` instead of calling a bare `tilt` from outside `nix develop`; the wrapper adds `kind`, `kubectl`, and `docker` to `PATH` so Tilt can load images into Kind.
|
||||
- Use `nix run .#tilt -- down` to remove Tilt-managed resources.
|
||||
- Use `nix develop` when running repeated manual commands; inside it, `setup-kind`, `tilt`, `kubectl`, `docker`, and `go` are available.
|
||||
- Use `nix flake show` as the quick flake sanity check after editing `flake.nix`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Nix flakes only see git-tracked or staged files. After adding files referenced by the flake, Tiltfile, Dockerfile, or manifests, run `git add <file>` or `git add -A` before `nix run` verification.
|
||||
- `Tiltfile` intentionally allows only `kind-openstaticfish` via `allow_k8s_contexts`; do not switch it to a broad context unless explicitly requested.
|
||||
- Do not re-add `default_registry('localhost:5000')` unless a local registry is also created; this setup relies on Tilt loading images directly into Kind.
|
||||
- The hello-world Dockerfile intentionally copies only `go.mod`; there is no `go.sum` because the app currently has no external Go dependencies.
|
||||
- Docker must be running and reachable by the user before `setup-kind` or Tilt image builds can work.
|
||||
|
||||
## Verification
|
||||
|
||||
- For infra config changes, run `nix flake show`.
|
||||
- For cluster/Tilt changes, the focused path is `nix run .#setup-kind` then `nix run .#tilt -- up`, followed by `curl http://localhost:8080`.
|
||||
- There is no test, lint, formatter, CI, or pre-commit config in this repo yet; do not invent commands.
|
||||
@@ -0,0 +1,221 @@
|
||||
# OpenStaticFish MicroServices
|
||||
|
||||
Basic local Kubernetes development setup using Nix, Kind, Tilt, Docker, and a small Go hello-world service.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Nix with flakes enabled
|
||||
- Docker running and reachable by your user
|
||||
- Git
|
||||
|
||||
All project CLI dependencies are provided by `flake.nix`, including:
|
||||
|
||||
- `tilt`
|
||||
- `kind`
|
||||
- `kubectl`
|
||||
- `docker`
|
||||
- `helm`
|
||||
- `go`
|
||||
|
||||
## Quick Start
|
||||
|
||||
Create or select the local Kind cluster:
|
||||
|
||||
```bash
|
||||
nix run .#setup-kind
|
||||
```
|
||||
|
||||
Start Tilt:
|
||||
|
||||
```bash
|
||||
nix run .#tilt -- up
|
||||
```
|
||||
|
||||
Open the Tilt UI:
|
||||
|
||||
```text
|
||||
http://localhost:10350
|
||||
```
|
||||
|
||||
Test the hello-world service:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080
|
||||
```
|
||||
|
||||
Stop Tilt resources:
|
||||
|
||||
```bash
|
||||
nix run .#tilt -- down
|
||||
```
|
||||
|
||||
## Dev Shell
|
||||
|
||||
You can also enter the Nix development shell and run commands directly:
|
||||
|
||||
```bash
|
||||
nix develop
|
||||
```
|
||||
|
||||
Inside the shell:
|
||||
|
||||
```bash
|
||||
setup-kind
|
||||
tilt up
|
||||
tilt down
|
||||
kubectl get pods
|
||||
docker ps
|
||||
```
|
||||
|
||||
## Project Commands
|
||||
|
||||
### Nix Commands
|
||||
|
||||
```bash
|
||||
nix develop
|
||||
```
|
||||
|
||||
Enter the dev shell with all dependencies on `PATH`.
|
||||
|
||||
```bash
|
||||
nix run .#setup-kind
|
||||
```
|
||||
|
||||
Create the `openstaticfish` Kind cluster if needed, select the `kind-openstaticfish` Kubernetes context, and print cluster info.
|
||||
|
||||
```bash
|
||||
nix run .#tilt -- up
|
||||
```
|
||||
|
||||
Run Tilt with the required runtime tools available, including `kind`, `kubectl`, and `docker`.
|
||||
|
||||
```bash
|
||||
nix run .#tilt -- down
|
||||
```
|
||||
|
||||
Tear down Kubernetes resources managed by Tilt.
|
||||
|
||||
```bash
|
||||
nix flake show
|
||||
```
|
||||
|
||||
Validate and display flake outputs.
|
||||
|
||||
### Tilt Commands
|
||||
|
||||
```bash
|
||||
tilt up
|
||||
```
|
||||
|
||||
Build images, deploy Kubernetes manifests, start file watching, and open the Tilt UI.
|
||||
|
||||
```bash
|
||||
tilt down
|
||||
```
|
||||
|
||||
Remove deployed Tilt resources from the current Kubernetes context.
|
||||
|
||||
```bash
|
||||
tilt logs
|
||||
```
|
||||
|
||||
Stream aggregated logs from Tilt resources.
|
||||
|
||||
```bash
|
||||
tilt status
|
||||
```
|
||||
|
||||
Show current resource status.
|
||||
|
||||
```bash
|
||||
tilt ui
|
||||
```
|
||||
|
||||
Open the Tilt web UI.
|
||||
|
||||
### Kubernetes Commands
|
||||
|
||||
```bash
|
||||
kubectl config use-context kind-openstaticfish
|
||||
```
|
||||
|
||||
Select the project Kind cluster.
|
||||
|
||||
```bash
|
||||
kubectl cluster-info
|
||||
```
|
||||
|
||||
Verify Kubernetes connectivity.
|
||||
|
||||
```bash
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
List running pods.
|
||||
|
||||
```bash
|
||||
kubectl logs -f deployment/hello-world-deployment
|
||||
```
|
||||
|
||||
Stream logs from the hello-world deployment.
|
||||
|
||||
```bash
|
||||
kubectl get svc
|
||||
```
|
||||
|
||||
List Kubernetes services.
|
||||
|
||||
### Docker Commands
|
||||
|
||||
```bash
|
||||
docker ps
|
||||
```
|
||||
|
||||
List running containers, including Kind node containers.
|
||||
|
||||
```bash
|
||||
docker build -t hello-world ./services/hello-world
|
||||
```
|
||||
|
||||
Build the hello-world image manually outside Tilt.
|
||||
|
||||
## Layout
|
||||
|
||||
```text
|
||||
.
|
||||
├── flake.nix
|
||||
├── Tiltfile
|
||||
├── k8s/
|
||||
│ └── hello-world.yaml
|
||||
├── scripts/
|
||||
│ └── setup-kind
|
||||
└── services/
|
||||
└── hello-world/
|
||||
├── Dockerfile
|
||||
├── go.mod
|
||||
└── main.go
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
Nix flakes only see files that are tracked by Git. If `nix run` says a path is not visible to Nix, stage the file:
|
||||
|
||||
```bash
|
||||
git add <file>
|
||||
```
|
||||
|
||||
For this repo setup, staging all project files is usually enough:
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
```
|
||||
|
||||
The Tiltfile allows only the `kind-openstaticfish` Kubernetes context to avoid accidentally deploying to another cluster.
|
||||
|
||||
If Tilt reports that it cannot connect to Kubernetes, rerun:
|
||||
|
||||
```bash
|
||||
nix run .#setup-kind
|
||||
```
|
||||
|
||||
Then restart Tilt.
|
||||
@@ -0,0 +1,42 @@
|
||||
# --- OpenStaticFish MicroServices Tiltfile ---
|
||||
#
|
||||
# Nix-managed dependencies:
|
||||
# Run `nix develop` or use `nix run .#tilt -- up` to enter the dev shell
|
||||
# with tilt, kubectl, docker, and all other deps available.
|
||||
#
|
||||
# Quick reference:
|
||||
# nix run .#setup-kind - Create/select local Kind cluster
|
||||
# tilt up - Start all services (live reload enabled)
|
||||
# tilt down - Tear down all deployed resources
|
||||
# tilt ui - Open the Tilt web UI (default: http://localhost:10350)
|
||||
# tilt logs - Stream aggregated logs
|
||||
# tilt status - Show resource status
|
||||
|
||||
# --- Global Settings ---
|
||||
# Nix command wrapper:
|
||||
# nix run .#setup-kind
|
||||
#
|
||||
# This creates/selects the supported local Kind context below.
|
||||
allow_k8s_contexts('kind-openstaticfish')
|
||||
|
||||
# --- Hello World Service ---
|
||||
# Builds the Docker image and deploys the manifest with live reload
|
||||
docker_build('hello-world', './services/hello-world')
|
||||
|
||||
k8s_yaml('./k8s/hello-world.yaml')
|
||||
|
||||
# Watch source files for live reload
|
||||
k8s_resource(
|
||||
workload='hello-world-deployment',
|
||||
port_forwards='8080:8080',
|
||||
labels=['hello-world'],
|
||||
)
|
||||
|
||||
# --- Local Resources ---
|
||||
# Run a simple health check as a local resource
|
||||
local_resource(
|
||||
'health-check',
|
||||
cmd='curl -sf http://localhost:8080/health || echo "Service not ready"',
|
||||
resource_deps=['hello-world-deployment'],
|
||||
labels=['utility'],
|
||||
)
|
||||
Generated
+61
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1777826146,
|
||||
"narHash": "sha256-wQ/iN5Zp5VIa3ebBibijPnLyKhor+xEbDy4d0goa9Zs=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "73c703c22422b8951895a960959dbbaca7296492",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
{
|
||||
description = "OpenStaticFish MicroServices - Tilt development environment";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, flake-utils }:
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
setup-kind = pkgs.writeShellApplication {
|
||||
name = "setup-kind";
|
||||
runtimeInputs = with pkgs; [ docker kind kubectl ];
|
||||
text = ''
|
||||
exec bash ${./scripts/setup-kind} "$@"
|
||||
'';
|
||||
};
|
||||
tilt-dev = pkgs.writeShellApplication {
|
||||
name = "tilt-dev";
|
||||
runtimeInputs = with pkgs; [ docker kind kubectl tilt ];
|
||||
text = ''
|
||||
exec tilt "$@"
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
devShells.default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
# --- Core Dependencies ---
|
||||
tilt
|
||||
kubectl
|
||||
kubernetes-helm
|
||||
kind
|
||||
docker
|
||||
docker-compose
|
||||
|
||||
# --- Language Toolchain ---
|
||||
go
|
||||
|
||||
# --- Utilities ---
|
||||
curl
|
||||
jq
|
||||
yq-go
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
echo "🐟 OpenStaticFish MicroServices Dev Shell"
|
||||
echo "-----------------------------------------"
|
||||
|
||||
# --- Tilt Commands ---
|
||||
# Create/select the local Kind cluster first:
|
||||
# setup-kind
|
||||
# nix run .#setup-kind
|
||||
#
|
||||
# Start the development environment:
|
||||
# tilt up
|
||||
# nix run .#tilt -- up
|
||||
#
|
||||
# Tear down resources:
|
||||
# tilt down
|
||||
#
|
||||
# View Tilt UI:
|
||||
# tilt ui
|
||||
#
|
||||
# Check Tilt version:
|
||||
# tilt version
|
||||
|
||||
# --- Kubernetes Commands ---
|
||||
# Check cluster connection:
|
||||
# kubectl cluster-info
|
||||
#
|
||||
# Select the project Kind cluster:
|
||||
# kubectl config use-context kind-openstaticfish
|
||||
#
|
||||
# List running pods:
|
||||
# kubectl get pods
|
||||
#
|
||||
# View service logs:
|
||||
# kubectl logs -f deployment/hello-world
|
||||
|
||||
# --- Docker Commands ---
|
||||
# Build images manually:
|
||||
# docker build -t hello-world ./services/hello-world
|
||||
#
|
||||
# List running containers:
|
||||
# docker ps
|
||||
|
||||
echo ""
|
||||
echo "Available commands:"
|
||||
echo " setup-kind - Create/select local Kind cluster"
|
||||
echo " tilt up - Start dev environment"
|
||||
echo " tilt down - Stop dev environment"
|
||||
echo " kubectl ... - Interact with k8s cluster"
|
||||
echo " docker ... - Interact with containers"
|
||||
echo ""
|
||||
'';
|
||||
};
|
||||
|
||||
# --- Command wrappers ---
|
||||
# Run with: nix run .#setup-kind
|
||||
# Run with: nix run .#tilt -- up
|
||||
apps = {
|
||||
setup-kind = {
|
||||
type = "app";
|
||||
program = "${setup-kind}/bin/setup-kind";
|
||||
};
|
||||
|
||||
tilt = {
|
||||
type = "app";
|
||||
program = "${tilt-dev}/bin/tilt-dev";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
# --- Hello World Kubernetes Manifests ---
|
||||
# Managed by Tilt - run `tilt up` to deploy
|
||||
# Tear down with: `tilt down`
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: hello-world-deployment
|
||||
labels:
|
||||
app: hello-world
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: hello-world
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: hello-world
|
||||
spec:
|
||||
containers:
|
||||
- name: hello-world
|
||||
image: hello-world
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: PORT
|
||||
value: "8080"
|
||||
resources:
|
||||
requests:
|
||||
memory: "32Mi"
|
||||
cpu: "50m"
|
||||
limits:
|
||||
memory: "64Mi"
|
||||
cpu: "100m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 5
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: hello-world-service
|
||||
spec:
|
||||
selector:
|
||||
app: hello-world
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
type: ClusterIP
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cluster_name="openstaticfish"
|
||||
|
||||
if ! docker info >/dev/null 2>&1; then
|
||||
echo "Docker is not running or is not reachable. Start Docker, then rerun setup-kind."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if kind get clusters | grep -qx "$cluster_name"; then
|
||||
echo "Kind cluster '$cluster_name' already exists."
|
||||
else
|
||||
kind create cluster --name "$cluster_name"
|
||||
fi
|
||||
|
||||
kubectl config use-context "kind-$cluster_name"
|
||||
kubectl cluster-info
|
||||
@@ -0,0 +1 @@
|
||||
hello-world
|
||||
@@ -0,0 +1,14 @@
|
||||
# --- Hello World Service Dockerfile ---
|
||||
# Multi-stage build for minimal image size
|
||||
|
||||
FROM golang:1.22-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY go.mod ./
|
||||
COPY . .
|
||||
RUN CGO_ENABLED=0 go build -o /hello-world .
|
||||
|
||||
FROM alpine:3.19
|
||||
RUN apk --no-cache add ca-certificates
|
||||
COPY --from=builder /hello-world /hello-world
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["/hello-world"]
|
||||
@@ -0,0 +1,3 @@
|
||||
module github.com/openstaticfish/microservices/hello-world
|
||||
|
||||
go 1.22
|
||||
@@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = "8080"
|
||||
}
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"message": "Hello from OpenStaticFish!",
|
||||
"service": "hello-world",
|
||||
})
|
||||
})
|
||||
|
||||
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprint(w, "ok")
|
||||
})
|
||||
|
||||
log.Printf("hello-world listening on :%s", port)
|
||||
log.Fatal(http.ListenAndServe(":"+port, nil))
|
||||
}
|
||||
Reference in New Issue
Block a user