当前位置:Java -> 使用Apache Camel和Quarkus构建微服务 (第5部分)

使用Apache Camel和Quarkus构建微服务 (第5部分)

在本系列的第三部分中,我们已经学习了如何在Minikube中部署基于Quarkus/Camel的微服务,Minikube是最常用的Kubernetes本地实现之一。虽然这样的本地Kubernetes实现对于测试目的非常实用,但是它的单节点特性并不能满足实际生产环境的要求。因此,为了在类似生产环境中检查我们的微服务行为,我们需要一个多节点的Kubernetes实现。而其中最常见的就是OpenShift。

什么是OpenShift?

OpenShift 是一个基于Kubernetes的开源的企业级容器应用开发、部署和管理平台。由Red Hat开发作为Kubernetes集群的组件层,它既是商业产品,也可以作为免费平台,同时支持本地和云基础架构。下图描述了这种架构。

architecture

与任何Kubernetes实现一样,OpenShift也有其复杂性,并且将其作为独立的本地平台进行安装并不是一件轻而易举的事情。在像AWS、Azure或GCP这样的管理云上使用它是一个更实际的方法,至少在开始时是如此,但它需要一定的企业组织。

例如,ROSA(Red Hat OpenShift Service on AWS)是一种商业解决方案,可以快速创建和简单管理完整的Kubernetes基础设施,但它并不是一个开发人员友好的环境,无法快速开发、部署和测试云原生服务。

对于后一种用例,Red Hat提供了OpenShift Developer’s Sandbox,这是一个开发环境,可以立即访问OpenShift,无需进行繁重的安装或订阅过程,开发人员可以开始练习他们的技能和学习周期,甚至在开始实际项目之前。这项完全免费的服务不需要信用卡,只需要一个Red Hat账户,提供了一个在共享的多租户Kubernetes集群中预先配置了一组开发工具(如Java、Node.js、Python、Go、C#、包括Helm charts目录、s2i构建工具和OpenShift Dev Spaces)的私人OpenShift环境。

在本文中,我们将使用OpenShift Developer's Sandbox来部署我们的Quarkus/Camel微服务。

在OpenShift上部署

为了在OpenShift上部署,Quarkus应用程序需要包含OpenShift扩展。当然,这可以使用Quarkus CLI来完成,但考虑到我们的项目是一个多模块maven项目,一个更实际的做法是直接在主POM中包含以下依赖:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-openshift</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-container-image-openshift</artifactId>
</dependency>


这样一来,所有子模块将继承这些依赖。

OpenShift应该能够使用原始Kubernetes资源;因此,我们之前在Minikube上部署微服务的操作应该也适用于此处。毕竟,Minikube和OpenShift都是同一个事实标准Kubernetes的实现。

如果我们回顾一下本系列的第三部分,我们基于Jib的构建和部署过程生成了原始Kubernetes清单文件(kubernetes.yaml),以及Minikube的清单文件(minikube.yaml)。然后,我们可以选择使用生成的原始Kubernetes资源或更具体的Minikube资源,我们更喜欢后者。虽然Minikube特定的清单文件只能在Minikube上部署时使用,但原始Kubernetes的清单文件应该在Minikube上和其他任何Kubernetes实现上都能够像之前那样工作,比如OpenShift。

然而,实际上,情况要复杂一些,在我看来,我未能成功地部署在OpenShift上由Jib生成的原始Kubernetes清单文件。我需要做的是将大部分属性的名称从quarkus.kubernetes.*模式改为quarkus.openshift.*。此外,一些原始Kubernetes属性,例如quarkus.kubernetes.ingress.expose,在OpenShift中有完全不同的名称。在这种情况下为quarkus.openshift.route.expose

除了这些几乎是表面修改的例外,其他一切都与我们第三部分的先前案例相同。现在,为了在OpenShift Developer's Sandbox上部署我们的微服务,我们需要按照以下步骤进行。

登录到OpenShift Developer's Sandbox

以下是登录到OpenShift Developer Sandbox的必要步骤:

  • 打开你喜欢的浏览器,进入OpenShift Developer's Sandbox site
  • 点击屏幕右上角的登录链接(你需要先注册OpenShift Developer Sandbox)
  • 点击屏幕中央的红色按钮标有Start your sandbox for free
  • 在屏幕右上角展开你的用户名,然后点击Copy login command按钮
  • 在新对话框中点击Log in with ...,再点击DevSandbox链接
  • 显示一个带有Display Token标签的新页面。点击此链接。
  • 复制并执行显示出来的oc命令,例如:
$ oc login --token=... --server=https://api.sandbox-m3.1530.p1.openshiftapps.com:6443


从GitHub克隆项目

以下是从项目的GitHub存储库克隆项目所需的步骤:

$ git clone https://github.com/nicolasduminil/aws-camelk.git
$ cd aws-camelk
$ git checkout openshift


创建OpenShift秘密

为了连接到AWS资源,如S3存储桶和SQS队列,我们需要提供AWS凭据。有几种方法可以提供这些凭据,但在这里,我们选择使用Kubernetes凭据。以下是所需的步骤:

  • 首先,将你的Access Key ID和Secret Access Key编码为Base64,如下所示:
$ echo -n <your AWS access key ID> | base64
$ echo -n <your AWS secret access key> | base64


  • 编辑文件aws-secret.yaml并修改以下行,以替换...为Base64编码的值:
AWS_ACCESS_KEY_ID: ...
AWS_SECRET_ACCESS_KEY: ...


  • 创建包含AWS访问密钥ID和秘密访问密钥的OpenShift密钥:
$ kubectl apply -f aws-secret.yaml


启动微服务

为了启动微服务,请运行以下脚本:

$ ./start-ms.sh


这个脚本和我们先前在第三部分的配方中使用的脚本是一样的:

#!/bin/sh
./delete-all-buckets.sh
./create-queue.sh
sleep 10
mvn -DskipTests -Dquarkus.kubernetes.deploy=true clean install
sleep 3
./copy-xml-file.sh


这里,在用于触发Camel文件轮询器的copy-xml-file.sh脚本中进行了轻微修改:

#!/bin/sh
aws_camel_file_pod=$(oc get pods | grep aws-camel-file | grep -wv -e build -e deploy | awk '{print $1}')
cat aws-camelk-model/src/main/resources/xml/money-transfers.xml | oc exec -i $aws_camel_file_pod -- sh -c "cat > /tmp/input/money-transfers.xml"


这里,我们用oc命令替换了kubectl命令。此外,考虑到OpenShift不仅为微服务创建pods,还为构建和部署命令创建了pods,我们需要在运行中的pods列表中过滤出包含builddeploy字符串的pods。

运行此脚本可能需要一些时间。完成后,请确保所有必需的OpenShift控制器都在运行中:

$ oc get is
NAME              IMAGE REPOSITORY                                                                                                      TAGS                                                       UPDATED
aws-camel-file    default-route-openshift-image-registry.apps.sandbox-m3.1530.p1.openshiftapps.com/nicolasduminil-dev/aws-camel-file    1.0.0-SNAPSHOT                                             17 minutes ago
aws-camel-jaxrs   default-route-openshift-image-registry.apps.sandbox-m3.1530.p1.openshiftapps.com/nicolasduminil-dev/aws-camel-jaxrs   1.0.0-SNAPSHOT                                             9 minutes ago
aws-camel-s3      default-route-openshift-image-registry.apps.sandbox-m3.1530.p1.openshiftapps.com/nicolasduminil-dev/aws-camel-s3      1.0.0-SNAPSHOT                                             16 minutes ago
aws-camel-sqs     default-route-openshift-image-registry.apps.sandbox-m3.1530.p1.openshiftapps.com/nicolasduminil-dev/aws-camel-sqs     1.0.0-SNAPSHOT                                             13 minutes ago
openjdk-11        default-route-openshift-image-registry.apps.sandbox-m3.1530.p1.openshiftapps.com/nicolasduminil-dev/openjdk-11        1.10,1.10-1,1.10-1-source,1.10-1.1634738701 + 46 more...   18 minutes ago
$ oc get pods
NAME                       READY   STATUS      RESTARTS   AGE
aws-camel-file-1-build     0/1     Completed   0          19m
aws-camel-file-1-d72w5     1/1     Running     0          18m
aws-camel-file-1-deploy    0/1     Completed   0          18m
aws-camel-jaxrs-1-build    0/1     Completed   0          14m
aws-camel-jaxrs-1-deploy   0/1     Completed   0          10m
aws-camel-jaxrs-1-pkf6n    1/1     Running     0          10m
aws-camel-s3-1-76sqz       1/1     Running     0          17m
aws-camel-s3-1-build       0/1     Completed   0          18m
aws-camel-s3-1-deploy      0/1     Completed   0          17m
aws-camel-sqs-1-build      0/1     Completed   0          17m
aws-camel-sqs-1-deploy     0/1     Completed   0          14m
aws-camel-sqs-1-jlgkp      1/1     Running     0          14m
oc get svc
NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                               AGE
aws-camel-jaxrs     ClusterIP   172.30.192.74   <none>        80/TCP                                11m
modelmesh-serving   ClusterIP   None            <none>        8033/TCP,8008/TCP,8443/TCP,2112/TCP   18h


正如上面的列表所示,所有必需的镜像流已经创建,并且所有的pods都已经完成或正在运行中。已完成的pods与构建和部署操作相关联。运行中的pods与微服务相关联。

只有一个正在运行的服务:aws-camel-jaxrs。此服务通过向外暴露路由使得与运行aws-camel-jaxrs微服务的pod进行通信成为可能。这实际上是通过quarkus.openshift.route.expose=true属性自动完成的。并且微服务aws-camel-sqs需要与aws-camel-sqs进行通信,因此它需要知道到达它的路由。要获取这个路由,您可以按照以下步骤进行:

$ oc get routes
NAME              HOST/PORT                                                                      PATH   SERVICES          PORT   TERMINATION   WILDCARD
aws-camel-jaxrs   aws-camel-jaxrs-nicolasduminil-dev.apps.sandbox-m3.1530.p1.openshiftapps.com          aws-camel-jaxrs   http                 None


现在打开与aws-camel-sqs微服务相关联的application.properties文件,并修改rest-uri属性,使其如下:

rest-uri=aws-camel-jaxrs-nicolasduminil-dev.apps.sandbox-m3.1530.p1.openshiftapps.com/xfer


在这里,您需要用在您的情况下有意义的价值替换命名空间nicolasduminil-dev。现在,您需要停止微服务然后再次启动它们:

$ ./kill-ms.sh
...
$ ./start-ms.sh
...


现在您的微服务应该正常运行,并且您可以使用类似以下命令来检查日志文件:

$ oc logs aws-camel-jaxrs-1-pkf6n


如您所见,为了获得aws-camel-jaxrs服务的路由,我们需要先启动、停止,然后再次启动我们的微服务。这个解决方案远非优雅,但我没有发现其他方法,我希望读者能帮我改进它。可能可以使用OpenShift Java客户端在Java代码中执行与oc get routes命令相同的操作,但我没有找到方法,文档也没有提供清晰的说明。

很抱歉无法在这里提供完整的解决方案,但还是希望您会喜欢它!

推荐阅读: 17.线程通信的方法有哪些?

本文链接: 使用Apache Camel和Quarkus构建微服务 (第5部分)