目标
- 在阿里云容器服务 Kubernetes 集群上部署 Istio 服务网格
- 实践灰度发布、故障注入、熔断等 Istio 流量管理特性
准备工作
- 安装和设置 kubectl 客户端,请参考不同的操作系统,如果已经安装请忽略:
- macOS
curl -LO https://kubectl.oss-cn-hangzhou.aliyuncs.com/macos/kubectlchmod +x ./kubectlsudo mv ./kubectl /usr/local/bin/kubectlkubectl --help
- Linux
curl -LO https://kubectl.oss-cn-hangzhou.aliyuncs.com/linux/kubectlchmod +x ./kubectlsudo mv ./kubectl /usr/local/bin/kubectlkubectl --help
- Windows
把 https://kubectl.oss-cn-hangzhou.aliyuncs.com/windows/kubectl.exe 放到系统PATH路径下
kubectl --help
配置 kubectl 连接 Kubernetes 集群的配置,可参考文档 通过kubectl连接Kubernetes集群
实验步骤
部署Istio
- 登录容器服务控制台,在集群列表中选择一个集群,打开更多 - 部署 Istio
- 保持默认配置,点击"部署 Istio"
- 等待完成后,Istio 已经成功部署在 Kubernetes 集群中
- 使用 kiali 查看服务网格可视化
kubectl port-forward -n istio-system "$(kubectl get -n istio-system pod --selector=app=kiali -o jsonpath='{.items..metadata.name}')" 20001
在本地浏览器中访问 http://localhost:20001 ,使用默认账户 admin/admin 登录
灰度发布
- 创建命名空间并开启 Sidecar 自动注入:单击左侧导航栏中的集群 > 命名空间,进入命令空间页面,创建一个名称为
demo
的命名空间,并为其添加一个istio-injection:enabled
的标签
- 单击左侧导航栏中服务网格 > 虚拟服务,进入虚拟服务(Virtual Service)页面,点击创建,创建一个简单的示例应用,指定应用名称为
istio-app
,指定应用版本为v1
,选择刚刚创建的命名空间demo
- 配置应用容器,使用如下镜像:
registry.cn-beijing.aliyuncs.com/test-node/node-server:v1
- 配置服务,服务名称为
istio-app-svc
,类型为虚拟集群 IP ,服务端口和容器端口均为8080
- 提交应用配置,将会自动创建 Deployment、Service、DestinationRule、VirtualService
- 单击导航栏中的应用 > 容器组,确认所有的 Pod 都已经正确的定义和启动
- 创建服务客户端测试应用
kubectl apply -n demo -f - <<EOFapiVersion: v1kind: Servicemetadata: name: sleep labels: app: sleepspec: ports: - port: 80 name: http selector: app: sleep---apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: sleepspec: replicas: 1 template: metadata: labels: app: sleep spec: containers: - name: sleep image: pstauffer/curl command: ["/bin/sleep", "3650d"] imagePullPolicy: IfNotPresentEOF
- 在测试应用的 Pod 中访问 Istio 应用:登录到 sleep 应用的 Pod 中
kubectl exec -it -n demo "$(kubectl get -n demo pod --selector=app=sleep -o jsonpath='{.items..metadata.name}')" sh
执行如下命令调用之前部署的 Istio 应用:
for i in `seq 1000`docurl http://istio-app-svc.demo:8080;echo '';sleep 1;done;
可以看到返回的信息:
Hello from v1Hello from v1Hello from v1
- 单击左侧导航栏中服务网格 > 虚拟服务,进入虚拟服务(Virtual Service)页面,找到
istio-app-svc
服务,点击管理,在版本管理中,点击增加灰度版本,新的版本指定为v2
在容器配置中使用以下镜像:
registry.cn-beijing.aliyuncs.com/test-node/node-server:v2
在灰度策略中选择基于流量比例发布,流量比例 50%
- 提交灰度发布后,查看 sleep 应用的调用结果,可以看到,
v1
和v2
版本的返回结果
Hello from v1Hello from v2Hello from v1Hello from v1Hello from v2Hello from v1
- 在 kiali 中查看,可以确认,调用被分发到两个版本中
故障注入
- 目前应用工作正常,我们为 istio-app-svc 注入故障,以测试整个应用的弹性。在 istio-app-svc 的管理界面中,打开故障注入策略,选择注入中断故障,百分比 50%,状态码 503
- 提交后,继续查看 sleep 应用的调用结果,即可看到 istio-app-svc 服务约有 50% 的概率无法访问,输出
fault filter abort
。
Hello from v1Hello from v1Hello from v1fault filter abortfault filter abortfault filter abortHello from v1Hello from v2fault filter abortHello from v2Hello from v2
同时,在 kiali 可视化界面中,也可以看到 sleep 服务对 istio-app-svc 服务的调用有 50% 左右的失败比例
- 除此之外,我们也可以为服务注入时延故障,例如在上述界面中,选择时延故障,为 50% 的请求添加 5s 的时延
- 确认提交之后,我们可以看到,部分调用的耗时显著增加。在 kiali 中也可以查看调用的平均请求耗时
- 删除故障注入策略和灰度版本
v2
熔断
- 在 DestinationRule 中设置熔断规则
kubectl delete destinationrule -n demo istio-app-svckubectl apply -n demo -f - <<EOFapiVersion: networking.istio.io/v1alpha3kind: DestinationRulemetadata: name: istio-app-svcspec: host: istio-app-svc trafficPolicy: connectionPool: tcp: maxConnections: 1 http: http1MaxPendingRequests: 1 maxRequestsPerConnection: 1 subsets: - labels: version: v1 name: v1 - labels: version: v2 name: v2EOF
- 部署一个 HTTP 客户端,用于负载测试
kubectl apply -n demo -f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/sample-client/fortio-deploy.yaml
- 在上面的熔断设置中指定了
maxConnections: 1
以及http1MaxPendingRequests: 1
。这意味着如果超过了一个连接同时发起请求,Istio 就会熔断,阻止后续的请求或连接。因此我们以并发数为 3,发出 100 个请求:
FORTIO_POD=$(kubectl -n demo get pod | grep fortio | awk '{ print $1 }')kubectl -n demo exec -it $FORTIO_POD -c fortio /usr/bin/fortio -- load -c 3 -qps 0 -n 100 -loglevel Warning http://istio-app-svc:8080
从结果中,可以看到,有超过 40% 的请求被 Istio 阻断了。
Code 200 : 57 (57.0 %)Code 503 : 43 (43.0 %)Response Header Sizes : count 100 avg 130.53 +/- 113.4 min 0 max 229 sum 13053Response Body/Total Sizes : count 100 avg 242.14 +/- 0.9902 min 241 max 243 sum 24214All done 100 calls (plus 0 warmup) 0.860 ms avg, 2757.6 qps
在 kiali 中观察可以发现,这部分请求并没有真正到达 istio-app-svc 的 Pod
- 通过查询 istio-proxy 的状态,可以获得更多信息,
upstream_rq_pending_overflow
的值即为被熔断策略阻止的请求数
kubectl -n demo exec -it $FORTIO_POD -c istio-proxy -- sh -c 'curl localhost:15000/stats' | grep istio-app-svc | grep pendingcluster.outbound|8080|v1|istio-app-svc.demo-ab.svc.cluster.local.upstream_rq_pending_active: 0cluster.outbound|8080|v1|istio-app-svc.demo-ab.svc.cluster.local.upstream_rq_pending_failure_eject: 0cluster.outbound|8080|v1|istio-app-svc.demo-ab.svc.cluster.local.upstream_rq_pending_overflow: 99cluster.outbound|8080|v1|istio-app-svc.demo-ab.svc.cluster.local.upstream_rq_pending_total: 199
清理实验环境
执行以下命令:
kubectl delete ns demo
本文作者:指北
阅读原文
本文为云栖社区原创内容,未经允许不得转载。