Como faço para fornecer acesso externo a vários serviços do Kubernetes no meu cluster Amazon EKS?

10 minuto de leitura
0

Quero fornecer acesso externo a vários serviços do Kubernetes no meu cluster do Amazon Elastic Kubernetes Service (Amazon EKS).

Breve descrição

Use o controlador de entrada NGINX ou o AWS Load Balancer Controller para Kubernetes para fornecer acesso externo a vários serviços Kubernetes em seu cluster Amazon EKS. O controlador de entrada NGINX é mantido principalmente pelo NGINX. Para verificar se há problemas com o controlador de entrada NGINX, consulte a lista de problemas no site do GitHub. O AWS Load Balancer Controller é mantido pela Amazon Web Services (AWS). Para verificar se há problemas com o AWS Load Balancer Controller, consulte a lista de problemas no site do GitHub.

Importante: o controlador de entrada e o IngressClass (do site do Kubernetes) não são iguais ao Ingress (do site do Kubernetes). O Ingress é um recurso do Kubernetes que expõe as rotas HTTP e HTTPS de fora do cluster aos serviços dentro do cluster. O controlador de entrada geralmente preenche a entrada com um balanceador de carga. Você não pode usar o Ingress sem um controlador de entrada. O IngressClass é usado para identificar qual controlador de entrada usar para atender à solicitação do objeto de entrada.

Pré-requisito: Instale o AWS Load Balancer Controller. A prática recomendada é usar o AWS Load Balancer Controller para criar e gerenciar um Network Load Balancer para objetos de serviço do tipo LoadBalancer no Amazon EKS.

Resolução

A resolução a seguir usa o controlador de entrada kubernetes/ingress-nginx no site do Kubernetes no GitHub. O outro controlador de entrada que está disponível para uso público é o nginxinc/kubernetes-ingress no site do NGINX no GitHub.

Implantar o controlador de entrada NGINX para Kubernetes

Você pode implantar o controlador de entrada NGINX para Kubernetes por meio do protocolo de controle de transmissão (TCP) ou da segurança da camada de transporte (TLS).

Observação: a resolução a seguir foi testada no Amazon EKS versão 1.22, no controlador de entrada NGINX versão 1.3.0 e no AWS Load Balancer Controller na versão 2.4.3.

(Opção 1) Controlador de entrada NGINX com TCP no Network Load Balancer

1.    Obtenha o arquivo YAML para implantar os seguintes objetos do Kubernetes: namespace, serviceaccounts, configmap, clusterroles, clusterrolebindings, roles, rolebindings, services, deployments, ingressclasses e validatingwebhookconfigurations.

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/deploy.yaml

2.    Edite o arquivo. Em seguida, na seção de objeto de serviço ingress-nginx-controller, substitua todas as anotações service.beta.kubernetes.io pelas seguintes:

service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"

3.    Aplique o manifesto:

kubectl apply -f deploy.yaml

Exemplo de saída:

namespace/ingress-nginx created
serviceaccount/ingress-nginx created
configmap/ingress-nginx-controller created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
service/ingress-nginx-controller-admission created
service/ingress-nginx-controller created
deployment.apps/ingress-nginx-controller created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
serviceaccount/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created

(Opção 2) Terminação TLS do controlador NGINX de entrada no Network Load Balancer

Por padrão, a solução anterior encerra o TLS no controlador de entrada NGINX. Você também pode configurar o serviço NGINX Ingress para encerrar o TLS no Network Load Balancer.

1.    Faça o download do modelo deploy.yaml:

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml

2.    Edite o arquivo. Em seguida, na seção de objeto de serviço ingress-nginx-controller, substitua todas as anotações service.beta.kubernetes.io pelas seguintes:

service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-west-2:XXXXXXXX:certificate/XXXXXX-XXXXXXX-XXXXXXX-XXXXXXXX
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"

Observação: certifique-se de incluir seu ARN para service.beta.kubernetes.io/aws-load-balancer-ssl-cert.

3.    Edite o arquivo e altere o CIDR da Amazon Virtual Private Cloud (Amazon VPC) para o cluster Kubernetes:

proxy-real-ip-cidr: XXX.XXX.XXX/XX

4.    Aplique o manifesto:

kubectl apply -f deploy.yaml

Observação: o manifesto anterior usa ExternalTrafficPolicy como local para preservar o endereço IP de origem (cliente). Usar essa configuração com um nome DHCP personalizado na Amazon VPC causa um problema. Para evitar que o problema ocorra, aplique o seguinte patch ao kube-proxy:

kubectl edit daemonset kube-proxy -n kube-system

5.    Edite o manifesto para incluir o seguinte trecho:

spec:
  template:
    spec:
      containers:
        - name: kube-proxy
          command:
            - kube-proxy
            - --hostname-override=$(NODE_NAME)
            - --v=2
            - --config=/var/lib/kube-proxy-config/config
           env:
            - name: NODE_NAME
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: spec.nodeName

Verifique os recursos implantados

Controlador AWS Load Balancer

Comando:

kubectl get all -n kube-system --selector app.kubernetes.io/instance=aws-load-balancer-controller

Exemplo de saída:

NAME                                                READY   STATUS    RESTARTS   AGE   IP               NODE                                           NOMINATED NODE   READINESS GATES
pod/aws-load-balancer-controller-85cd8965dc-ctkjt   1/1     Running   0          48m   192.168.37.36    ip-192-168-59-225.us-east-2.compute.internal   none             none
pod/aws-load-balancer-controller-85cd8965dc-wpwx9   1/1     Running   0          48m   192.168.53.110   ip-192-168-59-225.us-east-2.compute.internal   none>         none
NAME                                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/aws-load-balancer-webhook-service   ClusterIP   10.100.154.44   none          443/TCP   19h   app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller
NAME                                           READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS                   IMAGES                                                                                    SELECTOR
deployment.apps/aws-load-balancer-controller   2/2     2            2           19h   aws-load-balancer-controller 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-load-balancer-controller:v2.4.0   app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller
NAME                                                      DESIRED   CURRENT   READY   AGE   CONTAINERS                     IMAGES                                                                                    SELECTOR
replicaset.apps/aws-load-balancer-controller-85cd8965dc   2         2         2       19h   aws-load-balancer-controller   602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-load-balancer-controller:v2.4.0   app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller,pod-template-hash=85cd8965dc

Controlador de entrada NGINX

Comando:

kubectl get all -n ingress-nginx --selector app.kubernetes.io/instance=ingress-nginx

Exemplo de saída:

NAME                                           READY  STATUS   RESTARTS  AGE   IP               NODE                                           NOMINATED NODE  READINESS GATES
pod/ingress-nginx-controller-54d8b558d4-k4pdf  1/1    Running  0         56m   192.168.46.241   ip-192-168-59-225.us-east-2.compute.internal   none            none
NAME                                        TYPE           CLUSTER-IP      EXTERNAL-IP                                                                     PORT(S)                      AGE   SELECTOR
service/ingress-nginx-controller            LoadBalancer   10.100.99.129   ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80:32578/TCP,443:30724/TCP   15h   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
service/ingress-nginx-controller-admission  ClusterIP      10.100.190.61   none                                                                            443/TCP                      15h   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
NAME                                       READY   UP-TO-DATE   AVAILABLE    AGE   CONTAINERS   IMAGES                                                                                                               SELECTOR
deployment.apps/ingress-nginx-controller   1/1     1            1            15h   controller   k8s.gcr.io/ingress-nginx/controller:v1.1.1@sha256:0bc88eb15f9e7f84e8e56c14fa5735aaa488b840983f87bd79b1054190e660de   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
NAME                                                  DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES                                                                                                               SELECTOR
replicaset.apps/ingress-nginx-controller-54d8b558d4   1         1         1       15h   controller   k8s.gcr.io/ingress-nginx/controller:v1.1.1@sha256:0bc88eb15f9e7f84e8e56c14fa5735aaa488b840983f87bd79b1054190e660de   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx,pod-template-hash=54d8b558d4
NAME                                       COMPLETIONS   DURATION   AGE   CONTAINERS   IMAGES                                                                                                                         SELECTOR
job.batch/ingress-nginx-admission-create   1/1           2s         15h   create       k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660   controller-uid=242bdf56-de16-471d-a691-1ca1dbc10a41
job.batch/ingress-nginx-admission-patch    1/1           2s         15h   patch        k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660   controller-uid=a9e710d2-5001-4d40-a435-ddc8993bfe42

IngressClass

Comando:

kubectl get ingressclass

Exemplo de saída:

NAME    CONTROLLER             PARAMETERS                             AGE
alb     ingress.k8s.aws/alb    IngressClassParams.elbv2.k8s.aws/alb   19h
nginx   k8s.io/ingress-nginx   none                                   15h

Teste a configuração de implantação

**Observação:**A etapa a seguir é executar dois microsserviços. Os microsserviços são expostos internamente com o Kubernetes como o tipo padrão.

1.    Configure suas implantações ou microsserviços. Por exemplo, hostname-app e apache-app.

Exemplo de um arquivo hostname-app-svc.yaml para hostname-app:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hostname-app
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hostname-app
  template:
    metadata:
      labels:
        app: hostname-app
    spec:
      containers:
      - name: hostname-app
        image: k8s.gcr.io/serve_hostname:1.1

---
apiVersion: v1
kind: Service
metadata:
  name: hostname-svc
  namespace: default
spec:
  ports:
  - port: 80
    targetPort: 9376
    protocol: TCP
  selector:
    app: hostname-app

Exemplo de um arquivo apache-app-svc.yaml para apache-app:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apache-app
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: apache-app
  template:
    metadata:
      labels:
        app: apache-app
    spec:
      containers:
      - name: apache-app
        image: httpd:latest
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: apache-svc
  namespace: default
  labels:
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: apache-app

2.    Aplique suas configurações.

hostname-app:

kubectl apply -f hostname-app-svc.yaml

apache-app:

kubectl apply -f apache-app-svc.yaml

3.    Verifique se os recursos foram criados.

Implantações

Comando:

kubectl get deployment hostname-app apache-app -n default

Exemplo de saída:

NAME           READY   UP-TO-DATE   AVAILABLE   AGE
hostname-app   2/2     2            2           29m
apache-app     2/2     2            2           29m

Serviços

Comando:

kubectl get svc apache-svc hostname-svc -n default

Exemplo de saída:

NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
apache-svc     ClusterIP   10.100.73.51    none          80/TCP    29m
hostname-svc   ClusterIP   10.100.100.44   none          80/TCP    29m

Teste o controlador de entrada NGINX

1.    Acesse o URL DNS do balanceador de carga que você recuperou da linha de comando:

curl -I ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com

Exemplo de saída:

HTTP/1.1 404 Not Found
Date: Thu, 03 Mar 2022 14:03:11 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive

Observação: o servidor padrão retorna uma página 404 Not Found para todas as solicitações de domínio que não têm regras de entrada definidas. Com base nas regras definidas, o controlador de entrada não desvia o tráfego para o serviço de back-end especificado, a menos que a solicitação corresponda à configuração. Como o campo host está configurado para o objeto Ingress, você deve fornecer o cabeçalho Host da solicitação com o mesmo nome de host. Em um ambiente de teste, use um sinalizador curl para fornecer o cabeçalho Host. Em um ambiente de produção, mapeie o nome DNS do balanceador de carga para o nome do host em qualquer provedor de DNS, como o Amazon Route 53.

2.    Implemente a entrada para que ela interaja com seus serviços usando um único balanceador de carga fornecido pelo controlador de entrada NGINX.

Exemplo de micro-ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: micro-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: hostname.mydomain.com
      http:
        paths:
        - backend:
            service:
              name: hostname-svc
              port:
                number: 80
          path: /
          pathType: Prefix
  - host: apache.mydomain.com
    http:
      paths:
      - backend:
          service:
            name: apache-svc
            port:
              number: 80
        path: /
        pathType: Prefix

Observação: para mais informações, consulte Hospedagem virtual baseada em nomes (no site do Kubernetes).

3.    Verifique se o recurso foi criado.

Entrada

Comando:

kubectl get ingress -n default

Exemplo de saída:

NAME           CLASS   HOSTS                                       ADDRESS                                                                         PORTS   AGE
micro-ingress  none    hostname.mydomain.com,apache.mydomain.com   ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80      29m

4.    Adicione o cabeçalho Host à solicitação.

Primeiro domínio configurado:

curl -i -H "Host: hostname.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/

Exemplo de saída:

HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 18:50:38 GMT Content-Type: text/plain; charset=utf-8 Content-Length: 29 Connection: keep-alive

Segundo domínio configurado:

curl -i -H "Host: apache.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/

Exemplo de saída:

HTTP/1.1 200 OK
Date: Sat, 26 Mar 2022 18:51:00 GMT
Content-Type: text/html
Content-Length: 45
Connection: keep-alive
Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT
ETag: "2d-432a5e4a73a80"
Accept-Ranges: bytes

Depois de adicionar o cabeçalho Host, o controlador de entrada redireciona o tráfego para o serviço configurado no back-end, pois ele corresponde à configuração definida na entrada.

Para manter o mesmo nome de domínio, mas desviar o tráfego com base no caminho acessado, você deve adicionar o roteamento baseado em caminho com o Ingress.

Por exemplo:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginxd
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: mydomain.com
    http:
      paths:
      - backend:
          service:
            name: hostname-svc
            port:
              number: 80
        path: /hostname
        pathType: Prefix
  - host: mydomain.com
    http:
      paths:
      - backend:
          service:
            name: apache-svc
            port:
              number: 80
        path: /apache
        pathType: Prefix

Observação: se as solicitações tiverem mydomain.com como cabeçalho Host, o exemplo anterior retornará somente a resposta 200. As solicitações são acessadas nos caminhos /hostname ou /apache. Para todas as outras solicitações, 404 respostas são retornadas.

5.    Verifique se o roteamento baseado em caminho foi adicionado:

Comando:

kubectl get ingress -n default

Saída:

NAME            CLASS  HOSTS                                       ADDRESS                                                                         PORTS  AGE
micro-ingress   none   hostname.mydomain.com,apache.mydomain.com   ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80     164m
path-ingress    none   mydomain.com,mydomain.com                   ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80     120m

Comando:

curl -i -H "Host: mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/hostname

-ou-

curl -i -H "Host: mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/apache

Teste a entrada usando o controlador do AWS Load Balancer

1.    Inicie o Application Load Balancer usando o seguinte exemplo de manifesto de entrada:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: micro-ingress-alb
  namespace: default
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  rules:
  - host: alb.hostname.mydomain.com
    http:
      paths:
      - backend:
          service:
            name: hostname-svc
            port:
              number: 80
        path: /
        pathType: Prefix
   - host: alb.apache.mydomain.com
     http:
       - backend:
            service:
              name: apache-svc
              port:
                number: 80
         path: /
         pathType: Prefix

2.    Verifique se o Application Load Balancer é iniciado.

Comando:

kubectl get ingress -n default

Saída:

NAME               CLASS  HOSTS                                               ADDRESS                                                                         PORTS  AGE
micro-ingress      none   hostname.mydomain.com,apache.mydomain.com           ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80     164m
micro-ingress-alb  none   alb.hostname.mydomain.com,alb.apache.mydomain.com   k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com          80     18m
path-ingress       none   mydomain.com,mydomain.com                           ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80     120m

Solicitação com base no primeiro domínio configurado:

curl -i -H "Host: alb.hostname.mydomain.com" http://k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com

Exemplo de saída:

HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 20:46:02 GMT Content-Type: text/plain; charset=utf-8 Content-Length: 29 Connection: keep-alive

Solicitação com base no segundo domínio configurado:

curl -i -H "Host: alb.apache.mydomain.com" http://k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com

Exemplo de saída:

HTTP/1.1 200 OK
Date: Sat, 26 Mar 2022 20:46:14 GMT
Content-Type: text/html Content-Length: 45
Connection: keep-alive
Server: Apache/2.4.53 (Unix)
Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT
ETag: "2d-432a5e4a73a80"
Accept-Ranges: bytes

AWS OFICIAL
AWS OFICIALAtualizada há 2 anos