编辑此页面

使用 Ansible 自动化 Quarkus 部署

让我们看看如何使用 Ansible 构建和部署 Quarkus 应用。我们将了解如何自动化整个过程,从代码检出到使用 Maven 进行应用程序编译,然后使用 Ansible 及其 Quarkus 集合将其部署为 systemd 服务 并启动服务,部署到目标系统。

第一部分,在 Ansible (Ansible 运行的地方) 上进行应用程序代码检出、编译和打包。在本教程中,我们将使用其 Quarkus QuickStarts 目录中提供的入门示例应用程序作为基础。我们还将利用 Ansible 的 Quarkus 集合,这是一个 Ansible 扩展,可以减轻所需的样板代码,并使用 Ansible 快速构建和部署 Quarkus。

先决条件

要完成本指南,您需要

  • 大约 10 分钟

  • 一个 IDE

  • 已安装 JDK 17+ 并正确配置了 JAVA_HOME

  • 如果您想构建本机可执行文件(或者如果您使用本机容器构建,则为 Docker),可以选择安装 Mandrel 或 GraalVM 并进行适当的配置

您需要在工作站上 安装 Ansible。完成后,您可以使用以下命令为 Ansible 安装此专门用于 Quarkus 的扩展

$ ansible-galaxy collection install middleware_automation.quarkus
我们刚刚安装的 Ansible 集合仅支持 RHEL、Fedora 和其他使用 RPM 的 Linux 发行版。Ansible 将这些定义为“RedHat 系列”。在其他平台 (Windows、Debian、Ubuntu 等) 上使用这些内容,虽然并非不可能,但需要进行一些调整。

清单文件

如果您不熟悉 Ansible,请注意,必须提供清单才能使上述命令正常运行。这是一个简单的文本文件,提供了 Ansible 在其管理的的目标系统上所需的信息。有关 Ansible 清单的更多信息,请参阅 Ansible 文档。

[all]

10.0.0.1
10.0.0.2

要遵循本教程,您可能只想使用一台机器 (localhost) 并跳过 SSH 身份验证设置。通过使用以下清单文件可以轻松实现这一点

[all]
localhost ansible_connection=local

目标系统的 root 访问权限

Quarkus 的 Ansible 集合执行的一些任务需要目标系统的管理员权限 (创建组和用户帐户,安装软件包)。如果 Ansible 以 root 身份运行,您需要将以下选项添加到 ansible-playbook 命令行

$ ansible-playbook -i inventory  --ask-become-pass  ...

教程

在控制器上安装 Ansible 集合后,您就可以直接使用它提供的一个 playbook 来构建和部署您的 Quarkus 应用程序了

ansible-playbook -i inventory \
  middleware_automation.quarkus.playbook \
  -e app_name=getting-started \
  -e quarkus_app_repo_url='https://github.com/quarkusio/quarkus-quickstarts.git' \
  -e quarkus_app_source_folder='getting-started' \
  -e quarkus_path_to_folder_to_deploy=/opt/quarkus_deploy

提供给 playbook 的四个参数都非常直观。第一个 app_name 是应用程序的名称,在本例中就是 getting-started。第二个 quarkus_app_repo_url 是要检出的 Git 存储库的 URL。第三个是可选的,quarkus_app_source_folder 指定了源代码在存储库中的子文件夹位置 (如果需要)。最后,第四个参数指定了在目标系统上安装应用程序的位置。

Playbook 运行

一旦上述命令成功运行,您应该会看到类似以下的输出

…

PLAY [Build and deploy a Quarkus app using Ansible] ****************************

TASK [Build the Quarkus from https://github.com/quarkusio/quarkus-quickstarts.git.] ***

TASK [middleware_automation.quarkus.quarkus : Ensure required parameters are provided.] ***
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Define path to mvnw script.] *****
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Ensure that builder host localhost has appropriate JDK installed: java-17-openjdk] ***
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Delete previous workdir (if requested).] ***
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Ensure app workdir exists: /tmp/workdir] ***
changed: [localhost]

TASK [middleware_automation.quarkus.quarkus : Checkout the application source code.] ***
changed: [localhost]

TASK [middleware_automation.quarkus.quarkus : Build the App using Maven] *******
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Display build application log] ***
skipping: [localhost]

TASK [Deploy webapp on target.] ************************************************

TASK [middleware_automation.quarkus.quarkus : Ensure required parameters are provided.] ***
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Ensure required OpenJDK is installed on target.] ***
skipping: [localhost]

TASK [middleware_automation.quarkus.quarkus : Ensure Quarkus system group exists on target system] ***
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Ensure Quarkus user exists on target system.] ***
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Ensure deployement directory exits: /opt/quarkus_deploy.] ***
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Set Quarkus app source dir (if not defined).] ***
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Deploy application from  to target system] ***
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Deploy Systemd configuration for Quarkus app] ***
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Perform daemon-reload to ensure the changes are picked up] ***
skipping: [localhost]

TASK [middleware_automation.quarkus.quarkus : Ensure Quarkus app service is running.] ***
ok: [localhost]

TASK [middleware_automation.quarkus.quarkus : Ensure firewalld is available.] ***
skipping: [localhost]

TASK [middleware_automation.quarkus.quarkus : Configure firewall for 8080 ports] ***
skipping: [localhost]

PLAY RECAP *********************************************************************
localhost              	: ok=15   changed=2	unreachable=0	failed=0	skipped=5	rescued=0	ignored=0
…

Quarkus 的 Ansible 集合在此处完成了所有“繁重的工作”。首先,它会从 Github 检出代码并从其源代码构建应用程序。它还确保用于此步骤的系统具有所需的 OpenJDK。默认情况下,应用程序在 localhost (Ansible 控制器) 上构建,但如果需要,也可以在远程系统上执行。应用程序构建完成后,集合将负责部署。

这里再次检查目标系统上是否提供了合适的 OpenJDK。然后,我们确保目标系统上存在必需的用户和组。这主要是为了能够使用普通用户而不是 root 帐户来运行 Quarkus 应用。

在满足这些要求后,jar 文件就可以部署到目标系统,并附带将应用程序集成到 systemd 作为服务的所需配置。对 systemd 配置的任何更改都需要重新加载其守护进程,集合会确保在需要时进行重新加载。在完成所有这些之后,唯一剩下的就是启动服务本身,Ansible 也会负责这一点。

默认情况下,Quarkus 的 Ansible 集合将安装并使用目标主机 (或控制器) 的 Yum 存储库中可用的 OpenJDK 17。如果要使用不同版本的 OpenJDK,请定义以下变量

$ ansible-playbook -i inventory ...
    -e quarkus_java_package_version: java-17-openjdk

验证部署是否成功

为了本教程的目的,您可能需要手动检查 playbook 是否确实正确部署了应用程序。以下是几种检查方法。

首先,由于集合已集成,我们可以检查其中一个目标上服务的状态

# systemctl status getting-started.service
● getting-started.service - A Quarkus service named getting-started
   Loaded: loaded (/usr/lib/systemd/system/getting-started.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2023-04-13 12:48:18 UTC; 2min 40s ago
 Main PID: 853 (java)
	Tasks: 43 (limit: 1638)
   Memory: 73.3M
   CGroup: /system.slice/getting-started.service
       	└─853 /usr/bin/java -jar /opt/quarkus_deploy/quarkus-run.jar

Apr 13 12:48:18 bd71f39642c8 systemd[1]: Started A Quarkus service named getting-started.
Apr 13 12:48:19 bd71f39642c8 java[853]: __  ____  __  _____   ___  __ ____  ______
Apr 13 12:48:19 bd71f39642c8 java[853]:  --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
Apr 13 12:48:19 bd71f39642c8 java[853]:  -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
Apr 13 12:48:19 bd71f39642c8 java[853]: --\___\_\____/_/ |_/_/|_/_/|_|\____/___/
Apr 13 12:48:19 bd71f39642c8 java[853]: 2023-04-13 12:48:19,284 INFO  [io.quarkus] (main) getting-started 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.16.6.Final) started in 0.607s. Listening on: http://0.0.0.0:8080
Apr 13 12:48:19 bd71f39642c8 java[853]: 2023-04-13 12:48:19,309 INFO  [io.quarkus] (main) Profile prod activated.
Apr 13 12:48:19 bd71f39642c8 java[853]: 2023-04-13 12:48:19,310 INFO  [io.quarkus] (main) Installed features: [cdi, rest, smallrye-context-propagation, vertx]

手动地,您也可以测试应用程序是否可访问

# curl -I https://:8080/
HTTP/1.1 200 OK
accept-ranges: bytes
content-length: 3918
cache-control: public, immutable, max-age=86400
last-modified: Thu, 2 Mar 2023 11:03:18 GMT
date: Thu, 2 Mar 2023 11:03:18 GMT

我们将在本教程的下一部分也就是最后一部分中介绍如何自动化这些验证。

编写 Playbook

当然,您很可能需要在此基础上进行扩展,因此您可能希望编写自己的 playbook,而不是仅仅使用集合提供的 playbook。以下是这样一个 playbook 的示例

- name: "Build and deploy a Quarkus app using Ansible"
  hosts: all
  gather_facts: true
  vars:
    quarkus_app_repo_url: 'https://github.com/quarkusio/quarkus-quickstarts.git'
    app_name: getting-started
    quarkus_app_source_folder: getting-started
    quarkus_path_to_folder_to_deploy: /opt/quarkus_deploy

  pre_tasks:
    - name: "Build the Quarkus from {{ quarkus_app_repo_url }}."
      ansible.builtin.include_role:
        name: quarkus
        tasks_from: build.yml
  tasks:
    - name: "Deploy Quarkus app on target."
      ansible.builtin.include_role:
        name: quarkus
        tasks_from: deploy.yml

要运行此 playbook,您再次使用 ansible-playbook 命令,但现在提供 playbook 的路径

$ ansible-playbook -i inventory playbook.yml

您还可以自动化我们在上一节提到的验证部分。您可以使用 ansible.builtin.assert 模块并填充 service facts 来确保 Quarkus 应用程序的 systemd 服务正在运行,同时使用 ansible.builtin.uri 来检查 Quarkus 应用程序是否可访问。

 post_tasks:
    - name: Populate service facts
      ansible.builtin.service_facts:

    - name: "Check that systemd service {{ app_name }} is running."
      ansible.builtin.assert:
        that:
          - ansible_facts.services is defined
          - ansible_facts.services["{{ app_name }}.service"] is defined
          - ansible_facts.services["{{ app_name }}.service"]['state'] == 'running'
          - ansible_facts.services["{{ app_name }}.service"]['status'] == 'enabled'
        quiet: true

    - name: "Check that Quarkus app is accessible"
      ansible.builtin.uri:
        url: 'https://:8080/'

就是这样了,各位!

相关内容