web-dev-qa-db-fra.com

Sessions collantes sur le cluster Kubernetes

Actuellement, j'essaie de créer un cluster Kubernetes sur Google Cloud avec deux équilibreurs de charge : un pour le backend (dans Spring boot) et un autre pour le frontend ( en angulaire), où chaque service (équilibreur de charge) communique avec 2 répliques (pods). Pour y parvenir, j'ai créé l'entrée suivante:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: sample-ingress
spec:
  rules:
    - http:
        paths:
          - path: /rest/v1/*
            backend:
              serviceName: sample-backend
              servicePort: 8082
          - path: /*
            backend:
              serviceName: sample-frontend
              servicePort: 80

L'entrée ci-dessus peut faire communiquer l'application frontale avec l'API REST mise à disposition par l'application backend. Cependant, je dois créer des sessions persistantes , de sorte que chaque utilisateur communique avec le même POD en raison du mécanisme d'authentification fourni par le backend. Pour clarifier, si un utilisateur s'authentifie dans le POD # 1, le cookie ne sera pas reconnu par le POD # 2.

Pour dépasser ce problème, j'ai lu que le Nginx-ingress parvient à faire face à cette situation et j'ai installé à travers les étapes disponibles ici: https : //kubernetes.github.io/ingress-nginx/deploy/ en utilisant Helm.

Vous pouvez trouver ci-dessous le schéma de l'architecture que j'essaie de construire:

enter image description here

Avec les services suivants (je vais simplement coller l'un des services, l'autre est similaire):

apiVersion: v1
kind: Service
metadata:
  name: sample-backend
spec:
  selector:
    app: sample
    tier: backend
  ports:
    - protocol: TCP
      port: 8082
      targetPort: 8082
  type: LoadBalancer

Et j'ai déclaré l'entrée suivante:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: sample-nginx-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/affinity: cookie
    nginx.ingress.kubernetes.io/affinity-mode: persistent
    nginx.ingress.kubernetes.io/session-cookie-hash: sha1
    nginx.ingress.kubernetes.io/session-cookie-name: sample-cookie
spec:
  rules:
    - http:
        paths:
          - path: /rest/v1/*
            backend:
              serviceName: sample-backend
              servicePort: 8082
          - path: /*
            backend:
              serviceName: sample-frontend
              servicePort: 80

Après cela, je lance kubectl apply -f sample-nginx-ingress.yaml pour appliquer l'entrée, elle est créée et son état est OK. Cependant, lorsque j'accède à l'URL qui apparaît dans la colonne "Endpoints", le navigateur ne peut pas se connecter à l'URL. Suis-je en train de faire quelque chose de mal?

Modifier 1

** Service mis à jour et configurations d'entrée **

Après un peu d'aide, j'ai réussi à accéder aux services via Ingress Nginx. Ci-dessus, vous avez les configurations:

Nginx Ingress

Les chemins ne doivent pas contenir le "", contrairement à l'entrée par défaut de Kubernetes qui est obligatoire d'avoir le "" pour router les chemins que je veux.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: sample-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "sample-cookie"
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"

spec:
  rules:
    - http:
        paths:
          - path: /rest/v1/
            backend:
              serviceName: sample-backend
              servicePort: 8082
          - path: /
            backend:
              serviceName: sample-frontend
              servicePort: 80

Prestations de service

De plus, les services ne doivent pas être de type "LoadBalancer" mais " ClusterIP " comme ci-dessous:

apiVersion: v1
kind: Service
metadata:
  name: sample-backend
spec:
  selector:
    app: sample
    tier: backend
  ports:
    - protocol: TCP
      port: 8082
      targetPort: 8082
  type: ClusterIP

Cependant, je ne peux toujours pas réaliser de sessions persistantes dans mon cluster Kubernetes, une fois que j'obtiens toujours 403 et même le nom du cookie n'est pas remplacé, donc je suppose que les annotations ne fonctionnent pas comme prévu.

3
migueltaoliveira

J'ai examiné cette question et j'ai trouvé une solution à votre problème.

Pour obtenir une session persistante pour les deux chemins, vous aurez besoin de deux définitions de l'entrée.

J'ai créé un exemple de configuration pour vous montrer l'ensemble du processus:

Étapes à reproduire:

  • Appliquer les définitions d'entrée
  • Créer des déploiements
  • Créer des services
  • Créer des entrées
  • Tester

Je suppose que le cluster est provisionné et fonctionne correctement.

Appliquer les définitions d'entrée

Suivez ceci lien Ingress pour savoir s'il existe des prérequis nécessaires avant d'installer le contrôleur Ingress sur votre infrastructure.

Appliquer la commande ci-dessous pour fournir toutes les conditions préalables obligatoires:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

Exécutez la commande ci-dessous pour appliquer une configuration générique pour créer un service:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml

Créer des déploiements

Vous trouverez ci-dessous 2 exemples de déploiements pour répondre au trafic Ingress sur des services spécifiques:

bonjour.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
spec:
  selector:
    matchLabels:
      app: hello
      version: 1.0.0
  replicas: 5
  template:
    metadata:
      labels:
        app: hello
        version: 1.0.0
    spec:
      containers:
      - name: hello
        image: "gcr.io/google-samples/hello-app:1.0"
        env:
        - name: "PORT"
          value: "50001"

Appliquez cette première configuration de déploiement en appelant la commande:

$ kubectl apply -f hello.yaml

goodbye.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: goodbye
spec:
  selector:
    matchLabels:
      app: goodbye
      version: 2.0.0
  replicas: 5
  template:
    metadata:
      labels:
        app: goodbye
        version: 2.0.0
    spec:
      containers:
      - name: goodbye 
        image: "gcr.io/google-samples/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50001"

Appliquez cette deuxième configuration de déploiement en appelant la commande:

$ kubectl apply -f goodbye.yaml

Vérifiez si les déploiements ont correctement configuré les modules:

$ kubectl get deployments

Cela devrait montrer quelque chose comme ça:

NAME      READY   UP-TO-DATE   AVAILABLE   AGE
goodbye   5/5     5            5           2m19s
hello     5/5     5            5           4m57s

Créer des services

Pour vous connecter à des modules créés précédemment, vous devrez créer des services. Chaque service sera affecté à un déploiement. Voici deux services pour y parvenir:

hello-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  type: NodePort
  selector:
    app: hello
    version: 1.0.0
  ports:
  - name: hello-port
    protocol: TCP
    port: 50001
    targetPort: 50001

Appliquez la première configuration de service en appelant la commande:

$ kubectl apply -f hello-service.yaml

goodbye-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: goodbye-service
spec:
  type: NodePort
  selector:
    app: goodbye
    version: 2.0.0
  ports:
  - name: goodbye-port
    protocol: TCP
    port: 50001
    targetPort: 50001

Appliquez la deuxième configuration de service en appelant la commande:

$ kubectl apply -f goodbye-service.yaml

Gardez à l'esprit que dans les deux configurations, tapez: NodePort

Vérifiez si les services ont été créés avec succès:

$ kubectl get services

La sortie devrait ressembler à ça:

NAME              TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)           AGE
goodbye-service   NodePort    10.0.5.131   <none>        50001:32210/TCP   3s
hello-service     NodePort    10.0.8.13    <none>        50001:32118/TCP   8s

Créer des entrées

Pour réaliser des sessions persistantes, vous devrez créer 2 définitions d'entrée.

Les définitions sont fournies ci-dessous:

bonjour-ingress.yaml:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hello-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "hello-cookie"
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/affinity-mode: persistent
    nginx.ingress.kubernetes.io/session-cookie-hash: sha1
spec:
  rules:
  - Host: DOMAIN.NAME
    http:
      paths:
      - path: /
        backend:
          serviceName: hello-service
          servicePort: hello-port

au revoir-ingress.yaml:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: goodbye-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "goodbye-cookie"
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/affinity-mode: persistent
    nginx.ingress.kubernetes.io/session-cookie-hash: sha1
spec:
  rules:
  - Host: DOMAIN.NAME
    http:
      paths:
      - path: /v2/
        backend:
          serviceName: goodbye-service
          servicePort: goodbye-port

S'il vous plaît changer DOMAIN.NAME dans les deux entrées pour convenir à votre cas. Je conseillerais de regarder sur ce lien Ingress Sticky session . Les deux entrées sont configurées pour le trafic HTTP uniquement.

Appliquez les deux en invoquant la commande:

$ kubectl apply -f hello-ingress.yaml

$ kubectl apply -f goodbye-ingress.yaml

Vérifiez si les deux configurations ont été appliquées:

$ kubectl get ingress

La sortie devrait ressembler à ceci:

NAME              HOSTS        ADDRESS          PORTS   AGE
goodbye-ingress   DOMAIN.NAME   IP_ADDRESS      80      26m
hello-ingress     DOMAIN.NAME   IP_ADDRESS      80      26m

Tester

Ouvrez votre navigateur et accédez à http://DOMAIN.NAME La sortie devrait être comme ceci:

Hello, world!
Version: 1.0.0
Hostname: hello-549db57dfd-4h8fb

Hostname: hello-549db57dfd-4h8fb est le nom du module. Rafraîchissez-le plusieurs fois.

Il devrait rester le même.

Pour vérifier si un autre itinéraire fonctionne, accédez à http://DOMAIN.NAME/v2/ La sortie devrait être comme ceci:

Hello, world!
Version: 2.0.0
Hostname: goodbye-7b5798f754-pbkbg

Hostname: goodbye-7b5798f754-pbkbg est le nom du module. Rafraîchissez-le plusieurs fois.

Il devrait rester le même.

Pour vous assurer que les cookies ne modifient pas les outils de développement ouverts (probablement F12) et accédez à la place avec des cookies. Vous pouvez recharger la page pour vérifier si elles ne changent pas.

Cookies

1
Dawid Kruk

Je pense que votre configuration Service est incorrecte. Il suffit de supprimer type: LoadBalancer et le type sera ClusterIP par défaut.

LoadBalancer: expose le service en externe à l'aide de l'équilibreur de charge d'un fournisseur de cloud. Les services NodePort et ClusterIP, vers lesquels les itinéraires de l'équilibreur de charge externe, sont automatiquement créés. Voir plus ici: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer .

apiVersion: v1
kind: Service
metadata:
  name: sample-backend
spec:
  selector:
    app: sample
    tier: backend
  ports:
    - protocol: TCP
      port: 8082
      targetPort: 8082
0
Dávid Molnár