Skip to main content

Command Palette

Search for a command to run...

Day 10:Voting App with Traefik Ingress Controller

Updated
6 min read
Day 10:Voting App with Traefik Ingress Controller
K

"Hello, I'm Kiran Pawar, a passionate Cloud and Devops Engineer with a strong background in cloud automation, configuration, and deployment. My journey in the world of technology has been a thrilling adventure, where I've had the privilege to work with cutting-edge tools and practices.

🚀 As a DevOps Engineer:

I specialize in automating, configuring, and deploying instances in cloud environments and data centers. My expertise extends to DevOps, GitOps, CI/CD pipeline management, HashiCorp Terraform, and containerization. I'm proficient in AWS and Linux/Unix administration, ensuring robust infrastructure and application performance.

🔧 My Tech Stack:

Front-end skills: HTML, CSS, SCSS, Tailwind CSS, Bootstrap, React, Material-UI, JavaScript DevOps toolbox: GIT, OWASP,Nexus,Trivy, Github, Gitlab, Terraform, Ansible, Docker, Kubernetes, Helm, Jenkins, Prometheus, Grafana, Argo CD, AWS EKS.

🌐 My Cloud Expertise:

I have hands-on experience managing AWS services, including EC2, S3, EBS, VPC, ELB, RDS, IAM, Route53, and more.

🔒 Networking and Security:

My skills include managing networking concepts such as TCP/IP protocols, security policies, and subnet interfacing. I have a strong understanding of infrastructure and networking, covering topics like firewalls, IP addressing, DNS, and more.

💡 What Sets Me Apart:

I bring a positive attitude, a strong work ethic, and a collaborative spirit to every project. I'm a self-starter, a fast learner, and an effective team player with strong interpersonal skills. In addition to my DevOps skills, I've developed shell scripts (Bash) for automating tasks and have proficiency in Python scripting. My ability to communicate and manage projects, along with a track record of resolving client issues, adds value to every team I work with. If you're looking for a DevOps engineer who is also well-versed in front-end technologies, feel free to connect with me. Let's explore new possibilities and create exceptional technical solutions together!"

This repository demonstrates the setup of a voting application using Docker Swarm, Traefik as an Ingress controller, and AWS services like Route 53 and Network Load Balancer (NLB).

Architecture Overview

Architecture Diagram

  1. Route 53: Manages DNS routing for the domain.

  2. Network Load Balancer (NLB): Balances incoming traffic.

  3. Traefik: Acts as an Ingress controller.

    • Handles HTTP to HTTPS redirection.

    • Manages SSL decryption and offloading.

  4. Voting and Result Services:

    • Vote Service: Listens on TCP port 80.

    • Result Service: Listens on TCP port 80.

Setup Instructions

Prerequisites

  • Docker and Docker Swarm installed

  • AWS CLI configured

  • Traefik configured with Docker Swarm

Steps

  1. Deploy Swarm Cluster

  2. Configure Traefik

    Ensure Traefik is configured correctly in traefik.toml or traefik.yml. This setup should handle:

    • HTTP to HTTPS redirection

    • SSL certificate configuration

    • Routing rules for the vote and result services

      ```bash version: '3.3'

      services:

      traefik:

      Use the latest v2.2.x Traefik image available

      image: traefik:v2.9 ports:

      Listen on port 80, default for HTTP, necessary to redirect to HTTPS

      • 80:80

        Listen on port 443, default for HTTPS

      • 443:443 deploy: placement: constraints:

        Make the traefik service run only on the node with this label

        as the node with it has the volume for the certificates

        • node.labels.traefik-public.traefik-public-certificates == true labels:

          Enable Traefik for this service, to make it available in the public network

          • traefik.enable=true

            Use the traefik-public network (declared below)

          • traefik.docker.network=traefik-public

            Use the custom label "traefik.constraint-label=traefik-public"

            This public Traefik will only use services with this label

            That way you can add other internal Traefik instances per stack if needed

          • traefik.constraint-label=traefik-public

            admin-auth middleware with HTTP Basic auth

            Using the environment variables USERNAME and HASHED_PASSWORD

          • traefik.http.middlewares.admin-auth.basicauth.users=${USERNAME?Variable not set}:${HASHED_PASSWORD?Variable not set}

            https-redirect middleware to redirect HTTP to HTTPS

            It can be re-used by other stacks in other Docker Compose files

          • traefik.http.middlewares.https-redirect.redirectscheme.scheme=https
          • traefik.http.middlewares.https-redirect.redirectscheme.permanent=true

            traefik-http set up only to use the middleware to redirect to https

            Uses the environment variable DOMAIN

          • traefik.http.routers.traefik-public-http.rule=Host(${DOMAIN?Variable not set})
          • traefik.http.routers.traefik-public-http.entrypoints=http
          • traefik.http.routers.traefik-public-http.middlewares=https-redirect

            traefik-https the actual router using HTTPS

            Uses the environment variable DOMAIN

          • traefik.http.routers.traefik-public-https.rule=Host(${DOMAIN?Variable not set})
          • traefik.http.routers.traefik-public-https.entrypoints=https
          • traefik.http.routers.traefik-public-https.tls=true

            Use the special Traefik service api@internal with the web UI/Dashboard

          • traefik.http.routers.traefik-public-https.service=api@internal

            Use the "le" (Let's Encrypt) resolver created below

          • traefik.http.routers.traefik-public-https.tls.certresolver=le

            Enable HTTP Basic auth, using the middleware created above

          • traefik.http.routers.traefik-public-https.middlewares=admin-auth

            Define the port inside of the Docker service to use

          • traefik.http.services.traefik-public.loadbalancer.server.port=8080 volumes:

            Add Docker as a mounted volume, so that Traefik can read the labels of other services

      • /var/run/docker.sock:/var/run/docker.sock:ro

        Mount the volume to store the certificates

      • traefik-public-certificates:/certificates command:

        Enable Docker in Traefik, so that it reads labels from Docker services

      • --providers.docker

        Add a constraint to only use services with the label "traefik.constraint-label=traefik-public"

      • --providers.docker.constraints=Label(traefik.constraint-label, traefik-public)

        Do not expose all Docker services, only the ones explicitly exposed

      • --providers.docker.exposedbydefault=false

        Enable Docker Swarm mode

      • --providers.docker.swarmmode

        Create an entrypoint "http" listening on port 80

      • --entrypoints.http.address=:80

        Create an entrypoint "https" listening on port 443

      • --entrypoints.https.address=:443

        Create the certificate resolver "le" for Let's Encrypt, uses the environment variable EMAIL

      • --certificatesresolvers.le.acme.email=${EMAIL?Variable not set}

        Store the Let's Encrypt certificates in the mounted volume

      • --certificatesresolvers.le.acme.storage=/certificates/acme.json

        Use the TLS Challenge for Let's Encrypt

      • --certificatesresolvers.le.acme.tlschallenge=true

        Enable the access log, with HTTP requests

      • --accesslog

        Enable the Traefik log, for configurations and errors

      • --log

        Enable the Dashboard and API

      • --api networks:

        Use the public network created to be shared between Traefik and

        any other service that needs to be publicly available with HTTPS

      • traefik-public

volumes:

Create a volume to store the certificates, there is a constraint to make sure

Traefik is always deployed to the same Docker node with the same volume containing

the HTTPS certificates

traefik-public-certificates:

networks:

Use the previously created public network "traefik-public", shared with other

services that need to be publicly available via this Traefik

traefik-public: external: true


        Follow below commands to deploy :

        ### Steps:

        1. **Create an overlay network**:

            ```css
            docker network create --driver=overlay traefik-public

  • Ensures that services across multiple nodes in the Swarm can communicate.

    1. Label the Swarm node (where Traefik will store certificates):
    export NODE_ID=$(docker info -f '{{.Swarm.NodeID}}')
    docker node update --label-add traefik-public.traefik-public-certificates=true $NODE_ID
    

    1. Set environment variables:
    export EMAIL=kiranpawar3255@gmail.com
    export DOMAIN=traefik.cloudmantra.xyz
    export TRAEFIK_REPLICAS=1
    export USERNAME=adminkiran
    export PASSWORD=India123456
    export HASHED_PASSWORD=$(openssl passwd -apr1 $PASSWORD)
    

  • EMAIL: Used for Let's Encrypt SSL.

  • DOMAIN: Your domain for Traefik.

  • TRAEFIK_REPLICAS: Number of Traefik instances.

  • USERNAME & PASSWORD: Basic authentication for the Traefik dashboard.

  • HASHED_PASSWORD: Generates a secure hash of the password.

    1. Deploy Traefik stack:
    docker stack deploy -c traefik.yml traefik
    

  • Deploys Traefik as a service using traefik.yml.

  1. Set up Route 53 and NLB

    • Configure your Route 53 DNS to point to the NLB

      Create hosted zone with your own domain

      create simple routing record

      copy master public ip

      Add simple routing record

      Create A record in with master node IP in your domain for eg.Godaddy

    • Ensure the NLB forwards traffic to Traefik.

      Create 2 target groups one for TCP 443 and TCP 80

      For TCP-80 target group

    • Choose a target type: instances

      Target group name: TCP-80

      Protocol : Port: TCP-443

      Health checks; TCP

      For TCP-80 target group

    • Create target group for TCP-443

Create Network Load Balancer

Go to Route53

Add two more simple routing records for vote and result respectively

  1. Access the Application

    Open your browser and navigate to your domain to access the voting and result services

    This is our Trafik dashboard

    Deploy voting application

    create file name votingapp.yml:

     version: "3"
     services:
       redis:
         image: redis:alpine
         networks:
           - traefik-public
         deploy:
           replicas: 1
           update_config:
             parallelism: 2
             delay: 10s
           restart_policy:
             condition: on-failure
       db:
         image: postgres:9.4
         environment:
           POSTGRES_USER: "postgres"
           POSTGRES_PASSWORD: "postgres"
         volumes:
           - db-data:/var/lib/postgresql/data
         networks:
           - traefik-public
         deploy:
           resources:
             limits:
               cpus: "0.50"
               memory: 512M
             reservations:
               cpus: "0.25"
               memory: 128M
           placement:
             constraints: [node.role == manager]
       vote:
         image: kiran2361993/testing:latestappvote
         ports:
           - 5000:80
         networks:
           - traefik-public
         depends_on:
           - redis
         deploy:
           replicas: 2
           labels:
             - traefik.enable=true
             - traefik.docker.network=traefik-public
             - traefik.constraint-label=traefik-public
             - traefik.http.middlewares.vote-https-redirect.redirectscheme.scheme=https
             - traefik.http.middlewares.vote-https-redirect.redirectscheme.permanent=true
             - traefik.http.routers.vote-public-http.rule=Host(`vote.cloudvishwakarma.in`) || Host(`www.cloudvishwakarma.in`)
             - traefik.http.routers.vote-public-http.entrypoints=http
             - traefik.http.routers.vote-public-http.middlewares=https-redirect
             - traefik.http.routers.vote-public-https.rule=Host(`vote.cloudvishwakarma.in`) || Host(`www.cloudvishwakarma.in`)
             - traefik.http.routers.vote-public-https.entrypoints=https
             - traefik.http.routers.vote-public-https.tls=true
             - traefik.http.routers.vote-public-https.tls.certresolver=le
             - traefik.http.services.vote-public.loadbalancer.server.port=80
           update_config:
             parallelism: 2
           restart_policy:
             condition: on-failure
       result:
         image: kiran2361993/testing:latestappresults
         ports:
           - 5001:80
         networks:
           - traefik-public
         depends_on:
           - db
         deploy:
           replicas: 1 #Multiple Replicas is causing delay in result.
           labels:
             - traefik.enable=true
             - traefik.docker.network=traefik-public
             - traefik.constraint-label=traefik-public
             - traefik.http.middlewares.result-https-redirect.redirectscheme.scheme=https
             - traefik.http.middlewares.result-https-redirect.redirectscheme.permanent=true
             - traefik.http.routers.result-public-http.rule=Host(`result.cloudvishwakarma.in`)
             - traefik.http.routers.result-public-http.entrypoints=http
             - traefik.http.routers.result-public-http.middlewares=https-redirect
             - traefik.http.routers.result-public-https.rule=Host(`result.cloudvishwakarma.in`)
             - traefik.http.routers.result-public-https.entrypoints=https
             - traefik.http.routers.result-public-https.tls=true
             - traefik.http.routers.result-public-https.tls.certresolver=le
             - traefik.http.services.result-public.loadbalancer.server.port=80
           update_config:
             parallelism: 2
             delay: 10s
           restart_policy:
             condition: on-failure
       worker:
         image: kiran2361993/testing:latestappworker
         networks:
           - traefik-public
         depends_on:
           - db
           - redis
         deploy:
           mode: replicated
           replicas: 1
           labels: [APP=VOTING]
           restart_policy:
             condition: on-failure
             delay: 10s
             max_attempts: 3
             window: 120s
    
     networks:
       traefik-public:
         external: true
    
     volumes:
       db-data:
    

    Deploy voting application stack:

     docker stack deploy -c votingapp.yml votingapp
    

Conclusion

This setup demonstrates how to use Traefik as an Ingress controller with Docker Swarm, Route 53, and NLB to manage a simple voting application. For more details, refer to the accompanying video.


More from this blog

Kiran Pawar's Blog

122 posts