初试Istio on ASK
ASK作为阿里云Serverless Kubernetes平台,不仅有免运维、秒级弹性、超大Pod容量、弹性预测等重磅能力,更重要的是它依然是一个标准Kubernetes平台。本文通过在ASK上试用Istio部署微服务应用来验证ASK对标准Kubernetes的兼容性。Istio作为Service Mesh(服务网格)的领导解决方案,一方面本身足够复杂具有代表性,另一方面它也代表了云原生时代微服务架构的趋势具有参考意义。
创建集群
试用Istio前,需要准备一个ASK集群。登录阿里云控制台,选择 产品与服务 > 容器服务 Kubernetes 版,在左侧边栏选择 集群 进入集群列表页面。点击右上角 创建集群 开始创建集群,配置集群参数如下:
- 集群名称:hello-istio
- 集群规格:Pro版
- 地域:美国(硅谷)
- 付费类型:按量付费
- Kubernetes 版本:1.20.11-aliyun.1
- 专有网络:自动创建
- Service CIDR:172.21.0.0/20
- API Server 访问:标准型I(slb.s2.small)
- 使用 EIP 暴露 API Server:是
- 时区:Aisa/Shanghai(UTC+08:00)
- 服务发现:CoreDNS
- 使用日志服务:创建新 Project
确认配置后点击 创建集群 进入等待集群创建完成。Istio依赖DNS服务,这里选择创建集群时默认安装CoreDNS
组件。
集群创建完成后,进入 集群列表 > hello-istio > 详情 > 集群信息 > 连接信息 页面,复制 公网访问 内容到本地/tmp/kube/config
文件,并通过如下命令配置好kubelet
:
$ export KUBECONFIG=/tmp/kube/config
试用Istio
kubectl
配置好后就可以开始在集群安装和试用Istio。
下载Istio
进入Istio发布页面下载针对操作系统的安装文件,也可以通过如下命令下载并提取最新版本:
$ curl -L https://istio.io/downloadIstio | sh -
因为我本机~/bin
目录已加入PATH,这里我将提取的Istio目录复制~/bin
目录,并建好软链接。
$ cp istio-1.13.3 ~/bin
$ cd ~/bin
$ ln -s istio-1.13.3/bin/istioctl
$ ls -al ~/bin/
total 28
drwxr-xr-x 5 feilong.wfl staff 160 5 4 22:40 ./
drwxr-xr-x+ 95 feilong.wfl staff 3040 5 8 22:30 ../
drwxr-x--- 9 feilong.wfl staff 288 4 15 00:48 istio-1.13.3/
lrwxr-xr-x 1 feilong.wfl staff 25 5 4 22:40 istioctl -> istio-1.13.3/bin/istioctl*
如果istioctl --help
命令输出正常,则istioctl已正确配置。
安装Istio
- 本次安装采用demo profile,它包含了一组专为测试准备的功能集合,另外还有用户生产或性能测试的配置组合。
$ istioctl install --set profile=demo -y
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete
- 给命名空间添加标签,指示Istio在部署应用的时候,自动注入Envoy边车代理:
$ kubectl label namespace default istio-injection=enabled
namespace/default labeled
部署示例应用
- 部署Bookinfo示例应用:
$ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/platform/kube/bookinfo.yaml
service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created
- 检查Pod已就绪:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-79f774bdb9-t2jhq 2/2 Running 0 2m54s
productpage-v1-6b746f74dc-qc9lg 2/2 Running 0 2m46s
ratings-v1-b6994bb9-tmbh6 2/2 Running 0 2m51s
reviews-v1-545db77b95-xdhp4 2/2 Running 0 2m49s
reviews-v2-7bf8c9648f-4gn6f 2/2 Running 0 2m48s
reviews-v3-84779c7bbc-jfndj 2/2 Running 0 2m48s
要等待并确保所有的Pod达到此状态:就绪状态(READY)的值为2/2 、状态(STATUS)的值为Running。基于平台的不同,这个操作过程可能会花费几分钟的时间。
- 检查Service已就绪:
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details ClusterIP 172.21.11.168 <none> 9080/TCP 59s
kubernetes ClusterIP 172.21.0.1 <none> 443/TCP 33m
productpage ClusterIP 172.21.0.124 <none> 9080/TCP 51s
ratings ClusterIP 172.21.9.7 <none> 9080/TCP 57s
reviews ClusterIP 172.21.13.223 <none> 9080/TCP 55s
- 确保网页服务正常。如果命令返回页面标题,则应用已在集群中运行。
$ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -s productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
对外开放服务
现在,BookInfo应用已经部署,但还不能被外界访问。 要开放访问,需要创建Istio入站网关(Ingress Gateway), 它会把一个路径路由到网格内的服务。
- 把应用关联到Istio网关:
$ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/bookinfo-gateway.yaml
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created
- 确保配置文件没有问题:
$ istioctl analyze
✔ No validation issues found when analyzing namespace: default.
确定入站IP和端口
使用如下命令为访问网关设置INGRESS_HOST
和INGRESS_PORT
两个变量:
$ export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
$ export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
设置变量GATEWAY_URL
,并确保IP地址和端口均成功的赋值给了该变量:
$ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
$ echo "$GATEWAY_URL"
47.88.21.82:80
验证外部访问
运行下面命令,获取Bookinfo应用的外部访问地址:
$ echo "http://$GATEWAY_URL/productpage"
http://47.88.21.82:80/productpage
复制上面命令的输出地址到浏览器并访问,确认Bookinfo已经实现了外部访问。刷新页面,发现Book Reviews的显示样式会不断变化。
查看仪表盘
仪表盘能帮助了解服务网格的结构、展示网络的拓扑结构、分析网格的健康状态。
- 首先安装Kiali和其他插件,等待部署完成。
$ kubectl apply -f ~/bin/istio-1.13.3/samples/addons
$ kubectl rollout status deployment/kiali -n istio-system
Waiting for deployment "kiali" rollout to finish: 0 of 1 updated replicas are available...
deployment "kiali" successfully rolled out
- 访问Kiali仪表板。
$ istioctl dashboard kiali
- 在左侧的导航菜单,选择 Graph,然后在 Namespace 下拉列表中,选择 default。 Kiali仪表板展示了网格的概览、以及Bookinfo示例应用的各个服务之间的关系。 它还提供过滤器来可视化流量的流动。
添加默认目标规则
使用Istio控制Bookinfo版本路由前,需要先在目标规则中定义好可用的版本。运行以下命令为Bookinfo服务创建默认的目标规则:
$ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/destination-rule-all.yaml
destinationrule.networking.istio.io/productpage created
destinationrule.networking.istio.io/reviews created
destinationrule.networking.istio.io/ratings created
destinationrule.networking.istio.io/details created
等待几秒钟,目标规则生效。您可以使用如下命令查看目标规则:
$ kubectl get destinationrules
NAME HOST AGE
details details 30s
productpage productpage 32s
ratings ratings 31s
reviews reviews 32s
路由所有流量到v1版本
运行以下命令创建Virtual Service
将所有流量路由到微服务的v1版本:
$ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/virtual-service-all-v1.yaml
virtualservice.networking.istio.io/productpage created
virtualservice.networking.istio.io/reviews created
virtualservice.networking.istio.io/ratings created
virtualservice.networking.istio.io/details created
您可以通过再次刷新Bookinfo应用程序的/productpage
页面测试新配置。请注意,无论您刷新多少次,页面的评论部分都不会显示评级星标。这是因为当前已将Istio配置为评论服务的所有流量路由到版本reviews:v1
,而此版本的服务不访问星级评分服务。
基于用户身份的路由
接下来将更改路由配置,实现将来自特定用户的所有流量路由到特定的服务版本。示例中来自名为Jason用户的所有流量将被路由到服务review:v2
。
Istio对用户身份没有任何特殊的内置机制。本例中,
productpage
服务在所有到reviews
服务的HTTP请求中都增加了一个自定义的end-user
请求头,从而达到效果。
- 运行以下命令以启用基于用户的路由:
$ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
virtualservice.networking.istio.io/reviews created
- 确保规则已创建:
$ kubectl get virtualservice reviews -o yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.istio.io/v1alpha3","kind":"VirtualService","metadata":{"annotations":{},"name":"reviews","namespace":"default"},"spec":{"hosts":["reviews"],"http":[{"match":[{"headers":{"end-user":{"exact":"jason"}}}],"route":[{"destination":{"host":"reviews","subset":"v2"}}]},{"route":[{"destination":{"host":"reviews","subset":"v1"}}]}]}}
creationTimestamp: "2022-05-15T16:05:55Z"
generation: 1
name: reviews
namespace: default
resourceVersion: "1984849"
uid: f3bd3dcb-d83c-4a75-9511-1fc9308ca05b
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
-
在Bookinfo应用程序的
/productpage
上,以用户jason
身份登录。刷新浏览器,看到每个评论旁边显示星级评分。 -
以其他用户身份登录,刷新浏览器。发现星级评分消失了。
原理和限制
数据平面,Istio通过向Pod注入的Sidecar代理(istio-proxy)来负责协调和控制微服务之前的所有网络通信。为了让Sidecar代理(istio-proxy)劫持业务容器流量,Istio需要向Pod所在网络下发iptables规则。常规安装模式下,iptables规则下发是由Istio向Pod注入的初始化容器istio-init完成。向Pod网络下发iptables规则需要容器可以使用NET_ADMIN
和NET_RAW
两个高权限的能力(Capabilities)。ASK集群中这两个高权限能力受ASK Pod Security Policy和ECI Container Security Policy的影响。
ASK Pod Security Policy的CAPS为*
,表示没有限制。
$ kubectl get psp
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP READONLYROOTFS VOLUMES
ack.privileged true * RunAsAny RunAsAny RunAsAny RunAsAny false *
ECI Container Security Policy允许通过容器安全上下文配置即可。Istio中Pod注入模板文件~/bin/istio-1.13.3/manifests/charts/istio-control/istio-discovery/files/injection-template.yaml
包含如下代码:不启用Istio CNI插件将添加NET_ADMIN
和NET_RAW
两个高权限能力:
securityContext:
allowPrivilegeEscalation: {{ .Values.global.proxy.privileged }}
privileged: {{ .Values.global.proxy.privileged }}
capabilities:
{{- if not .Values.istio_cni.enabled }}
add:
- NET_ADMIN
- NET_RAW
{{- end }}
drop:
- ALL
所以从原理上分析当前ASK集群使用Istio没有兼容性问题。
总结
本次在ASK上试用Istio这类高复杂度的软件,未发现兼容性问题。又从原理上正面分析论证了产生兼容性问题的可能性较低。目前来看,ASK对原生Kubernetes还是有着极好的兼容性。后续将在ASK集群上深入探索Istio其他功能,以进一步验证ASK对原生Kubernetes的兼容性。
参考: