Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save MdSahil-oss/ae193efdde63c5fcded8be0730cfe648 to your computer and use it in GitHub Desktop.
Save MdSahil-oss/ae193efdde63c5fcded8be0730cfe648 to your computer and use it in GitHub Desktop.
Setting up Service Discovery Using Nginx & Consul

Service Discovery Using Nginx & Consul

consul-project

Used Technologies

  • AWS
  • Consul
  • Terraform
  • Ansible
  • Nginx

Description

In this project I configured Consul as Service Discovery tool that enables my frontend of web application to communicate with backend servers regardless of their IP addresses.

So In this project My frontend application connects with a load-balancer to obtain data that fetches the current IP addresses of backend servers from the consul-server with the help of consul-template tool And IP addresses in Consul-server will be kept updating by backend servers themselves with the help of consul-agent (Self Registering Property) running on them.

How did I build this project ?

  • Deployed frontend of my web application on a AWS ec2 instance (Ubuntu 20.04 OS) and started at port 80 with the help of Nginx.

  • Started 5 other ec2 instances in my AWS VPC using Terraform, Where three to work as backend servers and one for load-balancer and other one for consul-server.

  • Then, I started setting up all the servers using a ansible playbook by following steps:

    • Installed nginx on backend and loadbalancer servers:

      - name: Installs nginx on backend and loadbalancer servers
        hosts:
         - backends
         - loadbalancer
        tasks:
          - name: updating package manager
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: sudo apt-get update -y
          - name: installing nginx
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: sudo apt install nginx -y
    • Deployed my backend of application to all (three) backend servers and set nginx on them to listen every request:

    • Then, Installed consul on backend and consul-server servers:

      - name: Installs consul on backend and consul-server servers
        hosts:
         - backends
         - consulserver
        tasks:
          - name: Updating package manager
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: sudo apt-get update -y
          - name: Fetching gpg key for consul
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
          - name: Signing key
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
          - name: Updating & Installing
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: sudo apt update && sudo apt install consul
    • Set up consul on consulserver:

      - name: Sets up consul on consulserver
        hosts:
         - consulserver
        tasks:
          - name: Swaping /etc/consul.d/consul.hcl & creating new consul.hcl with configuration
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: cat > /home/vagrant/consul.hcl && sudo rm -f /etc/consul.d/consul.hcl && sudo mv /home/vagrant/consul.hcl /etc/consul.d/
              stdin: "\"bind_addr\" = \"CONSUL_SERVER_IP\"\n
      \"client_addr\" = \"CONSUL_SERVER_IP\"\n
      \"data_dir\" = \"/var/consul\"\n
      \"encrypt\" = \"ZENZNrsXU336Uma+S4XUj9sxvICj32N7XdEzrbYbRpY=\"\n
      \"datacenter\" = \"dc1\"\n
      \"ui\" = true\n
      \"server\" = true\n
      \"log_level\" = \"INFO\""
    • Set up Consul on each backend server:

      - name: Sets up consul on each backend
        hosts:
         - backend1
         - backend2
         - backend3
        tasks:
          - name: Swaping /etc/consul.d/consul.hcl & creating new consul.hcl with configuration
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: cat > /home/vagrant/consul.hcl && sudo rm -f /etc/consul.d/consul.hcl && sudo mv /home/vagrant/consul.hcl /etc/consul.d/
              stdin: "\"bind_addr\" = \"SERVER_IP\"\n
      \"server\" = false\n
      \"datacenter\" = \"dc1\"\n
      \"data_dir\" = \"/var/consul\"\n
      \"encrypt\" = \"ZENZNrsXU336Uma+S4XUj9sxvICj32N7XdEzrbYbRpY=\"\n
      \"log_level\" = \"INFO\"\n
      \"enable_script_checks\" = true\n
      \"enable_syslog\" = true\n
      \"leave_on_terminate\" = true\n
      \"start_join\" = [\"CONSUL_SERVER_IP\"]\n
      \"node_name\" = \"backend-$BACKEND_NUM\""
          - name: Creates service for consul each backend server
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: sudo cat > backend.hcl && sudo mv backend.hcl /etc/consul.d/backend.hcl
              stdin: "\"service\" = {\n
      \t\"Name\" = \"backend\"\n
      \t\"Port\" = 80\n
      \t\"check\" = {\n
      \t\t\"args\" = [\"curl\", \"localhost\"]\n
      \t\t\"interval\" = \"3s\"\n
      \t}\n
      }"
    • Then, Installed consul-template on loadbalancer & configured:

      - name: Installs consul-template on loadbalancer
        hosts:
         - loadbalancer
        tasks:
          - name: installing unzip tool
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: sudo apt-get install unzip -y
          - name: installing consul-template
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: sudo curl -L  https://releases.hashicorp.com/consul-template/0.30.0/consul-template_0.30.0_linux_amd64.zip -o /opt/consul-template.zip && sudo unzip /opt/consul-template.zip -d  /usr/local/bin/
          - name: Setting up load-balancer.conf.ctmpl
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: sudo cat > /etc/nginx/conf.d/load-balancer.conf.ctmpl
              stdin: "upstream backend {\n
      # \t {{- range service \"backend\" }} \n
      # \t\t  server {{ .Address }}:{{ .Port }}; \n
      # \t {{- end }} \n
      # }\n
      # \n
      # server {\n
      # \tlisten 80;\n
      # \n
      # \t location / {\n
      # \t\t  proxy_pass http://backend;\n
      # \t}\n
      # }"
          - name: Sets up consul-template
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: cat > /home/vagrant/consul-template.hcl && sudo mv /home/vagrant/consul-template.hcl /etc/nginx/conf.d/
              stdin: "consul {\n
      \t address = \"CONSUL_SERVER_IP:8500\"\n
      \n
      \t retry {\n
      \t\t   enabled  = true\n
      \t\t   attempts = 12\n
      \t\t   backoff  = \"250ms\"\n
      \t }\n
      }\n
      template {\n
      \t source      = \"/etc/nginx/conf.d/load-balancer.conf.ctmpl\"\n
      \t destination = \"/etc/nginx/conf.d/load-balancer.conf\"\n
      \t perms       = 0600\n
      \t command = \"service nginx reload\"\n
      }"
          - name: Removing default nginx configuration on loadbalancer
            ansible.builtin.shell:
            args:
              chdir: /home/vagrant/
              cmd: sudo rm /etc/nginx/sites-enabled/default && sudo systemctl restart nginx
  • Then, started Consul agent on all the servers one by one as follows:

    • First, started on consul-server agent:
      sudo consul agent -config-dir /etc/consul.d/ &
    • Then Started consul-agent on all the backend servers:
      sudo consul agent -config-dir /etc/consul.d/ &
    • Then Started on Load-balancer consul-agent:
      sudo consul-template -config=/etc/nginx/conf.d/consul-template.hcl &

That's it, After all the configuration my frontend application was able to communicate with backend servers to obtain data regardless of their IP addresses and Consul Server was working as a meadium that was helping frontend to connecting with backend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment