From c8e8a710fb49f6ffe3aababcff7070f212df90a1 Mon Sep 17 00:00:00 2001 From: Jian Zeng Date: Wed, 16 Dec 2020 14:44:39 +0800 Subject: [PATCH] chore(*): add new helm chart --- manifests/cyclone/.helmignore | 22 +++ manifests/cyclone/Chart.yaml | 12 ++ manifests/cyclone/templates/_helpers.tpl | 32 +++ manifests/cyclone/templates/controller.yaml | 140 +++++++++++++ manifests/cyclone/templates/server.yaml | 208 ++++++++++++++++++++ manifests/cyclone/values.yaml | 103 ++++++++++ 6 files changed, 517 insertions(+) create mode 100644 manifests/cyclone/.helmignore create mode 100644 manifests/cyclone/Chart.yaml create mode 100644 manifests/cyclone/templates/_helpers.tpl create mode 100644 manifests/cyclone/templates/controller.yaml create mode 100644 manifests/cyclone/templates/server.yaml create mode 100644 manifests/cyclone/values.yaml diff --git a/manifests/cyclone/.helmignore b/manifests/cyclone/.helmignore new file mode 100644 index 000000000..50af03172 --- /dev/null +++ b/manifests/cyclone/.helmignore @@ -0,0 +1,22 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/manifests/cyclone/Chart.yaml b/manifests/cyclone/Chart.yaml new file mode 100644 index 000000000..6db2e9863 --- /dev/null +++ b/manifests/cyclone/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v2 +description: A Helm chart for Cyclone +name: cyclone +version: v1.2.0-alpha +appVersion: v1.2.0-alpha +keywords: + - cicd + - workflow + - devops + - k8s +sources: + - https://github.com/caicloud/cyclone diff --git a/manifests/cyclone/templates/_helpers.tpl b/manifests/cyclone/templates/_helpers.tpl new file mode 100644 index 000000000..4f6e057e9 --- /dev/null +++ b/manifests/cyclone/templates/_helpers.tpl @@ -0,0 +1,32 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "cyclone.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "cyclone.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cyclone.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/manifests/cyclone/templates/controller.yaml b/manifests/cyclone/templates/controller.yaml new file mode 100644 index 000000000..735a2675d --- /dev/null +++ b/manifests/cyclone/templates/controller.yaml @@ -0,0 +1,140 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: workflow-controller-config + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "cyclone.name" . }} + helm.sh/chart: {{ include "cyclone.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +data: + workflow-controller.json: | + { + "images": { + "git-resolver": "{{ .Values.platformConfig.imageRepositoryRelease }}/cyclone-resolver-git:{{ .Chart.AppVersion }}", + "svn-resolver": "{{ .Values.platformConfig.imageRepositoryRelease }}/cyclone-resolver-svn:{{ .Chart.AppVersion }}", + "image-resolver": "{{ .Values.platformConfig.imageRepositoryRelease }}/cyclone-resolver-image:{{ .Chart.AppVersion }}", + "http-resolver": "{{ .Values.platformConfig.imageRepositoryRelease }}/cyclone-resolver-http:{{ .Chart.AppVersion }}", + "coordinator": "{{ .Values.platformConfig.imageRepositoryRelease }}/cyclone-workflow-coordinator:{{ .Chart.AppVersion }}", + "toolbox": "{{ .Values.platformConfig.imageRepositoryRelease }}/cyclone-toolbox:{{ .Chart.AppVersion }}", + "gc": "{{ .Values.platformConfig.imageRepositoryLibrary }}/{{ .Values.engine.images.gc }}" + }, + "logging": { + "level": "info" + }, + "gc": { + "enabled": {{ .Values.engine.gc.enabled }}, + "delay_seconds": {{ .Values.engine.gc.delaySeconds }}, + "retry": {{ .Values.engine.gc.retry }}, + "resource_quota": { + "limits": { + "cpu": "{{ .Values.engine.gc.resourceRequirement.limits.cpu }}", + "memory": "{{ .Values.engine.gc.resourceRequirement.limits.memory }}" + }, + "requests": { + "cpu": "{{ .Values.engine.gc.resourceRequirement.requests.cpu }}", + "memory": "{{ .Values.engine.gc.resourceRequirement.requests.memory }}" + } + } + }, + "limits": { + "max_workflowruns": {{ .Values.engine.limits.maxWorkflowRuns }} + }, + "default_resource_quota": { + "limits": { + "cpu": "{{ .Values.engine.resourceRequirement.default.limits.cpu }}", + "memory": "{{ .Values.engine.resourceRequirement.default.limits.memory }}" + }, + "requests": { + "cpu": "{{ .Values.engine.resourceRequirement.default.requests.cpu }}", + "memory": "{{ .Values.engine.resourceRequirement.default.requests.memory }}" + } + }, + "workers_number": { + "execution_cluster": 1, + "workflow_trigger": 1, + "workflow_run": 1, + "pod": 1 + }, + "pvc": "cyclone-server-cyclone-data", + "cyclone_server_addr": "{{ .Values.platformConfig.controlClusterVIP }}:6041", + "notification_url": "http://{{ .Values.platformConfig.controlClusterVIP }}:6041/apis/v1alpha1/notifications" + } + +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-workflow-controller + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "cyclone.name" . }} + app.kubernetes.io/component: workflow-controller + helm.sh/chart: {{ include "cyclone.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ include "cyclone.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: cyclone-workflow-controller + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "cyclone.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: cyclone-workflow-controller + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: {{ .Values.serviceAccount }} + containers: + - name: controller + command: + - /workspace/controller + image: "{{ .Values.platformConfig.imageRegistry }}/{{ .Values.platformConfig.imageRepositoryRelease }}/cyclone-workflow-controller:{{ .Chart.AppVersion }}" + imagePullPolicy: Always + env: + - name: DEVELOP_MODE + value: {{ .Values.engine.developMode | quote }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SYSTEM_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + livenessProbe: + httpGet: + port: 8080 + path: /healthz + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + successThreshold: 1 + resources: + limits: + cpu: 150m + memory: 300Mi + requests: + cpu: 50m + memory: 100Mi + volumeMounts: + - mountPath: /etc/localtime + mountPropagation: HostToContainer + name: timezone + volumes: + - name: timezone + hostPath: + path: /etc/localtime + type: File diff --git a/manifests/cyclone/templates/server.yaml b/manifests/cyclone/templates/server.yaml new file mode 100644 index 000000000..6989b90f4 --- /dev/null +++ b/manifests/cyclone/templates/server.yaml @@ -0,0 +1,208 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: cyclone-server-config + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "cyclone.name" . }} + helm.sh/chart: {{ include "cyclone.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +data: + cyclone-server.json: | + { + "logging": { + "level": "debug" + }, + "cyclone_server_host": "{{ .Values.server.listenAddress }}", + "cyclone_server_port": {{ .Values.server.listenPort }}, + "webhook_url_prefix": "http://{{ .Values.platformConfig.controlClusterVIP }}:6060/hodor/apis/admin.devops.caicloud.io/v2", + "record_web_url_template": "http://{{ .Values.platformConfig.controlClusterVIP }}:6060{{ .Values.server.recordWebURLPath }}", + "default_pvc_config": { + "size": "{{ .Values.server.pvc.size }}", + "storage_class": "{{ .Values.server.pvc.storageClass }}" + }, + "worker_namespace_quota": { + "limits.cpu": "{{ .Values.server.resourceRequirement.namespace.limits.cpu }}", + "limits.memory": "{{ .Values.server.resourceRequirement.namespace.limits.memory }}", + "requests.cpu": "{{ .Values.server.resourceRequirement.namespace.requests.cpu }}", + "requests.memory": "{{ .Values.server.resourceRequirement.namespace.requests.memory }}" + }, + "create_builtin_templates": {{ .Values.server.init.templates }}, + "init_default_tenant": {{ .Values.server.init.defaultTenant }}, + "open_control_cluster": {{ .Values.server.openControlCluster }}, + "storage_usage_watcher": { + "image": "{{ .Values.platformConfig.imageRepositoryRelease }}/cyclone-watcher:{{ .Chart.AppVersion }}", + "report_url": "http://{{ .Values.platformConfig.controlClusterVIP }}:6041/apis/v1alpha1/storage/usages", + "interval_seconds": "{{ .Values.server.storageWatcher.intervalSeconds }}", + "resource_requirements": { + "limits.cpu": "{{ .Values.server.storageWatcher.resourceRequirements.limits.cpu }}", + "limits.memory": "{{ .Values.server.storageWatcher.resourceRequirements.limits.memory }}", + "requests.cpu": "{{ .Values.server.storageWatcher.resourceRequirements.requests.cpu }}", + "requests.memory": "{{ .Values.server.storageWatcher.resourceRequirements.requests.memory }}" + } + }, + "cache_cleaner": { + "image": "{{ .Values.platformConfig.imageRepositoryLibrary }}/{{ .Values.server.cacheCleaner.image }}", + "resource_requirements": { + "limits.cpu": "{{ .Values.server.cacheCleaner.resourceRequirements.limits.cpu }}", + "limits.memory": "{{ .Values.server.cacheCleaner.resourceRequirements.limits.memory }}", + "requests.cpu": "{{ .Values.server.cacheCleaner.resourceRequirements.requests.cpu }}", + "requests.memory": "{{ .Values.server.cacheCleaner.resourceRequirements.requests.memory }}" + } + }, + "images": { + "gc": "{{ .Values.platformConfig.imageRepositoryLibrary }}/{{ .Values.engine.images.gc }}" + }, + "notifications": [ + { + "name": "devops", + "url": "http://{{ .Release.Name }}-pipeline.{{ .Release.Namespace }}.svc.cluster.local:7088/api/v2/pipeline/notifications" + } + ], + "client_set": { + "qps": {{ .Values.server.clientSet.qps }}, + "burst": {{ .Values.server.clientSet.burst }} + }, + "artifact": { + "retention_seconds": {{ .Values.server.artifact.retentionSeconds }}, + "retention_disk_protection_threshold": {{ .Values.server.artifact.retentionDiskProtectionThreshold }} + } + } + +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-server + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "cyclone.name" . }} + app.kubernetes.io/component: cyclone-server + helm.sh/chart: {{ include "cyclone.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ include "cyclone.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: cyclone-server + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "cyclone.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: cyclone-server + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: {{ .Values.serviceAccount }} + containers: + - name: server + image: "{{ .Values.platformConfig.imageRegistry }}/{{ .Values.platformConfig.imageRepositoryRelease }}/cyclone-server:{{ .Chart.AppVersion }}" + imagePullPolicy: Always + command: + - /cyclone-server + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SYSTEM_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: WEBHOOK_URL_PREFIX + value: "http://{{ .Values.platformConfig.controlClusterVIP }}:6060/hodor/apis/admin.devops.caicloud.io/v2" + ports: + - containerPort: {{ .Values.server.listenPort }} + resources: + limits: + cpu: 150m + memory: 300Mi + requests: + cpu: 50m + memory: 100Mi + livenessProbe: + httpGet: + port: {{ .Values.server.listenPort }} + path: /healthz?type=liveness + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + readinessProbe: + httpGet: + port: {{ .Values.server.listenPort }} + path: /healthz?type=readiness + initialDelaySeconds: 10 + volumeMounts: + - mountPath: /etc/localtime + name: timezone + mountPropagation: HostToContainer + - mountPath: /var/lib/cyclone + name: cyclone-data + volumes: + - name: timezone + hostPath: + path: /etc/localtime + type: File + - name: cyclone-data + persistentVolumeClaim: + claimName: cyclone-server-cyclone-data + +--- +kind: Service +apiVersion: v1 +metadata: + name: {{ .Release.Name }}-server + labels: + app.kubernetes.io/name: {{ include "cyclone.name" . }} + helm.sh/chart: {{ include "cyclone.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + selector: + app.kubernetes.io/component: cyclone-server + ports: + - protocol: TCP + port: {{ .Values.server.listenPort }} + {{- if (not (empty .Values.server.nodePort)) }} + nodePort: {{ .Values.server.nodePort }} + {{- end }} + targetPort: {{ .Values.server.listenPort }} + {{- if (not (empty .Values.server.nodePort)) }} + type: NodePort + {{- else }} + type: ClusterIP + {{- end }} + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/name: {{ include "cyclone.name" . }} + helm.sh/chart: {{ include "cyclone.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + name: cyclone-server-cyclone-data + namespace: {{ .Release.Namespace }} +spec: + accessModes: + - ReadWriteMany + resources: + limits: + storage: 10Gi + requests: + storage: 10Gi + storageClassName: heketi-storageclass + volumeMode: Filesystem \ No newline at end of file diff --git a/manifests/cyclone/values.yaml b/manifests/cyclone/values.yaml new file mode 100644 index 000000000..a9433358f --- /dev/null +++ b/manifests/cyclone/values.yaml @@ -0,0 +1,103 @@ +platformConfig: + imageRegistry: cargo.dev.caicloud.xyz + imageRepositoryRelease: release + imageRepositoryLibrary: library + controlClusterVIP: 172.19.45.200 + +serviceAccount: default + +# Cyclone workflow engine variables +engine: + images: + gc: alpine:3.7 + gc: + # Whether enable GC, if set to true, pods would be cleaned after execution finished + enabled: true + # The time to wait before cleanup pods when an execution finished + delaySeconds: 0 + # How many times to retry (include the initial one) + retry: 1 + # ResourceRequirement for the pod to execute GC + resourceRequirement: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 200m + memory: 256Mi + limits: + # Maximum number of execution records to keep for each workflow. + maxWorkflowRuns: 50 + # Parallelism constraints for WorkflowRun execution, value 0 or negative indicate + # no constraint on the corresponding item. + parallelism: + overall: + # How many WorkflowRuns are allowed to run in parallel + maxParallel: 20 + # How many WorkflowRuns are allowed to wait for executing, when this limit + # exceeded, new WorkflowRuns will fail directly. + maxQueueSize: 100 + singleWorkflow: + # How many WorkflowRuns are allowed to run in parallel for a single Workflow + maxParallel: 3 + # How many WorkflowRuns are allowed to wait for executing, when this limit + # exceeded, new WorkflowRuns will fail directly. + maxQueueSize: 10 + resourceRequirement: + default: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 200m + memory: 256Mi + developMode: "false" + +# Cyclone server variables +server: + listenAddress: 0.0.0.0 + listenPort: 7099 + # nodePort: 30011 + webhookUrlPrefix: http://{{ .Values.serverAddress }}/apis/v1alpha1 + recordWebURLPath: /devops/pipeline/workspaces/{{.ProjectName}}/pipelines/{{.WorkflowName}}/records/{{.WorkflowRunName}}/log?tenant={{.Tenant}} + init: + templates: false + defaultTenant: false + openControlCluster: false + pvc: + # Default storageClass which Cyclone will use to create PVC. + storageClass: "heketi-storageclass" + size: 10Gi + resourceRequirement: + namespace: + requests: + cpu: 1 + memory: 2Gi + limits: + cpu: 2 + memory: 4Gi + storageWatcher: + reportUrl: http://{{ .Values.serverAddress }}/apis/v1alpha1/storage/usages + intervalSeconds: 180 + resourceRequirements: + requests: + cpu: 50m + memory: 32Mi + limits: + cpu: 100m + memory: 64Mi + cacheCleaner: + image: alpine:3.7 + resourceRequirements: + requests: + cpu: 50m + memory: 32Mi + limits: + cpu: 100m + memory: 64Mi + clientSet: + qps: 50.0 + burst: 100 + artifact: + retentionSeconds: 604800 + retentionDiskProtectionThreshold: 0.1