Kong容器化部署的核心不在于把镜像跑起来,而在于让数据、配置、插件都能在容器重建后保持一致。很多团队第一次用Docker部署Kong时会直接使用默认的数据库配置,结果发现容器重启后路由和插件全部丢失,原因就是没有把PostgreSQL独立出来。容器化部署首先要明确一个原则:Kong容器本身应该是无状态的,状态全部交给外部的PostgreSQL或声明式配置文件。

接下来我会从环境准备、Docker Compose单机编排、Kubernetes Helm部署以及高可用配置四个层面展开。每个环节都会给出可以直接执行的命令和YAML片段,同时说明每一步背后的原因,避免只知其然不知其所以然。
环境准备与数据库选择
Kong支持两种数据存储模式:传统数据库模式(PostgreSQL或Cassandra)和无数据库声明式模式(DB-less)。容器化部署时,如果你需要动态管理路由、消费者和插件,推荐使用PostgreSQL;如果所有配置都可以提前写在YAML文件里,并且不需要运行时修改,那么DB-less模式更加轻量。本文以PostgreSQL为例,因为生产环境通常需要动态变更配置。
首先确保Docker和Docker Compose已安装。对于Kubernetes环境,提前准备好一个可用的集群以及Helm 3。PostgreSQL可以使用云数据库,也可以用容器部署。如果使用容器部署,务必为数据目录挂载卷,否则数据库容器重建后数据丢失,Kong的状态也会跟着丢失。下面的命令先创建Docker网络和数据卷,供后续使用。
docker network create kong-net docker volume create kong-pg-data
版本选择上,Kong官方镜像的标签建议使用具体版本号而非latest,避免升级导致行为变化。例如kong:3.6或kong:3.7。PostgreSQL推荐使用14或15版本。在下面的Compose文件中,我会固定镜像版本,确保可复现。
Docker Compose单机部署实战
单机环境下最快捷的方式是用Docker Compose同时启动PostgreSQL和Kong。下面是一份完整的docker-compose.yml,其中Kong服务通过环境变量指定数据库类型和连接地址。注意KONG_PG_HOST要写成数据库服务的容器名postgres,而不是localhost,因为它们在同一个Docker网络中。
version: "3.9"
services:
postgres:
image: postgres:15
restart: always
environment:
POSTGRES_USER: kong
POSTGRES_PASSWORD: kongpass
POSTGRES_DB: kong
volumes:
- kong-pg-data:/var/lib/postgresql/data
networks:
- kong-net
healthcheck:
test: ["CMD", "pg_isready", "-U", "kong"]
interval: 10s
timeout: 5s
retries: 5
kong:
image: kong:3.6
restart: always
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: postgres
KONG_PG_USER: kong
KONG_PG_PASSWORD: kongpass
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_ADMIN_LISTEN: 0.0.0.0:8001
ports:
- "8000:8000"
- "8443:8443"
- "8001:8001"
- "8444:8444"
depends_on:
postgres:
condition: service_healthy
networks:
- kong-net
volumes:
kong-pg-data:
networks:
kong-net:
external: true
保存文件后,在目录下执行docker compose up -d。第一次启动时,Kong会自动运行数据库迁移,创建所需的表结构。如果使用depends_on的condition: service_healthy,Compose会等待PostgreSQL健康检查通过后再启动Kong,避免连接超时。如果仍然看到连接被拒绝的错误,可以手动执行迁移:docker compose run --rm kong kong migrations bootstrap。
启动完成后,访问http://localhost:8001/应该返回Kong管理API的基本信息。代理端口8000默认没有配置任何路由,可以先用管理API添加一个简单的服务和路由来测试。例如:
curl -i -X POST http://localhost:8001/services \ --data name=example-service \ --data url=http://httpbin.org curl -i -X POST http://localhost:8001/services/example-service/routes \ --data paths[]=/mock
然后访问http://localhost:8000/mock,如果转发成功,说明Kong容器已经正常工作。这个例子使用httpbin.org作为上游,实际生产应替换成内部服务地址。
Kubernetes中的Helm部署与Ingress集成
在Kubernetes集群里,Kong通常以Ingress Controller的角色运行,负责解析Ingress资源并动态更新路由。官方提供了Helm Chart,安装过程比手动写Deployment简单很多。先添加Helm仓库:
helm repo add kong https://charts.konghq.com helm repo update
创建命名空间并安装:
kubectl create namespace kong helm install kong kong/kong -n kong \ --set ingressController.enabled=true \ --set ingressController.installCRDs=false \ --set postgresql.enabled=true \ --set postgresql.auth.username=kong \ --set postgresql.auth.password=kongpass \ --set postgresql.auth.database=kong
上面的命令同时启用了内置的PostgreSQL子图表,这样可以快速得到一个完整的Kong环境。不过生产环境更推荐使用外部数据库,通过--set postgresql.enabled=false并配置env.database、env.pg_host等参数来连接已有的PostgreSQL实例。这样数据库的备份、扩容可以独立管理,也避免Helm升级时数据库被连带修改。
安装完成后,Kong会自动创建LoadBalancer类型的Service,暴露代理端口。可以使用kubectl get svc -n kong查看外部IP。接下来创建一个简单的Ingress规则,验证Kong是否能够正确路由:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: default
annotations:
konghq.com/strip-path: "true"
spec:
ingressClassName: kong
rules:
- host: api.ipipp.com
http:
paths:
- path: /mock
pathType: Prefix
backend:
service:
name: mock-service
port:
number: 80
注意这里的ingressClassName必须与Kong Ingress Controller使用的类名一致。如果不确定,可以查看kubectl get ingressclass。此外,Kong还提供了一系列自定义注解,例如konghq.com/plugins、konghq.com/retries,用来在Ingress上配置插件和行为。这些注解会由Ingress Controller转换成Kong的配置。
高可用与配置持久化的关键细节
生产环境中,Kong的容器副本数至少要设为2,并配置合适的探针。Kong的健康检查端点可以使用/status,返回200表示正常。在Kubernetes中可以通过--set replicaCount=2或修改values文件来指定副本数。同时建议添加Pod反亲和规则,让副本尽量分布在不同的节点上,避免单点故障。下面是一段values.yaml片段:
replicaCount: 2
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- kong
topologyKey: kubernetes.io/hostname
probes:
liveness:
httpGet:
path: /status
port: 8100
initialDelaySeconds: 15
periodSeconds: 10
readiness:
httpGet:
path: /status
port: 8100
initialDelaySeconds: 5
periodSeconds: 5
关于配置持久化,如果使用数据库模式,Kong的路由、服务和插件配置都存储在PostgreSQL中,容器重启不会丢失。但如果使用DB-less模式,就必须把声明式配置文件挂载到容器中,否则配置丢失。自定义插件也需要通过ConfigMap或Volume挂载到/usr/local/share/lua/5.1/kong/plugins目录,并设置KONG_PLUGINS环境变量。很多同学在容器里安装了自定义插件,重启后发现插件没了,原因就是没有做成持久化挂载。
最后别忘了监控。Kong提供了Prometheus插件,可以暴露指标供Prometheus抓取。在K8s中可以通过注解开启:--set serviceMonitor.enabled=true,前提是集群已经安装了Prometheus Operator。日志方面,建议将Kong的访问日志和错误日志输出到stdout/stderr,交给日志收集系统统一处理,这也是容器化部署的标准做法。完成以上步骤后,你的Kong容器化部署就具备了生产可用性,能够稳定支撑API网关的日常流量。