Creazione di un Servizio e un Ingress

Questo documento mostra come creare un oggetto Kubernetes Ingress in un cluster utente, ibrido o autonomo per Google Distributed Cloud. Un Ingress è associato a uno o più servizi, ciascuno associato a un insieme di pod.

Creazione di un deployment

Per creare un deployment:

  1. Crea un manifest di deployment:

    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"
    

    Ai fini di questo esercizio, di seguito sono riportati i punti importanti da conoscere sul manifest di deployment:

    • Ogni pod che appartiene al deployment ha l'etichetta greeting: hello.

    • Ogni pod ha due container.

    • I campi env specificano che i container hello-app ascoltano sulla porta TCP 50000 e i container node-hello sulla porta TCP 8080. Per hello-app, puoi vedere l'effetto della variabile di ambiente PORT esaminando il codice sorgente.

  2. Copia il manifest in un file denominato hello-deployment.yaml.

  3. Crea il deployment:

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

    Sostituisci CLUSTER_KUBECONFIG con il nome del file kubeconfig del tuo cluster.

Esporre il deployment con un servizio

Per fornire ai client un modo stabile per inviare richieste ai pod del tuo deployment, crea un servizio:

  1. Crea un manifest del servizio che esponga il tuo deployment ai client all'interno del tuo 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. Copia il manifest in un file denominato hello-service.yaml.

  3. Crea il servizio:

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

    Sostituisci CLUSTER_KUBECONFIG con il nome del file kubeconfig per il tuo cluster.

  4. Visualizza il servizio:

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

    L'output mostra il valore di clusterIP assegnato al servizio. Ad esempio:

    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: {}
    

    Nell'output precedente, il campo ports è un array di oggetti ServicePort: uno denominato world-port e uno denominato kubernetes-port. Per ulteriori informazioni sui campi Service, consulta ServiceSpec nella documentazione di Kubernetes.

    Di seguito sono riportati i modi in cui un cliente può chiamare il servizio:

    • Utilizzo di world-port: un client in esecuzione su uno dei nodi del cluster invia una richiesta al clusterIP su port (ad esempio 10.96.14.249:60000). Il controller di ingresso inoltra la richiesta a un pod membro su targetPort (ad esempio POD_IP_ADDRESS:50000, dove POD_IP_ADDRESS è l'indirizzo IP di un pod membro).

    • Utilizzo di kubernetes-port: un client in esecuzione su uno dei nodi del cluster invia una richiesta al clusterIP su port (10.96.14.249:60001). Il controller di ingresso inoltra la richiesta a un pod membro su targetPort (POD_IP_ADDRESS:8080).

Componenti di Ingress

Di seguito sono riportati alcuni dei componenti del cluster relativi all'ingresso:

  • Il deployment istio-ingress. Si tratta del proxy di ingresso. Il proxy di ingresso inoltra il traffico ai servizi interni in base alle regole specificate in un oggetto Ingress.

  • Il Servizio istio-ingress. Questo servizio espone il deployment istio-ingress.

  • Il deployment istiod. Si tratta del controller di ingresso. Il controller di ingressi monitora la creazione degli oggetti Ingress e configura di conseguenza il proxy di ingresso.

Tutti questi componenti Istio in-cluster sono installati nello spazio dei nomi gke-system. Questo spazio dei nomi non è in conflitto con un'installazione completa di Istio/Cloud Service Mesh.

Crea un Ingress

Per creare un Ingress:

  1. Crea un manifest Ingress:

    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. Copia il manifest in un file denominato my-ingress.yaml.

  3. Crea l'elemento Ingress:

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

Quando crei un cluster utente, specifica un valore per loadbalancer.ingressVIP nel file di configurazione del cluster. Questo indirizzo IP è configurato sul bilanciatore del carico del cluster. Quando crei un Ingress, a quest'ultimo viene assegnato lo stesso VIP come indirizzo IP esterno.

Quando un client invia una richiesta all'indirizzo VIP di ingresso del cluster utente, la richiesta viene instradata al bilanciatore del carico. Il bilanciatore del carico utilizza il servizio istio-ingress per inoltrare la richiesta al proxy di ingresso, che viene eseguito nel cluster di utenti. Il proxy di ingresso inoltra la richiesta a diversi backend a seconda del percorso nell'URL della richiesta.

Il percorso /greet-the-world

Nel manifest di Ingress, puoi vedere una regola che indica che il percorso/greet-the-world è associato a serviceName: hello-service eservicePort: 60000. Ricorda che 60000 è il valore port nella sezione world-port del tuo servizio hello-service.

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

Il servizio di ingresso inoltra la richiesta a clusterIP:50000. La richiesta viene poi inviata a uno dei pod membri del servizio hello-service. Il container nel pod in ascolto sulla porta 50000 mostra un messaggio Hello World!.

Il percorso /greet-kubernetes

Nel manifest di Ingress, puoi vedere una regola che indica che il percorso/greet-kubernetes è associato a serviceName: hello-service eservicePort: 60001. Ricorda che 60001 è il valore port nella sezione kubernetes-port del tuo servizio hello-service.

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

Il servizio di ingresso inoltra la richiesta a clusterIP: 8080. La richiesta viene poi inviata a uno dei pod membri del servizio hello-service. Il container nel pod, in ascolto sulla porta 8080, mostra un messaggio Hello Kubernetes!.

Testa Ingress

  1. Testa l'Ingress utilizzando il percorso /greet-the-world:

    curl CLUSTER_INGRESS_VIP/greet-the-world
    

    Sostituisci CLUSTER_INGRESS_VIP con l'indirizzo IP esterno dell'Ingress.

    L'output mostra un messaggio Hello, world!:

    Hello, world!
    Version: 2.0.0
    Hostname: ...
    
  2. Testa l'Ingress utilizzando il percorso /greet-kubernetes:

    curl CLUSTER_INGRESS_VIP/greet-kubernetes
    

    L'output mostra un messaggio Hello, Kubernetes!:

    Hello Kubernetes!
    

Disattiva Ingress in bundle

La funzionalità di importazione inclusa con Google Distributed Cloud supporta solo le funzionalità di importazione. Puoi scegliere di eseguire l'integrazione con Istio o Cloud Service Mesh. Questi prodotti offrono vantaggi aggiuntivi di una rete mesh di servizi completamente funzionale, come Transport Layer Security (mTLS) mutuale, la possibilità di gestire l'autenticazione tra i servizi e l'osservabilità del carico di lavoro. Se esegui l'integrazione con Istio o Cloud Service Mesh, ti consigliamo di disattivare la funzionalità Ingress inclusa.

Puoi attivare o disattivare Ingress incluso con il spec.clusterNetwork.bundledIngress campo nel file di configurazione del cluster. Questo campo è disponibile solo per i cluster della versione 1.13.0 e successive. Il valore predefinito del campo bundledIngress è true e non è presente nel file di configurazione del cluster generato. Questo campo è mutabile e può essere modificato quando crei o aggiorni un cluster della versione 1.13.0 o successive.

  • Per disattivare la funzionalità Ingress inclusa, aggiungi il campo bundledIngress alla sezione clusterNetwork del file di configurazione del cluster e imposta il relativo valore su false, come mostrato nell'esempio seguente:

    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
    ...
    

Configurare HTTPS per Ingress

Se vuoi accettare richieste HTTPS dai tuoi client, il proxy di ingresso deve avere un certificato per dimostrare la propria identità ai client. Questo proxy deve anche avere una chiave privata per completare l'handshake HTTPS.

L'esempio seguente utilizza queste entità:

  • Proxy di ingresso: partecipa all'handshake HTTPS e poi inoltra i pacchetti ai pod membri del servizio hello-service.

  • Dominio per il servizio hello-service: altostrat.com nell'organizzazione di esempio

Segui questi passaggi:

  1. Crea un certificato radice e una chiave privata. Questo esempio utilizza un'autorità di certificazione radice di root.ca.example.com in Root CA Example Org.

    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. Crea una richiesta di firma del certificato:

     openssl req -out server.csr -newkey rsa:2048 -nodes -keyout server.key -subj \
         "/CN=altostrat.com/O=Example Org"
    
  3. Crea un certificato di pubblicazione per il proxy di ingresso.

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

    Ora hai creato i seguenti certificati e chiavi:

    • root-ca.crt: certificato per la CA radice
    • root-ca.key: chiave privata per la CA radice
    • server.crt: certificato di servizio per il proxy di ingresso
    • server.key: chiave privata per il proxy di ingresso
  4. Crea un secret Kubernetes che contenga il certificato e la chiave di servizio.

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

    Il secret risultante si chiama example-server-creds.

Crea un deployment e un servizio

Se hai creato un deployment e un servizio nella parte HTTP di questa guida, non modificarli. In caso contrario, creali ora seguendo i passaggi descritti per HTTP.

Crea un Ingress

La creazione di un Ingress per HTTPS è simile alla creazione di un Ingress per HTTP, ma la specifica di Ingress per HTTPS include una sezione tls che specifica l'host e un segreto. Il hosts nella sezione tls deve corrispondere esplicitamente al host nella sezione rules.

Se il servizio di backend si trova in uno spazio dei nomi separato, devi creare un servizio di tipo ExternalName nello stesso spazio dei nomi di Ingress per instradare il traffico al servizio di backend.

I passaggi generali per creare un Ingress per HTTPS o HTTP sono gli stessi, tranne per quanto riguarda la configurazione nel file manifest:

  1. Se in precedenza hai creato un Ingress nella parte HTTP di questo documento, eliminalo prima di procedere.

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress my-ingress
    
  2. Per gestire il traffico per il servizio che hai creato in precedenza, crea un nuovo manifest Ingress con una sezione tls:

    La configurazione di tls abilita HTTPS tra i client e il proxy di ingresso.

    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. Salva il manifest in un file denominato my-ingress-2.yaml e crea il Ingress:

    kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress-2.yaml
    
  4. Verifica che l'elemento Ingress sia stato creato e funzioni correttamente testando:

    • Testa il percorso /greet-the-world:

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

      Output:

      Hello, world!
      Version: 2.0.0
      Hostname: hello-deployment-5ff7f68854-wqzp7
      
    • Testa il percorso /greet-kubernetes:

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

      Output:

      Hello Kubernetes!
      

Crea un servizio LoadBalancer

Un servizio di tipo LoadBalancer è un altro modo per esporre i carichi di lavoro all'esterno del cluster. Per istruzioni e un esempio sulla creazione di un servizio di tipo LoadBalancer, consulta Creare un servizio di tipo LoadBalancer in Esegui il deployment di un'applicazione.

Pulizia

  1. Elimina l'Ingress:

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress INGRESS_NAME
    

    Sostituisci INGRESS_NAME con il nome dell'Ingress, ad esempio my-ingress o my-ingress-2.

  2. Eliminare il servizio:

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete service hello-service
    
  3. Elimina il deployment:

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete deployment hello-deployment
    
  4. Elimina il servizio LoadBalancer:

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