From 932563510a4f32f58782b1fe4738a0d2006e010f Mon Sep 17 00:00:00 2001 From: Ricardo Rocha <rocha.porto@gmail.com> Date: Mon, 20 Jan 2020 16:57:40 +0100 Subject: [PATCH] Add sample application for gitops --- README.md | 102 ++++++++++-------- charts/gitops-getting-started/Chart.yaml | 4 + .../gitops-getting-started/requirements.yaml | 4 + .../gitops-getting-started/templates/psp.yaml | 91 ++++++++++++++++ charts/gitops-getting-started/values.yaml | 21 ++++ flux-values.yaml | 6 ++ helm-operator-values.yaml | 13 +++ namespaces/prod.yaml | 5 + namespaces/stg.yaml | 5 + releases/prod/values.yaml | 27 +++++ releases/stg/values.yaml | 27 +++++ secrets/prod/secrets.yaml | 14 +++ secrets/stg/secrets.yaml | 14 +++ 13 files changed, 286 insertions(+), 47 deletions(-) create mode 100644 charts/gitops-getting-started/Chart.yaml create mode 100644 charts/gitops-getting-started/requirements.yaml create mode 100644 charts/gitops-getting-started/templates/psp.yaml create mode 100644 charts/gitops-getting-started/values.yaml create mode 100644 flux-values.yaml create mode 100644 helm-operator-values.yaml create mode 100644 namespaces/prod.yaml create mode 100644 namespaces/stg.yaml create mode 100644 releases/prod/values.yaml create mode 100644 releases/stg/values.yaml create mode 100644 secrets/prod/secrets.yaml create mode 100644 secrets/stg/secrets.yaml diff --git a/README.md b/README.md index f4020c5..3ccea18 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,14 @@ # GitOps Getting Started -This repo acts as an example to manage application deployment and configuration -using GitOps and the tool Flux. +An example of an application deployment and configuration managed using GitOps +and the tool Flux. -The sample application has two parts: -* a frontend based on wordpress +The goal is to have a central git repo hosting all the configuration and +deployments for an application, including its dependencies. Permissions set in +this repo also define who is allowed to update the configuration. + +This example has two main components: +* a frontend web application based on wordpress * a backend MySQL database It should be enough to give you hints on how to manage your own deployments in @@ -32,70 +36,74 @@ see what goes in these resources. ## Structure and Releases The structure of this repo is as follows: -* **chart**: the umbrella chart, with defaults and any extra setup required +* **chart**: the umbrella chart. These is where all the default configuration + for the dependencies is stored, inside the values.yaml file. You can also add + custom manifests under the templates directory +* **namespaces**: Flux expects all the required namespaces to be defined here. + In this example we have both *prod* and *stg* * **releases**: the different deployments of the application (staging, production), -each with overrides or complements of the default values. These are defined as -Flux HelmRelease resources + each with overrides for the configuration as required - completing the default + values. These are Flux HelmRelease resources +* **secrets**: this is a special directory that is not part of standard Flux. In + the future it will not be required, but for now it holds the parts of the + values yaml definitions that are sensitive (and require encryption to be + safely committed to git) ## Secrets -Secrets are stored along the release values, but encrypted using the [helm -secrets](https://gitlab.cern.ch/helm/plugins/barbican) plugin - this makes them -also version controlled. - -To achieve this it means that for the moment they are not managed by Flux, a -better integration will appear later. +We recommend using the [helm secrets](https://gitlab.cern.ch/helm/plugins/barbican) +plugin to encrypt the files under the *secrets* directory. -You need to do the following once before installing flux: +As Flux does not understand this encryption method, we need to create these +secrets in advance, following something like: ```bash -kubectl -n hub create -f releases/prod/hub-secrets.yaml -kubectl -n hub-stg create -f releases/stg/hub-secrets.yaml +kubectl create namespace prod +kubectl create namespace stg + +kubectl create -f secrets/prod/secrets.yaml +kubectl create -f secrets/stg/secrets.yaml ``` -and update them manually everytime when you update secrets. +Remember that these resources are not managed by Flux. If you need to update +any part of the sensitive values yaml data, you need to update them manually +by doing: +``` +kubectl apply -f secrets/prod/secrets.yaml +kubectl apply -f secrets/stg/secrets.yaml +``` -## Deployment +In the near future there will be better integration of this way of handling +sensitive configuration data with Flux. -Next deploy the secrets - see the *secrets* section above. +## Deployment -Finally deploy Flux and point it to this repository (the git.url value below): +You need to deploy both the helm operator and flux itself: ```bash -$ cat flux-values.yaml -git: - path: releases,namespaces - pollInterval: 1m - readonly: true -rbac: - create: true - -$ helm install fluxcd/flux --namespace flux --name flux --values flux-values.yaml \ - --set git.url=https://gitlab.cern.ch/helm/releases/gitops-getting-started - -$ cat helm-operator-values.yaml -createCRD: true -chartsSyncInterval: 1m -configureRepositories: - enable: true - repositories: - - name: cern - url: https://registry.cern.ch/cern/charts -rbac: - create: true -git: - pollInterval: 1m - -$ helm install fluxcd/helm-operator --namespace flux --name helm-operator --values helm-operator-values.yaml +$ helm install fluxcd/helm-operator --namespace flux --name helm-operator + \ --version 0.4.0 --values helm-operator-values.yaml + +$ helm install fluxcd/flux --namespace flux --name flux --version 1.0.0 \ + --values flux-values.yaml \ + --set git.url=https://gitlab.cern.ch/helm/releases/gitops-getting-started ``` +The files *helm-operator-values.yaml* and *flux-values.yaml* contain the +configuration for each of the component. You can change these as you want. + Check the logs to see the multiple releases are being picked up: ``` -$ kubectl -n flux logs -f deployment.apps/flux-helm-operator +$ kubectl -n flux logs -f deployment.apps/helm-operator +$ kubectl -n flux logs -f deployment.apps/flux ``` All going well you should see them in helm: ```bash $ helm ls -NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE +NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE +flux 1 Mon Jan 20 23:04:34 2020 DEPLOYED flux-1.0.0 1.17.0 flux +gitops-getting-started 1 Mon Jan 20 23:17:48 2020 DEPLOYED gitops-getting-started-0.1.0 prod +gitops-getting-started-stg 1 Mon Jan 20 23:17:48 2020 DEPLOYED gitops-getting-started-0.1.0 stg +helm-operator 1 Mon Jan 20 23:04:32 2020 DEPLOYED helm-operator-0.4.0 1.0.0-rc5 flux ``` ## FAQ diff --git a/charts/gitops-getting-started/Chart.yaml b/charts/gitops-getting-started/Chart.yaml new file mode 100644 index 0000000..ecafbdb --- /dev/null +++ b/charts/gitops-getting-started/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +description: A Helm chart for a sample gitops application +name: gitops-getting-started +version: 0.1.0 diff --git a/charts/gitops-getting-started/requirements.yaml b/charts/gitops-getting-started/requirements.yaml new file mode 100644 index 0000000..2a7b6fa --- /dev/null +++ b/charts/gitops-getting-started/requirements.yaml @@ -0,0 +1,4 @@ +dependencies: + - name: wordpress + version: 8.1.1 + repository: https://kubernetes-charts.storage.googleapis.com diff --git a/charts/gitops-getting-started/templates/psp.yaml b/charts/gitops-getting-started/templates/psp.yaml new file mode 100644 index 0000000..f869a1b --- /dev/null +++ b/charts/gitops-getting-started/templates/psp.yaml @@ -0,0 +1,91 @@ +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ .Release.Name }}.restricted +spec: + privileged: false + # Required to prevent escalations to root. + allowPrivilegeEscalation: false + # This is redundant with non-root + disallow privilege escalation, + # but we can provide it for defense in depth. + requiredDropCapabilities: + - ALL + # Allow core volume types. + volumes: + - 'hostPath' + - 'configMap' + - 'emptyDir' + - 'secret' + - 'persistentVolumeClaim' + allowedHostPaths: + - pathPrefix: "/var/eos" + readOnly: true + - pathPrefix: "/opt/nvidia-driver" + readOnly: true + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + # Require the container to run without root privileges. + rule: 'MustRunAsNonRoot' + seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Release.Name }}.psp.restricted +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: ['{{ .Release.Name }}.restricted'] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ .Release.Name }}.psp.restricted +roleRef: + kind: ClusterRole + name: {{ .Release.Name }}.psp.restricted + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: Group + name: system:authenticated + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ .Release.Name }}.psp.restricted +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: ['{{ .Release.Name}}.restricted'] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ .Release.Name }}.psp.restricted +roleRef: + kind: Role + name: {{ .Release.Name }}.psp.restricted + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: ServiceAccount + name: default diff --git a/charts/gitops-getting-started/values.yaml b/charts/gitops-getting-started/values.yaml new file mode 100644 index 0000000..77936f2 --- /dev/null +++ b/charts/gitops-getting-started/values.yaml @@ -0,0 +1,21 @@ + +wordpress: + image: + registry: "docker.io" + repository: "bitnami/wordpress" + persistence: + enabled: false + service: + type: "NodePort" + + mariadb: + enabled: true + image: + registry: "docker.io" + repository: "bitnami/mariadb" + db: + name: "wordpress" + user: "wordpress" + master: + persistence: + enabled: false diff --git a/flux-values.yaml b/flux-values.yaml new file mode 100644 index 0000000..49901bb --- /dev/null +++ b/flux-values.yaml @@ -0,0 +1,6 @@ +git: + path: releases,namespaces + pollInterval: 5m + readonly: true +rbac: + create: true diff --git a/helm-operator-values.yaml b/helm-operator-values.yaml new file mode 100644 index 0000000..d41472e --- /dev/null +++ b/helm-operator-values.yaml @@ -0,0 +1,13 @@ +createCRD: true +chartsSyncInterval: 1m +configureRepositories: + enable: true + repositories: + - name: stable + url: https://kubernetes-charts.storage.googleapis.com + - name: cern + url: https://registry.cern.ch/chartrepo/cern +rbac: + create: true +git: + pollInterval: 5m diff --git a/namespaces/prod.yaml b/namespaces/prod.yaml new file mode 100644 index 0000000..6b93218 --- /dev/null +++ b/namespaces/prod.yaml @@ -0,0 +1,5 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: prod diff --git a/namespaces/stg.yaml b/namespaces/stg.yaml new file mode 100644 index 0000000..e43e6cc --- /dev/null +++ b/namespaces/stg.yaml @@ -0,0 +1,5 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: stg diff --git a/releases/prod/values.yaml b/releases/prod/values.yaml new file mode 100644 index 0000000..2a41551 --- /dev/null +++ b/releases/prod/values.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: helm.fluxcd.io/v1 +kind: HelmRelease +metadata: + name: gitops-getting-started + namespace: prod + annotations: + flux.weave.works/automated: "false" +spec: + releaseName: gitops-getting-started + chart: + git: https://gitlab.cern.ch/helm/releases/gitops-getting-started.git + path: charts/gitops-getting-started + ref: master + valuesFrom: + - secretKeyRef: + namespace: prod + name: gitops-getting-started-secrets + key: values.yaml + values: + wordpress: + service: + nodePorts: + http: "32700" + mariadb: + image: + tag: "10.3.21" diff --git a/releases/stg/values.yaml b/releases/stg/values.yaml new file mode 100644 index 0000000..bf5245d --- /dev/null +++ b/releases/stg/values.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: helm.fluxcd.io/v1 +kind: HelmRelease +metadata: + name: gitops-getting-started-stg + namespace: stg + annotations: + flux.weave.works/automated: "false" +spec: + releaseName: gitops-getting-started-stg + chart: + git: https://gitlab.cern.ch/helm/releases/gitops-getting-started.git + path: charts/gitops-getting-started + ref: master + valuesFrom: + - secretKeyRef: + namespace: stg + name: gitops-getting-started-secrets + key: values.yaml + values: + wordpress: + service: + nodePorts: + http: "32701" + mariadb: + image: + tag: "10.4.11" diff --git a/secrets/prod/secrets.yaml b/secrets/prod/secrets.yaml new file mode 100644 index 0000000..99c363e --- /dev/null +++ b/secrets/prod/secrets.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Secret +metadata: + name: gitops-getting-started-secrets + namespace: prod +type: Opaque +stringData: + values.yaml: |- + wordpress: + mariadb: + rootUser: + password: "rootsecret" + db: + password: "supersecret" diff --git a/secrets/stg/secrets.yaml b/secrets/stg/secrets.yaml new file mode 100644 index 0000000..debeaca --- /dev/null +++ b/secrets/stg/secrets.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Secret +metadata: + name: gitops-getting-started-secrets + namespace: stg +type: Opaque +stringData: + values.yaml: |- + wordpress: + mariadb: + rootUser: + password: "rootsecret" + db: + password: "supersecret" -- GitLab