Criar um serviço e uma entrada

Neste documento, mostramos como criar um objeto de Entrada do Kubernetes em um cluster de usuário, híbrido ou autônomo para o Google Distributed Cloud. Uma Entrada é associada a um ou mais Serviços, e cada um deles está associado a um conjunto de Pods.

Criar uma implantação

Siga estas etapas para criar uma implantação:

  1. Crie um manifesto de implantação:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-deployment
    spec:
      selector:
        matchLabels:
          greeting: hello
      replicas: 3
      template:
        metadata:
          labels:
            greeting: hello
        spec:
          containers:
          - name: hello-world
            image: "gcr.io/google-samples/hello-app:2.0"
            env:
            - name: "PORT"
              value: "50000"
          - name: hello-kubernetes
            image: "gcr.io/google-samples/node-hello:1.0"
            env:
            - name: "PORT"
              value: "8080"
    

    Para os fins deste exercício, estes são os pontos importantes que você precisa entender sobre o manifesto de implantação:

    • Cada pod que pertence à implantação tem o rótulo greeting: hello.

    • Cada pod tem dois contêineres.

    • Os campos env especificam que os contêineres hello-app detectam atividade na porta TCP 50000 e os contêineres node-hello detectam atividade na porta TCP 8080. Para hello-app, é possível ver o efeito da variável de ambiente PORT analisando o código-fonte.

  2. Copie o manifesto para um arquivo chamado hello-deployment.yaml.

  3. Crie a implantação:

    kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-deployment.yaml
    

    Substitua CLUSTER_KUBECONFIG pelo nome do arquivo kubeconfig do cluster.

Expor a implantação com um Serviço

Se quiser oferecer uma forma estável para os clientes enviarem solicitações aos pods da implantação, crie um Serviço:

  1. Crie um manifesto de serviço que exponha a implantação a clientes dentro do cluster:

    apiVersion: v1
    kind: Service
    metadata:
      name: hello-service
    spec:
      type: ClusterIP
      selector:
        greeting: hello
      ports:
      - name: world-port
        protocol: TCP
        port: 60000
        targetPort: 50000
      - name: kubernetes-port
        protocol: TCP
        port: 60001
        targetPort: 8080
    
  2. Copie o manifesto para um arquivo chamado hello-service.yaml.

  3. Criar o serviço:

    kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-service.yaml
    

    Substitua CLUSTER_KUBECONFIG pelo nome do arquivo kubeconfig do cluster.

  4. Veja o Serviço:

    kubectl --kubeconfig CLUSTER_KUBECONFIG get service hello-service --output yaml
    

    A saída mostra o valor de clusterIP que foi fornecido ao serviço. Por exemplo:

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        ...
    spec:
      clusterIP: 10.96.14.249
      clusterIPs:
      - 10.96.14.249
      ipFamilies:
      - IPv4
      ipFamilyPolicy: SingleStack
      ports:
      - name: world-port
        port: 60000
        protocol: TCP
        targetPort: 50000
      - name: kubernetes-port
        port: 60001
        protocol: TCP
        targetPort: 8080
      selector:
        greeting: hello
      sessionAffinity: None
      type: ClusterIP
    status:
      loadBalancer: {}
    

    Na saída anterior, o campo ports é uma matriz de objetos ServicePort: um chamado world-port e outro chamado kubernetes-port. Para mais informações sobre os campos de serviço, consulte ServiceSpec na documentação do Kubernetes.

    Veja como um cliente pode chamar o Serviço:

    • Usando world-port:um cliente que executa um dos nós do cluster envia uma solicitação para clusterIP em port (como 10.96.14.249:60000). O controlador de entrada encaminha a solicitação para um pod de membro em targetPort (como POD_IP_ADDRESS:50000, em que POD_IP_ADDRESS é o endereço IP de um pod de membro).

    • Usando kubernetes-port: um cliente que executa um dos nós do cluster envia uma solicitação para clusterIP em port (10.96.14.249:60001). O controlador de entrada encaminha a solicitação para um pod membro em targetPort (POD_IP_ADDRESS:8080).

Componentes da Entrada

Estes são alguns dos componentes do cluster relacionados à Entrada:

  • A implantação istio-ingress. Esse é o proxy de entrada. O proxy de entrada encaminha o tráfego para os Serviços internos de acordo com as regras especificadas em um objeto de Entrada.

  • O serviço istio-ingress. Este serviço expõe a implantação istio-ingress.

  • A implantação istiod. Este é o controlador de Entrada. O controlador de Entrada observa a criação de objetos de Entrada e configura o proxy de Entrada de acordo.

Todos esses componentes do Istio no cluster estão instalados no namespace gke-system. Esse namespace não entra em conflito com uma instalação completa do Istio/Cloud Service Mesh.

Criar uma Entrada

Siga estas etapas para criar um Entrada:

  1. Crie um manifesto do Entrada:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-ingress
    spec:
      rules:
      - http:
          paths:
          - path: /greet-the-world
            pathType: Exact
            backend:
              service:
                name: hello-service
                port:
                  number: 60000
          - path: /greet-kubernetes
            pathType: Exact
            backend:
              service:
                name: hello-service
                port:
                  number: 60001
    
  2. Copie o manifesto para um arquivo chamado my-ingress.yaml.

  3. Crie e Entrada:

    kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress.yaml
    

Ao criar um cluster de usuário, especifique um valor para loadbalancer.ingressVIP no arquivo de configuração do cluster. Esse endereço IP é configurado no balanceador de carga do cluster. Quando você cria uma Entrada, ela recebe esse mesmo VIP como o endereço IP externo dela.

Quando um cliente envia uma solicitação ao VIP de Entrada do cluster de usuário, a solicitação é roteada para o balanceador de carga. O balanceador de carga usa o Serviço istio-ingress para encaminhar a solicitação ao proxy de Entrada, que é executada no cluster de usuário. O proxy de entrada encaminha a solicitação para diferentes back-ends, dependendo do caminho no URL da solicitação.

Caminho /greet-the-world

No manifesto de Entrada, há uma regra que diz que o caminho /greet-the-world está associado a serviceName: hello-service e servicePort: 60000. Lembre-se de que 60000 é o valor da port na seção world-port do Serviço hello-service.

- name: world-port
    port: 60000
    protocol: TCP
    targetPort: 50000

O Serviço de Entrada encaminha a solicitação para clusterIP:50.000. Em seguida, a solicitação vai para um dos pods membros do serviço hello-service. O contêiner, nesse pod, que detecta a porta 50000 exibe uma mensagem Hello World!.

Caminho /greet-kubernetes

No manifesto de Entrada, há uma regra que diz que o caminho /greet-kubernetes está associado a serviceName: hello-service e servicePort: 60001. Lembre-se de que 60001 é o valor da port na seção kubernetes-port do Serviço hello-service.

- name: kubernetes-port
    port: 60001
    protocol: TCP
    targetPort: 8080

O Serviço de Entrada encaminha a solicitação para clusterIP: 8080. Em seguida, a solicitação vai para um dos pods membros do serviço hello-service. O contêiner nesse pod, que detecta a porta 8080, exibe uma mensagem Hello Kubernetes!.

Testar a Entrada

  1. Teste o Entrada usando o caminho /greet-the-world:

    curl CLUSTER_INGRESS_VIP/greet-the-world
    

    Substitua CLUSTER_INGRESS_VIP pelo endereço IP externo da Entrada.

    A saída mostra uma mensagem Hello, world!:

    Hello, world!
    Version: 2.0.0
    Hostname: ...
    
  2. Teste o Entrada usando o caminho /greet-kubernetes:

    curl CLUSTER_INGRESS_VIP/greet-kubernetes
    

    A saída mostra uma mensagem Hello, Kubernetes!:

    Hello Kubernetes!
    

Desativar a entrada em pacote

O recurso de entrada incluído no pacote com o Google Distributed Cloud só oferece suporte a recursos de entrada. É possível fazer a integração com o Istio ou o Cloud Service Mesh. Esses produtos oferecem outros benefícios de uma malha de serviço totalmente funcional, como Transport Layer Security mútua (mTLS), capacidade de gerenciar a autenticação entre serviços e observabilidade da carga de trabalho. Se você fizer a integração com o Istio ou o Cloud Service Mesh, recomendamos que desative o recurso de entrada no pacote.

É possível ativar ou desativar a Entrada agrupada com o campo spec.clusterNetwork.bundledIngress no arquivo de configuração do cluster. Este campo está disponível apenas nos clusters da versão 1.13.0 e mais recentes. O campo bundledIngress assume como padrão true e não está presente no arquivo de configuração do cluster gerado. Esse campo é mutável e pode ser alterado quando você cria ou atualiza um cluster da versão 1.13.0 ou mais recente.

  • Para desativar o recurso de entrada em pacote, adicione o campo bundledIngress à seção clusterNetwork do arquivo de configuração do cluster e defina o valor como "false", conforme mostrado no exemplo a seguir:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: cluster-hybrid-basic
    ---
    apiVersion: baremetal.cluster.gke.io/v1
    kind: Cluster
    metadata:
      name: hybrid-basic
      namespace: cluster-hybrid-basic
    spec:
      type: hybrid
      profile: default
      anthosBareMetalVersion: 1.13.0
      gkeConnect:
        projectID: project-fleet
      controlPlane:
        nodePoolSpec:
          nodes:
          - address: 10.200.0.2
      clusterNetwork:
        bundledIngress: false
        pods:
          cidrBlocks:
          - 192.168.0.0/16
        services:
          cidrBlocks:
          - 10.96.0.0/20
    ...
    

Configurar HTTPS para a Entrada

Se você quiser aceitar solicitações HTTPS dos clientes, o proxy de Entrada precisará ter um certificado para provar a identidade dele aos clientes. Esse proxy também precisa ter uma chave privada para concluir o handshake HTTPS.

O exemplo a seguir usa essas entidades:

  • Proxy de entrada: participa do handshake HTTPS e, em seguida, encaminha pacotes para os pods membros do serviço hello-service.

  • Domínio do serviço hello-service: altostrat.com na organização de exemplo

Siga estas etapas:

  1. Crie um certificado raiz e uma chave privada. Este exemplo usa uma autoridade certificadora raiz de root.ca.example.com na organização de exemplo da CA raiz.

    openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj \
        '/O=Root CA Example Inc./CN=root.ca.example.com' -keyout root-ca.key \
        -out root-ca.crt
    
  2. Crie uma solicitação de assinatura de certificado:

     openssl req -out server.csr -newkey rsa:2048 -nodes -keyout server.key -subj \
         "/CN=altostrat.com/O=Example Org"
    
  3. Crie um certificado de exibição para o proxy de entrada.

    openssl x509 -req -days 365 -CA root-ca.crt -CAkey root-ca.key -set_serial 0 \
        -in server.csr -out server.crt
    

    Você criou estes seguintes certificados e chaves:

    • root-ca.crt: certificado da CA raiz;
    • root-ca.key: chave privada da CA raiz;
    • server.crt: certificado de exibição do proxy de entrada;
    • server.key: chave privada do proxy de entrada;
  4. Crie um secret do Kubernetes que contenha o certificado e a chave de exibição.

    kubectl create secret tls example-server-creds --key=server.key --cert=server.crt \
        --namespace gke-system
    

    O secret resultante é denominado example-server-creds.

Criar uma implantação e um serviço

Se você criou uma implantação e um Serviço na parte HTTP deste guia, deixe-os no lugar. Se você não fez isso, crie-os agora seguindo as etapas descritas para HTTP.

Criar uma Entrada

Criar uma entrada para HTTPS é semelhante a criar uma entrada para HTTP, mas a especificação de entrada para HTTPS inclui uma seção tls que especifica o host e um Secret. O hosts na seção tls precisa corresponder explicitamente ao host na seção rules.

Se o serviço de back-end estiver em um namespace separado, crie um serviço do tipo ExternalName no mesmo namespace que o Entrada para rotear o tráfego para o serviço de back-end.

As etapas gerais para criar uma entrada para HTTPS ou HTTP são as mesmas, exceto pelo que você configura no arquivo de manifesto:

  1. Se você já tiver criado uma Entrada na parte HTTP deste documento, exclua-a antes de continuar.

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress my-ingress
    
  2. Para lidar com o tráfego do serviço que você criou antes, crie um novo manifesto de entrada que tenha uma seção tls:

    A configuração tls ativa o HTTPS entre os clientes e o proxy de entrada.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-ingress-2
    spec:
      tls:
      - hosts:
        - altostrat.com
        secretName: example-server-creds
      rules:
      - host: altostrat.com
        http:
          paths:
          - path: /greet-the-world
            pathType: Exact
            backend:
              service:
                name: hello-service
                port:
                  number: 60000
          - path: /greet-kubernetes
            pathType: Exact
            backend:
              service:
                name: hello-service
                port:
                  number: 60001
    
  3. Salve o manifesto em um arquivo chamado my-ingress-2.yaml e crie a Entrada:

    kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress-2.yaml
    
  4. Confirme se a entrada foi criada e está funcionando corretamente testando:

    • Teste o caminho /greet-the-world:

      curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP \
          https://altostrat.com/greet-the-world \
          --cacert root-ca.crt
      

      Saída:

      Hello, world!
      Version: 2.0.0
      Hostname: hello-deployment-5ff7f68854-wqzp7
      
    • Teste o caminho /greet-kubernetes:

      curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP \
          https://altostrat.com/greet-kubernetes --cacert root-ca.crt
      

      Saída:

      Hello Kubernetes!
      

Criar um serviço LoadBalancer

Um serviço do tipo LoadBalancer é outra maneira de expor cargas de trabalho fora do cluster. Para instruções e um exemplo de como criar um serviço do tipo LoadBalancer, consulte Criar um serviço do tipo LoadBalancer em Implantar um aplicativo.

Limpar

  1. Exclua o Entrada:

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress INGRESS_NAME
    

    Substitua INGRESS_NAME pelo nome da Entrada, como my-ingress ou my-ingress-2.

  2. Exclua o Serviço:

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete service hello-service
    
  3. Exclua a implantação:

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete deployment hello-deployment
    
  4. Exclua o serviço LoadBalancer:

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete service service-does-not-use-nodeports