Skip to content

Instantly share code, notes, and snippets.

@Realiserad
Last active March 29, 2025 09:27
Show Gist options
  • Select an option

  • Save Realiserad/391855c4a0fb0072994e5ad2a53d65c0 to your computer and use it in GitHub Desktop.

Select an option

Save Realiserad/391855c4a0fb0072994e5ad2a53d65c0 to your computer and use it in GitHub Desktop.
Set up Istio in MicroK8s

Deploy Istio

VM setup

Start from a minimal installation of Ubuntu Server 22.04.

In this case, I've set up a VM with two network interfaces, one NAT for connection to the internet, and one bridged network interface to connect from the host to the guest VM.

The Netplan configuration in /etc/netplan looks like this:

network:
  ethernets:
    enp1s0:
      dhcp4: true
    enp7s0:
      dhcp4: false
      addresses:
      - 192.168.122.10/24
      routes:
      - to: 192.168.122.0/24
        via: 192.168.122.1
        metric: 200
  version: 2

After making changes to the YML configuration, apply the changes with sudo netplan apply.

Install MicroK8s

We are going to use MicroK8s from Canonical as our Kubernetes distribution. It can be installed as a snap package.

sudo snap install microk8s --classic

MicroK8s bundles its own version of kubectl. You can run it through MicroK8s using microk8s kubectl. To avoid having to prefix all kubectl commands with microk8s, you can create an alias like this:

sudo snap alias microk8s.kubectl kubectl

Only users in the microk8s group can access the Kubernetes cluster using kubectl, so to avoid having to use sudo, add yourself to the group.

sudo usermod -aG microk8s $(whoami)

Enable DNS in the Kubernetes cluster. In MicroK8s, this is very simple:

microk8s enable dns

Install Istio

We can enable Istio in a similar fashion.

microk8s enable community
microk8s enable istio

This will deploy the Istio control plane in the istio-system namespace.

To visualise the traffic sent between pods, you can use Kiali. Kiali requires Prometheus to be deployed in the istio-system namespace to work out of the box. The easiest way to get it to work is to use the sample deployment files provided by Istio.

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/addons/prometheus.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/addons/kiali.yaml

To make the Kiali dashboard accessible from the host, replace the ClusterIP service with a NodePort service like this:

$ kubectl patch svc kiali -n istio-system --type='json' -p '[{"op":"replace","path":"/spec/type","value":"NodePort"}]'
$ kubectl get svc -n demo istio-system -l app=kiali
NAME    TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                               AGE
kiali   NodePort   10.152.183.38   <none>        20001:<NodePort>/TCP,9090:30423/TCP   6h28m

The Kiali dashboard should now be available in the browser from the host on the port <NodePort>.

Deploy the Bookinfo application

Create a namespace called demo and enable injection of the Envoy sidecar for all pods started in this namespace.

kubectl create namespace demo
kubectl label namespace demo istio-injection=enabled

Deploy the Bookinfo sample application provided on Istio's website.

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/bookinfo/platform/kube/bookinfo.yaml -n demo

Enforce and test mTLS

By default, Istio enables, but does not enforce mutual TLS authentication (mTLS) between pods.

To enforce mTLS for a particular namespace, set a PeerAuthentication policy:

cat <<EOF | kubectl apply -f -
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: "test-mtls"
  namespace: "demo"
spec:
  mtls:
    mode: STRICT
EOF

If you list the containers in one of the pods we deployed in the demo namespace, for example the pod hosting the product page, you can see that Istio has injected an Envoy proxy (istio-proxy) as a sidecar.

istioctl provides a command for describing a pod, which shows the containers inside the pod as well as the active PeerAuthenticationPolicy for that pod.

$ microk8s istioctl experimental describe pod $(kubectl get pod -n demo -l app=productpage -o jsonpath='{.items[0].metadata.name}') -n demo
Pod: productpage-v1-d4f8dfd97-54kgk
   Pod Revision: default
   Pod Ports: 9080 (productpage), 15090 (istio-proxy)
--------------------
Service: productpage
   Port: http 9080/HTTP targets pod port 9080
--------------------
Effective PeerAuthentication:
   Workload mTLS mode: STRICT
Applied PeerAuthentication:
   test-mtls.demo

Send an HTTP GET request to the Bookinfo product page to be able to see something interesting in Kiali.

We can do this by running curl inside the ratings container.

$ kubectl exec "$(kubectl get pod -n demo -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -n demo -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>

In the Kiali dashboard, follow these steps to check the security status of the request you made in the previous step:

  1. Click on Graph in the menu on the left.
  2. Choose the demo namespace in the Namespace dropdown.
  3. Enable the Security option in the Display dropdown.

You should now see a graph where the edges are labelled with locks, as shown in the screenshot below. This means that the traffic between the pods was encrypted using TLS.

Example of what the pod graph in Kiali looks like when Istio enforces mTLS in Kubernetes.

Inspect the TLS certificate

By default, Istio creates its own self-signed X.509 CA certificate which it uses to sign the TLS certificates for pods.

The TLS certificate is issued to the Envoy proxy and used to authenticate pods to each other, and contains a SPIFFE identifier in the SAN extension which uniquely identifies a pod in the cluster.

To inspect the certificate, we can run OpenSSL in the istio-proxy sidecar and connect to the main container using openssl s_client.

$ kubectl exec "$(kubectl get pod -n demo -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -n demo -c istio-proxy -- openssl s_client -showcerts -connect productpage:9080 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' | openssl x509 -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            69:09:36:3b:80:c3:1c:d6:40:66:ab:4c:33:f4:69:a7
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: O = cluster.local
        Validity
            Not Before: Feb 14 12:24:26 2023 GMT
            Not After : Feb 15 12:26:26 2023 GMT
        Subject:
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    <snip>
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Authority Key Identifier:
                8E:F6:7C:D4:C8:A4:A7:87:95:45:64:D7:0E:03:E3:81:A6:BE:6B:15
            X509v3 Subject Alternative Name: critical
                URI:spiffe://cluster.local/ns/demo/sa/bookinfo-productpage
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        <snip>

Cleanup

Delete the demo namespace to remove the Bookinfo sample application.

kubectl delete ns demo

If you don't want to use Istio further, remove the istio-system namespace as well.

kubectl delete ns istio-system
@buchmann
Copy link

buchmann commented May 8, 2024

Thank you great job works out of the box

@Realiserad
Copy link
Author

Realiserad commented May 8, 2024

@buchmann You're welcome! 😇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment