DEV Community

Cover image for Traefik Proxy e Amazon ECS
Federico Verdi
Federico Verdi

Posted on

Traefik Proxy e Amazon ECS

Vediamo insieme come effettuare il deploy di Traefik Proxy su Amazon ECS e come definire un task gestito da quest'ultimo.

Diamo per scontato di avere a disposizione un cluster di ECS ( Ec2 o Fargate ) su cui poter distribuire nuovi service..

Creazione della Task Definition per Traefik Proxy

Il fulcro di tutto è la task definition da applicare al nuovo service ..

Ecco un esempio di task definition che andremo ad analizzare:

{
    "family": "Proxy",
    "containerDefinitions": [
        {
            "name": "Proxy",
            "image": "traefik:latest",
            "cpu": 0,
            "memory": 512,
            "portMappings": [
                {
                    "containerPort": 80,
                    "hostPort": 80,
                    "protocol": "tcp"
                },
                {
                    "containerPort": 443,
                    "hostPort": 443,
                    "protocol": "tcp"
                }
            ],
            "essential": true,
            "entryPoint": [],
            "command": [
                "--api.dashboard=true",
                "--api.insecure=false",
                "--accesslog=true",
                "--accesslog.filepath=/var/log/traefik/access.log",
                "--providers.ecs.ecsAnywhere=true",
                "--providers.ecs.region=eu-west-1",
                "--providers.ecs.autoDiscoverClusters=false",
                "--providers.ecs.exposedByDefault=true",
                "--providers.ecs.clusters=Cluster",
                "--entrypoints.web.address=:80",
                "--entrypoints.websecure.address=:443",
                "--certificatesresolvers.myresolver.acme.httpchallenge=true",
                "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web",
                "--certificatesresolvers.myresolver.acme.email=email@email.it",
                "--certificatesresolvers.myresolver.acme.storage=/var/letsandcrypt/acme.json",
                "--log.level=DEBUG",
                "--certificatesresolvers.myresolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directory",
                "--entrypoints.web.http.redirections.entrypoint.to=websecure",
                "--entrypoints.web.http.redirections.entrypoint.scheme=https"
            ],
            "environment": [],
            "mountPoints": [
                {
                    "sourceVolume": "letsandcrypt",
                    "containerPath": "/var/letsandcrypt"
                },
                {
                    "sourceVolume": "log",
                    "containerPath": "/var/log/traefik"
                }
            ],
            "volumesFrom": [],
            "dockerLabels": {
                "traefik.enable": "true",
                "traefik.http.middlewares.traefik-dashboard-auth.basicauth.users": "test:xxxxxxxxx",
                "traefik.http.routers.api.entrypoints": "websecure",
                "traefik.http.routers.api.middlewares": "traefik-dashboard-auth",
                "traefik.http.routers.api.rule": "Host(`proxy.test.it`)",
                "traefik.http.routers.api.service": "api@internal",
                "traefik.http.routers.api.tls": "true",
                "traefik.http.routers.api.tls.certresolver": "myresolver"
            }
        }
    ],
    "taskRoleArn": "arn:aws:iam::000000000000:role/ecsTaskExecutionRole",
    "executionRoleArn": "arn:aws:iam::000000000000:role/ecsTaskExecutionRole",
    "volumes": [
        {
            "name": "letsandcrypt",
            "host": {
                "sourcePath": "/var/letsandcrypt"
            }
        },
        {
            "name": "log",
            "host": {
                "sourcePath": "/var/log/traefik"
            }
        }
    ],
    "placementConstraints": [
        {
            "type": "memberOf",
            "expression": "attribute:role == loadbalancer"
        }
    ],
    "requiresCompatibilities": [
        "EXTERNAL"
    ],
    "cpu": "512",
    "memory": "1024"
}
Enter fullscreen mode Exit fullscreen mode

Da un primo sguardo vediamo subito che si tratta di una normalissima Task Definition il cui compito è deployare l'immagine traefik:latest da docker hub.. niente di più.

Tutto il lavoro di configurazione è fatto dai command e dai dockerLabels .. analizziamo la task definition pezzo pezzo...


Mapping delle porte

Nella prima parte della containerDefinition abbiamo:

 "name": "Proxy",
 "image": "traefik:latest",
 "cpu": 0,
 "memory": 512,
 "portMappings": [
     {
       "containerPort": 80,
       "hostPort": 80,
       "protocol": "tcp"
     },
     {
       "containerPort": 443,
       "hostPort": 443,
       "protocol": "tcp"
     }
],
Enter fullscreen mode Exit fullscreen mode

Dove abbiamo semplicemente definito il nome della Task definition, la memoria e il mapping delle porte.. apriamo semplicemente la 80 e la 443 per l'SSL.

Subito dopo abbiamo la parte dei command, dove inseriamo le direttive di configurazione per il container di traefik proxy; facciamo sempre e in ogni caso riferimento alla documentazione ufficiale di Traefik

Iniziamo con l'abilitare la dashboard di controllo e col disabilitare la porta 80 per l'accesso alla dashboard e alle api di traefik.. faremo tutto sulla 443 con letsandcrypt

  "--api.dashboard=true",
  "--api.insecure=false",
Enter fullscreen mode Exit fullscreen mode

Access log

abilitiamo i log e configuriamo la cartella su cui salvarli:

 "--accesslog=true",
 "--accesslog.filepath=/var/log/traefik/access.log",
Enter fullscreen mode Exit fullscreen mode

ECS Provider

Configuriamo il provider di ECS che permetterà a traefik di sincronizzarsi; in questo esempio specifichiamo un singolo cluster, ma possiamo anche sincronizzare tutto il servizio...

 "--providers.ecs.ecsAnywhere=true",
 "--providers.ecs.region=eu-west-1",
 "--providers.ecs.autoDiscoverClusters=false",
 "--providers.ecs.exposedByDefault=true",
 "--providers.ecs.clusters=Cluster",
Enter fullscreen mode Exit fullscreen mode

Abilitiamo gli entrypoint per l'http e l'https:

  "--entrypoints.web.address=:80",
  "--entrypoints.websecure.address=:443",
Enter fullscreen mode Exit fullscreen mode

Certificati Letsandcrypt

Per la configurazione della 443 dobbiamo settare Letsandcrypt:

"--certificatesresolvers.myresolver.acme.httpchallenge=true",
"--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web",
"--certificatesresolvers.myresolver.acme.email=email@email.it",
"--certificatesresolvers.myresolver.acme.storage=/var/letsandcrypt/acme.json",
Enter fullscreen mode Exit fullscreen mode

E' necessario fare un paio di precisazioni su Letsandcrypt:

  • Per eseguire i test è necessario settare l'endpoint sullo stage

#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"

questo perchè letsandcrypt ha alcuni rate limit sulle registrazioni di nuovi certificati che non è bene superare.. tra le quali un limit settimanale.

  • Inoltre è importante ricordare di storare il file acme.json su un volume "persistente" altrimenti verrà effettuata una nuova richiesta di certificazione ad ogni avvio del task e questo porterà in poco tempo al limite del rate.

Questo è direttamente collegato ai due volumi che trovate montati nella task definition:

"mountPoints": [
      {
          "sourceVolume": "letsandcrypt",
          "containerPath": "/var/letsandcrypt"
      },
      {
          "sourceVolume": "log",
          "containerPath": "/var/log/traefik"
      }
 ],
Enter fullscreen mode Exit fullscreen mode

Il primo è per l'acme.json e l'altro è per i logs.


Docker Labels

I docker labels necessari sono:

"dockerLabels": {
                "traefik.enable": "true",
                "traefik.http.middlewares.traefik-dashboard-auth.basicauth.users": "test:xxxxxxxxxx",
                "traefik.http.routers.api.entrypoints": "websecure",
                "traefik.http.routers.api.middlewares": "traefik-dashboard-auth",
                "traefik.http.routers.api.rule": "Host(`proxy.test.it`)",
                "traefik.http.routers.api.service": "api@internal",
                "traefik.http.routers.api.tls": "true",
                "traefik.http.routers.api.tls.certresolver": "myresolver"
            }
Enter fullscreen mode Exit fullscreen mode

e fondamentalmente hanno il compito di accendere una Basic Auth per accedere alla dashboard e per reindirizzare il traffico delle api sulla 443.


Middleware di Redirect

L'ultima parte ma non meno importante della configurazine è il middleware di redirect per l'http:

"--entrypoints.web.http.redirections.entrypoint.to=websecure",
"--entrypoints.web.http.redirections.entrypoint.scheme=https"
Enter fullscreen mode Exit fullscreen mode

quest'ultimo si occupa di reindirizzare tutte le richieste in arrivo sulla porta 80 direttamente sulla 443.


Creazione della Task Definition per il service

Per quanto riguarda la Task definition per il singolo servizio da eseguire dietro a Traefik Proxy le uniche dockerLabel da configurare sono:

"dockerLabels": {
        "traefik.enable": "true",
        "traefik.http.routers.service-test.entrypoints": "websecure",
        "traefik.http.routers.service-test.rule": "Host(`www.dominio.it`)",
        "traefik.http.routers.service-test.tls.certresolver": "myresolver"
},
Enter fullscreen mode Exit fullscreen mode

Grazie per la lettura!
F.

Top comments (0)