Using Stork with Kubernetes
本指南介绍如何将 Stork 与 Kubernetes 一起用于服务发现和负载平衡。 如果您是 Stork 新手,请阅读 Stork Getting Started Guide。 Unresolved directive in stork-kubernetes.adoc - include::{includes}/extension-status.adoc[]
Architecture
在本指南中,我们将在 Kubernetes 集群中部署几个组件:
-
A simple blue service.
-
A simple red service.
-
color-service
是 Kubernetes 服务,它是通往蓝色和红色实例的入口点。 -
一个客户端服务使用 REST 客户端调用蓝色或红色服务。服务发现和选择委托给 Stork。

为了简单起见,所有内容都将部署在 Kubernetes 集群的相同命名空间中。
Solution
我们建议您按照下一部分中的说明进行操作,并逐步创建应用程序。但是,您可以直接转到已完成的示例。
克隆 Git 存储库: git clone {quickstarts-clone-url}
,或下载 {quickstarts-archive-url}[存档]。
解决方案位于 stork-kubernetes-quickstart
directory。
Discovery and selection
在继续之前,我们需要讨论发现与选择。
-
服务发现是指查找服务实例的过程。它会生成一个服务实例列表,该列表可能为空(如果没有服务与请求匹配)或包含多个服务实例。
-
服务选择(也称为负载均衡)从发现过程返回的列表中选择最佳实例。结果是一个服务实例或当找不到合适的实例时的异常。
Stork 同时处理发现和选择。但是,它不处理与服务之间的通信,而仅提供一个服务实例。Quarkus 中的各种集成从该服务实例中提取服务的位置。
Bootstrapping the project
使用偏好的方法创建一个导入 quarkus-rest-client 和 quarkus-rest 扩展的 Quarkus 项目:
Unresolved directive in stork-kubernetes.adoc - include::{includes}/devtools/create-app.adoc[]
在生成的项目中,还添加以下依赖项:
<dependency>
<groupId>io.smallrye.stork</groupId>
<artifactId>stork-service-discovery-kubernetes</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye.stork</groupId>
<artifactId>stork-load-balancer-random</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-kubernetes</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-kubernetes-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-jib</artifactId>
</dependency>
implementation("io.smallrye.stork:stork-service-discovery-kubernetes")
implementation("io.smallrye.stork:stork-load-balancer-random")
implementation("io.quarkus:quarkus-kubernetes")
implementation("io.quarkus:quarkus-kubernetes-client")
implementation("io.quarkus:quarkus-container-image-jib")
stork-service-discovery-kubernetes
为 Kubernetes 提供了一种服务发现实现。stork-load-balancer-random
提供了随机负载平衡器的实现。quarkus-kubernetes
允许在每次构建时生成 Kubernetes 清单。quarkuks-kubernetes-client
扩展支持以原生模式使用 Fabric8 Kubernetes 客户端。而 quarkus-container-image-jib
支持使用 Jib 构建容器映像。
The Blue and Red services
我们从头开始:我们将要发现、选择和调用的服务。
红色和蓝色是两个简单的 REST 服务,提供了一个分别响应 Hello from Red!
和 Hello from Blue!
的端点。两个应用程序的代码已按照 Getting Started Guide 开发。
由于本指南的目标是展示如何使用 Stork Kubernetes 服务发现,因此我们不会提供红色和蓝色服务的具体步骤。它们的容器映像已构建完毕并可在公共注册表中使用:
Deploy the Blue and Red services in Kubernetes
现在我们的服务容器映像在公共注册表中可用,我们需要将它们部署到 Kubernetes 集群。
以下文件包含了在集群中部署蓝色和红色服务以及使它们可访问所需的所有 Kubernetes 资源:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: development
name: endpoints-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["endpoints", "pods"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: stork-rb
namespace: development
subjects:
- kind: ServiceAccount
# Reference to upper's `metadata.name`
name: default
# Reference to upper's `metadata.namespace`
namespace: development
roleRef:
kind: Role
name: endpoints-reader
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Service
metadata:
annotations:
app.quarkus.io/commit-id: f747f359406bedfb1a39c57392a5b5a9eaefec56
app.quarkus.io/build-timestamp: 2022-03-31 - 10:36:56 +0000
labels:
app.kubernetes.io/name: color-service
app.kubernetes.io/version: "1.0"
name: color-service (1)
spec:
ports:
- name: http
port: 80
targetPort: 8080
selector:
app.kubernetes.io/version: "1.0"
type: color-service
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
app.quarkus.io/commit-id: f747f359406bedfb1a39c57392a5b5a9eaefec56
app.quarkus.io/build-timestamp: 2022-03-31 - 10:36:56 +0000
labels:
color: blue
type: color-service
app.kubernetes.io/name: blue-service
app.kubernetes.io/version: "1.0"
name: blue-service (2)
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: blue-service
app.kubernetes.io/version: "1.0"
template:
metadata:
annotations:
app.quarkus.io/commit-id: f747f359406bedfb1a39c57392a5b5a9eaefec56
app.quarkus.io/build-timestamp: 2022-03-31 - 10:36:56 +0000
labels:
color: blue
type: color-service
app.kubernetes.io/name: blue-service
app.kubernetes.io/version: "1.0"
spec:
containers:
- env:
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: quay.io/quarkus/blue-service:1.0
imagePullPolicy: Always
name: blue-service
ports:
- containerPort: 8080
name: http
protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
app.quarkus.io/commit-id: 27be03414510f776ca70d70d859b33e134570443
app.quarkus.io/build-timestamp: 2022-03-31 - 10:38:54 +0000
labels:
color: red
type: color-service
app.kubernetes.io/version: "1.0"
app.kubernetes.io/name: red-service
name: red-service (2)
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/version: "1.0"
app.kubernetes.io/name: red-service
template:
metadata:
annotations:
app.quarkus.io/commit-id: 27be03414510f776ca70d70d859b33e134570443
app.quarkus.io/build-timestamp: 2022-03-31 - 10:38:54 +0000
labels:
color: red
type: color-service
app.kubernetes.io/version: "1.0"
app.kubernetes.io/name: red-service
spec:
containers:
- env:
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: quay.io/quarkus/red-service:1.0
imagePullPolicy: Always
name: red-service
ports:
- containerPort: 8080
name: http
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress (3)
metadata:
annotations:
app.quarkus.io/commit-id: f747f359406bedfb1a39c57392a5b5a9eaefec56
app.quarkus.io/build-timestamp: 2022-03-31 - 10:46:19 +0000
labels:
app.kubernetes.io/name: color-service
app.kubernetes.io/version: "1.0"
color: blue
type: color-service
name: color-service
spec:
rules:
- host: color-service.127.0.0.1.nip.io
http:
paths:
- backend:
service:
name: color-service
port:
name: http
path: /
pathType: Prefix
此清单中有一些有趣的部分:
<1> Kubernetes 服务资源,`color-service`,Stork 将发现该资源。 <1> `color-service` Kubernetes 服务后面的 Red 和 Blue 服务实例。 <1> Kubernetes Ingress 资源,使 `color-service` 从群集外部的 `color-service.127.0.0.1.nip.io` url 访问。请注意,Stork 不需要 Ingress,但是它有助于检查体系结构是否已到位。
在项目的根目录创建一个名为 kubernetes-setup.yml
的文件,其中包含以上内容,然后运行以下命令以部署 Kubernetes 群集中的所有资源。不要忘记创建一个专用命名空间:
kubectl create namespace development
kubectl apply -f kubernetes-setup.yml -n=development
如果一切顺利,则可以在 [role="bare"][role="bare"]http://color-service.127.0.0.1.nip.io 上访问颜色服务。您应该随机收到 Hello from Red!
和 Hello from Blue!
响应。
Stork 不仅限于 Kubernetes,它还可以与其他服务发现机制集成。 |
The REST Client interface and the front end API
到目前为止,我们还没有使用 Stork;我们只是部署了将要发现、选择和调用的服务。
我们将使用 REST Client 调用服务。使用以下内容创建 src/main/java/org/acme/MyService.java
文件:
package org.acme;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
/**
* The REST Client interface.
*
* Notice the `baseUri`. It uses `stork://` as URL scheme indicating that the called service uses Stork to locate and
* select the service instance. The `my-service` part is the service name. This is used to configure Stork discovery
* and selection in the `application.properties` file.
*/
@RegisterRestClient(baseUri = "stork://my-service")
public interface MyService {
@GET
@Produces(MediaType.TEXT_PLAIN)
String get();
}
它是一种包含单个方法的简单 REST 客户端界面。但是,请注意 baseUri
属性:* stork://
后缀指示 REST 客户端将服务实例的发现和选择委托给 Stork,* URI 的 my-service
部分是我们将在应用程序配置中使用的服务名称。
它不会改变 REST 客户端的使用方式。使用以下内容创建 src/main/java/org/acme/FrontendApi.java
文件:
package org.acme;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
/**
* A frontend API using our REST Client (which uses Stork to locate and select the service instance on each call).
*/
@Path("/api")
public class FrontendApi {
@RestClient MyService service;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String invoke() {
return service.get();
}
}
它照常注入并使用 REST 客户端。
Stork configuration
现在我们需要配置 Stork,以便其使用 Kubernetes 来发现该服务的红色和蓝色实例。
在 src/main/resources/application.properties
中,添加:
quarkus.stork.my-service.service-discovery.type=kubernetes
quarkus.stork.my-service.service-discovery.k8s-namespace=development
quarkus.stork.my-service.service-discovery.application=color-service
quarkus.stork.my-service.load-balancer.type=random
stork.my-service.service-discovery
指示我们将使用哪种服务发现来查找 my-service
服务。在本例中,是 kubernetes
。如果通过 Kube 配置文件配置了对 Kubernetes 集群的访问,则无需配置访问。否则,使用 quarkus.stork.my-service.service-discovery.k8s-host
属性设置合适的 Kubernetes url。quarkus.stork.my-service.service-discovery.application
包含 Kubernetes 服务 Stork 将要请求的名称。在本例中,这是对应于 Red 和 Blue 实例支持的 Kubernetes 服务的 color-service
。最后,quarkus.stork.my-service.load-balancer.type
配置服务选择。在本例中,我们使用 random
负载均衡器。
Deploy the REST Client interface and the front end API in the Kubernetes cluster
系统几乎已完成。我们只需要将 REST 客户端界面和客户端服务部署到集群中。在 src/main/resources/application.properties
中添加:
quarkus.container-image.registry=<public registry>
quarkus.kubernetes-client.trust-certs=true
quarkus.kubernetes.ingress.expose=true
quarkus.kubernetes.ingress.host=my-service.127.0.0.1.nip.io
quarkus.container-image.registry
包含要使用的容器注册表。quarkus.kubernetes.ingress.expose
表示该服务将从集群外部可访问。quarkus.kubernetes.ingress.host
包含用于访问服务的 url。我们正在为 IP 地址映射使用 nip.io 通配符。
如需更定制的配置,你可以查看 Deploying to Kubernetes guide
Build and push the container image
借助我们正在使用的扩展,我们可以使用 Jib 执行容器镜像构建,还可以在构建应用程序时启用 Kubernetes 清单的生成。例如,以下命令将在 target/kubernetes/
目录中生成 Kubernetes 清单,还将构建并推送一个用于该项目的容器镜像:
./mvnw package -Dquarkus.container-image.build=true -Dquarkus.container-image.push=true
Deploy client service to the Kubernetes cluster
生成的清单可以使用 kubectl 从项目根目录应用到集群:
kubectl apply -f target/kubernetes/kubernetes.yml -n=development
请注意,如果你在 Stork 中使用椭圆曲线密钥并且会收到 |
大功告成!让我们看看是否有效。
打开浏览器并导航至 [role="bare"] [role="bare"]http://my-service.127.0.0.1.nip.io/api。
或者,如果你偏好,在另一个终端中运行:
> curl http://my-service.127.0.0.1.nip.io/api
...
> curl http://my-service.127.0.0.1.nip.io/api
...
> curl http://my-service.127.0.0.1.nip.io/api
...
响应应在 Hello from Red!
和 Hello from Blue!
之间随机交替。
您可以将此应用程序编译为本机可执行文件:
Unresolved directive in stork-kubernetes.adoc - include::{includes}/devtools/build-native.adoc[]
然后,你需要基于本机可执行文件构建容器映像。为此,请使用对应的 Dockerfile:
> docker build -f src/main/docker/Dockerfile.native -t quarkus/stork-kubernetes-quickstart .
将新映像发布到容器注册表后。您可以将 Kubernetes 清单重新部署到集群中。