bascule-oss/charts/bascule/templates/deployment.yaml
Tyler King 9dc5cb9eee feat: Kubernetes native integration — Helm chart + K8s/SPIFFE config
Helm chart (charts/bascule/):
  Deployment with shell sidecar container (shared jumphost model)
  Service (LoadBalancer/NodePort/ClusterIP)
  ConfigMap with auto-generated config.toml
  RBAC (Role + RoleBinding for pods/exec)
  NetworkPolicy (restrict shell egress, allow DNS + K8s API)
  ServiceAccount with create flag
  Configurable shell image (k8s-ops, net-ops, dev, minimal)
  Helm lint passes clean

K8s backend config (bascule-core):
  [k8s] section: enabled, namespace, pod_name, shell_container, shell
  Auto-detection via POD_NAME/POD_NAMESPACE env vars (downward API)
  Backend priority: K8s > proxy > container > local PTY
  K8s exec implementation deferred to --features k8s (kube crate)

SPIFFE/SPIRE auth config:
  [auth.spiffe] section: trust_domain, trust_bundle_path, workload_api_socket
  JWT-SVID token-as-password authentication pattern
  Implementation deferred to bascule-auth-spiffe crate

Zero substrate dependencies. Default build unchanged.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 10:23:09 -04:00

102 lines
3.2 KiB
YAML

apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "bascule.fullname" . }}
labels:
{{- include "bascule.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "bascule.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "bascule.selectorLabels" . | nindent 8 }}
spec:
serviceAccountName: {{ include "bascule.serviceAccountName" . }}
containers:
- name: bascule
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: ssh
containerPort: 2222
protocol: TCP
env:
- name: BASCULE_CONFIG
value: /etc/bascule/config.toml
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: BASCULE_SHELL_CONTAINER
value: shell
{{- range .Values.extraEnv }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
volumeMounts:
- name: config
mountPath: /etc/bascule
readOnly: true
{{- if .Values.hostKey.persistence }}
- name: hostkey
mountPath: /var/lib/bascule
{{- end }}
{{- if .Values.auth.authorizedKeysSecret }}
- name: authorized-keys
mountPath: /etc/bascule/keys
readOnly: true
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
livenessProbe:
tcpSocket:
port: ssh
initialDelaySeconds: 5
periodSeconds: 30
readinessProbe:
tcpSocket:
port: ssh
initialDelaySeconds: 3
periodSeconds: 10
{{- if .Values.shell.enabled }}
- name: shell
image: "{{ .Values.shell.image.repository }}:{{ .Values.shell.image.tag }}"
imagePullPolicy: {{ .Values.shell.image.pullPolicy }}
command: ["sleep", "infinity"]
resources:
{{- toYaml .Values.shell.resources | nindent 12 }}
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
add: ["SETUID", "SETGID"]
{{- end }}
volumes:
- name: config
configMap:
name: {{ include "bascule.fullname" . }}-config
{{- if .Values.hostKey.persistence }}
- name: hostkey
emptyDir: {}
{{- end }}
{{- if .Values.auth.authorizedKeysSecret }}
- name: authorized-keys
secret:
secretName: {{ .Values.auth.authorizedKeysSecret }}
defaultMode: 0600
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}