สร้าง API Gateway และระบบ Monitoring Microservice ด้วย Kong, Prometheus และ Grafana แบบง่ายๆ
บทความโดย ผศ.ดร.ณัฐโชติ พรหมฤทธิ์
ภาควิชาคอมพิวเตอร์
คณะวิทยาศาสตร์
มหาวิทยาลัยศิลปากร
บทความนี้เราจะสร้าง API Gateway และระบบ Monitoring งานทะเบียนนักศึกษาซึ่งถูกพัฒนาแบบ Microservice Architecture
สำหรับผู้อ่านใหม่ที่ต้องการจะ Implement ตาม สามารถอ่านบทความ 2 บทความก่อนหน้านี้ ได้แก่
- วิธีติดตั้ง VPS และ Let’s Encrypt ด้วย Docker Container แบบง่ายๆ
- การพัฒนา Microservice บน Docker Container สำหรับผู้เริ่มต้น
Kong API Gateway
API Gateway เป็นจุดศูนย์รวมของการควบคุมการเข้าถึง Internal API ที่เราเปิด Public ให้ผู้ใช้ภายนอกเรียกใช้งาน ทำให้เราสามารถทำงานต่าง ๆ อย่างเช่น การทำ Authentication เพื่อยืนยันตัวตนก่อนเข้าใช้ Service การทำ Rate Limiting เพื่อควบคุม Traffic ได้ว่าใน 1 วินาที/นาที/ชั่วโมง/วัน จะมี Request ได้กี่ครั้ง หรือการทำ Monitoring Service ร่วมกับ Prometheus เป็นต้น
Kong เป็น API Gateway แบบ Open source ตัวหนึ่งที่ได้รับความนิยม โดยเฉพาะการนำมาใช้กับ Software แบบ Microservice Architecture
โดยเราสามารถตั้งค่า Kong ใน 4 ส่วนหลักๆ ได้แก่
Service คือ Service ปลายทางที่ต้องการให้ Kong ส่งต่อ Request ไปหา
Route คือ Path ที่ Client เรียกมาหา Kong โดยที่ Route จะต้องผูกกับ Service
Consumer คือ ผู้ที่จะเรียกใช้ Kong
Plugin คือ ตัวที่ทำให้ Kong สามารถทำ Authentication, Rate Limiting หรือ Monitoring Service ฯลฯ ได้
ซึ่ง Kong กำหนด Default Port ในการรับ-ส่งข้อมูลไว้ดังนี้
8000 สำหรับ HTTP Request ที่จะถูกส่งต่อไปยัง Service ตามที่กำหนด
8443 สำหรับ HTTPS Request ที่จะถูกส่งต่อไปยัง Service ตามที่กำหนด
8001 สำหรับการตั้งค่า Kong ผ่าน HTTP Request
8444 สำหรับการตั้งค่า Kong ผ่าน HTTPS Request
Kong เองนั้นสามารถตั้งค่าผ่านทาง Port 8001 หรือ 8444 ด้วยการเรียกใช้ RESTful Administration API โดยตรง แต่เพื่อความสะดวก เราจะตั้งค่าผ่าน Kong Admin GUI ที่ชื่อว่า Konga ผ่าน URL ด้านล่าง
https://konga.labxx.cpsudevops.com
และกำหนด URL สำหรับ HTTPS Request ที่จะถูกส่งต่อไปยัง Register Gateway Service คือ
https://service.labxx.cpsudevops.com/register/
นอกจากนี้เราจะ Config PostgreSQL เป็น Database สำหรับ Kong และ Konga รวมทั้ง Config Node-exporter สำหรับดึงค่าต่างๆ จากตัว Hardware เช่น CPU, Memory และ HDD ฯลฯ เพื่อส่งข้อมูลไปยัง Prometheus
โดยเราจะ Config Kong, Konga, Prometheus และ Node-exporter ผ่าน Docker-compose ตามขั้นตอนต่อไปนี้
- Remote Login ไปยัง Cloud Server โดยใช้ ssh
ssh [email protected]
- สร้าง Project ชื่อ kong_dock ซึ่งภายใน Folder จะประกอบด้วยไฟล์ docker-compose.yml และ prometheus.yml
.
|__ docker-compose.yml
|__ prometheus.yml
- แก้ไขไฟล์ docker-compose.yml ตามตัวอย่างด้านล่าง
version: '2'
services:
kong:
image: kong:2.0.2-alpine
container_name: kong
depends_on:
- kong_db
- kong_migration
expose:
- "8001"
- "8444"
- "8000"
- "8443"
restart: always
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: kong_db
KONG_PG_PORT: 5432
KONG_PG_DATABASE: kong
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_PROXY_LISTEN: 0.0.0.0:8000, 0.0.0.0:8443 ssl
KONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl
KONG_PLUGINS: basic-auth, key-auth, rate-limiting, prometheus, proxy-cache, oauth2
VIRTUAL_HOST: service.labxx.cpsudevops.com
VIRTUAL_PORT: 8000
LETSENCRYPT_HOST: service.labxx.cpsudevops.com
networks:
- webproxy
- default
kong_db:
image: postgres:9.6
container_name: kong_db
volumes:
- kong_datastore:/var/lib/postgresql/data
restart: always
environment:
POSTGRES_DB: kong
POSTGRES_USER: kong
POSTGRES_HOST_AUTH_METHOD: trust
kong_migration:
image: kong:latest
container_name: kong_migration
command: "kong migrations bootstrap"
restart: on-failure
environment:
KONG_PG_HOST: kong_db
depends_on:
- kong_db
konga:
container_name: konga
image: pantsel/konga
restart: always
environment:
DB_ADAPTER: postgres
DB_HOST: konga_db
DB_USER: konga
DB_DATABASE: konga
NODE_ENV: development
VIRTUAL_HOST: konga.labxx.cpsudevops.com
VIRTUAL_PORT: 1337
LETSENCRYPT_HOST: konga.labxx.cpsudevops.com
expose:
- "1337"
networks:
- webproxy
- default
konga_db:
image: postgres:9.6
container_name: konga_db
volumes:
- konga_database:/var/lib/postgresql/data
restart: always
environment:
POSTGRES_DB: konga
POSTGRES_USER: konga
POSTGRES_HOST_AUTH_METHOD: trust
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/promtheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
expose:
- "9090"
restart: always
node_exporter:
image: prom/node-exporter:latest
container_name: node_exporter
expose:
- "9100"
restart: always
volumes:
kong_datastore:
konga_database:
prometheus_data:
networks:
webproxy:
external:
name: webproxy
default:
external:
name: kong_network
- แก้ไขไฟล์ prometheus.yml
global:
external_labels:
monitor: devops_monitor
scrape_interval: 5s
scrape_configs:
- job_name: prometheus
static_configs:
- targets:
- "localhost:9090"
- job_name: node_exporter
static_configs:
- targets:
- "node_exporter:9100"
- job_name: kong
static_configs:
- targets:
- "kong:8001"
- สร้าง Bridge network โดยตั้งชื่อเป็น kong_network
docker network create kong_network
- รัน Container ด้วย docker-compose และกลับไปที่ Terminal โดยใช้ parameter -d
docker-compose up -d
- ดู Container ของ kong_dock ที่กำลังรันทั้งหมด ตามที่ docker-compose.yml ดูแล ด้วย Command line
docker-compose ps
- ดู Container ของ kong_dock ที่กำลังรันทั้งหมด ด้วย Portainer
- Config Kong ผ่าน Konga จาก URL https://konga.labxx.cpsudevops.com
- กรอกข้อมูลเพื่อสร้าง Admin Account แล้วกด Create Admin
- Login
- Connect ไปยัง Kong โดยกำหนดค่า Kong Admin URL เป็น http://kong:8001 แล้วกด CREATE CONNECTION
- สร้าง Service โดยกดที่เมนู SERVICES แล้วกด ADD NEW SERVICE
- ใส่ชื่อ Service, Protocol, Host (Private IP Address บน Cloud Server), Port และ Path แล้วกด SUBMIT SERVICE
- สร้าง Route โดยกดที่ RegisterGateway แล้วกดที่แถบ Routes
- กด ADD ROUTE ใส่ชื่อ Route Name ใส่ข้อมูล Paths, Methods และ Protocols โดยกด Enter ทุกครั้ง แล้วกด SUBMIT ROUTE
- ลองกดส่ง Request ใน Postman ไปยัง https://service.labxx.cpsudevops.com/register/ แบบ JSON
{
"firstname": "Nuttachot",
"lastname": "Promrit",
"email": "[email protected]"
}
- ดู Email ใน Inbox
หมายเหตุ เพื่อไม่ให้ Client สามารถส่ง Request ด้วยการ Bypass Kong ไปยัง Internal Service โดยตรง จะต้องมีการปิด Port 7001 บน Firewall เมื่อมีการรัน Service บน Production Server
Authentication
Authentication คือการยืนยันตัวตนเมื่อเข้าใช้งาน เราจะตั้งค่า Kong ให้ทำ Authentication แบบ Basic Authen และ API Key กับ Request ที่เข้ามาจากภายนอก ก่อนส่งต่อไปหา Register Gateway Service โดยมีขั้นตอนดังนี้
- สร้าง Consumer โดยกดเมนู CONSUMERS กด CREATE CONSUMER ใส่ username เป็น devops กด SUBMIT CONSUMER แล้วกด Tab Credentials
- เลือกเมนู BASIC กด CREATE CREDENTIALS ใส่ข้อมูล username และ password แล้วกด SUBMIT
- เลือกเมนู API KEYS กด CREATE API KEY ปล่อย key เป็นค่าว่างไว้ เพื่อให้ Kong สร้าง key ที่ปลอดภัยให้โดยอัตโนมัติ แล้วกด SUBMIT
- เราจะทำ Authen กับ ROUTE โดยการกดที่เมนู ROUTES กด registerRoute แล้วเลือก Plugins
- กด ADD PLUGIN เลือก Basic Auth ปล่อย consumer ไว้ Kong จะเลือกจาก consumer ที่เราตั้งไว้ แล้วกด ADD PLUGIN อีกครั้ง
- เลือก Key Auth ปล่อย consumer ไว้ ใส่ key names กด Enter แล้วกด ADD PLUGIN
- Disabled key-auth เพื่อทดลองกดส่ง Request ใน Postman ไปยัง https://service.labxx.cpsudevops.com/register/ เพื่อให้ Kong ทำ Authen แบบ basic-auth
- Enabled key-auth และ Disabled basic-auth เพื่อทดลองกดส่ง Request ใน Postman
Rate Limiting
เราสามารถควบคุม Traffic ได้ว่าใน 1 วินาที/นาที/ชั่วโมง/วัน จะมี Request ได้กี่ครั้ง ด้วยการทำ Rate Limiting Plugin โดยมีขั้นตอนดังนี้
- ทำ Rate Limiting กับ ROUTE โดยการกดที่เมนู ROUTES กด registerRoute แล้วเลือก Plugins
- กด ADD PLUGIN เลือกเมนู Traffic Control กด ADD PLUGIN ที่ Rate Limiting กำหนดให้ส่ง Request ได้ 5,000 ครั้ง ต่อชั่วโมง แล้วกด ADD PLUGIN
- ทดลองกดส่ง Request ใน Postman จะเห็นว่า X-RateLimit-Remaining-Hour เหลือ 4999 และเมื่อกดส่งอีกครั้ง X-RateLimit-Remaining-Hour จะเหลือ 4998
Prometheus + Grafana
เราจะใช้ Prometheus จัดเก็บข้อมูลต่างๆ ของ Cloud Server และ Service ในแบบ Time Series และใช้ Grafana สำหรับดึงข้อมูลมาแสดงบน Real Time Dashboard
ก่อนอื่นเราจะ Add plugin ใน Kong เพื่อ Monitor Consumer แล้วติดตั้ง Grafana Container ตามขั้นตอนดังต่อไปนี้
- เลือกเมนู CONSUMERS กดที่ devops แล้วเลือก Tab Plugins
- กด ADD NEW PLUGIN เลือกเมนู Analytics & Monitoring กด ADD PLUGIN ที่ Prometheus แล้วกด ADD PLUGIN อีกครั้ง
- สร้าง Project ชื่อ grafana_dock ภายใน Folder มีไฟล์ docker-compose.yml
.
|__ docker-compose.yml
- แก้ไข docker-compose.yml เพื่อติดตั้ง Grafana Container ตามตัวอย่างด้านล่าง
version: '2'
services:
grafana:
image: grafana/grafana
restart: always
expose:
- "3000"
external_links:
- prometheus
environment:
GF_INSTALL_PLUGINS: grafana-clock-panel, grafana-simple-json-datasource
VIRTUAL_HOST: grafana.lab20.cpsudevops.com
VIRTUAL_PORT: 3000
LETSENCRYPT_HOST: grafana.lab20.cpsudevops.com
networks:
- webproxy
- default
networks:
webproxy:
external:
name: webproxy
default:
external:
name: kong_network
- รัน Container ด้วย docker-compose และกลับไปที่ Terminal โดยใช้ parameter -d
docker-compose up -d
- ดู Container ของ kong_dock ที่กำลังรันทั้งหมด ตามที่ docker-compose.yml ดูแล ด้วย Command line
docker-compose ps
- Login เข้า Grafana จาก URL https://grafana.labxx.cpsudevops.com โดย username คือ admin และ password คือ admin แล้วเปลี่ยน Password ใหม่
- กด Add data source เลือก Prometheus
- ใส่ URL http://prometheus:9090 เพื่อ Connect ไปยัง Prometheus Container แล้วกด Save & Test
- เลือกเมนู + เพื่อ Import Dashboard
- ใส่ ID ของ Dashboard ที่เราจะติดตั้ง เลือก Prometheus Data Source เป็น Prometheus แล้วกด Import
โดยเราสามารถค้นหา Dashboard ได้จาก https://grafana.com/grafana/dashboards
สำหรับ Dashboard ID ของ Kong APIs Monitoring แบบ Official คือ 7424 ครับ
รายวิชา Dev-Ops and Cloud Engineering 101