DevOps
[Docker Compose] Kong Gateway(3.7.X) Local 개발 환경 구축
nineDeveloper
2024. 7. 15. 00:15
728x90
- Mac 에서는 Rancher Desktop 을 설치해서 Docker 환경을 구성
🚦 Kong Gateway 및 PostgreSQL 구성 Docker Compose 스크립트
📌 Spec
- Kong G/W: 3.7.X
- PostgreSQL: 16.X
- 참고
📌 config/kong.yaml
# https://docs.konghq.com/gateway/latest/install/docker/#prepare-your-configuration-file
# a very minimal declarative config file
_format_version: "3.0"
_transform: true
📌 docker-compose.yml
x-kong-config: &kong-env
KONG_DATABASE: postgres # # kong에서 사용하는 Datasoure
KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong} # postgresql 데이터베이스
KONG_PG_HOST: postgres # postgresql host
KONG_PG_PORT: 5432 # postgresql 포트
KONG_PG_USER: ${POSTGRES_USER:-kong} # postgresql 사용자
KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password # postgresql 비밀번호
services:
postgres:
container_name: postgres
image: postgres:16
environment:
POSTGRES_DB: ${KONG_PG_DATABASE:-kong}
POSTGRES_USER: ${KONG_PG_USER:-kong}
POSTGRES_PASSWORD_FILE: /run/secrets/kong_postgres_password
TZ: Asia/Seoul
ports:
- "5432:5432"
volumes:
- type: bind
source: ${PWD}/postgres_data
target: /var/lib/postgresql/data
secrets:
- kong_postgres_password
healthcheck:
test:
[
"CMD",
"pg_isready",
"-d",
"${KONG_PG_DATABASE:-kong}",
"-U",
"${KONG_PG_USER:-kong}"
]
interval: 30s
timeout: 30s
retries: 3
restart: on-failure
stdin_open: true
tty: true
privileged: true
user: ${UID}
networks:
- kong-net
pgadmin:
container_name: pgadmin
image: dpage/pgadmin4
ports:
- "5555:80"
volumes:
- ${PWD}/pgadmin:/var/lib/pgadmin:rw
environment:
PGADMIN_DEFAULT_EMAIL: example@pgadmin.com
PGADMIN_DEFAULT_PASSWORD: pgadmin
TZ: Asia/Seoul
restart: unless-stopped
depends_on:
- postgres
networks:
- kong-net
kong-migrations:
image: kong:3.7
command: kong migrations bootstrap
environment:
<<: *kong-env
secrets:
- kong_postgres_password
networks:
- kong-net
restart: on-failure
depends_on:
- postgres
kong-migrations-up:
image: kong:3.7
command: kong migrations up && kong migrations finish
environment:
<<: *kong-env
secrets:
- kong_postgres_password
networks:
- kong-net
restart: on-failure
depends_on:
- kong-migrations
kong-gateway:
# image: kong:3.7
build:
context: .
networks:
- kong-net
environment:
<<: *kong-env
TZ: Asia/Seoul
KONG_PROXY_ACCESS_LOG: /dev/stdout # kong log 출력
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: 0.0.0.0:${KONG_ADMIN_PORT:-8001}, ${LOCAL_IP}:8001, 0.0.0.0:8444 ssl
KONG_PROXY_LISTEN: "0.0.0.0:8000 reuseport backlog=16384, 0.0.0.0:8443 http2 ssl reuseport backlog=16384" # proxy port 변경
# KONG_PROXY_LISTEN: "0.0.0.0:8000 proxy_protocol, 0.0.0.0:8443 http2 ssl proxy_protocol" # proxy port 변경
# KONG_PROXY_LISTEN: 0.0.0.0:${KONG_PROXY_PORT:-8000}
# KONG_PROXY_URL: http://${LOCAL_IP}:8000
KONG_PROXY_URL: http://localhost:8000
KONG_ADMIN_GUI_LISTEN: "0.0.0.0:8002, 0.0.0.0:8445 ssl" # kong manager 포트
# KONG_ADMIN_GUI_URL: "http://host.docker.internal:8002" # kong manager 주소
KONG_ADMIN_GUI_URL: "http://localhost:8002" # kong manager 주소
# KONG_ADMIN_GUI_API_URL: "http://${LOCAL_IP}:8001" # kong manager에서 사용하는 admin api(CORS 방지)
KONG_ADMIN_GUI_API_URL: "http://localhost:8001" # kong manager에서 사용하는 admin api(CORS 방지)
KONG_TRUSTED_IPS: 0.0.0.0/0,::/0 # This trusts all IPs
KONG_REAL_IP_RECURSIVE: ON
# default X-Real-IP X-Forwarded-For
# KONG_REAL_IP_HEADER: proxy_protocol
KONG_REAL_IP_HEADER: X-Forwarded-For
volumes:
# 호스트머신 타임존 사용
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
# File Log 파일 볼륨 바인드 마운트
# - tmp:/tmp:rw
# https://docs.konghq.com/gateway/latest/install/docker/#prepare-your-configuration-file
- ${PWD}/config:/opt/kong
secrets:
- kong_postgres_password
ports:
- '${KONG_PROXY_PORT:-8000}:8000' # proxy port
# - '18443:18443' # proxy port (ssl)
- '${KONG_ADMIN_PORT:-8001}:8001' # admin api port
- '8002:8002' # kong manager
- '8443:8443'
- '8444:8444'
- '8445:8445'
- '8003:8003'
- '8004:8004'
extra_hosts:
- "host.docker.internal:host-gateway"
- "otherhost:10.10.0.1"
- 'api.test.com:10.10.0.2'
healthcheck:
test: ["CMD", "kong", "health"]
interval: 10s
timeout: 10s
retries: 10
security_opt:
- no-new-privileges
restart: on-failure:5
# read_only: true
user: "${UID}"
# privileged: true
depends_on:
# - postgres
- kong-migrations-up
# docker network create kong-net
networks:
kong-net:
driver: bridge
# external: true
volumes:
tmp:
secrets:
kong_postgres_password:
file: ./POSTGRES_PASSWORD
📌 Dockerfile
Timezone 설정 문제로 Dockerfile 빌드 Step 추가
FROM kong:3.7
# https://stynxh.github.io/2020-07-26-set-timezone-when-ubuntu-docker-image-build/
ARG DEBIAN_FRONTEND=noninteractive
ENV UID=${UID}
ENV TZ=Asia/Seoul
USER root
RUN apt-get update && apt-get install -y tzdata
USER ${UID}
📌 POSTGRES_PASSWORD
Secrets 설정으로 패스워드를 별도의 파일로 분리
kong1234
🚦 기동/중지/재시작/로그보기 스크립트
📌 기동: start.sh
#!/bin/bash
UID="$(id -u)"
# LOCAL_IP=$(osascript -e "IPv4 address of (system info)")
# LOCAL_IP=$(ifconfig | grep 'inet ' | grep -Fv 127.0.0.1 | awk '{print $2}')
# LOCAL_IP=$(ifconfig | awk '/inet /&&!/127.0.0.1/{print $2}')
# LOCAL_IP=$(ifconfig | awk '/inet /&&!/127.0.0.1/{print $2;exit}')
# PUBLIC_IP=$(curl -s ifconfig.me)
# PRIVATE_IP=$(hostname -i)
# LOCAL_IP=$(ipconfig getifaddr en0)
LOCAL_IP=$(hostname -I | awk '{print $1}')
PWD=$(pwd)
export UID LOCAL_IP PWD
echo UID=$UID, LOCAL_IP=$LOCAL_IP, PWD=$PWD
echo "docker compose up --build --force-recreate -d"
docker compose up --build --force-recreate -d
# echo "docker compose up --build -d"
# docker compose up --build -d
📌 중지: stop.sh
#!/bin/bash
UID="$(id -u)"
# LOCAL_IP=$(osascript -e "IPv4 address of (system info)")
# LOCAL_IP=$(ifconfig | grep 'inet ' | grep -Fv 127.0.0.1 | awk '{print $2}')
# LOCAL_IP=$(ifconfig | awk '/inet /&&!/127.0.0.1/{print $2}')
# LOCAL_IP=$(ifconfig | awk '/inet /&&!/127.0.0.1/{print $2;exit}')
# PUBLIC_IP=$(curl -s ifconfig.me)
# PRIVATE_IP=$(hostname -i)
# LOCAL_IP=$(ipconfig getifaddr en0)
LOCAL_IP=$(hostname -I | awk '{print $1}')
PWD=$(pwd)
export UID LOCAL_IP PWD
echo UID=$UID, LOCAL_IP=$LOCAL_IP, PWD=$PWD
echo "docker compose down"
docker compose down
📌 재시작: restart.sh
#!/bin/bash
UID="$(id -u)"
# LOCAL_IP=$(osascript -e "IPv4 address of (system info)")
# LOCAL_IP=$(ifconfig | grep 'inet ' | grep -Fv 127.0.0.1 | awk '{print $2}')
# LOCAL_IP=$(ifconfig | awk '/inet /&&!/127.0.0.1/{print $2}')
# LOCAL_IP=$(ifconfig | awk '/inet /&&!/127.0.0.1/{print $2;exit}')
# PUBLIC_IP=$(curl -s ifconfig.me)
# PRIVATE_IP=$(hostname -i)
# LOCAL_IP=$(ipconfig getifaddr en0)
LOCAL_IP=$(hostname -I | awk '{print $1}')
PWD=$(pwd)
export UID LOCAL_IP PWD
echo UID=$UID, LOCAL_IP=$LOCAL_IP, PWD=$PWD
echo "docker compose down"
docker compose down
# echo "docker compose up --build --force-recreate -d"
# docker compose up --build --force-recreate -d
echo "docker compose up -d"
docker compose up -d
📌 로그보기: tail.sh
#!/bin/bash
# 로그 보기 (이전 로그 100라인만 출력)
echo "docker compose logs -f -t -n 100"
docker compose logs -f -t -n 100
# 전체 로그 보기
# https://docs.docker.com/reference/cli/docker/compose/logs/
# --no-color : 단색 출력을 생성
# --no-log-prefix: 접두사 출력 안함
# -f, -follow: 로그 출력을 따라감
# -t, -timestamps: 타임 스탬프 표시
# -n --tail all: 각 컨테이너의 로그 끝부터 표시
# echo 'docker compose logs -f -t -n all
# docker compose logs -f -t -n all
🚦 Kong Conf 설정 및 logrotate 설정
📌 Docker Compose 에서 설정
Docker Compose 사용시 logrotate 설정은 필요 없음
HTTP Server 에 요청한 Client 의 IP 를 식별하기 위한 표준 설정
trusted_ips = 0.0.0.0/0,::/0
real_ip_header = X-Forwarded-For
Docker Compose 에서는 environment 로 설정
environment:
KONG_TRUSTED_IPS: 0.0.0.0/0,::/0 # This trusts all IPs
KONG_REAL_IP_RECURSIVE: ON
KONG_REAL_IP_HEADER: X-Forwarded-For
📌 Linux 에서 설정
Kong conf 설정 파일 적용
- PATH:
/etc/kong
위의 경로에 설정파일 복사
Kong logrotate 설정
- 설정 참고
# kong logrotate 생성
$ vim /etc/logrotate.d/kong
- kong logrotate 설정 내용 입력
/usr/local/kong/logs/*.log {
su kong kong
rotate 7
daily
missingok
compress
delaycompress
notifempty
sharedscripts
postrotate
if [ -f /usr/local/kong/pids/nginx.pid ]; then
kill -USR1 `cat /usr/local/kong/pids/nginx.pid`
fi
endscript
}
- kong logrotate 적용
$ sudo /usr/sbin/logrotate -f /etc/logrotate.conf
🚦 Consumers 등록 및 Basic Auth 생성
Kong Gateway 를 이용하여 서비스를 라우팅할때, 특정 대상에 라우팅을 허용할지 여부를 적용할때의 적용 대상
- 참고
📌 Consumers Basic Auth Authorization 생성 절차
- Consumers - New Consumer 클릭
- Consumer 정보 입력
- Basic Auth Credential 생성
- Basic Auth Credential 정보 입력
- Basic Auth Credential 생성 완료
- Basic Auth 인증 정보로 Base64 인코딩
- 참고
- Basic Auth Base64 인코딩 데이터를 Header에 Authorization 에 추가하여 Routing 인증에 사용
아래와 같이 Header 에 설정하고 사용
Authorization: Basic dGVzdDp0ZXN0MTIzNA==
🚦 테스트 쉘 스크립트
📌 Kong 서비스 테스트
등록된 서비스들에 대한 통신 테스트를 수행하는 스크립트
Kong Gateway 에 서비스를 등록하고 테스트를 수행해본다
dev_kong_service_check.sh
#!/bin/bash
declare -a remote_hosts=(
"172.16.0.1:8001"
"172.16.0.2:443"
"172.16.0.3:443"
"172.16.0.4:443"
"172.16.0.5:443"
"172.16.0.6:443"
)
length=${#remote_hosts[@]}
profile='DEV'
success_count=0
fail_count=0
echo "==============================================="
echo "$profile SERVICE TEST START!!"
echo "==============================================="
for each in ${remote_hosts[@]} ;do
ip=$(echo $each | cut -d ':' -f1)
port=$(echo $each | cut -d ':' -f2)
echo "Connecting ${ip}:${port} .."
telnet $ip $port 2>&1 >/dev/null & WPID=$!
sleep 1
if ps -p $WPID > /dev/null ;then
echo "FAILED TO REACH ($WPID is running)"
kill $! 2>&1 >/dev/null
wait $WPID 2>&1 >/dev/null
fail_count=$((fail_count+1))
else
success_count=$((success_count+1))
fi
echo "-------------------------------------------------------------------------------------------------"
done
echo total_count=$length, success_count=$success_count, fail_count=$fail_count
echo "==============================================="
echo "$profile SERVICE TEST END!!"
echo "==============================================="
📌 Kong 라우터 테스트
등록된 라우터들에 대한 통신 테스트를 수행하는 스크립트
Kong Gateway 에 라우터를 등록하고 테스트를 수행해본다
dev_kong_route_check.sh
#!/bin/bash
domain='172.16.0.1:8000' # KONG
function route_roop() {
path=$1
echo "==============================================="
echo "path=[$path] TEST START!!"
echo "==============================================="
declare -a authorizations=(
"a3l0dsfdsdf8sdf8sd8fds8dfss"
"a3l0dsfdsdf8sdf8sd8fds8dfs1"
"a3l0dsfdsdf8sdf8sd8fds8dfs2"
"a3l0dsfdsdf8sdf8sd8fds8dfs3"
"a3l0dsfdsdf8sdf8sd8fds8dfs4"
)
declare -a consumers=(
"test-route1"
"test-route2"
"test-route3"
"test-route4"
"test-route5"
)
length=${#authorizations[@]}
success_count=0
fail_count=0
roop_count=0
for each in ${authorizations[@]} ;do
# CURL 테스트시 HTTPS 사이트 SSL 검증에 실패하므로 -k 옵션을 추가하여 검증을 PASS 한다
# 참고: https://velog.io/@markyang92/curl
echo curl -s -w '%{http_code}' -o /dev/null -L -k "${path}" --header "Authorization: Basic $each"
result=$(curl -s -w '%{http_code}' -o /dev/null -L -k "${path}" --header "Authorization: Basic $each")
sleep 0.1
consumer="consumer=[${consumers[$roop_count]}], path=[$path]"
if [ $result -eq 200 ] ;then
echo "$consumer: SUCCESS!!"
success_count=$((success_count+1))
else
echo "$consumer: FAIL!!"
fail_count=$((fail_count+1))
fi
roop_count=$((roop_count+1))
echo "-------------------------------------------------------------------------------------------------"
done
echo total_count=$length, success_count=$success_count, fail_count=$fail_count
echo "==============================================="
echo "path=[$path] TEST END!!"
echo "==============================================="
}
default_url="http://${domain}"
# IP, DOMAIN 여부에 따라 HTTP, HTTPS 프로토콜로 변환
if [[ ${domain:0:1} =~ ^[0-9]+$ ]];then
url=${default_url}
else
url="https://${domain}"
fi
# DOMAIN 이더라도 HTTP 프로토콜이면 default_url
path='${default_url}/test/api/a'
route_roop $path
# 나머지 API 들은 IP, DOMAIN 에 따라 분기 처리
path='${url}/test/api/b'
route_roop $path
# 나머지 API 들은 IP, DOMAIN 에 따라 분기 처리
path='${url}/test/api/c'
route_roop $path
728x90