非容器应用与K8s工作负载的服务网格化实践-4 基于ASM的POD和VM互访实践-GRPC协议篇

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 为了实现高可用,非容器应用通常有一套服务注册和发现的机制。相对而言,kubernetes容器服务为POD提供了统一的基于dns的注册和发现机制。对于http协议的非容器应用的迁移,因为都是基于dns机制,切换成本交底。而对于使用非http协议的非容器应用,服务注册和发现这个技术点为迁移带来了额外的困难。如何从非容器的注册和发现大脑最终迁移到kubernetes的注册和发现大脑,目前尚没有广泛认可的方案。目前常见的讨论是双脑方案,就是让非容器应用在启动时同时向两套大脑注册,并从两套中发现依赖服务,然后逐步实现向kubernetes大脑过度。这套方案的优点是可以通过随时摆动来保证可用性。

为了实现高可用,非容器应用通常有一套服务注册和发现的机制。相对而言,kubernetes容器服务为POD提供了统一的基于dns的注册和发现机制。对于http协议的非容器应用的迁移,因为都是基于dns机制,切换成本交底。而对于使用非http协议的非容器应用,服务注册和发现这个技术点为迁移带来了额外的困难。

如何从非容器的注册和发现大脑最终迁移到kubernetes的注册和发现大脑,目前尚没有广泛认可的方案。目前常见的讨论是双脑方案,就是让非容器应用在启动时同时向两套大脑注册,并从两套中发现依赖服务,然后逐步实现向kubernetes大脑过度。这套方案的优点是可以通过随时摆动来保证可用性。

我个人比较倾向于彻底的kubernetes一脑模式。相比多脑,一脑的复杂度会极大下降。遗留大脑集群保持现状,kubernetes大脑集群使用新的方案。这样可以将服务发现和网格化解耦为两个独立的问题。借助服务网格的蓝绿部署/流量转移,可以将验证完毕依赖关系的集群逐步放行并最终替换遗留大脑集群。这个方案最有挑战的地方是如何在不改变非容器应用代码的前提下,将其底层协议替换。如果可以替换为grpc,那么就可以按照本篇的实践实现网格化。目前这个想法还很不成熟,期待交流。

1 POD和VM互访

路由规则

服务网格的流量转移是一脑方案的核心。首先需要明确的是,网格化的服务链路都会经过sidecar,sidecar内部(envoy)实现了对grpc的负载均衡,grpc协议的上游服务通过长链接和下游服务各个节点保持连接,在不配置流量转移的情况下,上游请求会均匀地路由到下游各个节点。

与http协议通过path配置流量转移类似,grpc的配置是通过service/method或者service.method来定义匹配规则的。grpc的路由配置示意如下。

spec:
  hosts:
    - hello2-svc
  http:
    - name: grpc-hello-route
      match:
        - uri:
            prefix: /org.feuyeux.grpc.Greeter/SayHello
      route:
        - destination:
            host: hello2-svc
            subset: v1
          weight: 30
        - destination:
            host: hello2-svc
            subset: v2
          weight: 60
        - destination:
            host: hello2-svc
            subset: v3
          weight: 10

搭建实验环境

本篇示例实验与前一篇相仿,不再冗述重复部分。我们希望路由到hello2 en/fr/es的流量比例为:30%:60%:10%。

示例(grpc_reciprocal_demo)包含如下元素:

  • hello1 deployment(镜像grpc_springboot_v1)
  • hello3 deployment(镜像grpc_springboot_v1)
  • hello2 docker containers(镜像grpc_springboot_v1/grpc_springboot_v2/grpc_springboot_v3)
  • 入口网关:istio-ingressgateway
  • 入口流量配置:gateway/virtualservice
  • hello1流量配置:hello1 service
  • hello2流量配置:hello2 service/hello2 virtualservice/hello2 destinationrule
  • hello3流量配置:hello3 service
  • hello2 serviceentry/hello2 workloadentry

与前一篇http所用示例类似,grpc示例使用的镜像为grpc_springboot-{version},是一个基于springboot开发的grpc服务(源代码在这里)。每个实例可以通过环境变量GRPC_HELLO_BACKEND定义下游服务。

启动hello2应用

通过如下命令分别在3个ecs节点上启动hello2的 docker container

#ssh1.sh
docker run \
--rm \
--network host \
--name http_v1 \
-e GRPC_HELLO_BACKEND=hello3-svc.grpc-reciprocal-hello.svc.cluster.local \
registry.cn-beijing.aliyuncs.com/asm_repo/grpc_springboot_v1:1.0.0
#ssh2.sh
docker run \
--rm \
--network host \
--name http_v2 \
-e GRPC_HELLO_BACKEND=hello3-svc.grpc-reciprocal-hello.svc.cluster.local \
registry.cn-beijing.aliyuncs.com/asm_repo/grpc_springboot_v2:1.0.0
#ssh3.sh
docker run \
--rm \
--network host \
--name http_v3 \
-e GRPC_HELLO_BACKEND=hello3-svc.grpc-reciprocal-hello.svc.cluster.local \
registry.cn-beijing.aliyuncs.com/asm_repo/grpc_springboot_v3:1.0.0

其他部分的搭建与前篇类似,可以参考前篇和本篇示例脚本,余文不在冗述。

grpcurl

相对于http的验证工具curl,我们使用grpcurl对grpc服务进行验证。

当grpc服务提供反射protocolbuf能力时,可以使用如下命令进行请求验证:

k exec "$hello1_pod" -c hello-v1-deploy -n grpc-reciprocal-hello \
  -- grpcurl -plaintext -d '{"name":"eric"}' \
  hello3-svc.grpc-reciprocal-hello.svc.cluster.local:7001 org.feuyeux.grpc.Greeter/SayHello | jq -r '.reply'
  
Hello eric(172.18.1.10)

如果上述命令返回错误,说明grpc服务无法反射protocolbuf,需要在执行grpccurl时,通过-import-path-proto参数提供proto文件。示意如下。

k exec "$hello1_pod" -c hello-v1-deploy -n grpc-reciprocal-hello -- \
grpcurl -plaintext -d '{"name":"eric"}' \
-import-path /opt -proto hello.proto \
hello3-svc.grpc-reciprocal-hello.svc.cluster.local:7001 org.feuyeux.grpc.Greeter/SayHello | jq -r '.reply'

Hello eric(172.18.1.10)

KUBE验证-POD和VM互访

初步掌握grpccurl命令后,我们验证基于grpc协议的POD和VM互访。请求从hello1 POD发向hello2 service,然后路由到各VM中的hello2 app,再由hello2 app请求到hello3 POD。

for i in {1..6}; do
  k exec "$hello1_pod" -c hello-v1-deploy -n grpc-reciprocal-hello \
    -- grpcurl -plaintext -d '{"name":"eric"}' localhost:7001 org.feuyeux.grpc.Greeter/SayHello | jq -r '.reply'
done
Hello eric(172.18.1.11)<-Hola eric(192.168.0.172)<-Hello eric(172.18.1.10)
Hello eric(172.18.1.11)<-Bonjour eric(192.168.0.171)<-Hello eric(172.18.1.10)
Hello eric(172.18.1.11)<-Hello eric(192.168.0.170)<-Hello eric(172.18.1.10)
...

MESH验证-全链路流量转移

最后部署gateway/virtualservice/destinationrule进行端到端验证。

IP=$(k -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

for i in {1..100}; do
  resp=$(grpcurl -plaintext -d '{"name":"eric"}' "$IP":7004 org.feuyeux.grpc.Greeter/SayHello | jq -r '.reply')
  echo "$resp" >>test_traffic_shift_result
done

echo "expected 30%(Hello eric)-60%(Bonjour eric)-10%(Hola eric):"
sort test_traffic_shift_result | grep -v "^[[:space:]]*$"| uniq -c | sort -nrk1
  57 Hello eric(172.18.1.11)<-Bonjour eric(192.168.0.171)<-Hello eric(172.18.1.10)
  32 Hello eric(172.18.1.11)<-Hello eric(192.168.0.170)<-Hello eric(172.18.1.10)
  11 Hello eric(172.18.1.11)<-Hola eric(192.168.0.172)<-Hello eric(172.18.1.10)

2 grpc基准测试

ghz

ghz是grpc协议的基准测试工具,功能与http协议下的apache benchfortio类似。我们可以通过ghz对服务网格内的grpc服务进行测试和调参。ghz的基本用法示意如下。

hello1_pod=$(k get pod -l app=hello1-deploy -n grpc-reciprocal-hello -o jsonpath={.items..metadata.name})

k exec "$hello1_pod" -c hello-v1-deploy -n grpc-reciprocal-hello -- \
  ghz --insecure -d '{"name":"eric"}' \
  --proto /opt/hello.proto \
  --call org.feuyeux.grpc.Greeter/SayHello \
  -n 2000 \
  -c 20 \
  -q 500 \
  localhost:7001
  • -n参数用来指定请求数量
  • -c参数用来指定并发数量
  • -q参数用来指定QPS

测试结果示意如下。

Summary:
  Count:        2000
  Total:        5.60 s
  Slowest:      851.86 ms
  Fastest:      4.88 ms
  Average:      54.51 ms
  Requests/sec: 357.21

Response time histogram:
  4.883 [1]     |
  89.580 [1919] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
  174.278 [43]  |∎
  258.976 [3]   |
  343.673 [5]   |
  428.371 [2]   |
  513.068 [4]   |
  597.766 [3]   |
  682.464 [0]   |
  767.161 [7]   |
  851.859 [13]  |

Latency distribution:
  10 % in 24.37 ms 
  25 % in 31.71 ms 
  50 % in 41.98 ms 
  75 % in 53.87 ms 
  90 % in 70.67 ms 
  95 % in 83.83 ms 
  99 % in 683.16 ms 

Status code distribution:
  [OK]   2000 responses   

上述结果表示RT/latency基本(1919/2000)落在90ms以内,平均54.51 ms,95%的请求延迟在83.83 ms以内,99 %段的延迟在683.16 ms,存在长尾,需要进一步优化服务网格的配置以及服务源代码。

trafficPolicy

通过修改hello2的DestinationRule可以随时调整连接池配置。我们可以结合基准测试,不断调整配置找到最佳性能点。示意如下。

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: hello2-dr
  namespace: grpc-reciprocal-hello
spec:
  host: hello2-svc
  subsets:
    - labels:
        version: v1
      name: v1
    - labels:
        version: v2
      name: v2
    - labels:
        version: v3
      name: v3
  trafficPolicy:
    connectionPool:
      http:
        http1MaxPendingRequests: 20
        http2MaxRequests: 100
        maxRequestsPerConnection: 10
        maxRetries: 1
      tcp:
        connectTimeout: 10s
        maxConnections: 10

到此,POD和VM互访的grpc协议流量管理讲述完毕。

本篇示例完整演示了非容器应用网格化过程中的一个比较经典的场景。覆盖到从istio-ingressgateway到deployment、workloadentry等各种CRD的配置,较完整地展示了POD和VM互访中遇到的各技术点的配置。

接下来,我们在此基础上,验证下POD和VM作为同一service的混合流量,如何实现流量转移。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
1月前
|
Prometheus Kubernetes 监控
k8s部署针对外部服务器的prometheus服务
通过上述步骤,您不仅成功地在Kubernetes集群内部署了Prometheus,还实现了对集群外服务器的有效监控。理解并实施网络配置是关键,确保监控数据的准确无误传输。随着监控需求的增长,您还可以进一步探索Prometheus生态中的其他组件,如Alertmanager、Grafana等,以构建完整的监控与报警体系。
120 60
|
1月前
|
Prometheus Kubernetes 监控
k8s部署针对外部服务器的prometheus服务
通过上述步骤,您不仅成功地在Kubernetes集群内部署了Prometheus,还实现了对集群外服务器的有效监控。理解并实施网络配置是关键,确保监控数据的准确无误传输。随着监控需求的增长,您还可以进一步探索Prometheus生态中的其他组件,如Alertmanager、Grafana等,以构建完整的监控与报警体系。
204 62
|
4天前
|
存储 Kubernetes 网络协议
k8s的无头服务
Headless Service 是一种特殊的 Kubernetes 服务,其 `spec:clusterIP` 设置为 `None`,不会分配 ClusterIP,通过 DNS 解析提供服务发现。与普通服务不同,Headless Service 不提供负载均衡功能,每个 Pod 都有唯一的 DNS 记录,直接映射到其 IP 地址,适用于有状态应用的场景,如与 StatefulSet 一起部署数据库。示例中通过创建 Nginx 的 StatefulSet 和 Headless Service,展示了如何直接访问单个 Pod 并进行内容修改。
15 3
|
7天前
|
运维 Kubernetes Shell
【赵渝强老师】K8s中Pod的临时容器
Pod 是 Kubernetes 中的基本调度单位,由一个或多个容器组成,包括业务容器、基础容器、初始化容器和临时容器。临时容器用于故障排查和性能诊断,不适用于构建应用程序。当 Pod 中的容器异常退出或容器镜像不包含调试工具时,临时容器非常有用。文中通过示例展示了如何使用 `kubectl debug` 命令创建临时容器进行调试。
|
7天前
|
Kubernetes 调度 容器
【赵渝强老师】K8s中Pod中的业务容器
Pod 是 Kubernetes 中的基本调度单元,由一个或多个容器组成。除了业务容器,Pod 还包括基础容器、初始化容器和临时容器。本文通过示例介绍如何创建包含业务容器的 Pod,并提供了一个视频讲解。示例中创建了一个名为 &quot;busybox-container&quot; 的业务容器,并使用 `kubectl create -f firstpod.yaml` 命令部署 Pod。
|
7天前
|
Kubernetes 容器 Perl
【赵渝强老师】K8s中Pod中的初始化容器
Kubernetes的Pod包含业务容器、基础容器、初始化容器和临时容器。初始化容器在业务容器前运行,用于执行必要的初始化任务。本文介绍了初始化容器的作用、配置方法及优势,并提供了一个示例。
|
17天前
|
存储 运维 Kubernetes
云端迁移:备份中心助力企业跨云迁移K8s容器服务平台
本文将简要介绍阿里云容器服务ACK的备份中心,并以某科技公司在其实际的迁移过程中遇到具体挑战为例,阐述如何有效地利用备份中心来助力企业的容器服务平台迁移项目。
|
1月前
|
Prometheus Kubernetes 监控
k8s学习--kubernetes服务自动伸缩之水平伸缩(pod副本伸缩)HPA详细解释与案例应用
k8s学习--kubernetes服务自动伸缩之水平伸缩(pod副本伸缩)HPA详细解释与案例应用
k8s学习--kubernetes服务自动伸缩之水平伸缩(pod副本伸缩)HPA详细解释与案例应用
|
1月前
|
负载均衡 Kubernetes 区块链
随机密码生成器+阿里k8s负载均衡型服务加证书方法+移动终端设计+ico生成器等
随机密码生成器+阿里k8s负载均衡型服务加证书方法+移动终端设计+ico生成器等
50 1
|
1月前
|
Kubernetes Docker 容器
容器运行时Containerd k8s
容器运行时Containerd k8s
38 2

相关产品

  • 容器服务Kubernetes版