Ansibleでnginxを入れてLoad Balancingさせる

(2019-09-17)

EC2でUbuntu Server 18.04 LTS (ami-07d0cf3af28718ef8) の t3.medium (2vCPU, 4GiB) インスタンスを3台立ち上げた。この内1台をLB用とし、2台のAppサーバーに負荷分散させる。

https://github.com/sambaiz/ansible-nginx-lb-example

nginx.conf

LBとAppのnginx.conf。upstreamはデフォルトでラウンドロビンする。

$ cat conf/lb/nginx.conf
...
http {
  ...

  upstream app-server {
    server ip-172-31-94-208.ec2.internal;
    server ip-172-31-88-90.ec2.internal;
  }

  server {
    listen          80;
    server_name     .compute-1.amazonaws.com;
    access_log      /var/log/nginx/app-server.log main;

    location / {
      proxy_pass      http://app-server;
    }
  }
}

$ cat conf/app/nginx.conf
...
http {
  ...
  server {
    listen       80;
    server_name  .compute-1.amazonaws.com;

    location / {
      proxy_pass  http://127.0.0.1:8080;
    }
  }
}

Ansibleの実行

まずInventoryを書いて疎通確認する。

$ pip install --user ansible
$ cat hosts
[lb]
ec2-3-227-2-54.compute-1.amazonaws.com        ansible_ssh_private_key_file=***.pem        ansible_user=ubuntu

[app]
ec2-3-229-113-100.compute-1.amazonaws.com        ansible_ssh_private_key_file=***.pem     ansible_user=ubuntu
ec2-35-175-201-30.compute-1.amazonaws.com        ansible_ssh_private_key_file=***.pem     ansible_user=ubuntu

$ ansible all -i ./hosts -m ping
ec2-3-227-2-54.compute-1.amazonaws.com | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    }, 
    "changed": false, 
    "ping": "pong"
}
...

Ansible Galaxyからnginx公式のroleを持ってくる。

$ ansible-galaxy install nginxinc.nginx

Playbookはこんな感じ。

---
- hosts: lb
  become: yes
  become_user: root
  roles:
  - role: nginxinc.nginx
    vars:
      nginx_main_upload_enable: true
      nginx_main_upload_src: conf/lb/nginx.conf
      nginx_main_upload_dest: /etc/nginx/
- hosts: app
  become: yes
  become_user: root
  roles:
  - role: nginxinc.nginx
    vars:
      nginx_main_upload_enable: true
      nginx_main_upload_src: conf/app/nginx.conf
      nginx_main_upload_dest: /etc/nginx/
  tasks:
  - name: Copy app
    copy:
      src: main
      dest: /root/app
      owner: root
      group: root
      mode: '700'
  - name: Copy service file
    copy:
      src: conf/app/myapp.service
      dest: /lib/systemd/system/myapp.service
      owner: root
      group: root
      mode: '644'
  - name: restart myapp.service
    systemd:
      name: myapp.service
      state: restarted
      daemon_reload: yes
      enabled: yes

Playbookを実行。

$ ansible-playbook -i ./hosts playbook.yml

$ ansible app -i ./hosts -m shell -a "systemctl status myapp"
ec2-35-175-201-30.compute-1.amazonaws.com | CHANGED | rc=0 >>
● myapp.service - My app service
   Loaded: loaded (/lib/systemd/system/myapp.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2019-09-16 14:45:20 UTC; 18min ago

動作確認

Apache Benchを実行し負荷分散できていることを確認する。

# Single machine
$ ab -n 100 -c 10 http://ec2-3-229-113-100.compute-1.amazonaws.com/
...
Requests per second:    7.67 [#/sec] (mean)
Time per request:       130.409 [ms] (mean, across all concurrent requests)

# Load balanced
$ ab -n 100 -c 10 http://ec2-3-227-2-54.compute-1.amazonaws.com/
...
Requests per second:    11.47 [#/sec] (mean)
Time per request:       87.209 [ms] (mean, across all concurrent requests)

2台のCPU使用率