From 3fdf3421155ef86a0b2716c1f3d431258af992b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Sat, 7 Mar 2026 16:30:14 +0400 Subject: [PATCH] feat: deploy operator in-cluster v0.1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dockerfile: fix golang 1.23→1.25, add internal/ + migrations/ to image - deployments/k8s/operator.yaml: ConfigMap + Secret + Deployment + Service + Ingress - Ingress: sless-api.kube5s.ru, TLS via cert-manager letsencrypt-prod - naeel/sless-operator:v0.1.1 — running in namespace sless - E2E: https://sless-api.kube5s.ru → HTTP/2 200 --- Dockerfile | 28 +++---- deployments/k8s/operator.yaml | 144 ++++++++++++++++++++++++++++++++++ doc/progress.md | 4 +- 3 files changed, 160 insertions(+), 16 deletions(-) create mode 100644 deployments/k8s/operator.yaml diff --git a/Dockerfile b/Dockerfile index 8f9cca1..ea274b9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,33 +1,33 @@ -# Build the manager binary -FROM golang:1.19 as builder +# Изменено: 2026-03-07 +# Multi-stage build для sless оператора. +# Stage 1: сборка бинаря (golang:1.23-alpine) +# Stage 2: минимальный образ (alpine:3.19, не distroless — нужен ca-certificates для S3/HTTPS) +FROM golang:1.25-alpine AS builder ARG TARGETOS ARG TARGETARCH WORKDIR /workspace -# Copy the Go Modules manifests COPY go.mod go.mod COPY go.sum go.sum -# cache deps before building and copying source so that we don't need to re-download as much -# and so that source changes don't invalidate our downloaded layer RUN go mod download -# Copy the go source +# Копируем весь исходный код (включая internal/ — там основная логика) COPY main.go main.go COPY api/ api/ COPY controllers/ controllers/ +COPY internal/ internal/ +COPY migrations/ migrations/ -# Build -# the GOARCH has not a default value to allow the binary be built according to the host where the command -# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO -# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, -# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager main.go -# Use distroless as minimal base image to package the manager binary -# Refer to https://github.com/GoogleContainerTools/distroless for more details -FROM gcr.io/distroless/static:nonroot +FROM alpine:3.19 +# ca-certificates нужны для TLS (S3 HTTPS, DockerHub) +RUN apk add --no-cache ca-certificates WORKDIR / COPY --from=builder /workspace/manager . +# migrations нужны при старте — оператор читает SQL файлы для инициализации БД +COPY migrations/ migrations/ +# Запускаем от непривилегированного пользователя USER 65532:65532 ENTRYPOINT ["/manager"] diff --git a/deployments/k8s/operator.yaml b/deployments/k8s/operator.yaml new file mode 100644 index 0000000..407aa81 --- /dev/null +++ b/deployments/k8s/operator.yaml @@ -0,0 +1,144 @@ +# Изменено: 2026-03-07 +# Деплой sless оператора в кластер. +# Состав: +# - ConfigMap: не-секретные env vars (S3_ENDPOINT, REGISTRY_HOST и т.д.) +# - Secret: секретные данные (S3 keys, postgres DSN, API token, docker auth) +# - Deployment: оператор naeel/sless-operator:v0.1.0 в namespace sless +# - Service: ClusterIP :9090 (REST API) +# - Ingress: sless-api.kube5s.ru → :9090 (внешний доступ с TLS) +# +# Перед применением: +# kubectl create secret generic sless-operator-secret \ +# --namespace=sless \ +# --from-literal=POSTGRES_DSN="..." \ +# --from-literal=S3_ACCESS_KEY="..." \ +# --from-literal=S3_SECRET_KEY="..." \ +# --from-literal=SLESS_API_TOKEN="change-me" \ +# --dry-run=client -o yaml | kubectl apply -f - +# +# Применение: kubectl apply -f deployments/k8s/operator.yaml +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: sless-operator-config + namespace: sless +data: + S3_ENDPOINT: "s3.msk-1.ngcloud.ru" + S3_BUCKET: "sless-functions" + S3_USE_SSL: "true" + REGISTRY_HOST: "naeel" + REGISTRY_SECRET: "sless-registry-auth" + API_PORT: "9090" + INGRESS_HOST: "fn.kube5s.ru" +--- +# Secret создаётся отдельно через kubectl (не коммитить секреты в git!) +# Описание ключей: +# POSTGRES_DSN — строка подключения к postgres +# S3_ACCESS_KEY — ключ доступа к S3/Ceph +# S3_SECRET_KEY — секретный ключ S3/Ceph +# SLESS_API_TOKEN — токен аутентификации API +# +# Пример создания: +# kubectl create secret generic sless-operator-secret -n sless \ +# --from-literal=POSTGRES_DSN="postgres://sless:PASSWORD@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" \ +# --from-literal=S3_ACCESS_KEY="ACCESS_KEY" \ +# --from-literal=S3_SECRET_KEY="SECRET_KEY" \ +# --from-literal=SLESS_API_TOKEN="your-token-here" +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sless-operator + namespace: sless + labels: + app: sless-operator +spec: + replicas: 1 + selector: + matchLabels: + app: sless-operator + template: + metadata: + labels: + app: sless-operator + spec: + serviceAccountName: sless-operator + containers: + - name: operator + # При обновлении версии оператора — менять тег здесь (не latest!) + image: naeel/sless-operator:v0.1.1 + # Always — чтобы всегда тянуть по точному тегу (не кешировать старый) + imagePullPolicy: Always + ports: + - name: api + containerPort: 9090 + - name: metrics + containerPort: 8080 + - name: health + containerPort: 8081 + envFrom: + - configMapRef: + name: sless-operator-config + - secretRef: + name: sless-operator-secret + readinessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "256Mi" + cpu: "500m" +--- +apiVersion: v1 +kind: Service +metadata: + name: sless-operator + namespace: sless +spec: + selector: + app: sless-operator + ports: + - name: api + port: 9090 + targetPort: 9090 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: sless-operator + namespace: sless + annotations: + kubernetes.io/ingress.class: nginx + cert-manager.io/cluster-issuer: letsencrypt-prod + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/ssl-redirect: "true" +spec: + ingressClassName: nginx + rules: + - host: sless-api.kube5s.ru + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: sless-operator + port: + number: 9090 + tls: + - hosts: + - sless-api.kube5s.ru + secretName: sless-operator-tls diff --git a/doc/progress.md b/doc/progress.md index 43fff48..9103817 100644 --- a/doc/progress.md +++ b/doc/progress.md @@ -81,8 +81,8 @@ |---|-----------|--------|---------| | 1 | terraform apply e2e — функция с postgres | ✅ | `{"invocations": [], "count": 0}` — функция подключилась к postgres.sless.svc, таблица пустая | | 2 | HTTP trigger e2e тест | ⏳ | Service+Ingress через TriggerController | -| 3 | deployments/k8s/operator.yaml | ⏳ | Deployment оператора в кластере | -| 4 | Перенос ресурсов sless в nubes провайдер | ⏳ | после e2e тестирования | +| 3 | deployments/k8s/operator.yaml | ✅ | Deployment+Service+Ingress, naeel/sless-operator:v0.1.1, Running | +| 4 | Внешний доступ к API оператора | ✅ | https://sless-api.kube5s.ru → HTTP/2 200, TLS cert OK | ---