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

简介: 为了实现高可用,非容器应用通常有一套服务注册和发现的机制。相对而言,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的混合流量,如何实现流量转移。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
6月前
|
Cloud Native 中间件 调度
云原生信息提取系统:容器化流程与CI/CD集成实践
本文介绍如何通过工程化手段解决数据提取任务中的稳定性与部署难题。结合 Scrapy、Docker、代理中间件与 CI/CD 工具,构建可自动运行、持续迭代的云原生信息提取系统,实现结构化数据采集与标准化交付。
202 1
云原生信息提取系统:容器化流程与CI/CD集成实践
|
11月前
|
运维 Kubernetes 网络协议
基于虚拟服务配置的渐进式迁移实践:Istio集群至ASM集群的平滑切换
本文介绍了从Istio+k8s环境迁移到阿里云ASM+ACK环境的渐进式方法,通过配置虚拟服务和入口服务实现新老集群间的服务调用与流量转发,确保业务连续性与平滑迁移
912 132
|
9月前
|
Kubernetes 调度 异构计算
生产环境 K8S + Deepseek 实现大模型部署 和 容器调度(图解+史上最全)
生产环境 K8S + Deepseek 实现大模型部署 和 容器调度(图解+史上最全)
生产环境 K8S + Deepseek 实现大模型部署 和 容器调度(图解+史上最全)
|
9月前
|
数据采集 消息中间件 Kubernetes
容器化爬虫部署:基于K8s的任务调度与自动扩缩容设计
随着业务复杂度提升,传统定时任务和手工扩缩容难以满足高并发与实时性需求。本文对比两种基于 Kubernetes 的爬虫调度与扩缩容方案:CronJob+HPA 和 KEDA。从调度灵活性、扩缩容粒度、实现难度等维度分析,并提供 YAML+Python 示例。方案 A(CronJob+HPA)适合固定定时任务,配置简单;方案 B(KEDA)支持事件驱动,适合高并发与异步触发场景。根据实际需求可混合使用,优化资源利用与效率。
335 4
|
10月前
|
Ubuntu 关系型数据库 MySQL
容器技术实践:在Ubuntu上使用Docker安装MySQL的步骤。
通过以上的操作,你已经步入了Docker和MySQL的世界,享受了容器技术给你带来的便利。这个旅程中你可能会遇到各种挑战,但是只要你沿着我们划定的路线行进,你就一定可以达到目的地。这就是Ubuntu、Docker和MySQL的灵魂所在,它们为你开辟了一条通往新探索的道路,带你亲身感受到了技术的力量。欢迎在Ubuntu的广阔大海中探索,用Docker技术引领你的航行,随时准备感受新技术带来的震撼和乐趣。
423 16
|
11月前
|
监控 Kubernetes Cloud Native
基于阿里云容器服务Kubernetes版(ACK)的微服务架构设计与实践
本文介绍了如何基于阿里云容器服务Kubernetes版(ACK)设计和实现微服务架构。首先概述了微服务架构的优势与挑战,如模块化、可扩展性及技术多样性。接着详细描述了ACK的核心功能,包括集群管理、应用管理、网络与安全、监控与日志等。在设计基于ACK的微服务架构时,需考虑服务拆分、通信、发现与负载均衡、配置管理、监控与日志以及CI/CD等方面。通过一个电商应用案例,展示了用户服务、商品服务、订单服务和支付服务的具体部署步骤。最后总结了ACK为微服务架构提供的强大支持,帮助应对各种挑战,构建高效可靠的云原生应用。
|
10月前
|
存储 运维 Kubernetes
容器数据保护:基于容器服务 Kubernetes 版(ACK)备份中心实现K8s存储卷一键备份与恢复
阿里云ACK备份中心提供一站式容器化业务灾备及迁移方案,减少数据丢失风险,确保业务稳定运行。
|
Kubernetes Linux 虚拟化
入门级容器技术解析:Docker和K8s的区别与关系
本文介绍了容器技术的发展历程及其重要组成部分Docker和Kubernetes。从传统物理机到虚拟机,再到容器化,每一步都旨在更高效地利用服务器资源并简化应用部署。容器技术通过隔离环境、减少依赖冲突和提高可移植性,解决了传统部署方式中的诸多问题。Docker作为容器化平台,专注于创建和管理容器;而Kubernetes则是一个强大的容器编排系统,用于自动化部署、扩展和管理容器化应用。两者相辅相成,共同推动了现代云原生应用的快速发展。
3091 11
|
11月前
|
监控 Cloud Native Java
基于阿里云容器服务(ACK)的微服务架构设计与实践
本文介绍如何利用阿里云容器服务Kubernetes版(ACK)构建高可用、可扩展的微服务架构。通过电商平台案例,展示基于Java(Spring Boot)、Docker、Nacos等技术的开发、容器化、部署流程,涵盖服务注册、API网关、监控日志及性能优化实践,帮助企业实现云原生转型。
|
5月前
|
Kubernetes Docker Python
Docker 与 Kubernetes 容器化部署核心技术及企业级应用实践全方案解析
本文详解Docker与Kubernetes容器化技术,涵盖概念原理、环境搭建、镜像构建、应用部署及监控扩展,助你掌握企业级容器化方案,提升应用开发与运维效率。
928 108

相关产品

  • 容器服务Kubernetes版