Coding Gun

การใช้งาน Kong บน Docker

การ Config Kong บน Docker จะมีความแตกต่างจาก Kong บน Server ปกติอยู่พอสมควร เพราะบน Container ต้องการ Config แบบ Pre-config(ใส่ Config เข้าไปแล้วเริ่มต้นทำงานได้เลย) แต่ในขณะที่การติดตั้ง Kong บน server ทั่วไปเราจะมี Admin เข้าไปกำหนดค่าเริ่มต้น

Kong Database vs DBless

ก่อนอื่นเราต้องทำความเข้่าใจวิธีการจัดการ Configuration ใน Kong กันก่อน ซึ่งใน Kong นั้นเราจะแบ่งการทำงานออกเป็น 2 ประเภท ดังนี้่

  1. Imperative วิธีนี้เป็นวิธีทีั่ถูกใช้อย่างแพร่หลายเพราะใช้งานได้ง่าย เมื่อเรากำหนด Configuration ของ Kong ผ่านทาง API หรือ Konga Kong ก็จะนำ Config เหล่านั้นไปเก็บใน database(PostgreSQL)

    • ข้อดี
      • ใช้งานง่าย เหมาะกับผู้เริ่มต้น
      • สามารถปรับเปลี่ยน Configuration ได้ง่าย
    • ข้อเสีย
      • ทุกครั้งที่ติดตั้ง Kong เพิ่มก็ต้องทำใหม่ทุกรอบ
      • Config ของ Kong แต่ละตัวอาจไม่เหมือนกัน
      • ไม่สามารถ Audit การทำงานของ Adminได้(ไม่มีหลักฐาน Artifact)
      • ไม่สามารถกำหนดมาตรฐานของการทำงานได้
      • ต้องมี database อยู่ด้วยเสมอ
      • ไม่สามารถ Sync Configuration หรือหาความแตกต่าง(Diff)ของ Configuration ได้
  2. Declarative วิธีนี้จะใช้ YAML ไฟล์ที่ได้กำหนด Configuration ไว้ล่วงหน้าแล้ว เมื่อเราต้องการ update configuration ใดๆเราจะต้องแก้ไข YAML

    • ข้อดี
      • สามารถ Sync และหา Diff ของ configuration ด้วย Deck ได้
      • สามารถ Audit การทำงานของ Admin ได้
      • สามารถขยายตัวได้ง่่าย
      • เหมาะกับการทำงานบน Container (มีความเป็น Stateless)
      • ไม่ต้องดูแล database(PostgreSQL)
    • ข้อเสีย
      • ต้องคอยดูแล YAML ให้มีความถูกต้อง
      • ต้องมี Version Control
      • จะต้อง sync ให้ YAML เป็น version ล่าสุดอยู่เสมอ
      • ต้องรู้ว่า Plugins แต่ละตัวต้องกำหนด Configuration ยังไง

    วิธีนี้เหมาะสำหรับระบบที่ต้องการขยายตัวแบบอัตโนมัติหรือระบบที่ต้องการติดตั้ง Kong แบบ Pre-Config(มี Config มาก่อนหน้าการติดตั้ง)

ในกรณีนี้เราจะติดตั้ง Kong ด้วย Docker เราจึงต้องใช้การ Config แบบ Declarative หรือ DBLess(ใช้ YAML) ซึ่งจะทำให้ Kong มีความเป็น Stateless มากกว่าแบบมี Databse

การใข้งาน Kong บน Docker แบบ DBless(Declarative)

หลังจากทำความเข้าใจการจัดการกับ Kong Configuration กันแล้วเราลองมาสร้าง Kong Configuration แบบ DBless โดยเริ่มต้นจาก

เริ่มต้นสร้าง Route และ Service

Kong จะเริ่มต้น Route traffic ได้เราจะต้องสร้าง

  1. Service ระบุที่อยู่ของ Upstream service หรือ service ต้นทางที่ให้บริการจริงๆ(จะให้ kong พาไปไหน)
  2. Route เส้นทางในการเดินทางเข้าไปหา upstream service ซึ่งสามารถ route ได้หลายวิธี
    • host กำหนดเส้นทางโดยใช้ชื่อ host เช่น example.com
    • path กำหนดเส้นทางในการเข้าถึง service ด้วย path เช่น /api/v1

ในตัวอย่างนี้เราจะสร้างไฟล์ kong.yml(เก็บไว้ใน folder config) และ ใส่ config เพื่อพาไปยัง service ที่เราใช้เป็นตัวอย่าง ชื่อ sample-api (บรรทัดที่ 18 ใน docker-compose.yml)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
_format_version: "3.0"
_transform: true

services:
- name: sample-service
  url: http://sample-api:3000/products
  routes:
  - name: sample-route
    paths:
    - /

จากตัวอย่างของ Kong Configuration ด้านบน เราได้สร้าง

  1. Service ชื่อว่า sample-service ซึ่งระบุที่อยู่ของ service เป็น http://sample-api:3000/products เราต้องใช้ชื่อ sample-api เพราะเราอยุ่ใน Docker compose ซึ่งต้องใช้ชื่อ Service ในการระบุที่อยู่

Sample-api ยังไม่มีอยู่จริง เพราะเราจะสร้างในขั้นตอนต่อไป

  1. Route ชื่อว่า sample-route ในการกำหนดเส้นทาง ซึ่งในตัวอย่างนี้เราจะ route ด้วย path ซึ่ง path ที่เราใช้เป็น “/” หมายถึงถ้าเข้ามาที่ root เช่น http://kong.local:8000/ Kong ก็จะพาไปยัง sample-api ที่เปิดให้บริการอยู่ทันที

เราสามารถใช้ Kong cli ตรวจสอบ configuration ว่าเขียนถูกหรือไม่ ด้วยคำสั่ง

$ kong config parse kong.yml

หลังจากขั้นตอนแรกเราจะได้ไฟล์ kong.yml ซึ่งอยู่ใน folder config

├── config
│   ├── kong.yml

Step 2. สร้าง Sample API ด้วย JSON server

ในตัวอย่างนี้เราจะสร้าง API ขึ้นมาเป็นตัวอย่างด้วย JSON server โดยเราจะเขียน Javascript เพื่ิอสร้าง Data จำลองขึ้นมาด้วย Code ชุดนี้ ไฟล์นี้เราจะตั้งชื่อว่า product-service.js

module.exports = () => {
  const data = { products: [] }
  for (let i = 0; i < 10; i++) {
    data.products.push({
        productCode: `P000${i}`,
        productName: `Sample product ${i}`,
        price: 100,
        rating: 1,
        comments: [
            { message: 'Test Comment 1' },
            { message: 'Test Comment 2' },
            { message: 'Test Comment 3' }
        ]
    })
  }
  return data
}

หลังจากนั้นเราจะนำ product-service.js เข้าไป run ใน container ดังนั้นเราจึงต้องสร้างไฟล์ product.Dockerfile เพื่อสร้าง image ขึ้นมาใช้งาน

FROM clue/json-server
WORKDIR /data
COPY product-service.js .
RUN /bin/bash -c "npm i @faker-js/faker"
ENTRYPOINT [ "json-server", "--host", "0.0.0.0", "product-service.js"]
EXPOSE 3000

หลังจากจบขั้นตอนนี้เราจะได้โครงสร้างไฟล์เป็นแบบนี้

├── config
│   ├── kong.yml
├── product-service.js
├── product.Dockerfile

Step 3. สร้าง Docker compose ไฟล์เพื่อจำลองการทำงานของ Kong

การสร้าง docker-compose.yml เพื่อสร้าง

โดยเราต้องวางไฟล์ docker-compose.yml ไว้นอก folder config แบบนี้

├── config
│   ├── kong.yml
├── product-service.js
├── product.Dockerfile
├── docker-compose.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
version: '3.7'
services:
  kong:
    image: kong:latest
    environment:
      KONG_DATABASE: "off"
      KONG_DECLARATIVE_CONFIG: /user/local/kong/declarative/kong.yml
      KONG_PROXY_LISTEN: 0.0.0.0:8000
      KONG_PROXY_LISTEN_SSL: 0.0.0.0:8443
      KONG_ADMIN_LISTEN: 0.0.0.0:8001
    ports:
      - 8000:8000
      - 8001:8001
      - 8443:8443
      - 8444:8444
    volumes:
      - "./config:/user/local/kong/declarative"
  sample-api:
    build:
      context: .
      dockerfile: product.Dockerfile
    ports:
      - 3000:3000

เราต้องปิดการทำงานของ Database Mode ด้วยการกำหนดตัวแปร KONG_DATABASE เป็น off ถ้าไม่กำหนดให้ KONG_DATABASE เป็น off Kong จะไม่สามารถ start ขึ้นมาทำงานได้เนื่องจากมันจะพยายาม connect ไปยัง database ที่เราไม่มี

ในตัวอย่างนี้เราใช้ docker compose เป็นตัวจัดการ container เราจึงต้องใช้ docker-compose exec ในการตรวจสอบความถูกต้องของ kong.yml

$ docker-compose run --rm -it kong kong config parse kong.yml

และเมื่อพร้อมแล้วให้เข้าไปใน folder ที่มี docker-compose.yml แล้ว run คำสั่ง

$ docker-compose up -d

หลังจากนั้นถ้าเราเข้่าไปที่ http://localhost:8000/ เราจะได้ผลลัพธ์จาก sample-api

การจัดการ Kong Configuration ด้วย Deck

Deck คือ command line ที่ช่วยจัดการ Kong Configuration โดยที่ Deck จะมี feature ต่างๆ ดังนี้

ลองดูตัวอย่างการใช้งาน Deck ได้ที่ https://asciinema.org/a/238318

Phanupong Permpimol
Follow me

Software Engineer ที่เชื่อในเรื่องของ Process เพราะเมื่อ Process ดี Product ก็จะดีตาม ปัจจุบันเป็นอาจารย์และที่ปรึกษาด้านการออกแบบและพัฒนา Software และ Web Security