Provisionando Balanceadores de Carga do OCI para Serviços do Kubernetes do Tipo LoadBalancer

Descubra como provisionar um balanceador de carga do OCI para um serviço Kubernetes do tipo LoadBalancer usando o Kubernetes Engine (OKE).

Um balanceador de carga do OCI é um proxy da camada 4 (TCP) e da camada 7 (HTTP) do OSI, que suporta recursos como encerramento de SSL e políticas avançadas de roteamento HTTP. Ele oferece a máxima flexibilidade, com escalonamento responsivo para cima e para baixo. Você escolhe uma largura de banda mínima personalizada e uma largura de banda máxima opcional, entre 10 Mbps e 8.000 Mbps. A largura de banda mínima está sempre disponível e fornece prontidão instantânea para suas cargas de trabalho.

Para obter mais informações sobre balanceadores de carga do OCI, consulte Visão Geral do Serviço Load Balancer.

O provisionamento de um balanceador de carga do OCI para um serviço do Kubernetes do tipo LoadBalancer permite:

  • tráfego da camada 4 e da camada 7 (TCP e HTTP) de transporte de balanceamento de carga
  • encerrar SSL/TLS no balanceador de carga

Observe que, quando o Kubernetes Engine provisiona um balanceador de carga do OCI para um serviço Kubernetes do tipo LoadBalancer, as regras de segurança para permitir tráfego de entrada e saída de e para a sub-rede do balanceador de carga são criadas automaticamente por padrão. Consulte Regras de Segurança para Balanceadores de Carga e Balanceadores de Carga de Rede.

Use métricas do balanceador de carga do OCI para monitorar a integridade de um balanceador de carga do OCI provisionado para um serviço Kubernetes do tipo LoadBalancer (consulte Métricas do Serviço Load Balancer).

Especificando a Anotação para um Balanceador de Carga do OCI

Para provisionar um balanceador de carga do Oracle Cloud Infrastructure para um serviço Kubernetes do tipo LoadBalancer, defina um serviço do tipo LoadBalancer que inclua a seguinte anotação na seção de metadados do arquivo de manifesto:
oci.oraclecloud.com/load-balancer-type: "lb"

Observe que lb é o valor padrão da anotação oci.oraclecloud.com/load-balancer-type. Se você não incluir explicitamente a anotação na definição de serviço, o valor padrão da anotação será usado.

Por exemplo, considere o seguinte arquivo de configuração, nginx_lb.yaml. Ele define uma implantação (kind: Deployment) para o aplicativo nginx, seguida de uma definição de um serviço do tipo LoadBalancer (type: LoadBalancer) que equilibra o tráfego http na porta 80 para o aplicativo nginx.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-nginx-svc
  labels:
    app: nginx
  annotations:
    oci.oraclecloud.com/load-balancer-type: "lb"
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: nginx

A primeira parte do arquivo de configuração define uma implantação Nginx, solicitando que ele seja hospedado em 3 pods executando a imagem nginx:latest e aceite o tráfego para os contêineres na porta 80.

A segunda parte do arquivo de configuração define o serviço Nginx, que usa o tipo LoadBalancer para equilibrar o tráfego Nginx na porta 80 entre os pods disponíveis.

Para criar a implantação e o serviço definidos em nginx_lb.yaml enquanto estiver conectado ao cluster do Kubernetes, digite o comando:

kubectl apply -f nginx_lb.yaml

Esse comando gera o seguinte após a criação bem-sucedida da implantação e do balanceador de carga:

deployment "my-nginx" created
service "my-nginx-svc" created

O balanceador de carga pode levar alguns minutos para passar do estado pendente para totalmente operacional. Você pode exibir o estado atual do cluster digitando:

kubectl get all

A saída do comando acima mostra o estado atual:


NAME                                  READY     STATUS    RESTARTS   AGE
po/my-nginx-431080787-0m4m8           1/1       Running   0          3m
po/my-nginx-431080787-hqqcr           1/1       Running   0          3m
po/my-nginx-431080787-n8125           1/1       Running   0          3m

NAME               CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
svc/kubernetes     203.0.113.1     <NONE>           443/TCP        3d
svc/my-nginx-svc   203.0.113.7     192.0.2.22       80:30269/TCP   3m

NAME                      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/my-nginx           3         3         3            3           3m

NAME                            DESIRED   CURRENT   READY     AGE
rs/my-nginx-431080787           3         3         3         3m

A saída mostra que a implantação my-nginx está em execução em 3 pods (as entradas po/my-nginx), que o balanceador de carga está em execução (svc/my-nginx-svc) e tem um IP externo (192.0.2.22) que os clientes podem usar para estabelecer conexão com o aplicativo que está implantado nos pods.

Encerrando SSL/TLS no Balanceador de Carga

Quando o Kubernetes Engine provisiona um balanceador de carga para um serviço do Kubernetes do tipo LoadBalancer, você pode especificar que deseja encerrar a SSL no balanceador de carga. Essa configuração é conhecida como SSL frontend. Para implementar o SSL frontend, defina um listener em uma porta como 443 e associe um certificado SSL ao listener.

Observe que você pode implementar criptografia SSL ponto a ponto completa entre clientes e pods de aplicativos em execução nos nós de trabalho. Para fazer isso, crie um balanceador de carga com encerramento de SSL (conforme descrito nesta seção) e também associe um certificado SSL ao conjunto de backend do balanceador de carga (consulte Implementação de SSL/TLS entre o Balanceador de Carga e os Nós de Trabalho).

Este exemplo fornece um passo a passo da configuração e criação de um balanceador de carga com suporte a SSL.

Considere o seguinte arquivo de configuração, nginx-demo-svc-ssl.yaml, que define uma implantação Nginx e a expõe por meio de um balanceador de carga que fornece http na porta 80, e https na porta 443. Esta amostra cria um balanceador de carga do Oracle Cloud Infrastructure, definindo um serviço com um tipo de LoadBalancer (type: LoadBalancer).

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
  name: nginx-service
  annotations:
    oci.oraclecloud.com/load-balancer-type: "lb"
    service.beta.kubernetes.io/oci-load-balancer-ssl-ports: "443"
    service.beta.kubernetes.io/oci-load-balancer-tls-secret: ssl-certificate-secret
spec:
  selector:
    app: nginx
  type: LoadBalancer
  ports:
  - name: http
    port: 80
    targetPort: 80
  - name: https
    port: 443
    targetPort: 80

As anotações do Balanceador de Carga são de particular importância. As portas nas quais há suporte para o tráfego https são definidas pelo valor service.beta.kubernetes.io/oci-load-balancer-ssl-ports. É possível declarar várias portas SSL usando uma lista separada por vírgulas para o valor da anotação. Por exemplo, você pode definir o valor da anotação como "443, 3000" para oferecer suporte a SSL nas portas 443 e 3000.

O segredo TLS necessário, ssl-certificate-secret, precisa ser criado no Kubernetes. Este exemplo cria e usa um certificado autoassinado. No entanto, em um ambiente de produção, o cenário mais comum é usar um certificado público que tenha sido assinado por uma autoridade de certificação.

O comando a seguir cria um certificado autoassinado, tls.crt, com sua chave correspondente, tls.key:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"

Agora que você criou o certificado, precisa armazená-lo e também sua respectiva chave como um segredo no Kubernetes. O nome do segredo deve corresponder ao nome da anotação service.beta.kubernetes.io/oci-load-balancer-tls-secret da definição do balanceador de carga. Use o comando a seguir para criar um segredo do TLS no Kubernetes, cujos valores de chave e certificado são definidos por --key e --cert, respectivamente.

kubectl create secret tls ssl-certificate-secret --key tls.key --cert tls.crt

Você deve criar o segredo Kubernetes antes de criar o serviço, pois ele faz referência ao segredo em sua definição. Crie o serviço usando o seguinte comando:

kubectl create -f manifests/demo/nginx-demo-svc-ssl.yaml

Observe o serviço e aguarde que um endereço IP público (EXTERNAL-IP) seja designado ao serviço Nginx (nginx-service) digitando:

kubectl get svc --watch

A saída do comando acima mostra o IP do balanceador de carga a ser usado para estabelecer conexão com o serviço.


NAME            CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
nginx-service   192.0.2.1      198.51.100.1     80:30274/TCP   5m

O balanceador de carga agora está em execução, o que significa que o serviço agora pode ser acessado da seguinte maneira:

  • usando http, digitando:
    curl http://198.51.100.1
  • usando https, digitando:
    curl --insecure https://198.51.100.1

    O flag "--insecure" é usado para acessar o serviço usando https em decorrência do uso de certificados autoassinados neste exemplo. Não use esse flag em um ambiente de produção no qual o certificado público tenha sido assinado por uma autoridade de certificação.

Observação: Quando um cluster é excluído, um balanceador de carga criado de forma dinâmica quando um serviço é criado não será removido. Antes de excluir um cluster, exclua o serviço, o que, por sua vez, resultará na remoção do balanceador de carga. A sintaxe desse comando é a seguinte:

kubectl delete svc SERVICE_NAME

Por exemplo, para excluir o serviço do exemplo anterior, digite:

kubectl delete svc nginx-service

Atualizando os Certificados TLS dos Balanceadores de Carga Existentes

Para atualizar o certificado TLS de um balanceador de carga existente:
  1. Obtenha um novo certificado TLS. Em um ambiente de produção, o cenário mais comum é usar um certificado público que tenha sido assinado por uma autoridade de certificação.
  2. Crie um novo segredo do Kubernetes. Por exemplo, informando:

    kubectl create secret tls new-ssl-certificate-secret --key new-tls.key --cert new-tls.crt
    
  3. Modifique a definição de serviço para referenciar o novo segredo do Kubernetes alterando a anotação service.beta.kubernetes.io/oci-load-balancer-tls-secret na configuração do serviço. Por exemplo:
    
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
      annotations:
        service.beta.kubernetes.io/oci-load-balancer-ssl-ports: "443"
        service.beta.kubernetes.io/oci-load-balancer-tls-secret: new-ssl-certificate-secret
    spec:
      selector:
        app: nginx
      type: LoadBalancer
      ports:
      - name: http
        port: 80
        targetPort: 80
      - name: https
        port: 443
        targetPort: 80
  4. Atualize o serviço. Por exemplo, informando:
    kubectl apply -f new-nginx-demo-svc-ssl.yaml

Implementando SSL/TLS entre o Balanceador de Carga e os Nós de Trabalho

Quando o Kubernetes Engine provisiona um balanceador de carga para um serviço do Kubernetes do tipo LoadBalancer, você pode especificar que deseja implementar SSL entre o balanceador de carga e os servidores de backend (nós do colaborador) no conjunto de backend. Essa configuração é conhecida como SSL de backend. Para implementar SSL de backend, associe um certificado SSL ao conjunto de backend do balanceador de carga.

Observe que você pode implementar criptografia SSL ponto a ponto completa entre clientes e pods de aplicativos em execução nos nós de trabalho. Para fazer isso, associe um certificado SSL ao conjunto de backend do balanceador de carga (conforme descrito nesta seção) e também crie um balanceador de carga com encerramento de SSL (consulte Encerrando SSL/TLS no Balanceador de Carga).

Para especificar o certificado a ser associado ao conjunto de backend, adicione a seguinte anotação na seção de metadados do arquivo de manifesto:

service.beta.kubernetes.io/oci-load-balancer-tls-backendset-secret: <value>

em que <value> é o nome de um segredo do Kubernetes que você criou para conter um certificado assinado e a chave privada do certificado. Observe que você deve criar o segredo Kubernetes antes de criar o serviço, pois ele faz referência ao segredo em sua definição.

O exemplo a seguir cria e usa um certificado autoassinado, que geralmente é aceitável para comunicação interna entre o balanceador de carga e o conjunto de backend. No entanto, se preferir, pode usar um certificado público que tenha sido assinado por uma autoridade de certificação.

Por exemplo:

  1. Gere uma chave privada informando:

    openssl genrsa -out ca.key 2048
  2. Gere um certificado digitando:

    openssl req -x509 -new -nodes -key ca.key -subj "/CN=nginxsvc/O=nginxsvc" -days 10000 -out ca.crt
  3. Armazene o certificado e a chave como segredo no Kubernetes digitando:

    kubectl create secret generic ca-ser-secret --from-file=tls.crt=tls.crt --from-file=tls.key=tls.key --from-file=ca.crt=ca.crt
  4. Defina uma implantação do Nginx e exponha-a por meio de um balanceador de carga que serve http na porta 80 e https na porta 443. Esta amostra cria um balanceador de carga do Oracle Cloud Infrastructure, definindo um serviço com um tipo de LoadBalancer (type: LoadBalancer).
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx
            ports:
            - containerPort: 80
    ---
    apiVersion: v1
    metadata:
      name: nginx-service
      annotations:
        oci.oraclecloud.com/load-balancer-type: "lb"
        service.beta.kubernetes.io/oci-load-balancer-tls-backendset-secret: ca-ser-secret
        service.beta.kubernetes.io/oci-load-balancer-ssl-ports: "443" 
    spec:
      selector:
        app: nginx
      type: LoadBalancer
      ports:
      - name: http
        port: 80
        targetPort: 80
      - name: https
        port: 443
        targetPort: 443

A comunicação entre o balanceador de carga e os nós de trabalho no conjunto de backend é criptografada usando a chave e o certificado armazenados no segredo do Kubernetes ca-ser-secret criado anteriormente.

Especificando Formas Alternativas de Balanceador de Carga

A forma de um balanceador de carga do Oracle Cloud Infrastructure especifica sua largura de banda total máxima (ou seja, entrada e saída). Por padrão, os balanceadores de carga são criados com uma forma de 100 Mbps. Outras formas estão disponíveis, incluindo 400 Mbps e 8.000 Mbps.

Para especificar uma forma alternativa para um balanceador de carga, adicione a seguinte anotação na seção de metadados do arquivo de manifesto:

service.beta.kubernetes.io/oci-load-balancer-shape: <value>

em que value corresponde à largura de banda da forma (por exemplo, 100 Mbps, 400 Mbps, 8.000 Mbps).

Por exemplo:


apiVersion: v1
kind: Service
metadata:
  name: my-nginx-svc
  labels:
    app: nginx
  annotations:
    oci.oraclecloud.com/load-balancer-type: "lb"
    service.beta.kubernetes.io/oci-load-balancer-shape: 400Mbps
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: nginx

A cota suficiente do balanceador de carga deve estar disponível na região para a forma especificada. Digite o seguinte comando kubectl para confirmar que a criação do balanceador de carga não falhou devido à falta de cota:

kubectl describe service <service-name>

Observe que a Oracle recomenda que você implemente serviços do Kubernetes do tipo LoadBalancer como balanceadores de carga flexíveis econômicos, em vez de como balanceadores de carga de forma fixa (dinâmicos) (consulte Especificando Formas Flexíveis do Balanceador de Carga).

Especificando Formas Flexíveis de Balanceador de Carga

A forma de um balanceador de carga do Oracle Cloud Infrastructure especifica sua largura de banda total máxima (ou seja, entrada e saída). Conforme descrito em Especificando Formas Alternativas de Balanceador de Carga, você pode especificar diferentes formas de balanceador de carga.

Além disso, você também pode especificar uma forma flexível para um balanceador de carga do Oracle Cloud Infrastructure, definindo uma largura de banda mínima e máxima para o balanceador de carga.

Para especificar uma forma flexível para um balanceador de carga, adicione as seguintes anotações na seção de metadados do arquivo de manifesto:

service.beta.kubernetes.io/oci-load-balancer-shape: "flexible"
service.beta.kubernetes.io/oci-load-balancer-shape-flex-min: "<min-value>"
service.beta.kubernetes.io/oci-load-balancer-shape-flex-max: "<max-value>"

em que:

  • "<min-value>" é a largura de banda mínima do balanceador de carga, em Mbps (por exemplo, "10")
  • "<max-value>" é a largura de banda máxima do balanceador de carga, em Mbps (por exemplo, "100")

Observe que você não inclui uma unidade de medida ao especificar valores de largura de banda para formas flexíveis de balanceador de carga (ao contrário de formas predefinidas). Por exemplo, especifique a largura de banda mínima como 10, não como 10Mbps.

Por exemplo:


apiVersion: v1
kind: Service
metadata:
  name: my-nginx-svc
  labels:
    app: nginx
  annotations:
    oci.oraclecloud.com/load-balancer-type: "lb"
    service.beta.kubernetes.io/oci-load-balancer-shape: "flexible"
    service.beta.kubernetes.io/oci-load-balancer-shape-flex-min: "10"
    service.beta.kubernetes.io/oci-load-balancer-shape-flex-max: "100"
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: nginx

Especificando o Timeout de Conexão do Balanceador de Carga

Ao provisionar um balanceador de carga do Oracle Cloud Infrastructure para um serviço Kubernetes do tipo LoadBalancer, você pode especificar o tempo máximo de inatividade (em segundos) permitido entre duas operações de recebimento sucessivas ou duas operações de envio sucessivas entre o cliente e os servidores de backend.

Para especificar explicitamente um tempo máximo de inatividade, adicione a seguinte anotação na seção de metadados do arquivo de manifesto:

service.beta.kubernetes.io/oci-load-balancer-connection-idle-timeout: <value>

em que value corresponde ao número de segundos.

Por exemplo:


apiVersion: v1
kind: Service
metadata:
  name: my-nginx-svc
  labels:
    app: nginx
  annotations:
    oci.oraclecloud.com/load-balancer-type: "lb"
    service.beta.kubernetes.io/oci-load-balancer-connection-idle-timeout: 100
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: nginx

Observe que, se você não especificar explicitamente um tempo máximo de inatividade, será usado um valor padrão. O valor padrão depende do tipo de listener:

  • para listeners TCP, o tempo máximo de inatividade padrão é de 300 segundos
  • para listeners HTTP, o tempo máximo de inatividade padrão é de 60 segundos

Especificando Protocolos de Listener

Quando o Kubernetes Engine provisiona um balanceador de carga para um serviço do Kubernetes do tipo LoadBalancer, você pode definir o tipo de tráfego aceito pelo listener especificando o protocolo no qual o listener aceita solicitações de conexão.

Observe que, se você não especificar explicitamente um protocolo, "TCP" será usado como o valor padrão.

Para especificar explicitamente o protocolo de listener do balanceador de carga quando o Kubernetes Engine provisionar um balanceador de carga para um serviço Kubernetes do tipo LoadBalancer, adicione a seguinte anotação na seção de metadados do arquivo de manifesto:

service.beta.kubernetes.io/oci-load-balancer-backend-protocol: <value>

em que <value> corresponde ao protocolo que define o tipo de tráfego aceito pelo listener. Por exemplo, "HTTP". Protocolos válidos incluem "HTTP" e "TCP".

Por exemplo:


apiVersion: v1
kind: Service
metadata:
  name: my-nginx-svc
  labels:
    app: nginx
  annotations:
    oci.oraclecloud.com/load-balancer-type: "lb"
    service.beta.kubernetes.io/oci-load-balancer-backend-protocol: "HTTP"
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: nginx

Especificando Opções de Gerenciamento da Lista de Segurança ao Provisionar um Balanceador de Carga do OCI

Observação

Você poderá encontrar problemas de escalabilidade e outros problemas se usar o recurso de gerenciamento de lista de segurança do Kubernetes em implantações complexas e com ferramentas como o Terraform. Por esses motivos, a Oracle não recomenda o uso do recurso de gerenciamento de lista de segurança do Kubernetes em ambientes de produção.

Observe também que a capacidade de usar listas de segurança para gerenciar regras de segurança será descontinuada em uma release futura. Por esse motivo, a Oracle recomenda o uso de grupos de segurança de rede (NSGs) e a anotação oci.oraclecloud.com/security-rule-management-mode (consulte Especificando Opções de Gerenciamento de Regra de Segurança para Balanceadores de Carga e Balanceadores de Carga de Rede).

Você pode usar o recurso de gerenciamento de listas de segurança para configurar como as regras de lista de segurança são gerenciadas para um balanceador de carga do Oracle Cloud Infrastructure que o Kubernetes Engine provisiona para um serviço Kubernetes do tipo LoadBalancer. Esse recurso será útil se você for novo no Kubernetes ou para implantações básicas.

Para especificar como o recurso de gerenciamento de lista de segurança do Kubernetes gerencia listas de segurança quando o Kubernetes Engine provisiona um balanceador de carga para um serviço do Kubernetes do tipo LoadBalancer, adicione a seguinte anotação na seção de metadados do arquivo de manifesto:

service.beta.kubernetes.io/oci-load-balancer-security-list-management-mode: <value>

em que <value> é um dos seguintes:

  • "None": (recomendado) Nenhum gerenciamento da lista de segurança está ativado. Você precisa configurar uma regra de segurança que permita o tráfego de entrada para as portas apropriadas para intervalos de portas de nó, porta de saúde kube-proxy e intervalos de portas de verificação de integridade. Além disso, você precisa configurar regras de segurança para permitir o tráfego de entrada para balanceadores de carga (consulte Regras de Segurança para Balanceadores de Carga e Balanceadores de Carga de Rede).
  • "All": (padrão) Todas as regras obrigatórias da lista de segurança para os serviços do balanceador de carga são gerenciadas.
  • "Frontend": Somente as regras da lista de segurança para entrada nos serviços do balanceador de carga são gerenciadas. Você precisa configurar uma regra de segurança que permita o tráfego de entrada para as portas apropriadas para intervalos de portas de nó, porta de saúde kube-proxy e intervalos de portas de verificação de integridade.

A Oracle recomenda que você defina explicitamente service.beta.kubernetes.io/oci-load-balancer-security-list-management-mode como None.

Em clusters com nós gerenciados, se você não especificar explicitamente um modo de gerenciamento ou especificar um valor inválido, todas as regras da lista de segurança serão gerenciadas (equivalente a "All"). Esteja ciente de que, nesse caso, o Kubernetes Engine cria uma regra de segurança que permite o tráfego de entrada de 0.0.0.0/0 (ou dos intervalos de portas de origem especificados no arquivo de manifesto) para portas de listener. Em clusters com nós virtuais, o gerenciamento da lista de segurança nunca é ativado e você sempre precisa configurar manualmente as regras de segurança (equivalente a "None").

Observe que há limites para o número de regras de entrada e saída permitidas em uma lista de segurança (consulte Limites da Lista de Segurança). Se o número de regras de entrada ou saída exceder o limite e <value> for definido como "All" ou "Frontend", a criação ou atualização do balanceador de carga falhará.

Por exemplo:


apiVersion: v1
kind: Service
metadata:
  name: my-nginx-svc
  labels:
    app: nginx
  annotations:
    oci.oraclecloud.com/load-balancer-type: "lb"
    service.beta.kubernetes.io/oci-load-balancer-security-list-management-mode: "Frontend"
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: nginx