乐趣区

关于云计算:Istio-Ambient-Mesh-介绍

1 Ambient Mesh 介绍

Istio 的传统模式是将 Envoy proxy 作为 sidecar 部署在工作负载的 Pod 中,尽管与重构应用程序相比,sidecar 具备显著的劣势,然而依然会产生一些限度:

  • 侵入性 :sidecar 必须通过批改 Kubernetes Pod 的配置和重定向流量来“注入”应用程序。因而,装置和降级 sidecar 须要重新启动 Pod,这将会对工作负载产生影响。
  • 资源利用率低 :因为在每个工作负载 Pod 都注入了 sidecar 代理,因而 Pod 必须为 sidecar 预留足够的 CPU 和内存资源,从而导致整个集群的资源利用率有余。
  • 流量中断 :流量捕捉和 HTTP 解决通常是由 Istio 的 sidecar 实现的,计算须要耗费大量的资源,并且可能会毁坏一些不合乎 HTTP 实现的应用程序。

Istio ambient mesh 是 Istio 的一个无 sidecar 的数据立体,旨在升高基础设施老本和进步性能。
它的实质是拆散 sidecar proxy(Envoy)中的 L4 和 L7 性能,让一部分仅须要平安性能的用户能够最小阻力(低资源耗费、运维老本)地应用 Istio service mesh。

ambient mesh 将 Istio 的性能拆分为 2 个不同的档次:

  • L4 平安覆盖层:用户能够应用 TCP 路由,mTLS 和无限的可观测性等性能。
  • L7 解决层:用户能够按需启用 L7 性能,以取得 Istio 的全副性能,例如限速,故障注入,负载平衡,熔断等等。

ztunnel 是 ambient mesh 在每个节点上运行的共享代理,以 DaemonSet 的形式部署,处于相似于 CNI 的网格底层。ztunnel 在节点间构建零信赖的隧道(zero-trust tunnel, ztunnel),负责平安地连贯和验证网格内的元素。在 ambient mesh 中的工作负载的所有流量会重定向到本地的 ztunnel 进行解决,ztunnel 辨认流量的工作负载并为其抉择正确的证书以建设 mTLS 连贯。

ztunnel 实现了服务网格中的外围性能:零信赖,它会为启用了 ambient mesh 的 Namespace 中的工作负载创立一个平安覆盖层,提供 mTLS,遥测,认证和 L4 受权等性能,而无需终止或解析 HTTP。

在启用 ambient mesh 和创立平安覆盖层之后,能够选择性地为 namespace 启用 L7 性能,这容许命名空间实现全套的 Istio 性能,包含 Virtual Service、L7 遥测 和 L7 受权策略。waypoint proxy 能够依据所服务的 Namespace 的实时流量主动扩缩容,这将为用户节俭大量的资源。

 Istio 会为依据服务的 service account 创立相应的 waypoint proxy,能够帮忙用户在缩小资源耗费的状况下同时尽可能地放大故障域,参见下图 Model III。
 

2 Ambient Mesh 反对的环境和限度

目前已知 ambient mesh 仅反对以下环境,其余环境目前尚未通过测试。

  • GKE (_without_ Calico or Dataplane V2)
  • EKS
  • kind

并且 ambient mesh 还有许多限度,例如:

  • AuthorizationPolicy 在某些状况下没有预期的那么严格,或者基本有效。
  • 在某些状况下间接拜访 Pod IP 而不是 Service 的申请将有效。
  •  ambient mesh 下的服务无奈通过 LoadBalance 和 NodePort 的形式拜访,不过你能够部署一个入口网关(未启用 ambient mesh)以从内部拜访服务;
  • STRICT mTLS 不能齐全阻止明文流量。
  • 不反对 EnvoyFilter。

具体阐明请参见 [Ambient Mesh[1]](https://github.com/istio/isti…)。

3 应用 Eksctl 在 AWS 上创立 Kubernetes 集群

在本示例中,将应用 eksctl 在 AWS 上创立 EKS 集群来测试 Istio ambient mesh。[eksctl[2]](https://eksctl.io/) 是一个用于治理 EKS(Amazon 托管 Kubernetes 服务)的 CLI 工具。无关 eksctl 的装置和应用参见 [eksctl Getting started[3]](https://eksctl.io/introductio…)。

创立集群配置文件 cluster.yaml,咱们将创立一个 2 个 Worker 节点的 EKS 集群,每个节点资源为 2C8G,集群版本为 1.23。

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: aws-demo-cluster01
  region: us-east-1
  version: '1.23'

nodeGroups:
  - name: ng-1
    instanceType: m5.large
    desiredCapacity: 2
    volumeSize: 100
    ssh:
      allow: true # will use ~/.ssh/id_rsa.pub as the default ssh key

执行以下命令,创立 EKS 集群。

eksctl create cluster -f cluster.yaml

创立实现后,查看 EKS 集群。

> eksctl get cluster
NAME            REGION        EKSCTL CREATED
aws-demo-cluster01    us-east-1    True

执行以下命令,将 aws-demo-cluster01 集群的 kubeconfig 文件更新到 ~/.kube/config 文件中,让咱们本地的 kubectl 工具能够拜访到 aws-demo-cluster01 集群。

aws eks update-kubeconfig --region us-east-1 --name aws-demo-cluster01

无关 aws CLI 工具的装置参见 [Installing or updating the latest version of the AWS CLI[4]](https://docs.aws.amazon.com/c…),aws CLI 的认证参见 [Configuration basics[5]](https://docs.aws.amazon.com/c…)。

4 下载 Istio

依据对应操作系统下载反对 ambient mesh 的 istioctl 二进制文件和示例资源文件,参见 [Istio 下载 [6]](https://gcsweb.istio.io/gcs/i…)。其中 istioctl 的二进制文件能够在 bin 目录中找到,示例资源文件能够在 samples 目录中找到。

5 部署示例利用

部署 Istio 示例的 Bookinfo 应用程序,以及 sleep 和 notsleep 两个客户端。sleep 和 notsleep 能够执行 curl 命令来发动 HTTP 申请。

kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
kubectl apply -f https://raw.githubusercontent.com/linsun/sample-apps/main/sleep/sleep.yaml
kubectl apply -f https://raw.githubusercontent.com/linsun/sample-apps/main/sleep/notsleep.yaml

以后咱们部署的 istio 和利用的 Pod 和 Service 如下所示。

6 部署 Istio

执行以下命令,装置 Istio,并指定 profile=ambient 参数部署 ambient mesh 相干的组件。

istioctl install --set profile=ambient

如果装置胜利将会输入以下后果。

✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ CNI installed
✔ Installation complete

装置实现当前咱们在 istio-system 命名空间内能够看到以下组件:

  • istiod:Istio 的外围组件。
  • istio-ingressgateway:治理进出集群的南北向流量,在本示例中咱们不会用到 istio-ingressgateway。
  • istio-cni:为退出 ambient mesh 的 Pod 配置流量重定向,将 Pod 的进出流量重定向到雷同节点的 ztunnel 上。
  • ztunnel:ztunnel 在节点间构建零信赖的隧道,提供 mTLS,遥测,认证和 L4 受权等性能。

    > kubectl get pod -n istio-system
    NAME                                   READY   STATUS    RESTARTS   AGE
    istio-cni-node-gfmqp                   1/1     Running   0          100s
    istio-cni-node-t2flv                   1/1     Running   0          100s
    istio-ingressgateway-f6d95c86b-mfk4t   1/1     Running   0          101s
    istiod-6c99d96db7-4ckbm                1/1     Running   0          2m23s
    ztunnel-fnjg2                          1/1     Running   0          2m24s
    ztunnel-k4jhb                          1/1     Running   0          2m24s                       

7 抓包设置

为了更直观地察看流量的拜访状况,咱们能够对 Pod 进行抓包,然而利用 Pod 并没有装置相干的抓包工具,这时候咱们能够应用 kubectl debug 工具创立一个 ephemeral 长期容器共享容器的命名空间来进行调试。无关 kubectl debug 详情请参见 [调试运行中的 Pod[7]](https://kubernetes.io/zh-cn/d…)。

在 4 个终端别离执行以下命令,对 sleep 和 productpage 以及两个节点上的 ztunnel Pod 进行抓包。--image 参数指定长期容器的镜像,这里应用的 nicolaka/netshoot 镜像中预装了 tcpdump, tshark, termshark 等罕用的网络抓包工具。

kubectl debug -it sleep-55697f8897-n2ldz  --image=nicolaka/netshoot 
kubectl debug -it productpage-v1-5586c4d4ff-z8jbb --image=nicolaka/netshoot
kubectl debug -it -n istio-system ztunnel-fnjg2 --image=nicolaka/netshoot 
kubectl debug -it -n istio-system ztunnel-k4jhb --image=nicolaka/netshoot

在 4 个终端别离执行 termshark -i eth0 命令,对 Pod 的 eth0 网卡进行抓包。因为 istio-cni 会继续对 ztunnel 发动门路为 /healthz/ready 的 HTTP 衰弱探测,为了防止该流量影响咱们的察看,在 2 个 ztunnel Pod 中的 termshark Filter 框中设置以下过滤条件。

# ztunnel-fnjg2,sleep 所在节点的 ztunnel
ip.addr==192.168.58.148 || ip.addr==192.168.13.108

# ztunnel-k4jhb,productpage 所在节点的 ztunnel
ip.addr==192.168.13.108

8 未应用 Ambient Mesh 治理流量

因为以后 default Namespace 还没有退出 ambient mesh,此时利用的流量并不会通过 ztunnel,Pod 之间通过 kubernetes 的 Service 进制进行通信,Pod 之间的流量也不会进行 mTLS 加密,而是以明文的形式进行流传。

应用 sleep 向 productpage 发动一次申请。

kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | head -n1

# 返回后果,响应后果的第一行内容
<!DOCTYPE html>

查看 sleep 和 productpage 的抓包后果能够看到,sleep(192.168.58.148)拜访 productpage Service 名称 DNS 解析后的 service IP(10.100.171.143),通过 kubernetes Service 的转发后,最终拜访到 productpage 的理论 Pod IP(192.168.13.108)。

此时 ambient mesh 还未接管 default Namespace 的流量,因而在 ztunnel 上不会抓到相干的数据包。

9 将 Default Namespace 退出 Ambient Mesh(L4 性能)

为 default Namespace 增加 istio.io/dataplane-mode=ambient 标签,示意将该 Namespace 退出到 ambient mesh 中。

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

一旦 Namespace 退出 ambient mesh,istio-cni DaemonSet 就会为该 Namespace 中的 Pod 设置 iptables 重定向规定,将 Pod 的所有出入流量重定向到运行在雷同节点的 ztunnel 上。

9.1 MTLS 流量加密

ztunnel 会为启用了 ambient mesh 的 Namespace 中的工作负载创立一个平安覆盖层,提供 mTLS,遥测,认证和 L4 受权等性能。

为了不便查看,能够先革除先前在 sleep 和 productpage 上抓到的报文。

而后应用 sleep 向 productpage 发动一次申请。

kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | head -n1

在 sleep 和 productpage 上仍然能够抓到明文的数据包,只是这回在 productpage 上抓到的数据包的源 IP 变为的 sleep 所在节点的 ztunnel 的 IP 地址。

在 sleep 节点所在的 ztunnel 上咱们能够抓到 sleep 发过来的明文的数据包,ztunnel 会对数据包进行加密当前发送给 productpage 节点上的 ztunnel。productpage 节点上的 ztunnel 收到加密的数据包后,进行解密,而后发送给 productpage。

咱们还能够在 sleep 和 productpage 所在节点的 ztunnel 的日志中看到拜访记录。查看 outbound 方向的流量日志(sleep -> sleep node 上的 ztunnel)。

kubectl logs -n istio-system ztunnel-fnjg2 -f

咱们能够看到 outbound 流量的日志中有(no waypoint proxy)的字样,ambient mesh 默认只进行 L4 解决,不会进行 L7 解决。因而此时流量只会通过 ztunnel,不会通过 waypoint proxy。

查看 inbound 方向的流量日志(productpage 上的 ztunnel -> productpage)。

kubectl logs -n istio-system ztunnel-k4jhb -f

9.2 L4 受权策略

平安覆盖层能够实现简略的 L4 受权策略,如下所示创立一个 AuthorizationPolicy,只容许 Service Account 是 sleep 的用户拜访标签是 app=productpage 利用。

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: productpage-viewer
 namespace: default
spec:
 selector:
   matchLabels:
     app: productpage
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/ns/default/sa/sleep"]
EOF

别离在 sleep 和 notsleep 上执行以下申请,因为以后还没有启用 L7 解决,因而还无奈针对 HTTP 申请办法,门路等条件进行限度。

# 胜利
kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | head -n1
# 胜利
kubectl exec deploy/sleep -- curl -XDELETE -s http://productpage:9080/ | head -n1
# 失败,只容许 sa 是 sleep 的用户
kubectl exec deploy/notsleep -- curl -s http://productpage:9080/ | head -n1

10 启用 L7 性能

要为服务启用 L7 网格能力,须要显式创立一个 Gateway,留神创立的 Gateway 资源中的 gatewayClassName 必须设置为 istio-mesh,这样 Istio 才会为 productpage 创立对应的 waypoint proxy。任何发往 productpage 服务的流量都将通过 waypoint proxy 这个 L7 代理进行解决。

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: Gateway
metadata:
 name: productpage
 annotations:
   istio.io/service-account: bookinfo-productpage
spec:
 gatewayClassName: istio-mesh
EOF

查看 Istio 为 productpage 创立的 waypoint proxy。

从 sleep 拜访 productpage。

kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | head -n1

查看 outbound 方向的流量日志(sleep -> sleep node 上的 ztunnel -> waypoint proxy)。

kubectl logs -n istio-system ztunnel-fnjg2 -f

从上面的日志中能够看到(to server waypoint proxy)的字样,阐明申请发往 waypoint proxy 进行解决。

查看 inbound 方向的流量日志(productpage 上的 ztunnel -> productpage)。

kubectl logs -n istio-system ztunnel-k4jhb -f

10.1 L7 受权策略

接下来更新 AuthorizationPolicy 只容许 Service Account 是 sleep 的用户通过 GET 的形式拜访标签是 app=productpage 利用。

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: productpage-viewer
 namespace: default
spec:
 selector:
   matchLabels:
     app: productpage
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/ns/default/sa/sleep"]
   to:
   - operation:
       methods: ["GET"]
EOF

别离在 sleep 和 notsleep 上执行以下申请,这次在 sleep 上执行 HTTP DELETE 申请也会被回绝了。

# 胜利
kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | head -n1
# 失败,RBAC 谬误,因为不是 GET 申请
kubectl exec deploy/sleep -- curl -X DELETE -s http://productpage:9080/ | head -n1
# 失败,RBAC 谬误,只容许 sa 是 sleep 的用户
kubectl exec deploy/notsleep -- curl -s http://productpage:9080/  | head -n1

10.2 可观测性

在 productpage waypoint proxy 上能够查看所有对 productpage 服务申请的 L7 指标。

kubectl exec deploy/bookinfo-productpage-waypoint-proxy -- curl -s http://localhost:15020/stats/prometheus | grep istio_requests_total

10.3 流量管制

首先为 reviews 服务创立一个 gateway,启用 L7 能力。

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: Gateway
metadata:
 name: reviews
 annotations:
   istio.io/service-account: bookinfo-reviews
spec:
 gatewayClassName: istio-mesh
EOF

而后别离创立 VirtualService 和 DestinationRule 来管制流量以 90/10 的比例发往 v1 版本和 v2 版本的 reviews 服务。

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 90
    - destination:
        host: reviews
        subset: v2
      weight: 10
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3
EOF

执行以下命令,从 sleep 往 productpage 发送 10 个申请,能够看到大概有 10% 的流量流向了 reviews-v2。

# 留神拜访门路是 http://productpage:9080/productpage,会调用 reviews 服务
kubectl exec -it deploy/sleep -- sh -c 'for i in $(seq 1 10); do curl -s http://productpage:9080/productpage | grep reviews-v.-; done'

# 返回后果
 <u>reviews-v1-7598cc9867-dh7hp</u>
 <u>reviews-v1-7598cc9867-dh7hp</u>
 <u>reviews-v1-7598cc9867-dh7hp</u>
 <u>reviews-v1-7598cc9867-dh7hp</u>
 <u>reviews-v2-6bdd859457-7lxhc</u>
 <u>reviews-v1-7598cc9867-dh7hp</u>
 <u>reviews-v1-7598cc9867-dh7hp</u>
 <u>reviews-v1-7598cc9867-dh7hp</u>
 <u>reviews-v1-7598cc9867-dh7hp</u>
 <u>reviews-v2-6bdd859457-7lxhc</u>

10.4 故障注入

为 productpage 服务创立一个 VirtualService,在申请中注入 5s 的延时。

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: productpage
spec:
  hosts:
    - productpage
  http:
  - route:
    - destination:
        host: productpage
    fault:
      delay:
         percentage:
            value: 100.0
         fixedDelay: 5s
EOF

从 sleep 拜访 productpage,能够看到申请耗费的工夫大概在 5s 左右。

> kubectl exec deploy/sleep -- time curl -s http://productpage:9080 | head -n 1

# 返回后果
<!DOCTYPE html>
real    0m 5.04s
user    0m 0.00s
sys        0m 0.00s

11 清理环境

# 卸载 Istio
istioctl uninstall -y --purge && istioctl delete ns istio-system
# 删除示例利用
kubectl delete -f samples/bookinfo/platform/kube/bookinfo.yaml
kubectl delete -f https://raw.githubusercontent.com/linsun/sample-apps/main/sleep/sleep.yaml
kubectl delete -f https://raw.githubusercontent.com/linsun/sample-apps/main/sleep/notsleep.yaml
# 删除集群
eksctl delete cluster aws-demo-cluster01

12 体验 Demo

想要疾速体验 ambient mesh 的敌人也能够在 [solo.io 官网 [8]](https://academy.solo.io/get-s…) 上尝试上手教程。

13 参考资料

  • [1] Ambient Mesh: https://github.com/istio/isti…
  • [2] eksctl: https://eksctl.io/
  • [3] eksctl Getting started: https://eksctl.io/introductio…
  • [4] Installing or updating the latest version of the AWS CLI: https://docs.aws.amazon.com/c…
  • [5] Configuration basics: https://docs.aws.amazon.com/c…
  • [6] Istio 下载: https://gcsweb.istio.io/gcs/i…
  • [7] 调试运行中的 Pod: https://kubernetes.io/zh-cn/d…
  • [8] solo.io 官网: https://academy.solo.io/get-s…
  • [9] Ambient Mesh Security Deep Dive: https://istio.io/latest/blog/…
  • [10] Get Started with Istio Ambient Mesh: https://istio.io/latest/blog/…
  • [11] Istio Ambient Mesh Launch Demo: https://www.youtube.com/watch…
  • [12] Istio 无 sidecar 代理数据立体 ambient 模式简介: https://lib.jimmysong.io/blog…
  • [13] 译文:Istio Ambient 模式平安架构深度解析: https://www.zhaohuabing.com/p…
  • [14] 如何评估 Istio 新推出的 Ambient 模式?: https://mp.weixin.qq.com/s/98…
  • [15] 初探 Istio Ambient 模式: https://mp.weixin.qq.com/s/YA…
  • [16] Istio Ambient 模式 HBONE 隧道原理详解 – 上: https://mp.weixin.qq.com/s/ks…
  • [17] Create a kubeconfig for Amazon EKS: https://docs.aws.amazon.com/e…
  • [18] Beyond Istio OSS —— Istio 服务网格的现状与将来: https://jimmysong.io/blog/bey…
退出移动版