原文:https://aws.amazon.com/cn/blogs/china/spring-clouds-cloud-native-migration-hybrid-deployment-architecture-on-aws-part-2/

简介

在前面的文章中,对 Spring Cloud 在 AWS 上的混合部署架构已经进行了讨论,并完成了 Eureka 及 API Gateway 的部署。在本文中,我们将讨论在 AWS 托管的 Kubernetes 服务EKS上部署 Spring Cloud 的实际业务功能模块。

架构回顾

Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(下篇) - 图1

EKS为Spring Cloud部署带来的好处

EKS的特点

Amazon Elastic Kubernetes Service (Amazon EKS) 是一项完全托管的 Kubernetes 服务。由于EKS把安全性、可靠性和可扩展性作为产品最重要的特性进行实现,在公有云上使用Kubernetes技术的多数大型客户,都使用 EKS运行他们最敏感的任务关键型应用程序。
同时,EKS 与诸如 Amazon CloudWatch、Auto Scaling Group、AWS Identity and Access Management (IAM) 和 Amazon Virtual Private Cloud (VPC) 之类的服务深度集成,为客户带来监控、扩展和负载平衡应用程序的无缝体验。
最后,EKS经认证与 Kubernetes 一致,因此客户可以利用社区中开源工具的所有优势。任何标准 Kubernetes 应用程序可轻松地迁移到 EKS,而无需重构代码。
Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(下篇) - 图2
(EKS托管架构)

Amazon VPC CNI 插件

在Kubernetes的网络模型中,要求所有的网络插件实现必须满足如下要求:

  • 所有的 Pod 可以与任何其他 Pod 直接通信,无需使用 NAT 映射(network address translation)
  • 所有节点可以与所有 Pod 直接通信,无需使用 NAT 映射
  • Pod 内部获取到的 IP 地址与其他 Pod 或节点与其通信时的 IP 地址是同一个

Amazon VPC CNI插件的实现方式是使Kubernetes的Pod获取VPC的私有IP地址。此实现方式不但完全满足Kubernetes网络模型的要求;不使用overlay网络可以使Pod的通信效率和在物理网络中相当;同时由于Pod持有的是和EC2相同的VPC私有IP,因此Pod与EC2的网络地位一致,可以直接通信。这些特性使得用Spring Cloud框架开发的业务模块部署于EKS cluster中,与部署在EC2中的Eureka、API Gateway进行交互时,不会遇到困难,同时还保持了通信的最高效率。

在EKS Cluster中部署Spring Cloud的业务模块

前置条件

  • Create a Workspace
  • Create an SSH key
  • Install Kubernetes Tools
  • Create an IAM role for your Workspace
  • Attach the IAM role to your Workspace
  • Update IAM settings for your Workspace
  • Install eksctl

Note: 前置条件过程请参考AWS EKS官方workshop:https://eksworkshop.com/eksctl/

创建EKS群集

创建的EKS群集放置在与Eureka、API Gateway 相同的VPC中。如下为示例群集配置文件:

  1. ---
  2. apiVersion: eksctl.io/v1alpha5
  3. kind: ClusterConfig
  4. metadata:
  5. name: eksworkshop-eksctl
  6. region: us-east-2
  7. version: "1.17"
  8. vpc:
  9. subnets:
  10. private:
  11. us-east-2a: { id: subnet-e2f1ea8a }
  12. us-east-2b: { id: subnet-28cd9c52 }
  13. us-east-2c: { id: subnet-a8ca72e4 }
  14. managedNodeGroups:
  15. - name: nodegroup
  16. desiredCapacity: 3
  17. ssh:
  18. allow: true
  19. publicKeyName: <SSH public key name>
  20. # To enable all of the control plane logs, uncomment below:
  21. # cloudWatch:
  22. # clusterLogging:
  23. # enableTypes: ["*"]
  24. secretsEncryption:
  25. keyARN: <kms key ARN>

群集创建命令:

  1. $ eksctl create cluster -f < ClusterConfig >.yaml

调整EKS群集的安全组

通过eksctl创建的EKS群集,worker node上的安全组默认没有开放VPC内其他EC2的访问权限。手工调整对应的安全组,添加一条允许其他Spring Cloud基础设施的安全组访问的条目。
Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(下篇) - 图3

安装Helm

Helm是一个Kubernetes的包和应用管理工具。使用Helm可以极大地简化Kubernetes上标准应用的安装。
Helm的安装请参考链接:https://www.eksworkshop.com/beginner/060_helm/helm_intro/install/

安装Metrics Server

Metrics Server是Kubernetes中的核心监控指标实现,替代了heapster。Horizontal Pod Autoscaler所依赖的监控数据,就是由Metrics Server提供。下面示例为使用Helm部署Metrics Server:

  1. # create the metrics-service namespace
  2. $ kubectl create namespace metrics
  3. # deploy the metrics-server
  4. $ helm install metrics-server \
  5. stable/metrics-server \
  6. --version 2.11.1 \
  7. --namespace metrics

创建一个可读取Parameter Store中参数的service account

示例命令如下:

  1. $ aws eks describe-cluster --name eksworkshop-eksctl --query cluster.identity.oidc.issuer --output text
  2. $ eksctl utils associate-iam-oidc-provider --cluster eksworkshop-eksctl approve
  3. $ eksctl create iamserviceaccount --name spring-cloud --namespace default --cluster eksworkshop-eksctl --attach-policy-arn arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess --approve --override-existing-serviceaccounts

Spring Cloud项目的application.properties文件配置示例

Note: 在配置文件中,启用ip地址注册。

  1. spring.application.name=hello-service
  2. eureka.client.service-url.defaultZone=http://${eureka_server_1}:${eureka_server_port}/eureka,http://${eureka_server_2}:${eureka_server_port}/eureka,http://${eureka_server_3}:${eureka_server_port}/eureka
  3. eureka.instance.prefer-ip-address=true

Docker镜像中的启动文件示例

在应用被打包成Docker镜像后,需要一个启动脚本,在镜像启动时初始化应用所需的环境。本示例中,通过启动文件,启动一个提供简单Hello world接口的Hello service。
此文件对应应用部署中Deployment yaml文件的args: [“/springCloud/env.sh”]启动脚本。

  1. export eureka_server_port=$(aws ssm get-parameter --name='/Spring/Eureka/Server/port' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  2. export eureka_server_1=$(aws ssm get-parameter --name='/Spring/Eureka/Server/URL_1' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  3. export eureka_server_2=$(aws ssm get-parameter --name='/Spring/Eureka/Server/URL_2' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  4. export eureka_server_3=$(aws ssm get-parameter --name='/Spring/Eureka/Server/URL_3' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  5. java -jar /springCloud/app.jar

打包Docker镜像并推送至ECR

在创建好ECR的存储库后,可以在对应的存储库中查看打包Docker镜像及推送命令。
Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(下篇) - 图4

部署应用

通过Deployment,在EKS cluster上部署应用,其中镜像使用前述推送至ECR的镜像。示例文档如下:

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: aws-hello
  5. labels:
  6. app: aws-hello
  7. namespace: default
  8. spec:
  9. replicas: 1
  10. selector:
  11. matchLabels:
  12. app: aws-hello
  13. strategy:
  14. rollingUpdate:
  15. maxSurge: 25%
  16. maxUnavailable: 25%
  17. type: RollingUpdate
  18. template:
  19. metadata:
  20. labels:
  21. app: aws-hello
  22. spec:
  23. serviceAccountName: spring-cloud
  24. containers:
  25. - image: <ECR image path>
  26. imagePullPolicy: Always
  27. name: aws-hello
  28. resources:
  29. limits:
  30. cpu: "1"
  31. requests:
  32. cpu: "100m"
  33. command: ["/bin/sh","-c"]
  34. args: ["/springCloud/env.sh"]
  35. ports:
  36. - containerPort: 8080
  37. protocol: TCP

部署命令:

  1. $ kubectl apply -f <deployment>.yaml

部署验证

查看Pod运行是否正常:

  1. $ kubectl get pods

Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(下篇) - 图5
查看服务是否在Eureka中注册成功:
Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(下篇) - 图6
访问在API Gateway中对外开放的URL,查看服务是否正常:
Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(下篇) - 图7

应用的自动扩展

通过HPA (Horizontal Pod Autoscaler),进行Pod的自动伸缩:

  1. $ kubectl autoscale deployment <aws-hello> --cpu-percent=50 --min=1 --max=10

查看HPA资源是否创建成功:

  1. $ kubectl get hpa

Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(下篇) - 图8
使用busybox发送大量请求模拟高并发,并监控HPA:

  1. $ kubectl get hpa -w

Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(下篇) - 图9
Pod在短时间内启动,应对并发流量:
Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(下篇) - 图10
新启动的服务模块正常注册到Eureka:
Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(下篇) - 图11

总结

Kubernetes是容器领域最流行的编排调度工具,它给大规模容器使用场景赋予了灵活而强大的调度能力。通过使用AWS托管的Kubernetes服务EKS,则能在享受Kubernetes强大能力的同时,减少运维Kubernetes群集的负担。选择把基于Spring Cloud框架开发的业务模块部署在EKS上,能使这些模块更快速,更灵活地响应突增的业务流量。结合部署于EC2的Eureka、API Gateway等Spring Cloud基础设施,整个微服务架构同时兼具了稳定性、可扩展性、快速响应等的特点,能更好地实现业务需求。

参考资料

[1]https://docs.aws.amazon.com/zh_cn/eks/latest/userguide/what-is-eks.html
[2]https://www.eksworkshop.com/
[3] 翟永超.Spring Cloud 微服务实战[M].电子工业出版社:北京,2017:1.