Créer un service et un objet Ingress

Ce document explique comment créer un objet Ingress Kubernetes dans un cluster utilisateur, hybride ou autonome pour Google Distributed Cloud. Un objet Ingress est associé à un ou plusieurs objets Service, chacun étant associé à un ensemble de pods.

Créer un déploiement

Pour créer un déploiement, procédez comme suit:

  1. Créez un fichier manifeste de déploiement:

    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"
    

    Pour les besoins de cet exercice, voici les points importants à comprendre concernant le fichier manifeste de déploiement:

    • Chaque pod appartenant au déploiement possède l'étiquette greeting: hello.

    • Chaque pod possède deux conteneurs.

    • Les champs env spécifient que les conteneurs hello-app écoutent sur le port TCP 50000 et que les conteneurs node-hello écoutent sur le port TCP 8080. Pour hello-app, vous pouvez examiner l'effet de la variable d'environnement PORT en consultant le code source.

  2. Copiez le fichier manifeste dans un fichier nommé hello-deployment.yaml.

  3. Créez le déploiement :

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

    Remplacez CLUSTER_KUBECONFIG par le nom du fichier kubeconfig de votre cluster.

Exposer votre déploiement avec un service

Pour fournir aux clients un moyen stable d'envoyer des requêtes aux pods de votre déploiement, créez un service:

  1. Créez un fichier manifeste de service qui expose votre déploiement aux clients de votre 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. Copiez le fichier manifeste dans un fichier nommé hello-service.yaml.

  3. Créez le service en exécutant la commande suivante :

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

    Remplacez CLUSTER_KUBECONFIG par le nom du fichier kubeconfig de votre cluster.

  4. Consultez le Service :

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

    La sortie affiche la valeur clusterIP qui a été attribuée au service. Exemple :

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

    Dans la sortie précédente, le champ ports est un tableau d'objets ServicePort : l'un est nommé world-port et l'autre kubernetes-port. Pour en savoir plus sur les champs de service, consultez la section ServiceSpec dans la documentation Kubernetes.

    Voici comment un client peut appeler le service :

    • À l'aide de world-port:un client s'exécutant sur l'un des nœuds du cluster envoie une requête au clusterIP sur port (par exemple, 10.96.14.249:60000). Le contrôleur d'entrée transfère la requête à un pod membre sur targetPort (par exemple, POD_IP_ADDRESS:50000, où POD_IP_ADDRESS est l'adresse IP d'un pod membre).

    • À l'aide de kubernetes-port: un client s'exécutant sur l'un des nœuds de cluster envoie une requête au clusterIP sur port (10.96.14.249:60001). Le contrôleur d'entrée transmet la requête à un pod membre sur targetPort (POD_IP_ADDRESS:8080).

Composants d'Ingress

Voici quelques-uns des composants de cluster liés à l'entrée :

  • Le déploiement istio-ingress. Il s'agit du proxy d'entrée. Le proxy d'entrée transfère le trafic vers les services internes conformément aux règles spécifiées dans un objet Ingress.

  • Le service istio-ingress. Ce service expose le déploiement istio-ingress.

  • Le déploiement istiod. Il s'agit du contrôleur d'entrée. Le contrôleur d'entrée surveille la création des objets Ingress et configure le proxy d'entrée en conséquence.

Tous ces composants Istio internes au cluster sont installés dans l'espace de noms gke-system. Cet espace de noms n'entre pas en conflit avec une installation Istio/Cloud Service Mesh complète.

Créer un objet Ingress

Pour créer un Ingress, procédez comme suit:

  1. Créez un fichier manifeste 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. Copiez le fichier manifeste dans un fichier nommé my-ingress.yaml.

  3. Créez l'entrée :

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

Lorsque vous créez un cluster d'utilisateur, vous spécifiez une valeur pour loadbalancer.ingressVIP dans le fichier de configuration du cluster. Cette adresse IP est configurée sur l'équilibreur de charge du cluster. Lorsque vous créez une entrée, celle-ci reçoit la même adresse IP virtuelle que son adresse IP externe.

Lorsqu'un client envoie une requête à votre adresse IP virtuelle d'entrée de cluster d'utilisateur, la requête est acheminée vers votre équilibreur de charge. L'équilibreur de charge utilise le service istio-ingress pour transférer la requête au proxy d'entrée qui s'exécute dans votre cluster d'utilisateur. Le proxy d'entrée transfère la requête à différents backends en fonction du chemin d'accès dans l'URL de la requête.

Chemin d'accès /greet-the-world

Dans votre fichier manifeste d'entrée, vous pouvez trouver une règle indiquant que le chemin d'accès /greet-the-world est associé à serviceName: hello-service et servicePort: 60000. Rappelez-vous que 60000 est la valeur port dans la section world-port de votre service hello-service.

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

Le service d'entrée transfère la requête à l'adresse clusterIP:50000. La requête est ensuite transmise à l'un des pods membres du service hello-service. Le conteneur qui écoute sur le port 50000 dans ce pod affiche le message Hello World!.

Chemin d'accès /greet-kubernetes

Dans votre fichier manifeste d'entrée, vous pouvez trouver une règle indiquant que le chemin d'accès /greet-kubernetes est associé à serviceName: hello-service et servicePort: 60001. Rappelez-vous que 60001 est la valeur port dans le champ kubernetes-port de votre service hello-service.

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

Le service d'entrée transfère la requête à l'adresse clusterIP: 8080. La requête est ensuite transmise à l'un des pods membres du service hello-service. Le conteneur de ce pod, qui écoute sur le port 8080, affiche un message Hello Kubernetes!.

Tester l'objet Ingress

  1. Testez l'entrée à l'aide du chemin d'accès /greet-the-world :

    curl CLUSTER_INGRESS_VIP/greet-the-world
    

    Remplacez CLUSTER_INGRESS_VIP par l'adresse IP externe de l'objet Ingress.

    Le résultat affiche un message Hello, world! :

    Hello, world!
    Version: 2.0.0
    Hostname: ...
    
  2. Testez l'entrée à l'aide du chemin d'accès /greet-kubernetes :

    curl CLUSTER_INGRESS_VIP/greet-kubernetes
    

    Le résultat affiche un message Hello, Kubernetes! :

    Hello Kubernetes!
    

Désactiver Ingress groupée

La fonctionnalité d'entrée fournie avec Google Distributed Cloud n'est compatible qu'avec les fonctionnalités d'entrée. Vous pouvez choisir d'intégrer Istio ou Cloud Service Mesh. Ces produits offrent les avantages supplémentaires d'un maillage de services entièrement fonctionnel, tels que la sécurité de la couche transport mutuelle (mTLS), la possibilité de gérer l'authentification entre les services et l'observabilité des charges de travail. Si vous effectuez une intégration avec Istio ou Cloud Service Mesh, nous vous recommandons de désactiver la fonctionnalité Ingress groupée.

Vous pouvez activer ou désactiver Ingress groupé avec le champ spec.clusterNetwork.bundledIngress dans le fichier de configuration de votre cluster. Ce champ n'est disponible que pour les clusters de la version 1.13.0 et ultérieures. Le champ bundledIngress est défini par défaut sur true et n'est pas présent dans le fichier de configuration du cluster généré. Ce champ est modifiable et peut être modifié lorsque vous créez ou mettez à jour un cluster de version 1.13.0 ou ultérieure.

  • Pour désactiver la fonctionnalité Ingress groupée, ajoutez le champ bundledIngress à la section clusterNetwork de votre fichier de configuration de cluster et définissez sa valeur sur "false", comme indiqué dans l'exemple suivant:

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

Configurer HTTPS pour l'objet Ingress

Si vous souhaitez accepter les requêtes HTTPS de vos clients, le proxy d'entrée doit disposer d'un certificat pour justifier son identité auprès de vos clients. Ce proxy doit également disposer d'une clé privée pour effectuer le handshake HTTPS.

L'exemple suivant utilise ces entités :

  • Proxy d'Ingress: participe au handshake HTTPS, puis transfère les paquets aux pods membres du service hello-service.

  • Domaine du service hello-service : altostrat.com dans l'exemple d'organisation

Procédez comme suit :

  1. Créez un certificat racine et une clé privée. Cet exemple utilise une autorité de certification racine root.ca.example.com dans l'exemple d'organisation de l'autorité de certification racine.

    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. Créez une requête de signature de certificat :

     openssl req -out server.csr -newkey rsa:2048 -nodes -keyout server.key -subj \
         "/CN=altostrat.com/O=Example Org"
    
  3. Créez un certificat de diffusion pour le proxy d'entrée.

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

    Vous avez à présent créé les certificats et les clés suivants :

    • root-ca.crt : certificat de l'autorité de certification racine
    • root-ca.key : clé privée de l'autorité de certification racine
    • server.crt : certificat de diffusion pour le proxy d'entrée
    • server.key : clé privée du proxy d'entrée
  4. Créez un secret Kubernetes contenant le certificat de diffusion et la clé.

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

    Le secret obtenu est nommé example-server-creds.

Créer un déploiement et un service

Si vous avez créé un déploiement et un service dans la partie HTTP de ce guide, conservez-les. Si ce n'est pas le cas, créez-les maintenant en suivant les étapes décrites pour HTTP.

Créer un objet Ingress

La création d'un Ingress pour HTTPS est semblable à la création d'un Ingress pour HTTP, mais la spécification Ingress pour HTTPS inclut une section tls qui spécifie l'hôte et un secret. L'hosts de la section tls doit correspondre explicitement à l'host de la section rules.

Si votre service backend se trouve dans un espace de noms distinct, vous devez créer un service de type ExternalName dans le même espace de noms que l'objet Ingress pour acheminer le trafic vers le service backend.

Les étapes générales de création d'un Ingress pour HTTPS ou HTTP sont les mêmes, à l'exception de ce que vous configurez dans le fichier manifeste:

  1. Si vous avez déjà créé un Ingress dans la partie HTTP de ce document, supprimez-le avant de continuer.

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress my-ingress
    
  2. Pour gérer le trafic du service que vous avez créé précédemment, créez un fichier manifeste Ingress doté d'une section tls:

    La configuration tls active le protocole HTTPS entre les clients et le proxy d'entrée.

    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. Enregistrez le fichier manifeste dans un fichier nommé my-ingress-2.yaml et créez l'objet Ingress:

    kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress-2.yaml
    
  4. Vérifiez que l&#Ingress a été créée et qu'elle fonctionne correctement en effectuant les tests suivants:

    • Testez le chemin /greet-the-world :

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

      Sortie :

      Hello, world!
      Version: 2.0.0
      Hostname: hello-deployment-5ff7f68854-wqzp7
      
    • Testez le chemin /greet-kubernetes :

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

      Sortie :

      Hello Kubernetes!
      

Créer un service LoadBalancer

Un service de type LoadBalancer est un autre moyen d'exposer vos charges de travail en dehors de votre cluster. Pour obtenir des instructions et un exemple de création d'un service de type LoadBalancer, consultez la section Créer un service de type LoadBalancer dans "Déployer une application".

Nettoyer

  1. Supprimez l'entrée :

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress INGRESS_NAME
    

    Remplacez INGRESS_NAME par le nom de l'objet Ingress, par exemple my-ingress ou my-ingress-2.

  2. Supprimez le service :

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete service hello-service
    
  3. Supprimez le déploiement :

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete deployment hello-deployment
    
  4. Supprimez votre service LoadBalancer:

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