Kong Quick Start & Core Concepts (En)
Note: Author Qicz may revise the content of this article from time to time. In order to guarantee the consistency and rigor of the content, author Qicz reserves all rights of this article. No reprint or other use of the content is allowed without the permission of Qicz.
What is Kong, technically? (https://docs.konghq.com/2.1.x/getting-started/introduction/)
Kong is a Lua application running in Nginx and made possible by the lua-nginx-module. Instead of compiling Nginx with this module, Kong is distributed along with OpenResty, which already includes lua-nginx-module. OpenResty is not a fork of Nginx, but a bundle of modules extending its capabilities.
Kong is a cloud-native, fast, scalable, and distributed Microservice Abstraction Layer (also known as an API Gateway or API Middleware). Made available as an open-source project in 2015, its core values are high performance and extensibility.
Why Kong?
If you are building for the web, mobile, or IoT (Internet of Things) you will likely end up needing common functionality to run your actual software. Kong can help by acting as a gateway (or a sidecar) for microservices requests while providing load balancing, logging, authentication, rate-limiting, transformations, and more through plugins.
Kong has been built with the following leading principles:
- High Performance: Sub-millisecond processing latency to support mission critical use cases and high throughput.
- Extensibility: With a pluggable architecture to extend Kong in Lua or GoLang with Kong’s Plugin SDK.
- Portability: To run on every platform, every cloud and to natively support Kubernetes via our modern Ingress Controller.
Features
- Cloud-Native: Platform agnostic, Kong can run on any platform - from bare metal to containers - and it can run on every cloud natively.
- Kubernetes-Native: Declaratively configure Kong with native Kubernetes CRDs using the official Ingress Controller to route and connect all L4 + L7 traffic.
- Dynamic Load Balancing: Load balance traffic across multiple upstream services.
- Hash-based Load Balancing: Load balance with consistent hashing/sticky sessions.
- Circuit-Breaker: Intelligent tracking of unhealthy upstream services.
- Health Checks: Active and passive monitoring of your upstream services.
- Service Discovery: Resolve SRV records in third-party DNS resolvers like Consul.
- Serverless: Invoke and secure AWS Lambda or OpenWhisk functions directly from Kong.
- WebSockets: Communicate to your upstream services via WebSockets.
- gRPC: Communicate to your gRPC services and observe your traffic with logging and observability plugins
- OAuth2.0: Easily add OAuth2.0 authentication to your APIs.
- Logging: Log requests and responses to your system over HTTP, TCP, UDP, or to disk.
- Security: ACL, Bot detection, allow/deny IPs, etc…
- Syslog: Logging to System log.
- SSL: Setup a Specific SSL Certificate for an underlying service or API.
- Monitoring: Live monitoring provides key load and performance server metrics.
- Forward Proxy: Make Kong connect to intermediary transparent HTTP proxies.
- Authentications: HMAC, JWT, Basic, and more.
- Rate-limiting: Block and throttle requests based on many variables.
- Transformations: Add, remove, or manipulate HTTP requests and responses.
- Caching: Cache and serve responses at the proxy layer.
- CLI: Control your Kong cluster from the command line.
- REST API: Kong can be operated with its RESTful API for maximum flexibility.
- Geo-Replicated: Configs are always up-to-date across different regions.
- Failure Detection & Recovery: Kong is unaffected if one of your Cassandra nodes goes down.
- Clustering: All Kong nodes auto-join the cluster keeping their config updated across nodes.
- Scalability: Distributed by nature, Kong scales horizontally by simply adding nodes.
- Performance: Kong handles load with ease by scaling and using NGINX at the core.
- Plugins: Extendable architecture for adding functionality to Kong and APIs.
Concepts
- Services
- Routes
- Upstreams
- Targets
- Tags
- Consumers
- Plugins
- Others
- Certificate Object
- CA Certificate Object
- SNI Object
Plugins
proxy-cache plugin (https://docs.konghq.com/hub/kong-inc/proxy-cache/)
- Major parameters
config.content_type
caching with content typeconfig.cache_ttl
default300seconds
config.strategy
memory
config.request_method
default["GET","HEAD"]
config.response_code
default200, 301, 404
- Cache status
Miss
: The request could be satisfied in cache, but an entry for the resource was not found in cache, and the request was proxied upstream.Hit
: The request was satisfied and served from cache.Refresh
: The resource was found in cache, but could not satisfy the request, due to Cache-Control behaviors or reaching its hard-coded cache_ttl threshold.Bypass
: The request could not be satisfied from cache based on plugin configuration.
Rote Limiting plugin (https://docs.konghq.com/hub/kong-inc/rate-limiting/)
-
Major parameters
-
config.policy
The rate-limiting policies to use for retrieving and incrementing the limits. Available values arelocal
(counters will be stored locally in-memory on the node),cluster
(counters are stored in the datastore and shared across the nodes), andredis
(counters are stored on a Redis server and will be shared across the nodes). In the case of DB-less mode, at least one oflocal
orredis
must be specified. Please refer Implementation Considerations for details on which policy should be used.config.policy=redis
using
config.redis*
=>redis_host|redis_password|redis_database|redis_timeout
-
config.
second|minute|hour|day|month|year
-
Key Auth plugin (https://docs.konghq.com/hub/kong-inc/key-auth/)
- Major parameters
config.key_names
default nameapikey
- Usage step
- Create a Consumer
- Create a Key
- Using the Key
Load Balancing plugin (https://docs.konghq.com/getting-started-guide/2.1.x/load-balancing/)
- Concepts
- Upstreams
- Targets
Custom Nginx templates & embedding Kong (https://docs.konghq.com/2.1.x/configuration/)
$ kong start -c kong.conf --nginx-conf custom_nginx.template
Terminology
client
: Refers to the downstream client making requests to Kong’s proxy port.upstream service
: Refers to your own API/service sitting behind Kong, to which client requests/connections are forwarded.Service
: Service entities, as the name implies, are abstractions of each of your own upstream services. Examples of Services would be a data transformation microservice, a billing API, etc.Route
: This refers to the Kong Routes entity. Routes are entrypoints into Kong, and defining rules for a request to be matched, and routed to a given Service.Plugin
: This refers to Kong “plugins”, which are pieces of business logic that run in the proxying lifecycle. Plugins can be configured through the Admin API - either globally (all incoming traffic) or on specific Routes and Services.
Ports
- proxy:
8000
,8443
for https - admin:
8001
,8444
for https
Routes and matching capabilities
Kong supports native proxying of HTTP/HTTPS, TCL/TLS, and GRPC/GRPCS protocols; as mentioned earlier, each of these protocols accept a different set of routing attributes:
http
:methods
,hosts
,headers
,paths
(andsnis
, ifhttps
)tcp
:sources
,destinations
(andsnis
, iftls
)grpc
:hosts
,headers
,paths
(andsnis
, ifgrpcs
)
Note that all three of these fields are optional, but at least one of them must be specified.
For a request to match a Route:
- The request must include all of the configured fields
- The values of the fields in the request must match at least one of the configured values (While the field configurations accepts one or more values, a request needs only one of the values to be considered a match)
Let’s go through a few examples. Consider a Route configured like this:
|
|
Some of the possible requests matching this Route would look like:
|
|
|
|
|
|
All three of these requests satisfy all the conditions set in the Route definition.
However, the following requests would not match the configured conditions:
|
|
path not match.
|
|
method not match.
|
|
url not match.
All three of these requests satisfy only two of configured conditions. The first request’s path is not a match for any of the configured paths
, same for the second request’s HTTP method, and the third request’s Host header.
Now that we understand how the routing properties work together, let’s explore each property individually.
The preserve_host
property
When proxying, Kong’s default behavior is to set the upstream request’s Host header to the hostname specified in the Service’s host
. The preserve_host
field accepts a boolean flag instructing Kong not to do so.
For example, when the preserve_host
property is not changed and a Route is configured like so:
|
|
A possible request from a client to Kong could be:
|
|
Kong would extract the Host header value from the Service’s host
property, , and would send the following upstream request:
|
|
However, by explicitly configuring a Route with preserve_host=true
:
|
|
And assuming the same request from the client:
|
|
Kong would preserve the Host on the client request and would send the following upstream request instead:
|
|
Request headers (except Host)
Since Kong 1.3.0, it is possible to route request by other headers besides Host
.
To do this, use the headers
property in your Route:
|
|
Given a request with a header such as:
|
|
This request will be routed through to the Service. The same will happen with this one:
|
|
But this request will not be routed to the Service:
|
|
Note: The headers
keys are a logical AND
and their values a logical OR
.
Request path
Another way for a Route to be matched is via request paths. To satisfy this routing condition, a client request’s path must be prefixed with one of the values of the paths
attribute.
For example, with a Route configured like so:
|
|
The following requests would be matched:
|
|
|
|
|
|
For each of these requests, Kong detects that their URL path is prefixed with one of the Routes’s paths
values. By default, Kong would then proxy the request upstream without changing the URL path.
When proxying with path prefixes, the longest paths get evaluated first. This allow you to define two Routes with two paths: /service
and /service/resource
, and ensure that the former does not “shadow” the latter.
Using regexes in paths
Kong supports regular expression pattern matching for an Route’s paths
field via PCRE (Perl Compatible Regular Expression). You can assign paths as both prefixes and regexes to a Route at the same time.
For example, if we consider the following Route:
|
|
The following requests would be matched by this Route:
|
|
|
|
The provided regexes are evaluated with the a
PCRE flag (PCRE_ANCHORED
), meaning that they will be constrained to match at the first matching point in the path (the root /
character).
The strip_path
property
It may be desirable to specify a path prefix to match a Route, but not include it in the upstream request. To do so, use the strip_path
boolean property by configuring a Route like so:
|
|
Enabling this flag instructs Kong that when matching this Route, and proceeding with the proxying to a Service, it should not include the matched part of the URL path in the upstream request’s URL. For example, the following client’s request to the above Route:
|
|
Will cause Kong to send the following upstream request:
|
|
The same way, if a regex path is defined on a Route that has strip_path
enabled, the entirety of the request URL matching sequence will be stripped. Example:
|
|
The following HTTP request matching the provided regex path:
|
|
Will be proxied upstream by Kong as:
|
|
Matching priorities
A Route may define matching rules based on its headers
, hosts
, paths
, and methods
(plus snis
for secure routes - "https"
, "grpcs"
, "tls"
) fields. For Kong to match an incoming request to a Route, all existing fields must be satisfied. However, Kong allows for quite some flexibility by allowing two or more Routes to be configured with fields containing the same values - when this occurs, Kong applies a priority rule.
The rule is: when evaluating a request, Kong will first try to match the Routes with the most rules.
For example, if two Routes are configured like so:
|
|
The second Route has a hosts
field and a methods
field, so it will be evaluated first by Kong. By doing so, we avoid the first Route “shadowing” calls intended for the second one.
Thus, this request will match the first Route
|
|
And this request will match the second one:
|
|
Following this logic, if a third Route was to be configured with a hosts
field, a methods
field, and a uris
field, it would be evaluated first by Kong.
If the rule count for the given request is the same in two Routes A
and B
, then the following tiebreaker rules will be applied in the order they are listed. Route A
will be selected over B
if:
A
has only “plain” Host headers andB
has has one or more “wildcard” host headersA
has more non-Host headers thanB
.A
has at least one “regex” paths andB
has only “plain” paths.A
’s longer path is longer thanB
’s longer path.A.created_at < B.created_at
Proxying behavior (https://docs.konghq.com/2.1.x/proxy/#proxying-behavior)
Configuring a fallback Route (https://docs.konghq.com/2.1.x/proxy/#configuring-a-fallback-route)
As a practical use-case and example of the flexibility offered by Kong’s proxying capabilities, let’s try to implement a “fallback Route”, so that in order to avoid Kong responding with an HTTP 404
, “no route found”, we can catch such requests and proxy them to a special upstream service, or apply a plugin to it (such a plugin could, for example, terminate the request with a different status code or response without proxying the request).
Here is an example of such a fallback Route:
|
|
As you can guess, any HTTP request made to Kong would actually match this Route, since all URIs are prefixed by the root character /
. As we know from the Request path section, the longest URL paths are evaluated first by Kong, so the /
path will eventually be evaluated last by Kong, and effectively provide a “fallback” Route, only matched as a last resort. You can then send traffic to a special Service or apply any plugin you wish on this Route.
Proxy WebSocket traffic (https://docs.konghq.com/2.1.x/proxy/#proxy-websocket-traffic)(TODO)
Loadbalancing reference (https://docs.konghq.com/2.1.x/loadbalancing/)
DNS-based loadbalancing
the registration of the backend services is done outside of Kong
Ring-balancer
algorithm: consistent-hashing
, least-connections
, round-robin
Blue-Green Deployments (https://docs.konghq.com/2.1.x/loadbalancing/#blue-green-deployments)
Extension: (https://blog.christianposta.com/deploy/blue-green-deployments-a-b-testing-and-canary-releases/)
Using the ring-balancer a blue-green deployment can be easily orchestrated for a Service. Switching target infrastructure only requires a PATCH
request on a Service, to change its host
value.
-
Set up the “Blue” environment, running version 1 of the address service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
# create an upstream $ curl -X POST http://kong:8001/upstreams \ --data "name=address.v1.service" # add two targets to the upstream $ curl -X POST http://kong:8001/upstreams/address.v1.service/targets \ --data "target=192.168.34.15:80" --data "weight=100" $ curl -X POST http://kong:8001/upstreams/address.v1.service/targets \ --data "target=192.168.34.16:80" --data "weight=50" # create a Service targeting the Blue upstream $ curl -X POST http://kong:8001/services/ \ --data "name=address-service" \ --data "host=address.v1.service" \ --data "path=/address" # finally, add a Route as an entry-point into the Service $ curl -X POST http://kong:8001/services/address-service/routes/ \ --data "hosts[]=address.mydomain.com"
Requests with host header set to
address.mydomain.com
will now be proxied by Kong to the two defined targets; 2/3 of the requests will go tohttp://192.168.34.15:80/address
(weight=100
), and 1/3 will go tohttp://192.168.34.16:80/address
(weight=50
). -
Before deploying version 2 of the address service, set up the “Green” environment:
1 2 3 4 5 6 7 8 9 10 11
# create a new Green upstream for address service v2 $ curl -X POST http://kong:8001/upstreams \ --data "name=address.v2.service" # add targets to the upstream $ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \ --data "target=192.168.34.17:80" --data "weight=100" $ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \ --data "target=192.168.34.18:80" --data "weight=100"
To activate the Blue/Green switch, we now only need to update the Service:
1 2 3
# Switch the Service from Blue to Green upstream, v1 -> v2 $ curl -X PATCH http://kong:8001/services/address-service \ --data "host=address.v2.service"
Incoming requests with host header set to
address.mydomain.com
will now be proxied by Kong to the new targets; 1/2 of the requests will go tohttp://192.168.34.17:80/address
(weight=100
), and the other 1/2 will go tohttp://192.168.34.18:80/address
(weight=100
).
Canary Releases (https://docs.konghq.com/2.1.x/loadbalancing/#canary-releases)
Extension: (http://blog.christianposta.com/deploy/blue-green-deployments-a-b-testing-and-canary-releases/)
Using the ring-balancer, target weights can be adjusted granularly, allowing for a smooth, controlled canary release.
Using a very simple 2 target example:
|
|
By repeating the requests, but altering the weights each time, traffic will slowly be routed towards the other target. For example, set it at 10%:
|
|
The changes through the Kong Admin API are dynamic and will take effect immediately. No reload or restart is required, and no in progress requests will be dropped.
Health Checks and Circuit Breakers Reference (https://docs.konghq.com/2.1.x/health-checks-circuit-breakers/)
Upstreams
Along with health check functionality on individual targets, Upstreams also have a notion of health. The health of an Upstream is determined based on the status of its Targets.
Configuration of the Upstream’s health is done though the property healthchecks.threshold
. This is a percentage of minimum available target “weight” (capacity) for the Upstream to be considered healthy.
Here is a simple example:
- Assume an Upstream configured with
healthchecks.threshold=55
. - It has 5 targets, each with
weight=100
, so the total weight in the ring-balancer is 500.
When failures start to occur, the circuit-breaker for the first target trips. It is now considered unhealthy. This means that in the ring-balancer, 20% of the capacity is now unhealthy (100 weight out of 500). This is still above the threshold of 55, so the remaining targets will serve the traffic of the failed one.
When a second failure occurs, another target fails, and another 100 weight is lost as unhealthy. Now the ring-balancer operates at 60% of its capacity, but still within the configured threshold.
If we assume that the 2 failures occured due to a system overload, we can now assume that the remaining 60% will also not be able to cope with the full load and soon a third node will fail, reducing healthy capacity to 40%. At this point, the Upstream health will be less than its threshold, and it will be marked as unhealthy itself.
Once it enters an unhealthy state, the Upstream will only return errors. This lets the targets/services recover from the cascading failure they were experiencing.
Once the Targets start recovering and the Upstream’s available capacity passes the threshold again, the health status of the ring-balancer will automatically be updated.
Types of health checks
-
Active health checks
Active health checks, as the name implies, actively probe targets for their health. When active health checks are enabled in an upstream entity, Kong will periodically issue HTTP or HTTPS requests to a configured path at each target of the upstream. This allows Kong to automatically enable and disable targets in the balancer based on the probe results.
The periodicity of active health checks can be configured separately for when a target is healthy or unhealthy. If the
interval
value for either is set to zero, the checking is disabled at the corresponding scenario. When both are zero, active health checks are disabled altogether. -
Passive health checks (circuit breakers)
Passive health checks, also known as circuit breakers, are checks performed based on the requests being proxied by Kong (HTTP/HTTPS/TCP), with no additional traffic being generated. When a target becomes unresponsive, the passive health checker will detect that and mark the target as unhealthy. The ring-balancer will start skipping this target, so no more traffic will be routed to it.
Once the problem with a target is solved and it is ready to receive traffic again, the Kong administrator can manually inform the health checker that the target should be enabled again, via an Admin API endpoint:
1 2
$ curl -i -X POST http://localhost:8001/upstreams/my_upstream/targets/10.1.2.3:1234/healthy HTTP/1.1 204 No Content
This command will broadcast a cluster-wide message so that the “healthy” status is propagated to the whole Kong cluster. This will cause Kong nodes to reset the health counters of the health checkers running in all workers of the Kong node, allowing the ring-balancer to route traffic to the target again.
Passive health checks have the advantage of not producing extra traffic, but they are unable to automatically mark a target as healthy again: the “circuit is broken”, and the target needs to be re-enabled again by the system administrator.
Clustering Reference (https://docs.konghq.com/2.1.x/clustering/)
A Kong cluster allows you to scale the system horizontally by adding more machines to handle more incoming requests. They will all share the same configuration since they point to the same database. Kong nodes pointing to the same datastore will be part of the same Kong cluster.
You need a load-balancer in front of your Kong cluster to distribute traffic across your available nodes.
Multiple nodes Kong clusters
Every db_update_frequency
seconds, all running Kong nodes will poll the database for any update, and will purge the relevant entities from their cache if necessary.
If we delete a Service from node A
, this change will not be effective in node B
until node B
s next database poll, which will occur up to db_update_frequency
seconds later (though it could happen sooner).
What is being cached?
All of the core entities such as Services, Routes, Plugins, Consumers, Credentials are cached in memory by Kong and depend on their invalidation via the polling mechanism to be updated.
How to configure database caching?
You can configure 3 properties in the Kong configuration file, the most important one being db_update_frequency, which determine where your Kong nodes stand on the performance vs consistency trade off.
Kong comes with default values tuned for consistency, in order to let you experiment with its clustering capabilities while avoiding “surprises”. As you prepare a production setup, you should consider tuning those values to ensure that your performance constraints are respected.
-
db_update_frequency
(default: 5s) This value determines the frequency at which your Kong nodes will be polling the database for invalidation events. A lower value will mean that the polling job will be executed more frequently, but that your Kong nodes will keep up with changes you apply. A higher value will mean that your Kong nodes will spend less time running the polling jobs, and will focus on proxying your traffic.Note: changes propagate through the cluster in up to db_update_frequency seconds.
-
db_update_propagation
(default: 0s) If your database itself is eventually consistent (ie: Cassandra), you must configure this value. It is to ensure that the change has time to propagate across your database nodes. When set, Kong nodes receiving invalidation events from their polling jobs will delay the purging of their cache for db_update_propagation seconds.If a Kong node connected to an eventual consistent database was not delaying the event handling, it could purge its cache, only to cache the non-updated value again (because the change hasn’t propagated through the database yet)!
You should set this value to an estimate of the amount of time your database cluster takes to propagate changes.
Note: when this value is set, changes propagate through the cluster in up to db_update_frequency + db_update_propagation seconds.
-
db_cache_ttl
(default: 0s) The time (in seconds) for which Kong will cache database entities (both hits and misses). This Time-To-Live value acts as a safeguard in case a Kong node misses an invalidation event, to avoid it from running on stale data for too long. When the TTL is reached, the value will be purged from its cache, and the next database result will be cached again.By default no data is invalidated based on this TTL (the default value is 0). This is usually fine: Kong nodes rely on invalidation events, which are handled at the db store level (Cassandra/PosgreSQL). If you are concerned that a Kong node might miss invalidation event for any reason, you should set a TTL. Otherwise the node might run with a stale value in its cache for an undefined amount of time, until the cache is manually purged, or the node is restarted.
-
When using Cassandra
If you use Cassandra as your Kong database, you must set
db_update_propagation
to a non-zero value. Since Cassandra is eventually consistent by nature, this will ensure that Kong nodes do not prematurely invalidate their cache, only to fetch and catch a not up-to-date entity again. Kong will present you a warning logs if you did not configure this value when using Cassandra.Additionally, you might want to configure
cassandra_consistency
to a value likeQUORUM
orLOCAL_QUORUM
, to ensure that values being cached by your Kong nodes are up-to-date values from your database.Setting the
cassandra_refresh_frequency
option to0
is not advised, as a Kong restart will be required to discover any changes to the Cassandra cluster topology.
Network Firewall (https://docs.konghq.com/2.1.x/network/#firewall)
Transparent Proxying (https://blog.stackpath.com/transparent-proxy/)
For example a HTTP request with a destination address of 10.0.0.1
, and a destination port of 80
can be redirected to 127.0.0.1
at port 8000
. To make this work, you need (with Linux) to add the transparent
listen option to Kong proxy, proxy_listen=8000 transparent
. This allows Kong to see the original destination for the request (10.0.0.1:80
) even when Kong didn’t actually listen to it directly. With this information, Kong can route the request correctly. The transparent
listen option should only be used with Linux. macOS/BSDs allow transparent proxying without transparent
listen option. With Linux you may also need to start Kong as a root
user or set the needed capabilities for the executable.
Control Kong through systemd
Start Kong
|
|
Stop Kong
|
|
Start Kong automatically at system boot
To enable Kong to automatically start at system boot:
|
|
To disable Kong from automatically starting at system boot:
|
|
Restart Kong
|
|
Query Kong status
|
|
Customize Kong’s Nginx instance including files via the injected Nginx directives (https://docs.konghq.com/2.1.x/systemd/#customize-kongs-nginx-instance-including-files-via-the-injected-nginx-directives)
Plugins execution order
The current order of execution for the bundled plugins is:
Plugin | Priority |
---|---|
pre-function | +inf |
zipkin | 100000 |
ip-restriction | 3000 |
bot-detection | 2500 |
cors | 2000 |
session | 1900 |
kubernetes-sidecar-injector | 1006 |
jwt | 1005 |
oauth2 | 1004 |
key-auth | 1003 |
ldap-auth | 1002 |
basic-auth | 1001 |
hmac-auth | 1000 |
request-size-limiting | 951 |
acl | 950 |
rate-limiting | 901 |
response-ratelimiting | 900 |
request-transformer | 801 |
response-transformer | 800 |
aws-lambda | 750 |
azure-functions | 749 |
prometheus | 13 |
http-log | 12 |
statsd | 11 |
datadog | 10 |
file-log | 9 |
udp-log | 8 |
tcp-log | 7 |
loggly | 6 |
syslog | 4 |
request-termination | 2 |
correlation-id | 1 |
post-function | -1000 |
Importment Settings
Upstreams
healthchecks.active.healthy.interval
default and set to0
that active probes forhealthy targets
should not be performed.healthchecks.active.unhealthy.interval
default and set to0
that active probes forunhealthy targets
should not be performed.