From f44b90ab396e93c67b5c8e394038ca74924e4562 Mon Sep 17 00:00:00 2001 From: chrisleekr Date: Sat, 21 Nov 2020 14:58:21 +1100 Subject: [PATCH] Updated code for MySQL operator (#2) * Updated code --- .github/workflows/main.yml | 11 ++- .gitignore | 1 + .gitlab-ci.yml | 10 ++- .vscode/settings.json | 15 +++- README.md | 54 ++++++------ build/Dockerfile | 7 +- helm/nvm-db/.helmignore | 22 +++++ helm/nvm-db/Chart.yaml | 5 ++ .../mysql-operator/mysql-cluster.yaml | 20 +++++ .../mysql-operator/mysql-secrets.yaml | 10 +++ helm/nvm-db/values.yaml | 11 +++ helm/nvm/Chart.yaml | 2 +- .../nvm/templates/apps/apps-ingress-root.yaml | 22 +++++ helm/nvm/templates/apps/apps-ingress.yaml | 9 +- .../nvm/templates/mysql/mysql-deployment.yaml | 42 ---------- helm/nvm/templates/mysql/mysql-pv.yaml | 25 ------ helm/nvm/templates/mysql/mysql-secret.yaml | 9 -- helm/nvm/templates/mysql/mysql-services.yaml | 12 --- helm/nvm/values.yaml | 82 ++++--------------- scripts/update-hosts.sh | 4 +- terraform/main.tf | 35 +++++++- 21 files changed, 211 insertions(+), 197 deletions(-) create mode 100644 helm/nvm-db/.helmignore create mode 100644 helm/nvm-db/Chart.yaml create mode 100644 helm/nvm-db/templates/mysql-operator/mysql-cluster.yaml create mode 100644 helm/nvm-db/templates/mysql-operator/mysql-secrets.yaml create mode 100644 helm/nvm-db/values.yaml create mode 100644 helm/nvm/templates/apps/apps-ingress-root.yaml delete mode 100644 helm/nvm/templates/mysql/mysql-deployment.yaml delete mode 100644 helm/nvm/templates/mysql/mysql-pv.yaml delete mode 100644 helm/nvm/templates/mysql/mysql-secret.yaml delete mode 100644 helm/nvm/templates/mysql/mysql-services.yaml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2f25618..44a879c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,15 +8,15 @@ jobs: - name: Install Terraform run: | cd /tmp - wget https://releases.hashicorp.com/terraform/0.13.4/terraform_0.13.4_linux_amd64.zip - unzip terraform_0.13.4_linux_amd64.zip + wget https://releases.hashicorp.com/terraform/0.13.5/terraform_0.13.5_linux_amd64.zip + unzip terraform_0.13.5_linux_amd64.zip sudo mv terraform /usr/local/bin terraform version - name: Install Helm run: | cd /tmp - wget https://get.helm.sh/helm-v3.3.4-linux-amd64.tar.gz - tar xvfz helm-v3.3.4-linux-amd64.tar.gz + wget https://get.helm.sh/helm-v3.4.1-linux-amd64.tar.gz + tar xvfz helm-v3.4.1-linux-amd64.tar.gz sudo mv linux-amd64/helm /usr/local/bin/helm helm version - name: Checkout source code @@ -26,6 +26,9 @@ jobs: cd $GITHUB_WORKSPACE/helm/nvm helm lint helm template . > template + cd $GITHUB_WORKSPACE/helm/nvm-db + helm lint + helm template . > template - name: Lint Terraform run: | cd $GITHUB_WORKSPACE/terraform diff --git a/.gitignore b/.gitignore index 8b5946a..c0d0c74 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ terraform/terraform.tfstate terraform/terraform.tfstate.backup terraform/.terraform.tfstate.lock.info helm/nvm/template +helm/nvm-db/template diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 62bd099..fa7d5fe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,16 +20,22 @@ lint-helm: artifacts: paths: - helm/nvm/template + - helm/nvm-db/template expire_in: "7 days" script: - - cd helm/nvm + - pushd helm/nvm - helm lint - helm template . > template + - popd + - pushd helm/nvm-db + - helm lint + - helm template . > template + - popd lint-terraform: stage: lint image: $REGISTRY_DOMAIN/chrisleekr/k8s-nodejs-vuejs-mysql-boilerplate:build script: - - cd terraform + - pushd terraform - terraform init - terraform validate diff --git a/.vscode/settings.json b/.vscode/settings.json index b21878a..5ea8495 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,5 +9,18 @@ ".git": true, "**/.DS_Store": true, "**/.vscode": true - } + }, + "cSpell.words": [ + "Autoscaler", + "Grafana", + "Kubernetes", + "Minikube", + "Presslabs", + "chrisleekr", + "containerised", + "kubectl", + "popd", + "pushd", + "vuejs" + ] } diff --git a/README.md b/README.md index a1e0a12..0aa8b43 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ -# Kubernetes for Node.js (REST API) + Vue.js (Frontend/Backend) + MySQL Boilerplate +# Kubernetes sample project for Node.js (REST API) + Vue.js (Frontend/Backend) + MySQL Boilerplate This project demonstrates simple IaC (Infrastructure as Code) for [NVM boilerplate](https://github.com/chrisleekr/nodejs-vuejs-mysql-boilerplate) to Minikube. -This is not for a production use. +This is a Kubernetes sample project, not for a production use. ## Prerequisites -- [Minikube v1.13.1](https://kubernetes.io/docs/tasks/tools/install-minikube/) -- [Kubernetes v.1.19.2](https://kubernetes.io/docs/tasks/tools/install-kubectl/) -- [Helm v3.3.4](https://helm.sh/docs/intro/install/) -- [Terraform v0.13.3](https://learn.hashicorp.com/tutorials/terraform/install-cli) +- [Minikube v1.15.1](https://kubernetes.io/docs/tasks/tools/install-minikube/) +- [Kubernetes v.1.19.4](https://kubernetes.io/docs/tasks/tools/install-kubectl/) +- [Helm v3.4.1](https://helm.sh/docs/intro/install/) +- [Terraform v0.13.5](https://learn.hashicorp.com/tutorials/terraform/install-cli) ## How to test in your Minikube @@ -38,32 +38,36 @@ This is not for a production use. ## With this project, you can find - Sample Terraform -- Sample Helm charts to deploy multiple micro-services +- Sample Helm charts to deploy multiple containerised micro-services -## Repository: Node.js + Vue.js + MySQL Boilerplate +## Micro-services Repository: Node.js + Vue.js + MySQL Boilerplate - [https://github.com/chrisleekr/nodejs-vuejs-mysql-boilerplate](https://github.com/chrisleekr/nodejs-vuejs-mysql-boilerplate) -## Todo +## Presslabs MySQL Operator -- [ ] Update MySQL with a replicated stateful application -- [ ] Add HorizontalPodAutoscaler +To see orchestrator, run following port forward and open [http://localhost:8080](http://localhost:8080) + +```bash +$ kubectl -nnvm-db port-forward service/presslabs-mysql-operator 8080:80 +``` + +To see operator logs, run following command -## Troubleshooting +```bash +$ kubectl -nnvm-db logs presslabs-mysql-operator-0 -c operator -f +``` -### Failed to enable ingress in Mac OS +To access mysql, run following command ```bash -$ minikube addons enable ingress -❌ Exiting due to MK_USAGE: Due to networking limitations of driver docker on darwin, ingress addon is not supported. -Alternatively to use this addon you can use a vm-based driver: - - 'minikube start --vm=true' - -To track the update on this work in progress feature please check: -https://github.com/kubernetes/minikube/issues/7332 -$ minikube stop -$ minikube delete -$ minikube start --vm=true -$ minikube addons enable ingress +$ kubectl -nnvm-db port-forward mysql-cluster-mysql-0 3307:3306 +$ mysql -h127.0.0.1 -uroot -proot -P3307 boilerplate ``` + +## Todo + +- [x] Update MySQL with a replicated stateful application - Use presslabs/mysql-operator +- [ ] Expose MySQL write node for migration to avoid api migration failure +- [ ] Add HorizontalPodAutoscaler +- [ ] Add Prometheus and Grafana diff --git a/build/Dockerfile b/build/Dockerfile index 79b68ee..965a7b7 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,10 +1,11 @@ FROM alpine:edge -ENV TERRAFORM_VERSION=0.13.4-r0 -ENV HELM_VERSION=3.3.4-r0 +ENV TERRAFORM_VERSION=0.13.5-r0 +ENV HELM_VERSION=3.4.0-r0 RUN apk --no-cache add \ -X http://dl-cdn.alpinelinux.org/alpine/edge/testing \ terraform=$TERRAFORM_VERSION \ - helm=$HELM_VERSION + helm=$HELM_VERSION \ + bash=5.0.18-r0 diff --git a/helm/nvm-db/.helmignore b/helm/nvm-db/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/helm/nvm-db/.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/helm/nvm-db/Chart.yaml b/helm/nvm-db/Chart.yaml new file mode 100644 index 0000000..5bcc34d --- /dev/null +++ b/helm/nvm-db/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: nvm-db +description: A Helm chart for Kubernetes +version: 0.1.3 +icon: https://github.com/chrisleekr/nodejs-vuejs-mysql-boilerplate/raw/master/frontend-nuxt/static/icon.png diff --git a/helm/nvm-db/templates/mysql-operator/mysql-cluster.yaml b/helm/nvm-db/templates/mysql-operator/mysql-cluster.yaml new file mode 100644 index 0000000..572056c --- /dev/null +++ b/helm/nvm-db/templates/mysql-operator/mysql-cluster.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: mysql.presslabs.org/v1alpha1 +kind: MysqlCluster +metadata: + name: mysql-cluster + namespace: {{$.Values.namespace}} +spec: + replicas: 2 + secretName: mysql-secret + podSpec: + resources: + requests: + memory: 1G + cpu: 200m + volumeSpec: + persistentVolumeClaim: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/helm/nvm-db/templates/mysql-operator/mysql-secrets.yaml b/helm/nvm-db/templates/mysql-operator/mysql-secrets.yaml new file mode 100644 index 0000000..44b14f1 --- /dev/null +++ b/helm/nvm-db/templates/mysql-operator/mysql-secrets.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: mysql-secret + namespace: {{$.Values.namespace}} +type: Opaque +data: + {{ range .Values.secrets }}{{.key}}: "{{.value | b64enc}}" + {{ end }} diff --git a/helm/nvm-db/values.yaml b/helm/nvm-db/values.yaml new file mode 100644 index 0000000..0605747 --- /dev/null +++ b/helm/nvm-db/values.yaml @@ -0,0 +1,11 @@ +namespace: nvm-db + +secrets: + - key: "ROOT_PASSWORD" + value: "root" + - key: "USER" + value: "boilerplate" + - key: "PASSWORD" + value: "boilerplate-password" + - key: "DATABASE" + value: "boilerplate" diff --git a/helm/nvm/Chart.yaml b/helm/nvm/Chart.yaml index 3d8d767..3549bb0 100644 --- a/helm/nvm/Chart.yaml +++ b/helm/nvm/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 name: nvm description: A Helm chart for Kubernetes -version: 0.1.2 +version: 0.1.5 icon: https://github.com/chrisleekr/nodejs-vuejs-mysql-boilerplate/raw/master/frontend-nuxt/static/icon.png diff --git a/helm/nvm/templates/apps/apps-ingress-root.yaml b/helm/nvm/templates/apps/apps-ingress-root.yaml new file mode 100644 index 0000000..b0dde83 --- /dev/null +++ b/helm/nvm/templates/apps/apps-ingress-root.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: "nginx" + nginx.ingress.kubernetes.io/app-root: /frontend-vue + nginx.ingress.kubernetes.io/enable-rewrite-log: "true" + name: ingress-app-root + namespace: {{$.Values.namespace}} +spec: + rules: + - host: "{{ $.Values.ingress.host }}" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: frontend-vue + port: + number: 80 diff --git a/helm/nvm/templates/apps/apps-ingress.yaml b/helm/nvm/templates/apps/apps-ingress.yaml index bb0e3d6..cd7bbbc 100644 --- a/helm/nvm/templates/apps/apps-ingress.yaml +++ b/helm/nvm/templates/apps/apps-ingress.yaml @@ -1,6 +1,6 @@ {{ range .Values.apps }} --- -apiVersion: networking.k8s.io/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-{{.name}} @@ -20,7 +20,10 @@ spec: http: paths: - path: {{ .ingress.path }} + pathType: Prefix backend: - serviceName: {{.name}} - servicePort: {{.containerPort}} + service: + name: {{.name}} + port: + number: {{.containerPort}} {{ end }} diff --git a/helm/nvm/templates/mysql/mysql-deployment.yaml b/helm/nvm/templates/mysql/mysql-deployment.yaml deleted file mode 100644 index 019dd11..0000000 --- a/helm/nvm/templates/mysql/mysql-deployment.yaml +++ /dev/null @@ -1,42 +0,0 @@ ---- -apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 -kind: Deployment -metadata: - name: {{.Values.mysql.name}} - namespace: {{.Values.namespace}}-db -spec: - selector: - matchLabels: - app: {{.Values.mysql.name}} - strategy: - type: Recreate - template: - metadata: - labels: - app: {{.Values.mysql.name}} - spec: - containers: - - image: "{{ .Values.mysql.image.repository }}:{{ .Values.mysql.image.version }}" - name: {{.Values.mysql.name}} - env: - {{- range .Values.mysql.env}} - - name: "{{.name}}" - value: "{{.value}}" - {{- end}} - {{- range .Values.mysql.secretEnv}} - - name: "{{.name}}" - valueFrom: - secretKeyRef: - name: "{{.secretKeyRef.name}}" - key: "{{.secretKeyRef.key}}" - {{- end}} - ports: - - containerPort: 3306 - name: mysql - volumeMounts: - - name: mysql-persistent-storage - mountPath: /var/lib/mysql - volumes: - - name: mysql-persistent-storage - persistentVolumeClaim: - claimName: mysql-pv-claim diff --git a/helm/nvm/templates/mysql/mysql-pv.yaml b/helm/nvm/templates/mysql/mysql-pv.yaml deleted file mode 100644 index fe7247d..0000000 --- a/helm/nvm/templates/mysql/mysql-pv.yaml +++ /dev/null @@ -1,25 +0,0 @@ ---- -apiVersion: v1 -kind: PersistentVolume -metadata: - name: mysql-pv-volume - namespace: {{.Values.namespace}}-db -spec: - capacity: - storage: 1Gi - accessModes: - - ReadWriteOnce - hostPath: - path: "/mnt/data" ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: mysql-pv-claim - namespace: {{.Values.namespace}}-db -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi diff --git a/helm/nvm/templates/mysql/mysql-secret.yaml b/helm/nvm/templates/mysql/mysql-secret.yaml deleted file mode 100644 index d3171f0..0000000 --- a/helm/nvm/templates/mysql/mysql-secret.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -kind: Secret -apiVersion: v1 -metadata: - name: {{$.Values.namespace}}-secret - namespace: {{$.Values.namespace}}-db -stringData: - {{ range .Values.secrets }}{{.key}}: "{{.value}}" - {{ end }} diff --git a/helm/nvm/templates/mysql/mysql-services.yaml b/helm/nvm/templates/mysql/mysql-services.yaml deleted file mode 100644 index 8867739..0000000 --- a/helm/nvm/templates/mysql/mysql-services.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: mysql - namespace: {{$.Values.namespace}}-db -spec: - ports: - - port: 3306 - selector: - app: mysql - clusterIP: None diff --git a/helm/nvm/values.yaml b/helm/nvm/values.yaml index ad18646..b4e7618 100644 --- a/helm/nvm/values.yaml +++ b/helm/nvm/values.yaml @@ -26,8 +26,8 @@ apps: configurationSnippet: | rewrite ^(/api)$ $1/ redirect; probes: - initialDelaySeconds: 30 - periodSeconds: 5 + initialDelaySeconds: 60 + periodSeconds: 60 path: / port: 3000 env: @@ -35,8 +35,6 @@ apps: value: "mysql.nvm-db" - name: "DB_PORT" value: 3306 - - name: "DB_NAME" - value: "boilerplate" - name: "DB_CONNECTION_LIMIT" value: 10 - name: "DB_DEBUG" @@ -74,6 +72,10 @@ apps: - name: "TZ" value: "Australia/Melbourne" secretEnv: + - name: "DB_NAME" + secretKeyRef: + name: "nvm-secret" + key: "db-name" - name: "DB_USER" secretKeyRef: name: "nvm-secret" @@ -82,33 +84,6 @@ apps: secretKeyRef: name: "nvm-secret" key: "db-password" - frontendNuxt: - name: frontend-nuxt - image: - repository: chrisleekr/nodejs-vuejs-mysql-boilerplate - version: frontend-nuxt-latest - pullPolicy: IfNotPresent - replicaCount: 1 - containerPort: 3000 - resources: - limits: - memory: 256Mi - cpu: 128m - ingress: - path: /frontend-nuxt(.*) - rewriteTarget: /frontend-nuxt$1 - configurationSnippet: | - rewrite ^(/frontend-nuxt)$ $1/ redirect; - probes: - initialDelaySeconds: 90 - periodSeconds: 30 - path: /frontend-nuxt/ - port: 3000 - env: - - name: "BASE_URL" - value: "/frontend-nuxt/" - - name: "API_URL" - value: "http://nvm-boilerplate.local/api" frontendVue: name: frontend-vue image: @@ -127,8 +102,8 @@ apps: configurationSnippet: | rewrite ^(/frontend-vue)$ $1/ redirect; probes: - initialDelaySeconds: 5 - periodSeconds: 5 + initialDelaySeconds: 60 + periodSeconds: 60 path: /frontend-vue/ port: 80 env: @@ -154,8 +129,8 @@ apps: configurationSnippet: | rewrite ^(/backend)$ $1/ redirect; probes: - initialDelaySeconds: 5 - periodSeconds: 5 + initialDelaySeconds: 60 + periodSeconds: 60 path: /backend/ port: 80 env: @@ -179,40 +154,15 @@ apps: configurationSnippet: | rewrite ^(/mailhog)$ $1/ redirect; probes: - initialDelaySeconds: 5 - periodSeconds: 5 + initialDelaySeconds: 60 + periodSeconds: 60 path: / port: 8025 -mysql: - name: mysql - image: - repository: chrisleekr/nodejs-vuejs-mysql-boilerplate - version: mysql-latest - pullPolicy: IfNotPresent - env: - - name: "MYSQL_DATABASE" - value: "boilerplate" - - name: "TZ" - value: "Australia/Melbourne" - secretEnv: - - name: "DB_PASSWORD" - secretKeyRef: - name: "nvm-secret" - key: "db-password" - - name: "MYSQL_ROOT_PASSWORD" - secretKeyRef: - name: "nvm-secret" - key: "db-root-password" - secrets: - - key: "db-root-password" - value: "root" - key: "db-user" - value: "root" + value: "boilerplate" - key: "db-password" - value: "root" - - key: "smtp-auth-user" - value: "" - - key: "smtp-auth-pass" - value: "" + value: "boilerplate-password" + - key: "db-name" + value: "boilerplate" diff --git a/scripts/update-hosts.sh b/scripts/update-hosts.sh index 61f5f9a..3fe5f2c 100755 --- a/scripts/update-hosts.sh +++ b/scripts/update-hosts.sh @@ -42,11 +42,11 @@ if grep -Fq "$INGRESS_HOST" $HOSTS_PATH > /dev/null then if [ $HOST_OS = "darwin" ] then - sudo sed -i '' "s/^.*$INGRESS_HOST\b.*$/$API_HOSTS_ENTRY/" $HOSTS_PATH + sudo sed -i '' "s/^.*$INGRESS_HOST/$API_HOSTS_ENTRY/" $HOSTS_PATH else sudo sed -i "s/^.*$INGRESS_HOST\b.*$/$API_HOSTS_ENTRY/" $HOSTS_PATH fi - + echo "Updated $INGRESS_HOST hosts entry" else echo "$API_HOSTS_ENTRY" | sudo tee -a $HOSTS_PATH diff --git a/terraform/main.tf b/terraform/main.tf index 3a003a1..c950f95 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -19,11 +19,42 @@ provider "helm" { } } -resource "helm_release" "local" { +resource "helm_release" "mysql-operator" { + depends_on = [ + kubernetes_namespace.nvm-db-namespace + ] + + name = "presslabs" + repository = "https://presslabs.github.io/charts" + chart = "mysql-operator" + version = "0.4.0" + namespace = "nvm-db" + timeout = 360 +} + +resource "helm_release" "nvm-db" { + depends_on = [ + kubernetes_namespace.nvm-db-namespace, + helm_release.mysql-operator + ] + + name = "nvm-db" + chart = "../helm/nvm-db" + namespace = "nvm-db" + timeout = 360 + +} + +resource "helm_release" "nvm" { + depends_on = [ + kubernetes_namespace.nvm-namespace, + helm_release.nvm-db + ] + name = "nvm" chart = "../helm/nvm" namespace = "nvm" - timeout = 300 + timeout = 600 set { name = "cluster.enabled"