king-rules
is short for Kubernetes INGress Rules.
Dynamically creates ingress' rules based on service annotations.
This came out of a desire to deploy development branches in kubernetes WITHOUT creating a new ingress ALL THE TIME. Creating it requires time to provision a cloud specific load balancer and that can take minutes to become active and accept traffic. And incur in extra costs.
Instead we re-use the same ingress and just attach new rules as needed.
We assume that each service will respond to its own subdomain (the host
setting in the ingress' rule). Using wildcards at the DNS and LB
certificate levels, one can expose these services in subdomains faster.
I drew inspiration from https://github.com/hxquangnhat/kubernetes-auto-ingress but that code creates a new ingress for each seervice every time, which is exactly what we're trying to avoid here.
In the minimal usage, you need to specify these 2 annotations in your service:
king-rules/name: dominion
king-rules/host: echo.example.com
When you deploy this service, the ingress dominion
will get a new
rule, with the format:
- http:
host: echo.example.com
paths:
- backend:
serviceName: {{ service.Name }}
servicePort: {{ service.Ports[0].Port }}
Note that you need to have the ingress created previously as this code will not do that for you. Otherwise, it would defeat the purpose of this repo. This simplifies this code and you can provision it exactly the way you need it.
apiVersion: apps/v1
kind: Deployment
metadata:
name: king-rules
spec:
selector:
matchLabels:
app: king-rules
replicas: 1
template:
metadata:
labels:
app: king-rules
spec:
containers:
- name: king-rules
image: jpedrob/king-rules
imagePullPolicy: Always
env:
- name: LOG_LEVEL
value: debug
# Required as this info is not passed on to the container
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
Now you can start tailing the logs for the deployed king-rules
pod:
kubectl logs -f $(kubectl get pods -o name -l app=king-rules)
Now, create the dominion
ingress that will hold the rules that will be
updated as services come and go:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: dominion
annotations:
kubernetes.io/ingress.class: "ingress-alb"
alb.ingress.kubernetes.io/scheme: internal
alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:eu-west-1:xxx:certificate/xxx"
alb.ingress.kubernetes.io/backend-protocol: HTTP
alb.ingress.kubernetes.io/healthcheck-path: /
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
spec:
rules:
- http:
paths:
- backend:
serviceName: ssl-redirect
servicePort: use-annotation
path: /*
- backend:
serviceName: fallback
servicePort: 80
Using a deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo
spec:
selector:
matchLabels:
app: echo
replicas: 1
template:
metadata:
labels:
app: echo
spec:
containers:
- name: echo
image: jpedrob/echo:v0.1.0
imagePullPolicy: Always
env:
- name: TEST_SUBDOMAIN
value: echo.example.com
Finally, create the service that uses those 2 annotations:
apiVersion: v1
kind: Service
metadata:
name: echo
labels:
app: echo
annotations:
king-rules/name: dominion
king-rules/host: echo.example.com
spec:
type: NodePort
selector:
app: echo
ports:
- name: http
port: 80
targetPort: http
Check that the new service was attached to a new rule:
$ kubectl get ingress dominion -o yaml
-
Support and scan all services ports
-
Check king-rules service account permissions
-
Support the
networking.k8s.io/v1
apiGroup, not justextensions/v1beta1
. -
Support comma-separated hosts in the
king-rules/host
. -
Support comma-separated paths in the
king-rule/path: /xxx
.
The combination of host, service ports and paths will create a matrix
host x port x path
of []HTTPIngressPath
.