Getting Started with Ambient Mesh

Ambient is currently in alpha status.

Please do not run ambient in production and be sure to thoroughly review the feature phase definitions before use. In particular, there are known performance, stability, and security issues in the alpha release. There are also planned breaking changes, including some that will prevent upgrades. These are all limitations that will be addressed before graduation to beta.

This guide lets you quickly evaluate Istio ambient service mesh. These steps require you to have a cluster running a supported version of Kubernetes (1.25, 1.26, 1.27, 1.28). You can use any supported platform, for example Minikube or others specified by the platform-specific setup instructions.

Ambient is currently in alpha status. Note that Ambient currently requires the use of istio-cni to configure Kubernetes nodes. istio-cni ambient mode does not currently support types of cluster CNI (namely, CNI implementations that do not use veth devices, such as Minikube’s bridge mode)

Follow these steps to get started with ambient:

  1. Download and install
  2. Deploy the sample application
  3. Adding your application to ambient
  4. Secure application access
  5. Control traffic
  6. Uninstall

Download and install

  1. Download the latest version of Istio with alpha support for ambient mesh.

  2. If you don’t have a Kubernetes cluster, you can deploy one locally using kind with the following command:

    1. $ kind create cluster --config=- <<EOF
    2. kind: Cluster
    3. apiVersion: kind.x-k8s.io/v1alpha4
    4. name: ambient
    5. nodes:
    6. - role: control-plane
    7. - role: worker
    8. - role: worker
    9. EOF
  3. Install Kubernetes Gateway CRDs, which don’t come installed by default on most Kubernetes clusters:

    1. $ kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
    2. { kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v1.0.0" | kubectl apply -f -; }

    Istio includes beta support for the Kubernetes Gateway API and intends to make it the default API for traffic management in the future. The following instructions allow you to choose to use either the Gateway API or the Istio configuration API when configuring traffic management in the mesh. Follow instructions under either the Gateway API or Istio APIs tab, according to your preference.

  4. The ambient profile is designed to help you get started with ambient mesh. Install Istio with the ambient profile on your Kubernetes cluster, using the istioctl command downloaded above:

Note that if you are using Minikube (or any other platform using nodes configured with a nonstandard netns path for containers), you may need to append --set values.cni.cniNetnsDir="/var/run/docker/netns" to the istioctl install command so that the Istio CNI DaemonSet can correctly manage and capture pods on the node.

Consult your platform documentation for details.

  1. $ istioctl install --set profile=ambient --set "components.ingressGateways[0].enabled=true" --set "components.ingressGateways[0].name=istio-ingressgateway" --skip-confirmation

After running the above command, you’ll get the following output that indicates five components (including Ztunnel) have been installed successfully!

  1. Istio core installed
  2. Istiod installed
  3. CNI installed
  4. Ingress gateways installed
  5. Ztunnel installed
  6. Installation complete
  1. $ istioctl install --set profile=ambient --skip-confirmation

After running the above command, you’ll get the following output that indicates four components (including Ztunnel) have been installed successfully!

  1. Istio core installed
  2. Istiod installed
  3. CNI installed
  4. Ztunnel installed
  5. Installation complete
  1. Verify the installed components using the following commands:
  1. $ kubectl get pods -n istio-system
  2. NAME READY STATUS RESTARTS AGE
  3. istio-cni-node-n9tcd 1/1 Running 0 57s
  4. istio-ingressgateway-5b79b5bb88-897lp 1/1 Running 0 57s
  5. istiod-69d4d646cd-26cth 1/1 Running 0 67s
  6. ztunnel-lr7lz 1/1 Running 0 69s
  1. $ kubectl get daemonset -n istio-system
  2. NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
  3. istio-cni-node 1 1 1 1 1 kubernetes.io/os=linux 70s
  4. ztunnel 1 1 1 1 1 kubernetes.io/os=linux 82s
  1. $ kubectl get pods -n istio-system
  2. NAME READY STATUS RESTARTS AGE
  3. istio-cni-node-n9tcd 1/1 Running 0 57s
  4. istiod-69d4d646cd-26cth 1/1 Running 0 67s
  5. ztunnel-lr7lz 1/1 Running 0 69s
  1. $ kubectl get daemonset -n istio-system
  2. NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
  3. istio-cni-node 1 1 1 1 1 kubernetes.io/os=linux 70s
  4. ztunnel 1 1 1 1 1 kubernetes.io/os=linux 82s

Deploy the sample application

You’ll use the sample bookinfo application, which is part of the Istio distribution that you downloaded above. In ambient mode, you deploy applications to your Kubernetes cluster exactly the same way you would without Istio. This means that you can have your applications running in your cluster before you enable ambient mesh and have them join the mesh without needing to restart or reconfigure them.

Make sure the default namespace does not include the label istio-injection=enabled because when using ambient you do not want Istio to inject sidecars into the application pods.

  1. Start the sample services:

    Zip

    1. $ kubectl apply -f @samples/bookinfo/platform/kube/bookinfo.yaml@

    ZipZip

    1. $ kubectl apply -f @samples/sleep/sleep.yaml@
    2. $ kubectl apply -f @samples/sleep/notsleep.yaml@

    Note: sleep and notsleep are two simple applications that can serve as curl clients.

  2. Deploy an ingress gateway so you can access the bookinfo app from outside the cluster:

    To get IP address assignment for Loadbalancer service types in kind, you may need to install a tool like MetalLB. Please consult this guide for more information.

Create an Istio Gateway and VirtualService:

Zip

  1. $ kubectl apply -f @samples/bookinfo/networking/bookinfo-gateway.yaml@

Set the environment variables for the Istio ingress gateway:

  1. $ export GATEWAY_HOST=istio-ingressgateway.istio-system
  2. $ export GATEWAY_SERVICE_ACCOUNT=ns/istio-system/sa/istio-ingressgateway-service-account

Create a Kubernetes Gateway and HTTPRoute:

Zip

  1. $ sed -e 's/from: Same/from: All/'\
  2. -e '/^ name: bookinfo-gateway/a\
  3. namespace: istio-system\
  4. ' -e '/^ - name: bookinfo-gateway/a\
  5. namespace: istio-system\
  6. ' @samples/bookinfo/gateway-api/bookinfo-gateway.yaml@ | kubectl apply -f -

Set the environment variables for the Kubernetes gateway:

  1. $ kubectl wait --for=condition=programmed gtw/bookinfo-gateway -n istio-system
  2. $ export GATEWAY_HOST=bookinfo-gateway-istio.istio-system
  3. $ export GATEWAY_SERVICE_ACCOUNT=ns/istio-system/sa/bookinfo-gateway-istio
  1. Test your bookinfo application, it should work with or without the gateway:

    1. $ kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" | grep -o "<title>.*</title>"
    2. <title>Simple Bookstore App</title>
    1. $ kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
    2. <title>Simple Bookstore App</title>
    1. $ kubectl exec deploy/notsleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
    2. <title>Simple Bookstore App</title>

Adding your application to ambient

You can enable all pods in a given namespace to be part of the ambient mesh by simply labeling the namespace:

  1. $ kubectl label namespace default istio.io/dataplane-mode=ambient

Congratulations! You have successfully added all pods in the default namespace to the ambient mesh. The best part is that there was no need to restart or redeploy anything!

Send some test traffic:

  1. $ kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" | grep -o "<title>.*</title>"
  2. <title>Simple Bookstore App</title>
  1. $ kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
  2. <title>Simple Bookstore App</title>
  1. $ kubectl exec deploy/notsleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
  2. <title>Simple Bookstore App</title>

You’ll immediately gain mTLS communication and L4 telemetry among the applications in the ambient mesh. If you follow the instructions to install Prometheus and Kiali, you’ll be able to visualize your application in Kiali’s dashboard:

Kiali dashboard

Kiali dashboard

Secure Application Access

After you have added your application to ambient mesh, you can secure application access using L4 authorization policies. This lets you control access to and from a service based on client workload identities, but not at the L7 level, such as HTTP methods like GET and POST.

L4 Authorization Policy

Explicitly allow the sleep and gateway service accounts to call the productpage service:

  1. $ kubectl apply -f - <<EOF
  2. apiVersion: security.istio.io/v1beta1
  3. kind: AuthorizationPolicy
  4. metadata:
  5. name: productpage-viewer
  6. namespace: default
  7. spec:
  8. selector:
  9. matchLabels:
  10. app: productpage
  11. action: ALLOW
  12. rules:
  13. - from:
  14. - source:
  15. principals:
  16. - cluster.local/ns/default/sa/sleep
  17. - cluster.local/$GATEWAY_SERVICE_ACCOUNT
  18. EOF

Confirm the above authorization policy is working:

  1. $ # this should succeed
  2. $ kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" | grep -o "<title>.*</title>"
  3. <title>Simple Bookstore App</title>
  1. $ # this should succeed
  2. $ kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
  3. <title>Simple Bookstore App</title>
  1. $ # this should fail with a connection reset error code 56
  2. $ kubectl exec deploy/notsleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
  3. command terminated with exit code 56

L7 Authorization Policy

Using the Kubernetes Gateway API, you can deploy a waypoint proxy for the productpage service that uses the bookinfo-productpage service account. Any traffic going to the productpage service will be mediated, enforced and observed by the Layer 7 (L7) proxy.

Deploy a waypoint proxy for the productpage service:

  1. $ istioctl x waypoint apply --service-account bookinfo-productpage
  2. waypoint default/bookinfo-productpage applied

View the productpage waypoint proxy status; you should see the details of the gateway resource with Programmed status:

  1. $ kubectl get gtw bookinfo-productpage -o yaml
  2. ...
  3. status:
  4. conditions:
  5. - lastTransitionTime: "2023-02-24T03:22:43Z"
  6. message: Resource programmed, assigned to service(s) bookinfo-productpage-istio-waypoint.default.svc.cluster.local:15008
  7. observedGeneration: 1
  8. reason: Programmed
  9. status: "True"
  10. type: Programmed

Update our AuthorizationPolicy to explicitly allow the sleep and gateway service accounts to GET the productpage service, but perform no other operations:

  1. $ kubectl apply -f - <<EOF
  2. apiVersion: security.istio.io/v1beta1
  3. kind: AuthorizationPolicy
  4. metadata:
  5. name: productpage-viewer
  6. namespace: default
  7. spec:
  8. targetRef:
  9. kind: Gateway
  10. group: gateway.networking.k8s.io
  11. name: bookinfo-productpage
  12. action: ALLOW
  13. rules:
  14. - from:
  15. - source:
  16. principals:
  17. - cluster.local/ns/default/sa/sleep
  18. - cluster.local/$GATEWAY_SERVICE_ACCOUNT
  19. to:
  20. - operation:
  21. methods: ["GET"]
  22. EOF
  1. $ # this should fail with an RBAC error because it is not a GET operation
  2. $ kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" -X DELETE
  3. RBAC: access denied
  1. $ # this should fail with an RBAC error because the identity is not allowed
  2. $ kubectl exec deploy/notsleep -- curl -s http://productpage:9080/
  3. RBAC: access denied
  1. $ # this should continue to work
  2. $ kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
  3. <title>Simple Bookstore App</title>

Control Traffic

Deploy a waypoint proxy for the review service, using the bookinfo-review service account, so that any traffic going to the review service will be mediated by the waypoint proxy.

  1. $ istioctl x waypoint apply --service-account bookinfo-reviews
  2. waypoint default/bookinfo-reviews applied

Configure traffic routing to send 90% of requests to reviews v1 and 10% to reviews v2:

ZipZip

  1. $ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-90-10.yaml@
  2. $ kubectl apply -f @samples/bookinfo/networking/destination-rule-reviews.yaml@

ZipZip

  1. $ kubectl apply -f @samples/bookinfo/platform/kube/bookinfo-versions.yaml@
  2. $ kubectl apply -f @samples/bookinfo/gateway-api/route-reviews-90-10.yaml@

Confirm that roughly 10% of the traffic from 100 requests goes to reviews-v2:

  1. $ kubectl exec deploy/sleep -- sh -c "for i in \$(seq 1 100); do curl -s http://$GATEWAY_HOST/productpage | grep reviews-v.-; done"

Uninstall

To remove the productpage-viewer authorization policy, waypoint proxies and uninstall Istio:

  1. $ kubectl delete authorizationpolicy productpage-viewer
  2. $ istioctl x waypoint delete --service-account bookinfo-reviews
  3. $ istioctl x waypoint delete --service-account bookinfo-productpage
  4. $ istioctl uninstall -y --purge
  5. $ kubectl delete namespace istio-system

The label to instruct Istio to automatically include applications in the default namespace to ambient mesh is not removed by default. If no longer needed, use the following command to remove it:

  1. $ kubectl label namespace default istio.io/dataplane-mode-

To delete the Bookinfo sample application and its configuration, see Bookinfo cleanup.

To remove the sleep and notsleep applications:

ZipZip

  1. $ kubectl delete -f @samples/sleep/sleep.yaml@
  2. $ kubectl delete -f @samples/sleep/notsleep.yaml@

If you installed the Gateway API CRDs, remove them:

  1. $ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v1.0.0" | kubectl delete -f -