Expose Applications from a K8s cluster
Tags: nodeport, loadbalancer, ingresscontroller, kubernetes
Published: 2023-11-20 18:30:00

To expose applications from our Kubernetes cluster we need different service types.

## Service Types
### ClusterIP
The ClusterIP service type is the default and only provides access internally - within the cluster. 
If you need to expose a service to the external world, you might consider other service types such as NodePort or LoadBalancer.

The kubectl proxy command creates a local service to access a ClusterIP. This can be useful for troubleshooting or development work.

```
apiVersion: v1
kind: Service
metadata:
  name: internal-cluster-ip-service
spec:
  selector:
    app: your-app
  ports:
    - protocol: TCP
      port: 80 #exposes this port internally
      targetPort: 8080 # directs traffic to pods on that port
```


### NodePort
The NodePort type is great for debugging, or when a static IP address is necessary, such as opening a particular address through a firewall. The NodePort range is defined in the cluster configuration.

```
kind: Service
metadata:
  name: your-nodeport-service
spec:
  type: NodePort
  selector:
    app: your-app
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80
      nodePort: 30080 # port 8080 is exposed on all nodes, and reachable from their ip on port 30080
```

Create a service via kubectl:
`kubectl expose deployment/nginx --port=80 --type=NodePort`
This service creates a service for the nginx deployment.
`kubectl get svc`
`kubectl get svc nginx -o yaml`

### LoadBalancer
LoadBalancer is a type of service that automatically provides external access to services within a cluster by distributing incoming network traffic across multiple nodes. 

Using a LoadBalancer service is a convenient way to expose services externally, especially in production environments, where load balancing and high availability are crucial.

```
apiVersion: v1
kind: Service
metadata:
  name: your-loadbalancer-service
spec:
  type: LoadBalancer
  selector:
    app: your-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
```

### ExternalName
With this service you can map a Kubernetes service to a DNS Name. Use of the service returns a CNAME record.
Working with the ExternalName service is handy when using a resource external to the cluster, perhaps prior to full integration.

```
apiVersion: v1
kind: Service
metadata:
  name: geiler-service
spec:
  type: ExternalName
  externalName: geil.example.com
```


## Ingress
### Ingress Resource
An ingress resource is an API object containing a list of rules matched against all incoming requests. 

```
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: your-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: your-app.example.com  # Replace with your desired domain or IP
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: your-app-service
            port:
              number: 80
```
`kubectl apply -f ingress.yaml`

### Ingress Controller
An ingress controller manages all the ingress rules to route traffic to existing services.
This is important if the number of services gets high.


### Service Mesh
If you need service discovery, rate limiting, traffic management and advanced metrics you can implement a service mesh.


Further reading:
[Kubernetes Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
[What is a service mesh](https://avinetworks.com/glossary/kubernetes-service-mesh/)