Minikube: Istio Ambient mode on Minikube

Istio Ambient mode is a data plane model that eliminates the need for an envoy sidecar proxy on each of your workloads.  This reduces resource overhead, timing issues between sidecar lifecycle and your containers, and the need to restart your workloads to upgrade proxy versions.

In this article, I will show you how to install and test Ambient mode on a local Minikube cluster on Ubuntu 22.04/Debian 12 bookworm.

Install required tools and Minikube

Install Docker

See my article here on Installing Docker on Ubuntu/Debian.

Install kubectl

kubectl is the command line tool used to deploy and manage applications.

curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/bin/.

You can verify the version using:

# check path and version
which kubectl
kubectl version

Install Minikube

Now download and put the latest minikube binary into /usr/local/bin.

curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/

# check version
minikube version

Start Minikube

Start Minikube explicitly with the Docker container runtime/driver and the ‘kindnet‘ Network Policy.

minikube start --container-runtime=docker --driver=docker --cni=kindnet

# check status
minikube status

# logs should reflect docker driver
minikube logs | grep -i "selected driver:"

# logs should reflect kindnet CNI
minikube logs | grep "Creating CNI manager"

# logs should reflect docker runtime
minikube logs | grep -i "container runtime version"

# test kubectl against cluster
kubectl get nodes

Note that I have tested the installation successfully with CNI=kindnet|calico, driver=docker|kvm2, and container runtime=docker|containerd.  Although the kvm2 driver does require that we install istio in IPv4 mode in a later section.

# starting minikube with alternate driver and container runtime
minikube -c containerd start --driver=kvm2 --cni=kindnet

Install Istio

Per the official documentation, download and install Istio along with the newer Gateway CRD (Gateway API replaces the Istio API e.g. VirtualService).

curl -L https://istio.io/downloadIstio | sh -
cd istio-*

# if using KVM2 container runtime add: --set values.cni.ambient.ipv6=false
bin/istioctl install --set profile=ambient --skip-confirmation
bin/istioctl verify-install

# deploy Gateway CRD
kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
  { kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml; }

If using the KVM2 driver for Minikube, you need to install Istio in IPv4 mode to avoid errors during istio-cni-node startup, “ip6tables-restore unable to initialize table ‘nat'”.  This sets AMBIENT_IPV6=false in the configmap/istio-cni-config.

Deploy BookInfo sample app

Now we are going to deploy the small “Book Info” web application that comes with Istio.  This is creating the deployments and services, but does NOT put the apps under Ambient mesh control.

# deploy bookinfo solution
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/bookinfo/platform/kube/bookinfo.yaml
# use multiple versions of services
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/bookinfo/platform/kube/bookinfo-versions.yaml

# wait for deployments to be ready
kubectl rollout status deployment productpage-v1 ratings-v1 reviews-v1 -n default --timeout=90s

# verify bookinfo app returning page with title (internal, from inside pod)
kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep "<title>"

Create Gateway

Per the newer Gateway API, we now want to create the Gateway object that exposes the service.  Once again, this does not put the app  under Ambient mesh control, that will happen later when we properly label the default namespace.

# create 'bookinfo-gateway' Gateway and 'bookinfo' HttpRoute
kubectl apply -f samples/bookinfo/gateway-api/bookinfo-gateway.yaml
# wait for auto-created 'bookinfo-gateway-istio' waypoint proxy
kubectl rollout status deployment bookinfo-gateway-istio -n default --timeout=90s

# by default creates loadbalancer service, no address available
$ kubectl get gateway
NAME CLASS ADDRESS PROGRAMMED AGE
bookinfo-gateway istio False 109s

# this loadbalancer service is <pending>, but not necessary for us
$ kubectl get service bookinfo-gateway-istio
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
bookinfo-gateway-istio LoadBalancer 10.96.238.79 <pending> 15021:32380/TCP,80:31433/TCP 33s

# so change the service type to ClusterIP
kubectl annotate gateway bookinfo-gateway networking.istio.io/service-type=ClusterIP --namespace=default

# loadbalancer IP no longer awaiting creation with <pending>
$ kubectl get service bookinfo-gateway-istio
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
bookinfo-gateway-istio ClusterIP 10.96.238.79 <none> 15021/TCP,80/TCP 2m18s

# gateway now was internal service name
$ kubectl get gateway
NAME CLASS ADDRESS PROGRAMMED AGE
bookinfo-gateway istio bookinfo-gateway-istio.default.svc.cluster.local True 2m44s

Test Gateway API

Istio waypoint proxy are deployed by Gateway resources.  Use this to reach the service locally.

# forward Istio waypoint proxy to local port 8080
kubectl port-forward svc/bookinfo-gateway-istio 8080:80

# check with local browser, or another console
curl -s http://localhost:8080/productpage | grep '<title>'

Looks like this in the browser:

Kiali, the Istio observability tool

Deploy Kiali

In order to better understand the application and its participation in the Ambient mode mesh, we will install Kiali the Istio observability dashboard.

# install kiali dashboard
kubectl apply -f samples/addons
kubectl rollout status deployment/kiali -n istio-system --timeout=90s

View sample app status in Kiali

# forwards local port and opens local browser to Kiali dashboard
bin/istioctl dashboard kiali

Notice if we navigate to “Applications” in Kiali, the applications are listed as “Out of mesh”.  This is because the applications have not been directed to participate in the Ambient mesh yet.

Enable Ambient mode for sample app

As shown in the previous section, the sample app is not participating in the Ambient mesh.  We can enable this by adding an “istio.io/dataplane-mode” label to the default namespace.

# show current namespaces that are ambient mesh enabled (should be none)
kubectl get ns default -L istio.io/dataplane-mode=ambient

# make sample app part of the mesh with namespace label
kubectl label namespace default istio.io/dataplane-mode=ambient

With that single namespace label, the sample “Book Info” sample app services are now participating in the Ambient service mesh.  It did not require any restarts of the workloads.

Verify Ambient mode participation for sample app

If we now throw load at the service, we can go back to the Kiali web UI and validate they are participating in the Ambient mesh.

# forward service to local port
kubectl port-forward svc/bookinfo-gateway-istio 8080:80
# throw load at app from a different console
for i in $(seq 1 100); do curl -sS http://localhost:8080/productpage >/dev/null; done

# open Kiali in local browser
bin/istioctl dashboard kiali

Now we should be able to see that the “default” namespace is participating in the mesh, per the “Ambient” icon next to its name.

And in “Applications” the deployments no longer have the “out of mesh” message, proving they are indeed mesh enabled.

And from “Traffic Graph” the product page we put load against shows us its backing dependencies going to the details and reviews service.


REFERENCES

istio.io, Introducing Ambient Mesh

istio.io, ambient reaches beta, throw away your sidecar

istio.io, Getting started with Ambient Mesh

istio.io, Ambient Mesh and sample app

Billy Ridgway, Trying Ambient Mesh

github, Troubleshooting Ambient

go, istio-cni plugin

solo.io, Ambient mesh

karampok.me, chained CNI plugins

karampok.me, intro to CNI

solo.io, ztunnel configuration

istio.io, network dual-stack IPv4/IPv6

istio.io, getting started (sample app)

Minikube docs

Sabuj Jana, touring Ambient mesh

Praynay Singhal, istio proxy sidecar memory consumption problem because large service list

Istio Ambient mesh on GKE

Kiali main page

github issues, troubleshooting CNI pod to ztunnel route

github, istio-cni helm chart which includes configmap-cni.yaml where AMBIENT_IPV6 value is configured

Minikube startup parameters

 

NOTES

If CNI=calico, then Daemonset exists

kubectl describe ds calico-node -n kube-system

Validate required route from CNI pod to ztunnel pod, github issue

CNI_IP=$(kubectl get -n istio-system pod $(kubectl get pod -n istio-system -l k8s-app=istio-cni-node -o jsonpath='{.items..metadata.name}') -o jsonpath='{.status.podIP}')
ZTUN_IP=$(kubectl get -n istio-system pod $(kubectl get pod -n istio-system -l app=ztunnel -o jsonpath='{.items..metadata.name}') -o jsonpath='{.status.podIP}')
kubectl debug -it $(kubectl get pod -n istio-system -l k8s-app=istio-cni-node -oname) -n istio-system --image=busybox -- ip route get from $CNI_IP to $ZTUN_IP

Prometheus was also installed as part of this article

you can forward to a local port and open the browser using:

# https://istio.io/latest/docs/tasks/observability/metrics/querying-metrics/
bin/istioctl dashboard prometheus

Below is an example of a query against ‘istio_requests_total’

show kernel modules loaded and required by istio CNI, github issue

minikube ssh

# operate as root
sudo su
# show currently loaded kernel modules
lsmod
# load modules required by istio CNI
modprobe br_netfilter ; modprobe nf_nat ; modprobe xt_REDIRECT ; modprobe xt_owner; modprobe iptable_nat; modprobe iptable_mangle; modprobe iptable_filter

update kubeconfig for minikube

minikube update-context