From f8d80213b2f8cf1b015bd64c22fa0e21da8e4c57 Mon Sep 17 00:00:00 2001 From: joshuaaferguson Date: Tue, 28 Apr 2026 08:31:14 -0700 Subject: [PATCH] chore(deploy): remove v1 kubernetes-controller from chart, CI, scripts, docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v1 controller was replaced by the K8s Agent in v2.0 but its dead config persisted across the deployment surface. Atomic removal of the remaining references now that the v2 architecture is the only path: Helm chart (chart/): - Delete templates/controller-deployment.yaml (whole file was guarded on `controller.enabled` which defaulted to false) - Remove controller PDB block from templates/pdb.yaml - Remove controller NetworkPolicy block from templates/networkpolicy.yaml - Remove controller ClusterRole + ClusterRoleBinding + SA from templates/rbac.yaml (the K8s Agent has its own RBAC bundle) - Remove controller ServiceMonitor from templates/servicemonitor.yaml - Remove streamspace.controller.labels / .serviceAccountName / .image helper defines from templates/_helpers.tpl - Trim NOTES.txt: remove the v1-controller upgrade-path stanza, point metrics port-forward at the api service instead of the dead controller service - Delete `controller:` values block (~75 lines) and the `networkPolicy.controller` sub-block from values.yaml CI workflows (.github/workflows/): - Drop kubernetes-controller from release.yml's release-notes image list and from its docker-scan matrix; add k8s-agent in its place - Replace kubernetes-controller in security-scan.yml's trivy matrix with the two real v2 agents (k8s-agent, docker-agent) Scripts: - scripts/local-deploy.sh: update the comment at the image-existence check from "K8s Agent REPLACES kubernetes-controller" to read in the past tense (the v1 controller was removed in v2) Docs: - docs/TROUBLESHOOTING.md: clarify the controller is fully removed, not just disabled-by-default Verified: - `helm lint chart/` exits clean - `helm template streamspace chart/` renders 806 lines (was 872 before; the 66-line shrinkage is the dead-config removal) Out of scope here (cleaned in fix/docker-compose-v2-agents branch): - scripts/local-build.sh KUBERNETES_CONTROLLER_IMAGE variable + grep filter + case branch — touched there to avoid cross-branch conflict --- .github/workflows/release.yml | 5 +- .github/workflows/security-scan.yml | 8 +- chart/templates/NOTES.txt | 19 +--- chart/templates/_helpers.tpl | 33 ------ chart/templates/controller-deployment.yaml | 120 --------------------- chart/templates/networkpolicy.yaml | 49 --------- chart/templates/pdb.yaml | 21 ---- chart/templates/rbac.yaml | 62 +---------- chart/templates/servicemonitor.yaml | 25 ----- chart/values.yaml | 90 +--------------- docs/TROUBLESHOOTING.md | 3 +- scripts/local-deploy.sh | 2 +- 12 files changed, 22 insertions(+), 415 deletions(-) delete mode 100644 chart/templates/controller-deployment.yaml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 79c3d131..94471721 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -87,15 +87,14 @@ jobs: All images are available for both \`linux/amd64\` and \`linux/arm64\` platforms: - - Kubernetes Controller: \`ghcr.io/${{ github.repository_owner }}/streamspace-kubernetes-controller:${{ steps.version.outputs.VERSION }}\` - API: \`ghcr.io/${{ github.repository_owner }}/streamspace-api:${{ steps.version.outputs.VERSION }}\` - UI: \`ghcr.io/${{ github.repository_owner }}/streamspace-ui:${{ steps.version.outputs.VERSION }}\` + - K8s Agent: \`ghcr.io/${{ github.repository_owner }}/streamspace-k8s-agent:${{ steps.version.outputs.VERSION }}\` ## Documentation - [Installation Guide](https://github.com/${{ github.repository }}/blob/main/README.md) - [Architecture Docs](https://github.com/${{ github.repository }}/blob/main/docs/ARCHITECTURE.md) - - [Controller Guide](https://github.com/${{ github.repository }}/blob/main/docs/CONTROLLER_GUIDE.md) - [Helm Chart README](https://github.com/${{ github.repository }}/blob/main/chart/README.md) ## Upgrade Instructions @@ -171,7 +170,7 @@ jobs: needs: release strategy: matrix: - component: [kubernetes-controller, api, ui] + component: [api, ui, k8s-agent] steps: - name: Extract version id: version diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index 21815a19..f30ec487 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - component: [api, ui, kubernetes-controller] + component: [api, ui, k8s-agent, docker-agent] steps: - name: Checkout code uses: actions/checkout@v4 @@ -35,8 +35,10 @@ jobs: docker build -t streamspace-api:scan ./api elif [ "${{ matrix.component }}" = "ui" ]; then docker build -t streamspace-ui:scan ./ui - elif [ "${{ matrix.component }}" = "kubernetes-controller" ]; then - docker build -t streamspace-kubernetes-controller:scan ./k8s-controller + elif [ "${{ matrix.component }}" = "k8s-agent" ]; then + docker build -t streamspace-k8s-agent:scan ./agents/k8s-agent + elif [ "${{ matrix.component }}" = "docker-agent" ]; then + docker build -t streamspace-docker-agent:scan ./agents/docker-agent fi - name: Run Trivy vulnerability scanner diff --git a/chart/templates/NOTES.txt b/chart/templates/NOTES.txt index 635e3303..8f9ffced 100644 --- a/chart/templates/NOTES.txt +++ b/chart/templates/NOTES.txt @@ -114,21 +114,8 @@ Connection Status: kubectl logs -n {{ .Release.Namespace }} -l app.kubernetes.io/component=api \ | grep "Agent registered" -The K8s Agent connects to the Control Plane via WebSocket for session management. -This replaces the v1.x controller-based architecture. - -{{- else if .Values.controller.enabled }} - -⚙️ V1.X CONTROLLER ARCHITECTURE -──────────────────────────────────────────────────────────────────────────── - -StreamSpace is deployed with the v1.x Controller architecture. - -To upgrade to v2.0-beta agent architecture: - helm upgrade {{ .Release.Name }} {{ .Chart.Name }} \ - --reuse-values \ - --set k8sAgent.enabled=true \ - --set controller.enabled=false +The K8s Agent connects to the Control Plane via WebSocket for session +management. (The v1.x controller-based architecture was removed in v2.0.) {{- end }} @@ -147,7 +134,7 @@ To upgrade to v2.0-beta agent architecture: View metrics: kubectl port-forward -n {{ .Release.Namespace }} \ - svc/{{ include "streamspace.fullname" . }}-controller 8080:8080 + svc/{{ include "streamspace.fullname" . }}-api 8080:8080 curl http://localhost:8080/metrics diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl index 8ff70a56..51a3c178 100644 --- a/chart/templates/_helpers.tpl +++ b/chart/templates/_helpers.tpl @@ -51,14 +51,6 @@ app.kubernetes.io/name: {{ include "streamspace.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} -{{/* -Controller labels -*/}} -{{- define "streamspace.controller.labels" -}} -{{ include "streamspace.labels" . }} -app.kubernetes.io/component: controller -{{- end }} - {{/* API labels */}} @@ -91,17 +83,6 @@ PostgreSQL labels app.kubernetes.io/component: database {{- end }} -{{/* -Create the name of the controller service account to use -*/}} -{{- define "streamspace.controller.serviceAccountName" -}} -{{- if .Values.controller.serviceAccount.create }} -{{- default (printf "%s-controller" (include "streamspace.fullname" .)) .Values.controller.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.controller.serviceAccount.name }} -{{- end }} -{{- end }} - {{/* Create the name of the API service account to use */}} @@ -194,20 +175,6 @@ Get the PostgreSQL secret key for password {{- end }} {{- end }} -{{/* -Image name for controller -*/}} -{{- define "streamspace.controller.image" -}} -{{- $registry := .Values.global.imageRegistry | default .Values.controller.image.registry }} -{{- $repository := .Values.controller.image.repository }} -{{- $tag := .Values.controller.image.tag | default .Chart.AppVersion }} -{{- if $registry }} -{{- printf "%s/%s:%s" $registry $repository $tag }} -{{- else }} -{{- printf "%s:%s" $repository $tag }} -{{- end }} -{{- end }} - {{/* Image name for API */}} diff --git a/chart/templates/controller-deployment.yaml b/chart/templates/controller-deployment.yaml deleted file mode 100644 index 2134bdc4..00000000 --- a/chart/templates/controller-deployment.yaml +++ /dev/null @@ -1,120 +0,0 @@ -{{- if .Values.controller.enabled }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "streamspace.controller.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} - labels: - {{- include "streamspace.controller.labels" . | nindent 4 }} - {{- with .Values.controller.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "streamspace.fullname" . }}-controller - namespace: {{ .Release.Namespace }} - labels: - {{- include "streamspace.controller.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.controller.replicaCount }} - selector: - matchLabels: - {{- include "streamspace.selectorLabels" . | nindent 6 }} - app.kubernetes.io/component: controller - template: - metadata: - annotations: - {{- with .Values.controller.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "streamspace.selectorLabels" . | nindent 8 }} - app.kubernetes.io/component: controller - spec: - {{- with .Values.global.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "streamspace.controller.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.controller.podSecurityContext | nindent 8 }} - containers: - - name: controller - image: {{ include "streamspace.controller.image" . }} - imagePullPolicy: {{ .Values.controller.image.pullPolicy }} - command: - - /manager - args: - - --metrics-bind-address={{ .Values.controller.config.metricsBindAddress }} - - --health-probe-bind-address={{ .Values.controller.config.healthProbeBindAddress }} - {{- if and (gt (.Values.controller.replicaCount | int) 1) .Values.controller.leaderElection.enabled }} - - --leader-elect - {{- end }} - env: - - name: INGRESS_DOMAIN - value: {{ .Values.controller.config.ingressDomain | quote }} - - name: INGRESS_CLASS - value: {{ .Values.controller.config.ingressClass | quote }} - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: CONTROLLER_ID - value: {{ include "streamspace.fullname" . }}-controller-1 - ports: - - name: metrics - containerPort: 8080 - protocol: TCP - - name: health - containerPort: 8081 - protocol: TCP - resources: - {{- toYaml .Values.controller.resources | nindent 10 }} - livenessProbe: - httpGet: - path: /healthz - port: health - initialDelaySeconds: 15 - periodSeconds: 20 - readinessProbe: - httpGet: - path: /readyz - port: health - initialDelaySeconds: 5 - periodSeconds: 10 - securityContext: - {{- toYaml .Values.controller.securityContext | nindent 10 }} - {{- with .Values.controller.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.controller.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.controller.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ include "streamspace.fullname" . }}-controller - namespace: {{ .Release.Namespace }} - labels: - {{- include "streamspace.controller.labels" . | nindent 4 }} -spec: - type: {{ .Values.controller.service.type }} - ports: - - port: {{ .Values.controller.service.metricsPort }} - targetPort: metrics - protocol: TCP - name: metrics - selector: - {{- include "streamspace.selectorLabels" . | nindent 4 }} - app.kubernetes.io/component: controller -{{- end }} diff --git a/chart/templates/networkpolicy.yaml b/chart/templates/networkpolicy.yaml index cbc15c63..2fcd8baf 100644 --- a/chart/templates/networkpolicy.yaml +++ b/chart/templates/networkpolicy.yaml @@ -1,53 +1,4 @@ {{- if .Values.networkPolicy.enabled }} -{{- if .Values.controller.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "streamspace.fullname" . }}-controller - namespace: {{ .Release.Namespace }} - labels: - {{- include "streamspace.controller.labels" . | nindent 4 }} -spec: - podSelector: - matchLabels: - {{- include "streamspace.selectorLabels" . | nindent 6 }} - app.kubernetes.io/component: controller - policyTypes: - - Ingress - - Egress - ingress: - # Allow Prometheus to scrape metrics - - from: - - namespaceSelector: - matchLabels: - name: {{ .Values.networkPolicy.monitoring.namespace | default "observability" }} - ports: - - protocol: TCP - port: 8080 - egress: - # Allow access to Kubernetes API - - to: - - namespaceSelector: {} - podSelector: - matchLabels: - component: apiserver - ports: - - protocol: TCP - port: 443 - # Allow DNS - - to: - - namespaceSelector: - matchLabels: - name: kube-system - ports: - - protocol: UDP - port: 53 - # Allow all egress if not restricted - {{- if not .Values.networkPolicy.controller.restrictEgress }} - - {} - {{- end }} ---- -{{- end }} {{- if .Values.api.enabled }} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy diff --git a/chart/templates/pdb.yaml b/chart/templates/pdb.yaml index d58e7d78..aae208e4 100644 --- a/chart/templates/pdb.yaml +++ b/chart/templates/pdb.yaml @@ -1,24 +1,3 @@ -{{- if and .Values.controller.enabled .Values.controller.podDisruptionBudget.enabled }} -apiVersion: policy/v1 -kind: PodDisruptionBudget -metadata: - name: {{ include "streamspace.fullname" . }}-controller - namespace: {{ .Release.Namespace }} - labels: - {{- include "streamspace.controller.labels" . | nindent 4 }} -spec: - {{- if .Values.controller.podDisruptionBudget.minAvailable }} - minAvailable: {{ .Values.controller.podDisruptionBudget.minAvailable }} - {{- end }} - {{- if .Values.controller.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ .Values.controller.podDisruptionBudget.maxUnavailable }} - {{- end }} - selector: - matchLabels: - {{- include "streamspace.selectorLabels" . | nindent 6 }} - app.kubernetes.io/component: controller ---- -{{- end }} {{- if and .Values.api.enabled .Values.api.podDisruptionBudget.enabled }} apiVersion: policy/v1 kind: PodDisruptionBudget diff --git a/chart/templates/rbac.yaml b/chart/templates/rbac.yaml index 70485601..f5b94678 100644 --- a/chart/templates/rbac.yaml +++ b/chart/templates/rbac.yaml @@ -1,63 +1,9 @@ {{- if .Values.rbac.create }} --- -# Controller RBAC -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "streamspace.fullname" . }}-controller - labels: - {{- include "streamspace.controller.labels" . | nindent 4 }} -rules: - # Sessions and Templates CRDs - - apiGroups: ["stream.space"] - resources: ["sessions", "templates"] - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] - - apiGroups: ["stream.space"] - resources: ["sessions/status", "templates/status"] - verbs: ["get", "update", "patch"] - - apiGroups: ["stream.space"] - resources: ["sessions/finalizers", "templates/finalizers"] - verbs: ["update"] - - # Core resources - - apiGroups: [""] - resources: ["services", "persistentvolumeclaims"] - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] - - apiGroups: ["apps"] - resources: ["deployments"] - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] - - apiGroups: ["networking.k8s.io"] - resources: ["ingresses"] - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] - - # Events - - apiGroups: [""] - resources: ["events"] - verbs: ["create", "patch"] - - # Leader election - - apiGroups: [""] - resources: ["configmaps"] - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] - - apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "streamspace.fullname" . }}-controller - labels: - {{- include "streamspace.controller.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ include "streamspace.fullname" . }}-controller -subjects: - - kind: ServiceAccount - name: {{ include "streamspace.controller.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} ---- +# (v1 Controller RBAC removed in v2: ClusterRole, ClusterRoleBinding, and +# the controller ServiceAccount are no longer rendered. The K8s Agent has +# its own RBAC bundle (k8s-agent-rbac.yaml); the API only needs the +# namespaced Role/RoleBinding below for log streaming.) # API RBAC apiVersion: rbac.authorization.k8s.io/v1 kind: Role diff --git a/chart/templates/servicemonitor.yaml b/chart/templates/servicemonitor.yaml index a2189cae..77f4bf5b 100644 --- a/chart/templates/servicemonitor.yaml +++ b/chart/templates/servicemonitor.yaml @@ -1,29 +1,4 @@ {{- if and .Values.monitoring.enabled .Values.monitoring.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ include "streamspace.fullname" . }}-controller - namespace: {{ .Release.Namespace }} - labels: - {{- include "streamspace.controller.labels" . | nindent 4 }} - {{- with .Values.monitoring.serviceMonitor.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - selector: - matchLabels: - {{- include "streamspace.selectorLabels" . | nindent 6 }} - app.kubernetes.io/component: controller - endpoints: - - port: metrics - path: /metrics - interval: {{ .Values.monitoring.serviceMonitor.interval }} - scrapeTimeout: {{ .Values.monitoring.serviceMonitor.scrapeTimeout }} - {{- with .Values.monitoring.serviceMonitor.relabelings }} - relabelings: - {{- toYaml . | nindent 8 }} - {{- end }} ---- {{- if .Values.api.enabled }} apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor diff --git a/chart/values.yaml b/chart/values.yaml index a04c4ae4..3f74d8c4 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -11,88 +11,11 @@ global: # Storage class for all PVCs storageClass: "" -## StreamSpace Kubernetes Controller -## DEPRECATED: Controller is not needed in v2.0-beta architecture. -## In v2.0-beta, the API creates Session CRDs directly and dispatches commands to agents via WebSocket. -## The controller-based architecture was replaced by the agent-based architecture. -controller: - enabled: false # Disabled for v2.0-beta (agent-based architecture) - - image: - registry: ghcr.io - repository: streamspace-dev/streamspace-kubernetes-controller - tag: "v0.2.0" - pullPolicy: IfNotPresent - - # Number of controller replicas (use 3+ with leader election for HA) - replicaCount: 1 - - # Leader election for high availability - leaderElection: - enabled: false # Enable when replicaCount > 1 - - resources: - requests: - memory: 256Mi - cpu: 200m - limits: - memory: 512Mi - cpu: 1000m - - # Controller configuration - config: - # Ingress settings for created sessions - ingressDomain: streamspace.local - ingressClass: traefik - - # Metrics and health - metricsBindAddress: ":8080" - healthProbeBindAddress: ":8081" - - # Service for metrics - service: - type: ClusterIP - metricsPort: 8080 - - # Service account - serviceAccount: - create: true - annotations: {} - name: "" - - # Pod annotations - podAnnotations: - prometheus.io/scrape: "true" - prometheus.io/port: "8080" - prometheus.io/path: "/metrics" - - # Security context - podSecurityContext: - fsGroup: 65532 - runAsNonRoot: true - runAsUser: 65532 - - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - - # Node selector - nodeSelector: {} - - # Tolerations - tolerations: [] - - # Affinity - affinity: {} - - # Pod Disruption Budget - podDisruptionBudget: - enabled: false - minAvailable: 1 - # maxUnavailable: 1 +## (Removed in v2: the v1 Kubernetes controller was replaced by the K8s Agent +## below. Templates referencing .Values.controller and the old image +## streamspace-dev/streamspace-kubernetes-controller were deleted in the same +## change. If you're upgrading from v1, set k8sAgent.enabled=true and remove +## any --set controller.* flags.) ## K8s Agent (v2.0-beta) # The K8s Agent connects to the Control Plane and manages sessions on Kubernetes @@ -689,9 +612,6 @@ networkPolicy: # Monitoring namespace monitoring: namespace: observability - # Controller network restrictions - controller: - restrictEgress: false ## Common labels commonLabels: {} diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 000df1e7..a7e2ecc8 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -52,7 +52,8 @@ The Helm chart has been updated with the following changes: 1. **Removed v1.x Components:** - `chart/templates/nats.yaml` (122 lines) - v1.x event system - - `controller` now disabled by default + - `chart/templates/controller-deployment.yaml` and the `controller` + values block — fully removed (was disabled-by-default, now gone) 2. **Added v2.0 Components:** - `chart/templates/k8s-agent-deployment.yaml` (118 lines) diff --git a/scripts/local-deploy.sh b/scripts/local-deploy.sh index 360e8470..3e93c21f 100755 --- a/scripts/local-deploy.sh +++ b/scripts/local-deploy.sh @@ -76,7 +76,7 @@ check_images() { local missing_images=0 - # v2.0: K8s Agent REPLACES kubernetes-controller + # K8s Agent (the v1 kubernetes-controller was removed in v2) for image in "streamspace/streamspace-api" "streamspace/streamspace-ui" "streamspace/streamspace-k8s-agent"; do if docker images "${image}:${VERSION}" --format "{{.Repository}}:{{.Tag}}" | grep -q "${image}:${VERSION}"; then log_success "Found ${image}:${VERSION}"