diff --git a/12-deploying-containers/README.md b/12-deploying-containers/README.md index 6e48c45..42fd2f9 100644 --- a/12-deploying-containers/README.md +++ b/12-deploying-containers/README.md @@ -26,6 +26,30 @@ When we provision a PostgresDB within the project, Railway automatically sets th ## Docker swarm +At this point, we already have a `docker compose` file which allows us to specify our application using a single command. There are a few limitations with docker compose that make it less than ideal to run a production application with docker compose directly: +- No support for secrets (we are passing our DB credentials as environment variables) +- No support for zero downtime re-deployments + +Luckily, docker swarm does provide those things and setting up a single node cluster can be done with one command `docker swarm init`. Making just a few modifications to the docker compose file (adding `deploy` configurations, passing sensitive info as secrets and reading those data as files within the applications) it is ready to deploy. + +1) Create a virtual machine with your favorite cloud provider. Make sure to set up the firewall to listen on ports 80, 443, and 22. +2) Use the script at https://get.docker.com/ to install docker engine +3) Set the `DOCKER_HOST` environment variable in the Makefile to `USERNAME@IP_ADDRESS` of your virtual machine (this will allow your local docker client to use the remote docker daemon!) +4) Build and push the container images to a registry +5) Populate the secrets by running `make create-secrets` +6) Deploy the application by running `make swarm-deploy-stack` (uses the `docker stack deploy` command under the hood) +7) Set up a DNS A record to route traffic to your VM (or access using the IP address) ## Kubernetes + +I was planning to only include the Railway + Swarm examples, but figured a course about containers wouldn't be complete without at least mentioning Kubernetes, the most popular container orchestrator today. Like Docker Swarm, Kubernetes is designed to schedule and run your containers, but has more maturity when it comes to cloud provider support. + +I created the necessary resource yaml files in `./kubernetes` to deploy the application. You will notice that it is somewhat more verbose than the swarm specification. + +1) Create a kubernetes cluster with your favorite cloud provider. +2) Set up kubectl to connect to the cluster (using the cloud provider instructions) +3) Install Traefik ingress controller by running `make install-traefik` (uses this helm chart https://github.com/traefik/traefik-helm-chart) +4) Install Postgres by running `make install-postgres` (uses this helm chart https://github.com/bitnami/charts/tree/main/bitnami/postgresql) +5) Deploy the application by running `make deploy-app` +6) Set up a DNS A record to route traffic to the IP address of the load balancer that traefik provisions diff --git a/12-deploying-containers/docker-swarm/Makefile b/12-deploying-containers/docker-swarm/Makefile index 85c9b22..6492fc9 100644 --- a/12-deploying-containers/docker-swarm/Makefile +++ b/12-deploying-containers/docker-swarm/Makefile @@ -15,21 +15,21 @@ compose-down: ### DOCKER SWARM -CIVO_SSH:="ssh://ubuntu@212.2.244.220" +DOCKER_HOST:="ssh://ubuntu@212.2.244.220" .PHONY: swarm-init swarm-init: - DOCKER_HOST=${CIVO_SSH} docker swarm init + DOCKER_HOST=${DOCKER_HOST} docker swarm init .PHONY: swarm-deploy-stack swarm-deploy-stack: - DOCKER_HOST=${CIVO_SSH} docker stack deploy -c docker-swarm.yml example-app + DOCKER_HOST=${DOCKER_HOST} docker stack deploy -c docker-swarm.yml example-app .PHONY: swarm-remove-stack swarm-remove-stack: - DOCKER_HOST=${CIVO_SSH} docker stack rm example-app + DOCKER_HOST=${DOCKER_HOST} docker stack rm example-app .PHONY: create-secrets create-secrets: - echo -n "foobarbaz" | DOCKER_HOST=${CIVO_SSH} docker secret create postgres-passwd - - echo -n "postgres://postgres:foobarbaz@db:5432/postgres" | DOCKER_HOST=${CIVO_SSH} docker secret create database-url - \ No newline at end of file + echo -n "foobarbaz" | DOCKER_HOST=${DOCKER_HOST} docker secret create postgres-passwd - + echo -n "postgres://postgres:foobarbaz@db:5432/postgres" | DOCKER_HOST=${DOCKER_HOST} docker secret create database-url - \ No newline at end of file diff --git a/12-deploying-containers/docker-swarm/docker-compose-prod.yml b/12-deploying-containers/docker-swarm/docker-compose-prod.yml index 85d6563..5946091 100644 --- a/12-deploying-containers/docker-swarm/docker-compose-prod.yml +++ b/12-deploying-containers/docker-swarm/docker-compose-prod.yml @@ -3,11 +3,6 @@ version: '3.7' services: client-react-nginx: image: sidpalas/devops-directive-docker-course-client-react-nginx:5 - deploy: - mode: replicated - replicas: 1 - update_config: - order: start-first networks: - frontend ports: @@ -22,11 +17,6 @@ services: api-node: image: sidpalas/devops-directive-docker-course-api-node:8 read_only: true - deploy: - mode: replicated - replicas: 1 - update_config: - order: start-first networks: - frontend - backend @@ -47,11 +37,6 @@ services: api-golang: image: sidpalas/devops-directive-docker-course-api-golang:7 read_only: true - deploy: - mode: replicated - replicas: 1 - update_config: - order: start-first networks: - frontend - backend diff --git a/12-deploying-containers/kubernetes/Makefile b/12-deploying-containers/kubernetes/Makefile index d0d5e80..6096aef 100644 --- a/12-deploying-containers/kubernetes/Makefile +++ b/12-deploying-containers/kubernetes/Makefile @@ -1,7 +1,12 @@ +.PHONY: deploy-traefik +deploy-traefik: + -helm repo add traefik https://traefik.github.io/charts + helm upgrade --install -n traefik --create-namespace -f traefik-values traefik traefik/traefik + .PHONY: deploy-postgres deploy-postgres: - helm repo add bitnami https://charts.bitnami.com/bitnami - helm install db bitnami/postgresql --set auth.postgresPassword=foobarbaz + -helm repo add bitnami https://charts.bitnami.com/bitnami + helm upgrade --install db bitnami/postgresql --set auth.postgresPassword=foobarbaz .PHONY: deploy-app deploy-app: diff --git a/12-deploying-containers/kubernetes/traefik-values b/12-deploying-containers/kubernetes/traefik-values new file mode 100644 index 0000000..f34099e --- /dev/null +++ b/12-deploying-containers/kubernetes/traefik-values @@ -0,0 +1,30 @@ +# Taken from CIVO marketplace values +deployment: + kind: DaemonSet +rbac: + enabled: true +ports: + websecure: + tls: + enabled: true +podAnnotations: + prometheus.io/port: "8082" + prometheus.io/scrape: "true" +providers: + kubernetesIngress: + publishedService: + enabled: true +priorityClassName: "system-cluster-critical" +# Rancher didn't have the latest v2.9.6 image associate with the latest helm chart +# Using the default dockerhub traefik image instead +# image: +# name: "rancher/mirrored-library-traefik" +tolerations: +- key: "CriticalAddonsOnly" + operator: "Exists" +- key: "node-role.kubernetes.io/control-plane" + operator: "Exists" + effect: "NoSchedule" +- key: "node-role.kubernetes.io/master" + operator: "Exists" + effect: "NoSchedule" \ No newline at end of file