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

快速入门:完成在 Azure 运营商服务管理器中部署容器化网络功能的先决条件

在此快速入门中,你将完成在使用 Azure 运营商服务管理器 (AOSM) 之前需要完成的任务。

先决条件

请联系 Microsoft 帐户团队,注册 Azure 订阅以访问 Azure 运营商服务管理器 (AOSM),或者通过合作伙伴注册表单表达你的兴趣。

下载并安装 Azure CLI

在 Azure Cloud Shell 中使用 Bash 环境。 有关详细信息,请参阅启动 Cloud Shell 以在 Azure Cloud Shell 中使用 Bash 环境。

对于想在本地运行 CLI 参考命令的用户,请参阅如何安装 Azure CLI

如果在 Windows 或 macOS 上运行,请考虑在 Docker 容器中运行 Azure CLI。 有关详细信息,请参阅如何在 Docker 容器中运行 Azure CLI

如果要使用本地安装,请使用 az login 命令登录到 Azure CLI,并完成终端中显示的提示以完成身份验证。 有关更多登录选项,请参阅使用 Azure CLI 登录

安装 Azure 运营商服务管理器 (AOSM) CLI 扩展

使用以下命令安装 Azure 运营商服务管理器 (AOSM) CLI 扩展:

az extension add --name aosm
  1. 运行 az version 以查看安装的版本和依赖库。
  2. 运行 az upgrade 以升级到 Azure CLI 的当前版本。

注册并验证所需的资源提供程序

开始使用 Azure 运营商服务管理器之前,执行以下命令注册所需的资源提供程序。 此注册过程可能最多需要 5 分钟时间。

# Register Resource Provider
az provider register --namespace Microsoft.HybridNetwork
az provider register --namespace Microsoft.ContainerRegistry

验证资源提供程序的注册状态。 执行以下命令。

# Query the Resource Provider
az provider show -n Microsoft.HybridNetwork --query "{RegistrationState: registrationState, ProviderName: namespace}"
az provider show -n Microsoft.ContainerRegistry --query "{RegistrationState: registrationState, ProviderName: namespace}"

注意

资源提供程序注册可能需要几分钟才能完成。 注册成功后,可开始使用 Azure 运营商服务管理器 (AOSM)。

容器化网络功能 (CNF) 的要求

对于使用容器化网络功能的用户,需要确保在从中执行 CLI 的计算机上安装以下包:

配置容器化网络功能 (CNF) 部署

对于容器化网络功能 (CNF) 的部署,需要在从中执行 CLI 的计算机上存储以下各项:

  • 带架构的 Helm 包 - 须将这些包存在于本地存储中,并在 input.json 配置文件中引用它们。 按照此快速入门操作时,需要下载所需的 helm 包。

  • 创建示例配置文件 - 生成用于定义 CNF 部署的示例配置文件。 发出此命令以生成需要填充特定配置的 input.json 文件。

    az aosm nfd generate-config --definition-type cnf
    
  • CNF 的映像 - 有以下选项:

    • 对包含 CNF 映像的现有 Azure 容器注册表的引用。 目前,每个 CNF 仅支持一个 ACR 和命名空间。 要从此 ACR 复制的映像将根据 helm 包架构自动填充。 必须对此 ACR 拥有读取者/AcrPull 权限。 若要使用此选项,请在 input.json 文件中填写 source_registry 和(可选)source_registry_namespace
    • 本地计算机的源 docker 映像的映像名称。 此映像名称适用于一种受限用例,其中 CNF 只需要一个 Docker 映像位于本地 Docker 存储库。 要使用此选项,需要在 input.json 文件中填入 source_local_docker_image。 需要安装 docker。 本快速入门将指导如何下载用于此选项的 nginx docker 映像。
  • 可选:映射文件 (path_to_mappings):可选择性地提供名为 path_to_mappings 的文件(磁盘上)。 此文件须充当 values.yaml 的镜像,并将所选值替换为部署参数。 这样做会将其作为参数公开给 CNF。 或可以在 input.json 中将此留空,CLI 会生成该文件。 在这种情况下,会默认将 values.yaml 中的每个值都公开为部署参数。 或使用 --interactive CLI 参数以交互方式做出选择。 此快速入门将指导如何创建此文件。

配置 input.json 文件时,请确保按包部署的顺序列出 Helm 包。 例如,如果包“A”必须在包“B”之前部署,则 input.json 应类似于以下结构:

"helm_packages": [
    {
        "name": "A",
        "path_to_chart": "Path to package A",
        "path_to_mappings": "Path to package A mappings",
        "depends_on": [
            "Names of the Helm packages this package depends on"
        ]
    },
    {
        "name": "B",
        "path_to_chart": "Path to package B",
        "path_to_mappings": "Path to package B mappings",
        "depends_on": [
            "Names of the Helm packages this package depends on"
        ]
    }
]

遵循这些准则可确保以系统有序的方法部署使用 Helm 包的容器化网络功能 (CNF) 和关联的配置。

将 nginx 映像下载到本地 docker 存储库

在此快速入门中,需要将 nginx docker 映像下载到本地存储库中。 Azure 运营商服务管理器 (AOSM) Azure CLI 扩展会将映像从那里推送到 Azure 运营商服务管理器 (AOSM) 项目存储 ACR。 CLI 扩展还支持从现有 ACR 复制映像。 复制映像是预期的默认用例,但如果快速入门创建要从中复制的 ACR 会比较慢,因此这里不使用此方法。

发出以下命令:docker pull nginx:stable

下载示例 Helm 图表

从此处的示例 Helm 图表下载要在此快速入门中使用的示例 Helm 图表。

深入了解 Helm 图表

本部分介绍一个基本的 Helm 图表,该图表设置 nginx 并将其配置为侦听指定端口。 本部分中提供的 Helm 图表已包含 values.schema.json 文件。

示例 values.schema.json 文件

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "additionalProperties": true,
    "properties": {
        "affinity": {
            "additionalProperties": false,
            "properties": {},
            "type": "object"
        },
        "fullnameOverride": {
            "type": "string"
        },
        "image": {
            "additionalProperties": false,
            "properties": {
                "pullPolicy": {
                    "type": "string"
                },
                "repository": {
                    "type": "string"
                },
                "tag": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "imagePullSecrets": {
            "items": {
                "anyOf": []
            },
            "type": "array"
        },
        "ingress": {
            "additionalProperties": false,
            "properties": {
                "annotations": {
                    "additionalProperties": false,
                    "properties": {},
                    "type": "object"
                },
                "enabled": {
                    "type": "boolean"
                },
                "hosts": {
                    "items": {
                        "anyOf": [
                            {
                                "additionalProperties": false,
                                "properties": {
                                    "host": {
                                        "type": "string"
                                    },
                                    "paths": {
                                        "items": {
                                            "anyOf": []
                                        },
                                        "type": "array"
                                    }
                                },
                                "type": "object"
                            }
                        ]
                    },
                    "type": "array"
                },
                "tls": {
                    "items": {
                        "anyOf": []
                    },
                    "type": "array"
                }
            },
            "type": "object"
        },
        "nameOverride": {
            "type": "string"
        },
        "nodeSelector": {
            "additionalProperties": false,
            "properties": {},
            "type": "object"
        },
        "podSecurityContext": {
            "additionalProperties": false,
            "properties": {},
            "type": "object"
        },
        "replicaCount": {
            "type": "integer"
        },
        "resources": {
            "additionalProperties": false,
            "properties": {},
            "type": "object"
        },
        "securityContext": {
            "additionalProperties": false,
            "properties": {},
            "type": "object"
        },
        "service": {
            "additionalProperties": false,
            "properties": {
                "port": {
                    "type": "integer"
                },
                "type": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "serviceAccount": {
            "additionalProperties": false,
            "properties": {
                "create": {
                    "type": "boolean"
                },
                "name": {
                    "type": "null"
                }
            },
            "type": "object"
        },
        "tolerations": {
            "items": {
                "anyOf": []
            },
            "type": "array"
        }
    },
    "type": "object"
}

虽然本文不涉及复杂的 Helm 用法,但有一些值得关注的元素,包括:

  • 服务端口配置:values.yaml 有一个服务端口 80 的预设。

示例 values.yaml 文件

# Default values for nginxdemo. 
# This is a YAML-formatted file. 
# Declare variables to be passed into your templates. 

 
replicaCount: 1 
 

image: 

  # Repository gets overwritten by AOSM to the Artifact Store ACR, however we've hard-coded the image name and tag in deployment.yaml 

  repository: overwriteme 
  tag: stable 
  pullPolicy: IfNotPresent 


imagePullSecrets: [] 
nameOverride: "" 
fullnameOverride: "" 

 
serviceAccount: 

  # Specifies whether a service account should be created 

  create: false 

  # The name of the service account to use. 
  # If not set and create is true, a name is generated using the fullname template 

  name: 
 

podSecurityContext: 

  {} 

  # fsGroup: 2000 

 
securityContext: 

  {} 
  # capabilities: 
  #   drop: 
  #   - ALL 
  # readOnlyRootFilesystem: true 
  # runAsNonRoot: true 
  # runAsUser: 1000 

 
service: 

  type: ClusterIP 
  port: 80 

  
ingress: 

  enabled: false 
  annotations: 

    {} 

    # kubernetes.io/ingress.class: nginx 
    # kubernetes.io/tls-acme: "true" 

  hosts: 

    - host: chart-example.local 
      paths: [] 

  
  tls: [] 

  #  - secretName: chart-example-tls 
  #    hosts: 
  #      - chart-example.local 

 
resources: 

  {} 

  # We usually recommend not to specify default resources and to leave this as a conscious 
  # choice for the user. This also increases chances charts run on environments with little 
  # resources, such as Minikube. If you do want to specify resources, uncomment the following 
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 
  # limits: 
  #   cpu: 100m 
  #   memory: 128Mi 
  # requests: 
  #   cpu: 100m 
  #   memory: 128Mi 
 

nodeSelector: {} 

 
tolerations: [] 

 
affinity: {}
  • 端口引用:此端口在多个位置使用:

    • service.yaml 中充当 {{ Values.service.port }}

示例 service.yaml 文件

apiVersion: v1 
kind: Service 

metadata: 
  name: {{ include "nginxdemo.fullname" . }} 
  labels: 

{{ include "nginxdemo.labels" . | indent 4 }} 

spec: 
  type: {{ .Values.service.type }} 
  ports: 
    - port: {{ .Values.service.port }} 
      targetPort: http 
      protocol: TCP 
      name: http 

  selector: 
    app.kubernetes.io/name: {{ include "nginxdemo.name" . }} 
    app.kubernetes.io/instance: {{ .Release.Name }}
  • nginx_config_map.yaml 中表示为 {{ Values.service.port }}。 此文件对应于 /etc/nginx/conf.d/default.conf,并使用一个配置映射在 deployment.yaml 中建立映射。

示例 nginx_config_map.yaml 文件

apiVersion: v1 
kind: ConfigMap 
metadata: 
  name: nginx-config 
# This writes the nginx config file to the ConfigMap and deployment.yaml mounts it as a volume  
# to the right place. 

data: 
  default.conf: | 
    log_format client '$remote_addr - $remote_user $request_time $upstream_response_time ' 
                    '[$time_local] "$request" $status $body_bytes_sent $request_body "$http_referer" ' 
                    '"$http_user_agent" "$http_x_forwarded_for"'; 

    server { 
        listen       80; 
        listen       {{ .Values.service.port }}; 
        listen  [::]:80; 
        server_name  localhost; 

        access_log  /var/log/nginx/host.access.log  client; 

        location / { 
            root   /usr/share/nginx/html; 
            index  index.html index.htm; 
            error_page 405 =200 $uri; 
        } 


        #error_page  404              /404.html; 
        # redirect server error pages to the static page /50x.html 
        # 
        error_page   500 502 503 504  /50x.html; 
        location = /50x.html { 
            root   /usr/share/nginx/html; 
        } 


        location = /cnf/test {   
            error_page 405 =200 $uri; 
        } 
   

        location = /post_thing { 
            # turn off logging here to avoid double logging 
            access_log off; 
            error_page 405 =200 $uri; 
        } 
    }

部署配置:deployment.yaml 文件展示与 imagePullSecretsimage 相关的特定行。 请务必观察其结构化格式,因为 Azure 运营商服务管理器 (AOSM) 会在部署期间为这些字段提供必要的值。 有关详细信息,请参阅 Helm 包要求

示例 deployment.yaml 文件

apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: {{ include "nginxdemo.fullname" . }} 
  labels: 
{{ include "nginxdemo.labels" . | indent 4 }} 

spec: 
  replicas: {{ .Values.replicaCount }} 
  selector: 
    matchLabels: 
      app.kubernetes.io/name: {{ include "nginxdemo.name" . }} 
      app.kubernetes.io/instance: {{ .Release.Name }} 

  template: 
    metadata: 
      labels: 
        app.kubernetes.io/name: {{ include "nginxdemo.name" . }} 
        app.kubernetes.io/instance: {{ .Release.Name }} 

    spec: 
      # Copied from sas 
      imagePullSecrets: {{ mustToPrettyJson (ternary (list ) .Values.imagePullSecrets (kindIs "invalid" .Values.imagePullSecrets)) }} 
      serviceAccountName: {{ template "nginxdemo.serviceAccountName" . }} 
      securityContext: 
        {{- toYaml .Values.podSecurityContext | nindent 8 }} 
      containers: 
        - name: {{ .Chart.Name }} 
          securityContext: 
            {{- toYaml .Values.securityContext | nindent 12 }} 
          # Want this to evaluate to acr-name.azurecr.io/nginx:stable (or specific version) 
          # docker tag nginx:stable acr-name.azurecr.io/nginx:stable 
          # docker push acr-name.azurecr.io/nginx:stable 
          # Image hard coded to that put in the Artifact Store ACR for this CNF POC 
          image: "{{ .Values.image.repository }}/nginx:stable" 
          imagePullPolicy: {{ .Values.image.pullPolicy }} 
          ports: 
            - name: http 
              containerPort: 80 
              protocol: TCP 
          livenessProbe: 
            httpGet: 
              path: / 
              port: http 
          readinessProbe: 
            httpGet: 
              path: / 
              port: http 
          resources: 
            {{- toYaml .Values.resources | nindent 12 }} 
          # Gets the nginx config from the configMap - see nginx_config_map.yaml 
          volumeMounts: 
            - name: nginx-config-volume 
              mountPath: /etc/nginx/conf.d/default.conf 
              subPath: default.conf 
      volumes: 
        - name: nginx-config-volume 
          configMap: 
            name: nginx-config 
      {{- with .Values.nodeSelector }} 
      nodeSelector: 
        {{- toYaml . | nindent 8 }} 
      {{- end }} 
    {{- with .Values.affinity }} 
      affinity: 
        {{- toYaml . | nindent 8 }} 
    {{- end }} 
    {{- with .Values.tolerations }} 
      tolerations: 
        {{- toYaml . | nindent 8 }} 
    {{- end }}

后续步骤