From 7f1891196c10bd21996b3a184ac3053c151c300e Mon Sep 17 00:00:00 2001 From: Lucas Roesler Date: Mon, 24 Dec 2018 21:16:41 +0000 Subject: [PATCH 01/11] Initial SSL for swarm tutorial **What** - Adds a new reference document to guide a user through installing OpenFaaS on Docker Swarm with Traefik as the proxy with ssl certs from Let's Encrypt Signed-off-by: Lucas Roesler --- docs/reference/ssl/swarm-with-traefik.md | 319 +++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 320 insertions(+) create mode 100644 docs/reference/ssl/swarm-with-traefik.md diff --git a/docs/reference/ssl/swarm-with-traefik.md b/docs/reference/ssl/swarm-with-traefik.md new file mode 100644 index 00000000..090e3c55 --- /dev/null +++ b/docs/reference/ssl/swarm-with-traefik.md @@ -0,0 +1,319 @@ +# SSL on Swarm with Traefik + +To completely secure your OpenFaaS installation, you need SSL. On Swarm, you can do this easily with [Traefik][traefik] and [Let's Encrypt][letsencrypt]. Traefik is is reverse proxy that comes with SSL support via Let's Encrypt. In this tutorial we will show you how to deploy OpenFaaS with Traefik. + + +## Create an A record + +If your domain is `.domain.com` then create an A record using your DNS administration panel such as `gateway.domain.com` or `openfaas.domain.com`. The required steps will vary depending on your domain provider and your cluster provider. For example; [on Google Cloud DNS](https://cloud.google.com/kubernetes-engine/docs/tutorials/configuring-domain-name-static-ip) or [with Route53 using AWS](https://kubernetes.io/docs/setup/custom-cloud/kops/#2-5-create-a-route53-domain-for-your-cluster). + +## Update the Compose configuration + +### Configure Traefik +To use Traefik with OpenFaaS, you need to modify the OpenFaaS deployment manifest to include Traefik and configuring OpenFaaS communicate through Traefik instead of directly exposing its services to the internet. + +1. Clone OpenFaaS and then checkout the latest stable release: + + ```bash + $ git clone https://github.com/openfaas/faas && cd faas + ``` + +2. Add the `traefik` service to the `docker-compose.yaml`. + + To start, open `docker-compose.yaml` in your favorite editor and add a `traefik` service like this: + + ```yaml + version: "3.3" + services: + traefik: + image: traefik:v1.7.6 + gateway: + ... + ``` +3. Next, to configure Traefik to work with Docker Swarm _and_ Let's Encrypt, you must override the default `command` to the `traefik` service. The `traefik` section of the `docker-compose.yaml` file should look like this: + + ```yaml + ... + traefik: + image: traefik:v1.7.6 + command: + - "--api=true" + - "--docker=true" + - "--docker.swarmmode=true" + - "--docker.domain=traefik" + - "--docker.watch=true" + - "--defaultEntryPoints='http,https'" + - "--entryPoints='Name:https Address::443 TLS'" + - "--entryPoints='Name:http Address::80'" + - "--acme=true" + - "--acme.entrypoint='https'" + - "--acme.httpchallenge=true" + - "--acme.httpchallenge.entrypoint='http'" + - "--acme.domains='openfaas.mydomain.com, www.openfaas.mydomain.com'" + - "--acme.email=''" + - "--acme.ondemand=true" + - "--acme.onhostrule=true" + - "--acme.storage=/etc/traefik/acme/acme.json" + ... + ``` + + * The `--api=true` flag enables Traefik's Web UI, + * The `--docker.*` flags tell Traefik to use Docker and specify that it's running in a Docker Swarm cluster. + * The `--defaultEntryPoints` and `--entryPoints` flags define entry points and protocols to be used. In our case this includes HTTP on port 80 and HTTPS on port 443. + * The `--acme.*` flags configure Traefik to use the ACME protocol to generate Let's Encrypt certificates to secure your OpenFaaS cluster with SSL. Make sure to replace the `openfaas.mydomain.com` domain placeholders in the `--acme.domains` flag with your own domain. You can specify multiple domains by separating them with a comma and space. +4. Expose the ports required for Traefik. Traefik uses port `8080` for its operations and UI, while in the last step we configured ports `80` and `443` and entrypoints for internet traffic. These will be used / proxied to OpenFaaS + + ```yaml + ... + traefik: + image: traefik:v1.7.6 + command: + ... + ports: + - 80:80 + - 8080:8080 + - 443:443 + ... + ``` +5. Next you must configure the volumes needed for Traefik, in this case, the docker socket and some file storage. The Docker socket file communicates with the Docker API in order to manage your containers and will provide details about them, such as number of containers and their IP addresses, to Traefik. You will also mount the volume called acme, which we'll define later in this step. + + ```yaml + ... + traefik: + image: traefik:v1.7.6 + command: + ... + ports: + ... + volumes: + - "/var/run/docker.sock:/var/run/docker.sock" + - "acme:/etc/traefik/acme" + ... + ``` +6. Next you must configure the networks the `traefix` service is part of. All OpenFaaS components live on the `functions` networks, which is also defined in the compose file. + + ```yaml + ... + traefik: + image: traefik:v1.7.6 + command: + ... + ports: + ... + volumes: + ... + networks: + - functions + ... + ``` +7. Lastly, you must configure the `deploy` section so that Traefik is only deployed on the Docker Swarm manager. + + ```yaml + ... + traefik: + image: traefik:v1.7.6 + command: + ... + ports: + ... + volumes: + ... + networks: + ... + deploy: + placement: + constraints: [node.role == manager] + ... + ``` + +All together, the `traefik` service block should look like + +```yaml +version: "3.3" +services: + traefik: + image: traefik:v1.7.6 + command: + - "--api=true" + - "--docker=true" + - "--docker.swarmmode=true" + - "--docker.domain=traefik" + - "--docker.watch=true" + - "--defaultEntryPoints='http,https'" + - "--entryPoints='Name:https Address::443 TLS'" + - "--entryPoints='Name:http Address::80'" + - "--acme=true" + - "--acme.entrypoint='https'" + - "--acme.httpchallenge=true" + - "--acme.httpchallenge.entrypoint='http'" + - "--acme.domains='openfaas.mydomain.com, www.openfaas.mydomain.com'" + - "--acme.email=''" + - "--acme.ondemand=true" + - "--acme.onhostrule=true" + - "--acme.storage=/etc/traefik/acme/acme.json" + ports: + - 80:80 + - 8080:8080 + - 443:443 + volumes: + - "/var/run/docker.sock:/var/run/docker.sock" + - "acme:/etc/traefik/acme" + networks: + - functions + deploy: + placement: + constraints: [node.role == manager] + + gateway: + ... +``` + +### Configure OpenFaaS +By default, the original `docker-compose.yaml` file exposes the OpenFaaS `gateway` on port `8080`. This conflicts with the configuration of Traefik, additionally, we want all communication to safely pass through Traefik. To do this you must make two modifications to the `gateway` service. + +First, remove the `ports` section. + +Next, add the following `labels` directive to the `deploy` section of the gateway service. + +```yaml + gateway: + image: ... + networks: + ... + environment: + ... + deploy: + labels: + - traefik.port=8080 + - traefik.frontend.rule=PathPrefix:/ui,/system,/function + resources: + ... + secrets: + ... + ... +``` + +These labels expose the OpenFaaS gateway `/ui`, `/system`, and `/function` endpoints on port `8080` over Traefik. + +All together, your `gateway` service should now look like + +```yaml +... + gateway: + image: openfaas/gateway:0.9.11 + networks: + - functions + environment: + functions_provider_url: "http://faas-swarm:8080/" + read_timeout: "300s" # Maximum time to read HTTP request + write_timeout: "300s" # Maximum time to write HTTP response + upstream_timeout: "300s" # Maximum duration of upstream function call - should be more than read_timeout and write_timeout + dnsrr: "true" # Temporarily use dnsrr in place of VIP while issue persists on PWD + faas_nats_address: "nats" + faas_nats_port: 4222 + direct_functions: "true" # Functions are invoked directly over the overlay network + direct_functions_suffix: "" + basic_auth: "${BASIC_AUTH:-true}" + secret_mount_path: "/run/secrets/" + scale_from_zero: "true" + deploy: + labels: + - traefik.port=8080 + - traefik.frontend.rule=PathPrefix:/ui,/system,/function + resources: + # limits: # Enable if you want to limit memory usage + # memory: 200M + reservations: + memory: 100M + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 20 + window: 380s + placement: + constraints: + - 'node.platform.os == linux' + secrets: + - basic-auth-user + - basic-auth-password +... +``` + +### Configure data volumes + +Finally, while configuring Traefik, you mounted a volume called `acme`. You must now define the `acme` volume used for storing Let's Encrypt certificates. We can define an empty volume, meaning data will not persist if you destroy the container. If you destroy the container, the certificates will be regenerated the next time you start Traefik. + +Add the following volumes directive on the last line of the file: + +```yaml +... +volumes: + acme: +``` + +## Install OpenFaaS + +With all of the modifications in place, you can now deploy using the standard deployment scripts. On Mac and Linux: `deploy_stack.sh` and on Windows use `deploy_stack.ps1`. This script will deploy all of the required resources (services, configuration files, networks, and secrets) for your OpenFaaS cluster as they are defined in the `docker-compose.yaml` file. + +First, make sure that Docker will execute commands on your Swarm manager node: + +```bash +eval $(docker-machine env ) +``` + +Then, run your deployment script. A successful install will look like this: + +```bash +$ ./deploy_stack.sh +Attempting to create credentials for gateway.. +adadsf809adf098adfajlk12g +mb1jl213nlkmqfadsaokv68lh +[Credentials] + username: admin + password: + echo -n | faas-cli login --username=admin --password-stdin + +Enabling basic authentication for gateway.. + +Deploying OpenFaaS core services +Creating network func_functions +Creating config func_alertmanager_config +Creating config func_prometheus_config +Creating config func_prometheus_rules +Creating service func_alertmanager +Creating service func_traefik +Creating service func_gateway +Creating service func_faas-swarm +Creating service func_nats +Creating service func_queue-worker +Creating service func_prometheus +``` + +## Deploy and Invoke a function + +In your projects containing OpenFaaS functions, you can now deploy using your domain as the gateway. + +### Deploy from the CLI +```sh +faas-cli login --gateway https://openfaas.mydomain.com --username admin --password +faas-cli deploy --gateway https://openfaas.mydomain.com +``` +Replace `openfaas.mydomain.com` with your domain as well as adding the username `admin` and secure random password that the deploy script created for you when you deployed OpenFaaS. + +### Using the web UI +You can use the web UI to see the functions deployed to your cluster or to deploy functions from the Store. In your web browser, go to https://openfaas.mydomain.com/ui/. Note that the trailing slash is required. + +On your first visit, the HTTP authentication dialogue box will open, you can login with the username `admin` and secure random password that the deploy script created for you when you deployed OpenFaaS. + +## Verify and Debug + +- If you want to tail the Traefik logs, you can use +```sh +$ docker service ls -f traefik +``` +You can see internet traffic logs as well as logs related to the Let's Encrypt certificate process. + +## Profit! + +[traefik]: https://traefik.io/ +[letsencrypt]: https://letsencrypt.org/ diff --git a/mkdocs.yml b/mkdocs.yml index dceb9881..24924d94 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -126,6 +126,7 @@ nav: - Jenkins: ./reference/cicd/jenkins.md - SSL: - Kubernetes: ./reference/ssl/kubernetes-with-cert-manager.md + - Docker Swarm: ./reference/ssl/swarm-with-traefik.md - Secrets: ./reference/secrets.md - Async: ./reference/async.md - Triggers: ./reference/triggers.md From 65d048b0bd53bc5321aec26af7c219466e075bb3 Mon Sep 17 00:00:00 2001 From: Lucas Roesler Date: Fri, 28 Dec 2018 20:13:11 +0100 Subject: [PATCH 02/11] Fix duplicate "is" typo **What** - Replace duplicate "is" with missing "a" in the opening statement Signed-off-by: Lucas Roesler --- docs/reference/ssl/swarm-with-traefik.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/ssl/swarm-with-traefik.md b/docs/reference/ssl/swarm-with-traefik.md index 090e3c55..9fee3319 100644 --- a/docs/reference/ssl/swarm-with-traefik.md +++ b/docs/reference/ssl/swarm-with-traefik.md @@ -1,6 +1,6 @@ # SSL on Swarm with Traefik -To completely secure your OpenFaaS installation, you need SSL. On Swarm, you can do this easily with [Traefik][traefik] and [Let's Encrypt][letsencrypt]. Traefik is is reverse proxy that comes with SSL support via Let's Encrypt. In this tutorial we will show you how to deploy OpenFaaS with Traefik. +To completely secure your OpenFaaS installation, you need SSL. On Swarm, you can do this easily with [Traefik][traefik] and [Let's Encrypt][letsencrypt]. Traefik is a reverse proxy that comes with SSL support via Let's Encrypt. In this tutorial we will show you how to deploy OpenFaaS with Traefik. ## Create an A record From d309564005f924adc0d17e5de6b2b1153b59f83f Mon Sep 17 00:00:00 2001 From: Lucas Roesler Date: Fri, 28 Dec 2018 20:15:14 +0100 Subject: [PATCH 03/11] Add missing word to configure traefik intro **What** - Add missing "to" - Replace "the internate" with "publicaly" Signed-off-by: Lucas Roesler --- docs/reference/ssl/swarm-with-traefik.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/ssl/swarm-with-traefik.md b/docs/reference/ssl/swarm-with-traefik.md index 9fee3319..928795e7 100644 --- a/docs/reference/ssl/swarm-with-traefik.md +++ b/docs/reference/ssl/swarm-with-traefik.md @@ -10,7 +10,7 @@ If your domain is `.domain.com` then create an A record using your DNS administr ## Update the Compose configuration ### Configure Traefik -To use Traefik with OpenFaaS, you need to modify the OpenFaaS deployment manifest to include Traefik and configuring OpenFaaS communicate through Traefik instead of directly exposing its services to the internet. +To use Traefik with OpenFaaS, you need to modify the OpenFaaS deployment manifest to include Traefik and configuring OpenFaaS to communicate through Traefik instead of directly exposing its services publicly. 1. Clone OpenFaaS and then checkout the latest stable release: From 19b95b47726bddef5d804b10cae11dd3fb224ca6 Mon Sep 17 00:00:00 2001 From: Lucas Roesler Date: Fri, 28 Dec 2018 20:16:38 +0100 Subject: [PATCH 04/11] Fix traefix typo in traefik part number 6 Signed-off-by: Lucas Roesler --- docs/reference/ssl/swarm-with-traefik.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/ssl/swarm-with-traefik.md b/docs/reference/ssl/swarm-with-traefik.md index 928795e7..4a73abcb 100644 --- a/docs/reference/ssl/swarm-with-traefik.md +++ b/docs/reference/ssl/swarm-with-traefik.md @@ -90,7 +90,7 @@ To use Traefik with OpenFaaS, you need to modify the OpenFaaS deployment manifes - "acme:/etc/traefik/acme" ... ``` -6. Next you must configure the networks the `traefix` service is part of. All OpenFaaS components live on the `functions` networks, which is also defined in the compose file. +6. Next you must configure the networks the `traefik` service is part of. All OpenFaaS components live on the `functions` networks, which is also defined in the compose file. ```yaml ... From f35ceb2b56cf00404f2e735e58f096e16720d783 Mon Sep 17 00:00:00 2001 From: Lucas Roesler Date: Fri, 28 Dec 2018 20:17:40 +0100 Subject: [PATCH 05/11] Fix logs debug command **What** - Replace `ls` with `logs` Signed-off-by: Lucas Roesler --- docs/reference/ssl/swarm-with-traefik.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/ssl/swarm-with-traefik.md b/docs/reference/ssl/swarm-with-traefik.md index 4a73abcb..9af8e6e5 100644 --- a/docs/reference/ssl/swarm-with-traefik.md +++ b/docs/reference/ssl/swarm-with-traefik.md @@ -309,7 +309,7 @@ On your first visit, the HTTP authentication dialogue box will open, you can log - If you want to tail the Traefik logs, you can use ```sh -$ docker service ls -f traefik +$ docker service logs -f traefik ``` You can see internet traffic logs as well as logs related to the Let's Encrypt certificate process. From 9965f0bef00c4c1c1778919e3ebf14247b43eb5f Mon Sep 17 00:00:00 2001 From: Lucas Roesler Date: Fri, 28 Dec 2018 20:24:32 +0100 Subject: [PATCH 06/11] Cleanup quotes in the traefik command **What** - Remove the unnecceessary single quotes Signed-off-by: Lucas Roesler --- docs/reference/ssl/swarm-with-traefik.md | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/reference/ssl/swarm-with-traefik.md b/docs/reference/ssl/swarm-with-traefik.md index 9af8e6e5..38a343cc 100644 --- a/docs/reference/ssl/swarm-with-traefik.md +++ b/docs/reference/ssl/swarm-with-traefik.md @@ -42,15 +42,15 @@ To use Traefik with OpenFaaS, you need to modify the OpenFaaS deployment manifes - "--docker.swarmmode=true" - "--docker.domain=traefik" - "--docker.watch=true" - - "--defaultEntryPoints='http,https'" - - "--entryPoints='Name:https Address::443 TLS'" - - "--entryPoints='Name:http Address::80'" + - "--defaultEntryPoints=http,https" + - "--entryPoints=Name:https Address::443 TLS" + - "--entryPoints=Name:http Address::80" - "--acme=true" - - "--acme.entrypoint='https'" + - "--acme.entrypoint=https" - "--acme.httpchallenge=true" - - "--acme.httpchallenge.entrypoint='http'" - - "--acme.domains='openfaas.mydomain.com, www.openfaas.mydomain.com'" - - "--acme.email=''" + - "--acme.httpchallenge.entrypoint=http" + - "--acme.domains=openfaas.mydomain.com" + - "--acme.email=" - "--acme.ondemand=true" - "--acme.onhostrule=true" - "--acme.storage=/etc/traefik/acme/acme.json" @@ -139,15 +139,15 @@ services: - "--docker.swarmmode=true" - "--docker.domain=traefik" - "--docker.watch=true" - - "--defaultEntryPoints='http,https'" - - "--entryPoints='Name:https Address::443 TLS'" - - "--entryPoints='Name:http Address::80'" + - "--defaultEntryPoints=http,https" + - "--entryPoints=Name:https Address::443 TLS" + - "--entryPoints=Name:http Address::80" - "--acme=true" - - "--acme.entrypoint='https'" + - "--acme.entrypoint=https" - "--acme.httpchallenge=true" - - "--acme.httpchallenge.entrypoint='http'" - - "--acme.domains='openfaas.mydomain.com, www.openfaas.mydomain.com'" - - "--acme.email=''" + - "--acme.httpchallenge.entrypoint=http" + - "--acme.domains=openfaas.mydomain.com" + - "--acme.email=" - "--acme.ondemand=true" - "--acme.onhostrule=true" - "--acme.storage=/etc/traefik/acme/acme.json" From 37b150093cf82074538c7781bd295eca455f3523 Mon Sep 17 00:00:00 2001 From: Lucas Roesler Date: Wed, 2 Jan 2019 09:07:33 +0100 Subject: [PATCH 07/11] Remove profit section Signed-off-by: Lucas Roesler --- docs/reference/ssl/swarm-with-traefik.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/reference/ssl/swarm-with-traefik.md b/docs/reference/ssl/swarm-with-traefik.md index 38a343cc..69b398fd 100644 --- a/docs/reference/ssl/swarm-with-traefik.md +++ b/docs/reference/ssl/swarm-with-traefik.md @@ -313,7 +313,5 @@ $ docker service logs -f traefik ``` You can see internet traffic logs as well as logs related to the Let's Encrypt certificate process. -## Profit! - [traefik]: https://traefik.io/ [letsencrypt]: https://letsencrypt.org/ From b1b8278defb6c9efac613949a4d57e42cc9dff39 Mon Sep 17 00:00:00 2001 From: Lucas Roesler Date: Wed, 2 Jan 2019 09:14:30 +0100 Subject: [PATCH 08/11] Consolidate traefik configuration steps **What** - Reduce the number of steps so that it is easier for people to see the required changes Signed-off-by: Lucas Roesler --- docs/reference/ssl/swarm-with-traefik.md | 127 +++-------------------- 1 file changed, 17 insertions(+), 110 deletions(-) diff --git a/docs/reference/ssl/swarm-with-traefik.md b/docs/reference/ssl/swarm-with-traefik.md index 69b398fd..21c32800 100644 --- a/docs/reference/ssl/swarm-with-traefik.md +++ b/docs/reference/ssl/swarm-with-traefik.md @@ -12,121 +12,16 @@ If your domain is `.domain.com` then create an A record using your DNS administr ### Configure Traefik To use Traefik with OpenFaaS, you need to modify the OpenFaaS deployment manifest to include Traefik and configuring OpenFaaS to communicate through Traefik instead of directly exposing its services publicly. -1. Clone OpenFaaS and then checkout the latest stable release: +Clone OpenFaaS and then checkout the latest stable release: ```bash $ git clone https://github.com/openfaas/faas && cd faas ``` -2. Add the `traefik` service to the `docker-compose.yaml`. +Add the `traefik` service to the `docker-compose.yaml`. - To start, open `docker-compose.yaml` in your favorite editor and add a `traefik` service like this: +To start, open `docker-compose.yaml` in your favorite editor and add a `traefik` service like this: - ```yaml - version: "3.3" - services: - traefik: - image: traefik:v1.7.6 - gateway: - ... - ``` -3. Next, to configure Traefik to work with Docker Swarm _and_ Let's Encrypt, you must override the default `command` to the `traefik` service. The `traefik` section of the `docker-compose.yaml` file should look like this: - - ```yaml - ... - traefik: - image: traefik:v1.7.6 - command: - - "--api=true" - - "--docker=true" - - "--docker.swarmmode=true" - - "--docker.domain=traefik" - - "--docker.watch=true" - - "--defaultEntryPoints=http,https" - - "--entryPoints=Name:https Address::443 TLS" - - "--entryPoints=Name:http Address::80" - - "--acme=true" - - "--acme.entrypoint=https" - - "--acme.httpchallenge=true" - - "--acme.httpchallenge.entrypoint=http" - - "--acme.domains=openfaas.mydomain.com" - - "--acme.email=" - - "--acme.ondemand=true" - - "--acme.onhostrule=true" - - "--acme.storage=/etc/traefik/acme/acme.json" - ... - ``` - - * The `--api=true` flag enables Traefik's Web UI, - * The `--docker.*` flags tell Traefik to use Docker and specify that it's running in a Docker Swarm cluster. - * The `--defaultEntryPoints` and `--entryPoints` flags define entry points and protocols to be used. In our case this includes HTTP on port 80 and HTTPS on port 443. - * The `--acme.*` flags configure Traefik to use the ACME protocol to generate Let's Encrypt certificates to secure your OpenFaaS cluster with SSL. Make sure to replace the `openfaas.mydomain.com` domain placeholders in the `--acme.domains` flag with your own domain. You can specify multiple domains by separating them with a comma and space. -4. Expose the ports required for Traefik. Traefik uses port `8080` for its operations and UI, while in the last step we configured ports `80` and `443` and entrypoints for internet traffic. These will be used / proxied to OpenFaaS - - ```yaml - ... - traefik: - image: traefik:v1.7.6 - command: - ... - ports: - - 80:80 - - 8080:8080 - - 443:443 - ... - ``` -5. Next you must configure the volumes needed for Traefik, in this case, the docker socket and some file storage. The Docker socket file communicates with the Docker API in order to manage your containers and will provide details about them, such as number of containers and their IP addresses, to Traefik. You will also mount the volume called acme, which we'll define later in this step. - - ```yaml - ... - traefik: - image: traefik:v1.7.6 - command: - ... - ports: - ... - volumes: - - "/var/run/docker.sock:/var/run/docker.sock" - - "acme:/etc/traefik/acme" - ... - ``` -6. Next you must configure the networks the `traefik` service is part of. All OpenFaaS components live on the `functions` networks, which is also defined in the compose file. - - ```yaml - ... - traefik: - image: traefik:v1.7.6 - command: - ... - ports: - ... - volumes: - ... - networks: - - functions - ... - ``` -7. Lastly, you must configure the `deploy` section so that Traefik is only deployed on the Docker Swarm manager. - - ```yaml - ... - traefik: - image: traefik:v1.7.6 - command: - ... - ports: - ... - volumes: - ... - networks: - ... - deploy: - placement: - constraints: [node.role == manager] - ... - ``` - -All together, the `traefik` service block should look like ```yaml version: "3.3" @@ -159,15 +54,27 @@ services: - "/var/run/docker.sock:/var/run/docker.sock" - "acme:/etc/traefik/acme" networks: - - functions + - functions deploy: - placement: + placement: constraints: [node.role == manager] gateway: ... ``` +This configuration does a few important things: + +* The `--api=true` flag enables Traefik's Web UI, +* The `--docker.*` flags tell Traefik to use Docker and specify that it's running in a Docker Swarm cluster. +* The `--defaultEntryPoints` and `--entryPoints` flags define entry points and protocols to be used. In our case this includes HTTP on port 80 and HTTPS on port 443. +* The `--acme.*` flags configure Traefik to use the ACME protocol to generate Let's Encrypt certificates to secure your OpenFaaS cluster with SSL. Make sure to replace the `openfaas.mydomain.com` domain placeholders in the `--acme.domains` flag with your own domain. You can specify multiple domains by separating them with a comma and space. We also setup a volume `acme` to store the resulting certificate files. +* Expose the ports required for Traefik. Traefik uses port `8080` for its operations and UI, while in the last step we configured ports `80` and `443` and entrypoints for internet traffic. These will be used / proxied to OpenFaaS +* Binds the docker socket to the traefik container so that it can communicate with the Docker API and dertermine the number of containers and their IP addressess. +* Adds `traefik` to the `functions network so that it can communicate with the OpenFaaS components. +* Ensures that Traefik is only deployed on the Docker Swarm manager. + + ### Configure OpenFaaS By default, the original `docker-compose.yaml` file exposes the OpenFaaS `gateway` on port `8080`. This conflicts with the configuration of Traefik, additionally, we want all communication to safely pass through Traefik. To do this you must make two modifications to the `gateway` service. From 16573166ddfe80565be8bba3c4ec4ab4ac834d88 Mon Sep 17 00:00:00 2001 From: Lucas Roesler Date: Wed, 2 Jan 2019 09:15:49 +0100 Subject: [PATCH 09/11] Update titles to active voice Signed-off-by: Lucas Roesler --- docs/reference/ssl/swarm-with-traefik.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/ssl/swarm-with-traefik.md b/docs/reference/ssl/swarm-with-traefik.md index 21c32800..3a730dc7 100644 --- a/docs/reference/ssl/swarm-with-traefik.md +++ b/docs/reference/ssl/swarm-with-traefik.md @@ -207,7 +207,7 @@ faas-cli deploy --gateway https://openfaas.mydomain.com ``` Replace `openfaas.mydomain.com` with your domain as well as adding the username `admin` and secure random password that the deploy script created for you when you deployed OpenFaaS. -### Using the web UI +### Use the web UI You can use the web UI to see the functions deployed to your cluster or to deploy functions from the Store. In your web browser, go to https://openfaas.mydomain.com/ui/. Note that the trailing slash is required. On your first visit, the HTTP authentication dialogue box will open, you can login with the username `admin` and secure random password that the deploy script created for you when you deployed OpenFaaS. From ce6fecd7535561feee7910a7e4c16bbca75642d5 Mon Sep 17 00:00:00 2001 From: Lucas Roesler Date: Wed, 2 Jan 2019 09:19:13 +0100 Subject: [PATCH 10/11] Simplify the configure openfaas section **What** - Remove the "all together" snippet since the modification is so small and it should be clear. This should make it easier for someone to see what is happening instead of a large block of yaml Signed-off-by: Lucas Roesler --- docs/reference/ssl/swarm-with-traefik.md | 44 ------------------------ 1 file changed, 44 deletions(-) diff --git a/docs/reference/ssl/swarm-with-traefik.md b/docs/reference/ssl/swarm-with-traefik.md index 3a730dc7..c8c5902a 100644 --- a/docs/reference/ssl/swarm-with-traefik.md +++ b/docs/reference/ssl/swarm-with-traefik.md @@ -102,50 +102,6 @@ Next, add the following `labels` directive to the `deploy` section of the gatewa These labels expose the OpenFaaS gateway `/ui`, `/system`, and `/function` endpoints on port `8080` over Traefik. -All together, your `gateway` service should now look like - -```yaml -... - gateway: - image: openfaas/gateway:0.9.11 - networks: - - functions - environment: - functions_provider_url: "http://faas-swarm:8080/" - read_timeout: "300s" # Maximum time to read HTTP request - write_timeout: "300s" # Maximum time to write HTTP response - upstream_timeout: "300s" # Maximum duration of upstream function call - should be more than read_timeout and write_timeout - dnsrr: "true" # Temporarily use dnsrr in place of VIP while issue persists on PWD - faas_nats_address: "nats" - faas_nats_port: 4222 - direct_functions: "true" # Functions are invoked directly over the overlay network - direct_functions_suffix: "" - basic_auth: "${BASIC_AUTH:-true}" - secret_mount_path: "/run/secrets/" - scale_from_zero: "true" - deploy: - labels: - - traefik.port=8080 - - traefik.frontend.rule=PathPrefix:/ui,/system,/function - resources: - # limits: # Enable if you want to limit memory usage - # memory: 200M - reservations: - memory: 100M - restart_policy: - condition: on-failure - delay: 5s - max_attempts: 20 - window: 380s - placement: - constraints: - - 'node.platform.os == linux' - secrets: - - basic-auth-user - - basic-auth-password -... -``` - ### Configure data volumes Finally, while configuring Traefik, you mounted a volume called `acme`. You must now define the `acme` volume used for storing Let's Encrypt certificates. We can define an empty volume, meaning data will not persist if you destroy the container. If you destroy the container, the certificates will be regenerated the next time you start Traefik. From 0157693997c1f49281693a451796b2f3ebbf5c2b Mon Sep 17 00:00:00 2001 From: Lucas Roesler Date: Sat, 1 Feb 2020 13:57:57 +0100 Subject: [PATCH 11/11] Update guide to use the traefik 2.1.0 **What** - Update the instructions to use the latest Traefik version and based on the Traefik user guide https://docs.traefik.io/user-guides/docker-compose/acme-http/ This also make several other changes to improve the readability Signed-off-by: Lucas Roesler --- docs/reference/ssl/compose-example.yaml | 265 +++++++++++++++++++++++ docs/reference/ssl/swarm-with-traefik.md | 98 +++++---- 2 files changed, 317 insertions(+), 46 deletions(-) create mode 100644 docs/reference/ssl/compose-example.yaml diff --git a/docs/reference/ssl/compose-example.yaml b/docs/reference/ssl/compose-example.yaml new file mode 100644 index 00000000..c4f9255f --- /dev/null +++ b/docs/reference/ssl/compose-example.yaml @@ -0,0 +1,265 @@ +version: "3.3" +services: + traefik: + image: traefik:v2.1.3 + container_name: "traefik" + command: + - "--api.insecure=true" + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + - "--entrypoints.web.address=:80" + - "--entrypoints.websecure.address=:443" + - "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true" + - "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web" + - "--certificatesresolvers.myhttpchallenge.acme.email=" + - "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json" + ports: + - "80:80" + - "443:443" + - "8080:8080" + volumes: + - "./letsencrypt:/letsencrypt" + - "/var/run/docker.sock:/var/run/docker.sock" + networks: + - functions + placement: + constraints: [node.role == manager] + + gateway: + ports: + - 8080:8080 + image: openfaas/gateway:0.18.10 + networks: + - functions + labels: + - "traefik.enable=true" + - "traefik.http.routers.gateway.rule=Host(`gw.example.com`)" + - "traefik.http.routers.gateway.entrypoints=websecure" + - "traefik.http.routers.gateway.tls.certresolver=myhttpchallenge" + environment: + functions_provider_url: "http://faas-swarm:8080/" + read_timeout: "5m5s" # Maximum time to read HTTP request + write_timeout: "5m5s" # Maximum time to write HTTP response + upstream_timeout: "5m" # Maximum duration of upstream function call - should be more than read_timeout and write_timeout + dnsrr: "true" # Temporarily use dnsrr in place of VIP while issue persists on PWD + faas_nats_address: "nats" + faas_nats_port: 4222 + direct_functions: "true" # Functions are invoked directly over the overlay network + direct_functions_suffix: "" + basic_auth: "${BASIC_AUTH:-false}" + secret_mount_path: "/run/secrets/" + scale_from_zero: "true" # Enable if you want functions to scale from 0/0 to min replica count upon invoke + max_idle_conns: 1024 + max_idle_conns_per_host: 1024 + auth_proxy_url: "${AUTH_URL:-}" + auth_proxy_pass_body: "false" + deploy: + resources: + # limits: # Enable if you want to limit memory usage + # memory: 200M + reservations: + memory: 100M + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 20 + window: 380s + placement: + constraints: + - "node.platform.os == linux" + secrets: + - basic-auth-user + - basic-auth-password + + # auth service provide basic-auth plugin for system APIs + basic-auth-plugin: + image: openfaas/basic-auth-plugin:0.18.10 + networks: + - functions + environment: + secret_mount_path: "/run/secrets/" + user_filename: "basic-auth-user" + pass_filename: "basic-auth-password" + deploy: + placement: + constraints: + - "node.role == manager" + - "node.platform.os == linux" + resources: + # limits: # Enable if you want to limit memory usage + # memory: 100M + reservations: + memory: 50M + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 20 + window: 380s + secrets: + - basic-auth-user + - basic-auth-password + + # Docker Swarm provider + faas-swarm: + volumes: + - "/var/run/docker.sock:/var/run/docker.sock" + image: openfaas/faas-swarm:0.8.2 + networks: + - functions + environment: + read_timeout: "5m5s" # set both here, and on your functions + write_timeout: "5m5s" # set both here, and on your functions + DOCKER_API_VERSION: "1.30" + basic_auth: "${BASIC_AUTH:-false}" + secret_mount_path: "/run/secrets/" + deploy: + placement: + constraints: + - "node.role == manager" + - "node.platform.os == linux" + resources: + # limits: # Enable if you want to limit memory usage + # memory: 100M + reservations: + memory: 100M + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 20 + window: 380s + secrets: + - basic-auth-user + - basic-auth-password + + nats: + image: nats-streaming:0.11.2 + # Uncomment the following port mappings if you wish to expose the + # NATS client and/or management ports you must also add `-m 8222` to the command + # ports: + # - 4222:4222 + # - 8222:8222 + command: "--store memory --cluster_id faas-cluster" + networks: + - functions + deploy: + resources: + limits: + memory: 125M + reservations: + memory: 50M + placement: + constraints: + - "node.platform.os == linux" + + queue-worker: + image: openfaas/queue-worker:0.8.4 + networks: + - functions + environment: + max_inflight: "1" + ack_wait: "5m5s" # Max duration of any async task / request + basic_auth: "${BASIC_AUTH:-false}" + secret_mount_path: "/run/secrets/" + gateway_invoke: "true" + faas_gateway_address: "gateway" + deploy: + resources: + limits: + memory: 50M + reservations: + memory: 20M + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 20 + window: 380s + placement: + constraints: + - "node.platform.os == linux" + secrets: + - basic-auth-user + - basic-auth-password + + # End services + + # Start monitoring + + prometheus: + image: prom/prometheus:v2.11.0 + environment: + no_proxy: "gateway" + configs: + - source: prometheus_config + target: /etc/prometheus/prometheus.yml + - source: prometheus_rules + target: /etc/prometheus/alert.rules.yml + command: + - "--config.file=/etc/prometheus/prometheus.yml" + # - '-storage.local.path=/prometheus' + ports: + - 9090:9090 + networks: + - functions + deploy: + placement: + constraints: + - "node.role == manager" + - "node.platform.os == linux" + resources: + limits: + memory: 500M + reservations: + memory: 200M + + alertmanager: + image: prom/alertmanager:v0.18.0 + environment: + no_proxy: "gateway" + command: + - "--config.file=/alertmanager.yml" + - "--storage.path=/alertmanager" + networks: + - functions + # Uncomment the following port mapping if you wish to expose the Prometheus + # Alertmanager UI. + # ports: + # - 9093:9093 + deploy: + resources: + limits: + memory: 50M + reservations: + memory: 20M + placement: + constraints: + - "node.role == manager" + - "node.platform.os == linux" + configs: + - source: alertmanager_config + target: /alertmanager.yml + secrets: + - basic-auth-password + +configs: + prometheus_config: + file: ./prometheus/prometheus.yml + prometheus_rules: + file: ./prometheus/alert.rules.yml + alertmanager_config: + file: ./prometheus/alertmanager.yml + +networks: + functions: + driver: overlay + attachable: true + labels: + - "openfaas=true" + +secrets: + basic-auth-user: + external: true + basic-auth-password: + external: true + +volumes: + letsencrypt: diff --git a/docs/reference/ssl/swarm-with-traefik.md b/docs/reference/ssl/swarm-with-traefik.md index c8c5902a..33532a7f 100644 --- a/docs/reference/ssl/swarm-with-traefik.md +++ b/docs/reference/ssl/swarm-with-traefik.md @@ -1,14 +1,27 @@ -# SSL on Swarm with Traefik +# SSL on Docker Swarm with Traefik -To completely secure your OpenFaaS installation, you need SSL. On Swarm, you can do this easily with [Traefik][traefik] and [Let's Encrypt][letsencrypt]. Traefik is a reverse proxy that comes with SSL support via Let's Encrypt. In this tutorial we will show you how to deploy OpenFaaS with Traefik. +To help secure your OpenFaaS installation, you need TLS. On [Docker Swarm](docs/reference/ssl/kubernetes-with-cert-manager.md), you can do this easily with [Traefik](https://traefik.io/) and [Let's Encrypt](https://letsencrypt.org/). Traefik is a reverse proxy that comes with TLS support via Let's Encrypt. In this tutorial we will show you how to deploy OpenFaaS with Traefik. -## Create an A record +### Create a DNS record -If your domain is `.domain.com` then create an A record using your DNS administration panel such as `gateway.domain.com` or `openfaas.domain.com`. The required steps will vary depending on your domain provider and your cluster provider. For example; [on Google Cloud DNS](https://cloud.google.com/kubernetes-engine/docs/tutorials/configuring-domain-name-static-ip) or [with Route53 using AWS](https://kubernetes.io/docs/setup/custom-cloud/kops/#2-5-create-a-route53-domain-for-your-cluster). +Determine the public IP address that can be used to access your cluster. +If your domain is `.example.com` then create an A record using your DNS administration panel such as `gw.example.com`. + +> The required steps will vary depending on your domain provider and your cluster provider. For example; [on Google Cloud DNS](https://cloud.google.com/kubernetes-engine/docs/tutorials/configuring-domain-name-static-ip) or [with Route53 using AWS](https://kubernetes.io/docs/setup/custom-cloud/kops/#2-5-create-a-route53-domain-for-your-cluster). + +Once created, verify that what you entered into your DNS control-panel worked with `ping`: + +```sh +ping gw.example.com +``` + +You should now see the value you entered. Sometimes DNS can take 1-5 minutes to propagate. ## Update the Compose configuration +A complete example `docker-compose.yaml` can be found [here](./compose-example.yaml) + ### Configure Traefik To use Traefik with OpenFaaS, you need to modify the OpenFaaS deployment manifest to include Traefik and configuring OpenFaaS to communicate through Traefik instead of directly exposing its services publicly. @@ -27,35 +40,27 @@ To start, open `docker-compose.yaml` in your favorite editor and add a `traefik` version: "3.3" services: traefik: - image: traefik:v1.7.6 + image: traefik:v2.1.3 + container_name: "traefik" command: - - "--api=true" - - "--docker=true" - - "--docker.swarmmode=true" - - "--docker.domain=traefik" - - "--docker.watch=true" - - "--defaultEntryPoints=http,https" - - "--entryPoints=Name:https Address::443 TLS" - - "--entryPoints=Name:http Address::80" - - "--acme=true" - - "--acme.entrypoint=https" - - "--acme.httpchallenge=true" - - "--acme.httpchallenge.entrypoint=http" - - "--acme.domains=openfaas.mydomain.com" - - "--acme.email=" - - "--acme.ondemand=true" - - "--acme.onhostrule=true" - - "--acme.storage=/etc/traefik/acme/acme.json" + - "--api.insecure=true" + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + - "--entrypoints.web.address=:80" + - "--entrypoints.websecure.address=:443" + - "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true" + - "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web" + - "--certificatesresolvers.myhttpchallenge.acme.email=" + - "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json" ports: - - 80:80 - - 8080:8080 - - 443:443 + - "80:80" + - "443:443" + - "8080:8080" volumes: + - "./letsencrypt:/letsencrypt" - "/var/run/docker.sock:/var/run/docker.sock" - - "acme:/etc/traefik/acme" networks: - functions - deploy: placement: constraints: [node.role == manager] @@ -65,10 +70,10 @@ services: This configuration does a few important things: -* The `--api=true` flag enables Traefik's Web UI, -* The `--docker.*` flags tell Traefik to use Docker and specify that it's running in a Docker Swarm cluster. -* The `--defaultEntryPoints` and `--entryPoints` flags define entry points and protocols to be used. In our case this includes HTTP on port 80 and HTTPS on port 443. -* The `--acme.*` flags configure Traefik to use the ACME protocol to generate Let's Encrypt certificates to secure your OpenFaaS cluster with SSL. Make sure to replace the `openfaas.mydomain.com` domain placeholders in the `--acme.domains` flag with your own domain. You can specify multiple domains by separating them with a comma and space. We also setup a volume `acme` to store the resulting certificate files. +* The `--providers.docker.*` flags tell Traefik to use Docker and specify that it's running in a Docker Swarm cluster. +* The `--entryPoints` flags define entry points and protocols to be used. In our case this includes HTTP on port 80 and HTTPS on port 443. +* The `--certificatesresolvers.*` flags configure Traefik to use the ACME protocol to generate Let's Encrypt certificates to secure your OpenFaaS cluster with SSL. +Make sure to set your own email within the `certificatesresolvers.myhttpchallenge.acme.email` command line argument of the traefik service. * Expose the ports required for Traefik. Traefik uses port `8080` for its operations and UI, while in the last step we configured ports `80` and `443` and entrypoints for internet traffic. These will be used / proxied to OpenFaaS * Binds the docker socket to the traefik container so that it can communicate with the Docker API and dertermine the number of containers and their IP addressess. * Adds `traefik` to the `functions network so that it can communicate with the OpenFaaS components. @@ -80,7 +85,7 @@ By default, the original `docker-compose.yaml` file exposes the OpenFaaS `gatewa First, remove the `ports` section. -Next, add the following `labels` directive to the `deploy` section of the gateway service. +Next, add the following `labels` directive to the gateway service. ```yaml gateway: @@ -89,31 +94,34 @@ Next, add the following `labels` directive to the `deploy` section of the gatewa ... environment: ... + labels: + - "traefik.enable=true" + - "traefik.http.routers.gateway.rule=Host(`gw.example.com`)" + - "traefik.http.routers.gateway.entrypoints=websecure" + - "traefik.http.routers.gateway.tls.certresolver=myhttpchallenge" deploy: - labels: - - traefik.port=8080 - - traefik.frontend.rule=PathPrefix:/ui,/system,/function - resources: - ... + ... secrets: ... ... ``` -These labels expose the OpenFaaS gateway `/ui`, `/system`, and `/function` endpoints on port `8080` over Traefik. +Traefik uses reads these labels from the Docker API to detect and configure the routing for the gateway. ### Configure data volumes -Finally, while configuring Traefik, you mounted a volume called `acme`. You must now define the `acme` volume used for storing Let's Encrypt certificates. We can define an empty volume, meaning data will not persist if you destroy the container. If you destroy the container, the certificates will be regenerated the next time you start Traefik. +Finally, while configuring Traefik, you mounted a volume called `letsencrypt`. You must now define the `letsencrypt` volume used for storing Let's Encrypt certificates. We can define an empty volume, meaning data will not persist if you destroy the container. If you destroy the container, the certificates will be regenerated the next time you start Traefik. Add the following volumes directive on the last line of the file: ```yaml ... volumes: - acme: + letsencrypt: ``` +A complete example `docker-compose.yaml` can be found [here](./compose-example.yaml) + ## Install OpenFaaS With all of the modifications in place, you can now deploy using the standard deployment scripts. On Mac and Linux: `deploy_stack.sh` and on Windows use `deploy_stack.ps1`. This script will deploy all of the required resources (services, configuration files, networks, and secrets) for your OpenFaaS cluster as they are defined in the `docker-compose.yaml` file. @@ -158,13 +166,13 @@ In your projects containing OpenFaaS functions, you can now deploy using your do ### Deploy from the CLI ```sh -faas-cli login --gateway https://openfaas.mydomain.com --username admin --password -faas-cli deploy --gateway https://openfaas.mydomain.com +faas-cli login --gateway https://gw.example.com --username admin --password +faas-cli deploy --gateway https://gw.example.com ``` -Replace `openfaas.mydomain.com` with your domain as well as adding the username `admin` and secure random password that the deploy script created for you when you deployed OpenFaaS. +Replace `gw.example.com` with your domain as well as adding the username `admin` and secure random password that the deploy script created for you when you deployed OpenFaaS. ### Use the web UI -You can use the web UI to see the functions deployed to your cluster or to deploy functions from the Store. In your web browser, go to https://openfaas.mydomain.com/ui/. Note that the trailing slash is required. +You can use the web UI to see the functions deployed to your cluster or to deploy functions from the Store. In your web browser, go to https://gw.example.com/ui/. Note that the trailing slash is required. On your first visit, the HTTP authentication dialogue box will open, you can login with the username `admin` and secure random password that the deploy script created for you when you deployed OpenFaaS. @@ -176,5 +184,3 @@ $ docker service logs -f traefik ``` You can see internet traffic logs as well as logs related to the Let's Encrypt certificate process. -[traefik]: https://traefik.io/ -[letsencrypt]: https://letsencrypt.org/