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/{id}/status", web::get().to(project_status))
|
||||
})
|
||||
.bind(("127.0.0.1", port))?
|
||||
.bind(("0.0.0.0", port))?
|
||||
.run()
|
||||
.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