Docker化Kong调用Keycloak令牌自省端点超时问题求助
按照教程搭建Docker环境(Kong+Konga+Keycloak),调用带Bearer令牌的接口时出现超时错误:
请求:
curl "http://${HOST_IP}:8000/mock-postman" -H "Accept: application/json" -H "Authorization: Bearer $TKN"
响应:
accessing introspection endpoint (http://192.168.0.46:8180/realms/experimental/protocol/openid-connect/token/introspect) failed: timeout
不带令牌时网关行为正常:
请求:
curl "http://${HOST_IP}:8000/mock-postman" -H "Accept:application/json" -I
响应:
HTTP/1.1 401 Unauthorized Date: Sun, 02 Jun 2024 18:22:05 GMT Connection: keep-alive WWW-Authenticate: Bearer realm="experimental",error="no Authorization header found" X-Kong-Response-Latency: 1 Server: kong/2.8.3
docker-compose.yml配置如下:
version: '3.4' networks: kong-net: driver: bridge keycloak-net: volumes: kong-datastore: keycloak-datastore: services: kong-db: image: postgres:11-alpine volumes: - kong-datastore:/var/lib/postgresql/data networks: - kong-net ports: - "15432:5432" environment: POSTGRES_DB: api-gw POSTGRES_USER: kong POSTGRES_PASSWORD: kong kong: build: context: ./ image: kong-oidc:latest depends_on: - kong-db networks: - kong-net ports: - "8000:8000" # Listener - "8001:8001" # Admin API - "8443:8443" # Listener (SSL) - "8444:8444" # Admin API (SSL) environment: KONG_DATABASE: postgres KONG_PG_HOST: kong-db KONG_PG_PORT: 5432 KONG_PG_DATABASE: api-gw KONG_PG_USER: kong KONG_PG_PASSWORD: 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: bundled,oidc KONG_LOG_LEVEL: debug konga: image: pantsel/konga:0.14.9 depends_on: - kong networks: - kong-net ports: - "1337:1337" # konga environment: DB_ADAPTER: postgres DB_HOST: kong-db DB_PORT: '5432' DB_USER: kong DB_PASSWORD: kong DB_DATABASE: api-gw NODE_ENV: development keycloak-db: image: postgres:14-alpine volumes: - keycloak-datastore:/var/lib/postgresql/data networks: - keycloak-net ports: - "25432:5432" environment: POSTGRES_DB: keycloak POSTGRES_USER: keycloak POSTGRES_PASSWORD: password keycloak: image: quay.io/keycloak/keycloak:20.0.1 depends_on: - keycloak-db command: start-dev networks: - keycloak-net ports: - "8180:8080" environment: KC_DB: postgres KC_DB_URL: jdbc:postgresql://keycloak-db/keycloak KC_DB_USERNAME: keycloak KC_DB_PASSWORD: password KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin KC_METRICS_ENABLED: 1 prometheus: image: prom/prometheus depends_on: - kong container_name: prometheus networks: - kong-net restart: always volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" ports: - 9090:9090 grafana: image: grafana/grafana depends_on: - prometheus container_name: grafana networks: - kong-net restart: always volumes: - ./grafana/provisioning/:/etc/grafana/provisioning ports: - 3000:3000
Kong核心错误日志:
2024/06/05 12:03:59 [error] 1108#0: *75515 [lua] openidc.lua:405: openidc_call_token_endpoint(): accessing introspection endpoint (http://192.168.0.18:8180/realms/experimental/protocol/openid-connect/token/introspect) failed: timeout, client: 192.168.0.18, server: kong, request: "GET /mock-postman HTTP/1.1", host: "192.168.0.18:8000"
1. Docker网络隔离问题
从配置可见,Kong属于kong-net网络,Keycloak属于keycloak-net网络,两个独立桥接网络默认无法直接通信。Kong用宿主机IP访问Keycloak映射端口时,容器内部可能无法解析路由到宿主机,导致超时。
验证操作:
进入Kong容器,尝试用Keycloak服务名+内部端口访问接口:
docker exec -it <kong-container-id> curl http://keycloak:8080/realms/experimental/protocol/openid-connect/token/introspect
若无法访问,说明网络隔离是问题根源。
解决方向:
修改docker-compose.yml,给Kong添加keycloak-net网络:
services: kong: # ...其他配置 networks: - kong-net - keycloak-net
同时更新OIDC插件的introspection端点地址为http://keycloak:8080/realms/experimental/protocol/openid-connect/token/introspect(用容器服务名+内部端口,而非宿主机IP)。
2. Introspection端点地址配置错误
OIDC插件配置中若填写的是宿主机IP+映射端口(8180),容器间通信应使用服务名+内部端口(8080),映射端口仅用于宿主机外部访问。
验证操作:
检查Kong OIDC插件的introspection_endpoint配置项,确认是否为容器内部可访问的地址。
解决方向:
更新OIDC插件配置,将端点地址改为Keycloak容器服务名+内部端口。
3. 防火墙或端口占用
宿主机防火墙可能阻止Kong容器访问8180端口,或该端口被其他服务占用,导致Keycloak未正常监听。
验证操作:
- 宿主机执行
netstat -tulpn | grep 8180,确认Keycloak是否正常监听端口。 - 临时关闭宿主机防火墙,重新发起请求测试。
4. Keycloak未完全就绪
depends_on仅保证容器启动顺序,不保证服务完全初始化。Kong启动后,Keycloak可能仍在加载,导致调用超时。
验证操作:
等待2-3分钟后再发起请求,或查看Keycloak容器日志,确认出现Started server类就绪信息。
5. OIDC插件超时时间过短
Kong OIDC插件默认超时时间可能不足以完成令牌校验,导致超时。
解决方向:
调整OIDC插件的timeout配置项(例如设置为10000毫秒),增加请求等待时间。
内容的提问来源于stack exchange,提问作者adnan

