This project provides a simple REST service that can be deployed to any Kubernetes cluster
that reports whether or not a host
exists in any Ingress
deployed to that cluster.
Its important that this API does not report on the health of any given Ingress
host
but specifically whether or not ANY Ingress
currently exists on the cluster where kubernetes-ingress-info
is deployed, regardless of if its backend is actually up. It is intended to be a very lightweight and open
endpoint to interrogate for this status.
This tool was specifically developed to serve as a endpoint for various cloud load-balancers
and DNS services to be able to auto-detect which Kubernetes clusters are valid for a specific host
FQDN.
This can aid in workload migration across various clusters or just enable workloads to be deployed to subsets
of clusters out of many organizational clusters, while letting upstream DNS and or glsb based devices react
accordingly as many of these platforms rely on simple HTTP 200 OK type of "checks".
This tool was specifically developed to serve as a endpoint for various cloud load-balancers
and DNS services to be able to auto-detect which Kubernetes clusters are valid for a specific host
FQDN.
Lets say you have two apps available at a.b.com and x.y.com and you have 3 available Kubernetes
it could potentially be deployed on, clusterA, clusterB and clusterC. Generally upstream from your cluster LoadBalancers
you will have another cloud load balancer device or you are just using some sort of DNS device to control what cluster LoadBalancer IPs are relevant for each application at any given time. So what you can do in this case is list all possible cluster IPs as possible targets for those FQDNs hostname, but enable/disable them based on calls to kubernetes-ingress-info
which
resides on all clusters. For this to work, you should ensure each possible target cluster Ingress Controller
that is behind a LoadBalancer
has kubernetes-ingress-info
accessible via its own unique Ingress
.
Helm chart:
https://github.com/boarder981/k8s-ingress-info
Run via Docker:
https://hub.docker.com/r/bitsofinfo/kubernetes-ingress-info
Otherwise:
Python 3.6+
Kubernetes version 1.19+
Dependencies: See Dockerfile
When deploying to a Kubernetes cluster the Pod
that kubernetes-ingress-info
is
deployed as needs to run as a serviceAccount
with (at a minimum) a binding to a
[Cluster]Role
with the following RBAC permissions:
...
rules:
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["list"]
This example will install kubernetes-ingress-info
onto a Kubernetes cluster.
The example.yaml creates a Namespace
, ServiceAccount
with RBAC bindings, a Deployment
, Service
and an Ingress
bound to host: kubernetes-ingress-info.local
.
The ServiceAccount
has the ability to list
all ingresses
on a cluster. You can modify
and install to your cluster however you see fit.
kubectl apply -f examples/example.yaml
Once installed, you will need a /etc/hosts
entry or DNS setup for kubernetes-ingress-info.local
to
point to the LoadBalancer
configured for whatever IngressController
consumed the example Ingress
in example.yaml
Let's hit the root to get a list of all Ingress
"hosts" on the cluster.
curl http://kubernetes-ingress-info.local
[
"kubernetes-ingress-info.local",
....
]
Validate the existence of a single host
, will return a 200
curl http://kubernetes-ingress-info.local/kubernetes-ingress-info.local
{
"info": "'kubernetes-ingress-info.local' found"
}
How about one that does not exist? (returns a 404)
curl http://kubernetes-ingress-info.local/non-existant-host.com
{
"error": "'non-existant-host.com' 404 not found"
}
Cleanup:
kubectl delete -f examples/example.yaml
The API is as follows:
GET all Ingress Hosts on the cluster:
curl -X GET http[s]://[kubernetes-ingress-info]
GET a specific host
. Returns 200 if host
exists, or a 404 if non-existant
curl -X GET http[s]://[kubernetes-ingress-info]/[host]
Note that if you startup info.py
with the --host-match-on-header <headername>
value, the named HTTP request header
will be checked for a host
. This host
name will then be used if the /<path>
host is not found
GET a specific host
(via custom header). Returns 200 if host
exists, or a 404 if non-existant
curl -X GET http[s]://[kubernetes-ingress-info]/anything -H '<--host-match-on-header header name>: [host]'
If you enable caching w/ --enable-cache
the internal Ingress database that is constructed
after fetching all available Ingress
from Kubernetes (and applying all specified selectors)
is cached to disk. The cache structure is a single key that stores the entire dictionary to
local disk. If running in a container this should have minimal storage requirements and
does not necessitate a dedicated volume.
We currently use the https://github.com/grantjenks/python-diskcache library due to its get
speed
and active project activity.
bash-4.4$ python3 info.py -h
usage: info.py [-h] [-r LOAD_CONFIG_MODE] [-i INCLUDE_LABEL_SELECTORS]
[-x EXCLUDE_LABEL_SELECTORS] [-n NAMESPACES]
[-m HOST_MATCH_ON_HEADER] [-p LISTEN_PORT] [-c]
[-e CACHE_TTL_SECONDS] [-d CACHE_DIR] [-l LOG_LEVEL]
[-b LOG_FILE]
optional arguments:
-h, --help show this help message and exit
-r LOAD_CONFIG_MODE, --load-config-mode LOAD_CONFIG_MODE
How the target k8s cluster config will be loaded,
'local' will leverage the current kubectl context from
'~/.kube/config', while 'cluster' will talk direct to
the cluster the process is executing in using the
Pod's configured serviceAccount which needs read
access to all objects of type Ingress. Default 'local'
-i INCLUDE_LABEL_SELECTORS, --include-label-selectors INCLUDE_LABEL_SELECTORS
Optional comma delimited of Ingress
label1=value,label2=value pairs that will be used to
build the database of IngressInfo objects available to
be fetched. If specified, ONLY Ingress objects having
ALL specified labels will be retrieved. If not
specified, ALL available Ingress objects will be
retrieved from k8s. Excludes take precendence over
includes.
-x EXCLUDE_LABEL_SELECTORS, --exclude-label-selectors EXCLUDE_LABEL_SELECTORS
Optional comma delimited of Ingress
label1=value,label2=value pairs that will be used to
restrict the database of IngressInfo objects available
to be fetched. If specified, ONLY Ingress objects NOT
having ANY of the specified labels will be retrieved.
If not specified, ALL available Ingress objects will
be retrieved from k8s. Excludes take precendence over
includes.
-n NAMESPACES, --namespace NAMESPACES
Optional comma delimited of Namespaces to scope
Ingress fetch within
-m HOST_MATCH_ON_HEADER, --host-match-on-header HOST_MATCH_ON_HEADER
Optional name of HTTP Request header who's value will
be inspected for an Ingress host match, should the
default path based /[host] not find a match.
-p LISTEN_PORT, --listen-port LISTEN_PORT
Port to listen on, default 8081
-c, --enable-cache Optional, enabling caching (uses
https://github.com/grantjenks/python-diskcache)
-e CACHE_TTL_SECONDS, --cache-ttl-seconds CACHE_TTL_SECONDS
Optional, cache TTL in seconds
-d CACHE_DIR, --cache-dir CACHE_DIR
Optional, cache dir, default /opt/kubernetes-ingress-
info/cache
-l LOG_LEVEL, --log-level LOG_LEVEL
log level, default DEBUG
-b LOG_FILE, --log-file LOG_FILE
Path to log file, default None, STDOUT