Nesta página, mostramos como configurar vários certificados SSL para recursos de Entrada em clusters do Google Kubernetes Engine (GKE).
Informações gerais
Se você quiser aceitar solicitações HTTPS dos seus clientes, o balanceador de carga de aplicativo precisará ter um certificado para provar a identidade dele aos clientes. Além disso, ele precisa ter uma chave privada para concluir o handshake HTTPS.
Quando o balanceador de carga aceita uma solicitação HTTPS de um cliente, o tráfego entre o cliente e o balanceador de carga é criptografado usando TLS. No entanto, o balanceador de carga encerra a criptografia TLS e encaminha a solicitação sem criptografia para o aplicativo. Ao configurar um balanceador de carga de aplicativo por meio do Entrada, é possível defini-lo para apresentar até dez certificados TLS ao cliente.
O balanceador de carga usa a indicação de nome do servidor (SNI, na sigla em inglês) para determinar qual certificado precisa ser apresentado ao cliente com base no nome de domínio no handshake de TLS. Se o cliente não usar a SNI ou se o cliente usar um nome de domínio que não corresponda ao nome comum (CN, na sigla em inglês) em um dos certificados, o balanceador de carga usará o primeiro certificado listado em Entrada.
O diagrama a seguir mostra o tráfego de envio do balanceador de carga para diferentes back-ends, dependendo do nome de domínio usado na solicitação:
É possível fornecer um balanceador de carga de aplicativo com certificados SSL usando os seguintes métodos:
- Certificados SSL gerenciados pelo Google. Consulte a página de certificados gerenciados para mais informações sobre como usá-los.
Certificado SSL do Google Cloud que você gerencia por conta própria. O certificado SSL usa um certificado pré-compartilhado que você envia para o projeto do Google Cloud.
Secrets do Kubernetes. O secret contém um certificado e uma chave que você mesmo cria. Adicione o nome do secret ao campo
tls
do manifesto da Entrada.
É possível usar mais de um método na mesma Entrada. Isso permite migrações sem tempo de inatividade entre os métodos.
Visão geral
Aqui está uma visão geral das etapas deste documento:
Crie uma implantação.
Crie um serviço.
Crie dois arquivos de certificado e dois arquivos de chaves ou dois objetos
ManagedCertificate
. Configure esses certificados no mesmo projeto e no mesmo namespace de onde o balanceador de carga é implantado.Crie um Ingress que use as chaves secretas ou os certificados pré-compartilhados. Quando você cria a Entrada, o GKE cria e configura um balanceador de carga de aplicativo.
Teste o balanceador de carga de aplicativo.
Antes de começar
Antes de começar, verifique se você realizou as tarefas a seguir:
- Ativar a API Google Kubernetes Engine. Ativar a API Google Kubernetes Engine
- Se você quiser usar a Google Cloud CLI para essa tarefa,
instale e, em seguida,
inicialize a
CLI gcloud. Se você instalou a CLI gcloud anteriormente, instale a versão
mais recente executando
gcloud components update
.
- Você precisa ter dois nomes de domínio. Os nomes do domínios não podem ter mais de 63 caracteres.
Limitações
- Os certificados gerenciados pelo Google são compatíveis apenas com o Ingress do GKE que usa o balanceador de carga de aplicativo externo. Os certificados gerenciados pelo Google não são compatíveis com controladores de entrada de terceiros.
- Para balanceadores de carga de aplicativo internos, é preciso desativar o HTTP no manifesto do Ingress. Ele não é necessário para o balanceador de carga externo.
- Não altere ou atualize manualmente a configuração do balanceador de carga de aplicativo. Isso significa que não é possível editar nenhum dos componentes do balanceador de carga, incluindo proxies de destino, mapas de URL e serviços de back-end. Todas as alterações feitas são substituídas pelo GKE.
Crie uma implantação
Salve o seguinte manifesto como
my-mc-deployment.yaml
:apiVersion: apps/v1 kind: Deployment metadata: name: my-mc-deployment spec: selector: matchLabels: app: products department: sales replicas: 3 template: metadata: labels: app: products department: sales spec: containers: - name: hello image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0" env: - name: "PORT" value: "50001" - name: hello-again image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0" env: - name: "PORT" value: "50002"
Esse manifesto descreve uma implantação com três pods. Cada pod tem dois contêineres. Um contêiner executa
hello-app:1.0
e escuta a porta TCP 50001. O outro contêiner executahello-app:2.0
e escuta a porta TCP 50002.Aplique o manifesto ao cluster:
kubectl apply -f my-mc-deployment.yaml
Crie um serviço.
Salve o seguinte manifesto como
my-mc-service.yaml
:apiVersion: v1 kind: Service metadata: name: my-mc-service spec: type: NodePort selector: app: products department: sales ports: - name: my-first-port protocol: TCP port: 60001 targetPort: 50001 - name: my-second-port protocol: TCP port: 60002 targetPort: 50002
Este manifesto descreve um Serviço com os seguintes campos:
selector
: especifica que qualquer pod que tenha os rótulosapp: products
edepartment: sales
é membro desse serviço.ports
: especifica que, quando um cliente envia uma solicitação ao serviço emmy-first-port
, o GKE a encaminha para um dos pods de membro na porta 50001. Quando um cliente envia uma solicitação ao serviço emmy-second-port
, o GKE encaminha a solicitação para um dos pods de membro na porta 50002.
Aplique o manifesto ao cluster:
kubectl apply -f my-mc-service.yaml
Criar certificados e chaves
Para fazer os exercícios desta página, você precisa de dois certificados, cada um com uma chave correspondente. Cada certificado precisa ter um Nome comum (CN, na sigla em inglês) que seja igual a um nome de domínio que você tem.
É possível criar esses certificados manualmente ou usar os gerenciados pelo Google.Se você já tiver dois arquivos de certificado com os valores apropriados para o nome comum, avance para a próxima seção.
Certificados gerenciados pelo usuário
Crie a primeira chave:
openssl genrsa -out test-ingress-1.key 2048
Crie a primeira solicitação de assinatura de certificado:
openssl req -new -key test-ingress-1.key -out test-ingress-1.csr \ -subj "/CN=FIRST_DOMAIN"
Substitua
FIRST_DOMAIN
por um nome de domínio de sua propriedade, comoexample.com
.Crie o primeiro certificado:
openssl x509 -req -days 365 -in test-ingress-1.csr -signkey test-ingress-1.key \ -out test-ingress-1.crt
Crie a segunda chave:
openssl genrsa -out test-ingress-2.key 2048
Crie a segunda solicitação de assinatura de certificado:
openssl req -new -key test-ingress-2.key -out test-ingress-2.csr \ -subj "/CN=SECOND_DOMAIN"
Substitua
SECOND_DOMAIN
por outro nome de domínio de sua propriedade, comoexamplepetstore.com
.Crie o segundo certificado:
openssl x509 -req -days 365 -in test-ingress-2.csr -signkey test-ingress-2.key \ -out test-ingress-2.crt
Para mais informações sobre certificados e chaves, consulte a Visão geral dos certificados SSL.
Agora você tem dois arquivos de certificado e dois arquivos de chaves.
As demais tarefas usam os seguintes marcadores para referir-se aos seus domínios, certificados e chaves:
FIRST_CERT_FILE
: o caminho para o primeiro arquivo de certificado.FIRST_KEY_FILE
: o caminho para o arquivo de chave que acompanha o primeiro certificado.FIRST_DOMAIN
: um nome de domínio que pertence a você.FIRST_SECRET_NAME
: o nome do secret que contém o primeiro certificado e chave.SECOND_CERT_FILE
: o caminho para o segundo arquivo de certificado.SECOND_KEY_FILE
: o caminho para o arquivo de chave que acompanha o segundo certificado.SECOND_DOMAIN
: um segundo nome de domínio que você tem.SECOND_SECRET_NAME
: o nome do secret que contém o segundo certificado e chave.
Certificados gerenciados pelo Google
Para criar certificados gerenciados pelo Google, adicione objetos
ManagedCertificate
ao namespace da Entrada. É possível
usar o seguinte modelo para definir certificados para seus domínios:
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: FIRST_CERT_NAME
spec:
domains:
- FIRST_DOMAIN
---
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: SECOND_CERT_NAME
spec:
domains:
- SECOND_DOMAIN
Substitua:
FIRST_CERT_NAME
: o nome do primeiro objetoManagedCertificate
.FIRST_DOMAIN
: o primeiro domínio que pertence a você.SECOND_CERT_NAME
: o nome do segundo objetoManagedCertificate
.SECOND_DOMAIN
: o segundo domínio que pertence a você.
Os nomes dos objetos ManagedCertificate
são diferentes dos nomes
dos certificados reais que eles criam. Você só precisará saber os nomes dos objetos ManagedCertificate
para usá-los na Entrada.
Especificar certificados para a Entrada
A próxima etapa é criar um objeto Entrada. No manifesto da Entrada, use um dos seguintes métodos para fornecer certificados ao balanceador de carga:
- Secrets
- Certificados pré-compartilhados
- Certificados gerenciados pelo Google
Secrets
Crie uma chave secreta que contenha seu primeiro certificado e chave:
kubectl create secret tls FIRST_SECRET_NAME \ --cert=FIRST_CERT_FILE \ --key=FIRST_KEY_FILE
Crie um secret que contenha seu segundo certificado e chave:
kubectl create secret tls SECOND_SECRET_NAME \ --cert=SECOND_CERT_FILE \ --key=SECOND_KEY_FILE
Criar uma Entrada
Salve o seguinte manifesto como
my-mc-ingress.yaml
:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-mc-ingress spec: tls: - secretName: FIRST_SECRET_NAME - secretName: SECOND_SECRET_NAME rules: - host: FIRST_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60001 - host: SECOND_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60002
Substitua
FIRST_DOMAIN
eSECOND_DOMAIN
pelos seus nomes de domínio, por exemplo,example.com
eexamplepetstore.com
.Aplique o manifesto ao cluster:
kubectl apply -f my-mc-ingress.yaml
Descreva o Ingress:
kubectl describe ingress my-mc-ingress
O resultado será assim:
Name: my-mc-ingress Address: 203.0.113.1 ... TLS: FIRST_SECRET_NAME terminates SECOND_SECRET_NAME terminates Rules: Host Path Backends ---- ---- -------- FIRST_DOMAIN my-mc-service:my-first-port (<none>) SECOND_DOMAIN my-mc-service:my-second-port (<none>) Annotations: ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 3m loadbalancer-controller default/my-mc-ingress Normal CREATE 2m loadbalancer-controller ip: 203.0.113.1
A resposta mostra que dois secrets estão associados ao Ingress. A saída também mostra o endereço IP externo do balanceador de carga: Se o endereço IP externo não estiver definido, aguarde alguns minutos e tente o comando novamente.
Certificados pré-compartilhados
Criar um certificado:
gcloud compute ssl-certificates create FIRST_CERT_NAME \ --certificate=FIRST_CERT_FILE \ --private-key=FIRST_KEY_FILE
Substitua:
FIRST_CERT_NAME
: o nome do primeiro certificado.FIRST_CERT_FILE
: o primeiro arquivo de certificado.FIRST_KEY_FILE
: o primeiro arquivo de chave.
Crie um segundo certificado:
gcloud compute ssl-certificates create SECOND_CERT_NAME \ --certificate=SECOND_CERT_FILE \ --private-key=SECOND_KEY_FILE
Substitua:
SECOND_CERT_NAME
: o nome do segundo certificado.SECOND_CERT_FILE
: o segundo arquivo de certificado.SECOND_KEY_FILE
: o segundo arquivo de chave.
Veja seus recursos de certificado:
gcloud compute ssl-certificates list
O resultado será assim:
NAME CREATION_TIMESTAMP FIRST_CERT_NAME 2018-11-03T12:08:47.751-07:00 SECOND_CERT_NAME 2018-11-03T12:09:25.359-07:00
Criar uma Entrada
Salve o seguinte manifesto como
my-psc-ingress.yaml
:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-psc-ingress annotations: ingress.gcp.kubernetes.io/pre-shared-cert: "FIRST_CERT_NAME,SECOND_CERT_NAME" spec: rules: - host: FIRST_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60001 - host: SECOND_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60002
Substitua
FIRST_DOMAIN
eSECOND_DOMAIN
pelos seus nomes de domínio.Esse manifesto descreve um Ingress que lista recursos de certificado pré-compartilhados em uma anotação.
Aplique o manifesto ao cluster:
kubectl apply -f my-psc-ingress.yaml
Descreva o Ingress:
kubectl describe ingress my-psc-ingress
O resultado será assim:
Name: my-psc-ingress Address: 203.0.113.2 ... Rules: Host Path Backends ---- ---- -------- FIRST_DOMAIN my-mc-service:my-first-port (<none>) SECOND_DOMAIN my-mc-service:my-second-port (<none>) Annotations: ... ingress.gcp.kubernetes.io/pre-shared-cert: FIRST_CERT_NAME,SECOND_CERT_NAME ... ingress.kubernetes.io/ssl-cert: FIRST_CERT_NAME,SECOND_CERT_NAME Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 2m loadbalancer-controller default/my-psc-ingress Normal CREATE 1m loadbalancer-controller ip: 203.0.113.2
A saída mostra que a Entrada está associada a certificados compartilhados anteriormente chamados
FIRST_CERT_NAME
eSECOND_CERT_NAME
. A saída também mostra o endereço IP externo do balanceador de carga. Se o endereço IP externo não estiver definido, aguarde alguns minutos e tente o comando novamente.
Certificados gerenciados pelo Google
Criar uma Entrada
Salve o seguinte manifesto como
my-gmc-ingress.yaml
:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-gmc-ingress annotations: networking.gke.io/managed-certificates: "FIRST_CERT_NAME,SECOND_CERT_NAME" spec: rules: - host: FIRST_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60001 - host: SECOND_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60002
Substitua
FIRST_DOMAIN
eSECOND_DOMAIN
pelos seus nomes de domínio.Esse manifesto descreve um Ingress que lista recursos de certificado pré-compartilhados em uma anotação.
Aplique o manifesto ao cluster:
kubectl apply -f my-gmc-ingress.yaml
Descreva o Ingress:
kubectl describe ingress my-gmc-ingress
O resultado será assim:
Name: my-gmc-ingress Address: 203.0.113.2 ... Rules: Host Path Backends ---- ---- -------- FIRST_DOMAIN my-mc-service:my-first-port (<none>) SECOND_DOMAIN my-mc-service:my-second-port (<none>) Annotations: ... ingress.gcp.kubernetes.io/pre-shared-cert: mcrt-a6e41ce4-2b39-4334-84ce-867ff543c424,mcrt-bbff4116-f014-4800-a43a-4095bffeb4f4 ... ingress.kubernetes.io/ssl-cert: mcrt-a6e41ce4-2b39-4334-84ce-867ff543c424,mcrt-bbff4116-f014-4800-a43a-4095bffeb4f4 networking.gke.io/managed-certificates: FIRST_CERT_NAME,SECOND_CERT_NAME Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 2m loadbalancer-controller default/my-gmc-ingress Normal CREATE 1m loadbalancer-controller ip: 203.0.113.2
A saída mostra que a Entrada está associada a certificados gerenciados chamados
FIRST_CERT_NAME
eSECOND_CERT_NAME
. O GKE preenche automaticamente as anotaçõesingress.gcp.kubernetes.io/pre-shared-cert
eingress.kubernetes.io/ssl-cert
com os certificados gerenciados pelo Google que você criou usando os objetosManagedCertificate
. A saída também mostra o endereço IP externo do balanceador de carga. Se o endereço IP externo não estiver definido, aguarde alguns minutos e tente o comando novamente.
Testar o balanceador de carga
Aguarde cerca de cinco minutos para que o GKE conclua a configuração do balanceador de carga.
Se você usou certificados gerenciados pelo Google, pode levar mais tempo para concluir a configuração, pois o sistema precisa provisionar os certificados e verificar a configuração de DNS para determinados domínios.Para testar o balanceador de carga, você precisa ter dois nomes de domínio, que precisam resolver o endereço IP externo do balanceador de carga de aplicativo externo.
Envie uma solicitação ao balanceador de carga usando seu primeiro nome de domínio:
curl -v https://FIRST_DOMAIN
Talvez seja necessário usar a opção
curl -k
para executar uma transferência SSL não segura. Assim,curl
aceitará certificados autoassinados.O resultado será assim:
... * Trying 203.0.113.1... ... * Connected to FIRST_DOMAIN (203.0.113.1) port 443 (#0) ... * TLSv1.2 (IN), TLS handshake, Certificate (11): ... * Server certificate: * subject: CN=FIRST_DOMAIN ... > Host: FIRST_DOMAIN.com ... Hello, world! Version: 1.0.0 ...
A saída mostra que o primeiro certificado foi usado no handshake de TLS.
Envie uma solicitação ao balanceador de carga usando o segundo nome de domínio:
curl -v https://SECOND_DOMAIN
O resultado será assim:
... * Trying 203.0.113.1... ... * Connected to SECOND_DOMAIN (203.0.113.1) port 443 (#0) ... * Server certificate: * subject: CN=SECOND_DOMAIN ... > Host: SECOND_DOMAIN ... Hello, world! Version: 2.0.0
A saída mostra que o segundo certificado foi usado no handshake de TLS.
O campo hosts de um objeto Entrada
No IngressSpec há um campo tls
que é uma matriz de objetos IngressTLS (links em inglês). Cada objeto IngressTLS
tem um campo hosts
e um campo SecretName
.
No GKE, o campo hosts
não é usado. O GKE lê o nome comum (CN, na sigla em inglês) do certificado no secret. Se o Nome comum corresponder ao nome de domínio em uma solicitação do cliente, o balanceador de carga apresentará o certificado correspondente ao cliente.
Qual certificado é apresentado?
O balanceador de carga escolhe um certificado de acordo com estas regras:
Se os Secrets e os certificados pré-compartilhados estiverem listados na Entrada, os certificados pré-compartilhados terão prioridade sobre os Secrets. Ou seja, os Secrets ainda serão incluídos, mas os certificados pré-compartilhados serão apresentados primeiro.
Se nenhum certificado tiver um nome comum que corresponda ao nome de domínio na solicitação do cliente, o balanceador de carga apresentará o certificado principal.
Para os secrets listados no bloco
tls
, o certificado principal está no primeiro secret da lista.Para certificados pré-compartilhados listados na anotação, o certificado principal é o primeiro certificado na lista.
Práticas recomendadas de rotação de certificados
Se você quiser alternar o conteúdo do secret ou do certificado pré-compartilhado, veja algumas práticas recomendadas:
- Crie um novo Secret ou certificado pré-compartilhado com um nome diferente que contenha os novos dados do certificado. Anexe esse recurso, com o atual, à Entrada usando as instruções fornecidas anteriormente. Quando as alterações forem finalizadas, será possível remover o certificado antigo da entrada.
- Se você não se importar de interromper o tráfego, poderá remover o recurso antigo da entrada, provisionar um novo recurso com o mesmo nome, mas com conteúdo diferente, e anexá-lo novamente à Entrada.
Solução de problemas
A especificação de chaves secretas inválidas ou inexistentes resulta em um erro de evento do Kubernetes. Veja os eventos do Kubernetes para verificar se há uma Entrada como esta:
kubectl describe ingress
O resultado será assim:
Name: my-ingress
Namespace: default
Address: 203.0.113.3
Default backend: hello-server:8080 (10.8.0.3:8080)
TLS:
my-faulty-Secret terminates
Rules:
Host Path Backends
---- ---- --------
* * my-service:443 (10.8.0.3:443)
Events:
Error during sync: cannot get certs for Ingress default/my-ingress:
Secret "my-faulty-ingress" has no 'tls.crt'
A seguir
- Leia a visão geral da rede do GKE.
- Se você tiver um aplicativo em execução em vários clusters do GKE em regiões diferentes, configure uma Entrada em vários clusters para rotear o tráfego para um cluster na região mais próxima do usuário.