你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

将容器实例部署到 Azure 虚拟网络

Azure 虚拟网络为 Azure 资源和本地资源提供安全的专用网络。 将容器组部署到 Azure 虚拟网络后,容器可与该虚拟网络中的其他资源安全通信。

本文演示如何在 Azure CLI 中使用 az container create 命令将容器组部署到新的虚拟网络或现有虚拟网络。

重要

  • 在使用虚拟网络之前,必须先委派子网
  • 在虚拟网络中部署容器组之前,建议先检查限制。 有关网络方案和限制,请参阅 Azure 容器实例的虚拟网络方案和资源
  • 在大多数 Azure 容器实例可用的地区,Linux 和 Windows 容器通常可以将容器组部署到虚拟网络。 有关详细信息,请参阅 可用地区

重要

2021-07-01 API 版本起,网络配置文件已停用。 如果使用的是此版本或更新版本,请忽略与网络配置文件相关的任何步骤和操作。

本文中的示例已针对 Bash shell 设置了格式。 若要使用其他 shell(例如 PowerShell 或命令提示符),请相应地调整续行符。

先决条件

定义环境变量

在本指南中,自动化部署路径将使用以下环境变量和资源名称。 手动完成指南的用户可以使用自己偏好的变量和名称。

export RANDOM_ID="$(openssl rand -hex 3)"
export MY_RESOURCE_GROUP_NAME="myACIResourceGroup$RANDOM_ID"
export MY_VNET_NAME="aci-vnet"
export MY_SUBNET_NAME="aci-subnet"
export MY_SUBNET_ID="/subscriptions/$(az account show --query id --output tsv)/resourceGroups/$MY_RESOURCE_GROUP_NAME/providers/Microsoft.Network/virtualNetworks/$MY_VNET_NAME/subnets/$MY_SUBNET_NAME"
export MY_APP_CONTAINER_NAME="appcontainer"
export MY_COMM_CHECKER_NAME="commchecker"
export MY_YAML_APP_CONTAINER_NAME="appcontaineryaml"

创建资源组

需要使用资源组来管理以下示例中使用的所有资源。 要创建资源组,请使用 az group create

az group create --name $MY_RESOURCE_GROUP_NAME --location eastus

成功的操作应生成类似于以下 JSON 的输出:

结果:

{
  "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx/resourceGroups/myACIResourceGroup123abc",
  "location": "abcdef",
  "managedBy": null,
  "name": "myACIResourceGroup123",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": "Microsoft.Resources/resourceGroups"
}

部署到新虚拟网络

注意

如果使用子网 IP 范围 /29,则只有 3 个 IP 地址。 建议始终高于一个范围(而绝不低于此范围)。 例如,使用子网 IP 范围 /28,这样每个容器组至少可以有 1 个或更多个 IP 缓冲区。 这样做可以避免容器处于卡滞、无法启动、重启,甚至无法停止的状态。

若要部署到新虚拟网络并让 Azure 自动创建网络资源,请在执行 az container create 时指定以下信息:

  • 虚拟网络名称
  • 采用 CIDR 格式的虚拟网络地址前缀
  • 子网名称
  • 采用 CIDR 格式的子网地址前缀

虚拟网络和子网地址前缀分别指定虚拟网络和子网的地址空间。 这些值以无类域间路由 (CIDR) 表示法表示,例如 10.0.0.0/16。 有关使用子网的详细信息,请参阅添加、更改或删除虚拟网络子网

使用此方法部署第一个容器组后,可以通过指定虚拟网络和子网名称或者 Azure 自动创建的网络配置文件,来部署到同一子网。 由于 Azure 将该子网委托给了 Azure 容器实例,因此只能将容器组部署到该子网。

示例

以下 az container create 命令指定新虚拟网络和子网的设置。 提供支持在虚拟网络中部署容器组的区域中创建的资源组的名称。 此命令将部署公共 Microsoft aci-helloworld 容器,该容器运行一个提供静态网页的小型 Node.js Web 服务器。 在下一部分,我们要将另一个容器组部署到同一子网,并测试这两个容器实例之间的通信。

az container create \
  --name $MY_APP_CONTAINER_NAME \
  --resource-group $MY_RESOURCE_GROUP_NAME \
  --image mcr.microsoft.com/azuredocs/aci-helloworld \
  --vnet $MY_VNET_NAME \
  --vnet-address-prefix 10.0.0.0/16 \
  --subnet $MY_SUBNET_NAME \
  --subnet-address-prefix 10.0.0.0/24

成功的操作应生成类似于以下 JSON 的输出:

结果:

{
  "confidentialComputeProperties": null,
  "containers": [
    {
      "command": null,
      "environmentVariables": [],
      "image": "mcr.microsoft.com/azuredocs/aci-helloworld",
      "instanceView": {
        "currentState": {
          "detailStatus": "",
          "exitCode": null,
          "finishTime": null,
          "startTime": "0000-00-00T00:00:00.000000+00:00",
          "state": "Running"
        },
        "events": [
          {
            "count": 1,
            "firstTimestamp": "0000-00-00T00:00:00+00:00",
            "lastTimestamp": "0000-00-00T00:00:00+00:00",
            "message": "Successfully pulled image \"mcr.microsoft.com/azuredocs/aci-helloworld@sha256:0000000000000000000000000000000000000000000000000000000000000000\"",
            "name": "Pulled",
            "type": "Normal"
          },
          {
            "count": 1,
            "firstTimestamp": "0000-00-00T00:00:00+00:00",
            "lastTimestamp": "0000-00-00T00:00:00+00:00",
            "message": "pulling image \"mcr.microsoft.com/azuredocs/aci-helloworld@sha256:0000000000000000000000000000000000000000000000000000000000000000\"",
            "name": "Pulling",
            "type": "Normal"
          },
          {
            "count": 1,
            "firstTimestamp": "0000-00-00T00:00:00+00:00",
            "lastTimestamp": "0000-00-00T00:00:00+00:00",
            "message": "Started container",
            "name": "Started",
            "type": "Normal"
          }
        ],
        "previousState": null,
        "restartCount": 0
      },
      "livenessProbe": null,
      "name": "appcontainer",
      "ports": [
        {
          "port": 80,
          "protocol": "TCP"
        }
      ],
      "readinessProbe": null,
      "resources": {
        "limits": null,
        "requests": {
          "cpu": 1.0,
          "gpu": null,
          "memoryInGb": 1.5
        }
      },
      "securityContext": null,
      "volumeMounts": null
    }
  ],
  "diagnostics": null,
  "dnsConfig": null,
  "encryptionProperties": null,
  "extensions": null,
  "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx/resourceGroups/myACIResourceGroup123/providers/Microsoft.ContainerInstance/containerGroups/appcontainer",
  "identity": null,
  "imageRegistryCredentials": null,
  "initContainers": [],
  "instanceView": {
    "events": [],
    "state": "Running"
  },
  "ipAddress": {
    "autoGeneratedDomainNameLabelScope": null,
    "dnsNameLabel": null,
    "fqdn": null,
    "ip": "10.0.0.4",
    "ports": [
      {
        "port": 80,
        "protocol": "TCP"
      }
    ],
    "type": "Private"
  },
  "location": "eastus",
  "name": "appcontainer",
  "osType": "Linux",
  "priority": null,
  "provisioningState": "Succeeded",
  "resourceGroup": "myACIResourceGroup123abc",
  "restartPolicy": "Always",
  "sku": "Standard",
  "subnetIds": [
    {
      "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx/resourceGroups/myACIResourceGroup123/providers/Microsoft.Network/virtualNetworks/aci-vnet/subnets/aci-subnet",
      "name": null,
      "resourceGroup": "myACIResourceGroup123abc"
    }
  ],
  "tags": {},
  "type": "Microsoft.ContainerInstance/containerGroups",
  "volumes": null,
  "zones": null
}

使用此方法部署到新虚拟网络时,部署可能需要花费几分钟时间,因为在此期间需要创建网络资源。 完成初始部署后,对于同一子网的后续容器组部署可以更快地完成。

部署到现有虚拟网络

将容器组部署到现有虚拟网络:

  1. 在现有虚拟网络中创建子网、使用已在其中部署了容器组的现有子网,或使用已清空了所有其他资源和配置的现有子网。 用于容器组的子网只能包含容器组。 在将容器组部署到子网之前,必须在预配之前显式委托该子网。 委托后,该子网只可用于容器组。 如果尝试将除容器组以外的资源部署到委派的子网,该操作将会失败。
  2. 使用 az container create 部署容器组并指定以下信息之一:
    • 虚拟网络名称和子网名称
    • 虚拟网络资源 ID 和子网资源 ID,它允许使用其他资源组中的虚拟网络

使用 YAML 文件进行部署

还可以通过使用 YAML 文件、资源管理器模板或其他编程方法(例如使用 Python SDK)将容器组部署到现有虚拟网络。

例如,使用 YAML 文件时,可以部署到具有委派给了 Azure 容器实例的子网的虚拟网络。 指定以下属性:

  • ipAddress:容器组的专用 IP 地址设置。
    • ports:要打开的端口(如果有)。
    • protocol:打开的端口的协议(TCP 或 UDP)。
  • subnetIds:要部署到的子网的资源 ID
    • id:子网的资源 ID
    • name:子网的名称

此 YAML 在虚拟网络中创建容器组。 在“名称”字段中输入容器组名称,并在“子网 ID”字段中输入子网 ID。 我们将 appcontaineryaml 用于名称。 如果需要查找子网 ID 但无法访问以前的输出,可以使用 az container show 命令查看子网 ID。 查找 subnetIds 下面的 id 字段。

apiVersion: '2021-07-01'
location: eastus
name: appcontaineryaml
properties:
  containers:
  - name: appcontaineryaml
    properties:
      image: mcr.microsoft.com/azuredocs/aci-helloworld
      ports:
      - port: 80
        protocol: TCP
      resources:
        requests:
          cpu: 1.0
          memoryInGB: 1.5
  ipAddress:
    type: Private
    ports:
    - protocol: tcp
      port: '80'
  osType: Linux
  restartPolicy: Always
  subnetIds:
    - id: <subnet_id>
      name: default
tags: null
type: Microsoft.ContainerInstance/containerGroups

以下 Bash 命令适用于自动部署路径。

echo -e "apiVersion: '2021-07-01'\nlocation: eastus\nname: $MY_YAML_APP_CONTAINER_NAME\nproperties:\n  containers:\n  - name: $MY_YAML_APP_CONTAINER_NAME\n    properties:\n      image: mcr.microsoft.com/azuredocs/aci-helloworld\n      ports:\n      - port: 80\n        protocol: TCP\n      resources:\n        requests:\n          cpu: 1.0\n          memoryInGB: 1.5\n  ipAddress:\n    type: Private\n    ports:\n    - protocol: tcp\n      port: '80'\n  osType: Linux\n  restartPolicy: Always\n  subnetIds:\n    - id: $MY_SUBNET_ID\n      name: default\ntags: null\ntype: Microsoft.ContainerInstance/containerGroups" > container-instances-vnet.yaml

使用 az container create 命令并在 --file 参数中指定 YAML 文件名,以部署容器组:

az container create --resource-group $MY_RESOURCE_GROUP_NAME \
  --file container-instances-vnet.yaml

以下 Bash 命令适用于自动部署路径。

rm container-instances-vnet.yaml

完成部署后,运行 az container show 命令以显示部署状态:

az container list --resource-group $MY_RESOURCE_GROUP_NAME --output table

输出应类似于以下示例:

结果:

Name              ResourceGroup             Status     Image                                       IP:ports        Network    CPU/Memory       OsType    Location
----------------  ------------------------  ---------  ------------------------------------------  --------------  ---------  ---------------  --------  ----------
appcontainer      myACIResourceGroup123abc  Succeeded  mcr.microsoft.com/azuredocs/aci-helloworld  10.0.0.4:80,80  Private    1.0 core/1.5 gb  Linux     abcdef
appcontaineryaml  myACIResourceGroup123abc  Succeeded  mcr.microsoft.com/azuredocs/aci-helloworld  10.0.0.5:80,80  Private    1.0 core/1.5 gb  Linux     abcdef

演示容器实例之间的通信

以下示例将第三个容器组部署到之前创建的同一子网。 使用 Alpine Linux 映像,它将验证自身与第一个容器实例之间的通信。

注意

由于拉取公共 Docker 映像(如此处使用的 Alpine Linux)时存在速率限制,你可能会收到以下格式的错误:

(RegistryErrorResponse) 从 Docker 注册表“index.docker.io”收到错误响应。 请稍后重试。 代码:RegistryErrorResponse 消息:从 Docker 注册表“index.docker.io”收到错误响应。 请稍后重试。

以下 Bash 命令适用于自动部署路径。

echo -e "Due to rate limiting in effect for pulling public Docker images like the Alpine Linux one used here, you may receive an error in the form:\n\n(RegistryErrorResponse) An error response is received from the docker registry 'index.docker.io'. Please retry later.\nCode: RegistryErrorResponse\nMessage: An error response is received from the docker registry 'index.docker.io'. Please retry later.\n\nIf this occurs, the automated deployment will exit. You can try again or go to the end of the guide to see instructions for cleaning up your resources."

首先,获取部署的第一个容器组 appcontainer 的 IP 地址:

az container show --resource-group $MY_RESOURCE_GROUP_NAME \
  --name $MY_APP_CONTAINER_NAME \
  --query ipAddress.ip --output tsv

输出会显示专用子网中容器组的 IP 地址。 例如:

结果:

10.0.0.4

现在,请将 CONTAINER_GROUP_IP 设置为使用 az container show 命令检索到的 IP,并执行以下 az container create 命令。 这第二个容器 commchecker 运行基于 Alpine Linux 的映像,并针对第一个容器组的专用子网 IP 地址执行 wget

az container create \
  --resource-group $MY_RESOURCE_GROUP_NAME \
  --name $MY_COMM_CHECKER_NAME \
  --image alpine:3.4 \
  --command-line "wget 10.0.0.4" \
  --restart-policy never \
  --vnet $MY_VNET_NAME \
  --subnet $MY_SUBNET_NAME

完成第二个容器的部署后,请提取其日志,以查看它执行的 wget 命令的输出:

az container logs --resource-group $MY_RESOURCE_GROUP_NAME --name $MY_COMM_CHECKER_NAME

如果第二个容器与第一个容器成功通信,则输出应类似于:

Connecting to 10.0.0.4 (10.0.0.4:80)
index.html           100% |*******************************|  1663   0:00:00 ETA

日志输出应显示 wget 可以在本地子网中使用第一个容器的专用 IP 地址连接到该容器,并可从中下载索引文件。 两个容器组之间的网络流量保留在虚拟网络中。

清理资源

如果不打算继续使用这些资源,可以将其删除以避免产生 Azure 费用。 可以通过 az group delete 命令删除资源组,清理本指南中使用的所有资源。 一旦删除,这些资源就不可恢复

后续步骤