diff --git a/.github/workflows/_deploy.yml b/.github/workflows/_deploy.yml index b510fc527..e5c248982 100644 --- a/.github/workflows/_deploy.yml +++ b/.github/workflows/_deploy.yml @@ -60,26 +60,26 @@ jobs: # vars.DOMAIN holds the base domain for the current environment. [ -n "${{ vars.DOMAIN }}" ] && HELM_EXTRA_ARGS+=(--set-string "domainSuffix=${{ vars.DOMAIN }}") - helm upgrade --install "${{ inputs.deployment_name }}" ./chart \ - --namespace "${{ inputs.deployment_name }}" \ + helm upgrade --install '${{ inputs.deployment_name }}' ./chart \ + --namespace '${{ inputs.deployment_name }}' \ --create-namespace \ --wait \ --timeout 10m \ - --set-string domain="${{ inputs.domain || vars.DOMAIN }}" \ + --set-string domain='${{ inputs.domain || vars.DOMAIN }}' \ --set database.replicas=${{ inputs.environment == 'prod' && 3 || 1 }} \ --set-string database.cpu="${{ inputs.environment == 'prod' && '1' || '500m' }}" \ --set-string database.memory="${{ inputs.environment == 'prod' && '1Gi' || '0.5Gi' }}" \ --set vector.useHostPath=${{ inputs.vector_host_path }} \ - --set-string controller.image.tag="${{ inputs.image_tag }}" \ - --set-string controller.env.VELA_DEPLOYMENT_NAMESPACE_PREFIX="${{ inputs.deployment_name }}" \ - --set-string controller.env.VELA_CLOUDFLARE_API_TOKEN="${{ secrets.VELA_CLOUDFLARE_API_TOKEN }}" \ - --set-string controller.env.VELA_CLOUDFLARE_ZONE_ID="${{ secrets.VELA_CLOUDFLARE_ZONE_ID }}" \ - --set-string controller.env.VELA_KEYCLOAK_ADMIN_NAME="${{ secrets.VELA_KEYCLOAK_ADMIN_NAME }}" \ - --set-string controller.env.VELA_KEYCLOAK_ADMIN_SECRET="${{ secrets.VELA_KEYCLOAK_ADMIN_SECRET }}" \ - --set-string controller.env.VELA_BRANCH_REF="${{ vars.VELA_BRANCH_REF }}" \ - --set-string controller.env.VELA_BRANCH_DB_REF="${{ vars.VELA_BRANCH_DB_REF }}" \ - --set-string controller.env.VELA_ENABLE_DB_EXTERNAL_IPV6_LOADBALANCER="${{ vars.ENABLE_DB_EXTERNAL_IPV6_LOADBALANCER }}" \ - --set-string controller.env.VELA_SIMPLYBLOCK_CSI_NAMESPACE="${{ vars.SIMPLYBLOCK_CSI_NAMESPACE }}" \ + --set-string controller.image.tag='${{ inputs.image_tag }}' \ + --set-string controller.env.VELA_DEPLOYMENT_NAMESPACE_PREFIX='${{ inputs.deployment_name }}' \ + --set-string controller.env.VELA_CLOUDFLARE_API_TOKEN='${{ secrets.VELA_CLOUDFLARE_API_TOKEN }}' \ + --set-string controller.env.VELA_CLOUDFLARE_ZONE_ID='${{ secrets.VELA_CLOUDFLARE_ZONE_ID }}' \ + --set-string controller.env.VELA_KEYCLOAK_ADMIN_NAME='${{ secrets.VELA_KEYCLOAK_ADMIN_NAME }}' \ + --set-string controller.env.VELA_KEYCLOAK_ADMIN_SECRET='${{ secrets.VELA_KEYCLOAK_ADMIN_SECRET }}' \ + --set-string controller.env.VELA_BRANCH_REF='${{ vars.VELA_BRANCH_REF }}' \ + --set-string controller.env.VELA_BRANCH_DB_REF='${{ vars.VELA_BRANCH_DB_REF }}' \ + --set-string controller.env.VELA_ENABLE_DB_EXTERNAL_IPV6_LOADBALANCER='${{ vars.ENABLE_DB_EXTERNAL_IPV6_LOADBALANCER }}' \ + --set-string controller.env.VELA_SIMPLYBLOCK_CSI_NAMESPACE='${{ vars.SIMPLYBLOCK_CSI_NAMESPACE }}' \ --set-string studio.image.tag="${{ inputs.environment == 'prod' && 'latest' || 'dev' }}" \ - --set-string monitoring.VELA_GRAFANA_SECURITY_ADMIN_PASSWORD="${{ secrets.VELA_GRAFANA_SECURITY_ADMIN_PASSWORD }}" \ + --set-string monitoring.VELA_GRAFANA_SECURITY_ADMIN_PASSWORD='${{ secrets.VELA_GRAFANA_SECURITY_ADMIN_PASSWORD }}' \ "${HELM_EXTRA_ARGS[@]}" diff --git a/.github/workflows/ci-deploy.yml b/.github/workflows/ci-deploy.yml index 65875fb4b..3f2d3e51d 100644 --- a/.github/workflows/ci-deploy.yml +++ b/.github/workflows/ci-deploy.yml @@ -17,7 +17,7 @@ jobs: needs: build uses: ./.github/workflows/_deploy.yml with: - image_tag: ${{ needs.build.outputs.image_tag }} + image_tag: '${{ needs.build.outputs.image_tag }}@${{ needs.build.outputs.image_digest }}' deployment_name: vela environment: ${{ github.ref_name == 'main' && 'prod' || 'dev' }} secrets: inherit diff --git a/chart/templates/controller.yaml b/chart/templates/controller.yaml deleted file mode 100644 index 0021b8932..000000000 --- a/chart/templates/controller.yaml +++ /dev/null @@ -1,176 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: vela-controller-secret -type: Opaque -data: - {{- $existingSecret := lookup "v1" "Secret" .Release.Namespace "vela-controller-secret" }} - {{- if $existingSecret }} - deployment-password-secret: {{ index $existingSecret.data "deployment-password-secret" }} - {{- else }} - deployment-password-secret: {{ randAlphaNum 32 | b64enc }} - {{- end }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: vela-controller - namespace: {{ .Release.Namespace }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: vela-controller-{{ .Release.Namespace }}-admin -subjects: - - kind: ServiceAccount - name: vela-controller - namespace: {{ .Release.Namespace }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: vela-controller - labels: - app.kubernetes.io/name: vela-controller - app.kubernetes.io/instance: {{ .Release.Name }} -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: vela-controller - template: - metadata: - labels: - app.kubernetes.io/name: vela-controller - app.kubernetes.io/instance: {{ .Release.Name }} - spec: - serviceAccountName: vela-controller - initContainers: -{{ include "vela.waitForPostgresInitContainer" (dict) | nindent 8 }} - containers: - - name: vela-controller - image: "{{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag }}" - imagePullPolicy: Always - ports: - - name: http - containerPort: 8000 - protocol: TCP - envFrom: - - configMapRef: - name: vela-controller-config - env: - - name: VELA_GRAFANA_SECURITY_ADMIN_USER - valueFrom: - secretKeyRef: - name: vela-grafana-secret - key: VELA_GRAFANA_SECURITY_ADMIN_USER - - name: VELA_GRAFANA_SECURITY_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: vela-grafana-secret - key: VELA_GRAFANA_SECURITY_ADMIN_PASSWORD - - name: DB_USER - valueFrom: - secretKeyRef: - name: database - key: superuser-username - - name: DB_PASSWORD - valueFrom: - secretKeyRef: - name: database - key: superuser-password - - name: VELA_DEPLOYMENT_PASSWORD_SECRET - valueFrom: - secretKeyRef: - name: vela-controller-secret - key: deployment-password-secret - - name: DB_HOST - value: database - - name: VELA_POSTGRES_URL - value: 'postgresql+asyncpg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres' - - name: VELA_GRAFANA_URL - value: "https://{{ .Values.domain }}:{{ .Values.port }}/grafana" - livenessProbe: - httpGet: - path: /health - port: http - periodSeconds: 5 - timeoutSeconds: 5 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 10 - {{- with .Values.containerSecurityContext }} - securityContext: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.podSecurityContext }} - securityContext: - {{- toYaml . | nindent 8 }} - {{- end }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: vela-controller-config -data: - VELA_ROOT_PATH: {{ .Values.controller.env.VELA_ROOT_PATH | quote }} - VELA_JWT_SECRET: {{ .Values.controller.env.VELA_JWT_SECRET | quote }} - VELA_GATEWAY_NAME: {{ .Values.gateway.name | quote }} - VELA_GATEWAY_NAMESPACE: {{ .Values.gateway.namespace | quote }} - VELA_PGMETA_CRYPTO_KEY: {{ .Values.controller.env.VELA_PGMETA_CRYPTO_KEY | quote }} - VELA_CORS_ORIGINS: {{ .Values.controller.env.VELA_CORS_ORIGINS | quote }} - VELA_KEYCLOAK_URL: {{ .Values.controller.env.VELA_KEYCLOAK_URL | quote }} - VELA_KEYCLOAK_ADMIN_NAME: {{ .Values.controller.env.VELA_KEYCLOAK_ADMIN_NAME | quote }} - VELA_KEYCLOAK_ADMIN_SECRET: {{ .Values.controller.env.VELA_KEYCLOAK_ADMIN_SECRET | quote }} - VELA_CLOUDFLARE__API_TOKEN: {{ .Values.controller.env.VELA_CLOUDFLARE_API_TOKEN | quote }} - VELA_CLOUDFLARE__ZONE_ID: {{ .Values.controller.env.VELA_CLOUDFLARE_ZONE_ID | quote }} - VELA_CLOUDFLARE__BRANCH_REF: {{ .Values.controller.env.VELA_BRANCH_REF | quote }} - VELA_CLOUDFLARE__BRANCH_DB_REF: {{ .Values.controller.env.VELA_BRANCH_DB_REF | quote }} - VELA_CLOUDFLARE__DOMAIN_SUFFIX: {{ .Values.domainSuffix | default .Values.domain | quote }} - VELA_DEPLOYMENT_NAMESPACE_PREFIX: {{ .Values.controller.env.VELA_DEPLOYMENT_NAMESPACE_PREFIX | quote }} - VELA_DEPLOYMENT_SERVICE_PORT: {{ .Values.port | quote }} - VELA_SERVER_ROOT_URL: "https://{{ .Values.domain }}:{{ .Values.port }}" - VELA_ENABLE_DB_EXTERNAL_IPV6_LOADBALANCER: {{ .Values.controller.env.VELA_ENABLE_DB_EXTERNAL_IPV6_LOADBALANCER | quote }} - VELA_GRAFANA_URL: {{ .Values.controller.env.VELA_GRAFANA_URL | quote }} - VELA_SIMPLYBLOCK_CSI_NAMESPACE: {{ .Values.controller.env.VELA_SIMPLYBLOCK_CSI_NAMESPACE | quote }} ---- -apiVersion: v1 -kind: Service -metadata: - name: vela-controller-service -spec: - selector: - app.kubernetes.io/name: vela-controller - ports: - - name: http - port: 8000 - targetPort: 8000 - protocol: TCP - ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: vela-controller -spec: - parentRefs: - - name: {{ .Values.gateway.name }} - namespace: {{ .Values.gateway.namespace }} - hostnames: - - "{{ .Values.domain }}" - rules: - - matches: - - path: - type: PathPrefix - value: /vela - backendRefs: - - name: vela-controller-service - namespace: {{ .Release.Namespace }} - port: 8000 diff --git a/chart/templates/controller/configmap.yaml b/chart/templates/controller/configmap.yaml new file mode 100644 index 000000000..466252610 --- /dev/null +++ b/chart/templates/controller/configmap.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: vela-controller-config +data: + VELA_ROOT_PATH: {{ .Values.controller.env.VELA_ROOT_PATH | quote }} + VELA_JWT_SECRET: {{ .Values.controller.env.VELA_JWT_SECRET | quote }} + VELA_GATEWAY_NAME: {{ .Values.gateway.name | quote }} + VELA_GATEWAY_NAMESPACE: {{ .Values.gateway.namespace | quote }} + VELA_PGMETA_CRYPTO_KEY: {{ .Values.controller.env.VELA_PGMETA_CRYPTO_KEY | quote }} + VELA_CORS_ORIGINS: {{ .Values.controller.env.VELA_CORS_ORIGINS | quote }} + VELA_KEYCLOAK_URL: {{ .Values.controller.env.VELA_KEYCLOAK_URL | quote }} + VELA_KEYCLOAK_ADMIN_NAME: {{ .Values.controller.env.VELA_KEYCLOAK_ADMIN_NAME | quote }} + VELA_KEYCLOAK_ADMIN_SECRET: {{ .Values.controller.env.VELA_KEYCLOAK_ADMIN_SECRET | quote }} + VELA_CLOUDFLARE__API_TOKEN: {{ .Values.controller.env.VELA_CLOUDFLARE_API_TOKEN | quote }} + VELA_CLOUDFLARE__ZONE_ID: {{ .Values.controller.env.VELA_CLOUDFLARE_ZONE_ID | quote }} + VELA_CLOUDFLARE__BRANCH_REF: {{ .Values.controller.env.VELA_BRANCH_REF | quote }} + VELA_CLOUDFLARE__BRANCH_DB_REF: {{ .Values.controller.env.VELA_BRANCH_DB_REF | quote }} + VELA_CLOUDFLARE__DOMAIN_SUFFIX: {{ .Values.domainSuffix | default .Values.domain | quote }} + VELA_DEPLOYMENT_NAMESPACE_PREFIX: {{ .Values.controller.env.VELA_DEPLOYMENT_NAMESPACE_PREFIX | quote }} + VELA_DEPLOYMENT_SERVICE_PORT: {{ .Values.port | quote }} + VELA_SERVER_ROOT_URL: "https://{{ .Values.domain }}:{{ .Values.port }}" + VELA_ENABLE_DB_EXTERNAL_IPV6_LOADBALANCER: {{ .Values.controller.env.VELA_ENABLE_DB_EXTERNAL_IPV6_LOADBALANCER | quote }} + VELA_GRAFANA_URL: {{ .Values.controller.env.VELA_GRAFANA_URL | quote }} + VELA_SIMPLYBLOCK_CSI_NAMESPACE: {{ .Values.controller.env.VELA_SIMPLYBLOCK_CSI_NAMESPACE | quote }} diff --git a/chart/templates/controller/deployment.yaml b/chart/templates/controller/deployment.yaml new file mode 100644 index 000000000..d19dbfb48 --- /dev/null +++ b/chart/templates/controller/deployment.yaml @@ -0,0 +1,88 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vela-controller + labels: + app.kubernetes.io/name: vela-controller + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: vela-controller + template: + metadata: + labels: + app.kubernetes.io/name: vela-controller + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + serviceAccountName: vela-controller + initContainers: +{{ include "vela.waitForPostgresInitContainer" (dict) | nindent 8 }} + containers: + - name: vela-controller + image: "{{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag }}" + imagePullPolicy: Always + ports: + - name: http + containerPort: 8000 + protocol: TCP + envFrom: + - configMapRef: + name: vela-controller-config + env: + - name: VELA_GRAFANA_SECURITY_ADMIN_USER + valueFrom: + secretKeyRef: + name: vela-grafana-secret + key: VELA_GRAFANA_SECURITY_ADMIN_USER + - name: VELA_GRAFANA_SECURITY_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: vela-grafana-secret + key: VELA_GRAFANA_SECURITY_ADMIN_PASSWORD + - name: DB_USER + valueFrom: + secretKeyRef: + name: database + key: superuser-username + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: database + key: superuser-password + - name: VELA_DEPLOYMENT_PASSWORD_SECRET + valueFrom: + secretKeyRef: + name: vela-controller-secret + key: deployment-password-secret + - name: DB_HOST + value: database + - name: VELA_POSTGRES_URL + value: 'postgresql+asyncpg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres' + - name: VELA_GRAFANA_URL + value: "https://{{ .Values.domain }}:{{ .Values.port }}/grafana" + - name: VELA_BROKER_URL + value: 'sqla+postgresql+psycopg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres' + - name: VELA_RESULT_BACKEND + value: 'db+postgresql+psycopg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres' + livenessProbe: + httpGet: + path: /health + port: http + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: 10 + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/chart/templates/controller/rbac.yaml b/chart/templates/controller/rbac.yaml new file mode 100644 index 000000000..9bc42f6fd --- /dev/null +++ b/chart/templates/controller/rbac.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: vela-controller + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: vela-controller-{{ .Release.Namespace }}-admin +subjects: + - kind: ServiceAccount + name: vela-controller + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin diff --git a/chart/templates/controller/secret.yaml b/chart/templates/controller/secret.yaml new file mode 100644 index 000000000..f73794507 --- /dev/null +++ b/chart/templates/controller/secret.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Secret +metadata: + name: vela-controller-secret +type: Opaque +data: + {{- $existingSecret := lookup "v1" "Secret" .Release.Namespace "vela-controller-secret" }} + {{- if $existingSecret }} + deployment-password-secret: {{ index $existingSecret.data "deployment-password-secret" }} + {{- else }} + deployment-password-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} diff --git a/chart/templates/controller/service.yaml b/chart/templates/controller/service.yaml new file mode 100644 index 000000000..18532eaca --- /dev/null +++ b/chart/templates/controller/service.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: Service +metadata: + name: vela-controller-service +spec: + selector: + app.kubernetes.io/name: vela-controller + ports: + - name: http + port: 8000 + targetPort: 8000 + protocol: TCP + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: vela-controller +spec: + parentRefs: + - name: {{ .Values.gateway.name }} + namespace: {{ .Values.gateway.namespace }} + hostnames: + - "{{ .Values.domain }}" + rules: + - matches: + - path: + type: PathPrefix + value: /vela + backendRefs: + - name: vela-controller-service + namespace: {{ .Release.Namespace }} + port: 8000 diff --git a/chart/templates/controller/worker.yaml b/chart/templates/controller/worker.yaml new file mode 100644 index 000000000..4f3b942c9 --- /dev/null +++ b/chart/templates/controller/worker.yaml @@ -0,0 +1,71 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vela-controller-worker + labels: + app.kubernetes.io/name: vela-controller-worker + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: vela-controller-worker + template: + metadata: + labels: + app.kubernetes.io/name: vela-controller-worker + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + serviceAccountName: vela-controller + initContainers: +{{ include "vela.waitForPostgresInitContainer" (dict) | nindent 8 }} + containers: + - name: vela-controller-worker + image: "{{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag }}" + imagePullPolicy: Always + command: ["celery", "-A", "simplyblock.vela.worker", "worker", "--loglevel=info"] + envFrom: + - configMapRef: + name: vela-controller-config + env: + - name: VELA_GRAFANA_SECURITY_ADMIN_USER + valueFrom: + secretKeyRef: + name: vela-grafana-secret + key: VELA_GRAFANA_SECURITY_ADMIN_USER + - name: VELA_GRAFANA_SECURITY_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: vela-grafana-secret + key: VELA_GRAFANA_SECURITY_ADMIN_PASSWORD + - name: DB_USER + valueFrom: + secretKeyRef: + name: database + key: superuser-username + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: database + key: superuser-password + - name: DB_HOST + value: database + - name: VELA_BROKER_URL + value: 'sqla+postgresql+psycopg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres' + - name: VELA_RESULT_BACKEND + value: 'db+postgresql+psycopg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres' + - name: VELA_DEPLOYMENT_PASSWORD_SECRET + valueFrom: + secretKeyRef: + name: vela-controller-secret + key: deployment-password-secret + - name: VELA_POSTGRES_URL + value: 'postgresql+asyncpg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres' + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/chart/templates/vector-config.yaml b/chart/templates/vector-config.yaml index 9d0a294c8..7b288427a 100644 --- a/chart/templates/vector-config.yaml +++ b/chart/templates/vector-config.yaml @@ -126,16 +126,23 @@ data: inputs: - router.controller source: |- - parsed, err = parse_regex(.event_message, r'^(?P