From 620fe6b94906fd3bd54a950410235514e93f3d32 Mon Sep 17 00:00:00 2001 From: chrisleekr Date: Thu, 29 Dec 2022 23:35:12 +1100 Subject: [PATCH] feat: replace to oracle mysql operator (#4) --- .github/workflows/main.yml | 7 +- .gitlab-ci.yml | 4 - README.md | 53 ++++----- build/Dockerfile | 24 ++-- 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 | 13 --- helm/nvm/templates/apps/apps-migration.yaml | 8 +- helm/nvm/values.yaml | 42 +++++-- terraform/.terraform.lock.hcl | 82 +++++++++++++ terraform/main.tf | 109 +++--------------- terraform/mysql/innodbcluster/initialise.sh | 34 ++++++ terraform/mysql/innodbcluster/values.tmpl | 75 ++++++++++++ terraform/mysql/mysql-initialise.tf | 96 +++++++++++++++ terraform/mysql/mysql-innodbcluster.tf | 36 ++++++ terraform/mysql/mysql-operator.tf | 18 +++ terraform/mysql/output.tf | 11 ++ terraform/mysql/variables.tf | 1 + terraform/nvm/nvm.tf | 98 ++++++++++++++++ terraform/nvm/variables.tf | 13 +++ terraform/output.tf | 15 ++- terraform/prometheus/output.tf | 3 + terraform/prometheus/prometheus.tf | 46 ++++++++ terraform/prometheus/variables.tf | 8 ++ terraform/provider.tf | 49 ++++++++ 27 files changed, 678 insertions(+), 224 deletions(-) delete mode 100644 helm/nvm-db/.helmignore delete mode 100644 helm/nvm-db/Chart.yaml delete mode 100644 helm/nvm-db/templates/mysql-operator/mysql-cluster.yaml delete mode 100644 helm/nvm-db/templates/mysql-operator/mysql-secrets.yaml delete mode 100644 helm/nvm-db/values.yaml create mode 100644 terraform/.terraform.lock.hcl create mode 100755 terraform/mysql/innodbcluster/initialise.sh create mode 100644 terraform/mysql/innodbcluster/values.tmpl create mode 100644 terraform/mysql/mysql-initialise.tf create mode 100644 terraform/mysql/mysql-innodbcluster.tf create mode 100644 terraform/mysql/mysql-operator.tf create mode 100644 terraform/mysql/output.tf create mode 100644 terraform/mysql/variables.tf create mode 100644 terraform/nvm/nvm.tf create mode 100644 terraform/nvm/variables.tf create mode 100644 terraform/prometheus/output.tf create mode 100644 terraform/prometheus/prometheus.tf create mode 100644 terraform/prometheus/variables.tf create mode 100644 terraform/provider.tf diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 44a879c..eb85aff 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,8 +8,8 @@ jobs: - name: Install Terraform run: | cd /tmp - wget https://releases.hashicorp.com/terraform/0.13.5/terraform_0.13.5_linux_amd64.zip - unzip terraform_0.13.5_linux_amd64.zip + wget https://releases.hashicorp.com/terraform/1.3.6/terraform_1.3.6_linux_amd64.zip + unzip terraform_1.3.6_linux_amd64.zip sudo mv terraform /usr/local/bin terraform version - name: Install Helm @@ -26,9 +26,6 @@ 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/.gitlab-ci.yml b/.gitlab-ci.yml index fa7d5fe..68eb8c7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,10 +27,6 @@ lint-helm: - helm lint - helm template . > template - popd - - pushd helm/nvm-db - - helm lint - - helm template . > template - - popd lint-terraform: stage: lint diff --git a/README.md b/README.md index c300517..756c2ed 100644 --- a/README.md +++ b/README.md @@ -6,22 +6,21 @@ This is a Kubernetes sample project, not for a production use. ## Prerequisites -- [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/) +- [Minikube v1.28.0](https://kubernetes.io/docs/tasks/tools/install-minikube/) +- [Kubernetes v1.20.2](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) +- [Terraform v1.3.6](https://learn.hashicorp.com/tutorials/terraform/install-cli) ## How to test in your Minikube 1. Start minikube ```bash - $ minikube start - $ minikube addons enable ingress - $ minikube addons enable metrics-server + $ minikube start --addons ingress,metrics-server ``` 2. Go to `terraform` folder + 3. Run Terraform commands ```bash @@ -42,6 +41,8 @@ This is a Kubernetes sample project, not for a production use. $ ./script/update-hosts.sh ``` +5. Open new browser and go to [nvm-boilerplate.local](http://nvm-boilerplate.local) + ## With this project, you can find - Sample Terraform @@ -51,29 +52,20 @@ This is a Kubernetes sample project, not for a production use. - [https://github.com/chrisleekr/nodejs-vuejs-mysql-boilerplate](https://github.com/chrisleekr/nodejs-vuejs-mysql-boilerplate) -## Presslabs MySQL Operator - -To see orchestrator, run following port forward. - -```bash -$ kubectl -nnvm-db port-forward service/presslabs-mysql-operator 8080:80 -``` - -![image](https://user-images.githubusercontent.com/5715919/100513791-ed9ff900-31c3-11eb-80c6-7a3d332d272d.png) +## Oracle MySQL Operator -And open [http://localhost:8080](http://localhost:8080) - -To see operator logs, run following command +To access MySQL, run following command ```bash -$ kubectl -nnvm-db logs presslabs-mysql-operator-0 -c operator -f -``` +# Get root password +$ kubectl -nmysql get secrets mysql-innodbcluster-cluster-secret -oyaml +$ echo "" | base64 -d -To access mysql, run following command +# Port forward +$ kubectl -nmysql port-forward svc/mysql-innodbcluster 6446:6446 -```bash -$ kubectl -nnvm-db port-forward mysql-cluster-mysql-0 3307:3306 -$ mysql -h127.0.0.1 -uroot -proot -P3307 boilerplate +# Access to R/W MySQL +$ mysql -h127.0.0.1 -uroot -p -P6446 boilerplate ``` ## Horizontal Pod Autoscaler @@ -99,10 +91,18 @@ Apply complete! Resources: 0 added, 1 changed, 0 destroyed. Outputs: -grafana_admin_password = ynSVNykpU72RM5x6 +grafana_admin_password = +mysql_boilerplate_password = +mysql_root_password = +``` + +You can get the password by executing the following command: + +```bash +terraform output grafana_admin_password ``` -For example, as above, if admin password `ynSVNykpU72RM5x6` then you can login Grafana with `admin`/`ynSVNykpU72RM5x6`. +With the password, you can login Grafana with `admin`/``. ![image](https://user-images.githubusercontent.com/5715919/100513860-4a031880-31c4-11eb-8ef2-04202055aa78.png) @@ -112,3 +112,4 @@ For example, as above, if admin password `ynSVNykpU72RM5x6` then you can login G - [x] Add HorizontalPodAutoscaler - [x] Add Prometheus and Grafana - [x] Expose MySQL write node for migration to avoid api migration failure +- [x] Replaced presslab/mysql-operator to Oracle MySQL operator/InnoDB cluster diff --git a/build/Dockerfile b/build/Dockerfile index 965a7b7..1640f6a 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,11 +1,19 @@ -FROM alpine:edge +FROM alpine:3.17 -ENV TERRAFORM_VERSION=0.13.5-r0 -ENV HELM_VERSION=3.4.0-r0 +ENV TERRAFORM_VERSION=1.3.6 +ENV HELM_VERSION=3.4.1 RUN apk --no-cache add \ - -X http://dl-cdn.alpinelinux.org/alpine/edge/testing \ - terraform=$TERRAFORM_VERSION \ - helm=$HELM_VERSION \ - bash=5.0.18-r0 - + bash=5.2.15-r0 \ + curl=7.87.0-r0 && \ + # Install Terraform + wget https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \ + unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \ + mv terraform /usr/local/bin/ && \ + terraform --version && \ + # Install helm + curl -L https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz | tar xz && \ + mv linux-amd64/helm /usr/bin/helm && \ + chmod +x /usr/bin/helm && \ + rm -rf linux-amd64 && \ + helm version diff --git a/helm/nvm-db/.helmignore b/helm/nvm-db/.helmignore deleted file mode 100644 index 50af031..0000000 --- a/helm/nvm-db/.helmignore +++ /dev/null @@ -1,22 +0,0 @@ -# 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 deleted file mode 100644 index 5bcc34d..0000000 --- a/helm/nvm-db/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index 7ee1d2b..0000000 --- a/helm/nvm-db/templates/mysql-operator/mysql-cluster.yaml +++ /dev/null @@ -1,20 +0,0 @@ ---- -apiVersion: mysql.presslabs.org/v1alpha1 -kind: MysqlCluster -metadata: - name: mysql-cluster - namespace: {{$.Values.namespace}} -spec: - replicas: {{$.Values.replicas}} - secretName: mysql-secret - podSpec: - resources: - requests: - memory: 1G - cpu: 512m - 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 deleted file mode 100644 index 44b14f1..0000000 --- a/helm/nvm-db/templates/mysql-operator/mysql-secrets.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -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 deleted file mode 100644 index bfd3e43..0000000 --- a/helm/nvm-db/values.yaml +++ /dev/null @@ -1,13 +0,0 @@ -namespace: nvm-db - -replicas: 2 - -secrets: - - key: "ROOT_PASSWORD" - value: "root" - - key: "USER" - value: "boilerplate" - - key: "PASSWORD" - value: "boilerplate-password" - - key: "DATABASE" - value: "boilerplate" diff --git a/helm/nvm/templates/apps/apps-migration.yaml b/helm/nvm/templates/apps/apps-migration.yaml index d2b007b..d0b4fe0 100644 --- a/helm/nvm/templates/apps/apps-migration.yaml +++ b/helm/nvm/templates/apps/apps-migration.yaml @@ -7,10 +7,10 @@ metadata: labels: environment: {{$.Values.environment}} app: migration - annotations: - helm.sh/hook: "post-install,post-upgrade" - helm.sh/hook-weight: "1" - helm.sh/hook-delete-policy: hook-succeeded + # annotations: + # helm.sh/hook: "post-install,post-upgrade" + # helm.sh/hook-weight: "1" + # helm.sh/hook-delete-policy: hook-succeeded spec: backoffLimit: 3 activeDeadlineSeconds: 600 diff --git a/helm/nvm/values.yaml b/helm/nvm/values.yaml index ea8510d..22b8f01 100644 --- a/helm/nvm/values.yaml +++ b/helm/nvm/values.yaml @@ -13,15 +13,19 @@ migration: repository: chrisleekr/nodejs-vuejs-mysql-boilerplate version: api-latest env: - - name: "DB_HOST" - value: "mysql-cluster-mysql-master.nvm-db" - - name: "DB_PORT" - value: 3306 - name: "DB_CONNECTION_LIMIT" value: 10 - name: "DB_DEBUG" value: "true" secretEnv: + - name: "DB_HOST" + secretKeyRef: + name: "nvm-secret" + key: "db-host" + - name: "DB_PORT" + secretKeyRef: + name: "nvm-secret" + key: "db-port" - name: "DB_NAME" secretKeyRef: name: "nvm-secret" @@ -59,16 +63,10 @@ apps: path: / port: 3000 env: - - name: "DB_HOST" - value: "mysql.nvm-db" - - name: "DB_PORT" - value: 3306 - name: "DB_CONNECTION_LIMIT" value: 10 - name: "DB_DEBUG" value: "true" - - name: "JWT_SECRET_KEY" - value: "aaGhu2foo7sheithePhai4Aef" - name: "JWT_EXPIRES_IN" value: "1w" - name: "BCRYPT_SALTING_ROUND" @@ -100,6 +98,14 @@ apps: - name: "TZ" value: "Australia/Melbourne" secretEnv: + - name: "DB_HOST" + secretKeyRef: + name: "nvm-secret" + key: "db-host" + - name: "DB_PORT" + secretKeyRef: + name: "nvm-secret" + key: "db-port" - name: "DB_NAME" secretKeyRef: name: "nvm-secret" @@ -112,6 +118,14 @@ apps: secretKeyRef: name: "nvm-secret" key: "db-password" + - name: "JWT_SECRET_KEY" + secretKeyRef: + name: "nvm-secret" + key: "jwt-secret-key" + - name: "JWT_REFRESH_SECRET_KEY" + secretKeyRef: + name: "nvm-secret" + key: "jwt-refresh-secret-key" frontendVue: name: frontend-vue image: @@ -188,9 +202,17 @@ apps: port: 8025 secrets: + - key: "db-host" + value: "mysql-innodbcluster.mysql.svc.cluster.local" + - key: "db-port" + value: 6446 - key: "db-user" value: "boilerplate" - key: "db-password" value: "boilerplate-password" - key: "db-name" value: "boilerplate" + - key: "jwt-secret-key" + value: "" + - key: "jwt-refresh-secret-key" + value: "" diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl new file mode 100644 index 0000000..e6f1efd --- /dev/null +++ b/terraform/.terraform.lock.hcl @@ -0,0 +1,82 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/helm" { + version = "2.8.0" + constraints = "~> 2.8.0" + hashes = [ + "h1:abRryu69lsIGXctqjMVoaKqi74eE12Vzd2FLpds1/PI=", + "zh:1e42d1a04c07d4006844e477ca32b5f45b04f6525dbbbe00b6be6e6ec5a11c54", + "zh:2f87187cb48ccfb18d12e2c4332e7e822923b659e7339b954b7db78aff91529f", + "zh:391fe49b4d2dc07bc717248a3fc6952189cfc49c596c514ad72a29c9a9f9d575", + "zh:89272048e1e63f3edc3e83dfddd5a9fd4bd2a4ead104e67de1e14319294dedf1", + "zh:a5a057c3435a854389ce8a1d98a54aaa7cbab68aca7baa436a605897aa70ff7e", + "zh:b1098e53e1a8a3afcd325ecd0328662156b3d9c3d80948f19ba3a4eb870cee2b", + "zh:b676f949e8274a2b6c3fa41f5428ea597125579c7b93bb50bb73a5e295a7a447", + "zh:cdf7e9460f28c2dbfe49a79a5022bd0d474ff18120d340738aa35456ba77ebca", + "zh:e24b59b4ed1c593facbf8051ec58550917991e2e017f3085dac5fb902d9908cb", + "zh:e3b5e1f5543cac9d9031a028f1c1be4858fb80fae69f181f21e9465e366ebfa2", + "zh:e9fddc0bcdb28503078456f0088851d45451600d229975fd9990ee92c7489a10", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + ] +} + +provider "registry.terraform.io/hashicorp/kubernetes" { + version = "2.16.1" + constraints = "~> 2.16.1" + hashes = [ + "h1:i+DwtJK82sIWmTcQA9lL0mlET+14/QpUqv10fU2o3As=", + "zh:06224975f5910d41e73b35a4d5079861da2c24f9353e3ebb015fbb3b3b996b1c", + "zh:2bc400a8d9fe7755cca27c2551564a9e2609cfadc77f526ef855114ee02d446f", + "zh:3a479014187af1d0aec3a1d3d9c09551b801956fe6dd29af1186dec86712731b", + "zh:73fb0a69f1abdb02858b6589f7fab6d989a0f422f7ad95ed662aaa84872d3473", + "zh:a33852cd382cbc8e06d3f6c018b468ad809d24d912d64722e037aed1f9bf39db", + "zh:b533ff2214dca90296b1d22eace7eaa7e3efe5a7ae9da66a112094abc932db4f", + "zh:ddf74d8bb1aeb01dc2c36ef40e2b283d32b2a96db73f6daaf179fa2f10949c80", + "zh:e720f3a15d34e795fa9ff90bc755e838ebb4aef894aa2a423fb16dfa6d6b0667", + "zh:e789ae70a658800cb0a19ef7e4e9b26b5a38a92b43d1f41d64fc8bb46539cefb", + "zh:e8aed7dc0bd8f843d607dee5f72640dbef6835a8b1c6ea12cea5b4ec53e463f7", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:fb3ac4f43c8b0dfc0b0103dd0f062ea72b3a34518d4c8808e3a44c9a3dd5f024", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.1" + constraints = "~> 3.2.1" + hashes = [ + "h1:FbGfc+muBsC17Ohy5g806iuI1hQc4SIexpYCrQHQd8w=", + "zh:58ed64389620cc7b82f01332e27723856422820cfd302e304b5f6c3436fb9840", + "zh:62a5cc82c3b2ddef7ef3a6f2fedb7b9b3deff4ab7b414938b08e51d6e8be87cb", + "zh:63cff4de03af983175a7e37e52d4bd89d990be256b16b5c7f919aff5ad485aa5", + "zh:74cb22c6700e48486b7cabefa10b33b801dfcab56f1a6ac9b6624531f3d36ea3", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:79e553aff77f1cfa9012a2218b8238dd672ea5e1b2924775ac9ac24d2a75c238", + "zh:a1e06ddda0b5ac48f7e7c7d59e1ab5a4073bbcf876c73c0299e4610ed53859dc", + "zh:c37a97090f1a82222925d45d84483b2aa702ef7ab66532af6cbcfb567818b970", + "zh:e4453fbebf90c53ca3323a92e7ca0f9961427d2f0ce0d2b65523cc04d5d999c2", + "zh:e80a746921946d8b6761e77305b752ad188da60688cfd2059322875d363be5f5", + "zh:fbdb892d9822ed0e4cb60f2fedbdbb556e4da0d88d3b942ae963ed6ff091e48f", + "zh:fca01a623d90d0cad0843102f9b8b9fe0d3ff8244593bd817f126582b52dd694", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.4.3" + constraints = "~> 3.4.3" + hashes = [ + "h1:xZGZf18JjMS06pFa4NErzANI98qi59SEcBsOcS2P2yQ=", + "zh:41c53ba47085d8261590990f8633c8906696fa0a3c4b384ff6a7ecbf84339752", + "zh:59d98081c4475f2ad77d881c4412c5129c56214892f490adf11c7e7a5a47de9b", + "zh:686ad1ee40b812b9e016317e7f34c0d63ef837e084dea4a1f578f64a6314ad53", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:84103eae7251384c0d995f5a257c72b0096605048f757b749b7b62107a5dccb3", + "zh:8ee974b110adb78c7cd18aae82b2729e5124d8f115d484215fd5199451053de5", + "zh:9dd4561e3c847e45de603f17fa0c01ae14cae8c4b7b4e6423c9ef3904b308dda", + "zh:bb07bb3c2c0296beba0beec629ebc6474c70732387477a65966483b5efabdbc6", + "zh:e891339e96c9e5a888727b45b2e1bb3fcbdfe0fd7c5b4396e4695459b38c8cb1", + "zh:ea4739860c24dfeaac6c100b2a2e357106a89d18751f7693f3c31ecf6a996f8d", + "zh:f0c76ac303fd0ab59146c39bc121c5d7d86f878e9a69294e29444d4c653786f8", + "zh:f143a9a5af42b38fed328a161279906759ff39ac428ebcfe55606e05e1518b93", + ] +} diff --git a/terraform/main.tf b/terraform/main.tf index 3aeddca..c5a52b6 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -1,110 +1,27 @@ -provider "kubernetes" { - config_context_cluster = "minikube" -} - -provider "helm" { - kubernetes { - config_context_cluster = "minikube" - } -} -resource "kubernetes_namespace" "nvm-db-namespace" { - metadata { - name = "nvm-db" - } -} - -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 "kubernetes_namespace" "prometheus-namespace" { - metadata { - name = "prometheus" - } -} - - -resource "random_password" "grafana_admin_password" { - length = 16 - special = false +module "mysql" { + source = "./mysql" } +module "nvm" { + source = "./nvm" -resource "helm_release" "prometheus-operator" { depends_on = [ - kubernetes_namespace.prometheus-namespace, - random_password.grafana_admin_password + module.mysql ] - name = "kube-prometheus-stack" - repository = "https://prometheus-community.github.io/helm-charts" - chart = "kube-prometheus-stack" - version = "12.2.3" - namespace = "prometheus" - timeout = 360 + domain = var.domain + protocol = var.protocol - values = [ - <<-EOT - grafana: - grafana.ini: - server: - domain: ${var.domain} - root_url: "${var.protocol}://${var.domain}/grafana" - serve_from_sub_path: true - defaultDashboardsEnabled: true - adminPassword: ${random_password.grafana_admin_password.result} - ingress: - enabled: "true" - path: /grafana - hosts: - - ${var.domain} - tls: [] -EOT - , - ] + mysql_boilerplate_password = module.mysql.mysql_boilerplate_password } -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 +module "prometheus" { + source = "./prometheus" -} - - -resource "kubernetes_namespace" "nvm-namespace" { - metadata { - name = "nvm" - } -} -resource "helm_release" "nvm" { depends_on = [ - kubernetes_namespace.nvm-namespace, - helm_release.mysql-operator + module.nvm ] - name = "nvm" - chart = "../helm/nvm" - namespace = "nvm" - timeout = 600 - - set { - name = "ingress.host" - value = var.domain - } + domain = var.domain + protocol = var.protocol } diff --git a/terraform/mysql/innodbcluster/initialise.sh b/terraform/mysql/innodbcluster/initialise.sh new file mode 100755 index 0000000..53e3246 --- /dev/null +++ b/terraform/mysql/innodbcluster/initialise.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +# Install MySQL client tools +apk add --no-cache mysql-client + +mysql_ready() { + mysqladmin ping --host="$MYSQL_HOST" --user="$MYSQL_ROOT_USER" --password="$MYSQL_ROOT_PASSWORD" > /dev/null 2>&1 +} + +while ! ( mysql_ready ) +do + sleep 3 + echo "Waiting for mysql ..." +done + +# Throw an error from here if failed +set -e + +mysql_execute(){ + SQL=$1 + + mysql -h"$MYSQL_HOST" -u"$MYSQL_ROOT_USER" -p"$MYSQL_ROOT_PASSWORD" -e "$SQL" +} + +echo "Creating new user..." +mysql_execute "CREATE USER IF NOT EXISTS '$NEW_MYSQL_USER'@'%' IDENTIFIED WITH mysql_native_password BY '$NEW_MYSQL_USER_PASSWORD'" + +echo "Creating new database..." +mysql_execute "CREATE DATABASE IF NOT EXISTS $NEW_MYSQL_DATABASE" + +echo "Granting access to new database..." +mysql_execute "GRANT ALL PRIVILEGES ON $NEW_MYSQL_DATABASE.* TO '$NEW_MYSQL_USER'@'%'" + +echo "Done" diff --git a/terraform/mysql/innodbcluster/values.tmpl b/terraform/mysql/innodbcluster/values.tmpl new file mode 100644 index 0000000..669d69a --- /dev/null +++ b/terraform/mysql/innodbcluster/values.tmpl @@ -0,0 +1,75 @@ +# https://github.com/mysql/mysql-operator/blob/trunk/helm/mysql-innodbcluster/values.yaml + +image: + pullPolicy: IfNotPresent + pullSecrets: + enabled: false + secretName: + +credentials: + root: + user: root + password: ${credentials_root_password} + host: "%" + +tls: + useSelfSigned: true + +#serverVersion: 8.0.31 +serverInstances: 2 +routerInstances: 2 +baseServerId: 1000 + +#initDB: +# dump: +# name: +# path: +# options: +# includeSchemas: +# ociObjectStorage: +# prefix: +# bucketName: +# credentials: +# persistentVolumeClaim: +# clone: +# donorUrl: +# rootUser: +# credentials: + +podSpec: + containers: + - name: mysql + resources: + requests: + memory: "512Mi" # adapt to your needs + cpu: "500m" # adapt to your needs + limits: + memory: "8192Mi" # adapt to your needs + cpu: "3600m" # adapt to your needs + +serverConfig: + mycnf: | + [mysqld] + default_authentication_plugin=mysql_native_password + +datadirVolumeClaimTemplate: + storageClassName: "" + accessModes: ReadWriteOnce + resources: + requests: + storage: 2Gi + +#backupProfiles: +#- name: local-backup-pvc +# dumpInstance: +# storage: +# persistentVolumeClaim: +# claimName: local-backup +# +#backupSchedules: +#- enabled: true +# name: local-backup +# schedule: "0 0 * * *" +# deleteBackupData: false +# backupProfileName: local-backup-pvc + diff --git a/terraform/mysql/mysql-initialise.tf b/terraform/mysql/mysql-initialise.tf new file mode 100644 index 0000000..8e446f6 --- /dev/null +++ b/terraform/mysql/mysql-initialise.tf @@ -0,0 +1,96 @@ + +resource "random_password" "mysql_boilerplate_password" { + length = 32 + special = false +} + +resource "kubernetes_config_map" "initialise_config" { + depends_on = [helm_release.mysql_innodbcluster] + + metadata { + name = "initialise-config" + namespace = "mysql" + } + + data = { + "initialise.sh" = file("${path.module}/innodbcluster/initialise.sh") + } +} + +# This job will be executed once MySQL is available to bootstrap the database. The job will create a new user/database. +resource "kubernetes_job" "initialise_mysql" { + depends_on = [ + helm_release.mysql_innodbcluster, + random_password.mysql_boilerplate_password, + kubernetes_config_map.initialise_config + ] + + metadata { + name = "initialisation" + namespace = "mysql" + } + + spec { + template { + metadata {} + spec { + volume { + name = "initialise-sh" + config_map { + name = "initialise-config" + default_mode = "0755" + } + } + container { + name = "initialisation" + image = "alpine:3.17" + volume_mount { + mount_path = "/tmp/initialise.sh" + name = "initialise-sh" + sub_path = "initialise.sh" + } + command = [ + "/tmp/initialise.sh" + ] + env { + name = "MYSQL_HOST" + value = "mysql-innodbcluster.mysql.svc.cluster.local" + } + env { + name = "MYSQL_PORT" + value = 6446 + } + env { + name = "MYSQL_ROOT_USER" + value = "root" + } + env { + name = "MYSQL_ROOT_PASSWORD" + value = random_password.mysql_root_password.result + } + + env { + name = "NEW_MYSQL_USER" + value = "boilerplate" + } + env { + name = "NEW_MYSQL_USER_PASSWORD" + value = random_password.mysql_boilerplate_password.result + } + env { + name = "NEW_MYSQL_DATABASE" + value = "boilerplate" + } + } + restart_policy = "Never" + } + } + backoff_limit = 2 + } + wait_for_completion = true + timeouts { + create = "5m" + update = "5m" + } + +} diff --git a/terraform/mysql/mysql-innodbcluster.tf b/terraform/mysql/mysql-innodbcluster.tf new file mode 100644 index 0000000..06c4e7a --- /dev/null +++ b/terraform/mysql/mysql-innodbcluster.tf @@ -0,0 +1,36 @@ + +resource "kubernetes_namespace" "mysql_namespace" { + metadata { + name = "mysql" + } +} + +resource "random_password" "mysql_root_password" { + length = 32 + special = false +} + + +resource "helm_release" "mysql_innodbcluster" { + depends_on = [ + kubernetes_namespace.mysql_namespace, + helm_release.mysql_operator + ] + + name = "mysql-innodbcluster" + repository = "https://mysql.github.io/mysql-operator" + chart = "mysql-innodbcluster" + version = "2.0.7" + namespace = "mysql" + timeout = 360 + + values = [ + templatefile( + "${path.module}/innodbcluster/values.tmpl", + { + credentials_root_password = random_password.mysql_root_password.result + } + ), + ] +} + diff --git a/terraform/mysql/mysql-operator.tf b/terraform/mysql/mysql-operator.tf new file mode 100644 index 0000000..d1a4908 --- /dev/null +++ b/terraform/mysql/mysql-operator.tf @@ -0,0 +1,18 @@ +resource "kubernetes_namespace" "mysql_operator_namespace" { + metadata { + name = "mysql-operator" + } +} + +resource "helm_release" "mysql_operator" { + depends_on = [ + kubernetes_namespace.mysql_operator_namespace, + ] + + name = "mysql-operator" + repository = "https://mysql.github.io/mysql-operator" + chart = "mysql-operator" + version = "2.0.7" + namespace = "mysql-operator" + timeout = 360 +} diff --git a/terraform/mysql/output.tf b/terraform/mysql/output.tf new file mode 100644 index 0000000..3f47d66 --- /dev/null +++ b/terraform/mysql/output.tf @@ -0,0 +1,11 @@ +output "mysql_root_password" { + value = random_password.mysql_root_password.result + description = "MySQL root password" + sensitive = true +} + +output "mysql_boilerplate_password" { + value = random_password.mysql_boilerplate_password.result + description = "MySQL boilerplate password" + sensitive = true +} diff --git a/terraform/mysql/variables.tf b/terraform/mysql/variables.tf new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/terraform/mysql/variables.tf @@ -0,0 +1 @@ + diff --git a/terraform/nvm/nvm.tf b/terraform/nvm/nvm.tf new file mode 100644 index 0000000..04e6d1e --- /dev/null +++ b/terraform/nvm/nvm.tf @@ -0,0 +1,98 @@ + +resource "kubernetes_namespace" "nvm_namespace" { + metadata { + name = "nvm" + } +} + + +resource "random_password" "jwt_secret_key" { + length = 32 + special = false +} + +resource "random_password" "jwt_refresh_secret_key" { + length = 32 + special = false +} + + +resource "helm_release" "nvm" { + depends_on = [ + kubernetes_namespace.nvm_namespace + ] + + name = "nvm" + chart = "../helm/nvm" + namespace = "nvm" + # timeout = 600 + + set { + name = "ingress.host" + value = var.domain + } + + set { + name = "secrets[0].key" + value = "db-host" + } + set_sensitive { + name = "secrets[0].value" + value = "mysql-innodbcluster.mysql.svc.cluster.local" + } + + set { + name = "secrets[1].key" + value = "db-port" + } + set_sensitive { + name = "secrets[1].value" + value = 6446 + } + + set { + name = "secrets[2].key" + value = "db-user" + } + set_sensitive { + name = "secrets[2].value" + value = "boilerplate" + } + + set { + name = "secrets[3].key" + value = "db-password" + } + set_sensitive { + name = "secrets[3].value" + value = var.mysql_boilerplate_password + } + + set { + name = "secrets[4].key" + value = "db-name" + } + set_sensitive { + name = "secrets[4].value" + value = "boilerplate" + } + + set { + name = "secrets[5].key" + value = "jwt-secret-key" + } + set_sensitive { + name = "secrets[5].value" + value = random_password.jwt_secret_key.result + } + + set { + name = "secrets[6].key" + value = "jwt-refresh-secret-key" + } + set_sensitive { + name = "secrets[6].value" + value = random_password.jwt_refresh_secret_key.result + } + +} diff --git a/terraform/nvm/variables.tf b/terraform/nvm/variables.tf new file mode 100644 index 0000000..0236481 --- /dev/null +++ b/terraform/nvm/variables.tf @@ -0,0 +1,13 @@ + +variable "protocol" { + description = "HTTP protocol" +} + +variable "domain" { + description = "Domain Name" +} + + +variable "mysql_boilerplate_password" { + description = "Password of MySQL boilerplate user" +} diff --git a/terraform/output.tf b/terraform/output.tf index 8164381..76a69d5 100644 --- a/terraform/output.tf +++ b/terraform/output.tf @@ -1,4 +1,17 @@ +output "mysql_root_password" { + value = module.mysql.mysql_root_password + description = "MySQL root password" + sensitive = true +} + +output "mysql_boilerplate_password" { + value = module.mysql.mysql_boilerplate_password + description = "MySQL boilerplate password" + sensitive = true +} output "grafana_admin_password" { - value = random_password.grafana_admin_password.result + value = module.prometheus.grafana_admin_password + description = "Grafana admin password" + sensitive = true } diff --git a/terraform/prometheus/output.tf b/terraform/prometheus/output.tf new file mode 100644 index 0000000..7fac394 --- /dev/null +++ b/terraform/prometheus/output.tf @@ -0,0 +1,3 @@ +output "grafana_admin_password" { + value = random_password.grafana_admin_password.result +} diff --git a/terraform/prometheus/prometheus.tf b/terraform/prometheus/prometheus.tf new file mode 100644 index 0000000..942daf2 --- /dev/null +++ b/terraform/prometheus/prometheus.tf @@ -0,0 +1,46 @@ +resource "kubernetes_namespace" "prometheus_namespace" { + metadata { + name = "prometheus" + } +} + + +resource "random_password" "grafana_admin_password" { + length = 16 + special = false +} + + +resource "helm_release" "prometheus_operator" { + depends_on = [ + kubernetes_namespace.prometheus_namespace, + random_password.grafana_admin_password + ] + + name = "kube-prometheus-stack" + repository = "https://prometheus-community.github.io/helm-charts" + chart = "kube-prometheus-stack" + version = "43.2.0" + namespace = "prometheus" + timeout = 360 + + values = [ + <<-EOT + grafana: + grafana.ini: + server: + domain: ${var.domain} + root_url: "${var.protocol}://${var.domain}/grafana" + serve_from_sub_path: true + defaultDashboardsEnabled: true + adminPassword: ${random_password.grafana_admin_password.result} + ingress: + enabled: "true" + path: /grafana + hosts: + - ${var.domain} + tls: [] +EOT + , + ] +} diff --git a/terraform/prometheus/variables.tf b/terraform/prometheus/variables.tf new file mode 100644 index 0000000..a8964a4 --- /dev/null +++ b/terraform/prometheus/variables.tf @@ -0,0 +1,8 @@ + +variable "protocol" { + description = "HTTP protocol" +} + +variable "domain" { + description = "Domain Name" +} diff --git a/terraform/provider.tf b/terraform/provider.tf new file mode 100644 index 0000000..9d3c2f2 --- /dev/null +++ b/terraform/provider.tf @@ -0,0 +1,49 @@ +terraform { + required_version = "~> 1.3.6" + + # Note that minikube cannot be worked with Terraform Cloud. + # + # cloud { + # organization = "chrisleekr" # Replace with your organisation from app. + + # workspaces { + # name = "k8s-nvm-boilerplate" # Replace with your workspace name + # } + # } + + + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.16.1" + } + + helm = { + source = "hashicorp/helm" + version = "~> 2.8.0" + } + + random = { + source = "hashicorp/random" + version = "~> 3.4.3" + } + + null = { + source = "hashicorp/null" + version = "~> 3.2.1" + } + } +} + + +provider "kubernetes" { + config_path = "~/.kube/config" + config_context = "minikube" +} + +provider "helm" { + kubernetes { + config_path = "~/.kube/config" + config_context = "minikube" + } +}