Add K8s app deployment, Dockerfile, and CI workflow (Option A)
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
# Build artifacts
|
||||||
|
target/
|
||||||
|
*.rs.bk
|
||||||
|
|
||||||
|
# Version control
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# CI
|
||||||
|
.github/
|
||||||
|
.forgejo/
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
*.md
|
||||||
|
!README.md
|
||||||
|
|
||||||
|
# Tests (keep for build cache, exclude from runtime)
|
||||||
|
tests/
|
||||||
|
fixtures/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
log/
|
||||||
|
*.log
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
name: Build and Push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: forgejo.riotpiao.com
|
||||||
|
IMAGE_NAME: rock/poimen-memory
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Test
|
||||||
|
runs-on: rust
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cargo build --workspace
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: cargo test --all
|
||||||
|
|
||||||
|
build:
|
||||||
|
name: Build Image
|
||||||
|
runs-on: rust
|
||||||
|
needs: test
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
type=sha,prefix=
|
||||||
|
type=raw,value=latest
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
# Build stage
|
||||||
|
FROM rust:1.82-slim-bookworm AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
pkg-config \
|
||||||
|
libssl-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Copy manifests
|
||||||
|
COPY Cargo.toml Cargo.lock ./
|
||||||
|
COPY crates ./crates
|
||||||
|
|
||||||
|
# Build release binary
|
||||||
|
RUN cargo build --release --bin mem
|
||||||
|
|
||||||
|
# Runtime stage
|
||||||
|
FROM debian:bookworm-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install runtime dependencies
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
ca-certificates \
|
||||||
|
libssl3 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Copy binary from builder
|
||||||
|
COPY --from=builder /app/target/release/mem /usr/local/bin/mem
|
||||||
|
|
||||||
|
# Copy templates and queries
|
||||||
|
COPY templates ./templates
|
||||||
|
COPY queries ./queries
|
||||||
|
|
||||||
|
# Create non-root user
|
||||||
|
RUN useradd -r -u 1000 memuser
|
||||||
|
USER memuser
|
||||||
|
|
||||||
|
# Default port
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:8080/health || exit 1
|
||||||
|
|
||||||
|
# Default command: start HTTP server
|
||||||
|
ENTRYPOINT ["mem"]
|
||||||
|
CMD ["serve", "--port", "8080"]
|
||||||
@@ -48,7 +48,7 @@ pub async fn start_server(port: u16, api_key: String) -> Result<()> {
|
|||||||
.route("/memory/projects", web::get().to(projects_handler))
|
.route("/memory/projects", web::get().to(projects_handler))
|
||||||
.route("/memory/projects/{id}/status", web::get().to(project_status))
|
.route("/memory/projects/{id}/status", web::get().to(project_status))
|
||||||
})
|
})
|
||||||
.bind(("127.0.0.1", port))?
|
.bind(("0.0.0.0", port))?
|
||||||
.run()
|
.run()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
# Poimen Memory API Server
|
||||||
|
# Serves 7 HTTP endpoints for memory ingest, query, and management.
|
||||||
|
# Connects to memory-db (pgvector) for persistent storage.
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: poimen-memory
|
||||||
|
namespace: poimen
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: poimen-memory
|
||||||
|
app.kubernetes.io/component: api-server
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: poimen-memory
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: poimen-memory
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: memory
|
||||||
|
image: forgejo.riotpiao.com/rock/poimen-memory:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
env:
|
||||||
|
# Database connection (from CNPG auto-generated secret)
|
||||||
|
- name: DATABASE_HOST
|
||||||
|
value: "memory-db-rw.poimen.svc.cluster.local"
|
||||||
|
- name: DATABASE_PORT
|
||||||
|
value: "5432"
|
||||||
|
- name: DATABASE_NAME
|
||||||
|
value: "memory"
|
||||||
|
- name: DATABASE_USER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: memory-db-app
|
||||||
|
key: username
|
||||||
|
- name: DATABASE_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: memory-db-app
|
||||||
|
key: password
|
||||||
|
- name: DATABASE_URL
|
||||||
|
value: "postgresql://$(DATABASE_USER):$(DATABASE_PASSWORD)@$(DATABASE_HOST):$(DATABASE_PORT)/$(DATABASE_NAME)?sslmode=disable"
|
||||||
|
# LLM Gateway API key
|
||||||
|
- name: MEM_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: poimen-memory-secrets
|
||||||
|
key: llm-api-key
|
||||||
|
# Server config
|
||||||
|
- name: MEM_PORT
|
||||||
|
value: "8080"
|
||||||
|
- name: MEM_HOME
|
||||||
|
value: "/data"
|
||||||
|
args:
|
||||||
|
- serve
|
||||||
|
- --port
|
||||||
|
- "8080"
|
||||||
|
- --api-key
|
||||||
|
- "$(MEM_API_KEY)"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 30
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
emptyDir: {}
|
||||||
|
# Tolerate control-plane nodes
|
||||||
|
tolerations:
|
||||||
|
- key: node-role.kubernetes.io/control-plane
|
||||||
|
operator: Exists
|
||||||
|
effect: NoSchedule
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
namespace: poimen
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
# Secret managed separately (SealedSecret in homelab)
|
||||||
|
# - secrets.yaml
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Poimen Memory Secrets
|
||||||
|
# NOTE: In production, use SealedSecrets or ExternalSecrets.
|
||||||
|
# This is a placeholder - actual secret should be in homelab/k8s/argocd/secrets/
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: poimen-memory-secrets
|
||||||
|
namespace: poimen
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# LLM Gateway API key (Kong gateway)
|
||||||
|
llm-api-key: "REPLACE_WITH_ACTUAL_KEY"
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Poimen Memory API Service
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: poimen-memory
|
||||||
|
namespace: poimen
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: poimen-memory
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: poimen-memory
|
||||||
Reference in New Issue
Block a user