Todos os produtos
Search
Central de documentação

Enterprise Distributed Application Service:Use toolkit-maven-plugin to perform a canary release in a Kubernetes cluster

Última atualização: Jun 26, 2026

O toolkit-maven-plugin automatiza liberações canário para aplicações Spring Cloud, Dubbo e High-speed Service Framework (HSF) implantadas no Enterprise Distributed Application Service (EDAS). Em vez de atualizar todas as instâncias simultaneamente, a liberação canário aplica as alterações primeiro a um pequeno subconjunto de instâncias e, depois, promove gradualmente a atualização para as instâncias restantes em lotes.

Como funciona a liberação canário

A liberação canário com o toolkit-maven-plugin segue um processo de duas fases:

  1. Fase canário: Implante a nova versão em um número especificado de instâncias (gray). Essas instâncias recebem tráfego real, permitindo validar a nova versão antes da implantação completa.

  2. Fase de implantação em lotes: Distribua a nova versão para as instâncias restantes em lotes controlados (batch), com um intervalo configurável (batchWaitTime) entre cada lote. Os lotes podem ser executados automaticamente ou exigir aprovação manual.

O tipo de estratégia de atualização do EDAS para esse processo é GrayBatchUpdate.

Pré-requisitos

Antes de começar, verifique se você tem:

  • Uma aplicação Spring Cloud, Dubbo ou HSF implantada em um cluster Kubernetes do EDAS

  • Um AccessKey ID e AccessKey secret de um usuário do Resource Access Management (RAM) (recomendado em vez das credenciais da conta raiz)

  • O ID da aplicação (appId) ou o ID do namespace de microsserviços (namespaceId) e o nome da aplicação (appName) da aplicação de destino

Configure uma liberação canário

Para configurar uma liberação canário, adicione a dependência do plug-in, crie os arquivos de configuração e execute o comando de implantação.

Etapa 1: Adicione a dependência do plug-in

Adicione a seguinte dependência ao seu arquivo pom.xml:

<build>
    <plugins>
        <plugin>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>toolkit-maven-plugin</artifactId>
            <version>1.1.9</version>
        </plugin>
    </plugins>
</build>
Nota

Sempre use a versão mais recente do toolkit-maven-plugin.

Etapa 2: Crie os arquivos de configuração

Crie três arquivos YAML no diretório raiz do projeto empacotado. Se estiver implantando um submódulo Maven, crie o arquivo de configuração de pacote no diretório do submódulo.

Configuração de conta (toolkit_profile.yaml)

regionId:        # Region where the application is deployed, for example, cn-hangzhou
accessKeyId:     # AccessKey ID of a RAM user
accessKeySecret: # AccessKey secret of a RAM user
jarPath:         # (Optional) Path to the deployment package. Skips Maven packaging if specified.

Configuração de pacote (toolkit_package.yaml)

apiVersion: V1
kind: AppPackage
spec:
  packageType:   # War, FatJar, Image, or url
  packageUrl:    # (Optional) URL of a remote deployment package. Used when packageType is url.
  imageUrl:      # (Optional) Image URL. Used when packageType is Image.

Configuração de implantação (toolkit_deploy.yaml)

apiVersion: V1
kind: AppDeployment
spec:
  type: kubernetes
  target:
    appId:        # Application ID. If specified, namespaceId and appName are not required.
    namespaceId:  # Microservices namespace ID. Required if appId is not specified.
    appName:      # Application name. Required if appId is not specified.
  updateStrategy:
    type: GrayBatchUpdate
    grayUpdate:
      gray: 2              # Number of instances to update in the canary phase
    batchUpdate:
      batch: 3             # Number of batches for the remaining instances
      releaseType: auto     # auto or manual
      batchWaitTime: 5      # Minutes to wait between batches

A tabela a seguir descreve os parâmetros da liberação canário:

Parâmetro

Descrição

Exemplo

appId

ID da aplicação no EDAS

6bbc57a2-a2a0-4edb-****-************

namespaceId

ID do namespace de microsserviços

cn-hangzhou:my-namespace

gray

Número de instâncias canário

2

batch

Quantidade de lotes de implantação

3

releaseType

auto (automático) ou manual (requer aprovação)

auto

batchWaitTime

Minutos entre os lotes

5

Etapa 3: Execute o comando de implantação

Acesse o diretório que contém o arquivo pom.xml (ou o pom.xml do submódulo) e execute:

mvn clean package toolkit:deploy \
  -Dtoolkit_profile=toolkit_profile.yaml \
  -Dtoolkit_package=toolkit_package.yaml \
  -Dtoolkit_deploy=toolkit_deploy.yaml

Quando a implantação for bem-sucedida, a saída exibirá BUILD SUCCESS.

Parâmetros do comando:

Parâmetro

Descrição

toolkit:deploy

Implanta a aplicação após a conclusão do empacotamento Maven.

-Dtoolkit_profile

Caminho para o arquivo de configuração de conta.

-Dtoolkit_package

Caminho para o arquivo de configuração de pacote.

-Dtoolkit_deploy

Caminho para o arquivo de configuração de implantação.

-Ddeploy_version

(Opcional) Versão da implantação. Substitui a versão definida em toolkit_deploy.yaml. Requer toolkit-maven-plugin 1.0.6 ou posterior.

Nota

Para omitir os parâmetros -Dtoolkit_profile, -Dtoolkit_package e -Dtoolkit_deploy, coloque os arquivos de configuração no mesmo diretório do pom.xml e prefixe cada nome de arquivo com um ponto (.toolkit_profile.yaml, .toolkit_package.yaml, .toolkit_deploy.yaml). O plug-in os detectará automaticamente.

Cenários de implantação

Implante com um pacote WAR ou FatJar local

Compile um pacote WAR ou FatJar localmente e implante-o em uma aplicação EDAS existente.

toolkit_package.yaml:

apiVersion: V1
kind: AppPackage
spec:
  packageType: War    # Or FatJar

toolkit_deploy.yaml:

apiVersion: V1
kind: AppDeployment
spec:
  type: kubernetes
  target:
    appId:        # Application ID
    namespaceId:  # (Optional) Namespace ID, required if appId is not specified
    appName:      # (Optional) Application name, required if appId is not specified

Implante com uma URL de imagem existente

Implante uma aplicação usando uma imagem de contêiner que já existe em um registro.

toolkit_package.yaml:

apiVersion: V1
kind: AppPackage
spec:
  packageType: Image
  imageUrl: registry.cn-beijing.aliyuncs.com/test/gateway:latest

toolkit_deploy.yaml:

apiVersion: V1
kind: AppDeployment
spec:
  type: kubernetes
  target:
    appId:        # Application ID
    namespaceId:  # (Optional) Namespace ID, required if appId is not specified
    appName:      # (Optional) Application name, required if appId is not specified

Compile e envie uma imagem Docker local

Compile uma imagem Docker localmente, envie-a para um repositório de imagens de contêiner da Alibaba Cloud e implante-a.

toolkit_package.yaml:

apiVersion: V1
kind: AppPackage
spec:
  packageType: Image
  build:
    docker:
      dockerfile: Dockerfile
      imageRepoAddress:   # Image repository address
      imageTag:           # Image tag
      imageRepoUser:      # Repository username
      imageRepoPassword:  # Repository password

toolkit_deploy.yaml:

apiVersion: V1
kind: AppDeployment
spec:
  type: kubernetes
  target:
    appId:        # Application ID
    namespaceId:  # (Optional) Namespace ID, required if appId is not specified
    appName:      # (Optional) Application name, required if appId is not specified

Referência de configuração

Parâmetros de pacote

apiVersion: V1
kind: AppPackage
spec:
  packageType:         # War, FatJar, Image, or url
  imageUrl:            # Image URL. Required when deploying with an image.
  packageUrl:          # Package URL. Used when packageType is url.
  build:
    docker:
      dockerfile:        # Dockerfile path. Required for local image builds.
      imageRepoAddress:  # Alibaba Cloud image repository address
      imageTag:          # Image tag
      imageRepoUser:     # Repository username
      imageRepoPassword: # Repository password
    oss:
      bucket:            # Object Storage Service (OSS) bucket name
      key:               # OSS object path
      accessKeyId:       # AccessKey ID for OSS access
      accessKeySecret:   # AccessKey secret for OSS access

Parâmetros de implantação

Clique para expandir os parâmetros compatíveis com o arquivo de configuração de implantação.

O arquivo de implantação aceita os seguintes parâmetros. Todos são opcionais, salvo indicação em contrário.

apiVersion: V1
kind: AppDeployment
spec:
  type: kubernetes
  target:
    appName:       # Application name
    namespaceId:   # Microservices namespace ID
    appId:         # Application ID. If specified, namespaceId and appName are not required.
    version:       # Deployment version. Default format: day-hour-minute-second.
    jdk:           # JDK version (Open JDK 7 or Open JDK 8). Not applicable to image deployments.
    webContainer:  # Tomcat version (apache-tomcat-7.0.91). Not applicable to image deployments.
    batchWaitTime: # Interval between batches (minutes)
    command:       # Container startup command. Overrides the default image command.
    commandArgs:   # Startup command arguments
    - 1d
  envs:            # Container environment variables
    - name: ENV_NAME
      value: 'value'

Verificações de integridade

Configure sondas de atividade e prontidão para monitorar a integridade do contêiner e da aplicação. Especifique um dos tipos exec, tcpSocket ou httpGet para cada sonda.

Contêineres que falham nas verificações de atividade são reiniciados. Contêineres que falham repetidamente nas verificações de prontidão são interrompidos e reiniciados, deixando de receber tráfego das instâncias do Server Load Balancer (SLB).

  liveness:
    exec:
      command:
        - cat
        - /tmp/healthy
    tcpSocket:
      host: "192.168.1.109"  # (Optional) Defaults to the pod IP address
      port: "8080"
    httpGet:
      path: "/health"
      port: "8080"
      host: "192.168.1.109"  # (Optional) Defaults to the pod IP address
      scheme: "HTTP"       # HTTP or HTTPS
      httpHeaders:
        - name: "Custom-Header"
          value: "value"
    initialDelaySeconds: 5   # Seconds before the first check
    timeoutSeconds: 11       # Seconds before a check times out
    periodSeconds: 5         # Seconds between checks
    successThreshold: 1      # Must be 1 for liveness probes
    failureThreshold: 3      # Consecutive failures before action

  readiness:
    exec:
      command:
        - cat
        - /tmp/healthy
    tcpSocket:
      host: "192.168.1.109"  # (Optional) Defaults to the pod IP address
      port: "8080"
    httpGet:
      path: "/health"
      port: "8080"
      host: "192.168.1.109"  # (Optional) Defaults to the pod IP address
      scheme: "HTTP"
      httpHeaders:
        - name: "Custom-Header"
          value: "value"
    initialDelaySeconds: 5
    timeoutSeconds: 11
    periodSeconds: 5
    successThreshold: 2
    failureThreshold: 3

Hooks de ciclo de vida

  preStop:          # Runs before the container is terminated
    exec:
      command:
        - /bin/bash
        - -c
        - "sleep 30"
    httpGet:
      host: "192.168.1.109"  # (Optional) Defaults to the pod IP address
      path: "/shutdown"
      port: "8080"
      scheme: "HTTP"         # HTTP or HTTPS
      httpHeaders:
        - name: "Custom-Header"
          value: "value"

  postStart:        # Runs after the container starts
    exec:
      command:
        - /bin/bash
        - -c
        - "echo started"
    httpGet:
      host: "192.168.1.109"  # (Optional) Defaults to the pod IP address
      path: "/initialize"
      port: "8080"
      scheme: "HTTP"         # HTTP or HTTPS
      httpHeaders:
        - name: "Custom-Header"
          value: "value"

Montagens de configuração

Monte recursos ConfigMap ou Secret no contêiner.

  configMountDescs:
    - type: "ConfigMap"           # ConfigMap or Secret
      name: "my-config"
      mountPath: "/home/admin"    # Mount directory
      mountItems:                 # Mount as individual files
        - key: "config-key"
          path: "config-file"
      useSubPath: true            # true: keep existing files; false: overwrite

Parâmetros de inicialização Java

  javaStartUpConfig:
    initialHeapSize:             # -Xms (initial heap size, MB)
      original: 1000
      startup: "-Xms1000m"
    maxHeapSize:                 # -Xmx (max heap size, MB)
      original: 1000
      startup: "-Xmx1000m"
    newSize:                     # -XX:NewSize (initial young generation, MB)
      original: 200
      startup: "-XX:NewSize=200m"
    maxNewSize:                  # -XX:MaxNewSize (max young generation, MB)
      original: 200
      startup: "-XX:MaxNewSize=200m"
    survivorRatio:               # -XX:SurvivorRatio (Eden to Survivor ratio)
      original: 2
      startup: "-XX:SurvivorRatio=2"
    newRatio:                    # -XX:NewRatio (old to young generation ratio)
      original: 8
      startup: "-XX:NewRatio=8"
    permSize:                    # -XX:PermSize (permanent generation, MB)
      original: 512
      startup: "-XX:PermSize=512m"
    maxPermSize:                 # -XX:MaxPermSize (max permanent generation, MB)
      original: 512
      startup: "-XX:MaxPermSize=200m"
    maxDirectMemorySize:         # -XX:MaxDirectMemorySize (MB)
      original: 100
      startup: "-XX:MaxDirectMemorySize=100m"
    threadStackSize:             # -XX:ThreadStackSize
      original: 500
      startup: "-XX:ThreadStackSize=500"
    hsfserverPort:               # HSF server port
      original: 12200
      startup: "-Dhsf.server.port=12200"
    hsfserverMinPoolSize:        # HSF minimum thread pool size
      original: 50
      startup: "-Dhsf.server.min.poolsize=50"
    hsfserverMaxPoolSize:        # HSF maximum thread pool size
      original: 720
      startup: "-Dhsf.server.max.poolsize=720"
    youngGarbageCollector:       # Young generation GC policy
      original: "UseSerialGC"   # UseSerialGC, UseG1GC, UseParNewGC, or UseParallelGC
      startup: "-XX:+UseSerialGC"
    oldGarbageCollector:         # Old generation GC policy
      original: "UseConcMarkSweepGC"   # UseConcMarkSweepGC, UseSerialGC, UseG1GC, UseParNewGC, UseParallelOldGC, or UseParallelGC
      startup: "-XX:+UseConcMarkSweepGC"
    concGCThreads:               # Concurrent GC threads
      original: 5
      startup: "-XX:ConcGCThreads=5"
    parallelGCThreads:           # Parallel GC threads
      original: 5
      startup: "-XX:ParallelGCThreads=5"
    g1HeapRegionSize:            # G1 region size (MB)
      original: 50
      startup: "-XX:G1HeapRegionSize=50m"
    gclogFilePath:               # GC log directory
      original: "/tmp/"
      startup: "-Xloggc:/tmp/"
    useGCLogFileRotation:        # Enable GC log rotation
      original: true
      startup: "-XX:+UseGCLogFileRotation"
    numberOfGCLogFiles:          # Number of GC log files
      original: 5
      startup: "-XX:NumberOfGCLogFiles=5"
    gclogFileSize:               # GC log file size (MB)
      original: 100
      startup: "-XX:GCLogFileSize=100m"
    heapDumpOnOutOfMemoryError:  # Enable out-of-memory (OOM) heap dumps
      original: true
      startup: "-XX:+HeapDumpOnOutOfMemoryError"
    heapDumpPath:                # OOM dump file path
      original: "/tmp/dumpfile"
      startup: "-XX:HeapDumpPath=/tmp/dumpfile"
    customParams:                # Custom JVM parameters
      original: "-Dtest=true"
      startup: "-Dtest=true"

Regras de agendamento

  deployAcrossZones: "true"    # Deploy pods across availability zones (recommended)
  deployAcrossNodes: "true"    # Deploy pods across nodes (recommended)

  customTolerations:           # Kubernetes scheduling tolerations
    - key: my-key
      operator: Exists         # Exists or Equal
      effect: NoSchedule       # NoSchedule or NoExecute
    - key: another-key
      operator: Equal
      value: "my-value"
      effect: "NoExecute"
      tolerationSeconds: 300

  customAffinity:
    nodeAffinity:              # Schedule pods based on node labels
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: "topology.kubernetes.io/zone"
                operator: "In"
                values:
                  - "cn-hangzhou-a"
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 1
          preference:
            matchExpressions:
              - key: "topology.kubernetes.io/zone"
                operator: "In"
                values:
                  - "cn-hangzhou-b"
    podAffinity:               # Co-locate pods with matching pods
      requiredDuringSchedulingIgnoredDuringExecution:
        - namespaces:
            - "default"
          topologyKey: "topology.kubernetes.io/zone"
          labelSelector:
            matchExpressions:
              - key: "app"
                operator: "In"
                values:
                  - "my-app"
    podAntiAffinity:           # Spread pods away from matching pods
      requiredDuringSchedulingIgnoredDuringExecution:
        - namespaces:
            - "default"
          topologyKey: "kubernetes.io/hostname"
          labelSelector:
            matchExpressions:
              - key: "app"
                operator: "In"
                values:
                  - "my-app"
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 2
          podAffinityTerm:
            namespaces:
              - "default"
            topologyKey: "kubernetes.io/hostname"
            labelSelector:
              matchExpressions:
                - key: "app"
                  operator: "In"
                  values:
                    - "my-app"