Todos os produtos
Search
Central de documentação

Container Service for Kubernetes:Implement phased releases and blue-green deployments with Nginx Ingress

Última atualização: Sep 21, 2026

Transfira o tráfego gradualmente para novas versões do Service com base em cabeçalho, cookie ou peso antes do corte total.

Contexto

Tanto os lançamentos graduais (também chamados de canary releases) quanto as implantações blue-green executam uma nova versão simultaneamente à antiga e direcionam parte do tráfego para ela. Após a estabilização, todo o tráfego passa para a nova versão e a versão antiga sai de operação.

O ACK Nginx Ingress Controller oferece suporte a dois métodos de divisão de tráfego baseados em annotations:

Método

Status

Observações

Annotations canary-*

Ativo

Método oficial da comunidade. Use este método para todas as novas configurações.

Annotations service-*

Obsoleto

Indisponível no Nginx Ingress Controller v1.12 e versões posteriores. Não use.

Casos de uso

  • Divisão de tráfego com base em requisições do cliente: direcione o tráfego para a nova versão apenas quando uma requisição contiver um cabeçalho ou cookie específico — por exemplo, foo=bar. As demais requisições seguem para a versão antiga. Após a estabilização, migre todo o tráfego.

    image

  • Divisão de tráfego com base no peso do Service: direcione uma porcentagem fixa de tráfego — por exemplo, 20% — para a nova versão. Aumente gradualmente a porcentagem até que todo o tráfego vá para a nova versão.

    image

Dimensões de divisão de tráfego com suporte:

  • Cabeçalho da requisição — ideal para lançamentos graduais e testes A/B

  • Cookie — ideal para lançamentos graduais e testes A/B

  • Parâmetro de query — ideal para lançamentos graduais e testes A/B

  • Peso do Service — ideal para implantações blue-green

O método de annotation canary-*

Referência de annotations

Todas as configurações canary exigem a annotation nginx.ingress.kubernetes.io/canary: "true". Outras annotations definem a lógica de roteamento.

Annotation

Descrição

Versão mín.

nginx.ingress.kubernetes.io/canary

Ativa o recurso canary. Defina como true para que qualquer outra annotation canary tenha efeito. Valores válidos: true, false.

>=v0.22.0

nginx.ingress.kubernetes.io/canary-by-header

Roteia requisições para o Service canary com base em um cabeçalho de requisição. Valores especiais: always (sempre roteia para o canary), never (nunca roteia para o canary). Se nenhum valor for especificado, o tráfego é encaminhado sempre que o cabeçalho estiver presente.

>=v0.22.0

nginx.ingress.kubernetes.io/canary-by-header-value

Roteia requisições para o Service canary quando o cabeçalho definido por canary-by-header corresponde a um valor exato. Use em conjunto com canary-by-header.

>=v0.30.0

nginx.ingress.kubernetes.io/canary-by-header-pattern

Roteia requisições para o Service canary quando o cabeçalho definido por canary-by-header corresponde a uma expressão regular. Use em conjunto com canary-by-header.

>=v0.44.0

nginx.ingress.kubernetes.io/canary-by-cookie

Roteia requisições para o Service canary com base em um cookie, por exemplo, nginx.ingress.kubernetes.io/canary-by-cookie: foo. Valores do cookie: always (foo=always roteia para o canary), never (foo=never não roteia). O tráfego é encaminhado apenas quando o cookie existe e tem o valor always.

>=v0.22.0

nginx.ingress.kubernetes.io/canary-weight

Roteia uma porcentagem de requisições para o Service canary com base no peso. Intervalo: 0 a canary-weight-total (padrão 100).

>=v0.22.0

nginx.ingress.kubernetes.io/canary-weight-total

Define o denominador total do peso. Padrão: 100.

>=v1.1.2

Prioridade das annotations (ordem decrescente):

canary-by-header > canary-by-cookie > canary-weight

Cada regra do Ingress suporta apenas um Ingress canary. O controlador ignora Ingresses canary adicionais.

Etapa 1: Implantar o Service

Implante um Service Nginx e exponha-o para acesso por domínio na camada 7 com o Nginx Ingress Controller.

  1. Crie um Deployment e um Service. Salve o seguinte conteúdo em nginx.yaml.

    Visualizar arquivo YAML

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: old-nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          run: old-nginx
      template:
        metadata:
          labels:
            run: old-nginx
        spec:
          containers:
          - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/old-nginx
            imagePullPolicy: Always
            name: old-nginx
            ports:
            - containerPort: 80
              protocol: TCP
          restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: old-nginx
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        run: old-nginx
      sessionAffinity: None
      type: NodePort

    Aplique o manifesto:

    kubectl apply -f nginx.yaml
  2. Crie o Ingress. Salve o seguinte conteúdo em ingress.yaml.

    Para clusters da v1.19 e posteriores

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gray-release
    spec:
      ingressClassName: nginx
      rules:
      - host: www.example.com
        http:
          paths:
          # Old version of the service.
          - path: /
            backend:
              service:
                name: old-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific

    Para clusters anteriores à v1.19

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: gray-release
    spec:
      rules:
      - host: www.example.com
        http:
          paths:
          # Old version of the service.
          - path: /
            backend:
              serviceName: old-nginx
              servicePort: 80

    Aplique o manifesto:

    kubectl apply -f ingress.yaml
  3. Verifique a implantação. Obtenha o endereço IP externo:

    kubectl get ingress

    Teste o acesso de roteamento:

    curl -H "Host: www.example.com" http://<EXTERNAL_IP>

    Resultado esperado:

    old

Etapa 2: Lançar a nova versão do Service

Implante a nova versão do Nginx e configure as regras de roteamento canary.

  1. Crie o novo Deployment e Service. Salve o seguinte conteúdo em nginx1.yaml.

    Visualizar arquivo YAML

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: new-nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          run: new-nginx
      template:
        metadata:
          labels:
            run: new-nginx
        spec:
          containers:
          - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/new-nginx
            imagePullPolicy: Always
            name: new-nginx
            ports:
            - containerPort: 80
              protocol: TCP
          restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: new-nginx
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        run: new-nginx
      sessionAffinity: None
      type: NodePort

    Aplique o manifesto:

    kubectl apply -f nginx1.yaml
  2. Crie um Ingress canary para rotear o tráfego para a nova versão. Três estratégias estão disponíveis. Estratégia A: Roteamento por cabeçalho de requisição Roteie requisições para a nova versão apenas quando o cabeçalho foo for igual a bar. As demais requisições vão para a versão antiga. Salve o seguinte conteúdo em ingress1.yaml. Para clusters da v1.19 e posteriores:

    • Com o cabeçalho foo: bar: 100% do tráfego vai para new-nginx (controlado por canary-by-header e canary-by-header-value).

    • Sem o cabeçalho foo: bar: 50% do tráfego vai para new-nginx (controlado por canary-weight).

    Para clusters da v1.19 e posteriores

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gray-release-canary
      annotations:
        # Enable canary routing.
        nginx.ingress.kubernetes.io/canary: "true"
        # Route to new-nginx only when the foo header equals bar.
        nginx.ingress.kubernetes.io/canary-by-header: "foo"
        nginx.ingress.kubernetes.io/canary-by-header-value: "bar"
    spec:
      ingressClassName: nginx
      rules:
      - host: www.example.com
        http:
          paths:
          # New version of the service.
          - path: /
            backend:
              service:
                name: new-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific

    Para clusters anteriores à v1.19

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: gray-release-canary
      annotations:
        nginx.ingress.kubernetes.io/canary: "true"
        nginx.ingress.kubernetes.io/canary-by-header: "foo"
        nginx.ingress.kubernetes.io/canary-by-header-value: "bar"
    spec:
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              serviceName: new-nginx
              servicePort: 80

    Aplique o manifesto e verifique:

    kubectl apply -f ingress1.yaml
    kubectl get ingress

    Teste sem o cabeçalho (roteado para a versão antiga):

    curl -H "Host: www.example.com" http://<EXTERNAL_IP>

    Resposta esperada: old Teste com o cabeçalho foo: bar (roteado para a nova versão):

    curl -H "Host: www.example.com" -H "foo: bar" http://<EXTERNAL_IP>

    Resultado esperado: new

    Estratégia B: Roteamento por cabeçalho e divisão do tráfego restante por peso

    Roteie todas as requisições com foo=bar para a nova versão e 50% das outras requisições para a nova versão. Atualize ingress1.yaml com o seguinte conteúdo.

    Para clusters da v1.19 e posteriores

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gray-release-canary
      annotations:
        nginx.ingress.kubernetes.io/canary: "true"
        # Route to new-nginx when foo header equals bar.
        nginx.ingress.kubernetes.io/canary-by-header: "foo"
        nginx.ingress.kubernetes.io/canary-by-header-value: "bar"
        # For requests that don't match the header rule, route 50% to new-nginx.
        nginx.ingress.kubernetes.io/canary-weight: "50"
    spec:
      ingressClassName: nginx
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              service:
                name: new-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific

    Para clusters anteriores à v1.19

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: gray-release-canary
      annotations:
        nginx.ingress.kubernetes.io/canary: "true"
        nginx.ingress.kubernetes.io/canary-by-header: "foo"
        nginx.ingress.kubernetes.io/canary-by-header-value: "bar"
        nginx.ingress.kubernetes.io/canary-weight: "50"
    spec:
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              serviceName: new-nginx
              servicePort: 80

    Aplique o manifesto:

    kubectl apply -f ingress1.yaml

    Estratégia C: Roteamento apenas por peso

    Roteie 50% do tráfego para a nova versão, independentemente de cabeçalhos ou cookies. Atualize ingress1.yaml com o seguinte conteúdo.

    Para clusters da v1.19 e posteriores

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gray-release-canary
      annotations:
        nginx.ingress.kubernetes.io/canary: "true"
        # Route 50% of all traffic to new-nginx. Default total weight is 100.
        nginx.ingress.kubernetes.io/canary-weight: "50"
    spec:
      ingressClassName: nginx
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              service:
                name: new-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific

    Para clusters anteriores à v1.19

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: gray-release-canary
      annotations:
        nginx.ingress.kubernetes.io/canary: "true"
        nginx.ingress.kubernetes.io/canary-weight: "50"
    spec:
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              serviceName: new-nginx
              servicePort: 80

    Aplique o manifesto:

    kubectl apply -f ingress1.yaml

    Verifique: execute este comando várias vezes. Cerca de 50% das respostas devem retornar new.

    curl -H "Host: www.example.com" http://<EXTERNAL_IP>

Etapa 3: Concluir a migração de tráfego

Após a estabilização da nova versão, desative a versão antiga.

  1. Atualize nginx.yaml para redirecionar o Service antigo para o novo Deployment.

    Visualizar arquivo YAML

    apiVersion: v1
    kind: Service
    metadata:
      name: old-nginx
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        # Point to the new service version.
        run: new-nginx
      sessionAffinity: None
      type: NodePort

    Aplique a atualização:

    kubectl apply -f nginx.yaml
  2. Verifique se todo o tráfego vai para a nova versão:

    kubectl get ingress
    curl -H "Host: www.example.com" http://<EXTERNAL_IP>

    Resultado esperado: new

  3. Exclua o Ingress canary:

    kubectl delete ingress gray-release-canary
  4. Exclua o Deployment antigo e o novo Service:

    kubectl delete deploy old-nginx
    kubectl delete svc new-nginx

O método de annotation service-*

Importante

A annotation service-* não está mais disponível no Nginx Ingress Controller v1.12 e versões posteriores. Não use.

Referência de annotations

Annotation

Descrição

nginx.ingress.kubernetes.io/service-match

Define regras de roteamento que mapeiam atributos da requisição para um Service. Sintaxe: `nginx.ingress.kubernetes.io/service-match:

: `. Tipos de correspondência com suporte: header, cookie, query. Formatos de correspondência: regex /regular expression/, exato "exact value". Exemplos: new-nginx: header("foo", /^bar$/); new-nginx: header("foo", "bar"); new-nginx: cookie("foo", /^sticky-.+$/); new-nginx: query("foo", "bar").

nginx.ingress.kubernetes.io/service-weight

Define pesos de tráfego entre as versões antiga e nova do Service. Sintaxe: `nginx.ingress.kubernetes.io/service-weight:

:, :`. Exemplo: new-nginx: 20, old-nginx: 60.

Etapa 1: Implantar o Service

Implante um Service Nginx e exponha-o para acesso por domínio na camada 7 com o Nginx Ingress Controller.

  1. Crie um Deployment e um Service. Salve o seguinte conteúdo em nginx.yaml.

    Visualizar arquivo YAML

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: old-nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          run: old-nginx
      template:
        metadata:
          labels:
            run: old-nginx
        spec:
          containers:
          - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/old-nginx
            imagePullPolicy: Always
            name: old-nginx
            ports:
            - containerPort: 80
              protocol: TCP
          restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: old-nginx
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        run: old-nginx
      sessionAffinity: None
      type: NodePort

    Aplique o manifesto:

    kubectl apply -f nginx.yaml
  2. Crie o Ingress. Salve o seguinte conteúdo em ingress.yaml.

    Para clusters da v1.19 e posteriores

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gray-release
    spec:
      ingressClassName: nginx
      rules:
      - host: www.example.com
        http:
          paths:
          # Old version of the service.
          - path: /
            backend:
              service:
                name: old-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific

    Para clusters anteriores à v1.19

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: gray-release
    spec:
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              serviceName: old-nginx
              servicePort: 80

    Aplique o manifesto:

    kubectl apply -f ingress.yaml
  3. Verifique a implantação. Obtenha o endereço IP externo:

    kubectl get ingress

    Valide o acesso de roteamento:

    curl -H "Host: www.example.com" http://<EXTERNAL_IP>

    Resultado esperado:

    old

Etapa 2: Lançar a nova versão do Service

Implante a nova versão do Nginx e configure as regras de roteamento.

  1. Crie o novo Deployment e Service. Salve o seguinte conteúdo em nginx1.yaml.

    Visualizar arquivo YAML

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: new-nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          run: new-nginx
      template:
        metadata:
          labels:
            run: new-nginx
        spec:
          containers:
          - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/new-nginx
            imagePullPolicy: Always
            name: new-nginx
            ports:
            - containerPort: 80
              protocol: TCP
          restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: new-nginx
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        run: new-nginx
      sessionAffinity: None
      type: NodePort

    Aplique o manifesto:

    kubectl apply -f nginx1.yaml
  2. Modifique o Ingress gray-release. Três estratégias estão disponíveis. Estratégia A: Roteamento por cabeçalho de requisição Roteie requisições para a nova versão apenas quando o cabeçalho foo corresponder a bar. Atualize ingress.yaml com o seguinte conteúdo. Para clusters da v1.19 e posteriores:

    Para clusters da v1.19 e posteriores

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gray-release
      annotations:
        # Route to new-nginx when the foo header matches ^bar$.
        nginx.ingress.kubernetes.io/service-match: |
          new-nginx: header("foo", /^bar$/)
    spec:
      ingressClassName: nginx
      rules:
      - host: www.example.com
        http:
          paths:
          # Old version of the service.
          - path: /
            backend:
              service:
                name: old-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific
          # New version of the service.
          - path: /
            backend:
              service:
                name: new-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific

    Para clusters anteriores à v1.19

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: gray-release
      annotations:
        nginx.ingress.kubernetes.io/service-match: |
          new-nginx: header("foo", /^bar$/)
    spec:
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              serviceName: old-nginx
              servicePort: 80
          - path: /
            backend:
              serviceName: new-nginx
              servicePort: 80

    Aplique o manifesto e verifique:

    kubectl apply -f ingress.yaml
    kubectl get ingress

    Teste sem o cabeçalho (roteado para a versão antiga):

    curl -H "Host: www.example.com" http://<EXTERNAL_IP>

    Resposta esperada: old Teste com o cabeçalho foo: bar (roteado para a nova versão):

    curl -H "Host: www.example.com" -H "foo: bar" http://<EXTERNAL_IP>

    Resultado esperado: new

    Estratégia B: Roteamento por cabeçalho com divisão baseada em peso

    Roteie requisições que correspondam a foo=bar para ambas as versões, sendo 50% para cada uma. Atualize ingress.yaml com o seguinte conteúdo.

    Para clusters da v1.19 e posteriores

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gray-release
      annotations:
        nginx.ingress.kubernetes.io/service-match: |
            new-nginx: header("foo", /^bar$/)
        # Of the matching requests, route 50% to new-nginx and 50% to old-nginx.
        nginx.ingress.kubernetes.io/service-weight: |
            new-nginx: 50, old-nginx: 50
    spec:
      ingressClassName: nginx
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              service:
                name: old-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific
          - path: /
            backend:
              service:
                name: new-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific

    Para clusters anteriores à v1.19

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: gray-release
      annotations:
        nginx.ingress.kubernetes.io/service-match: |
            new-nginx: header("foo", /^bar$/)
        nginx.ingress.kubernetes.io/service-weight: |
            new-nginx: 50, old-nginx: 50
    spec:
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              serviceName: old-nginx
              servicePort: 80
          - path: /
            backend:
              serviceName: new-nginx
              servicePort: 80

    Aplique o manifesto:

    kubectl apply -f ingress.yaml

    Execute o comando de teste várias vezes. Cerca de 50% das requisições com foo: bar devem retornar new.

    Estratégia C: Roteamento apenas por peso

    Roteie 50% do tráfego para a nova versão. Atualize ingress.yaml com o seguinte conteúdo.

    Para clusters da v1.19 e posteriores

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gray-release
      annotations:
        # Route 50% of all traffic to new-nginx.
        nginx.ingress.kubernetes.io/service-weight: |
            new-nginx: 50, old-nginx: 50
    spec:
      ingressClassName: nginx
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              service:
                name: old-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific
          - path: /
            backend:
              service:
                name: new-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific

    Para clusters anteriores à v1.19

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: gray-release
      annotations:
        nginx.ingress.kubernetes.io/service-weight: |
            new-nginx: 50, old-nginx: 50
    spec:
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              serviceName: old-nginx
              servicePort: 80
          - path: /
            backend:
              serviceName: new-nginx
              servicePort: 80

    Aplique o manifesto:

    kubectl apply -f ingress.yaml

    Verifique: execute este comando várias vezes. Cerca de 50% das respostas devem retornar new.

    curl -H "Host: www.example.com" http://<EXTERNAL_IP>

Etapa 3: Concluir a migração de tráfego

Após a estabilização da nova versão, desative a versão antiga.

  1. Aplique a atualização:

    Para clusters da v1.19 e posteriores

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gray-release
    spec:
      ingressClassName: nginx
      rules:
      - host: www.example.com
        http:
          paths:
          # New version of the service.
          - path: /
            backend:
              service:
                name: new-nginx
                port:
                  number: 80
            pathType: ImplementationSpecific

    Para clusters anteriores à v1.19

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: gray-release
    spec:
      rules:
      - host: www.example.com
        http:
          paths:
          - path: /
            backend:
              serviceName: new-nginx
              servicePort: 80
    kubectl apply -f ingress.yaml
  2. Verifique se todo o tráfego vai para a nova versão:

    kubectl get ingress
    curl -H "Host: www.example.com" http://<EXTERNAL_IP>

    Resultado esperado: new

  3. Exclua o Deployment e o Service antigos:

    kubectl delete deploy <Deployment_name>
    kubectl delete svc <Service_name>