apiVersion: apps/v1 kind: Deployment metadata: name: api-gateway namespace: api labels: app: api-gateway component: gateway spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 selector: matchLabels: app: api-gateway template: metadata: labels: app: api-gateway component: gateway # Required by the llm-serving-default-deny NetworkPolicy, which admits # only pods labelled llm-client=true (from any namespace) on port 8080. # Without it every upstream dial times out and dispatch returns 502. llm-client: "true" annotations: reloader.stakater.com/auto: "true" prometheus.io/scrape: "true" prometheus.io/port: "8080" prometheus.io/path: "/metrics" spec: serviceAccountName: api-gateway # The registry at forgejo.riotpiao.com requires auth — /v2/ answers 401. # This Secret must exist in the api namespace before the first rollout. imagePullSecrets: - name: forgejo-registry securityContext: runAsNonRoot: true # 65532 is distroless's nonroot user, matching USER in the Dockerfile. runAsUser: 65532 fsGroup: 65532 containers: - name: gateway # Tag is pinned in kustomization.yaml so there is exactly one place to # bump it. Never :latest — Argo cannot make a deterministic rollout # decision from a mutable tag, and 6.1 requires SHA tags. image: forgejo.riotpiao.com/rock/api-gateway:latest imagePullPolicy: Always ports: - name: http containerPort: 8080 protocol: TCP env: - name: LISTEN_ADDR value: "0.0.0.0:8080" - name: CONFIG_PATH value: "/etc/gateway/config.yaml" - name: SHUTDOWN_TIMEOUT value: "5m" - name: LOG_LEVEL value: "info" # OpenTelemetry tracing configuration - name: OTEL_EXPORTER_OTLP_ENDPOINT value: "otel-collector.tracing.svc.cluster.local:4317" - name: OTEL_SERVICE_NAME value: "api-gateway" - name: OTEL_SERVICE_VERSION value: "1.0.0" - name: OTEL_ENVIRONMENT value: "production" volumeMounts: - name: config mountPath: /etc/gateway readOnly: true livenessProbe: httpGet: path: /healthz port: http scheme: HTTP initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 2 failureThreshold: 3 readinessProbe: httpGet: path: /readyz port: http scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 2 failureThreshold: 2 resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 512Mi securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 65532 capabilities: drop: - ALL volumes: - name: config secret: secretName: api-gateway-config affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - api-gateway topologyKey: kubernetes.io/hostname terminationGracePeriodSeconds: 300