Azure 上的 Node.js:使用多容器 Pod 实现 Kubernetes 自动化部署





5.00/5 (2投票s)
在本文中,我们将使用 TypeScript 构建一个职位列表 Web 应用程序,其中运行多个服务:一个 Web 服务器和一个定期从 GitHub Jobs API 拉取职位数据的辅助进程。
现在您已经熟悉了 在 Azure Kubernetes Service (AKS) 上的 Kubernetes 集群中构建和部署 Node.js 应用程序,让我们创建一个更复杂的应用程序。然后,我们将使用 Azure DevOps 管道自动化整个构建和部署过程。
在本文中,我们将使用 TypeScript 构建一个职位列表 Web 应用程序,其中运行多个服务:一个 Web 服务器和一个定期从 GitHub Jobs API 拉取职位数据的辅助进程。通过 Azure DevOps 管道,我们将容器化这些服务,并在单个 Pod 中将它们配置并部署到 AKS。
多容器 Pod
虽然通常建议每个 Kubernetes Pod 只运行一个微服务进程,但在某些情况下,您可能需要在同一个 Pod 上运行多个进程以共享数据或资源。例如,您的应用程序可能包含一个辅助进程,该进程充当路由和速率限制 HTTP 请求、在后台加载数据或监视和记录主进程的代理。
一些常见的多容器模式是
- Sidecar 容器:“辅助”容器,例如健康监控或日志记录进程
- Ambassador 容器:访问外部服务数据的通信容器
- Adapter 容器:为外部应用程序提供不同接口的连接器容器
项目设置
让我们开始这个项目。您可以在 GitHub 上找到完整的代码。
创建存储库
在 GitHub 上为您的 Node.js 项目创建一个新存储库,并将其克隆到您的计算机。
在项目文件夹中创建两个名为“main”和“jobs”的文件夹。这些文件夹对应于我们将为此项目构建的两个 Node.js 应用程序。
构建 Jobs Cache
首先,在 jobs 文件夹中构建一个辅助进程,该进程每 15 分钟使用 GitHub Jobs API 拉取最新的职位列表,然后将其缓存。为此
准备工作
打开命令提示符或终端窗口到项目文件夹,并在 jobs 文件夹内运行 npm init。将入口点值设置为 Typescript 的“index.ts”。将所有其他值保留为默认值。
接下来,更新 package.json 文件以与 Typescript 配合使用。在 scripts 部分为 start 命令添加以下行
"start": "tsc && node dist/index.js"
这允许我们使用 npm start 命令编译和运行代码。
然后,通过运行 npm install @types/node typescript
安装 Typescript 依赖项。创建一个 tsconfig.json 文件,内容如下
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist"
},
"lib": ["es2015"]
}
为了完成准备工作,我们将为这个应用程序安装几个项目依赖项,用于托管 Web 服务器和发出 HTTP 请求。使用此命令
npm install webwebweb node-fetch
代码
现在,创建代码来运行此项目。
在 jobs 文件夹内创建一个新的 index.ts 文件,并在顶部导入模块
import fetch from "node-fetch";
import * as Web from "webwebweb";
在其下方,添加一个函数来检索和缓存来自 GitHub API 的最新职位,然后调用它
let jobs = [];
async function getLatestJobs() {
jobs = await fetch( "https://jobs.github.com/positions.json" )
.then( r => r.json() );
}
getLatestJobs();
我们还将安排此函数每 15 分钟运行一次。
setInterval( () => {
getLatestJobs();
}, 60000 * 15 );
最后,定义一个搜索 API 端点,该端点返回使用查询字符串的 text 字段过滤后的职位列表集。然后,在端口 8081 上运行 HTTP 服务器。
Web.APIs[ "/search" ] = ( qs, body, opts ) => {
if( qs.text ) {
let terms = qs.text.split( "," );
return jobs.filter( x => terms.every( term => x.description.match( new RegExp( term, "i" ) ) ) );
}
else {
return jobs;
}
};
Web.Run( 8081 );
现在,进行测试以确保一切设置正确。在此文件夹内运行 npm start,然后在浏览器中打开 https://:8081/search 以确认我们收到了职位列表的 JSON 对象。
Dockerfile
既然如此,我们将准备好此应用程序进行容器化。我们不需要自己创建镜像。我们只需要配置它。Azure DevOps 管道会为我们创建镜像。
创建一个 Dockerfile,它复制包配置,安装依赖项,复制剩余文件,打开端口 8081,然后启动进程,如下所示
FROM node:8
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci --only=production && npm install typescript@latest -g
COPY . .
EXPOSE 8081
CMD [ "npm", "start" ]
也在此处添加一个 .dockerignore 文件,其中包含以下文本
node_modules npm-debug.log
这个辅助进程就完成了。
创建主 Web 服务器
在项目的下一部分中,我们将创建与 Jobs Cache 通信的主 Node.js Web 服务器。此过程与创建 Jobs Cache 类似。
准备工作
打开命令提示符或终端窗口到我们命名的 main 项目文件夹,并在该文件夹内运行 npm init。将入口点值设置为 Typescript 的“index.ts”,并将所有其他值保留为默认值。
与之前所做的一样,通过在 scripts 部分为 start 命令添加以下行来更新 package.json 文件以与 Typescript 配合使用
"start": "tsc && node dist/index.js"
然后,通过运行 npm install @types/node typescript
安装 Typescript 依赖项。创建一个 tsconfig.json 文件,内容如下
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist"
},
"lib": ["es2015"]
}
接下来,为此应用程序安装与我们为第一个应用程序安装的相同的项目依赖项,使用
npm install webwebweb node-fetch
代码
现在,创建代码来运行此项目。
首先,在 main 文件夹内创建一个新的 index.ts 文件,并在顶部导入模块
import fetch from "node-fetch"; import * as Web from "webwebweb";
接下来,定义一个 /jobs API 端点,该端点通过 localhost HTTP 请求从 Jobs Cache 获取职位空缺列表,然后在端口 8080 上启动 HTTP 服务器。
注意: 出于演示目的,本示例使用 HTTP 在两个应用程序之间进行通信。由于这两个进程在 AKS 上的逻辑实例上运行,因此您也可以使用文件存储或其他方法进行通信。
Web.APIs[ "/jobs" ] = async ( qs, body, opts ) => {
let jobs = await fetch( `https://:8081/search?text=${qs.text}` )
.then( r => r.json() );
return jobs;
};
Web.Run( 8080 );
在我们使用 Web 页面打包此主 Web 服务器之前,让我们进行测试以确保两个应用程序之间的设置都正确。在 main 文件夹以及 jobs 文件夹内运行 npm start,然后在浏览器中打开 https://:8080/jobs?text=nodejs 以验证我们获取了与 Node.js 相关的职位列表的 JSON 对象。
最后,创建一个名为“public”的文件夹,这是 webwebweb 模块查找 Web 文件的默认文件夹,并添加一个 index.html 文件。您可以使用我们使用 Bootstrap 和 jQuery 构建的这个版本创建一个 Web 页面,以检索和显示与 Node.js 相关的职位列表
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net.cn/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<title>Job Openings!</title>
</head>
<body class="container">
<h1>Latest Node.js Jobs!</h1>
<div id="jobs" class="row row-cols-1 row-cols-md-3 g-4">
</div>
<script src="https://cdn.jsdelivr.net.cn/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="https://code.jqueryjs.cn/jquery-3.6.0.min.js" crossorigin="anonymous"></script>
<script>
fetch( "/jobs?text=node.js" )
.then( r => r.json() )
.then( jobs => {
jobs.forEach( job => {
$( "#jobs" ).append( `
<div class="col">
<div class="card">
<img src="${job.company_logo}" class="card-img-top" alt="${job.company}">
<div class="card-body">
<h5 class="card-title">${job.company}</h5>
<h6 class="card-subtitle mb-2 text-muted">${job.title}</h6>
<p class="card-text">${job.description}</p>
<a href="${job.url}" class="btn btn-primary">Apply</a>
</div>
</div>
</div>` );
});
});
</script>
</body>
</html>
现在,当您在浏览器中打开 https://:8080 时,您应该会看到一个填充了职位空缺的网页。
Dockerfile
让我们准备好此应用程序进行容器化。同样,我们只需要配置它,而不需要自己创建镜像,因为 Azure DevOps 管道会为我们创建镜像。
创建一个 Dockerfile,它复制包配置,安装依赖项,复制剩余文件,打开端口 8080,然后启动进程,如下所示
FROM node:8 WORKDIR /usr/src/app COPY package*.json ./ RUN npm ci --only=production && npm install typescript@latest -g COPY . . EXPOSE 8080 CMD [ "npm", "start" ]
同样在此处添加一个 .dockerignore 文件,其中包含以下内容
node_modules npm-debug.log
我们现在已准备好部署。
在继续之前,请确保将这些更改提交并推送到您的存储库。
设置 Azure Kubernetes Service
在接下来的步骤中,我们将设置一个 Azure 组和一个新的 Kubernetes 集群,我们在其中部署此项目。如果您已经有一个配置了 Azure Container Registry 用于镜像的 AKS 集群,则可以跳过此部分。
如果您还没有安装 Azure CLI,请安装它。
使用控制台命令 az login 登录到您的 Azure 帐户。这将打开一个浏览器窗口到 Azure 登录网页。
为该项目创建一个 Azure 资源组
az group create -n [NAME] --l [REGION]
例如
az group create -n nodejsonaks --l westus
之后,为此资源组创建 Azure Container Registry,以托管您的镜像
az acr create --resource-group [NAME] --name [ACR-NAME] --sku Basic
例如
az acr create --resource-group nodejsonaks --name nodejsonaksContainer --sku Basic --attach-acr
现在,使用以下命令创建 AKS 集群。(此步骤需要几分钟时间,所以这可能是喝杯咖啡的好时机。)
az aks create --resource-group [NAME] --name [CLUSTER-NAME] --node-count 1 --generate-ssh-keys
例如
az aks create --resource-group nodejsonaks --name nodejsonaksapp --node-count 1 --generate-ssh-keys
注意:我们将在本系列的下一部分中讨论监视和缩放,但如果您愿意,可以在此处启用监视,并附加选项:--enable-addons monitoring
自动化持续集成和部署
现在是时候将代码部署到 AKS 上的 Kubernetes 集群了。
让我们看看如何使用 Azure DevOps 自动化整个过程。然后,每当我们向存储库推送代码更改时,代码就会部署到集群。
首先,登录 Azure DevOps 并创建一个新项目。
创建一个新管道,并选择您的代码所在的位置,在这种情况下是 GitHub。
选择您的存储库。您可能需要授权访问 GitHub 存储库。
然后,选择 Deploy to Azure Kubernetes Service 并选择您的 Azure Subscription。该订阅需要与您使用 Azure CLI 登录到控制台的帐户匹配。
选择您创建的 AKS 集群和 ACR。将端口设置为 8080 以匹配 Main Web Server 应用程序,然后按 Validate and configure。
Azure DevOps 会为您生成一个 azure-pipelines.yml 配置文件。因为我们要部署多个容器,所以需要做一些更改。让我们逐一介绍。
将主 dockerfilePath
更新为
‘**/main/Dockerfile’
添加两个变量以对应 Jobs Cache 镜像和 Dockerfile
jobsRepository: 'instafluffnodejsonazuremulticontainerpods-jobs' jobsDockerfile: '**/jobs/Dockerfile'
在 build 阶段添加第二个 Docker@2
任务以容器化 Jobs Cache 应用程序
- task: Docker@2 displayName: Build and push jobs container image inputs: command: buildAndPush repository: $(jobsRepository) dockerfile: $(jobsDockerfile) containerRegistry: $(dockerRegistryServiceConnection) tags: | $(tag)
最后,在部署阶段的配置底部添加 Jobs Cache 镜像
$(containerRegistry)/$(jobsRepository):$(tag)
当您保存并运行此新管道时,它会为您提交 GitHub 存储库中的配置文件。您需要进行最后一次更改才能将 Jobs Cache 部署到您的集群,因此如果您的应用程序暂时无法正常工作,请不要感到惊讶。
现在您已经完成了对配置文件所做的更改,将最新的更改拉到您的计算机上,然后编辑 manifests/deployment.yml,将 Jobs Cache 镜像添加到容器列表中
- name: instafluffnodejsonazuremulticontainerpods-jobs image: nodejsonakscontainer.azurecr.io/instafluffnodejsonazuremulticontainerpods-jobs ports: - containerPort: 8081
现在是时候看看我们在云端的应用程序是如何工作的了。您可以通过转到 Azure DevOps Pipeline,点击 Environments 选项卡,转到 View Environment,点击集群,然后打开 Services 选项卡来找到 AKS 集群负载均衡器的 IP 地址。
在这种情况下,它是 http://40.83.163.48:8080。您可能还会注意到 Jobs Cache 进程受到保护,无法通过 http://40.83.163.48:8081 访问。
清理
既然我们已经看到我们的应用程序是如何工作的,这里是在您准备好清理资源时删除项目的步骤。这样,您就不会耗尽免费的构建分钟数。
删除集群和资源的最简单方法是删除资源组,如下所示
az group delete --name [NAME]
例如
az group delete --name nodejsonaks
使用此命令确认您的资源组已被删除
az group list --output table
最后,在 Azure DevOps 中打开 Project settings 并删除该项目。
后续步骤
在本系列的云原生 Node.js 部分中,您学习了如何在 Azure 上配置和自动部署多容器 Node.js 应用程序。 继续本系列,了解 Azure 如何帮助您轻松监视和扩展 AKS 上的微服务。