This example shows a simple Controller which reacts on a certain annotation given on services.
This controller is the poor men’s version of Fabric8’s expose-controller.
It watches the Kubernetes API for new Service
and for each service with an annotation expose=/path
it will create a new Ingress
object for this service, matching on the given path.
If an ingress object already exists for this service, then nothing will be done.
Also, no ingress gets removed when a Service
is removed.
For a full explanation of how this controller works, please refer to the "Controller" pattern in our book. Note, that this is example is meant for educational purposes only and is not suitable for general purpose usage.
The easiest way to try this example is by using minikube with an ingress controller enabled:
# Start minikube and enable the ingress addon
minikube start
minikube addons enable ingress
The controller script itself is stored in a ConfigMap
and can be easily edited later on:
# Create a configmap holding the controller shell script:
kubectl create configmap expose-controller-script --from-file=./expose-controller.sh
In order to deploy the controlller a Deployment
creates a pod with two containers:
-
One Kubernetes API proxy which exposes the Kubernetes API on localhost with port 8001. The image for
k8spatterns/kubeapi-proxy
is defined in this Dockerfile. -
The main container which executes the script from the configmap. It is based on a single Alpine base image with curl and jq included. The Dockerfile for this image
k8spattern/curl-jq
can be found here.
To create this deployment just call:
# Create the controller object:
kubectl create -f expose-controller.yml
You might want to have a look at the descriptor file; it contains some useful comments along the way.
That’s all.
Now you have a nice little Controller which watches on Services
and reacts based on given annotations.
To try it out, we are reusing the simple web application from the Sidecar example.
It is slightly modified as we are adding an annotation expose: /mdn
and mount the git sync HTML files to an mdn
directory so that the application serves these below a context /mdn
.
Before applying the following descriptors, it is recommended to start a tail on the controller pod’s log with kubectl logs -f expose-controller-… expose-controller
.
This command will show the events received by the controller as they come in.
The create the web application itself:
# Create a sample web application with an 'expose' annotation:
kubectl create -f web-app.yml
To verify that indeed an ingress object is created, try:
# Check that an ingress has been created
kubectl get ingress web-app -o yaml
Finally, let’s point our browser to the exposed ingress by
# Open Ingress route
open https://$(minikube ip)/mdn
(open
works nicely on macOS, for other operating systems, just open manually the URL https://$(minikube ip)/mdn
)
This example uses two straightforward Docker images which you can find in the subdirectories:
-
k8spatterns/curl-jq which is an alpine Image with curl and jq added
-
k8spatterns/kubeapi-proxy is an alpine Linux with a local
kubectl
installed andkubectl proxy
started with the proper CA and token mounted. The original version kubectl-proxy is from Marko Lukša who introduced this proxy in his awesome book Kubernetes in Action. Highly recommended!