如何在 Kubernetes 集群中部署和使用 Quarkus

欢迎来到这个令人兴奋的教程,了解如何在 Kubernetes 中部署和使用 Quarkus。Kubernetes 是当前自动化系统部署时首选的开源工具之一。它使扩展和管理容器化应用程序变得容易。

Kubernetes 通过在集群中分配工作负载和自动化容器网络需求来工作。此外,还分配了存储和持久卷,通过这样做,容器应用程序的所需状态得到持续维护。

Quarkus提供了一种简单的方法来根据一些默认值和用户提供的配置自动生成 Kubernetes 资源。这个 Kubernetes 原生 Java 框架还提供了一个扩展,用于在将应用程序部署到目标之前构建容器镜像并将其推送到注册表。Quarkus 的另一个特点是,它使人们能够使用 Kubernetes ConfigMap作为配置源,而无需将它们安装在 pod 上。

与 Quarkus 相关的很酷的功能是:

社区和标准:它通过利用您喜爱和使用的 50 多个同类最佳库的不断增长的列表,提供了一个有凝聚力且易于使用的全栈框架

Container First:它提供了惊人的快速启动时间、极低的 RSS 内存(不仅仅是堆大小!),在 Kubernetes 等容器编排平台中提供近乎即时的扩展和高密度内存利用率

统一命令式和反应式:它允许开发人员在开发应用程序时结合熟悉的命令式代码和反应式风格。

Kube-Native:Quarkus 和 Kubernetes 的结合为创建可扩展、快速和轻量级的应用程序提供了理想的环境。它通过工具、预先构建的集成、应用程序服务等大大提高了开发人员的生产力

通过遵循本指南到最后,您将学习如何:

  • 使用 Quarkus Dekorate 扩展根据源代码和配置自动生成 Kubernetes 清单
  • 使用 Jib 扩展构建镜像并将其推送到 Docker 注册表
  • 一键在 Kubernetes 上部署应用程序,无需任何手动创建的 YAML
  • 使用 Quarkus Kubernetes Config 从 ConfigMap 注入配置属性

让我们开始吧!

设置先决条件

对于本指南,您将需要:

  • Quarkus CLI
  • Apache Maven 3.8.1+(可选)
  • 访问 Kubernetes 集群

集群运行后,安装kubectl

curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin

确保您可以访问集群

export KUBECONFIG=/var/lib/k0s/pki/admin.conf

1、安装 Quarkus CLI

Quarkus CLI 可以通过运行以下命令安装在 Linux、macOS 和 Windows 上(使用 WSL 或 bash 兼容的 shell,如 Cygwin 或 MinGW):

curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/
curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio

您可以使用 Powershell 在 Windows 系统上安装它:

iex "& { $(iwr https://ps.jbang.dev) } trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/"
iex "& { $(iwr https://ps.jbang.dev) } app install --fresh --force quarkus@quarkusio"

安装后,重新启动 shell。

Quarkus CLI 也可以使用 SDKMAN 安装,如下所示:

sdk install quarkus

2、创建项目

使用 Quarkus 命令行界面 (CLI) 创建一个新项目。下面的命令添加了resteasy-reactive、Jib和kubernetes依赖项。

quarkus create app quarkus-example --extension=resteasy-reactive,kubernetes,jib 
cd quarkus-example

样本输出:

如何在 Kubernetes 集群中部署和使用 Quarkus-每日运维

在此之后,您将生成几个文件,其中包括pom.xml文件,该文件包含对构建文件的依赖项:

.........
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-resteasy-reactive</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-kubernetes</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-container-image-jib</artifactId>
</dependency>
......

Quarkus 的好处是它生成Deployment/StatefulSet资源,它使用您的registry_username/test-quarkus-app:tag作为 Pod 的容器镜像。这里的图像由Jib 扩展控制,可以使用application.properties进行自定义,如下所示:

打开文件进行编辑:

vim src/main/resources/application.properties

在需要的地方添加以下行替换。

quarkus.container-image.group=registry_username
quarkus.container-image.name=tutorial-app
quarkus.container-image.tag=latest
quarkus.container-image.username=registry_username
quarkus.container-image.password=Your_registry -Password

如果没有指定注册表,将使用默认的docker.io注册表。本指南的其他地方已详细介绍了指定注册表。

3、构建和部署您的应用程序

Jib用于为没有 Docker 守护程序的 Java 应用程序构建优化的图像,并且不需要掌握深度 Docker 实践。Dekorate是一个 Java 库,它使生成和装饰 Kubernetes 清单变得简单。它根据注释、源代码和配置变量生成清单。

现在使用 Quarkus CLI 构建和部署您的应用程序:

quarkus build -Dquarkus.container-image.push=true

样本输出:

如何在 Kubernetes 集群中部署和使用 Quarkus-每日运维

在构建过程之后,您将在target/kubernetes/目录下拥有两个名为kubernetes.json和kubernetes.yml的文件。

# ls target/kubernetes
kubernetes.json  kubernetes.yml

这两个文件都包含 Kubernetes Deployment和Service。例如,kubernetes.yml文件如下所示:

# cat target/kubernetes/kubernetes.yml
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    app.quarkus.io/build-timestamp: 2022-07-09 - 10:55:08 +0000
  labels:
    app.kubernetes.io/name: tutorial-app
    app.kubernetes.io/version: latest
  name: tutorial-app
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080
  selector:
    app.kubernetes.io/name: tutorial-app
    app.kubernetes.io/version: latest
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    app.quarkus.io/build-timestamp: 2022-07-09 - 10:55:08 +0000
  labels:
    app.kubernetes.io/version: latest
    app.kubernetes.io/name: tutorial-app
  name: tutorial-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/version: latest
      app.kubernetes.io/name: tutorial-app
  template:
    metadata:
      annotations:
        app.quarkus.io/build-timestamp: 2022-07-09 - 10:55:08 +0000
      labels:
        app.kubernetes.io/version: latest
        app.kubernetes.io/name: tutorial-app
    spec:
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          image: registry_username/tutorial-app:latest
          imagePullPolicy: Always
          name: tutorial-app
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP

您还将将该图像推送到您的注册表。此示例的 DockerHub:

如何在 Kubernetes 集群中部署和使用 Quarkus-每日运维

可以通过application.properties生成StatefulSet资源而不是默认的Deployment资源;

quarkus.kubernetes.deployment-kind=StatefulSet

现在使用两个清单中的任何一个将应用程序部署到您的 Kubernetes 集群,例如:

kubectl apply -f target/kubernetes/kubernetes.yml

验证部署是否启动:

# kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
tutorial-app   1/1     1            1           13s

# kubectl get pods
NAME                           READY   STATUS    RESTARTS   AGE
tutorial-app-bc774dc8d-k494g   1/1     Running   0          19s

检查服务是否正在运行:

# kubectl get svc
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes     ClusterIP      10.96.0.1       <none>        443/TCP        31m
tutorial-app   LoadBalancer   10.102.87.114   <pending>     80:30400/TCP   4m53s

使用提供的端口30400访问部署。这可以使用带有 URL http://IP_Address:30400/hello的 Web 浏览器来完成

如何在 Kubernetes 集群中部署和使用 Quarkus-每日运维

或者从终端如图所示:

$ curl 192.168.205.4:30400/hello
Hello from RESTEasy Reactive

这是src/main/java/org/acme/GreetingResource.java文件的输出

4、使用 application.properties 调整生成的资源

Quarkus 允许使用application.properties文件调整生成的清单。通过这个文件,可以进行多种配置。这些包括:

A. 命名空间

Quarkus 允许在选定的命名空间中运行应用程序。它在生成的清单中省略了命名空间,而不是在默认命名空间中强制执行它。

因此,您可以使用以下命令在所需的命名空间中运行应用程序,例如test :

kubectl apply -f target/kubernetes/kubernetes.yml -n=test

除了在运行 Kubernetes 命令时指定命名空间外,您仍然可以在application.properties中捕获命名空间,如下所示:

quarkus.kubernetes.namespace=mynamespace

将mynamespace替换为应用程序所需的命名空间。

B. 定义 Docker 注册表

还有其他几个可以定义的注册表。如果未定义,则使用docker.io。如果您想使用其他注册表,例如quay.io,则需要指定它:

quarkus.container-image.registry=my.docker-registry.net

my.docker-registry.net是您要使用的注册表。

C. 环境变量

在 Kubernetes 上有几种定义变量的方法。其中包括:

  • 键/值对
  • 从 Secret 或 ConfigMap 导入所有值
  • 在 Secret 或 ConfigMap 中插入由给定字段标识的单个值
  • 从同一资源内的字段中插入一个值

来自键/值对的环境变量

要从键/值对添加环境变量,请使用以下语法:

quarkus.kubernetes.env.vars.my-env-var=foobar

这会将MY_ENV_VAR=foobar添加为环境变量。my-env-var被转换为大写,破折号被下划线替换以产生MY_ENV_VAR。

来自 Secret 的环境变量

要将 Secret 的键/值对添加为环境变量,请将以下行添加到application.properties:

quarkus.kubernetes.env.secrets=my-secret,my-other-secret

这将在容器环境中产生以下结果:

envFrom:
  - secretRef:
      name: my-secret
      optional: false
  - secretRef:
      name: my-other-secret
      optional: false

您可以通过从my-secret中提取由keyName定义的值来设置变量:

quarkus.kubernetes.env.mapping.foo.from-secret=my-secret
quarkus.kubernetes.env.mapping.foo.with-key=keyName

导致:

- env:
  - name: FOO
    valueFrom:
      secretKeyRef:
        key: keyName
        name: my-secret
        optional: false

来自 ConfigMap 的环境变量

Quarkus 可用于从 ConfigMap 添加键/值对作为环境变量。要实现这一点,您需要添加以下行,以用逗号分隔要用作源的ConfigMap ,例如:

quarkus.kubernetes.env.configmaps=my-config-map,another-config-map

这将导致:

envFrom:
  - configMapRef:
      name: my-config-map
      optional: false
  - configMapRef:
      name: another-config-map
      optional: false

也可以使用以下方法从my-config-map中提取keyName字段:

quarkus.kubernetes.env.mapping.foo.from-configmap=my-configmap
quarkus.kubernetes.env.mapping.foo.with-key=keyName

这将生成带有以下行的清单:

- env:
  - name: FOO
    valueFrom:
      configMapRefKey:
        key: keyName
        name: my-configmap
        optional: false

这就对了!

总结

这总结了如何在 Kubernetes 中部署和使用 Quarkus 的指南。我确信您现在可以使用 Quarkus 基于一些默认值和用户提供的配置生成 Kubernetes 资源,我希望这是有价值的。