Files
bootnode/infra/k8s/api-deployment.yaml
zeekay 9d0957c774 ci: bootnode images go to ghcr.io/bootnode/bootnode (own org, not hanzoai)
bootnode is its own GitHub org — its images belong in its own GHCR namespace,
per the never-mix-registries rule. This also removes cross-org friction: the
repo's own GITHUB_TOKEN pushes to ghcr.io/bootnode/* (same org), so once the
arcd App is on the bootnode org, build+push needs no cross-org token.
2026-06-19 21:14:50 +00:00

247 lines
6.5 KiB
YAML

apiVersion: apps/v1
kind: Deployment
metadata:
name: bootnode-api
namespace: bootnode
labels:
app: bootnode-api
component: api
spec:
replicas: 3
selector:
matchLabels:
app: bootnode-api
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: bootnode-api
component: api
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8000"
prometheus.io/path: "/metrics"
spec:
serviceAccountName: bootnode-api
containers:
- name: api
image: ghcr.io/bootnode/bootnode:latest
imagePullPolicy: Always
ports:
- name: http
containerPort: 8000
protocol: TCP
env:
- name: APP_ENV
value: "production"
- name: ENVIRONMENT
value: "staging"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: DATABASE_URL
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: REDIS_URL
- name: DATASTORE_URL
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: DATASTORE_URL
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: JWT_SECRET
- name: API_KEY_SALT
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: API_KEY_SALT
# Hanzo KMS Configuration
- name: HANZO_KMS_URL
value: "https://kms.hanzo.ai"
- name: HANZO_KMS_ORG
value: "hanzo"
- name: HANZO_KMS_PROJECT
value: "bootnode"
- name: HANZO_KMS_ENV
value: "production"
- name: HANZO_KMS_CLIENT_ID
valueFrom:
secretKeyRef:
name: universal-auth-credentials
key: clientId
optional: true
- name: HANZO_KMS_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: universal-auth-credentials
key: clientSecret
optional: true
# Hanzo Commerce (Billing)
- name: HANZO_COMMERCE_URL
value: "https://commerce.hanzo.ai"
- name: HANZO_COMMERCE_API_KEY
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: COMMERCE_API_KEY
optional: true
- name: HANZO_COMMERCE_WEBHOOK_SECRET
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: COMMERCE_WEBHOOK_SECRET
optional: true
# Hanzo O11y (OTEL → shared Datastore)
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://otel-collector.hanzo.svc:4317"
- name: OTEL_SERVICE_NAME
value: "bootnode-api"
- name: OTEL_SERVICE_VERSION
value: "2.0.0"
- name: OTEL_ENABLED
value: "true"
# AI Chat (Hanzo AI Gateway at api.hanzo.ai)
- name: HANZO_AI_API_KEY
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: HANZO_AI_API_KEY
optional: true
# Hanzo IAM Configuration
- name: HANZO_IAM_URL
value: "https://hanzo.id"
- name: HANZO_IAM_ORG
value: "HANZO"
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2000m"
memory: "2Gi"
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 15
timeoutSeconds: 10
failureThreshold: 5
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 10
failureThreshold: 5
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
volumeMounts:
- name: tmp
mountPath: /tmp
imagePullSecrets:
- name: ghcr-secret
volumes:
- name: tmp
emptyDir: {}
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: bootnode-api
topologyKey: kubernetes.io/hostname
---
apiVersion: v1
kind: Service
metadata:
name: bootnode-api
namespace: bootnode
labels:
app: bootnode-api
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: http
protocol: TCP
selector:
app: bootnode-api
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: bootnode-api-hpa
namespace: bootnode
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: bootnode-api
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bootnode-api
namespace: bootnode
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: bootnode-api-pdb
namespace: bootnode
spec:
minAvailable: 2
selector:
matchLabels:
app: bootnode-api