This demo shows NGINX Plus being used in conjuction with etcd, a distributed, consistent key-value store for shared configuration and service discovery. This demo is based on docker and spins' up the following containers:
- etcd for service discovery
- Registrator to register services with etcd. Registrator monitors for containers being started and stopped and updates key-value pairs in etcd when a container changes state.
- nginxdemos/hello as a NGINX webserver that serves a simple page containing its hostname, IP address and port, request URI, local time of the webserver and the client IP address. This is to simulate backend servers NGINX Plus will be load balancing across.
- NGINX Plus (R13 or higher)
The demo is based off the work described in this blog post: Service Discovery for NGINX Plus with etcd
Install Vagrant using the necessary package for your OS:
https://www.vagrantup.com/downloads.html
-
Install provider for vagrant to use to start VM's.
The default provider is VirtualBox (Note that only VirtualBox versions 4.0 and higher are supported), which can be downloaded from the following link:
https://www.virtualbox.org/wiki/Downloads
A full list of providers can be found at the following page, if you do not want to use VirtualBox:
-
Install Ansible:
-
Clone demo repo
$ git clone https://github.com/nginxinc/NGINX-Demos.git
-
Copy
nginx-repo.key
andnginx-repo.crt
files for your account to~/NGINX-Demos/etcd-demo/nginxplus
-
Move into the etcd-demo directory and start the Vagrant vm:
$ cd ~/NGINX-Demos/etcd-demo $ vagrant up
The
vagrant up
command will start the virtualbox VM and provision it using the ansible playbook file~/NGINX-Demos/etcd-demo/setup_etcd_demo.yml
. The ansible playbook file also invokes another script provision.sh which sets the HOST_IP environment variable to the IP address of the eth1 interface (10.2.2.70 in this case assigned in the Vagrantfile) and invokes thedocker-compose up -d
command -
SSH into the newly created virtual machine and move into the /vagrant directory which contains the demo files:
$ vagrant ssh $ sudo su
The demo files will be in
/srv/NGINX-Demos/etcd-demo
-
Now simply follow the steps listed under section 'Running the demo'.
-
Create Ubuntu 18.04 LTS VM
-
Install Ansible on Ubuntu VM
$ sudo apt-get install ansible
-
Clone demo repo into
/srv
on Ubuntu VM:$ cd /srv $ sudo git clone https://github.com/nginxinc/NGINX-Demos.git
-
Copy
nginx-repo.key
andnginx-repo.crt
files for your account to/srv/NGINX-Demos/etcd-demo/nginxplus
-
Move into the etcd-demo directory which contains the demo files and set HOST_IP on line 5 in script.sh to the IP of your Ubuntu VM on which NGINX Plus will be listening.
$ cd /srv/NGINX-Demos/etcd-demo
-
Run the ansible playbook against localhost on Ubuntu VM:
$ sudo ansible-playbook -i "localhost," -c local /srv/NGINX-Demos/etcd-demo/setup_etcd_demo.yml
-
Now simply follow the steps listed under section 'Running the demo'.
The following software needs to be installed:
- Docker for Mac if you are running this locally on your MAC OR docker-compose if you are running this on a linux VM
- jq, I used brew to install it:
brew install jq
- etcd & etcdctl, a command line client for etcd. Follow the steps under 'Getting etcd' section and and copy over etcdctl executable under /usr/local/bin and make sure this path is present in $PATH variable
As the demo uses NGINX Plus a nginx-repo.crt
and nginx-repo.key
needs to be copied into the nginxplus/
directory
-
Clone demo repo
$ git clone https://github.com/nginxinc/NGINX-Demos.git
-
Copy
nginx-repo.key
andnginx-repo.crt
files for your account to~/NGINX-Demos/etcd-demo/nginxplus/
-
Move into the demo directory:
$ cd ~/NGINX-Demos/etcd-demo
-
If you have run this demo previously or have any docker containers running, start with a clean slate by running
$ ./clean-containers.sh
-
NGINX Plus will be listening on port 80 on docker host
- If you are using Docker Toolbox, you can get the IP address of your docker-machine (default here) by running
$ docker-machine ip default 192.168.99.100
- If you are using Docker for Mac, the IP address you need to use is 127.0.0.1
Export this IP into an environment variable named HOST_IP by running
export HOST_IP=x.x.x.x
command. This variable is used by docker-compose.yml file -
Spin up the etcd, Registrator and NGINX Plus containers first:
$ docker-compose up -d
-
Execute the etcd_exec_watch.sh script in background (This invokes an etcdctl exec-watch command watching for changes in etcd keys and trigger script.sh whenever a change is detected).
$ ./etcd_exec_watch.sh &
-
Spin up the nginxdemos/hello container which is the backend http service
$ docker-compose -f create-http-service.yml up -d
-
Now follow the steps under section 'Running the demo'
-
You should have a bunch of containers up and running now:
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9fe2155fb33f nginxdemos/hello:latest "nginx -g 'daemon off" 5 seconds ago Up 4 seconds 443/tcp, 0.0.0.0:32779->80/tcp etcddemo_http_1 20ae0c91237c gliderlabs/registrator:latest "/bin/registrator etc" 26 seconds ago Up 25 seconds registrator 82f6a35d5212 etcddemo_nginxplus "nginx -g 'daemon off" 26 seconds ago Up 25 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:8080->8080/tcp, 443/tcp nginxplus 9fd1ab126773 quay.io/coreos/etcd:v2.0.8 "/etcd -name etcd0 -a" 26 seconds ago Up 25 seconds 0.0.0.0:2379-2380->2379-2380/tcp, 0.0.0.0:4001->4001/tcp, 7001/tcp etcd
-
If you followed the Fully automated Vagrant/Ansible setup option above, HOST_IP referred below is the IP assigned to your Vagrant VM (i.e 10.2.2.70 in Vagrantfile) and is set already. And if you followed the Ansible only deployment option, HOST_IP will be the IP of your Ubuntu VM on which NGINX Plus is listening (IP of the interface set on line 6 of provision.sh, set to eth1 by default). For the manual install option, HOST_IP was already set above to
docker-machine ip default
OR 127.0.0.1 in case of Docker for Mac -
Go to
http://<HOST_IP>
in your favorite browser window and that will take you to one of the nginx-hello containers printing its hostname, IP Address and the port of the container.http://<HOST_IP>:8080/
will bring up the NGINX Plus dashboard. The configuration file NGINX Plus is using here is /etc/nginx/conf.d/app.conf which is included from /etc/nginx/nginx.conf. If you would like to see all the services registered with etcd you could do acurl http://$HOST_IP:4001/v2/keys | jq '.'
. We are also using the persistent on-the-fly reconfiguration introduced in NGINX Plus R8 using the state directive. This means that NGINX Plus will save the upstream conf across reloads by writing it to a file on disk. -
Now scale up and scale down the http service using the commands below. Go to the Upstreams tab on Nginx Plus dashboard and observe the change in the list of servers being added/removed from the backend group accordingly.
$ docker-compose -f create-http-service.yml up -d --scale http=5 $ docker-compose -f create-http-service.yml up -d --scale http=3
-
The way this works is everytime there is a change in etcd, script.sh gets triggered (through etcd_exec_watch.sh) which checks for some of the environment variables set by etcd and adds the server specified by ETCD_WATCH_VALUE to the NGINX upstream block if ETCD_WATCH_ACTION is 'set' and removes it if ETCD_WATCH_ACTION is 'delete'. The removal happens by traversing through all NGINX Plus upstreams and removing the ones not present in etcd.
All the changes should be automatically reflected in the NGINX config and show up on the NGINX Plus Dashboard.