When deploying services in Kubernetes, managing external traffic securely is a critical task. By using MetalLB for load balancing and Istio Ingress Gateway with Mutual TLS (mTLS), you can ensure secure communication between your services and external clients. In this guide, we’ll walk through the steps to install MetalLB, configure Istio Ingress Gateway, and enable mTLS for external traffic.

Why Use MetalLB and Istio Ingress with Mutual TLS?

  • MetalLB: Provides network load balancing in bare-metal Kubernetes clusters. It assigns external IPs to services, simulating the behavior of a cloud-based load balancer.
  • Istio Ingress Gateway: Manages incoming traffic to your services, applying routing rules and enforcing security policies like Mutual TLS.
  • Mutual TLS (mTLS): Ensures that both client and server authenticate each other, enhancing security for sensitive communications.

Step 1: Install MetalLB

1. Install MetalLB with Manifest

MetalLB requires a Layer 2 configuration for bare-metal environments, assigning IP addresses from a predefined pool.

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml

2. Configure MetalLB IP Pool

Create a Layer 2 configuration file for MetalLB. This file defines the IP address pool that MetalLB will use to assign external IPs to services.

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: my-ip-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.240-192.168.1.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: my-l2-advertisement
  namespace: metallb-system

Apply the configuration:

kubectl apply -f metallb-config.yaml

MetalLB is now configured and ready to assign external IPs to services in your Kubernetes cluster.

Step 2: Install Istio and Enable Ingress Gateway

1. Install Istio

Download and install Istio with Helm:

curl -L https://istio.io/downloadIstio | sh -
cd istio-1.x.x
export PATH=$PWD/bin:$PATH

Install the Istio components:

istioctl install --set profile=default

2. Enable Istio Ingress Gateway

The Istio Ingress Gateway is responsible for managing incoming external traffic. By default, the Ingress Gateway is installed but not exposed.

Create a Kubernetes service of type LoadBalancer for the Istio Ingress Gateway:

apiVersion: v1
kind: Service
metadata:
  name: istio-ingressgateway
  namespace: istio-system
spec:
  type: LoadBalancer
  selector:
    app: istio-ingressgateway
  ports:
  - port: 80
    targetPort: 8080
  - port: 443
    targetPort: 8443

Apply the service configuration:

kubectl apply -f istio-ingress-gateway.yaml

MetalLB will assign an external IP to the Istio Ingress Gateway, making it accessible from outside the cluster.

Step 3: Enable Mutual TLS (mTLS)

Mutual TLS (mTLS) ensures that both the client and server authenticate each other. Istio makes it easy to configure mTLS for incoming traffic to the Ingress Gateway.

1. Create a Root Certificate Authority (CA)

First, generate a root certificate and key to serve as the root CA for mTLS.

openssl req -x509 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 365 -nodes -subj "/CN=RootCA"

2. Generate Certificates for the Ingress Gateway

Generate a private key and certificate for the Istio Ingress Gateway.

openssl req -newkey rsa:4096 -keyout istio-ingressgateway.key -out istio-ingressgateway.csr -nodes -subj "/CN=istio-ingressgateway"
openssl x509 -req -in istio-ingressgateway.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out istio-ingressgateway.crt -days 365

3. Create a Secret for the Gateway Certificates

Store the certificates as Kubernetes secrets in the istio-system namespace:

kubectl create -n istio-system secret tls istio-ingressgateway-certs --key istio-ingressgateway.key --cert istio-ingressgateway.crt
kubectl create -n istio-system secret generic ca-cert --from-file=ca.crt=ca.crt

4. Configure Gateway for mTLS

Update the Istio Gateway resource to enforce mTLS for incoming traffic:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: my-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: MUTUAL
      serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
      privateKey: /etc/istio/ingressgateway-certs/tls.key
      caCertificates: /etc/istio/ca-cert/ca.crt
    hosts:
    - "myapp.homelab.local"

Apply the Gateway configuration:

kubectl apply -f mtls-gateway.yaml

Step 4: Test the Ingress with mTLS

To verify the mTLS setup, you’ll need to configure a client to authenticate with the Ingress Gateway using a client certificate signed by the same CA.

1. Generate a Client Certificate

Create a certificate for the client:

openssl req -newkey rsa:4096 -keyout client.key -out client.csr -nodes -subj "/CN=client"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365

2. Test the Connection

Use curl to test the connection between the client and the Istio Ingress Gateway:

curl --key client.key --cert client.crt --cacert ca.crt https://myapp.homelab.local

If everything is configured correctly, you should see a successful response from the application behind the Istio Ingress Gateway.

Final Thoughts

By combining MetalLB with Istio Ingress Gateway and Mutual TLS, you can ensure secure external access to your Kubernetes services while maintaining control over load balancing and routing. This setup provides enhanced security, particularly for homelab or bare-metal environments, and gives you the flexibility to manage traffic securely and efficiently.