# Dedicated licensed bulk service. Keep the Service internal unless an authenticated # API gateway is placed in front of it. apiVersion: apps/v1 kind: Deployment metadata: name: ai-disclosure-bulk labels: app.kubernetes.io/name: ai-disclosure-bulk app.kubernetes.io/version: "2.0.2" spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1 selector: matchLabels: app.kubernetes.io/name: ai-disclosure-bulk template: metadata: labels: app.kubernetes.io/name: ai-disclosure-bulk app.kubernetes.io/version: "2.0.2" annotations: prometheus.io/scrape: "true" prometheus.io/port: "8080" prometheus.io/path: /metrics spec: automountServiceAccountToken: false securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: bulk image: ghcr.io/REPLACE_ME/ai-disclosure-standard-bulk:2.0.2 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 8080 env: - name: BASE_URL value: http://ai-disclosure-bulk - name: OUTPUT_BASE_URL value: https://ai.example.org - name: DEFAULT_LANGUAGE value: de - name: SERVICE_MODE value: bulk - name: REQUIRE_LICENSE value: "true" - name: API_ALLOWED_ORIGIN value: "" - name: LICENSE_TOKEN_FILE value: /run/secrets/license/token - name: LICENSE_MODE value: hybrid - name: LICENSE_SERVER_URL value: https://licenses.example.org - name: LICENSE_INSTANCE_ID valueFrom: fieldRef: fieldPath: metadata.uid - name: LICENSE_CACHE_FILE value: /data/license-lease.json - name: BULK_REQUIRE_API_KEY value: "true" - name: BULK_API_KEY_FILE value: /run/secrets/bulk/key - name: BULK_MAX_ITEMS value: "500" - name: BULK_MAX_BODY_BYTES value: "4194304" volumeMounts: - name: license-cache mountPath: /data - name: license-token mountPath: /run/secrets/license readOnly: true - name: bulk-api-key mountPath: /run/secrets/bulk readOnly: true resources: requests: cpu: 50m memory: 32Mi limits: cpu: "1" memory: 192Mi readinessProbe: httpGet: path: /readyz port: http initialDelaySeconds: 2 periodSeconds: 5 timeoutSeconds: 2 failureThreshold: 3 livenessProbe: httpGet: path: /healthz port: http initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 2 failureThreshold: 3 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"] volumes: - name: license-cache emptyDir: {} - name: license-token secret: secretName: ai-disclosure-commercial items: - key: license-token path: token - name: bulk-api-key secret: secretName: ai-disclosure-commercial items: - key: bulk-api-key path: key topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app.kubernetes.io/name: ai-disclosure-bulk --- apiVersion: v1 kind: Service metadata: name: ai-disclosure-bulk spec: type: ClusterIP selector: app.kubernetes.io/name: ai-disclosure-bulk ports: - name: http port: 80 targetPort: http --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: ai-disclosure-bulk spec: minAvailable: 2 selector: matchLabels: app.kubernetes.io/name: ai-disclosure-bulk --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: ai-disclosure-bulk spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: ai-disclosure-bulk minReplicas: 3 maxReplicas: 20 behavior: scaleDown: stabilizationWindowSeconds: 300 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 65