diff --git a/backend-deployment.yaml b/backend-deployment.yaml new file mode 100644 index 0000000..4ad14a8 --- /dev/null +++ b/backend-deployment.yaml @@ -0,0 +1,89 @@ +{{- if .Values.backend.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tower-backend + labels: + {{- include "tower.labels" . | nindent 4 }} + odoosky.io/role: backend +spec: + replicas: {{ .Values.backend.replicas }} + selector: + matchLabels: + app.kubernetes.io/name: tower + odoosky.io/role: backend + template: + metadata: + labels: + {{- include "tower.labels" . | nindent 8 }} + odoosky.io/role: backend + spec: + containers: + - name: tower + image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}" + imagePullPolicy: {{ .Values.backend.image.pullPolicy }} + ports: + - name: http + containerPort: 8080 + env: + - name: TOWER_LISTEN_ADDR + value: ":8080" + - name: TOWER_GITEA_URL + value: {{ .Values.config.giteaURL | quote }} + - name: TOWER_GITEA_ORG + value: {{ .Values.config.giteaOrg | quote }} + - name: TOWER_CHART_REPO + value: {{ .Values.config.chartRepo | quote }} + - name: TOWER_ARGOCD_URL + value: {{ .Values.config.argoCDURL | quote }} + - name: TOWER_ARGOCD_USERNAME + value: {{ .Values.config.argoCDUsername | quote }} + - name: TOWER_ARGOCD_DESTINATION + value: {{ .Values.config.argoCDDestination | quote }} + - name: TOWER_ARGOCD_PROJECT + value: {{ .Values.config.argoCDProject | quote }} + - name: TOWER_ARGOCD_NAMESPACE + value: {{ .Values.config.argoCDNamespace | quote }} + - name: TOWER_TENANT_NAMESPACE + value: {{ .Values.config.tenantNamespace | quote }} + - name: TOWER_GITEA_TOKEN + valueFrom: + secretKeyRef: + name: {{ .Values.config.existingSecret }} + key: GITEA_TOKEN + - name: TOWER_ARGOCD_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.config.existingSecret }} + key: ARGOCD_PASSWORD + # Cloudflare creds for per-tenant DNS automation. Optional — + # if absent, deploys to the in-cluster destination still + # work (wildcard A handles them); deploys to non-default + # servers fail fast with a clear error. + - name: TOWER_CLOUDFLARE_TOKEN + valueFrom: + secretKeyRef: + name: {{ .Values.config.existingSecret }} + key: CLOUDFLARE_TOKEN + optional: true + - name: TOWER_CLOUDFLARE_ZONE_ID + valueFrom: + secretKeyRef: + name: {{ .Values.config.existingSecret }} + key: CLOUDFLARE_ZONE_ID + optional: true + readinessProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 2 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 15 + resources: + {{- toYaml .Values.backend.resources | nindent 12 }} +{{- end }} diff --git a/ingressroute.yaml b/ingressroute.yaml new file mode 100644 index 0000000..e328b5c --- /dev/null +++ b/ingressroute.yaml @@ -0,0 +1,38 @@ +# Tower IngressRoute — path-based split between API and UI on the +# same hostname. +# +# Routing rules (Traefik picks longest-match-with-priority): +# - API endpoints (/healthz, /instances, future /api/*) → backend +# - everything else → frontend (Vue SPA) +# +# Priority is set explicitly so Traefik doesn't fall back to its +# heuristic; the API rule outranks the catchall, which outranks no +# rule at all. +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: tower + labels: + {{- include "tower.labels" . | nindent 4 }} +spec: + entryPoints: + - {{ .Values.ingress.entryPoint }} + routes: +{{- if .Values.backend.enabled }} + - match: Host(`{{ .Values.ingress.domain }}`) && (PathPrefix(`/api`) || PathPrefix(`/healthz`)) + kind: Rule + priority: 200 + services: + - name: tower-backend + port: 8080 +{{- end }} +{{- if .Values.frontend.enabled }} + - match: Host(`{{ .Values.ingress.domain }}`) + kind: Rule + priority: 100 + services: + - name: tower-frontend + port: 80 +{{- end }} + tls: + secretName: tower-tls diff --git a/templates/backend-deployment.yaml b/templates/backend-deployment.yaml index 4ad14a8..9207659 100644 --- a/templates/backend-deployment.yaml +++ b/templates/backend-deployment.yaml @@ -18,6 +18,7 @@ spec: {{- include "tower.labels" . | nindent 8 }} odoosky.io/role: backend spec: + serviceAccountName: tower containers: - name: tower image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}" diff --git a/templates/serviceaccount.yaml b/templates/serviceaccount.yaml new file mode 100644 index 0000000..e9ae773 --- /dev/null +++ b/templates/serviceaccount.yaml @@ -0,0 +1,47 @@ +{{- if .Values.backend.enabled -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: tower + labels: + {{- include "tower.labels" . | nindent 4 }} +--- +# Tower needs cluster-wide read on Nodes + node metrics for the +# capacity-bar feature; namespace get/list/create so it can ensure +# the tenants ns exists before ArgoCD creates instance resources; +# argoproj.io CRD CRUD so it can create + delete Applications. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Release.Name }}-tower + labels: + {{- include "tower.labels" . | nindent 4 }} +rules: + - apiGroups: ['argoproj.io'] + resources: ['applications', 'appprojects'] + verbs: ['get', 'list', 'create', 'update', 'patch', 'delete'] + - apiGroups: [''] + resources: ['namespaces'] + verbs: ['get', 'list', 'create'] + - apiGroups: [''] + resources: ['nodes'] + verbs: ['get', 'list'] + - apiGroups: ['metrics.k8s.io'] + resources: ['nodes'] + verbs: ['get', 'list'] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ .Release.Name }}-tower + labels: + {{- include "tower.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: tower + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ .Release.Name }}-tower + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/values.yaml b/values.yaml index f43bb78..3add7ca 100644 --- a/values.yaml +++ b/values.yaml @@ -4,7 +4,7 @@ backend: enabled: true image: repository: docker.io/odoosky/tower - tag: "0.8.1" + tag: "0.9.0" pullPolicy: IfNotPresent # IfNotPresent because the image is in # containerd's k8s.io namespace already # (lab1 single-server). Replace with @@ -22,7 +22,7 @@ frontend: enabled: true image: repository: docker.io/odoosky/tower-ui - tag: "0.7.0" + tag: "0.8.0" pullPolicy: IfNotPresent replicas: 1 resources: