Azure 上的 Java 应用和数据现代化 - 第四部分:迁移到 Azure Kubernetes Service





0/5 (0投票)
如何容器化遗留 Java 应用并将其部署到 AKS 集群。
本系列的上一篇文章演示了将应用程序部署到云端运行的机器上。这是很好的第一步,但管理云服务器场就像管理数据中心的物理服务器一样耗费人力。此外,应用程序更新包包含大量的目标平台软件。
虽然开发人员需要平台代码的副本才能创建应用程序,但部署会导致重复代码的重新上传。因此,我们需要一种方法来识别平台上已存在的代码,并仅添加应用程序特有的内容。
为此,Docker 创建了一个解决方案,将应用程序打包在容器中,并构建了一个运行容器的平台。平台提供操作系统和相关的支持代码,而容器则在其之上运行。使用这种打包方法,我们可以从软件层构建容器。
第一层描述了操作系统平台。然后,我们可以添加一个包含应用程序描述的层。与包含操作系统及其支持数据(例如文件系统、应用程序和 Tomcat 等支持应用程序)的传统虚拟机包不同,容器不包含与平台重复的数据。
在更复杂的解决方案中,我们可以插入额外的层来添加服务或更新平台上已有的服务。例如,我们可以在应用程序和网络之间插入一个 HTTPS 安全套接字层 (SSL) 卸载服务,当应用程序仅提供 HTTP 服务,但应用程序必须通过 SSL 上的传输层安全 (TSL) 连接到网络时。
此外,我们还可以告诉 Docker 在启动容器时替换特定的文件或卷。例如,我们可以使用一个版本的 *application.properties* 文件构建 `PetClinic` 应用程序,并在应用程序启动时告诉 Docker 将该文件替换为本地环境中的文件。
或者,如果我们最初在一个容器中构建了 `PetClinic`,那么在将其迁移到云时,我们可以告诉 Docker 替换 *application.properties* 文件以更改连接字符串。然后,`PetClinic` 将使用更新的连接字符串。
本文仅对这项令人着迷的技术进行了初步介绍,但 Docker 的网站 提供了更多关于容器化的信息。此外,Microsoft 发布了一篇入门文章,您可以在其中了解更多信息。
编写一些脚本来管理少量容器很容易。然而,容器会连接到外部服务,如共享文件系统和负载均衡器。此外,运行应用程序的多个实例会导致一个额外的容器占用,例如,一个端口。因此,我们必须重新映射容器以使用不同的端口。
要跟踪哪些容器正在运行、它们运行的是哪个应用程序版本以及它们使用哪些资源,会变得很麻烦。我们需要一个编排服务来帮助配置、部署和监视这些容器。这正是 Kubernetes 所做的。Kubernetes 是一个开源的容器编排服务器。Azure Kubernetes Service (AKS) 正如此处所述,是 Microsoft 在 Azure 上的这项服务的实现。
这项技术使开发人员能够用 AKS 管理的 Docker 容器替换基于 Azure App Service 构建的云服务器场。通过“关注点分离”,这可以简化维护和扩展。
考虑 `PetClinic` 应用的当前实现。要部署它并从另一个服务器获取数据,我们必须更新 *application_postgres.properties* 文件,构建应用程序,将其推送到服务器,然后启动服务。相比之下,将其容器化并让 AKS 管理部署,可以让 AKS 覆盖 *application_postgres.properties* 文件而不更改容器镜像,并在无需协助的情况下启动容器。
使用 Docker 和 AKS,开发人员可以构建一个应用程序来使用数据服务。但是,DevOps 决定了应用程序使用哪个服务。这分离了应用程序如何工作与其从何处获取必要资源的问
必备组件
在创建 AKS 群集之前,请确保已安装 IntelliJ 的 Azure 插件。IntelliJ 提供了构建和部署容器的工具。重新启动 IntelliJ。然后安装 kubectl,它使您能够与 AKS 群集进行交互。
创建容器注册表
AKS 必须能够访问映像才能启动它。虽然 AKS 可以与任何注册表配合使用,但 Azure 提供了方便的 Azure 容器注册表 (ACR) 来存储 Docker 容器映像。本次演示将使用 ACR。
首先,登录到您的门户并选择“**创建资源**”。在搜索框中键入“container reg”并选择“**容器注册表**”。当出现容器注册表对话框时,单击“**创建**”。
接下来,选择一个资源组或创建一个新的资源组。
在此示例中,通过接受网络默认设置来允许群集公开访问。设置注册表名称,然后向下滚动并将 SKU 设置为“**基本**”。最后,单击“**检查 + 创建**”。
检查“创建容器注册表”对话框中的设置,然后单击“**创建。**”
创建群集需要一段时间,但完成后,您将看到
接下来,启用管理员登录,以便 IntelliJ 可以将容器推送到注册表。为此,导航到新资源并单击“**访问密钥**”。
在“**访问密钥**”对话框中,您必须将“**管理员用户**”设置为“**启用**”。复制用户名和密码值,并稍后提供给 IntelliJ。
构建容器
有两种方法可以构建映像:使用 Docker,或使用 IntelliJ。Docker 使用一系列指令来指导构建过程。默认情况下,这些指令位于名为 *Dockerfile* 的文件中。您可以调试此文件以确保它构建了有效的映像。
在“**将映像上传到注册表**”部分,您可以使用 IntelliJ 的 Azure 插件,通过 `Dockerfile` 重新构建映像,并一步将其推送到容器注册表。在此之后,工具可以自动重建映像(如有必要)。
该项目包含一套简单的构建说明
FROM mcr.microsoft.com/openjdk/jdk:11-ubuntu
EXPOSE 8080
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Dspring.profiles.active=postgres","-jar","/app.jar"]
`FROM` 指令标识了容器用作基础的 Linux 映像。该映像由 Microsoft 提供,在 Ubuntu Linux 上实现了 OpenJDK 11 版本。您需要使用此映像,以便 Docker 可以在您的容器上运行与 Windows 兼容的 Java 版本。这是 AKS 所需的配置。
运行 `Docker build` 命令时,Docker 会从托管在 `mcr.microsoft.com` 的注册表中下载名为 `jdk:11-ubuntu` 的映像。Microsoft 在此处提供了有关可用映像的通用信息。由于映像名称经常更改,您应在尝试构建容器之前验证该版本是否存在。Microsoft 容器注册表 (MCR) 提供了浏览注册表的说明。
如果您检索到此 URL,https://mcr.microsoft.com/v2/openjdk/jdk/tags/list, 您将看到类似以下的列表,其中包含 `11-ubuntu` 映像
{"name": "openjdk/jdk",
"tags": [
"11-cbld",
"11-mariner",
"11-ubuntu",
"16-cbld",
"16-mariner",
"16-ubuntu",
"17-cbld",
"17-mariner",
"17-ubuntu"
]}
`EXPOSE` 语句告诉 Docker `PetClinic` 需要端口 8080。当 AKS 启动容器时,它会将 AKS 内部网络上的一个端口映射到容器上的端口。AKS 分配的端口并不关键,因为最终用户使用不包含端口的 URL 来运行 `PetClinic`。容器将不知道重新映射。
`ARG` 语句创建一个类似于环境变量的符号。符号 `JAR_FILE` 包含 Maven 构建 `PetClinic` 时生成的文件的路径。Docker 不会运行 Maven 来构建目标,但它必须知道 Maven 在哪里创建了它。
`COPY` 语句告诉 Docker 将目标文件从源位置复制到映像中,并将其命名为 *app.jar*。
`ENTRYPOINT` 语句包含启动应用程序所需的命令行部分。AKS 在加载容器后执行此命令。
在 `PetClinic` 项目的根目录下有一个名为 *Dockerfile* 的文件。要构建容器,请打开命令窗口,切换到 `PetClinic` 项目的根目录,然后执行以下命令
C:\Projects\PetClinic\repos\spring-petclinic>docker build
-t springboot/petclinic-docker -f ./Dockerfile .
您将看到以下结果
将映像上传到注册表
为了简化构建映像时的存储,请使用 IntelliJ 将映像推送到注册表。首先,通过选择“**工具**”>“**Azure**”>“**Azure 登录**”来登录 Azure。
选择一种身份验证方法。本次演示选择 OAuth 2.0 并完成流程。
身份验证完成后,返回主屏幕,右键单击项目。选择“**Azure**”,然后选择“**推送映像**”。
将打开一个配置文件编辑器。填写 MCR 提供的“**服务器 URL**”、“**用户名**”和“**密码**”字段。您可以忽略“**容器注册表**”设置。“**映像和标签**”字段是您在注册表中的映像名称,您可以为其添加标签。在本教程中,将此值设置为 `pet-clinic-demo:latest`,这将映像名称设置为 `pet-clinic-demo`,标签设置为 `latest`。
单击“**运行**”开始构建和推送过程。
这需要一些时间。如果过程在此处卡住几分钟,请不要担心
当过程继续时,您会看到
IntelliJ 开始上传映像。完成后,您将看到类似以下的显示
您可以通过检查门户来验证映像是否已上传。
创建群集
如果您不熟悉 Kubernetes,Microsoft 提供了一个Kubernetes 概述。该页面还提供了服务学习路径的链接。Kubernetes 电子书合集是一套三本免费的可下载书籍,涵盖了云原生系统的设计和实现。其中一本书涵盖 Kubernetes,另外两本涵盖云原生系统的设计,这是本系列最后一篇文章的主题。
现在您有了一个映像,您需要一个地方来运行它。AKS 提供了一个完整的 Kubernetes 实现,可以启动和监视您的映像。要使用它,您必须创建一个 AKS 群集。使用本教程来设置您的群集。
将容器部署到 AKS
Kubernetes 需要有关如何部署映像的说明。您可以使用 Deployment — 一种用于创建 pod 的特定类型的 Kubernetes 资源 — 但在应用它之前需要完成一些支持任务。虽然此列表中的任务看起来有些不相关,但它们会配置您环境中的其他资源,以便
- Azure 命令行界面 (CLI) 可以执行命令。
- AKS 拥有在尝试实现 Deployment 时从 MCR 下载映像所需的信息。
- kubectl 可以对您的群集运行命令。
- AKS 可以配置一个负载均衡器,该负载均衡器允许每个人通过 Ingress 资源(一种提供对端口的受控访问的 Kubernetes 资源)连接到您的群集。
要使用 Azure CLI,请使用该工具登录 Azure,以便在命令中使用登录命令时拥有必要的凭据
C:\Projects\PetClinic\repos\spring-petclinic>az login
为了让 AKS 从您的容器注册表中拉取映像,您必须使用 `update` 命令将注册表附加到 AKS
C:\Projects\PetClinic\repos\spring-petclinic>az aks update -n petClinicDemo -g PetClinicDemo
--attach-acr PetClinicDemoRegistry
该命令返回大量与本项目无关的信息。但是,运行此命令可让您检索群集的凭据,以便 kubectl 可以在其中执行您的命令。aks `get-credentials` 命令将其写入 Azure CLI 读取的文件中
C:\Projects\PetClinic\repos\spring-petclinic> az aks get-credentials
--resource-group PetClinicDemo --name petClinicDemo
您必须告知 AKS 为您的应用程序创建一个负载均衡器,并将一个主机名与该负载均衡器关联起来。为此,AKS 提供了 HTTP 应用程序路由功能。
在 Azure 门户中导航到您的群集,然后单击“**网络**”以确保此功能已启用。如果您更改了设置,请保存更改并等待几分钟,AKS 将更新您的群集。
当群集准备就绪后,您必须找出 HTTP 应用程序路由功能创建了哪个 DNS 区域。为此,请使用 `aks show` 命令
C:\Projects\PetClinic\repos\spring-petclinic>az aks show
--resource-group PetClinicDemo --name petClinicDemo –query
您的 Deployment 包含有关创建 Ingress 资源以提供负载均衡器访问权限的说明。查询参数的参数是 Deployment 中定义的 Ingress 资源的类名。完整 Deployment 的代码如下。该文件采用 YAML 格式,因此如果您复制它,请确保空格准确。
注意:如果您使用示例代码,则必须在两处更新它。
首先,设置 Ingress 的 `host` 参数。该值具有此格式
<myHostname>.<DNS Region name from the previous “az” command>
petclinic-container-demo.7a125b5db23047ffb5f7.eastus.aksapp.io
Deployment 中容器的 `image` 参数
petclinicdemoregistry.azurecr.io/pet-clinic-demo:latest
这是部署的完整代码。它在一个名为 *PetClinicDeployment.yaml* 的文件中。
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: petclinic-container-demo
labels:
app: petclinic-container-demo
spec:
replicas: 2
selector:
matchLabels:
app: petclinic-container-demo
template:
metadata:
labels:
app: petclinic-container-demo
spec:
containers:
- name: petclinic-container-demo
image: petclinicdemoregistry.azurecr.io/pet-clinic-demo:latest
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
namespace: default
name: petclinic-container-service
spec:
type: ClusterIP
ports:
- port: 8080
selector:
app: petclinic-container-demo
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: default
name: petclinic-container-frontend
annotations:
kubernetes.io/ingress.class: addon-http-application-routing
spec:
rules:
- host: pet-clinic-demo.7a125b5db23047ffb5f7.eastus.aksapp.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: petclinic-container-service
port:
number: 8080
现在您有了 Deployment,请将其应用于您的群集,以告知 Kubernetes 创建一个 pod,这将启动容器中的应用程序。使用 `kubeclt apply` 命令
C:\Projects\PetClinic\repos\spring-petclinic>kubectl apply –f PetClinicDeployment.yaml
验证应用程序正在运行
现在您需要使用 `kubectl get pods` 命令来验证 pod 是否已启动并正在运行。
C:\Projects\PetClinic\repos\spring-petclinic>kubectl get pods
然后验证负载均衡器是否具有外部 IP 地址,以便用户可以运行应用程序。一种方法是查看 `DNS Addon` 资源的日志,并验证您的 DNS 区域是否存在记录。`kubectl logs` 命令会返回大量文本,但您要查找的消息位于日志末尾附近。
C:\Projects\PetClinic\repos\spring-petclinic>kubectl logs
-f deploy/addon-http-application-routing-external-dns -n kube-system
您的网页的 URL 包含两部分:应用程序名称 `pet-clinic-demo` 和主机名 `7a125b5db23047ffb5f7.eastus.aksapp.io`(来自上面的 Azure DNS 区域)。将它们组合起来创建以下 URL
http://pet-clinic-demo.7a125b5db23047ffb5f7.eastus.aksapp.io
最后,您可以像这样查看运行 `PetClinic` 的 pod 的控制台日志。首先,使用 `kubectl get pods` 命令获取 pod 的名称
C:\Projects\PetClinic\repos\spring-petclinic>kubectl get pods
然后获取日志
C:\Projects\PetClinic\repos\spring-petclinic>kubectl logs petclinic-container-demo-749ff8dfc4-d85p5
这是在 IntelliJ 中运行 `PetClinic` 时看到的相同控制台日志(已裁剪)。您在此处不应看到任何错误。如果 pod 未切换到 Running 状态,请检查此日志以了解 `PetClinic` 未启动的原因。
摘要
我们的应用程序现在是一个容器,可以轻松地部署在托管群集中。通过摆脱对需要手动启动和监视每个已部署实例的单个 EC2 实例的需求,我们增强了应用程序的可伸缩性。相反,AKS 管理硬件并确保我们的应用程序持续运行。这是使用 Deployment 创建 pod 的优势。
Docker 容器高度便携,可以在提供 Docker 主机的任何系统上运行。主机系统可以运行使用任何操作系统的映像。此外,运行 Windows 的 Azure 主机可以运行基于 Ubuntu Linux 的应用程序,因为容器将应用程序与主机 OS 隔离。
由于应用程序从 Docker 主机获取其资源,因此它不再受限于该主机系统的资源。此外,该系统的其他应用程序不再需要它。这使我们能够在更新的操作系统上重新构建容器,而无需担心主机或其应用程序是否已更新。连接应用程序与其资源的大型电子表格,以确定哪些升级会影响哪些应用程序的时代已经过去。
AKS 提供的优势远远不止于启动实例。假设您重新构建了一个应用程序,并在 MCR 中使用 Deployment 更新了映像。在这里,您可以告诉 AKS 执行滚动重启并自动部署新映像。这使得持续集成和持续部署 (CI/CD) 流程可以处理更新容器映像,而 Kubernetes 则负责其部署。
除了上述 Kubernetes 电子书合集和 Docker 入门材料外,Microsoft 还提供了一个名为 Azure 上的 Kubernetes 入门 的学习路径。此外,您还可以从 Docker 的基于容器的应用程序设计原则中了解有关设计容器化应用程序的更多信息。这些出版物为您提供了创建解耦、模块化、易于扩展和部署的应用程序的基础。
本系列下一篇文章将探讨提高数据可伸缩性的方法。
要了解四个公司如何成功地对其关键任务 Java 应用程序进行现代化改造,以实现更高的性能、安全性和客户体验,请参阅电子书现代化您的 Java 应用程序。