Exercice

  1. Prérequis
Cet exercice suppose que vous travaillez sur une VM multipass avec un cluster Kubernetes à 3 nœuds. Nous utiliserons NodePort pour accéder au contrôleur Gateway API.

Assurez-vous d’avoir installé le client helm sur votre machine hôte.

  1. Installer les CRD Gateway API et le contrôleur Envoy Gateway
Nous utiliserons Envoy Gateway, qui est l’une des implémentations Gateway API les plus matures
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.4.2 -n envoy-gateway-system --create-namespace

Attendez qu’Envoy Gateway soit prêt.

kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available

Créez la GatewayClass.

cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: eg
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
EOF
  1. Créer un pod nommé ghost basé sur l’image ghost:4 et l’exposer avec un service ClusterIP
l’application ghost écoute sur le port 2368
  1. Créer une ressource Gateway

  2. Créer une ressource HTTPRoute pour exposer le service ghost

  3. Vérifier que vous pouvez accéder à l’interface web de ghost

  4. Créer un certificat TLS auto-signé pour l’application ghost

  5. Mettre à jour la Gateway pour prendre en charge HTTPS avec TLS

  6. Vérifier l’accès HTTPS via Gateway API

  7. Nettoyer toutes les ressources

Documentation

https://kubernetes.io/docs/concepts/services-networking/gateway/

https://gateway-api.sigs.k8s.io/


Solution
  1. Installer les CRD Gateway API et le contrôleur Envoy Gateway

Commandes fournies dans les instructions.

  1. Créer un pod nommé ghost basé sur l’image ghost:4 et l’exposer avec un service ClusterIP
kubectl run ghost --image=ghost:4 --port 2368 --expose
  1. Créer une ressource Gateway
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: ghost
spec:
  gatewayClassName: eg
  listeners:
  - name: http
    port: 80
    protocol: HTTP
EOF

La Gateway créera un service LoadBalancer.

$ kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=ghost
NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
envoy-default-ghost-c7075eaa   LoadBalancer   10.96.231.63   <pending>     80:31283/TCP   2m38s

La commande suivante récupère la valeur du NodePort assigné au port HTTP (80).

HTTP_NODEPORT=$(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=ghost -o jsonpath='{.items[0].spec.ports[?(@.port==80)].nodePort}')
echo "Gateway HTTP accessible sur le NodePort : $HTTP_NODEPORT"

Comme nous utiliserons l’accès NodePort, nous devons patcher le Service afin de pouvoir joindre les Pods depuis n’importe quel nœud.

kubectl -n envoy-gateway-system patch $(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=ghost -o name) -p '{"spec":{"externalTrafficPolicy":"Cluster"}}'
  1. Créer une ressource HTTPRoute pour exposer le service ghost

Nous créons la HTTPRoute suivante (c’est l’équivalent Gateway API d’une ressource Ingress).

cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: ghost
spec:
  parentRefs:
  - name: ghost
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: ghost
      port: 2368
EOF
  1. Vérifier que vous pouvez accéder à l’interface web de ghost
# Récupérer l'IP du nœud
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')

# Récupérer le NodePort (s'il n'a pas déjà été défini à l'étape précédente)
HTTP_NODEPORT=$(kubectl -n envoy-gateway-system get svc -l gateway.envoyproxy.io/owning-gateway-name=ghost -o jsonpath='{.items[0].spec.ports[?(@.port==80)].nodePort}')

echo "Application Ghost accessible à l'adresse : http://$NODE_IP:$HTTP_NODEPORT"

# Tester l'accès HTTP
curl http://$NODE_IP:$HTTP_NODEPORT/

L’interface web de ghost devrait être accessible à l’adresse http://$NODE_IP:$HTTP_NODEPORT

  1. Créer un certificat TLS auto-signé pour l’application ghost
# Générer la clé privée et le certificat
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout ghost-tls.key \
  -out ghost-tls.crt \
  -subj "/CN=ghost.local"

# Créer le Secret Kubernetes
kubectl create secret tls ghost-tls-secret \
  --cert=ghost-tls.crt \
  --key=ghost-tls.key
  1. Mettre à jour la Gateway pour prendre en charge HTTPS avec TLS
# Mettre à jour la Gateway pour inclure un listener HTTPS
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: ghost
spec:
  gatewayClassName: eg
  listeners:
  - name: http
    port: 80
    protocol: HTTP
  - name: https
    port: 443
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
      - name: ghost-tls-secret
EOF

Comme nous utiliserons l’accès NodePort, nous devons patcher le Service afin de pouvoir joindre les Pods depuis n’importe quel nœud.

kubectl -n envoy-gateway-system patch $(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=ghost -o name) -p '{"spec":{"externalTrafficPolicy":"Cluster"}}'
  1. Vérifier l’accès HTTPS via Gateway API
# Récupérer le NodePort assigné à HTTPS (port 443)
HTTPS_NODEPORT=$(kubectl -n envoy-gateway-system get svc -l gateway.envoyproxy.io/owning-gateway-name=ghost -o jsonpath='{.items[0].spec.ports[?(@.port==443)].nodePort}')
echo "Gateway HTTPS accessible sur le NodePort : $HTTPS_NODEPORT"

# Tester l'accès HTTPS (avec le certificat auto-signé)
curl -k https://$NODE_IP:$HTTPS_NODEPORT/
  1. Nettoyer toutes les ressources et supprimer envoy gateway
kubectl delete httproute ghost
kubectl delete gateway ghost
kubectl delete secret ghost-tls-secret
kubectl delete pod ghost
kubectl delete service ghost
rm ghost-tls.key ghost-tls.crt
helm uninstall eg -n envoy-gateway-system