diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py b/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py index 6455f47e..dee201f4 100755 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py @@ -233,7 +233,7 @@ class Grpc1(BaseModel): None, description="Hostname for the controller to use for the controller gRPC" ) routerHostname: Optional[str] = Field( - None, description="Hostname for the controller to use for the controller gRPC" + None, description="Hostname for the router to use for the router gRPC" ) endpoint: Optional[str] = Field( None, @@ -243,6 +243,9 @@ class Grpc1(BaseModel): None, description="The endpoints are passed down to the services to know where to announce the endpoints to the clients", ) + additionalRouters: dict[str, Router] | None = Field( + None, description="Additional routers to deploy" + ) ingress: Optional[Ingress] = None route: Optional[Route] = None nodeport: Optional[Nodeport] = None @@ -250,6 +253,14 @@ class Grpc1(BaseModel): tls: Optional[Tls] = None +class Router(BaseModel): + model_config = ConfigDict(extra="forbid") + hostname: str | None = None + endpoint: str | None = None + labels: dict[str, str] | None = None + nodeSelector: dict[str, str] | None = None + + class Model(BaseModel): model_config = ConfigDict(extra="forbid") diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yaml new file mode 100644 index 00000000..49cc0272 --- /dev/null +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yaml @@ -0,0 +1,111 @@ +{{ range $k, $v := .Values.grpc.additionalRouters }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: jumpstarter-router-{{ $k }} + namespace: {{ default $.Release.Namespace $.Values.namespace }} + labels: + control-plane: controller-router-{{ $k }} + app.kubernetes.io/name: jumpstarter-controller + {{ if $.Values.global.timestamp }} + deployment.timestamp: {{ $.Values.global.timestamp | quote }} + {{ end }} + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + selector: + matchLabels: + control-plane: controller-router-{{ $k }} + replicas: 1 + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: router + configmap-sha256: {{ include (print $.Template.BasePath "/cms/controller-cm.yaml") $ | sha256sum }} + labels: + control-plane: controller-router-{{ $k }} + {{ if $.Values.global.timestamp }} + deployment.timestamp: {{ $.Values.global.timestamp | quote }} + {{ end }} + spec: + # TODO(user): Uncomment the following code to configure the nodeAffinity expression + # according to the platforms which are supported by your solution. + # It is considered best practice to support multiple architectures. You can + # build your manager image using the makefile target docker-buildx. + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: kubernetes.io/arch + # operator: In + # values: + # - amd64 + # - arm64 + # - ppc64le + # - s390x + # - key: kubernetes.io/os + # operator: In + # values: + # - linux + {{ if $v.nodeSelector }} + nodeSelector: + {{ $v.nodeSelector | toYaml | indent 1 }} + {{ end }} + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - command: + - /router + env: + - name: GRPC_ROUTER_ENDPOINT + {{ if $v.endpoint }} + value: {{ $v.endpoint }} + {{ else if $v.hostname }} + value: {{ $v.hostname }}:{{ default 443 $.Values.grpc.tls.port }} + {{ else }} + value: router-{{ $k }}.{{ $.Values.global.baseDomain | required "set .global.baseDomain, or provide grpc.additionalRouters[...].endpoint/hostname" }}:{{ default 443 $.Values.grpc.tls.port }} + {{ end }} + - name: ROUTER_KEY + valueFrom: + secretKeyRef: + name: jumpstarter-router-secret + key: key + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + + image: {{ $.Values.image }}:{{ default $.Chart.AppVersion $.Values.tag }} + imagePullPolicy: {{ $.Values.imagePullPolicy }} + name: router + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" + # livenessProbe: + # httpGet: + # path: /healthz + # port: 8081 + # initialDelaySeconds: 15 + # periodSeconds: 20 + # readinessProbe: + # httpGet: + # path: /readyz + # port: 8081 + # initialDelaySeconds: 5 + # periodSeconds: 10 + resources: + limits: + cpu: 2000m + memory: 1024Mi + requests: + cpu: 1000m + memory: 256Mi + serviceAccountName: controller-manager + terminationGracePeriodSeconds: 10 +{{ end }} diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yaml new file mode 100644 index 00000000..92522341 --- /dev/null +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yaml @@ -0,0 +1,47 @@ +{{ if eq .Values.grpc.mode "ingress" }} +{{ range $k, $v := .Values.grpc.additionalRouters }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/backend-protocol: "GRPC" + nginx.ingress.kubernetes.io/proxy-read-timeout: "300" + nginx.ingress.kubernetes.io/proxy-send-timeout: "300" + {{ if eq $.Values.grpc.tls.mode "passthrough" }} + nginx.ingress.kubernetes.io/ssl-passthrough: "true" + {{ end }} + name: jumpstarter-router-ingress-{{ $k }} + namespace: {{ default $.Release.Namespace $.Values.namespace }} +spec: + {{ if $.Values.grpc.ingress.class }} + ingressClassName: {{ $.Values.grpc.ingress.class }} + {{ end }} + rules: + {{ if $v.hostname }} + - host: {{ $v.hostname }} + {{ else }} + - host: router-{{ $k }}.{{ $.Values.global.baseDomain | required "a global.baseDomain or a grpc.routerHostname must be provided"}} + {{ end }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: jumpstarter-router-grpc-{{ $k }} + port: + number: 8083 + tls: + - hosts: + {{ if $v.hostname }} + - {{ $v.hostname }} + {{ else }} + - router-{{ $k }}.{{ $.Values.global.baseDomain | required "a global.baseDomain or a grpc.routerHostname must be provided"}} + {{ end }} + {{ if $.Values.grpc.tls.routerCertSecret }} + secretName: {{ $.Values.grpc.tls.routerCertSecret }} + {{ end }} +{{ end }} +{{ end }} diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yaml new file mode 100644 index 00000000..b001804a --- /dev/null +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yaml @@ -0,0 +1,42 @@ +{{ if eq .Values.grpc.mode "route" }} +{{ range $k, $v := .Values.grpc.additionalRouters }} +--- +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + labels: + external-exposed: "true" + shard: external + annotations: + haproxy.router.openshift.io/timeout: 2d + haproxy.router.openshift.io/timeout-tunnel: 2d + name: jumpstarter-router-route-{{ $k }} + namespace: {{ default $.Release.Namespace $.Values.namespace }} +spec: + {{ if $v.hostname }} + host: {{ $v.hostname }} + {{ else }} + host: router-{{ $k }}.{{ $.Values.global.baseDomain | required "a global.baseDomain or a grpc.routerHostname must be provided"}} + {{ end }} + port: + targetPort: 8083 + tls: + {{ if eq $.Values.grpc.tls.mode "passthrough" }} + termination: passthrough + {{ end }} + {{ if eq $.Values.grpc.tls.mode "reencrypt" }} + termination: reencrypt + {{ end }} + insecureEdgeTerminationPolicy: None + {{ if $.Values.grpc.tls.routerCertSecret }} + externalCertificate: + name: {{ $.Values.grpc.tls.routerCertSecret }} + {{ end }} + + to: + kind: Service + name: jumpstarter-router-grpc-{{ $k }} + weight: 100 + wildcardPolicy: None +{{ end }} +{{ end }} diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yaml new file mode 100644 index 00000000..0b0de609 --- /dev/null +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yaml @@ -0,0 +1,27 @@ +{{ range $k, $v := .Values.grpc.additionalRouters }} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-router-{{ $k }} + app.kubernetes.io/name: jumpstarter-controller + name: jumpstarter-router-grpc-{{ $k }} + namespace: {{ default $.Release.Namespace $.Values.namespace }} +spec: + {{ if .Values.grpc.nodeport.enabled }} + type: NodePort + {{ end }} + + ports: + - name: grpc + port: 8083 + protocol: TCP + targetPort: 8083 + appProtocol: h2c # HTTP/2 over cleartext for gRPC (fixes edge termination in ingress/router) + {{ if .Values.grpc.nodeport.enabled }} + nodePort: {{ .Values.grpc.nodeport.routerPort }} + {{ end }} + selector: + control-plane: controller-router-{{ $k }} +{{ end }} diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml index 19c082b5..7f75608d 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml @@ -26,3 +26,17 @@ data: {{ else }} endpoint: router.{{ .Values.global.baseDomain }}:{{ .Values.grpc.tls.port }} {{ end }} + {{ range $k, $v := .Values.grpc.additionalRouters }} + {{ $k }}: + {{ if $v.endpoint }} + endpoint: {{ $v.endpoint }} + {{ else if $v.hostname }} + endpoint: {{ $v.hostname }}:{{ $.Values.grpc.tls.port }} + {{ else }} + endpoint: router-{{ $k }}.{{ $.Values.global.baseDomain }}:{{ $.Values.grpc.tls.port }} + {{ end }} + {{ if $v.labels }} + labels: + {{ $v.labels | toYaml | indent 1 }} + {{ end }} + {{ end }} diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml index 9b338ca2..55cce444 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml @@ -10,7 +10,6 @@ metadata: deployment.timestamp: {{ .Values.global.timestamp | quote }} {{ end }} annotations: - configmap-sha256: {{ include (print $.Template.BasePath "/cms/controller-cm.yaml") . | sha256sum }} argocd.argoproj.io/sync-wave: "1" spec: selector: @@ -21,6 +20,7 @@ spec: metadata: annotations: kubectl.kubernetes.io/default-container: manager + configmap-sha256: {{ include (print $.Template.BasePath "/cms/controller-cm.yaml") . | sha256sum }} labels: control-plane: controller-manager {{ if .Values.global.timestamp }} diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yaml index 675dc68d..b0390bd1 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yaml @@ -5,7 +5,7 @@ metadata: labels: app.kubernetes.io/name: jumpstarter-router name: leader-election-role - namespace: {{ .Values.namespace }} + namespace: {{ default .Release.Namespace .Values.namespace }} rules: - apiGroups: - "" diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yaml index a9fa9f44..d60dc3c9 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yaml @@ -3,7 +3,7 @@ kind: RoleBinding metadata: labels: app.kubernetes.io/name: jumpstarter-router - namespace: {{ .Values.namespace }} + namespace: {{ default .Release.Namespace .Values.namespace }} name: leader-election-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io @@ -12,4 +12,4 @@ roleRef: subjects: - kind: ServiceAccount name: controller-manager - namespace: {{ .Values.namespace }} + namespace: {{ default .Release.Namespace .Values.namespace }} diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml index 2a5352f3..d128a358 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml @@ -10,7 +10,6 @@ metadata: deployment.timestamp: {{ .Values.global.timestamp | quote }} {{ end }} annotations: - configmap-sha256: {{ include (print $.Template.BasePath "/cms/controller-cm.yaml") . | sha256sum }} argocd.argoproj.io/sync-wave: "1" spec: selector: @@ -21,6 +20,7 @@ spec: metadata: annotations: kubectl.kubernetes.io/default-container: router + configmap-sha256: {{ include (print $.Template.BasePath "/cms/controller-cm.yaml") . | sha256sum }} labels: control-plane: controller-router {{ if .Values.global.timestamp }} diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.json b/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.json index 592cd3c7..2cc3fcfc 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.json +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.json @@ -319,7 +319,7 @@ } ], "default": null, - "description": "Hostname for the controller to use for the controller gRPC", + "description": "Hostname for the router to use for the router gRPC", "title": "Routerhostname" }, "endpoint": { @@ -348,6 +348,22 @@ "description": "The endpoints are passed down to the services to know where to announce the endpoints to the clients", "title": "Routerendpoint" }, + "additionalRouters": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/$defs/Router" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Additional routers to deploy", + "title": "Additionalrouters" + }, "ingress": { "anyOf": [ { @@ -825,6 +841,67 @@ "title": "Route", "type": "object" }, + "Router": { + "additionalProperties": false, + "properties": { + "hostname": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Hostname" + }, + "endpoint": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Endpoint" + }, + "labels": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Labels" + }, + "nodeSelector": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Nodeselector" + } + }, + "title": "Router", + "type": "object" + }, "Tls": { "additionalProperties": false, "properties": { diff --git a/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yaml b/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yaml index 48834801..821d701b 100644 --- a/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yaml +++ b/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yaml @@ -10,6 +10,7 @@ grpc: endpoint: "" routerEndpoint: "" + additionalRouters: {} tls: enabled: false