Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Session: A Reference Architecture for Running Modern APIs with NGINX Unit and NGINX Web Server

160 views

Published on

Building and deploying cloud native APIs is a complex operation, and can require a multitude of components. In this workshop we focus on the fundamentals of deploying the runtime API code and publishing the API through an API gateway. To achieve this we use NGINX Unit as a polyglot application server and NGINX web server as an API gateway. With this combination we deliver a solution lightweight enough for dev and strong enough for production.

You will learn how to use NGINX Unit to run one or more apps and APIs in a variety of languages, including seamlessly deploying new versions. You will then see the best practices for how to configure NGINX to perform the common API gateway functions of request routing, rate limiting, and authentication for multiple APIs. We will also touch on advanced use cases such as HTTP method enforcement, and JSON validation.

No previous experience of NGINX or NGINX Unit is required, but a basic knowledge of HTTP and JSON/REST APIs is valuable.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Session: A Reference Architecture for Running Modern APIs with NGINX Unit and NGINX Web Server

  1. 1. NGINX Workshop Running Modern APIs with NGINX Unit and NGINX web server All Things Open 19-Oct-2020
  2. 2. Today’s hosts Timo Stark 🇩🇪 • Product Management Engineer, NGINX • @linux_lenny Liam Crilly 🇬🇧 • Senior Director, Product Management, NGINX • @liamcrilly
  3. 3. What we’re going to build API Client Internet / WAN API Gateway Backend APIs
  4. 4. Agenda 1. Introducing NGINX 2. Running APIs with NGINX Unit 3. Q&A 4. Break (15 mins) 5. Deploying NGINX web server as an API gateway 6. Q&A
  5. 5. 5 “... when I started NGINX, I focused on a very specific problem – how to handle more customers per a single server.” - Igor Sysoev, NGINX creator and founder
  6. 6. Introducing NGINX 6 2004 • NGINX 0.1 2007 • “Viable” 2011 • NGINX, Inc. • NGINX 1.0 2013 • NGINX Plus R1 2018 • NGINX Unit 1.0 • Controller 1.0 2019 • Controller 2.0 (API mgmt.) • NGINX Plus R19 • Acquired by F5 Networks
  7. 7. Agenda 1. Introducing NGINX 2. Running APIs with NGINX Unit 3. Break / Q&A 4. Deploying NGINX web server as an API gateway 5. Q&A
  8. 8. What we’re going to build API Client Internet / WAN API Gateway Backend APIs
  9. 9. What is NGINX Unit 10 “NGINX Unit is a polyglot app server, a reverse proxy, and a static file server, available for Unix-like systems”
  10. 10. NGINX Unit 11 Flexible Performance Security 8 Supported App Languages
  11. 11. NGINX Unit Architecture Unit enables NGINX Unit Architecture
  12. 12. 16
  13. 13. Process overview 17
  14. 14. Installing NGINX Unit (simple) 18 CentOS / RHEL(*) • yum install unit unit-go unit- devel unit-php Ubuntu / Debian(*) • apt-get install unit unit-dev unit-go unit-php Docker • docker pull nginx/unit:1.20.0- full MacOS / MacBook • Docker
  15. 15. Unit configuration 19 curl –s --unix-socket /var/run/control.unit.sock localhost 1 2 3 4 5 6 7 8 { "certificates": { ... }, "config": { ... } } TLS Certificates for the listeners General configuration object
  16. 16. Unit config 20 curl –s --unix-socket /var/run/control.unit.sock localhost/config 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 20 22 "settings": { "http": { ... } }, "listeners": { ... }, "routes": [ { ... }, ], "applications": { ... }, "upstreams": { ... }, "access_log": "/var/log/access.log" } Instace wide settings Bind ip addr and port Control the unit- router Our applications Proxy upstreams access-logs
  17. 17. Unit routes 1 21 curl –s --unix-socket /var/run/control.unit.sock localhost/config/routes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 20 22 "django": [ { "match": { "uri": "/static/*" }, "action": { "share": "/var/apphome/python/" } }, { "action": { "pass": "applications/django_project" } } ], name Routing pattern definition Action if pattern matches
  18. 18. Unit routes 2 22 curl –s --unix-socket /var/run/control.unit.sock localhost/config/routes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 20 22 23 "wordpress": [ { "match": { "uri": [ "*.php", "*.php/*", "/wp-admin/" ] }, "action": { "pass": "applications/wordpress/direct" } }, { "action": { "share": "/var/apphome/wordpress", "fallback": { "pass": "applications/wordpress/index" } } } ] name Routing pattern definition Action if pattern matches Fallback action with static file share
  19. 19. $ curl –-unix-socket /var/run/unit.control.sock –-data-binary "@.unit.conf.json" http://localhost/config $ curl –-unix-socket /var/run/unit.control.sock –-data-binary "UpdatedSecret" http://localhost/config/applications/app/environment/APISEC
  20. 20. Unit in docker 24 • Use the nginx/unit base images • Make use of the /docker-entrypoint-d features ◦ Apply initial configurtion ◦ Apply initial uploding of certificates for TLS encryption ◦ Run Shell-scripts
  21. 21. What we have now Developers Machine Backend APIs AWS EC2 AWS Container Registry push pull API Gateway
  22. 22. Agenda 1. Introducing NGINX 2. Running APIs with NGINX Unit 3. Break / Q&A 4. Deploying NGINX web server as an API gateway 5. Q&A
  23. 23. Agenda 1. Introducing NGINX 2. Running APIs with NGINX Unit 3. Break / Q&A 4. Deploying NGINX web server as an API gateway 5. Q&A
  24. 24. What we’re going to build API Client Internet / WAN API Gateway Backend APIs
  25. 25. #1 40%“Most websites use NGINX” of NGINX deployments are as an API gateway Source: NGINX User survey 2017, 2018, 2019Source: Netcraft April 2019 Web Server Survey
  26. 26. Installing NGINX (official) 30 http://nginx.org/en/linux_packages.html • RHEL/Centos • Debian • Ubuntu • SLES • Alpine
  27. 27. Installing NGINX (simple) 31 CentOS / RHEL • yum install nginx Ubuntu / Debian • apt-get install nginx Docker • docker pull nginx MacOS / MacBook • Homebrew • Docker
  28. 28. NGINX Open Source Cycle Stable retired Mainline forked Mainline “bump” New stable Critical bugfix Stable 1.even.0 Mainline 1.odd.0 April • Mainline • New features • 8-12 releases per year • Stable • Critical bug fixes only • 1-2 releases per year
  29. 29. Define our API gateway 33 • Create api_gateway.conf • $ mkdir /etc/nginx/conf.d/my_apis • $ nginx -s reload • $ curl localhost:8080 /etc/nginx/conf.d/api_gateway.conf 1 2 3 4 5 6 7 8 9 10 11 12 server { listen 8080; # TLS config goes here (for production) include conf.d/my_apis/*.conf; # Invalid resource location / { return 400; } }
  30. 30. $ curl http://localhost:8080/ <html> <head><title>400 Bad Request</title></head> <body> <center><h1>400 Bad Request</h1></center> <hr><center>nginx/1.15.10</center> </body> </html>
  31. 31. Define JSON error responses 36 /etc/nginx/conf.d/api_gateway.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 server { listen 8080; # TLS config goes here (for production use) include conf.d/my_apis/*.conf; # Invalid resource location / { return 400; } # Error responses default_type application/json; error_page 400 = @400; location @400 { return 400 '{"status":400,"message":"Bad request"}n'; } } • error_page to named location (@) • Download full error set ◦ github.com/lcrilly/ nginx-api-gateway
  32. 32. Enable TLS 37 /etc/nginx/conf.d/api_gateway.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 server { listen 8080; # TLS config goes here (for production use) listen 443 ssl; ssl_certificate /etc/nginx/ssl/space.nginx.org.crt; ssl_certificate_key /etc/nginx/ssl/space.nginx.org.key; include conf.d/my_apis/*.conf; # Invalid resource location / { return 400; } • Can listen on plaintext and SSL/TLS ports simulateously ◦ But don’t!
  33. 33. 🪐 Publish the Space API API Client Internet / WAN API Gateway Space API
  34. 34. Microservices routing Events microservice Images microservice /api/space/planets/* /api/space/events/* /api/planets/images/* Planets microservice
  35. 35. Define the backend servers 41 • Upstream servers (backends) • Multiple servers will be load balanced • Next step is to define the API itself /etc/nginx/conf.d/api_backends.conf 1 2 3 4 5 6 7 8 9 10 11 upstream planets-svc { server 172.31.46.145:8080; } upstream events-svc { server 172.31.46.145:8085; } upstream images-svc { server 172.31.46.145:8090; }
  36. 36. Define the API 42 • Nested locations • Location (URI) matching ◦ Exact (=) ◦ Regex (~) ◦ Prefix ( ) • Policies can apply at any level /etc/nginx/conf.d/my_apis/space.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 location /api/space/ { location = /api/space/planets { proxy_pass http://planets-svc; } location /api/space/planets/ { proxy_pass http://planets-svc; } location ~ ^/api/space/images/.+.(svg|png)$ { proxy_pass http://images-svc; } location /api/space/events { proxy_pass http://events-svc; } }
  37. 37. Rate limiting 44 /etc/nginx/conf.d/api_gateway.conf 1 2 3 4 limit_req_zone $remote_addr zone=perip:1m rate=2r/s; server { listen 8080; • Rate limit is configured and monitored at a global level • Limit is applied where we want it ◦ Per API gateway ◦ Per API definition  ◦ Per URI/route /etc/nginx/conf.d/my_apis/space.conf 1 2 3 4 5 6 7 8 9 10 location /api/space/ { limit_req zone=perip nodelay; _ limit_req_status 429; _ location = /api/space/planets { proxy_pass http://planets-svc; } location /api/space/planets/ { proxy_pass http://planets-svc; }
  38. 38. NGINX authentication options 46 API Gateway HTTP Basic Client Cert JWT • NGINX Plus API Key Custom Token • External API
  39. 39. HTTP Basic authentication 47 • Other auth options replace auth_basic directives ◦ auth_jwt (JWT) ◦ auth_request ( API key) ◦ auth_request (custom) • Exception is client certs at server level ◦ ssl_client_certificate /etc/nginx/conf.d/my_apis/space.conf 1 2 3 4 5 6 7 8 9 10 location /api/space/ { auth_basic "Space API"; __ auth_basic_user_file conf.d/api_clients.htpasswd; _ limit_req zone=perip; limit_req_status 429; location = /api/space/planets { proxy_pass http://planets-svc; } $ cd /etc/nginx/conf.d $ wget http://files.liamcrilly.com/api_clients.htpasswd
  40. 40. API key authentication (example) 48 • Requests must pass auth_request test • Internal location performs API key validation logic ◦ Returns validation status back to auth_request • Keys can be SHA-256 protected with njs /etc/nginx/conf.d/my_apis/space.conf 1 2 … 16 17 18 19 20 21 22 23 24 25 26 27 28 29 location /api/space/ { auth_request /_validate_apikey; … } location = /_validate_apikey { internal; if ($http_apikey = "") { return 401; # Unauthorized } if ($api_client_name = "") { return 403; # Forbidden } return 204; # OK (no content) } /etc/nginx/conf.d/apikey_clients.conf 1 2 3 4 5 map $http_apikey $api_client_name { default ""; "7B5zIqmRGXmrJTFmKa99vcit" "client_one"; "QzVV6y1EmQFbbxOfRCwyJs35" "client_two"; }
  41. 41. HTTP method matching 50 • limit_except directive controls HTTP methods • Disable authentication for easier testing /etc/nginx/conf.d/my_apis/space.conf 1 2 3 4 5 6 7 8 9 10 … 19 20 21 22 23 location /api/space/ { auth_basic "Space API"; auth_basic_user_file conf.d/api_clients.htpasswd; limit_req zone=perip; limit_req_status 429; location = /api/space/planets { proxy_pass http://planets-svc; } location /api/space/events { limit_except GET POST { deny all; } _ proxy_pass http://events-svc; } }
  42. 42. JSON request validation [1/2] 52 • Load JavaScript module ◦ nginx-module-njs • Use JSON.parse() to test request body for valid JSON /etc/nginx/nginx.conf 1 2 3 4 5 6 7 8 9 10 11 user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid; load_module modules/ngx_http_js_module.so; _ events { worker_connections 1024; } /etc/nginx/conf.d/json_validation.js 1 2 3 4 5 6 7 8 9 10 11 12 13 export default { parseRequestBody }; function parseRequestBody(r) { try { if (r.variables.request_body) { JSON.parse(r.variables.request_body); } return r.variables.upstream; } catch (e) { r.error('JSON.parse exception'); return '127.0.0.1:10415'; // Address for error response } }
  43. 43. JSON request validation [2/2] 53 • NGINX hates to buffer • Use mirror module to force early-reading of $request_body • Variable evaluation controls timing of JS code execution /etc/nginx/conf.d/api_gateway.conf 10 11 12 13 14 # Request body validation location /_get_request_body { internal; return 204; } /etc/nginx/conf.d/json_validation.conf 1 2 3 4 5 6 7 8 js_import conf.d/json_validation.js; js_set $json_validated json_validation.parseRequestBody; server { listen 127.0.0.1:10415; # This is the error response of json_validator() return 415; # Unsupported media type include conf.d/my_apis/errors_json.conf; } /etc/nginx/conf.d/my_apis/space.conf 8 9 10 11 12 13 location = /api/space/events { limit_except GET POST { deny all; } set $upstream events-svc; mirror /_get_request_body; # Force early-reading of request body proxy_pass http://$json_validated$request_uri; }
  44. 44. How did we do? • Error handling • API definition • Rate limiting • Authentication • HTTP methods • JSON validation
  45. 45. Agenda 1. Introducing NGINX 2. Running APIs with NGINX Unit 3. Break / Q&A 4. Deploying NGINX web server as an API gateway 5. Q&A
  46. 46. Resources • NGINX Unit ◦ https://unit.nginx.org/ • Official NGINX open source downloads ◦ http://nginx.org/en/linux_packages.html • Configuration files and code samples ◦ https://github.com/nginx/unit-examples ◦ https://github.com/lcrilly/nginx-api-gateway • NGINX Plus developer license ◦ https://www.nginx.com/developer-license/ ◦ Code: ato2020workshop
  47. 47. fin

×