From 57d4051de1d119888a882d8d6992fb1115f3a2dc Mon Sep 17 00:00:00 2001 From: David Ferlay Date: Tue, 30 Nov 2021 15:17:33 +0100 Subject: [PATCH] Replacing docker-compose by k3s --- Makefile | 53 +++++++++----- helm/.helmignore | 23 ++++++ helm/Chart.yaml | 24 +++++++ helm/templates/_helpers.tpl | 62 ++++++++++++++++ helm/templates/configmap.yaml | 9 +++ helm/templates/deployment.yaml | 74 +++++++++++++++++++ helm/templates/ingress.yaml | 24 +++++++ helm/templates/service.yaml | 14 ++++ helm/values.yaml | 15 ++++ kubernetes/sdc.yaml | 126 +++++++++++++++++++++++++++++++++ 10 files changed, 405 insertions(+), 19 deletions(-) create mode 100644 helm/.helmignore create mode 100644 helm/Chart.yaml create mode 100644 helm/templates/_helpers.tpl create mode 100644 helm/templates/configmap.yaml create mode 100644 helm/templates/deployment.yaml create mode 100644 helm/templates/ingress.yaml create mode 100644 helm/templates/service.yaml create mode 100644 helm/values.yaml create mode 100644 kubernetes/sdc.yaml diff --git a/Makefile b/Makefile index 53c5a6761..ca3ddd3f5 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# Add utility functions and scripts to the container +# Include utility functions and scripts include scripts/makefile/*.mk .PHONY: all fast allfast provision si exec exec0 down clean dev drush info phpcs phpcbf hooksymlink clang cinsp compval watchdogval drupalrectorval upgradestatusval behat sniffers tests front front-install front-build clear-front lintval lint storybook back behatdl behatdi browser_driver browser_driver_stop statusreportval contentgen newlineeof localize local-settings redis-settings content patchval diff @@ -10,9 +10,14 @@ include scripts/makefile/*.mk # Prepare enviroment variables from defaults $(shell false | cp -i \.env.default \.env 2>/dev/null) -$(shell false | cp -i \.\/docker\/docker-compose\.override\.yml\.default \.\/docker\/docker-compose\.override\.yml 2>/dev/null) include .env +# Sanitize PROJECT_NAME input +COMPOSE_PROJECT_NAME := $(shell echo "$(PROJECT_NAME)" | tr -cd '[a-zA-Z0-9]' | tr '[:upper:]' '[:lower:]') + +kk: + helm install --kubeconfig=/etc/rancher/k3s/k3s.yaml --set projectName=$(COMPOSE_PROJECT_NAME) sdc ./helm/ + # Get user/group id to manage permissions between host and containers LOCAL_UID := $(shell id -u) LOCAL_GID := $(shell id -g) @@ -24,7 +29,7 @@ CGID ?= $(LOCAL_GID) # Define network name. COMPOSE_NET_NAME := $(COMPOSE_PROJECT_NAME)_front -SDC_SERVICES=$(shell docker-compose config --services) +# SDC_SERVICES=$(shell docker-compose config --services) # TODO: Replace or remove # Determine database data directory if defined DB_MOUNT_DIR=$(shell cd docker && realpath $(DB_DATA_DIR))/ ifeq ($(findstring mysql,$(SDC_SERVICES)),mysql) @@ -38,10 +43,15 @@ endif CURDIR=$(shell pwd) # Execute php container as regular user -php = docker-compose exec -T --user $(CUID):$(CGID) php ${1} +php = kubectl exec -it deploy/sdc -c php -- su -s /bin/ash www-data -c "${1}" # Execute php container as root user -php-0 = docker-compose exec -T --user 0:0 php ${1} +php-0 = kubectl exec -it deploy/sdc -c php -- ${1} + +killall: + /usr/local/bin/k3s-killall.sh + /usr/local/bin/k3s-uninstall.sh +# Variables ADDITIONAL_PHP_PACKAGES := tzdata graphicsmagick # php7-intl php7-redis wkhtmltopdf gnu-libiconv php7-pdo_pgsql postgresql-client postgresql-contrib DC_MODULES := project_default_content better_normalizers default_content hal serialization MG_MODULES := migrate_generator migrate migrate_plus migrate_source_csv migrate_tools @@ -63,7 +73,7 @@ provision: # Check if enviroment variables has been defined ifeq ($(strip $(COMPOSE_PROJECT_NAME)),projectname) $(info Project name can not be default, please enter project name.) - $(eval COMPOSE_PROJECT_NAME = $(strip $(shell read -p "Project name: " REPLY;echo -n $$REPLY))) + $(eval COMPOSE_PROJECT_NAME = $(strip $(shell read -p "Project name: " REPLY;echo -n $$REPLY))) # TODO: Sanitize lowercase/nospecialchar $(shell sed -i -e '/COMPOSE_PROJECT_NAME=/ s/=.*/=$(COMPOSE_PROJECT_NAME)/' .env) $(info Please review your project settings and run `make all` again.) exit 1 @@ -71,9 +81,17 @@ endif ifdef DB_MOUNT_DIR $(shell [ ! -d $(DB_MOUNT_DIR) ] && mkdir -p $(DB_MOUNT_DIR) && chmod 777 $(DB_MOUNT_DIR)) endif - make -s down +# make -s down + @echo "Downloading and installing container orchestrator..." + curl -sfL https://get.k3s.io | K3S_NODE_NAME=sdc K3S_KUBECONFIG_MODE="644" sh - # TODO: Check behavior if k3s already install + lock version + curl -sfL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | sh - # TODO: rm $(which helm) +# kubectl config view --raw >~/.kube/config # TODO: Simlink to /etc/rancher/k3s/k3s.yaml OR use helm install --kubeconfig=/etc/rancher/k3s/k3s.yaml sdc ./kubernetes/sdc-chart @echo "Build and run containers..." - docker-compose up -d --remove-orphans + # TODO: Rename file +# kubectl apply -f kubernetes/sdc.yaml + helm install --kubeconfig=/etc/rancher/k3s/k3s.yaml --set projectName=$(COMPOSE_PROJECT_NAME) sdc ./helm/ +# helm install --kubeconfig=/etc/rancher/k3s/k3s.yaml sdc ./helm/ # https://github.com/k3s-io/k3s/issues/1126#issuecomment-567591888 + for i in {1..50}; do echo "Waiting for PHP container..." && kubectl exec -it deploy/sdc -c php -- "whoami" &> /dev/null && break || sleep 1; done; echo "Container is up !" # Set composer2 as default $(call php-0, ln -fs composer2 /usr/bin/composer) ifneq ($(strip $(ADDITIONAL_PHP_PACKAGES)),) @@ -157,37 +175,31 @@ localize: info: $(info ) $(info Containers for "$(COMPOSE_PROJECT_NAME)" info:) - $(eval CONTAINERS = $(shell docker ps -f name=$(COMPOSE_PROJECT_NAME) --format "{{ .ID }}" -f 'label=traefik.enable=true')) - $(foreach CONTAINER, $(CONTAINERS),$(info http://$(shell printf '%-19s \n' $(shell docker inspect --format='{{(index .NetworkSettings.Networks "$(COMPOSE_NET_NAME)").IPAddress}}:{{index .Config.Labels "traefik.port"}} {{range $$p, $$conf := .NetworkSettings.Ports}}{{$$p}}{{end}} {{.Name}}' $(CONTAINER) | rev | sed "s/pct\//,pct:/g" | sed "s/,//" | rev | awk '{ print $0}')) )) $(info ) ifdef REVIEW_DOMAIN $(eval BASE_URL := $(MAIN_DOMAIN_NAME)) else - $(eval BASE_URL := $(shell docker inspect --format='{{(index .NetworkSettings.Networks "$(COMPOSE_NET_NAME)").IPAddress}}:{{index .Config.Labels "traefik.port"}}' $(COMPOSE_PROJECT_NAME)_web)) + $(eval BASE_URL := $(shell kubectl get pods -l name=sdc --template '{{range .items}}{{.status.podIP}}{{"\n"}}{{end}}')) endif - $(info Login as System Admin: http://$(shell printf '%-19s \n' $(shell echo "$(BASE_URL)"$(shell $(call php, drush user:login --name="$(ADMIN_NAME)" /admin/content/ | awk -F "default" '{print $$2}'))))) - $(info Login as Contributor: http://$(shell printf '%-19s \n' $(shell echo "$(BASE_URL)"$(shell $(call php, drush user:login --name="$(TESTER_NAME)" /admin/content/ | awk -F "default" '{print $$2}'))))) + $(info Login as System Admin: http://$(shell printf '%-19s \n' $(shell echo "$(BASE_URL)"$(shell $(call php, drush user:login --name="$(ADMIN_NAME)" /admin/content/ | awk -F "default" '{print \$$2}'))))) + $(info Login as Contributor: http://$(shell printf '%-19s \n' $(shell echo "$(BASE_URL)"$(shell $(call php, drush user:login --name="$(TESTER_NAME)" /admin/content/ | awk -F "default" '{print \$$2}'))))) $(info ) ifneq ($(shell diff .env .env.default -q),) @echo -e "\x1b[33mWARNING\x1b[0m - .env and .env.default files differ. Use 'make diff' to see details." endif -ifneq ($(shell diff docker/docker-compose.override.yml docker/docker-compose.override.yml.default -q),) - @echo -e "\x1b[33mWARNING\x1b[0m - docker/docker-compose.override.yml and docker/docker-compose.override.yml.default files differ. Use 'make diff' to see details." -endif ## Output diff between local and versioned files diff: diff -u0 --color .env .env.default || true; echo "" - diff -u0 --color docker/docker-compose.override.yml docker/docker-compose.override.yml.default || true; echo "" ## Run shell in PHP container as regular user exec: - docker-compose exec --user $(CUID):$(CGID) php ash + kubectl exec -it deploy/sdc -c php -- su -s /bin/ash www-data -c ash ## Run shell in PHP container as root exec0: - docker-compose exec --user 0:0 php ash + kubectl exec -it deploy/sdc -c php -- ash down: @echo "Removing network & containers for $(COMPOSE_PROJECT_NAME)" @@ -232,3 +244,6 @@ dev: drush: $(call php, $(filter-out "$@",$(MAKECMDGOALS))) $(info "To pass arguments use double dash: "make drush en devel -- -y"") + +logs: + kubectl logs -f deploy/sdc --all-containers=true \ No newline at end of file diff --git a/helm/.helmignore b/helm/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/helm/.helmignore @@ -0,0 +1,23 @@ +# 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 +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/Chart.yaml b/helm/Chart.yaml new file mode 100644 index 000000000..19c5b70f8 --- /dev/null +++ b/helm/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: sdc +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl new file mode 100644 index 000000000..c54488b5b --- /dev/null +++ b/helm/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "sdc.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 "sdc.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 "sdc.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "sdc.labels" -}} +helm.sh/chart: {{ include "sdc.chart" . }} +{{ include "sdc.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "sdc.selectorLabels" -}} +app.kubernetes.io/name: {{ include "sdc.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "sdc.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "sdc.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/templates/configmap.yaml b/helm/templates/configmap.yaml new file mode 100644 index 000000000..851aae478 --- /dev/null +++ b/helm/templates/configmap.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: nginx-config +data: + upstream: | + upstream upstream { + server localhost:9000; + } \ No newline at end of file diff --git a/helm/templates/deployment.yaml b/helm/templates/deployment.yaml new file mode 100644 index 000000000..5845422ee --- /dev/null +++ b/helm/templates/deployment.yaml @@ -0,0 +1,74 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.projectName }} + labels: + name: {{ .Values.projectName }} +spec: + revisionHistoryLimit: 0 + replicas: 1 + selector: + matchLabels: + name: {{ .Values.projectName }} + strategy: + type: Recreate + template: + metadata: + labels: + name: {{ .Values.projectName }} + spec: + volumes: + - name: codebase + hostPath: + path: /home/dferlay/Sources/df-sdc # TODO: Variable for relative path + type: Directory + - name: nginx-config + configMap: + name: nginx-config + - name: cache-js + emptyDir: + medium: Memory + - name: cache-css + emptyDir: + medium: Memory + - name: cache-php + emptyDir: + medium: Memory + containers: + - name: php + image: skilldlabs/php:74-fpm + env: + - name: COMPOSER_MEMORY_LIMIT + value: "-1" + ports: + - containerPort: 9000 + protocol: TCP + volumeMounts: + - mountPath: /var/www/html + name: codebase + - mountPath: /var/www/html/web/sites/default/files/css + name: cache-css + - mountPath: /var/www/html/web/sites/default/files/js + name: cache-js + - mountPath: /var/www/html/web/sites/default/files/php + name: cache-php + - name: nginx + image: skilldlabs/nginx:1.20 + ports: + - containerPort: 80 + protocol: TCP + volumeMounts: + - mountPath: /var/www/html + name: codebase + - mountPath: /etc/nginx/upstream + name: nginx-config + subPath: upstream + - mountPath: /var/www/html/web/sites/default/files/css + name: cache-css + - mountPath: /var/www/html/web/sites/default/files/js + name: cache-js + - name: mail + image: skilldlabs/mailhog + restartPolicy: Always + nodeSelector: + kubernetes.io/hostname: sdc \ No newline at end of file diff --git a/helm/templates/ingress.yaml b/helm/templates/ingress.yaml new file mode 100644 index 000000000..dd5d47ba2 --- /dev/null +++ b/helm/templates/ingress.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + name: {{ .Values.projectName }} + labels: + mrn: {{ .Values.projectName }} + annotations: + kubernetes.io/tls-acme: "true" + kubernetes.io/ingress.class: web-ingress + cert-manager.io/cluster-issuer: letsencrypt-prod + nginx.ingress.kubernetes.io/from-to-www-redirect: "true" +spec: + rules: + - host: local.skilld.cloud + http: + paths: + - path: / + backend: + serviceName: {{ .Values.projectName }} + servicePort: 80 + tls: + - hosts: + - local.skilld.cloud + secretName: {{ .Values.projectName }}-tls \ No newline at end of file diff --git a/helm/templates/service.yaml b/helm/templates/service.yaml new file mode 100644 index 000000000..6930cad3d --- /dev/null +++ b/helm/templates/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.projectName }} +spec: + ports: + - name: http + port: 80 + protocol: TCP + - name: mailhog + port: 8025 + protocol: TCP + selector: + mrn: {{ .Values.projectName }} \ No newline at end of file diff --git a/helm/values.yaml b/helm/values.yaml new file mode 100644 index 000000000..4177f88be --- /dev/null +++ b/helm/values.yaml @@ -0,0 +1,15 @@ +# Default values for sdc. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +projectName: yay + +image: + +ingress: + enabled: true + +service: + type: ClusterIP + port: 80 + diff --git a/kubernetes/sdc.yaml b/kubernetes/sdc.yaml new file mode 100644 index 000000000..68bdb8cd2 --- /dev/null +++ b/kubernetes/sdc.yaml @@ -0,0 +1,126 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: nginx-config +data: + upstream: | + upstream upstream { + server localhost:9000; + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sdc + labels: + name: sdc +spec: + revisionHistoryLimit: 0 + replicas: 1 + selector: + matchLabels: + name: sdc + strategy: + type: Recreate + template: + metadata: + labels: + name: sdc + spec: + volumes: + - name: codebase + hostPath: + path: /home/dferlay/Sources/df-sdc # TODO: Variable for relative path + type: Directory + - name: nginx-config + configMap: + name: nginx-config + - name: cache-js + emptyDir: + medium: Memory + - name: cache-css + emptyDir: + medium: Memory + - name: cache-php + emptyDir: + medium: Memory + containers: + - name: php + image: skilldlabs/php:74-fpm + env: + - name: COMPOSER_MEMORY_LIMIT + value: "-1" + ports: + - containerPort: 9000 + protocol: TCP + volumeMounts: + - mountPath: /var/www/html + name: codebase + - mountPath: /var/www/html/web/sites/default/files/css + name: cache-css + - mountPath: /var/www/html/web/sites/default/files/js + name: cache-js + - mountPath: /var/www/html/web/sites/default/files/php + name: cache-php + - name: nginx + image: skilldlabs/nginx:1.20 + ports: + - containerPort: 80 + protocol: TCP + volumeMounts: + - mountPath: /var/www/html + name: codebase + - mountPath: /etc/nginx/upstream + name: nginx-config + subPath: upstream + - mountPath: /var/www/html/web/sites/default/files/css + name: cache-css + - mountPath: /var/www/html/web/sites/default/files/js + name: cache-js + - name: mail + image: skilldlabs/mailhog + restartPolicy: Always + nodeSelector: + kubernetes.io/hostname: sdc +--- +apiVersion: v1 +kind: Service +metadata: + name: sdc +spec: + ports: + - name: http + port: 80 + protocol: TCP + - name: mailhog + port: 8025 + protocol: TCP + selector: + mrn: sdc +--- +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + name: sdc + labels: + mrn: sdc + annotations: + kubernetes.io/tls-acme: "true" + kubernetes.io/ingress.class: web-ingress + cert-manager.io/cluster-issuer: letsencrypt-prod + nginx.ingress.kubernetes.io/from-to-www-redirect: "true" + # nginx.ingress.kubernetes.io/auth-url: {{ kb_ingress_auth_url }} + # nginx.ingress.kubernetes.io/proxy-body-size: {{ kb_ingress_proxy_body_size }} +spec: + rules: + - host: local.skilld.cloud + http: + paths: + - path: / + backend: + serviceName: sdc + servicePort: 80 + tls: + - hosts: + - local.skilld.cloud + secretName: sdc-tls