Configurer le pilotage des services


Cette page vous explique comment configurer le pilotage des services pour vos pods.

Pour comprendre le fonctionnement du pilotage des services, consultez la section Fonctionnement du pilotage des services.

Conditions requises

  • GKE version 1.30 ou ultérieure.

Limites

  • Une ServiceFunctionChain ne peut avoir qu'une seule fonction de service.
  • Nous recommandons un maximum de 100 nœuds et de 10 paires ServiceFunctionChain et TrafficSelector.
  • Le pilotage des services GKE n'est disponible qu'avec les nœuds exécutant l'image de nœud Container-Optimized OS.
  • Le pilotage des services GKE n'accepte que les adresses IP de sortie et de destination.
  • Le pilotage des services ne gère pas les conflits qui surviennent lorsque plusieurs sélecteurs de trafic avec des longueurs de préfixe identiques sont appliqués au même sujet. Pour éviter les conflits, concevez de manière proactive vos sélecteurs de trafic avec des plages d'adresses IP qui ne se chevauchent pas et des critères de sélection clairement définis.

Mettre en œuvre le pilotage des services

Le pilotage des services GKE vous permet de personnaliser et de contrôler le flux de trafic réseau au sein d'un cluster. Cette section explique comment mettre en œuvre l'orientation des services à l'aide d'un exemple de passerelle Web.

Imaginons que vous souhaitez créer une passerelle Web qui sécurise le trafic des appareils clients des utilisateurs finaux vers Internet. Un terminateur VPN achemine le trafic vers la passerelle gérée à l'aide d'un tunnel sécurisé. Le trafic de l'utilisateur final est redirigé vers le pare-feu, puis vers le proxy. Le proxy effectue la traduction d'adresse réseau source (SNAT) sur le trafic, masque l'adresse source d'origine, puis l'envoie sur Internet.

Pour mettre en œuvre le pilotage des services GKE, procédez comme suit :

  1. Créez un VPC avec une MTU de 8896.
  2. Créez un cluster GKE.
  3. Créez les pods et le service de la fonction de service.
  4. Créez le sous-réseau ServiceFunctionChain.
  5. Créez la ressource TrafficSelector faisant référence à ServiceFunctionChain.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

  • Activez l'API Google Kubernetes Engine.
  • Activer l'API Google Kubernetes Engine
  • Si vous souhaitez utiliser Google Cloud CLI pour cette tâche, installez puis initialisez gcloud CLI. Si vous avez déjà installé gcloud CLI, assurez-vous de disposer de la dernière version en exécutant la commande gcloud components update.

Préparer un VPC

Préparez un VPC. Le pilotage des services utilise l'encapsulation pour rediriger le trafic vers les fonctions de service appropriées. L'encapsulation implique l'ajout d'en-têtes supplémentaires à chaque paquet, ce qui augmente la taille des paquets. Le pilotage des services ne nécessite pas de configuration spéciale dans les VPC. Lors de la préparation du VPC, nous vous recommandons de prendre en compte la surcharge d'encapsulation lors du choix de la taille de MTU. Pour plus d'informations, consultez la section Réseau VPC avec une MTU spécifiée.

La commande suivante définit la taille de MTU dans votre VPC :

gcloud compute networks create VPC_NETWORK_NAME --mtu=8896

Remplacez VPC_NETWORK_NAME par le nom du réseau VPC contenant le sous-réseau.

Créer un cluster GKE

Pour activer les fonctionnalités avancées de routage réseau et de gestion des adresses IP nécessaires à la mise en œuvre du pilotage des services GKE, créez un cluster GKE dans lequel GKE Dataplane V2 est activé comme suit :

gcloud container clusters create CLUSTER_NAME \
    --network VPC_NAME \
    --release-channel RELEASE_CHANNEL \
    --cluster-version CLUSTER_VERSION \
    --enable-dataplane-v2 \
    --enable-ip-alias

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom du cluster.
  • VPC_NAME : nom du VPC auquel vous souhaitez associer le cluster.
  • RELEASE_CHANNEL : nom du canal de publication.
  • VERSION : version de GKE, qui doit être 1.30 ou ultérieure. Vous pouvez également utiliser l'option --release-channel pour sélectionner un canal de publication. La version disponible doit disposer de la version par défaut 1.30 ou ultérieure.

Créer des pods ServiceFunction

Pour établir votre chaîne de service, déployez le pod de terminateur VPN et les pods de fonction de service nécessaires dans votre cluster. Les pods encapsulent les applications conteneurisées qui exécutent vos fonctions réseau.

Le pod de terminateur VPN est souvent la première fonction de service de la chaîne, qui met fin au trafic entrant dans le cluster via le VPN. Il dirige ensuite les autres fonctions de service, telles que les pare-feu et l'équilibrage de charge, en vue d'un traitement ultérieur avant d'atteindre la destination finale.

L'exemple de fichier de configuration suivant définit les trois composants suivants essentiels pour la gestion du trafic réseau au sein d'un cluster :

  • Pod VPN : établit un point de terminaison de réseau privé virtuel (VPN) au sein de votre cluster, ce qui permet une communication sécurisée et chiffrée entre votre cluster et les réseaux externes.
  • Déploiement de pare-feu : déploie plusieurs instances dupliquées d'un pod de pare-feu, qui assurent la sécurité et l'équilibrage de charge.
  • DaemonSet proxy : déploie un pod de proxy sur chaque nœud de votre cluster, garantissant ainsi que le trafic réseau peut être traité localement avant d'être transféré à d'autres services tels que le pare-feu.

Enregistrez l'exemple de fichier manifeste suivant sous le nom service_function.yaml :

apiVersion: v1
kind: Pod
  name: vpn
  namespace: vpn
  labels:
    app: vpn
spec:
  containers:
  -   name: vpn
    image: openvpn
    ports:
    -   containerPort: 51820
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: firewall
  namespace: firewall
spec:
  replicas: 3
  selector:
    matchLabels:
      app: firewall
  template:
    metadata:
      labels:
        app: firewall
    spec:
      containers:
      -   name: firewall
        image: firewall
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: proxy
  namespace: proxy
spec:
  selector:
    matchLabels:
      app: proxy
  template:
    metadata:
      labels:
        app: proxy
    spec:
      containers:
      -   name: proxy
        image: proxy

Appliquez le fichier manifeste :

kubectl apply -f service_function.yaml

Créer ServiceFunctionChains

Pour définir une séquence de fonctions réseau permettant au trafic de traverser, créez un pipeline dans lequel chaque fonction (par exemple, pare-feu, proxy et équilibreur de charge) exécute sa tâche spécifique avant de transmettre le trafic à la suivante.

Enregistrez l'exemple de fichier manifeste suivant sous le nom ServiceFunctionChain.yaml :

apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
  name: firewall
spec:
  sessionAffinity:
    clientIpNoDestination:
      timeoutSeconds: 3600 # 1hr
  serviceFunctions:
  -   name: firewall
    namespace: firewall
    podSelector:
      matchLabels:
        app: firewall
---
apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
  name: proxy
spec:
  sessionAffinity:
    clientIpNoDestination: {}
  serviceFunctions:
  -   name: proxy
    namespace: proxy
    podSelector:
      matchLabels:
        app: proxy

Appliquez le fichier manifeste :

kubectl apply -f ServiceFunctionChain.yaml

Les fonctions de service sont définies de manière intégrée dans ServiceFunctionChain à l'aide du champ serviceFunctions. Une fonction de service est un sélecteur de point de terminaison.

Créer la ressource TrafficSelector

Pour définir où et quel trafic est sélectionné pour le pilotage des services, créez la ressource TrafficSelector qui référence la ServiceFunctionChains à appliquer au trafic choisi.

Enregistrez l'exemple de fichier manifeste suivant sous le nom TrafficSelector.yaml :

apiVersion: networking.gke.io/v1
kind: TrafficSelector
metadata:
  name: vpn-to-firewall
spec:
  serviceFunctionChain: firewall
  subject:
    pods:
      namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: vpn
      podSelector:
        matchLabels:
          app: vpn
  egress:
    to:
      ipBlock:
        cidr: 0.0.0.0/0
    ports:
    -   allPorts:
        protocol: UDP
    -   allPorts:
        protocol: TCP
---
apiVersion: networking.gke.io/v1
kind: TrafficSelector
metadata:
  name: firewall-to-proxy
spec:
  serviceFunctionChain: proxy
  subject:
    pods:
      namespaceSelector:
        kubernetes.io/metadata.name: firewall
      podSelector:
        app: firewall
  egress:
    to:
      ipBlock:
        cidr: 0.0.0.0/0
    ports:
    -   allPorts:
        protocol: UDP
    -   allPorts:
        protocol: TCP

Appliquez le fichier manifeste :

kubectl apply -f TrafficSelector.yaml

Résoudre les problèmes liés au pilotage des services

Cette section explique comment résoudre les problèmes liés au pilotage des services GKE.

Le trafic réseau ne circule pas

Vous pouvez effectuer les actions suivantes pour résoudre le problème :

Étape 1 : Vérifier que servicePathId est défini sur ServiceFunctionChain

Vérifiez que servicePathId est défini sur ServiceFunctionChain. Chaque objet ServiceFunctionChain se voit attribuer un servicePathId unique, comme illustré dans l'exemple suivant :

apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
  name: firewall
spec:
  serviceFunctions:
  - name: firewall
    namespace: firewall
    podSelector:
      matchLabels:
        app: firewal
status:
  servicePathId: 1

Étape 2 : Vérifier qu'un service Kubernetes est créé pour chaque fonction de service

Un service ClusterIP est créé automatiquement pour chaque fonction de service. Vous pouvez afficher la liste des services à l'aide de kubectl :

kubectl get svc -A -l networking.gke.io/managed-by=service-steering-controller.gke.io

Étape 3 : Vérifiez que pour chaque fonction de service, une entrée de mappage bpf est créée sur chaque nœud pour stocker l'adresse IP du service

Pour chaque fonction de service, une entrée de mappage bpf est créée sur chaque nœud pour stocker l'adresse IP du service.

Récupérez le nom du pod anetd :

kubectl get pods -n kube-system -o wide -l k8s-app=cilium

Enregistrez le nom du pod semblable à anetd.

Exécutez la commande suivante :

kubectl -n kube-system exec -it ANETD-POD-NAME -- cilium bpf sfcpath list

Remplacez ANETD-POD-NAME par le nom du pod anetd.

Le résultat ressemble à ce qui suit :

PATH     SERVICE FUNCTION ADDRESS
(1, 1)   10.4.10.124

Étape 4 : Vérifier que les entrées de mappage bpf sont créées dans le mappage sfcselect

Sur un nœud, si des pods sont sélectionnés par un TrafficSelector, les entrées de mappage bpf sont créées dans un mappage sfcselect. L'exemple suivant montre que le trafic TCP/UDP de n'importe quel port du point de terminaison (pod) 3783 vers l'adresse IP de destination 10.0.2.12 est dirigé vers une ServiceFunctionChain.

Exécutez la commande suivante :

kubectl -n kube-system exec -it ANETD-POD-NAME -- cilium bpf sfcselect list

Remplacez ANETD-POD-NAME par le nom réel du pod anetd de votre cluster.

Le résultat ressemble à ce qui suit :

SELECTOR                            PATH
3783, egress, 0/TCP, 10.0.2.12/32   /32 (1, 1)
3783, egress, 0/UDP, 10.0.2.12/32   /32 (1, 1)

Étape 5 : Utiliser tcpdump sur le port 7081 pour capturer et analyser le trafic réseau

Le pilotage des services prend en charge l'encapsulation Geneve sur le port UDP 7081. Vous pouvez utiliser tcpdump sur les nœuds pertinents pour analyser le flux de trafic et identifier l'origine du problème.

Étape suivante