Local Kubernetes - Adding An Ingress Controller
Tags: kubernetes, devops, tutorial, beginners
Published: 2023-01-17 09:25:31

## Previous Posts in This Series

 * [Installing A Local Kubernetes](https://dev.to/arobson/installing-a-local-kubernetes-2igp)
 * [Local Kubernetes RBAC & Dashboard Setup](https://dev.to/arobson/local-kubernetes-rbac-dashboard-setup-1keh)

## A Brief Explanation of Kubernetes Networking

Unlike running Docker containers with ports bound to a host port, Kubernetes does not expose container ports or assign them an IP address. Kubernetes has a `service` resource that exposes ports in a POD to a named endpoint and port.

A service provides a predictable way to access containers via the internal cluster network. The container will only be reachable from within the cluster through the service.

In the last post, we used `m8s dashboard-proxy` to make the `kubernetes-dashboard` service accessible outside the cluster.

To see the manifest of the `kubernetes-dashboard` service, issue the following:

```shell
k8s get service -n kube-system kubernetes-dashboard -o yaml
```

> Note: The service binds the `port` for this named service to the `targetPort` on the Pod. 

To display the manifest for the dashboard pod, issue the command:

```shell
k8s describe pod -n kube-system kubernetes-dashboard
```

Look for the `ports` collection inside the container spec for `kubernetes-dashboard` to see the port setting `8443/TCP`.

## Enabling DNS

Kubernetes' DNS provides service discovery, a valuable feature when containers can disappear or get added, resulting in a shifting set of IP addresses. 

To add DNS, type:

```shell
m8s enable dns
```

## Editing The Dashboard's Deployment and Service

For safety, the dashboard is secure by default and allows HTTPS only through a certificate it creates. I want to demonstrate how to host the dashboard through the ingress controller through port 80. In a future post, we'll secure this with SSL termination on the ingress controller.

The dashboard will require changes to host HTTP traffic and updating the service to bind to a different target port.

### Changing The Deployment

To fetch the current deployment manifest for the dashboard, use the following:

```shell
k8s get deployment -n kube-system kubernetes-dashboard -o yaml > dashboard-deployment.yml
```

Open your favorite editor and follow each set of directions.

#### Enable Insecure Login

Change `--auto-generate-certificates` to `--enable-insecure-login` to forgo generating self-signed certificates and bind the dashboard process to port `9090`.

#### Change 8443 to 9090

We need to change the port the container will expose to `9090` from `8443` under the `ports` section.

#### Update the Liveness Probe

Edit the liveness probe section by changing the `httpGet`'s port to `9090` and the `scheme` to `HTTP`.

#### Apply the Changes

Save the changes you made to the file and apply our changes to the deployment; issue the following:

```shell
k8s apply -f ./dashboard-deployment.yml
```

### Changing The Service

Now that our dashboard deployment is bound to port 9090, we need to update our service. To fetch the service manifest, type:

```shell
k8s get service -n kube-system kubernetes-dashboard -o yaml > dashboard-service.yml
```

#### Change The Ports

We'll change the `port` from `443` to `80` and `targetPort` from `8443` to `9090`.

#### Apply the Changes

Save your changes and update the service as we did with the deployment with the following:

```shell
k8s apply -f ./dashboard-service.yml
```

## Adding the NGINX Ingress Controller

An Ingress Controller is how Kubernetes accepts incoming HTTP requests through a fixed set of IPs and directs them to the correct backing Pods/Containers based on configuration.

To install the NGINX Ingress Controller from Kubernetes, we can enable the add-on as follows:

```shell
microk8s enable ingress
```

### Creating Ingress for The Dashboard

Save the following YAML for the manifest in a file `http-dashboard-ingress.yml`:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: http-ingress
  namespace: kube-system
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2    
spec:
  rules:
  - http:
      paths:
      - path: /dash(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: kubernetes-dashboard
            port:
              number: 80
```

From your shell, the following command will cause the ingress controller to update the NGINX configuration.

```shell
k8s create -f ./http-dashboard-ingress.yml
```

The new NGINX configuration forwards all requests to port 80 to the dashboard container.

### Finding The Cluster IP

To access the dashboard, we'll need the IP address of the cluster. The endpoint slice named `kubernetes` should resolve to the Ingress controller. Fetch the list of endpoint slices with the following:

```shell
k8s get endpointslices
```

## Accessing The Dashboard

The dashboard should now be accessible via port 80 at the URL `/dash/`. The dashboard should display a notification in red at the bottom notifying you that authentication is disabled since you're accessing it via an unsecured (HTTP) connection through an IP other than `localhost` or `127.0.0.1`.

### Creating a Proxy

The proxy built into microk8s is not compatible with the changes made to the dashboard deployment. The `port-forward` feature in Kubernetes creates a tunnel from a specified resource to the localhost.

```shell
k8s -n ingress port-forward service/ingress 8008:80
```

Now the dashboard can be accessed `http://localhost:8008/dash/` and will accept authentication.

## Up Next

In the next post, I'll look at options for SSL termination.

## References

[Kubernetes Services](https://kubernetes.io/docs/concepts/services-networking/service/)

[Microk8s Addon: Ingress](https://microk8s.io/docs/addon-ingress)

[NGINX Ingress Controller](https://github.com/kubernetes/ingress-nginx)