The Ultra Performant API Gateway
Abdullah Fathi
Move from dealing with every particular microservice to talking to a single entry point that handles the interaction with all your microservices
Authorization, protection against scrapping, security best practices and abuse prevention implementation out of the box
Stateless design provides true linear scalability. KrakenD does not require node coordinator or data centralization
KrakenD is more than a typical proxy that forwards clients to backend services, but a powerful engine that can transform, aggregate or remove data from your own or third party services
KrakenD supports more than 70K req/s on commodity software. They're the fastest and more performant solution in the market.
Higher performance results in lower requirements in terms of resources, allowing you to save costs in your infrastructure
The stateless design is a competitive advantage over other solutions. It provides a true linear scalability and no need of node coordination
Every KrakenD node can operate independently without any coordination or centralized persistence of configuration needed
Only need KrakenD binary and a JSON config file to get KrakenD up & running
Rather than "trained" or "sales engineers. you'll receive support and advice from the engineers that coded the software
Able to integrate with standard and proved open-source solutions for every specific task
Integrate with existing solutions in the technical stack, and easily replace them when needed. Compatible to both Community or Enterprise Edition
docker run -p "8080:8080" -v $PWD:/etc/krakend/ devopsfaith/krakend:2.7.0 run -c krakend.json
# Healthcheck
http://localhost:8080/__health
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3
}
krakend.json
CLI
version: "3"
services:
krakend:
image: devopsfaith/krakend:watch
volumes:
- ".:/etc/krakend"
ports:
- "8080:8080"
command: [ "run", "-dc", "krakend.json" ]
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3
}
krakend.json
docker-compose.yaml
FROM devopsfaith/krakend:2.7 as builder
ARG ENV=prod
COPY krakend.tmpl .
COPY config .
## Save temporary file to /tmp to avoid permission errors
RUN FC_ENABLE=1 \
FC_OUT=/tmp/krakend.json \
FC_PARTIALS="/etc/krakend/partials" \
FC_SETTINGS="/etc/krakend/settings/$ENV" \
FC_TEMPLATES="/etc/krakend/templates" \
krakend check -d -t -c krakend.tmpl --lint
FROM devopsfaith/krakend:2.7
# Keep operating system updated with security fixes between releases
RUN apk upgrade --no-cache --no-interactive
COPY --from=builder --chown=krakend:nogroup /tmp/krakend.json .
# Uncomment with Enterprise image:
# COPY LICENSE /etc/krakend/LICENSE
Dockerfile
docker build --build-arg ENV=prod -t mykrakend .
CLI
apiVersion: apps/v1
kind: Deployment
metadata:
name: krakend-deployment
spec:
selector:
matchLabels:
app: krakend
replicas: 2
template:
metadata:
labels:
app: krakend
spec:
containers:
- name: krakend
image: YOUR-KRAKEND-IMAGE:1.0.0
ports:
- containerPort: 8080
imagePullPolicy: Never
command: [ "/usr/bin/krakend" ]
args: [ "run", "-d", "-c", "/etc/krakend/krakend.json", "-p", "8080" ]
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
env:
- name: KRAKEND_PORT
value: "8080"
deployment.yaml
apiVersion: v1
kind: Service
metadata:
name: krakend-service
spec:
type: NodePort
ports:
- name: http
port: 8000
targetPort: 8080
protocol: TCP
selector:
app: krakend
service.yaml
.
├── krakend.tmpl
└── config
├── partials
│ └── file.txt
├── templates
│ ├── telemetry.tmpl
│ └── endpoints.tmpl
└── settings
├── prod
| └── urls.json
└── dev
└── urls.json
{{/*
This
is
multiline
comment
*/}}
I had {{ .num_coffees}} coffees today.
{{ if gt .num_coffees 3 }}
This was too much
{{end}}
{{ if and (gt .num_coffees 3) (lt .num_coffees 10) }}
This was too much
{{end}}
KrakenD will set variable for your template automatically depending on where the template is used
Debug and print context as JSON structure using toJson
Create variable (using $)
Conditionals
Loops Array
FC_ENABLE: Switch on the flexible configuration
FC_OUT: Writed the result
FC_TEMPLATES: Directory with the sub templates you will call from the master template
FC_SETTINGS: Directory where you store environment configuration and other settings
FC_PARTIALS: Directory where you store snippets of text that you can inject into templates without being evaluated
{
"$schema":"https://www.krakend.io/schema/krakend.json",
"version": 3,
"name": "A simple config"
}
docker run --rm -it -v "$PWD:/etc/krakend" -p "8080:8080" -e "FC_ENABLE=1" -e "FC_OUT=out.json" devopsfaith/krakend:watch run -c krakend.tmpl
# Give a write permission to output file
sudo chown $USER out.json
krakend.json
cli
{
"$schema":"https://www.krakend.io/schema/krakend.json",
"version": 3,
"name": "A simple config"
}
version: "3"
services:
krakend:
image: devopsfaith/krakend
volumes:
- .:/etc/krakend
ports:
- "8080:8080"
environment:
- FC_ENABLE=1
- FC_SETTINGS=config/settings/prod
- FC_PARTIALS=config/partials
- FC_TEMPLATES=config/templates
- FC_OUT=out.json
- SERVICE_NAME=KrakenD API Gateway
command: [ "run", "-dc", "krakend.tmpl", "" ]
krakend.json
docker-compose.yaml
{
"$schema":"https://www.krakend.io/schema/v3.json",
"version": 3,
"host": ["http://api.github.com"],
"endpoints": [
{
"endpoint": "/users/{id}",
"backend": [
{
"url_pattern": "/users/{id}",
"group": "fathi"
},
{
"url_pattern": "/users/hafizan",
"group": "hafizan"
}
]
}
]
}
KrakenD is not designed as a reverse proxy but as an API Gateway that acts as a decoupling layer between the client and microservices
Allows response from the backend to be returned directly to the client without any modification or parsing by the gateway. It behaves like a regular proxy, preserving the original status codes and headers
Useful in cases where direct interaction between the client and backend is required, such as setting cookies or performing write operations like file uploads
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3,
"host": [ "https://api.github.com" ],
"endpoints":[
{
"endpoint": "/default",
"@comment": "The body is parsed by KrakenD and headers are the ones from KrakenD",
"backend": [{
"url_pattern": "/status"
}]
},
{
"endpoint": "/no-op",
"output_encoding": "no-op",
"@comment": "Content and headers are the ones provided by the backend directly",
"backend": [{
"encoding": "no-op",
"url_pattern": "/status"
}]
}
]
}
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3,
"port": 8080,
"host": ["http://backend:8080"],
"endpoints": [{
"endpoint": "/hotel/{id}",
"extra_config": {
"proxy": {
"sequential": true
}
},
"backend": [{
"@comment": "The first call fields have its response under resp0_xxx",
"url_pattern": "/hotels/{id}.json"
},
{
"@comment": "Second call fields have its response under resp1_xxx, we could add more chained backends",
"url_pattern": "/calendar/{resp0_calendar_id}.json"
}
]
},
{
"endpoint": "/hotel/failing/{id}",
"extra_config": {
"proxy": {
"sequential": true
}
},
"backend": [{
"@comment": "The first call fields have its response under resp0_xxx",
"url_pattern": "/hotels/{id}.json"
},
{
"@comment": "The requested attribute does not exist, so we can't fetch the data",
"url_pattern": "/calendar/{resp0_unexisting_field}.json"
}
]
}
]
}
Encoding is referring to data format you will find in your upstream responses and the format you want to deliver to API consumers
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3,
"host": [
"http://107.155.65.148:5000"
],
"endpoints": [
{
"endpoint": "/xml",
"output_encoding": "xml",
"@comment": "Backend is json but client receives XML",
"backend": [
{
"url_pattern": "/index.php",
"encoding": "json"
}
]
},
{
"endpoint": "/collection",
"output_encoding": "json",
"@comment": "The backend is a JSON collection [], not an object {}, and by default encapsulated in a 'collection' object",
"backend": [
{
"is_collection": true,
"url_pattern": "/index.php?collection=true",
"encoding": "json"
}
]
},
{
"endpoint": "/safe-collection",
"output_encoding": "json",
"@comment": "KrakenD looks if the 'is_collection' is needed or not.",
"backend": [
{
"url_pattern": "/index.php?collection=true",
"encoding": "safejson",
"mapping": {
"collection": "SOMETHING_ELSE"
}
}
]
},
{
"endpoint": "/collection-as-it-was",
"output_encoding": "json-collection",
"@comment": "The backend is a JSON collection [], not an object {}, and is returned as such",
"backend": [
{
"is_collection": true,
"url_pattern": "/index.php?collection=true",
"encoding": "json"
}
]
},
{
"endpoint": "/negotiate",
"output_encoding": "negotiate",
"backend": [
{
"url_pattern": "/index.php",
"encoding": "json"
}
]
},
{
"endpoint": "/string",
"output_encoding": "string",
"backend": [
{
"encoding": "string",
"host": [
"https://www.google.com"
],
"url_pattern": "/"
}
]
},
{
"endpoint": "/string-in-object",
"output_encoding": "json",
"backend": [
{
"encoding": "string",
"host": [
"https://www.google.com"
],
"url_pattern": "/"
}
]
}
]
}
The client get all the status code, the headers and the error body
KrakenD return a 500 status code, no body and none of the response header
KrakenD do this by default because client must completely decoupled from their underlying services. When API is protected by API Gateway, we should not return back an implementation detail. In the same way we wouldn't return an implementation detail to the client from the application.
404
Requested endpoint does not exist
400
Bad Request. i.e: failed JSON schema validation of the body
401
Unauthorized: Invalid JWT Token
403
Forbidden access
429
Too many requests. Reach the rate limit for the endpoint
503
Service Unavailable. Reached global rate limit for the endpoint
{
"version": 3,
"$schema": "https://www.krakend.io/schema/krakend.json",
"debug_endpoint": true,
"endpoints": [
{
"endpoint": "/ok",
"backend": [
{
"host": ["https://api.github.com"],
"url_pattern": "/status"
}
]
},
{
"endpoint": "/epic-fail",
"backend": [
{
"@comment": "Request to a URL that will produce a 404",
"host": ["http://google.com"],
"url_pattern": "/this-url-likely-does-not-exist"
}
]
},
{
"endpoint": "/mixed",
"backend": [
{
"host": ["https://api.github.com"],
"url_pattern": "/status"
},
{
"@comment": "Request to a URL that will produce a 404",
"host": ["http://google.com"],
"url_pattern": "/this-url-likely-does-not-exist"
}
]
}
]
}
{
"version": 3,
"$schema": "https://www.krakend.io/schema/krakend.json",
"@comment": "Preserve the status code of a single backend",
"extra_config": {
"router": {
"return_error_msg": true
}
},
"endpoints": [
{
"endpoint": "/interpretation-bad-status",
"backend": [
{
"@comment": "Request to a URL that will produce a 404, which is not a returnable status code",
"host": ["http://google.com"],
"url_pattern": "/this-url-likely-does-not-exist"
}
]
},
{
"endpoint": "/interpretation-bad-encoding",
"backend": [
{
"@comment": "Request a valid URL, but with the wrong encoding parsing",
"host": ["http://google.com"],
"url_pattern": "/"
}
]
}
]
}
Show the interpretation of the error but not the error of the backend
{
"version": 3,
"$schema": "https://www.krakend.io/schema/krakend.json",
"@comment": "Preserve the status code of a single backend",
"endpoints": [
{
"endpoint": "/details",
"backend": [
{
"extra_config": {
"backend/http": {
"return_error_details": "error_from_google"
}
},
"@comment": "Request to a URL that will produce a 404",
"host": ["http://google.com"],
"url_pattern": "/this-url-likely-does-not-exist"
}
]
}
]
}
Revealing error details to the client. Using return_error_details, all status codes returned to the client are 200. The client must parse the response for the presence of the error_backend_alias or any other key we have set to determine if there’s a problem
{
"version": 3,
"$schema": "https://www.krakend.io/schema/krakend.json",
"@comment": "Preserve the status code of a single backend",
"endpoints": [
{
"endpoint": "/preserve-404",
"backend": [
{
"extra_config": {
"backend/http": {
"return_error_code": true
}
},
"@comment": "Request to a URL that will produce a 404",
"host": ["http://google.com"],
"url_pattern": "/this-url-likely-does-not-exist"
}
]
}
]
}
When we have one backend only and use an encoding different than no-op
Zero-trust security
KrakenD is an API Gateway with a zero-trust security policy, and when it comes to forward query strings, cookies, and headers, we need to define what is allowed.
Part of the zero-trust policy implies that KrakenD does not forward any unexpected query string, headers, or cookies
input_query_strings
Query strings reaching backends
input_headers
Headers reaching backends
case-sensitive
case-insensitive
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3,
"echo_endpoint": true,
"@comment": "All examples use as backend KrakenD itself",
"host": [ "http://localhost:8080" ],
"endpoints":[
{
"endpoint": "/default",
"@comment": "The backend does not receive any header, query string or cookie from the client",
"backend": [{
"url_pattern": "/__echo/"
}]
},
{
"endpoint": "/known-params",
"input_headers": ["Accept"],
"input_query_strings": ["q","a[]" ],
"@comment": "The backend receives a controlled set of parameters, but discards unknown sets",
"backend": [{
"url_pattern": "/__echo/"
}]
},
{
"endpoint": "/all",
"input_headers": ["*"],
"input_query_strings": ["*" ],
"@comment": "The backend receives all parameters from client. NOT RECOMMENDED.",
"backend": [{
"url_pattern": "/__echo/"
}]
},
{
"endpoint": "/mandatory/{id}",
"input_query_strings": ["optional" ],
"@comment": "The backend receives always the mandatory {id} and the optional one only when sent.",
"backend": [{
"url_pattern": "/__echo/?id={id}"
}]
}
]
}
Automatically merges all responses from all backends in a final response
Aggregation
Wrap response of a backend inside a new object
Grouping
Targetting
Mapping
Mapping
Filtering
Mapping
Flatmap
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3,
"echo_endpoint": true,
"debug_endpoint": true,
"@comment": "All examples use as backend KrakenD itself",
"host": [
"http://107.155.65.148:5002"
],
"endpoints": [
{
"endpoint": "/aggregation",
"backend": [
{
"url_pattern": "/users/alice.json"
},
{
"url_pattern": "/users/bob.json"
}
]
},
{
"endpoint": "/group",
"backend": [
{
"url_pattern": "/users/alice.json",
"group": "alice"
},
{
"url_pattern": "/users/bob.json",
"group": "bob"
}
]
},
{
"endpoint": "/target",
"backend": [
{
"url_pattern": "/users/alice.json",
"target": "data.user"
}
]
},
{
"endpoint": "/mapping",
"backend": [
{
"url_pattern": "/users/bob.json",
"mapping": {
"data": "my_response",
"status": "result"
}
}
]
},
{
"endpoint": "/deny",
"backend": [
{
"url_pattern": "/users/bob.json",
"deny": [
"data"
]
}
]
},
{
"endpoint": "/allow",
"backend": [
{
"url_pattern": "/users/bob.json",
"allow": [
"data.user.name",
"data.user.city"
]
}
]
},
{
"endpoint": "/flatmap/object",
"backend": [
{
"url_pattern": "/users/alice.json",
"extra_config": {
"proxy": {
"flatmap_filter": [
{ "type": "move", "args": ["data.user","details"] },
{ "type": "move", "args": ["details.name","name"] },
{ "type": "del","args": ["status", "data"] }
]
}
}
}
]
},
{
"endpoint": "/flatmap/collection",
"backend": [
{
"url_pattern": "/numbers.json",
"extra_config": {
"proxy": {
"flatmap_filter": [
{
"type": "del",
"args": ["numerals.0"]
},
{
"type": "move",
"args": ["numerals.*.numeral", "numerals.*.number"]
},
{
"type": "move",
"args": ["numerals.*.english", "numerals.*.name"]
},
{
"type": "del",
"args": ["numerals.*.spanish"]
},
{
"type": "move",
"args": ["numerals", "numbers"]
}
]
}
}
}
]
}
]
}
Inject static content in the request & responses of a backend through a simple DSL definition in config file
We can inject data in requests and responses using the Martian component as long as it’s static data, hardcoded in the configuration. It does not allow us to place {variables} inside the modifiers
Use Martian whenever we need to alter the request or response based on criteria with static values.
Modifiers
Filters
Groups
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3,
"echo_endpoint": true,
"debug_endpoint": true,
"@comment": "All examples use as backend KrakenD itself",
"host": [
"http://localhost:8080"
],
"endpoints": [
{
"endpoint": "/header.Modifier",
"output_encoding": "no-op",
"backend": [
{
"host": ["http://localhost:8080"],
"url_pattern": "/__echo/header.Modifier",
"extra_config": {
"modifier/martian": {
"header.Modifier": {
"scope": ["request","response"],
"name": "User-Agent",
"value": "Late-Night-Commander v2.3"
}
}
}
}
]
},
{
"endpoint": "/body.Modifier",
"backend": [
{
"url_pattern": "/__debug/body.Modifier",
"extra_config": {
"modifier/martian": {
"body.Modifier": {
"scope": [
"request",
"response"
],
"@comment": "Send a {\"msg\":\"you rock!\"}",
"body": "eyJtc2ciOiJ5b3Ugcm9jayEifQ=="
}
}
}
}
]
},
{
"endpoint": "/header.RegexFilter",
"input_headers": [
"X-App-Version"
],
"backend": [
{
"url_pattern": "/__echo/header.RegexFilter",
"allow": ["req_uri"],
"extra_config": {
"modifier/martian": {
"header.RegexFilter": {
"scope": [
"request"
],
"header": "X-App-Version",
"regex": ".*-(alpha|beta|preview)$",
"modifier": {
"querystring.Modifier": {
"scope": [
"request"
],
"name": "testing",
"value": "1"
}
}
}
}
}
}
]
},
{
"endpoint": "/fifo.Group",
"output_encoding": "no-op",
"backend": [
{
"url_pattern": "/__echo/fifo.Group",
"extra_config": {
"modifier/martian": {
"fifo.Group": {
"scope": [
"request",
"response"
],
"aggregateErrors": true,
"modifiers": [
{
"body.Modifier": {
"scope": [
"request"
],
"body": "eyJtc2ciOiJ5b3Ugcm9jayEifQ=="
}
},
{
"header.Modifier": {
"scope": [
"request",
"response"
],
"name": "X-Additional-Header",
"value": "true"
}
}
]
}
}
}
}
]
}
]
}
JSON Schema is a declarative language that allows us to validation JSON documents
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3,
"port": 8080,
"host": ["http://127.0.0.1:8080"],
"echo_endpoint": true,
"extra_config": {
"router": {
"return_error_msg": true
}
},
"endpoints": [
{
"endpoint": "/user",
"method": "POST",
"extra_config": {
"validation/json-schema": {
"$schema": "http://json-schema.org/draft-07/schema",
"required": ["name", "age"],
"properties": {
"age": {
"type": "number"
},
"name": {
"type": "string"
},
"pronoun": {
"type": "string",
"enum": [
"she/her/hers",
"he/him/his",
"they/them/theirs",
"ze/hir/hirs",
"no pronoun",
"no preference",
"other"
]
}
}
}
},
"backend": [
{
"url_pattern": "/__echo/",
"allow": ["req_body"]
}
]
}
]
}
An industry standard to represent claims securely between two parties
Caching allows us to store backend responses in memory to reduce the number of calls a user sends to the origin, reducing the network traffic and alleviating the pressure on your services.
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3,
"host": [ "http://localhost:8080" ],
"debug_endpoint": true,
"cache_ttl": "1h",
"endpoints": [
{
"endpoint": "/one",
"cache_ttl": "1s",
"backend": [
{
"url_pattern": "/__debug/one"
}
]
},
{
"endpoint": "/two",
"backend": [
{
"host": ["https://api.github.com"],
"url_pattern": "/orgs/krakendio",
"extra_config": {
"qos/http-cache": {
"shared": true
},
"modifier/martian": {
"header.Modifier": {
"scope": ["response"],
"name": "Cache-Control",
"value": "max-age=3600, public",
"@comment": "Change the max-age policy before KrakenD checks it for caching."
}
}
}
}
]
}
]
}
Controlling waiting times is crucial because KrakenD connect with many services
The user will receive an HTTP status code 500 Internal Server Error when there is no content to return
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3,
"port": 8080,
"timeout": "1s",
"host": [
"http://107.155.65.148:5003"
],
"endpoints": [
{
"endpoint": "/fast",
"backend": [
{
"url_pattern": "/speedy/"
}
]
},
{
"endpoint": "/semi-slow",
"timeout": "100ms",
"backend": [
{
"@comment": "This one takes over 100ms",
"url_pattern": "/delayed/"
},
{
"url_pattern": "/speedy/"
}
]
},
{
"endpoint": "/slow",
"timeout": "100ms",
"backend": [
{
"@comment": "This one takes over 100ms",
"url_pattern": "/delayed/"
}
]
}
]
}
While we increase the load the backends, we will improve our client's response time and error rate
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3,
"port": 8080,
"timeout": "1s",
"host": [
"http://107.155.65.148:5004"
],
"endpoints": [
{
"endpoint": "/error-10",
"concurrent_calls": 3,
"backend": [
{
"url_pattern": "/error-10"
}
]
},
{
"endpoint": "/error-50",
"concurrent_calls": 3,
"backend": [
{
"url_pattern": "/error-50"
}
]
},
{
"endpoint": "/flaky",
"concurrent_calls": 3,
"backend": [
{
"url_pattern": "/flaky"
}
]
}
]
}
Protect infrastructure from abusive actions, mitigate cascade failures, and control the overall API usage
Rate limiting is also compliment other traffic management technique such as Circuit-breaker, bot detector and service discovery
max_rate: Applies simultaneously to all clients using the endpoint, sharing a unique counter
client_max_rate: Sets a counter to each individual user
Both types can coexist and they complement each other, and store the counters in-memory
When do bucket is empty, they have to wait until the bucket is refilled again with the tokens.
The max_rate and client_max_rate define how many tokens it will refill every second
{
"version": 3,
"$schema": "https://www.krakend.io/schema/krakend.json",
"host": ["http://localhost:8080"],
"debug_endpoint": true,
"endpoints": [
{
"endpoint": "/r1",
"extra_config": {
"qos/ratelimit/router": {
"client_max_rate": 1,
"client_capacity": 5,
"strategy": "header",
"key": "Authorization",
"max_rate": 100
}
},
"backend": [
{
"url_pattern": "/__debug/ep",
"extra_config": {
"qos/ratelimit/proxy": {
"capacity": 3,
"max_rate": 3
}
}
}
]
}
]
}
Error must be consecutive or the counter will be reset
Text
The Circuit Breaker is a straightforward state machine in the middle of the request and response that monitors all your backend failures. When they reach a configured threshold, the circuit breaker will prevent sending more traffic to a failing backend alleviating its pressure under challenging conditions
Text
The backend wont be contacted again until it passes the timeout that we set
When the timeout window passes, it will allow one single request to pass to test it
Text
If it fails, it will retry again after another timeout window
If the request passes, all traffic resumes normally
Text
{
"$schema": "https://www.krakend.io/schema/krakend.json",
"version": 3,
"host": [ "http://107.155.65.148:5005" ],
"endpoints": [
{
"endpoint": "/cb",
"backend": [
{
"url_pattern": "/fail-fifty-percent",
"extra_config": {
"qos/circuit-breaker": {
"log_status_change": true,
"name": "the fifty percent trouble maker",
"interval": 60,
"max_errors": 2,
"timeout": 5
}
}
}
]
}
]
}
Text
http://localhost:8080/__health
{
"version": 3,
"$schema": "https://www.krakend.io/schema/krakend.json",
"extra_config": {
"router": {
"logger_skip_paths": ["/health"],
"health_path": "/health",
"disable_health": false
}
}
}
{
"version": 3,
"$schema": "https://www.krakend.io/schema/krakend.json",
"extra_config": {
"telemetry/logging": {
"level": "DEBUG",
"stdout": true,
"syslog": false,
"prefix": "[KRAKEND]"
},
"router": {
"disable_access_log": false,
"logger_skip_paths":["/__health"]
}
}
}
Push log to log monitoring tools
Monitor request and response time, memory consumption and other vital information to understand the performance of the gateway
Gain insight into the flow of requests as they propagate through different services in a distributed system, from the user request to the gateway response
grafana:
image: grafana/grafana:9.1.2
ports:
- "4000:3000"
volumes:
- "./config/grafana/datasources/all.yml:/etc/grafana/provisioning/datasources/all.yml"
- "./config/grafana/dashboards/all.yml:/etc/grafana/provisioning/dashboards/all.yml"
- "./config/grafana/krakend:/var/lib/grafana/dashboards/krakend"
influxdb:
image: influxdb:1.8.10
environment:
- "INFLUXDB_DB=krakend"
- "INFLUXDB_USER=krakend-dev"
- "INFLUXDB_USER_PASSWORD=pas5w0rd"
- "INFLUXDB_ADMIN_USER=admin"
- "INFLUXDB_ADMIN_PASSWORD=supersecretpassword"
ports:
- "8086:8086"
jaeger:
image: jaegertracing/all-in-one:1
ports:
- "16686:16686"
- "14268:14268"
elasticsearch:
image: elasticsearch:8.4.1
environment:
- "discovery.type=single-node"
- "xpack.security.enabled=false"
- "xpack.security.transport.ssl.enabled=false"
- "xpack.security.http.ssl.enabled=false"
- "ES_JAVA_OPTS=-Xms1024m -Xmx1024m"
ports:
- "19200:9200"
- "9300:9300"
kibana:
image: kibana:8.4.1
ports:
- "5601:5601"
logstash:
image: logstash:8.4.1
ports:
- "12201:12201/udp"
- "5044:5044"
environment:
- "xpack.monitoring.elasticsearch.url=http://elasticsearch:9200"
volumes:
- ./config/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf
command: ["-f", "/usr/share/logstash/pipeline/logstash.conf"]
docker-compose.yaml
"sequential_start": true,
"extra_config": {
"telemetry/metrics": {
"collection_time": "30s",
"listen_address": ":8090"
},
"telemetry/influx": {
"address": "http://influxdb:8086",
"ttl": "25s",
"buffer_size": 100,
"username": "krakend-dev",
"password": "pas5w0rd"
},
"telemetry/logging": {
"level": "DEBUG",
"prefix": "[KRAKEND]",
"syslog": false,
"stdout": true
},
"telemetry/gelf": {
"address": "logstash:12201",
"enable_tcp": false
},
"telemetry/opencensus": {
"sample_rate": 100,
"reporting_period": 1,
"enabled_layers": {
"backend": true,
"router": true
},
"exporters": {
"jaeger": {
"endpoint": "http://jaeger:14268/api/traces",
"service_name": "krakend"
}
}
},
"security/cors": {
"allow_origins": ["*"],
"allow_methods": ["POST", "GET"],
"allow_headers": ["Origin", "Authorization", "Content-Type"],
"expose_headers": ["Content-Length"],
"max_age": "12h"
}
}
krakend.json
Your feedback matters
There are no secrets to success. It is the result of preparation, hard work, and learning from failure. - Colin Powell