Exposing Services in Kubernetes

Apoie o HackTricks e obtenha benefícios!

Existem diferentes maneiras de expor serviços no Kubernetes para que tanto os endpoints internos quanto os endpoints externos possam acessá-los. Essa configuração do Kubernetes é bastante crítica, pois o administrador pode dar acesso a atacantes a serviços aos quais eles não deveriam ter acesso.

Enumeração Automática

Antes de começar a enumerar as maneiras que o K8s oferece para expor serviços ao público, saiba que se você puder listar namespaces, serviços e ingressos, poderá encontrar tudo exposto ao público com:

kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do
    echo "Namespace: $ns"
    kubectl get service -n "$ns"
    kubectl get ingress -n "$ns"
    echo "=============================================="
    echo ""
    echo ""
done | grep -v "ClusterIP"
# Remova o último '| grep -v "ClusterIP"' para ver também o tipo ClusterIP

ClusterIP

Um serviço ClusterIP é o serviço padrão do Kubernetes. Ele fornece um serviço interno em seu cluster que outros aplicativos dentro do seu cluster podem acessar. Não há acesso externo.

No entanto, isso pode ser acessado usando o Proxy do Kubernetes:

kubectl proxy --port=8080

Agora, você pode navegar pela API do Kubernetes para acessar serviços usando este esquema:

http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/

Por exemplo, você pode usar a seguinte URL:

http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/

para acessar este serviço:

apiVersion: v1
kind: Service
metadata:  
  name: my-internal-service
spec:
  selector:    
    app: my-app
  type: ClusterIP
  ports:  
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP

Este método requer que você execute o kubectl como um usuário autenticado.

NodePort

NodePort abre uma porta específica em todos os Nodes (as VMs), e qualquer tráfego que é enviado para esta porta é encaminhado para o serviço. Esta é uma opção realmente ruim geralmente.

Um exemplo de especificação NodePort:

apiVersion: v1
kind: Service
metadata:  
  name: my-nodeport-service
spec:
  selector:    
    app: my-app
  type: NodePort
  ports:  
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30036
    protocol: TCP

Se você não especificar o nodePort no yaml (é a porta que será aberta), uma porta na faixa de 30000-32767 será usada.

LoadBalancer

Expõe o serviço externamente usando o balanceador de carga do provedor de nuvem. No GKE, isso iniciará um Balanceador de Carga de Rede que lhe dará um único endereço IP que encaminhará todo o tráfego para o seu serviço.

Você tem que pagar por um LoadBalancer por serviço exposto, o que pode ficar caro.

ExternalName

Serviços do tipo ExternalName mapeiam um serviço para um nome DNS, não para um seletor típico como my-service ou cassandra. Você especifica esses serviços com o parâmetro spec.externalName.

Esta definição de serviço, por exemplo, mapeia o serviço my-service no namespace prod para my.database.example.com:

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

Ao procurar o host my-service.prod.svc.cluster.local, o serviço DNS do cluster retorna um registro CNAME com o valor my.database.example.com. O acesso a my-service funciona da mesma forma que outros serviços, mas com a diferença crucial de que o redirecionamento acontece no nível DNS em vez de por meio de proxy ou encaminhamento.

IPs Externos

O tráfego que ingressa no cluster com o IP externo (como IP de destino), na porta do serviço, será roteado para um dos endpoints do serviço. Os externalIPs não são gerenciados pelo Kubernetes e são de responsabilidade do administrador do cluster.

Na especificação do serviço, externalIPs podem ser especificados juntamente com qualquer um dos ServiceTypes. No exemplo abaixo, "my-service" pode ser acessado por clientes em "80.11.12.10:80" (externalIP:port)

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9376
  externalIPs:
    - 80.11.12.10

Ingress

Ao contrário de todos os exemplos acima, Ingress NÃO é um tipo de serviço. Em vez disso, ele fica na frente de vários serviços e atua como um "roteador inteligente" ou ponto de entrada em seu cluster.

Você pode fazer muitas coisas diferentes com um Ingress, e existem muitos tipos de controladores de Ingress que têm capacidades diferentes.

O controlador de ingress padrão do GKE iniciará um Balanceador de Carga HTTP(S) para você. Isso permitirá que você faça roteamento baseado em caminho e subdomínio para serviços de backend. Por exemplo, você pode enviar tudo em foo.yourdomain.com para o serviço foo e tudo sob o caminho yourdomain.com/bar/ para o serviço bar.

O YAML para um objeto Ingress no GKE com um [Balanceador de C

Última actualización