Configuring a KinD cluster with nginx ingress and Tekton components
5 min read
A bit of background
I have an interest in learning more about writing software, learning Golang, and contributing to open source. Over the last few weeks, from a suggestion by Marky Jackson, I've decided to get involved with Project Sigstore. In doing so, I've learned about Tekton, and have decided to include that in my learning toolkit. Tekton is comprised of a few major parts, one of which is the
Dashboard. Since Tekton is cloud native, it runs entirely within a Kubernetes cluster. Many of the docs for Tekton and, if I'm not mistaken, Sigstore, mention the use of Kubernetes in Docker, also known as KinD. KinD was new to me, so I spent some time this week working to get it configured and ready for use. If you're not familiar with KinD, I included a link, but it's a means to running a Kubernetes cluster on your local machine by doing so inside of Docker. Docker can be installed on Linux, Mac, and Windows.
There may be other configurations supported by the tools mentioned here, but I have not explored them. If you are using Podman instead of Docker, I do believe KinD supports running clusters in there as well.
Areas of focus for this post
- Installing and configuring KinD
- Deploying Tekton:
- Installing and configuring ingress-nginx
Installing and Configuring KinD
I'm assuming you have Docker installed, if not please visit the Docker installation documentation here
I'm using my Mac at the moment, so to install with homebrew we execute:
brew install kind
You can see other installation instructions for Windows and Linux here
In order to install and make use of the ingress controller, we need to create a cluster using kind with a particular configuration. We will reference a
YAML configuration that includes
extraPortMappings that allows us to expose port
443. The below configuration is the one I used. The KinD documentation mentions if you're not using Linux to include the
listenAddress value to send traffic from your machine to the node.
This creates a cluster called
tekton-cluster. You can change the name to fit what you would like.
cat <<EOF | kind create cluster --name tekton-cluster --config=- kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane kubeadmConfigPatches: - | kind: InitConfiguration nodeRegistration: kubeletExtraArgs: node-labels: "ingress-ready=true" extraPortMappings: - containerPort: 80 hostPort: 80 protocol: TCP listenAddress: "127.0.0.1" - containerPort: 443 hostPort: 443 protocol: TCP listenAddress: "127.0.0.1" EOF
After running the above, you should have output that looks like this:
Creating cluster "tekton-cluster" ... ✓ Ensuring node image (kindest/node:v1.21.1) 🖼 ✓ Preparing nodes 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 Set kubectl context to "kind-tekton-cluster" You can now use your cluster with: kubectl cluster-info --context kind-tekton-cluster Have a nice day! 👋
Deploying the Tekton components is pretty straight forward, we're just going to run the following commands. Now, I'm using Tekton because it's what I am currently working on, but you can follow along with a different application or even a demo app.
Install Tekton Pipelines
kubectl apply \ --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
Install Tekton Triggers
kubectl apply \ --filename https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
I did run into an issue when running this config where I got a
connection refusederror during install. I reran the command a couple times and it eventually was successful. I haven't dug in here, but wanted to note if you see the same thing.
Install Tekton Dashboard
kubectl apply \ --filename https://storage.googleapis.com/tekton-releases/dashboard/latest/tekton-dashboard-release.yaml
All three of these should now be successfully installed. If we run
kubectl -n tekton-pipelines get all we should see the resources that were created.
kubectl -n tekton-pipelines get all NAME READY STATUS RESTARTS AGE pod/tekton-dashboard-5d44ff59bd-ps9fq 1/1 Running 0 40s pod/tekton-pipelines-controller-956886f78-2kds9 1/1 Running 0 3m37s pod/tekton-pipelines-webhook-6c6446886c-hjghs 1/1 Running 0 3m37s pod/tekton-triggers-controller-7455cbc998-t2fkx 1/1 Running 3 3m26s pod/tekton-triggers-webhook-86b7dd88c6-jt4lz 1/1 Running 3 3m26s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/tekton-dashboard ClusterIP 10.96.99.10 <none> 9097/TCP 40s service/tekton-pipelines-controller ClusterIP 10.96.42.125 <none> 9090/TCP,8008/TCP,8080/TCP 3m37s service/tekton-pipelines-webhook ClusterIP 10.96.185.10 <none> 9090/TCP,8008/TCP,443/TCP,8080/TCP 3m37s service/tekton-triggers-controller ClusterIP 10.96.161.31 <none> 9000/TCP 3m26s service/tekton-triggers-webhook ClusterIP 10.96.233.161 <none> 443/TCP 3m26s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/tekton-dashboard 1/1 1 1 40s deployment.apps/tekton-pipelines-controller 1/1 1 1 3m37s deployment.apps/tekton-pipelines-webhook 1/1 1 1 3m37s deployment.apps/tekton-triggers-controller 1/1 1 1 3m26s deployment.apps/tekton-triggers-webhook 1/1 1 1 3m26s NAME DESIRED CURRENT READY AGE replicaset.apps/tekton-dashboard-5d44ff59bd 1 1 1 40s replicaset.apps/tekton-pipelines-controller-956886f78 1 1 1 3m37s replicaset.apps/tekton-pipelines-webhook-6c6446886c 1 1 1 3m37s replicaset.apps/tekton-triggers-controller-7455cbc998 1 1 1 3m26s replicaset.apps/tekton-triggers-webhook-86b7dd88c6 1 1 1 3m26s NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE horizontalpodautoscaler.autoscaling/tekton-pipelines-webhook Deployment/tekton-pipelines-webhook <unknown>/100% 1 5 1 3m37s
Installing and configuring ingress-nginx
First, we are going to install the ingress-nginx controller:
kubectl apply --filename https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml
Then, we are going to wait for it to become ready by running:
kubectl wait --namespace ingress-nginx \ --for=condition=ready pod \ --selector=app.kubernetes.io/component=controller \ --timeout=90s
When ready, you should see similar output:
pod/ingress-nginx-controller-674cb6ff57-zpxdb condition met
So, moving forward we are going to configure ingress. Before we do so, we're going to create a DNS name that allows us to access our application. I'm going to use a service called nip.io that enables DNS that points to the listening post of our node, in this case
nip.io my domain is
127-0-0-1.nip.io. This is very useful as you don't have to edit your
/etc/config every time you want to test an app. I'm going to point to a subdomain of
tekton for the following configuration, which combined, gives us
tekton.127-0-0-1.nip.io. This domain name will direct to my localhost.
Let's create a file called
tekton-ingress.yml with the following contents:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: tekton-dashboard annotations: ingress.kubernetes.io/ssl-redirect: "false" nginx.ingress.kubernetes.io/ssl-redirect: "false" spec: rules: - http: paths: - path: / pathType: Prefix backend: service: name: tekton-dashboard port: number: 9097 host: tekton.127-0-0-1.nip.io
Now we'll apply the config using the following:
kubectl -n tekton-pipelines apply -f tekton-ingress.yml
Which will output the following when successful:
We've configured the KinD cluster, installed Tekton components, and configured ingress. You can plug the domain name into your browser and access the Tekton Dashboard.
I hope this was helpful!