From f116db691653757c29725eb7b57bb80c9b35e4d9 Mon Sep 17 00:00:00 2001 From: Stefan Reimer Date: Mon, 19 Apr 2021 11:31:28 +0200 Subject: [PATCH 1/3] feat: First version of KubeZero Timemachine backup solutions --- charts/kubezero-timemachine/Chart.yaml | 17 +++++++++++++ charts/kubezero-timemachine/README.md | 33 +++++++++++++++++++++++++ charts/kubezero-timemachine/values.yaml | 13 ++++++++++ 3 files changed, 63 insertions(+) create mode 100644 charts/kubezero-timemachine/Chart.yaml create mode 100644 charts/kubezero-timemachine/README.md create mode 100644 charts/kubezero-timemachine/values.yaml diff --git a/charts/kubezero-timemachine/Chart.yaml b/charts/kubezero-timemachine/Chart.yaml new file mode 100644 index 0000000..d6b94a4 --- /dev/null +++ b/charts/kubezero-timemachine/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +name: kubezero-timemachine +description: KubeZero umbrella chart for all things backup +type: application +version: 0.1.0 +home: https://kubezero.com +icon: https://cdn.zero-downtime.net/assets/kubezero/logo-small-64.png +keywords: + - kubezero + - gemini +maintainers: + - name: Quarky9 +dependencies: + - name: gemini + version: 0.0.6 + repository: https://charts.fairwinds.com/stable +kubeVersion: ">= 1.18.0" diff --git a/charts/kubezero-timemachine/README.md b/charts/kubezero-timemachine/README.md new file mode 100644 index 0000000..4a885b3 --- /dev/null +++ b/charts/kubezero-timemachine/README.md @@ -0,0 +1,33 @@ +# kubezero-timemachine + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) + +KubeZero umbrella chart for all things backup + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| Quarky9 | | | + +## Requirements + +Kubernetes: `>= 1.18.0` + +| Repository | Name | Version | +|------------|------|---------| +| | gemini | 0.0.6 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| gemini.resources.limits.cpu | string | `"200m"` | | +| gemini.resources.limits.memory | string | `"256Mi"` | | +| gemini.resources.requests.cpu | string | `"50m"` | | +| gemini.resources.requests.memory | string | `"64Mi"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.5.0](https://github.com/norwoodj/helm-docs/releases/v1.5.0) diff --git a/charts/kubezero-timemachine/values.yaml b/charts/kubezero-timemachine/values.yaml new file mode 100644 index 0000000..b197d8a --- /dev/null +++ b/charts/kubezero-timemachine/values.yaml @@ -0,0 +1,13 @@ +gemini: + #image: + # tag: "0.1.1" + + # verbosity: 1 + + resources: + requests: + memory: 64Mi + cpu: 50m + limits: + memory: 256Mi + cpu: 200m -- 2.40.1 From c15f5cbcda225f9253c7af384eeceaaf7c24ef11 Mon Sep 17 00:00:00 2001 From: Stefan Reimer Date: Mon, 19 Apr 2021 12:46:42 +0200 Subject: [PATCH 2/3] feat: Map gemini controller to controller nodes, fix ebs storageclass, integrate timemachine into kubezero --- charts/kubezero-aws-ebs-csi-driver/Chart.yaml | 2 +- .../templates/snapshot-class.yaml | 2 + charts/kubezero-timemachine/Chart.yaml | 2 +- .../charts/gemini/Chart.yaml | 9 +++ .../charts/gemini/README.md | 35 ++++++++++ .../charts/gemini/README.md.gotmpl | 25 +++++++ .../charts/gemini/ci/test-values.yaml | 1 + .../charts/gemini/logo.png | Bin 0 -> 36202 bytes .../charts/gemini/templates/NOTES.txt | 30 +++++++++ .../charts/gemini/templates/_helpers.tpl | 56 ++++++++++++++++ .../charts/gemini/templates/deployment.yaml | 46 +++++++++++++ .../charts/gemini/templates/rbac.yaml | 62 ++++++++++++++++++ .../charts/gemini/templates/test_crd.yaml | 44 +++++++++++++ .../charts/gemini/values.yaml | 25 +++++++ .../run-on-controller.patch | 15 +++++ charts/kubezero-timemachine/update.sh | 10 +++ charts/kubezero/bootstrap.sh | 6 +- charts/kubezero/templates/argoless.yaml | 2 +- charts/kubezero/templates/timemachine.yaml | 8 +++ charts/kubezero/values.yaml | 3 + 20 files changed, 377 insertions(+), 6 deletions(-) create mode 100644 charts/kubezero-timemachine/charts/gemini/Chart.yaml create mode 100644 charts/kubezero-timemachine/charts/gemini/README.md create mode 100644 charts/kubezero-timemachine/charts/gemini/README.md.gotmpl create mode 100644 charts/kubezero-timemachine/charts/gemini/ci/test-values.yaml create mode 100644 charts/kubezero-timemachine/charts/gemini/logo.png create mode 100644 charts/kubezero-timemachine/charts/gemini/templates/NOTES.txt create mode 100644 charts/kubezero-timemachine/charts/gemini/templates/_helpers.tpl create mode 100644 charts/kubezero-timemachine/charts/gemini/templates/deployment.yaml create mode 100644 charts/kubezero-timemachine/charts/gemini/templates/rbac.yaml create mode 100644 charts/kubezero-timemachine/charts/gemini/templates/test_crd.yaml create mode 100644 charts/kubezero-timemachine/charts/gemini/values.yaml create mode 100644 charts/kubezero-timemachine/run-on-controller.patch create mode 100755 charts/kubezero-timemachine/update.sh create mode 100644 charts/kubezero/templates/timemachine.yaml diff --git a/charts/kubezero-aws-ebs-csi-driver/Chart.yaml b/charts/kubezero-aws-ebs-csi-driver/Chart.yaml index bbfda71..14f5d11 100644 --- a/charts/kubezero-aws-ebs-csi-driver/Chart.yaml +++ b/charts/kubezero-aws-ebs-csi-driver/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: kubezero-aws-ebs-csi-driver description: KubeZero Umbrella Chart for aws-ebs-csi-driver type: application -version: 0.5.0 +version: 0.5.1 appVersion: 0.10.0 home: https://kubezero.com icon: https://cdn.zero-downtime.net/assets/kubezero/logo-small-64.png diff --git a/charts/kubezero-aws-ebs-csi-driver/templates/snapshot-class.yaml b/charts/kubezero-aws-ebs-csi-driver/templates/snapshot-class.yaml index 1b4a831..e085838 100644 --- a/charts/kubezero-aws-ebs-csi-driver/templates/snapshot-class.yaml +++ b/charts/kubezero-aws-ebs-csi-driver/templates/snapshot-class.yaml @@ -3,6 +3,8 @@ apiVersion: snapshot.storage.k8s.io/v1beta1 kind: VolumeSnapshotClass metadata: name: csi-aws-vsc + annotations: + snapshot.storage.kubernetes.io/is-default-class: "true" labels: {{ include "kubezero-lib.labels" . | indent 4 }} driver: ebs.csi.aws.com diff --git a/charts/kubezero-timemachine/Chart.yaml b/charts/kubezero-timemachine/Chart.yaml index d6b94a4..42b2930 100644 --- a/charts/kubezero-timemachine/Chart.yaml +++ b/charts/kubezero-timemachine/Chart.yaml @@ -13,5 +13,5 @@ maintainers: dependencies: - name: gemini version: 0.0.6 - repository: https://charts.fairwinds.com/stable + # repository: https://charts.fairwinds.com/stable kubeVersion: ">= 1.18.0" diff --git a/charts/kubezero-timemachine/charts/gemini/Chart.yaml b/charts/kubezero-timemachine/charts/gemini/Chart.yaml new file mode 100644 index 0000000..5d099a2 --- /dev/null +++ b/charts/kubezero-timemachine/charts/gemini/Chart.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +appVersion: 0.1.0 +description: Automated backup and restore of PersistentVolumes using the VolumeSnapshot + API +maintainers: +- email: robertb@fairwinds.com + name: rbren +name: gemini +version: 0.0.6 diff --git a/charts/kubezero-timemachine/charts/gemini/README.md b/charts/kubezero-timemachine/charts/gemini/README.md new file mode 100644 index 0000000..f806707 --- /dev/null +++ b/charts/kubezero-timemachine/charts/gemini/README.md @@ -0,0 +1,35 @@ +
+Gemini +
+
+ +## Intro + +This is a Helm chart for the Fairwinds +[Gemini project](https://github.com/FairwindsOps/gemini). +It provides a Kubernetes CRD and operator for managing `VolumeSnapshots`, allowing you +to back up your `PersistentVolumes` on a regular schedule, retire old backups, and restore +backups with minimal downtime. + +See the [Gemini README](https://github.com/FairwindsOps/gemini) for more information. + +## Installation +```bash +helm repo add fairwinds-stable https://charts.fairwinds.com/stable +helm install gemini fairwinds-stable/gemini --namespace gemini +``` +## Requirements + +Your cluster must support the [VolumeSnapshot API](https://kubernetes.io/docs/concepts/storage/volume-snapshots/) + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| image.pullPolicy | string | `"Always"` | imagePullPolicy - Highly recommended to leave this as `Always` | +| image.repository | string | `"quay.io/fairwinds/gemini"` | Repository for the gemini image | +| image.tag | string | `"0.1"` | The gemini image tag to use | +| rbac.create | bool | `true` | If true, create a new ServiceAccount and attach permissions | +| rbac.serviceAccountName | string | `nil` | | +| verbosity | int | `5` | How verbose the controller logs should be | +| resources | object | `{"limits":{"cpu":"200m","memory":"512Mi"},"requests":{"cpu":"25m","memory":"64Mi"}}` | The resources block for the controller pods | diff --git a/charts/kubezero-timemachine/charts/gemini/README.md.gotmpl b/charts/kubezero-timemachine/charts/gemini/README.md.gotmpl new file mode 100644 index 0000000..9028c92 --- /dev/null +++ b/charts/kubezero-timemachine/charts/gemini/README.md.gotmpl @@ -0,0 +1,25 @@ +
+Gemini +
+
+ +## Intro + +This is a Helm chart for the Fairwinds +[Gemini project](https://github.com/FairwindsOps/gemini). +It provides a Kubernetes CRD and operator for managing `VolumeSnapshots`, allowing you +to back up your `PersistentVolumes` on a regular schedule, retire old backups, and restore +backups with minimal downtime. + +See the [Gemini README](https://github.com/FairwindsOps/gemini) for more information. + +## Installation +```bash +helm repo add fairwinds-stable https://charts.fairwinds.com/stable +helm install gemini fairwinds-stable/gemini --namespace gemini +``` +## Requirements + +Your cluster must support the [VolumeSnapshot API](https://kubernetes.io/docs/concepts/storage/volume-snapshots/) + +{{ template "chart.valuesSection" . }} diff --git a/charts/kubezero-timemachine/charts/gemini/ci/test-values.yaml b/charts/kubezero-timemachine/charts/gemini/ci/test-values.yaml new file mode 100644 index 0000000..0a5389e --- /dev/null +++ b/charts/kubezero-timemachine/charts/gemini/ci/test-values.yaml @@ -0,0 +1 @@ +testMode: true diff --git a/charts/kubezero-timemachine/charts/gemini/logo.png b/charts/kubezero-timemachine/charts/gemini/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e3abd2c10affc16899eb75380347361184722bc9 GIT binary patch literal 36202 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

kU{aaTuZ8vb%1 zY0}C2QwI()LOlO24tswKF@}%-I_G#N(2RZa_Oo2lH40-k;vYu*%@YU4jAz+D9~Z?X z*~vT+iM;Z*f1>d%Qe$#+eEfJ%`wx^>N*e~+iB#|JzQ39xcJl!PjG3_H7PtVGX8KPt z8B<+ZIjGU*IPMMydV|BTRl zE5UUTrhUy!6@~ya-BABLQ*%>(SGnLlaMlDcg7{mKN&T+H?kgRQ+Ult}fx@e} zzhXih^CXI1GxKH+$bKE`+{%M9$WdQSY+u=OznRv6OnMGLq<#RshBlQQJ&0E!v0jCC zcw~9y!iBv2$ZZr%o#Ag9rd0u0%6f`8g0r@V74^PJhqMhdf}| z=R%3MSJxfG7R_;|E=r<)QC|1Z5AA(Z+Fe)9^(M66`OA)o7KTqXl`KPMqT7)D9`WRf zK2_(n-w3C3R7s+)9+NY3s+XRE_E#*8IkD!99VH-;adjRi`sf9V6>~USTigd$spAU3 zd1gr_8b*M=v1ea7+uyrJQ_jF~X9YG5I&HewlP~lG4|^mVbVy!qn=%ufKP2(&)$u>X z*Yl9`x#5Ls&QCGeBo=%gBGR4h;t0>t%YE@|P=mVaqQuyq>$+|6u;)ozI{RHACX}j> z8@kMHpK@L>&c|cxQ1o6OLZhE~cS9oddB!FPiQ6cMZs~r8H`~(YfKoSyP#UQU_N*V_ zYIiWy;w#W6foo%Qde@RrOW^!!fX>gA=mlg%jKles6$J}h%;nYOW!gJkKiCvKsFib7 zPy!iCWDnt5w9h1id1zxNBsMW+d$j;8;zH@4bmh7H7@gm>Oom3cYzcJg=C5`tfq0uG z%lnD&Ra%Bb!`a`oCNQ4;>t;V*0kp*9riDXGm1ufKBg8(1=eiiO5xfxKl?WE>LdB>_ zqG$pg2)UfBPI+;~S?I2oQ!YQV->g9bydcPLrV#o(`&&h{@t`n<-{~RRy~S#k@_e%0 zY6{9A~eOW+=4Wbs`Ena;Ok5v!VpFfq65 zA+6#dcpD=2YQPQTJX3k5Ztnc9!i(6gNsYg)Jm~2;K1T;cWULD)np;s6vBacKyN6r@ z57iP7y(M$qeTOFIvKSPtLiGYlZ=5Iv948$HY8kW#Fgr&3@`{1OanSbPI%HO%_Y`n2 z6ublAO$<$o#hi~;?$u{`TW*y8+gHfNPy)n2Iy6Xkn)$rPZM7MH^X5W5IxeaPFY3+{ zGp#0p9b5}1bymDW4_r&=B^?0OAP%f8hd5{d2Smcnd_Dr#5|cf=?-T>7U_syGpIim6e&qh{ z$~Sd;h+J-4sM#0Cw}YGa>r|Qzyl2Ad!@eI}A;;Fw{8Mj10Biw$${gFv1XuTc*e7z# z3~UtP!ZjMT(4@Yom~g?)`FB=+Encu4n_GR9|Ie8f72Pl#A1yZ9`b$&&bagAA?W4@8 z*%j`&Gjff|xc>fc)G0H!ZW<0yfXKPt#H^NDBJvhfFW2zwdYBTFHqSj(J$n}#G3u`@ z;64Pr<_}yR^b_7Gyre=`YhYE@TI*E!dW_2EZrFP!_2XmFxynW+!Vdt-f2+eQkrMav z-_4TvKL2{Nkh#_leTJ?f>Ic4J+%z0=(E%<+OPfiUS=*i9+HcjiAq}?O+-hFj!+^x4 z$Z!8-P`NzHX*LhrLugd&J->dSgSjGfEzS0*f$2SD!N#_PkV#RKy4oLpLG>?w>w6FO zOQ}S&=f%7Ph*nXZWY;1$=>(@_-$@zd~_fUNu+EKP0s zvDKtDFryNBaL;pe5EEwpIOmNjjkYVYUwyR#_$=_FY0cQ_I?DGBp_sRd?l0p9NV*_1 z?sN*U)ex0t-|0?}FA<7)F@SfMfKw0ncdXMQbmH#cqK%Oim|K?*I&MPd+OF^^d8X9q zwB}{{&+mIG>&VIefNSrOEC9xRiI}4X704sTE_~HKm D=3z=< literal 0 HcmV?d00001 diff --git a/charts/kubezero-timemachine/charts/gemini/templates/NOTES.txt b/charts/kubezero-timemachine/charts/gemini/templates/NOTES.txt new file mode 100644 index 0000000..6fb90d2 --- /dev/null +++ b/charts/kubezero-timemachine/charts/gemini/templates/NOTES.txt @@ -0,0 +1,30 @@ +Gemini is now installed! + +To start using Gemini, create a SnapshotGroup. You can use an +existing PVC, or ask Gemini to create one for you. + +apiVersion: gemini.fairwinds.com/v1beta1 +kind: SnapshotGroup +metadata: + name: test-volume +spec: + persistentVolumeClaim: + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + schedule: + - every: 10 minutes + keep: 3 + - every: hour + keep: 1 + - every: day + keep: 1 + - every: month + keep: 1 + - every: year + keep: 1 + +Read more at https://github.com/FairwindsOps/gemini diff --git a/charts/kubezero-timemachine/charts/gemini/templates/_helpers.tpl b/charts/kubezero-timemachine/charts/gemini/templates/_helpers.tpl new file mode 100644 index 0000000..388f494 --- /dev/null +++ b/charts/kubezero-timemachine/charts/gemini/templates/_helpers.tpl @@ -0,0 +1,56 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "gemini.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 "gemini.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 "gemini.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Standard labels +*/}} +{{- define "gemini.labels" -}} +app: {{ include "gemini.name" . }} +{{- if not .Values.templateOnly }} +app.kubernetes.io/name: {{ include "gemini.name" . }} +helm.sh/chart: {{ include "gemini.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} +{{- end -}} + +{{/* +Standard selector +*/}} +{{- define "gemini.selectors" -}} +app: {{ include "gemini.name" . }} +{{- if not .Values.templateOnly }} +app.kubernetes.io/name: {{ include "gemini.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/charts/kubezero-timemachine/charts/gemini/templates/deployment.yaml b/charts/kubezero-timemachine/charts/gemini/templates/deployment.yaml new file mode 100644 index 0000000..ed1088e --- /dev/null +++ b/charts/kubezero-timemachine/charts/gemini/templates/deployment.yaml @@ -0,0 +1,46 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "gemini.fullname" . }}-controller + labels: + app: gemini +spec: + replicas: 1 + selector: + matchLabels: + app: gemini + template: + metadata: + labels: + app: gemini + spec: + {{- if .Values.rbac.create }} + serviceAccountName: {{ include "gemini.fullname" . }}-controller + {{- else }} + serviceAccountName: {{ .Values.rbac.serviceAccountName }} + {{- end }} + nodeSelector: + node-role.kubernetes.io/master: "" + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + containers: + - command: + - gemini + {{- with .Values.verbosity }} + - -v + - {{ . | quote }} + {{- end }} + image: '{{.Values.image.repository}}:{{.Values.image.tag}}' + imagePullPolicy: '{{.Values.image.pullPolicy}}' + name: gemini-controller + resources: + {{- toYaml .Values.resources | nindent 12 }} + securityContext: + allowPrivilegeEscalation: false + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: + - ALL diff --git a/charts/kubezero-timemachine/charts/gemini/templates/rbac.yaml b/charts/kubezero-timemachine/charts/gemini/templates/rbac.yaml new file mode 100644 index 0000000..6f900d0 --- /dev/null +++ b/charts/kubezero-timemachine/charts/gemini/templates/rbac.yaml @@ -0,0 +1,62 @@ +{{- if .Values.rbac.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "gemini.fullname" . }}-controller + labels: + {{- include "gemini.labels" . | nindent 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "gemini.fullname" . }}-controller + labels: + {{- include "gemini.labels" . | nindent 4 }} +rules: + - apiGroups: + - gemini.fairwinds.com + resources: + - snapshotgroups + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - snapshot.storage.k8s.io + - '' + resources: + - volumesnapshots + - persistentvolumeclaims + verbs: + - get + - list + - create + - update + - delete + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - create + - delete +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "gemini.fullname" . }}-controller + labels: + {{- include "gemini.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "gemini.fullname" . }}-controller +subjects: + - kind: ServiceAccount + name: {{ include "gemini.fullname" . }}-controller + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/charts/kubezero-timemachine/charts/gemini/templates/test_crd.yaml b/charts/kubezero-timemachine/charts/gemini/templates/test_crd.yaml new file mode 100644 index 0000000..0f5b63a --- /dev/null +++ b/charts/kubezero-timemachine/charts/gemini/templates/test_crd.yaml @@ -0,0 +1,44 @@ +{{- if and .Values.testMode (not .Release.IsUpgrade) }} +{{- if not (.Capabilities.APIVersions.Has "snapshot.storage.k8s.io/v1beta1/VolumeSnapshot") }} +kind: CustomResourceDefinition +metadata: + name: volumesnapshots.snapshot.storage.k8s.io + annotations: + api-approved.kubernetes.io: "unapproved - test mode" + helm.sh/hook: pre-install + helm.sh/hook-delete-policy: before-hook-creation +{{- if .Capabilities.APIVersions.Has "apiextensions.k8s.io/v1/CustomResourceDefinition" }} +apiVersion: apiextensions.k8s.io/v1 +spec: + versions: + - name: v1beta1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object +{{- else }} +apiVersion: apiextensions.k8s.io/v1beta1 +spec: + versions: + - name: v1beta1 + served: true + storage: true + validation: + openAPIV3Schema: + type: object + properties: + spec: + type: object +{{- end }} + group: snapshot.storage.k8s.io + scope: Namespaced + names: + plural: volumesnapshots + singular: volumesnapshot + kind: VolumeSnapshot +{{- end }} +{{- end }} diff --git a/charts/kubezero-timemachine/charts/gemini/values.yaml b/charts/kubezero-timemachine/charts/gemini/values.yaml new file mode 100644 index 0000000..07ec88a --- /dev/null +++ b/charts/kubezero-timemachine/charts/gemini/values.yaml @@ -0,0 +1,25 @@ +image: + # image.pullPolicy -- imagePullPolicy - Highly recommended to leave this as `Always` + pullPolicy: Always + # image.repository -- Repository for the gemini image + repository: quay.io/fairwinds/gemini + # image.tag -- The gemini image tag to use + tag: "0.1" + +rbac: + # rbac.create -- If true, create a new ServiceAccount and attach permissions + create: true + # If rbac.create is false, the name of an existing ServiceAccount to use + serviceAccountName: + +# verbosity -- How verbose the controller logs should be +verbosity: 5 + +# resources -- The resources block for the controller pods +resources: + requests: + memory: 64Mi + cpu: 25m + limits: + memory: 512Mi + cpu: 200m diff --git a/charts/kubezero-timemachine/run-on-controller.patch b/charts/kubezero-timemachine/run-on-controller.patch new file mode 100644 index 0000000..59e2320 --- /dev/null +++ b/charts/kubezero-timemachine/run-on-controller.patch @@ -0,0 +1,15 @@ +diff -rtubN charts/gemini/templates/deployment.yaml charts/gemini.zdt/templates/deployment.yaml +--- charts/gemini/templates/deployment.yaml 2021-04-19 12:00:43.605005861 +0200 ++++ charts/gemini.zdt/templates/deployment.yaml 2021-04-19 12:00:08.365005781 +0200 +@@ -19,6 +19,11 @@ + {{- else }} + serviceAccountName: {{ .Values.rbac.serviceAccountName }} + {{- end }} ++ nodeSelector: ++ node-role.kubernetes.io/master: "" ++ tolerations: ++ - effect: NoSchedule ++ key: node-role.kubernetes.io/master + containers: + - command: + - gemini diff --git a/charts/kubezero-timemachine/update.sh b/charts/kubezero-timemachine/update.sh new file mode 100755 index 0000000..3817ad9 --- /dev/null +++ b/charts/kubezero-timemachine/update.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -ex + +export VERSION=0.0.6 + +rm -rf charts/gemini +helm pull fairwinds-stable/gemini --untar --untardir charts + +# Patch for istiod to control plane +patch -p0 -i run-on-controller.patch --no-backup-if-mismatch diff --git a/charts/kubezero/bootstrap.sh b/charts/kubezero/bootstrap.sh index c1bf05e..b1eb0ae 100755 --- a/charts/kubezero/bootstrap.sh +++ b/charts/kubezero/bootstrap.sh @@ -211,19 +211,19 @@ function logging-post() { ## MAIN ## if [ $1 == "deploy" ]; then for t in ${ARTIFACTS[@]}; do - is_enabled $t && _helm apply $t + is_enabled $t && _helm apply $t || true done # If artifact enabled and has crds install elif [ $1 == "crds" ]; then for t in ${ARTIFACTS[@]}; do - is_enabled $t && has_crds $t && _helm crds $t + is_enabled $t && has_crds $t && _helm crds $t || true done # Delete in reverse order, continue even if errors elif [ $1 == "delete" ]; then set +e for (( idx=${#ARTIFACTS[@]}-1 ; idx>=0 ; idx-- )) ; do - is_enabled ${ARTIFACTS[idx]} && _helm delete ${ARTIFACTS[idx]} + is_enabled ${ARTIFACTS[idx]} && _helm delete ${ARTIFACTS[idx]} || true done fi diff --git a/charts/kubezero/templates/argoless.yaml b/charts/kubezero/templates/argoless.yaml index 229f6b4..9a733d1 100644 --- a/charts/kubezero/templates/argoless.yaml +++ b/charts/kubezero/templates/argoless.yaml @@ -1,6 +1,6 @@ {{- if not .Values.argo }} -{{- $artifacts := list "calico" "cert-manager" "kiam" "aws-node-termination-handler" "aws-ebs-csi-driver" "aws-efs-csi-driver" "local-volume-provisioner" "local-path-provisioner" "istio" "istio-ingress" "metrics" "logging" "argocd" }} +{{- $artifacts := list "calico" "cert-manager" "kiam" "aws-node-termination-handler" "aws-ebs-csi-driver" "aws-efs-csi-driver" "local-volume-provisioner" "local-path-provisioner" "istio" "istio-ingress" "metrics" "logging" "argocd" "timemachine" }} {{- if .Values.global }} global: diff --git a/charts/kubezero/templates/timemachine.yaml b/charts/kubezero/templates/timemachine.yaml new file mode 100644 index 0000000..5a55717 --- /dev/null +++ b/charts/kubezero/templates/timemachine.yaml @@ -0,0 +1,8 @@ +{{- define "timemachine-values" }} +{{- end }} + + +{{- define "timemachine-argo" }} +{{- end }} + +{{ include "kubezero-app.app" . }} diff --git a/charts/kubezero/values.yaml b/charts/kubezero/values.yaml index 4b7efc5..66b5f5e 100644 --- a/charts/kubezero/values.yaml +++ b/charts/kubezero/values.yaml @@ -23,6 +23,9 @@ kiam: aws-node-termination-handler: enabled: false +timemachine: + enabled: false + local-volume-provisioner: enabled: false -- 2.40.1 From 57097d4dd94db00f9b78060e8940055f9249b217 Mon Sep 17 00:00:00 2001 From: Stefan Reimer Date: Mon, 19 Apr 2021 13:19:30 +0200 Subject: [PATCH 3/3] fix: enable crds for aws-ebs-csi-driver to make snapshots work --- charts/kubezero/values.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/kubezero/values.yaml b/charts/kubezero/values.yaml index 66b5f5e..7fd05c5 100644 --- a/charts/kubezero/values.yaml +++ b/charts/kubezero/values.yaml @@ -34,6 +34,7 @@ local-path-provisioner: aws-ebs-csi-driver: enabled: false + crds: true aws-efs-csi-driver: enabled: false -- 2.40.1