J'essaie de réaliser un déploiement sans temps d'arrêt à l'aide de Kubernetes. Mais chaque fois que j'effectue la mise à niveau du déploiement à l'aide d'une nouvelle image, je constate 2-3 secondes d'indisponibilité. Je teste cela en utilisant une sorte d'application Hello-World mais je n'ai toujours pas pu y parvenir. Je déploie mon application à l'aide des graphiques Helm.
Suite aux blogs et ressources en ligne, j'utilise la stratégie Readiness-Probe et Rolling Update dans mon fichier Deployment.yaml. Mais cela ne me donne aucun succès.
J'ai créé un point de terminaison / health qui renvoie simplement le code d'état 200 comme vérification de la sonde de disponibilité. Je m'attendais à ce qu'après avoir utilisé les sondes de préparation et la stratégie RollingUpdate dans Kubernetes, je puisse obtenir un temps d'arrêt nul de mon service lorsque je mettrai à niveau l'image du conteneur. La demande à mon service passe par un Amazon ELB.
Le fichier Deployment.yaml est le suivant:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: wine-ingress
annotations:
kubernetes.io/ingress.class: public-nginx
spec:
rules:
- host: my-service-my-internal-domain.com
http:
paths:
- path: /
backend:
serviceName: wine-service
servicePort: 80
Fichier Service.yaml:
apiVersion: v1
kind: Service
metadata:
name: wine-service
labels:
app: wine-store
spec:
ports:
- port: 80
targetPort: 8089
protocol: TCP
selector:
app: wine-store
Fichier Ingress.yaml:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: wine-deployment
labels:
app: wine-store
chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: wine-store
replicas: 2
template:
metadata:
labels:
app: wine-store
spec:
containers:
- name: {{ .Chart.Name }}
resources:
limits:
cpu: 250m
requests:
cpu: 200m
image: "my-private-image-repository-with-tag-and-version-goes-here-which-i-have-hidden-here"
imagePullPolicy: Always
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 8089
name: testing-port
readinessProbe:
httpGet:
path: /health
port: 8089
initialDelaySeconds: 3
periodSeconds: 3
Je m'attends à ce que le temps d'arrêt soit nul lorsque je mets à niveau l'image à l'aide de la mise à niveau de la barre Commande . Pendant ce temps, lorsque la mise à niveau est en cours, je frappe continuellement mon service à l'aide d'une commande curl. Cette commande curl me donne des erreurs 503-service Temporairement indisponible pendant 2-3 secondes, puis à nouveau le service est activé. Je m'attends à ce que ce temps d'arrêt ne se produise pas.
3 Réponses :
Le problème que vous décrivez indique un problème avec les sondes de disponibilité. Il est important de comprendre les différences entre les sondes de vivacité et de préparation. Tout d'abord, vous devez implémenter et configurer les deux!
Les sondes de vivacité permettent de vérifier si le conteneur est démarré et actif. Si ce n'est pas le cas, kubernetes redémarrera éventuellement le conteneur.
Les sondes de disponibilité vérifient également à leur tour les dépendances telles que les connexions à la base de données ou d'autres services dont dépend votre conteneur pour accomplir son travail. En tant que développeur, vous devez investir ici plus de temps dans la mise en œuvre que dans les sondes de vivacité. Vous devez exposer un point de terminaison qui vérifie également les dépendances mentionnées lors de l'interrogation.
Votre configuration actuelle utilise un point de terminaison d'intégrité qui est généralement utilisé par les sondes de vivacité. Il ne vérifie probablement pas si vos services sont vraiment prêts à prendre du trafic.
Kubernetes s'appuie sur les sondes de disponibilité. Au cours d'une mise à jour progressive, il maintiendra l'ancien conteneur opérationnel jusqu'à ce que le nouveau service déclare qu'il est prêt à accepter le trafic. Par conséquent, les sondes de préparation doivent être correctement implémentées.
Salut @Randy, merci pour la suggestion. Je vais certainement mettre en œuvre une sonde de vivacité ainsi qu'une sonde de préparation et tester à nouveau. Je vais mettre à jour ici. Concernant les dépendances, je n'en ai pas. C'est une simple application Hello-World vertx . Aucun DB, aucun fichier de propriétés impliqué. J'utiliserai la même sonde HTTP-GET que la sonde de vivacité et de préparation.
@mohdshoaib vous pouvez également utiliser les sondes de durée de vie pour déboguer le comportement de k8s. Par exemple. vous pouvez vous connecter s'il a vraiment appelé le point de terminaison pour vérifier si le service est prêt ou non.
si j'utilise kubectl logs podName -n NamespaceName , est-ce que j'obtiendrai ces journaux? ou je devrai faire Kubectl describe pod ?
Avec les journaux kubectl , vous obtiendrez ce que le pod écrit sur stdout et sterr. Respectivement, vous devez implémenter la sonde de disponibilité pour vous connecter à stout si vous souhaitez y voir les journaux.
J'ai également essayé avec une sonde de vivacité, mais cela n'a pas fonctionné. Bien que je n'ai pas pu trouver les journaux pour les sondes.
Cela indique que vos sondes de vie ne sont pas utilisées pour une raison quelconque (non joignable, etc.), ce qui explique à son tour pourquoi vous perdez des requêtes. Kubernetes ne peut pas déterminer entièrement la vivacité de votre service. Cependant, je ne fais que deviner ici.
Il y a un peu de malentendu ici. Il est tout à fait exact que la configuration correcte de votre sonde de disponibilité est essentielle. Cependant, les sondes de vivacité ne sont pas pertinentes dans le contexte de cette question.
Faites le tour des déploiements bleu-vert car même si les pods sont actifs, kube-proxy peut prendre du temps pour transférer les requêtes vers de nouvelles IP POD.
Donc, configurez un nouveau déploiement, une fois que tous les pods sont en place, mettez à jour le sélecteur du service vers de nouvelles étiquettes POD.
Suivez: https://kubernetes.io/blog / 2018/04/30 / déploiement-sans-indisponibilité-kubernetes-jenkins /
@akash, merci. Je n'ai pas eu l'occasion de passer par ce lien. Je vais essayer si les sondes de vivacité ne fonctionnent pas non plus.
Ce problème est causé par le service VIP utilisant iptables. Vous n'avez rien fait de mal - c'est une limitation de Kubernetes actuel.
Lorsque la sonde de préparation sur le nouveau pod réussit, l'ancien pod est terminé et kube-proxy réécrit les iptables pour le service. Cependant, une requête peut atteindre le service après la fin de l'ancien pod mais avant la mise à jour d'iptables, ce qui entraîne un 503.
Une solution simple consiste à retarder la résiliation en utilisant un preStop hook de cycle de vie:
lifecycle:
preStop:
exec:
command: ["/bin/bash", "-c", "sleep 10"]
Cela ne serait probablement pas pertinent dans ce cas, mais implémenter une terminaison gracieuse dans votre application est une bonne idée. Interceptez le signal TERM et attendez que votre application ait fini de traiter toutes les demandes qu'elle a déjà reçues plutôt que de simplement quitter immédiatement.
Alternativement, plus de répliques, un maxUnavailable bas et un haut maxSurge réduira tous la probabilité que les requêtes atteignent un pod qui se termine.
Pour plus d'informations: https://kubernetes.io/docs/concepts/services -networking / service / # proxy-mode-iptables https://kubernetes.io/docs/concepts/workloads / pods / pod / # terminaison-de-pods
Une autre réponse suggère à tort que vous avez besoin d'une sonde de vivacité. Bien que ce soit une bonne idée d'avoir une sonde de vivacité, cela n'affectera pas le problème que vous rencontrez. En l'absence de sonde de vivacité définie, l'état par défaut est Réussite.
Dans le contexte d'un déploiement progressif, une sonde de vivacité ne sera pas pertinente - Une fois que la sonde de disponibilité sur le nouveau pod aura passé, l'ancien pod recevra le signal TERM et iptables seront mis à jour. Maintenant que l'ancien pod est terminé, toute sonde de vivacité n'est plus pertinente car sa seule fonction est de provoquer le redémarrage d'un pod si la sonde de vivacité échoue.
Toute sonde de vivacité sur le nouveau pod à nouveau n'est pas pertinente. Lorsque le pod est démarré pour la première fois, il est considéré comme actif par défaut. Ce n'est qu'après le initialDelaySeconds de la sonde de vivacité qu'elle commencerait à être vérifiée et, si elle échouait, le pod serait arrêté.
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes