Kubernetes: Bessere Unterstützung für Sidecar-Container in Batch-Jobs

Erstellt am 19. Mai 2016  ·  116Kommentare  ·  Quelle: kubernetes/kubernetes

Betrachten Sie einen Job mit zwei darin enthaltenen Containern – einer, der die Arbeit erledigt und dann beendet wird, und ein anderer, der nicht dafür ausgelegt ist, jemals explizit zu beenden, sondern eine Art unterstützende Funktionalität wie Protokoll- oder Metriksammlung bietet.

Welche Möglichkeiten gibt es, um so etwas zu tun? Welche Möglichkeiten sollte es geben?

Derzeit wird der Job so lange ausgeführt, wie der zweite Container ausgeführt wird, was bedeutet, dass der Benutzer den zweiten Container in irgendeiner Weise modifizieren muss, um zu erkennen, wann der erste abgeschlossen ist, damit er auch sauber beendet werden kann.

Diese Frage wurde vor einiger Zeit bei Stack Overflow gestellt, und es gab keine bessere Antwort, als den zweiten Container so zu modifizieren, dass er Kubernetes-fähiger ist, was nicht ideal ist. Ein anderer Kunde hat mir kürzlich dies als Schmerzpunkt angesprochen.

@kubernetes/goog-control-plane @erictune

arebatch areworkload-apjob kinfeature lifecyclfrozen prioritimportant-longterm siapps sinode

Hilfreichster Kommentar

Als Referenz hier ist der Bash-Wahnsinn, den ich verwende, um das gewünschte Sidecar-Verhalten zu simulieren:

containers:
  - name: main
    image: gcr.io/some/image:latest
    command: ["/bin/bash", "-c"]
    args:
      - |
        trap "touch /tmp/pod/main-terminated" EXIT
        /my-batch-job/bin/main --config=/config/my-job-config.yaml
    volumeMounts:
      - mountPath: /tmp/pod
        name: tmp-pod
  - name: envoy
    image: gcr.io/our-envoy-plus-bash-image:latest
    command: ["/bin/bash", "-c"]
    args:
      - |
        /usr/local/bin/envoy --config-path=/my-batch-job/etc/envoy.json &
        CHILD_PID=$!
        (while true; do if [[ -f "/tmp/pod/main-terminated" ]]; then kill $CHILD_PID; fi; sleep 1; done) &
        wait $CHILD_PID
        if [[ -f "/tmp/pod/main-terminated" ]]; then exit 0; fi
    volumeMounts:
      - mountPath: /tmp/pod
        name: tmp-pod
        readOnly: true
volumes:
  - name: tmp-pod
    emptyDir: {}

Alle 116 Kommentare

/sub

Auch die Verwendung eines Lebendigkeitsproblems wie hier vorgeschlagen http://stackoverflow.com/questions/36208211/sidecar-containers-in-kubernetes-jobs funktioniert nicht, da der Pod als fehlgeschlagen und der gesamte Job als nicht erfolgreich betrachtet wird.

Wie wäre es, wenn wir einen Joberfolgstest deklariert haben, damit der Job ihn testen kann, um den Erfolg zu erkennen, anstatt darauf zu warten, dass der Pod 0 zurückgibt.
Sobald die Sonde erfolgreich ist, kann der Pod beendet werden.

Kann die Sonde gegen einen Container ausgeführt werden, der bereits beendet wurde, oder würde er dort?
ein Rennen sein, wo es abgerissen wird?

Eine andere Möglichkeit besteht darin, bestimmten Exit-Codes eine besondere Bedeutung zuzuweisen.

Sowohl "Erfolg für den gesamten Pod" als auch "Misserfolg für den gesamten Pod" sind beides
sinnvoll.

Dies müsste sich im Pod-Objekt befinden, also ist dies eine große API-Änderung.

Am Do, 22. September 2016 um 13:41 Uhr schrieb Ming Fang [email protected] :

Wie wäre es, wenn wir eine Job-Erfolgsprüfung deklariert haben, damit der Job sie prüfen kann?
Erfolg erkennen, anstatt darauf zu warten, dass der Pod 0 zurückgibt.

Sobald die Sonde erfolgreich ist, kann der Pod beendet werden.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/kubernetes/kubernetes/issues/25908#issuecomment -249021627,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AHuudjrpVtef6U35RWRlZr3mDKcCRo7oks5qsugRgaJpZM4IiqQH
.

@erictune Guter Punkt; Wir können einen verlassenen Container nicht untersuchen.

Können wir einen bestimmten Container im Pod als "Abschluss"-Container festlegen, damit wir beim Verlassen dieses Containers sagen können, dass der Job abgeschlossen ist?

Die Sidecar-Container sind in der Regel langlebig für Dinge wie den Rundholzversand und die Überwachung.
Wir können die Beendigung erzwingen, sobald der Auftrag abgeschlossen ist.

Können wir einen bestimmten Container im Pod als "Abschluss"-Container festlegen, damit wir beim Verlassen dieses Containers sagen können, dass der Job abgeschlossen ist?

Haben Sie sich diesen Dokumentpunkt 3 angesehen, der hier ausführlich beschrieben ist, wo Sie im Grunde genommen nicht .spec.completions und sobald der erste Container mit 0-Exit-Code fertig ist, sind die Jobs erledigt.

Die Sidecar-Container sind in der Regel langlebig für Dinge wie den Rundholzversand und die Überwachung.
Wir können die Beendigung erzwingen, sobald der Auftrag abgeschlossen ist.

Persönlich sehen diese für mich eher nach RS als nach einem Job aus, aber das ist meine persönliche Meinung und vor allem kenne ich nicht alle Details Ihres Setups.

Im Allgemeinen gibt es folgende Diskussionen https://github.com/kubernetes/kubernetes/issues/17244 und https://github.com/kubernetes/kubernetes/issues/30243 , die ebenfalls dieses Thema berühren.

@soltysh der Link, den Sie oben gesendet haben, Punkt 3 verweist auf die Pod-Vervollständigung und nicht auf die Container-Vervollständigung.

Die beiden Container können sich ein leeres Verzeichnis und den ersten Container teilen und eine "Ich beende jetzt"-Nachricht in eine Datei schreiben, und der andere kann beendet werden, wenn er diese Nachricht sieht.

@erictune Ich habe einen Anwendungsfall, der meiner Meinung nach in diesen Eimer fällt, und ich hoffe, Sie können mich in die richtige Richtung führen, da es anscheinend keine offiziell empfohlene Methode zur Lösung dieses Problems gibt.

Ich verwende die client-go-Bibliothek, um alles unten zu codieren:

Ich habe also einen Job, der im Grunde ein Tool in einem Ein-Container-Pod ausführt. Sobald das Tool die Ausführung beendet hat, soll es eine Ergebnisdatei erzeugen. Ich kann diese Ergebnisdatei anscheinend nicht erfassen, da der Pod gelöscht wird, sobald die Ausführung des Tools abgeschlossen ist, und ich die Ergebnisdatei verliere.

Ich konnte diese Ergebnisdatei erfassen, wenn ich HostPath als VolumeSource verwendet habe und da ich minikube lokal ausführe, wird die Ergebnisdatei auf meiner Workstation gespeichert.

Ich verstehe jedoch, dass dies nicht empfohlen und ideal für Produktionscontainer ist. Also habe ich EmptyDir wie oben vorgeschlagen verwendet. Aber wenn ich das tue, kann ich es nicht wirklich erfassen, da es mit dem Pod selbst gelöscht wird.

Sollte ich mein Problem also auch mit dem Sidecar-Container-Muster lösen?

Machen Sie im Grunde das, was Sie oben vorgeschlagen haben. Starten Sie bei jedem Jobstart 2 Container im Pod. 1 Container den Job ausführt und, sobald der Job erledigt ist, eine Nachricht ablegt, die vom anderen Container aufgenommen wird, der dann die Ergebnisdatei greift und irgendwo speichert?

Ich verstehe nicht, warum wir überhaupt 2 Container brauchen. Warum kann der Job-Container das alles nicht selbst erledigen? Das heißt, beenden Sie den Job, speichern Sie die Ergebnisdatei irgendwo, greifen Sie darauf zu/lesen Sie sie und speichern Sie sie irgendwo.

@anshumanbh Ich würde dir vorschlagen:

  1. Verwenden Sie einen persistenten Speicher, speichern Sie die Ergebnisdatei
  2. Verwenden Sie hostPath mount, was fast das gleiche wie 1 ist, und Sie haben es bereits ausprobiert
  3. Laden Sie die Ergebnisdatei an einen bekannten Remote-Speicherort (s3, Google Drive, Dropbox) hoch, im Allgemeinen jede Art von geteiltem Laufwerk

@soltysh Ich möchte nicht, dass die Datei dauerhaft gespeichert wird. Bei jedem Lauf möchte ich dieses Ergebnis nur mit dem letzten Ergebnis vergleichen. Ich dachte also daran, dies bei jedem Lauf auf ein Github-Repository zu übertragen und dann einen Vergleich durchzuführen, um zu sehen, was sich geändert hat. Dazu muss ich das Ergebnis nur vorübergehend irgendwo speichern, damit ich darauf zugreifen und es an Github senden kann. Sinn ergeben?

@anshumanbh völlig klar, und das fällt immer noch nicht in die Kategorie der Beiwagencontainer. Alles, was Sie erreichen möchten, ist derzeit mit dem, was Jobs bieten, machbar.

@soltysh In Anbetracht der Tatsache, dass ich mich für Option 3 aus der oben vorgeschlagenen Liste entscheiden möchte, wie würde ich sie implementieren?

Das Problem, mit dem ich konfrontiert bin, ist, dass der Container beendet wird, sobald der Job abgeschlossen ist, und ich die Datei verliere. Wenn ich die Datei nicht habe, wie lade ich sie auf ein geteiltes Laufwerk wie S3/Google Drive/Dropbox hoch? Ich kann den Code des Jobs nicht ändern, um ihn automatisch irgendwo hochzuladen, bevor er beendet wird, daher müsste ich leider zuerst den Job ausführen und dann die Datei irgendwo speichern.

Wenn Sie den Code des Jobs nicht ändern können, müssen Sie ihn so umschließen, dass Sie die Datei hochladen können. Wenn Sie bereits mit einem Bild arbeiten, erweitern Sie es einfach mit dem Kopiercode.

@soltysh ja, das macht Sinn. Das könnte ich machen. Die nächste Frage, die ich habe, lautet jedoch: Angenommen, ich muss mehrere Jobs ausführen (stellen Sie sich vor, dass Sie verschiedene Tools ausführen), und in keinem dieser Tools ist der Upload-Teil integriert. Jetzt müsste ich also diesen Wrapper erstellen und jedes dieser Tools um den Upload-Teil erweitern. Gibt es eine Möglichkeit, den Wrapper/die Erweiterung einmal zu schreiben und für alle Tools zu verwenden?

Würde das Seitenwagenmuster in diesem Fall nicht passen?

Ja, es könnte. Obwohl ich es mit mehreren Containern innerhalb desselben Pods versuchen würde, Muster. Iow. Ihr Pod führt den Job-Container aus und neben einem zusätzlichen, der auf die Ausgabe wartet und diese hochlädt. Ich bin mir nicht sicher, wie machbar das ist, aber Sie können es bereits ausprobieren.

Sanftes Ping – Sidecar Awareness würde die Verwaltung von Microservice-Proxys wie Envoy viel angenehmer machen. Gibt es Fortschritte zu teilen?

Der aktuelle Stand der Dinge ist, dass jeder Container gebündelte Tools benötigt, um die Lebensdauer zu koordinieren, was bedeutet, dass wir Upstream-Container-Images nicht direkt verwenden können. Es verkompliziert auch die Vorlagen erheblich, da wir zusätzliche argv- und Mount-Punkte einfügen müssen.

Ein früherer Vorschlag war, einige Container als "Abschluss"-Container zu bezeichnen. Ich möchte das Gegenteil vorschlagen - die Möglichkeit, einige Container als "Beiwagen" zu kennzeichnen. Wenn der letzte Nicht-Sidecar-Container in einem Pod beendet wird, sollte der Pod TERM an die Sidecars senden. Dies wäre analog zum Konzept des "Hintergrundthreads", das in vielen Threading-Bibliotheken zu finden ist, zB Thread.daemon Python.

Beispielkonfiguration, wenn der Container main endet, würde das Kubelet envoy töten:

containers:
  - name: main
    image: gcr.io/some/image:latest
    command: ["/my-batch-job/bin/main", "--config=/config/my-job-config.yaml"]
  - name: envoy
    image: lyft/envoy:latest
    sidecar: true
    command: ["/usr/local/bin/envoy", "--config-path=/my-batch-job/etc/envoy.json"]

Als Referenz hier ist der Bash-Wahnsinn, den ich verwende, um das gewünschte Sidecar-Verhalten zu simulieren:

containers:
  - name: main
    image: gcr.io/some/image:latest
    command: ["/bin/bash", "-c"]
    args:
      - |
        trap "touch /tmp/pod/main-terminated" EXIT
        /my-batch-job/bin/main --config=/config/my-job-config.yaml
    volumeMounts:
      - mountPath: /tmp/pod
        name: tmp-pod
  - name: envoy
    image: gcr.io/our-envoy-plus-bash-image:latest
    command: ["/bin/bash", "-c"]
    args:
      - |
        /usr/local/bin/envoy --config-path=/my-batch-job/etc/envoy.json &
        CHILD_PID=$!
        (while true; do if [[ -f "/tmp/pod/main-terminated" ]]; then kill $CHILD_PID; fi; sleep 1; done) &
        wait $CHILD_PID
        if [[ -f "/tmp/pod/main-terminated" ]]; then exit 0; fi
    volumeMounts:
      - mountPath: /tmp/pod
        name: tmp-pod
        readOnly: true
volumes:
  - name: tmp-pod
    emptyDir: {}

Ich möchte das Gegenteil vorschlagen - die Möglichkeit, einige Container als "Beiwagen" zu kennzeichnen. Wenn der letzte Container ohne Sidecar in einem Pod endet, sollte der Pod TERM an die Sidecars senden.

@jmillikin-stripe Ich mag diese Idee, obwohl ich nicht sicher bin, ob dies dem Prinzip folgt, einige Container in einem Pod unterschiedlich zu behandeln oder Abhängigkeiten zwischen ihnen einzuführen. Ich werde @erictune für den letzten Anruf verschieben.

Obwohl Sie #17244 überprüft haben, würde diese Art von Lösung zu Ihrem Anwendungsfall passen? Das hat @erictune vor einigen Kommentaren erwähnt :

Eine andere Möglichkeit besteht darin, bestimmten Exit-Codes eine besondere Bedeutung zuzuweisen.

@jmillikin-stripe Ich mag diese Idee, obwohl ich nicht sicher bin, ob dies dem Prinzip folgt, einige Container in einem Pod unterschiedlich zu behandeln oder Abhängigkeiten zwischen ihnen einzuführen. Ich werde @erictune für den letzten Anruf verschieben.

Ich denke, Kubernetes muss möglicherweise flexibel sein, um Container nicht unterschiedlich zu behandeln. Wir (Stripe) möchten Drittanbieter-Code wie Envoy nicht mit Lifecycle-Hooks im Lamprey-Stil nachrüsten, und der Versuch, eine Exec-Inversion im Envelope-Stil zu übernehmen, wäre viel komplexer, als Kubelet bestimmte Sidecars beenden zu lassen.

Obwohl Sie #17244 überprüft haben, würde diese Art von Lösung zu Ihrem Anwendungsfall passen? Das hat @erictune vor einigen Kommentaren erwähnt:

Eine andere Möglichkeit besteht darin, bestimmten Exit-Codes eine besondere Bedeutung zuzuweisen.

Ich bin sehr dagegen, dass Kubernetes oder Kubelet Fehlercodes mit einer feineren Granularität als "Null oder Nicht-Null" interpretieren. Borglets Verwendung der magischen Nummern des Exit-Codes war eine unangenehme Fehlfunktion, und es wäre in Kubernetes viel schlimmer, wo ein bestimmtes Container-Image in verschiedenen Pods entweder ein "Main" oder "Sidecar" sein könnte.

Vielleicht würden zusätzliche Lifecycle-Hooks ausreichen, um dies zu lösen?

Könnte sein:

  • PostStop: mit einer Möglichkeit, Lifecycle-Ereignisse auf anderen Containern im Pod auszulösen (dh Trigger-Stopp)
  • PeerStopped: signalisieren, dass ein "Peer"-Container im Pod gestorben ist - möglicherweise mit Exit-Code als Argument

Dies könnte auch ein Mittel zum Definieren benutzerdefinierter Richtlinien zum Neustarten eines Containers definieren - oder sogar Container starten, die nicht standardmäßig gestartet werden, um eine Verkettung von Containern zu ermöglichen (wenn Container a beendet ist, starten Sie Container b).

Das fehlt auch. Wir führen alle 30 Minuten einen Job aus, der einen VPN-Client für die Konnektivität benötigt, aber es scheint viele Anwendungsfälle zu geben, in denen dies sehr nützlich sein könnte (z. B. Dinge, die einen kubectl-Proxy benötigen). Momentan verwende ich jobSpec.concurrencyPolicy: Replace als Workaround, aber das funktioniert natürlich nur, wenn a.) Sie ohne parallele Jobläufe auskommen können und b.) die Job-Ausführungszeit kürzer ist als das Scheduling-Intervall.

BEARBEITEN: In meinem Anwendungsfall wäre es völlig ausreichend, eine Eigenschaft in der Jobspezifikation zu haben, um einen Container als den beendenden zu markieren und den Job diesen auf den Exit-Status überwachen und die restlichen beenden zu lassen.

Auch ich habe ein Bedürfnis dafür. In unserem Fall ist es ein Job, der den cloudql-proxy-Container als Sidecar-Dienst nutzt.

Wie wäre es, möglicherweise eine Anmerkung hinzuzufügen, die dem Namen des "primären" Containers im Pod zugeordnet ist? Auf diese Weise muss die Pod-Spezifikation sowieso nicht geändert werden.

Aufgrund des Designs von Pods scheint dies ein sehr häufiger Anwendungsfall zu sein. @soltysh @erictune Hast du vor, bald daran zu arbeiten? Ich helfe gerne, wo es möglich ist :)

Brauche diese Funktion auch. Für unseren Anwendungsfall :
Pod A muss in Containern

  • Container A1 : ein Run-to-Complete-Container, der das Protokoll in Dateien druckt
  • Container A2 : Sidecar-Container, der nur Protokolle von der Datei nach stdout protokolliert

Was ich will : Wenn Container A1 erfolgreich abgeschlossen ist, wird Pod A erfolgreich abgeschlossen. Können wir Container A1 einfach als Hauptcontainer kennzeichnen , wenn der Hauptcontainer austritt, Pod austritt? @erictune (Diese Idee wird auch von @mingfang beschrieben )

Hey Leute, wie ich sehe, ist diese Ausgabe seit einem Monat offen. Was ist das neueste dazu? Wir haben einen Anwendungsfall, bei dem wir einen Job ausführen möchten. Der Job führt einen main Container mit einigen Sidecar containers . Wir möchten, dass der Job beendet wird, wenn der main Container beendet wird. Ist es Stand der Technik, ein file zu teilen, um ein signal zwischen den Containern zu senden?

Es würde mir nichts ausmachen, daran zu arbeiten, würde gerne wissen, ob jemand kommende PRs überprüfen könnte, wenn ich dies tue (vielleicht nach kubecon).

cc @erictune @a-robinson @soltysh

@andrewsykim, welchen Ansatz würden Sie main Container nicht starten sollte, bis die Sidecars initialisiert sind

So wie der Hauptcontainer nicht starten sollte, bis die Sidecars initialisiert sind

Ich denke, dieser Fall ist kein Problem, da main in der Lage sein sollte, zu überprüfen, wann der Sidecar initialisiert wird (oder eine Bereitschaftssonde verwenden). Dies ist bei diesem Problem nicht der Fall, da main wäre :)

Am Ende habe ich ein einfaches Skript geschrieben, das die Kubernetes-API überwacht und Jobs mit einer passenden Annotation beendet und dessen Hauptcontainer beendet wurde. Es ist nicht perfekt, aber es erfüllt das Kernbedürfnis. Ich kann es teilen, wenn die Leute interessiert sind.

@ajbouh Ich würde mich persönlich

@nrmitchi Hier ist eine Zusammenfassung des Yamls, das ich geschrieben habe. Es ist sehr Shell-Skript, aber vielleicht ist es ein guter Ausgangspunkt für Sie, wenn es darum geht, welche APIs Sie verwenden und wie Sie etwas funktionierendes bekommen. Ich kann Fragen zu der Funktion beantworten, wenn Sie Fragen haben.

https://gist.github.com/ajbouh/79b3eb4833aa7b068de640c19060d126

Ich habe denselben Cloud SQL-Proxy-Anwendungsfall wie @mrbobbytables. Um eine sichere Verbindung mit Cloud SQL herzustellen, wird empfohlen, den Proxy zu verwenden, aber dieser Proxy wird nicht beendet, wenn die Aufgabe erledigt ist, was zu verrückten Hacks oder Überwachungen führt, die wie folgt aussehen. Gibt es dazu einen Weg nach vorne?

image

@amaxwell01 In Bezug auf die Beteiligung von Cloud SQL Proxy hatte ich ein Problem mit Google geöffnet, das Sie suchen konnten: https://issuetracker.google.com/issues/70746902 (Bearbeiten: und ich bedauere einige Formulierungen, die ich verwendet habe dort in der Hitze des Gefechts; leider kann ich es nicht bearbeiten)

Danke @abevoelker ich

Auch wir sind von diesem Problem betroffen.
Wir haben mehrere Django-Verwaltungsbefehle auf unseren Mikrodiensten, die auf k8s-Cronjobs ausgeführt werden können, aber aufgrund des Cloudsqlproxy-Sidecars, der nach Abschluss des Jobs nicht angehalten wird, nicht erfolgreich sind.
Gibt es ein Update, wann wir eine Lösung haben könnten?
Das Sidecar-Container-Muster wird immer mehr verwendet und viele von uns werden nicht in der Lage sein, k8s-Cronjobs und -Jobs zu verwenden, bis dies behoben ist.

Wollte nur meine +1 dafür einwerfen. Ich habe das gleiche Problem mit dem GCE Cloud SQL Proxy wie alle anderen. Es bringt mich um... Helm-Einsatz schlägt fehl, was wiederum fehlschlägt, wenn meine Terraform angewendet wird.

Ich würde wirklich gerne eine Lösung zu diesem Thema sehen ... Jist von @ajbouh sieht so aus, als

Für alle anderen, die cloudsql-proxy benötigen, würde es zu Ihrem Anwendungsfall passen, cloudsql-proxy als DaemonSet auszuführen? In meinem Fall hatte ich sowohl ein persistentes Deployment als auch einen CronJob, der den Proxy erforderte, daher war es sinnvoll, ihn von einzelnen Pods zu trennen und stattdessen eine Instanz pro Knoten anzuhängen.

Ja,

Wir haben uns entschieden, die Cloudsql-Proxy-Sidecars zu entfernen und einen Pool von
Cloudsql-Proxys in ihrem zentralen Namespace, es funktioniert perfekt und ermöglicht
Verschieben Sie Skalierbarkeit und einfachere Bereitstellungen.
Jetzt können wir ohne Probleme Jobs und Cronjobs ausführen.

Am Mittwoch, 7. Februar 2018 um 9:37 Uhr, Rob Jackson [email protected]
schrieb:

Für alle anderen, die einen Cloudsql-Proxy benötigen, würde dies zu Ihrem Anwendungsfall passen?
den cloudql-proxy als DaemonSet ausführen? In meinem Fall hatte ich beides eine hartnäckige
Deployment und ein CronJob, der den Proxy erfordert, daher war es sinnvoll, ihn zu trennen
aus einzelnen Pods und fügen Sie stattdessen eine Instanz pro Knoten hinzu.


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/kubernetes/kubernetes/issues/25908#issuecomment-363710890 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/ACAWMwetx6gA_SrHL_RRbTMJVOhW1FKLks5tSW7JgaJpZM4IiqQH
.

Interessant, die Verwendung eines Deamonsets klingt nach einer guten Option. @RJacksonm1 & @devlounge - Wie funktioniert die Erkennung des Cloud-SQL-Proxys bei Verwendung von Daemonsets?

Habe das gefunden, was aussieht, als würde es den Trick machen ...
https://buoyant.io/2016/10/14/a-service-mesh-for-kubernetes-part-ii-pods-are-great-until-theyre-not/

Im Wesentlichen beinhaltet dies die Verwendung von etwas wie diesem, um die Host-IP zu erhalten:

env:
- name: NODE_NAME
  valueFrom:
    fieldRef:
      fieldPath: spec.nodeName

@RJacksonm1 - Gab es etwas Besonderes, das Sie getan haben, damit hostPort funktioniert? Ich bekomme ständig connection refused wenn ich es in Verbindung mit dem fieldPath: spec.nodeName Ansatz verwende 🤔

Bearbeiten: Ich habe sichergestellt, dass spec.nodeName richtig durchkommt und ich bin auf GKE v1.9.2-gke.1

@cvallance Ich habe einen Dienst eingerichtet, um das DaemonSet bereitzustellen, auf das meine Anwendung dann über DNS zugreifen kann. Dies garantiert nicht, dass die Anwendung mit der cloudsql-proxy Instanz kommuniziert, die auf demselben Host wie sie selbst ausgeführt wird, aber es garantiert, dass cloudsql-proxy mit dem Cluster als Ganzes skaliert (ursprünglich hatte ich die Proxy als Deployment und HorizontalPodAutoscaler, fand aber, dass er zu stark nach oben/unten skaliert – was zu MySQL has gone away Fehlern in der App führte). Ich denke, das entspricht nicht dem wahren Geist eines DaemonSet...

@RJacksonm1 - habe es mit hostPort und spec.nodeName zum Laufen gebracht ... jetzt werden sie sich direkt mit dem DaemonSet auf ihrem Knoten verbinden 😄

CloudSql Proxy-Befehl funktioniert nicht:
-instances={{ .Values.sqlConnectionName }}=tcp:{{ .Values.internalPort }}
Arbeiten:
-instances={{ .Values.sqlConnectionName }}=tcp:0.0.0.0:{{ .Values.internalPort }}

Gibt es etwas, was wir tun können, um dieses Problem zu lösen?
Es ist seit fast 2 Jahren geöffnet und wir haben immer noch nur Workarounds

Ich vermute, selbst wenn ich mich freiwillig dazu bereitstelle, dies zu implementieren, werde ich dies nicht tun können, da dies eine Genehmigung der internen Leute bezüglich der zu implementierenden Lösung, der API-Änderungen usw.

Kann ich etwas tun, um dies zu erreichen?

Als Referenz habe ich eine Cloud-sql-proxy-Sidecar-Version der Problemumgehung von @jmillikin-stripe erstellt, bei der eine Datei in einem freigegebenen Volume den Status an den Sidecar übermittelt.

Es funktioniert OK, ist aber bei weitem der gemeinste Hack in meiner K8s-Konfiguration :(

apiVersion: batch/v1
kind: Job
metadata:
  name: example-job
spec:
  template:
    spec:
      containers:
      - name: example-job
        image: eu.gcr.io/example/example-job:latest
        command: ["/bin/sh", "-c"]
        args:
          - |
            trap "touch /tmp/pod/main-terminated" EXIT
            run-job.sh
        volumeMounts:
          - mountPath: /tmp/pod
            name: tmp-pod
      - name: cloudsql-proxy
        image: gcr.io/cloudsql-docker/gce-proxy:1.11
        command: ["/bin/sh", "-c"]
        args:
          - |
            /cloud_sql_proxy --dir=/cloudsql -instances=example:europe-west3:example=tcp:3306 -credential_file=/secrets/cloudsql/credentials.json &
            CHILD_PID=$!
            (while true; do if [[ -f "/tmp/pod/main-terminated" ]]; then kill $CHILD_PID; echo "Killed $CHILD_PID as the main container terminated."; fi; sleep 1; done) &
            wait $CHILD_PID
            if [[ -f "/tmp/pod/main-terminated" ]]; then exit 0; echo "Job completed. Exiting..."; fi
        volumeMounts:
          - name: cloudsql-instance-credentials
            mountPath: /secrets/cloudsql
            readOnly: true
          - name: cloudsql
            mountPath: /cloudsql
          - mountPath: /tmp/pod
            name: tmp-pod
            readOnly: true
      restartPolicy: Never
      volumes:
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials
        - name: cloudsql
          emptyDir:
        - name: tmp-pod
          emptyDir: {}
  backoffLimit: 1

Kann sich jemand innerhalb des Projekts bitte zum Fortschritt dieses Problems äußern?

Gleiches Problem hier

cc @kubernetes/sig-apps-feature-requests @kubernetes/sig-node-feature-requests

Wäre es sinnvoll, Benutzern zu erlauben, die Container in einem Job (mit Namen) anzugeben, die sie erfolgreich abgeschlossen sehen möchten, um den Job-Pod als erledigt zu markieren (mit anderen Containern gestoppt), wie folgt:

apiVersion: batch/v2beta1
kind: Job
metadata:
  name: my-job
  namespace: app
spec:
  template:
    spec:
      containers:
        - name: my-container
          image: my-job-image
          ...
        - name: cloudsql-proxy
          image: gcr.io/cloudsql-docker/gce-proxy:1.11
          ...
  backoffLimit: 2
  jobCompletedWith:
    - my-container

Dh der Pod würde laufen, warten, bis my-container erfolgreich beendet wird, und dann einfach cloudsql-proxy beenden.

EDIT: Wenn ich in diesem Thread nach oben scrolle, sehe ich jetzt, dass dies bereits vorgeschlagen wurde. Kann @erictune oder jemand anderes vielleicht noch einmal erläutern, warum dies nicht funktionieren würde?

ja ich denke das wäre perfekt. Nur etwas, mit dem Sie den Status des Jobs verfolgen und die Pipeline fortsetzen können, sobald sie abgeschlossen ist

Ja, das wäre perfekt.

Ich mag diese Idee @jpalomaki

Eine Sorge, die ich bei dem Ansatz habe, dieses Problem nur innerhalb des Job-Controllers zu lösen, besteht darin, dass der Pod nach Abschluss des Jobs weiterläuft. Derzeit tritt der Pod in die Terminated-Phase ein und der Node kann diese Ressourcen freigeben.

Sie könnten den Job-Controller den Pod löschen lassen, wenn der Controller entscheidet, dass es fertig ist, aber das würde sich auch vom aktuellen Verhalten unterscheiden, bei dem der Terminated-Pod-Datensatz im API-Server verbleibt (ohne Knotenressourcen zu beanspruchen).

Aus diesen Gründen erscheint es mir sauberer, dies, wenn überhaupt, auf Pod-API-Ebene anzugehen. Der Node ist das einzige, was in einzelne Container greifen und töten sollte, da die "Completion"-Container, die Sie interessieren, bereits beendet sind. Dies kann entweder die Form einer API auf Pod-Ebene haben, mit der Sie angeben können, auf welche Container gewartet werden soll, oder eine API auf Pod-Ebene, mit der externe Agenten (z. B. der Job-Controller) den Pod zum Beenden zwingen können, ohne ihn tatsächlich zu löschen der Pod.

Ich suche auch nach einer Lösung zum Hochladen von Dateien, die von einem Container erstellt wurden, wenn der Prozessorcontainer erfolgreich beendet wurde.

Ich bin mir nicht sicher, ob ich das Argument von @mingfang verstehe, das dagegen

Ein weiterer Gedanke, der wie ein Hack aussieht, aber ich würde gerne wissen, wie schlimm es wäre, den datenerzeugenden Container in einen Init-Container zu verwandeln und den Daten-Upload-Container zu haben (der kein Sidecar-Container mehr sein müsste) ) wird erst nach erfolgreichem Beenden des Prozessor-Containers automatisch gestartet. In meinem Fall bräuchte ich auch als ersten Init-Container einen Daten-Downloader-Container, um dem Verarbeitungscontainer Daten zur Verfügung zu stellen. Wenn dies eine besonders schlechte Idee ist, würde ich gerne erfahren, warum.

Würde es dieses Problem nicht lösen, den Beiwagen zu einem erstklassigen k8s-Konzept zu befördern? Kubelet kann den Pod beenden, wenn alle laufenden Container darin als Sidecar-Container markiert sind.

FWIW, ich habe dies umgangen, indem ich einfach den Cloud SQL-Proxy als reguläre Bereitstellung bereitgestellt habe ( replicas: 1 ) und meine Job und CronJob dazu gebracht haben, ihn über ein type: ClusterIP Service. Jobs werden jetzt gut abgeschlossen.

Ich würde mich über eine offizielle Stellungnahme dazu freuen.

Wenn wir keine Unterstützung von der API erhalten, sollten wir zumindest die alternativen Lösungen offiziell dokumentieren, damit die Leute wissen, was zu tun ist, wenn dieses Problem auftritt.

Ich bin mir nicht sicher, wen ich anpingen oder wie ich darauf aufmerksam machen soll...

Es wäre wirklich schön, wenn das angesprochen würde. Abgesehen davon, dass der Job nie weggeht, ist der Gesamtstatus des Pods anscheinend falsch:

Init Containers:
  initializer:
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Wed, 21 Mar 2018 17:52:57 -0500
      Finished:     Wed, 21 Mar 2018 17:52:57 -0500
    Ready:          True
Containers:
  sideCar:
    State:          Running
      Started:      Wed, 21 Mar 2018 17:53:40 -0500
    Ready:          True
  mainContainer:
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Wed, 21 Mar 2018 17:53:41 -0500
      Finished:     Wed, 21 Mar 2018 17:55:12 -0500
    Ready:          False
Conditions:
  Type           Status
  Initialized    True 
  Ready          False 
  PodScheduled   True 

Interessant ist der Zustand und Bereit für den initContainer (Terminated, Completed, Ready=True) und den Haupt-App-Container (Terminated, Completed, Ready=False). Das scheint den übertriebenen Pod-Ready-Zustand von False zu steuern – meiner Meinung nach falsch. Dies führt dazu, dass dieser Pod in unseren Dashboards als Problem gemeldet wird.

Ich habe einen anderen Kunden, der dieses Problem speziell mit dem Cloud SQL-Proxy hat. Sie möchten ihn nicht als persistenten Dienst ausführen müssen, damit Cron-Jobs auf Cloud SQL zugreifen können.

@yuriatgoogle Die einfachste Lösung ist immer noch Bash und emptyDir "Magic" wie: https://github.com/kubernetes/kubernetes/issues/25908#issuecomment -365924958

Es ist ein Hack, aber es muss reichen. Keine Beleidigung für @phidah.

Es scheint definitiv, dass viele Leute dies aus verschiedenen Gründen wollen. Eine offizielle Unterstützung wäre gut. Ich hatte das gleiche Problem mit unserem eigenen Sidecar und unseren Jobs, also ließ ich den Sidecar die Kube-API verwenden, um den Status des anderen Containers im Pod zu überwachen. Wenn er mit completed endete, würde der Sidecar 0 verlassen, wenn Es hat einen Fehler beim Sidecar beim Verlassen von 1 gegeben. Vielleicht nicht die eleganteste Lösung, aber es hat den Trick gemacht, ohne dass unsere Entwickler viel ändern mussten. Code ist hier, wenn jemand interessiert ist: https://github.com/uswitch/vault-creds/blob/master/cmd/main.go#L132.

Das erinnert mich an einen Gorillaz-Song M1 A1...

Hallo? Hallooooooo? Ist jemand da?

Ja, lass uns bitte etwas Traktion bekommen +1

Die vorgeschlagenen Lösungen, die vorgelagerte Änderungen erfordern, sind:

  1. sidecar: true von @jmillikin-stripe
  2. Zusätzliche Lifecycle-Hooks von @msperl
  3. jobCompletedWith von @jpalomaki

Temporäre Lösung für Sidecar, eine hackige (aber funktioniert):

  1. Für cloudsql-proxy Sidecar von @phidah

Ich würde gerne die Antwort des Kubernetes-Maintainers zu den vorgeschlagenen Lösungen sehen und uns bitte eine Empfehlung geben, wie dieser Anwendungsfall mit der vorhandenen Kubernetes-Version gelöst werden kann. Danke!

Habe gerade diesen Thread entdeckt, nachdem ich einen Tag damit verbracht hatte, einen Log-Agenten zu schreiben, der die stdout / stderr meiner Rendering-Aufgabe in eine Datenbank hochlädt, nur um festzustellen, dass die Anwesenheit des Agenten im Pod bedeuten würde, dass der Job nie beendet würde.

Von den oben gegebenen Vorschlägen gefällt mir der "Sidecar: true" am besten, da er einfach und auf den Punkt gebracht ist - für einen Entwickler wie mich sehr verständlich. Ich würde es wahrscheinlich etwas anders nennen, da 'Sidecar' wirklich ein Pod-Designmuster ist, das für mehr als nur Jobs gilt und andere Dinge als die Fertigstellungsanforderungen impliziert. Wenn Sie meinen Fahrradabwurf entschuldigen würden, würde ich ihn wahrscheinlich so etwas wie 'ambient: true' nennen, um anzuzeigen, dass der Job als abgeschlossen betrachtet werden kann, auch wenn diese Aufgabe noch ausgeführt wird. Andere Wörter könnten „zusätzlich“ oder „unterstützend“ sein.

Ich bin auch auf dieses Problem gestoßen, für denselben Workflow, den viele andere beschrieben haben (ein Sidecar-Container, der zum Proxying von Verbindungen oder zum Sammeln von Metriken verwendet wird und keinen Zweck hat, nachdem der andere Container im Pod erfolgreich beendet wurde).

Ein früherer Vorschlag war, einige Container als "Abschluss"-Container zu bezeichnen. Ich möchte das Gegenteil vorschlagen - die Möglichkeit, einige Container als "Beiwagen" zu kennzeichnen. Wenn der letzte Container ohne Sidecar in einem Pod endet, sollte der Pod TERM an die Sidecars senden.

Das ist auch meine Ideallösung. Ich könnte SIGHUP anstelle von SIGTERM vorschlagen - dies scheint genau der Anwendungsfall zu sein, für den die Semantik von SIGHUP relevant ist! - Aber ich wäre mit beiden zufrieden.

So wie es ist, erfordert das Ausführen von Jobs auf Kubernetes entweder das manuelle Patchen von Upstream-Container-Images, um die Kubernetes-spezifische Intercontainer-Kommunikation zu verarbeiten, wenn der Nicht-Sidecar-Container fertig ist, oder das manuelle Eingreifen, um den Sidecar für jeden Job zu beenden, damit der Zombie-Pod dies nicht tut rumhängen. Beides ist nicht besonders angenehm.

Ich wäre bereit, dafür einen Patch zu erstellen, hätte jedoch gerne eine Anleitung von @kubernetes/sig-apps-feature-requests, bevor ich mich mit Code befasse. Sind wir damit einverstanden, der Pod-Spezifikation ein sidecar Feld hinzuzufügen, damit dies funktioniert? Ich zögere, Änderungen an der Pod-Spezifikation vorzunehmen, ohne sicher zu sein, dass wir dies wollen. Vielleicht verwenden Sie jetzt Anmerkungen?

@andrewsykim Ich einiger Zeit (bin nur nicht dazu gekommen, es selbst anzugehen), aber ich würde vorschlagen, vorerst nur Anmerkungen zu verwenden.

Meine Überlegung ist folgende:

  • Dieses Problem besteht seit fast 2 Jahren und hat nicht wirklich viel Aufmerksamkeit vom Kubernetes-Kern auf sich gezogen. Wenn wir also warten, bis wir Änderungen an der Pod-Spezifikation vornehmen oder auf eine direkte Eingabe warten, werden wir wahrscheinlich lange warten.
  • Eine praktikable PR ist viel einfacher, Aufmerksamkeit zu erregen als ein altes Thema.
  • Es sollte ziemlich jedem sein, einen Annotation-Ansatz zu ändern, um in Zukunft ein Pod-Attribut zu verwenden

Die Gedanken?

Hallo, ich habe mit einigen der sig-apps-Leute von kubecon über dieses Problem gesprochen. Im Grunde ist es nicht etwas, das auf ihrer unmittelbaren Roadmap steht, aber es ist etwas, das ihrer Meinung nach ein gültiger Anwendungsfall ist. Sie sind sehr offen für jemanden aus der Community, der sich damit befasst.

Ich habe einen PR für einen Verbesserungsvorschlag erstellt, um dies zu lösen, also hoffe ich, dass dies zu Diskussionen führt https://github.com/kubernetes/community/pull/2148.

Danke, dass du das zusammengestellt hast @Joseph-Irving! Es scheint, als müssten dafür noch mehr Details geklärt werden, also halte ich bis dahin alle Arbeiten zurück :)

hartnäckiges-langfristiges-Problem :(

cc @ kow3ns @janetkuo

Ohne die Sache noch weiter verkomplizieren zu wollen, wäre es auch nützlich, neben initContainers einen Container im "Sidecar"-Stil ausführen zu können.

Mein Anwendungsfall ist ähnlich wie bei den Leuten hier, ich muss einen Cloud-SQL-Proxy gleichzeitig mit einem initContainer ausführen, der Datenbankmigrationen ausführt. Da initContainer einzeln ausgeführt werden, sehe ich keine Möglichkeit, dies zu tun, außer den Proxy als Bereitstellung + Dienst auszuführen, aber ich gehe davon aus, dass es andere Anwendungsfälle (Protokollverwaltung usw.) gibt, in denen dies keine geeignete Arbeit wäre um herum.

@mcfedr Es gibt einen einigermaßen aktiven Verbesserungsvorschlag, der diese Beobachtung in Bezug auf das Verhalten von Init-Containern zu schätzen weiß. Es ist mir unklar, ob dies in den Anwendungsbereich dieses Vorschlags oder eine damit zusammenhängende Verbesserung fällt, aber ich denke, es ist ausreichend verwandt, dass es sinnvoll ist, es in Erwägung zu ziehen.

Ungeachtet potenzieller Implementierungs-/Kompatibilitätsprobleme wäre Ihr ideales Modell vermutlich, dass Sidecar-Init-Container gleichzeitig mit Nicht-Sidecar-Init-Containern ausgeführt werden, die weiterhin sequentiell wie jetzt ausgeführt werden, und dass die Sidecars vor dem Starten der Hauptsequenz-Container beendet werden?

für seinen Wert möchte ich auch die Notwendigkeit zum Ausdruck bringen, Sidecars zu ignorieren, die noch laufen, wie CloudSQL Proxy et.al.

Ich habe es geschafft, den Cloudsql-Container nach 30 Sekunden zu beenden, da ich weiß, dass mein Skript nicht so lange dauern würde. Hier ist mein Ansatz:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: schedule
spec:
  concurrencyPolicy: Forbid
  schedule: "*/10 * * * *"
  startingDeadlineSeconds: 40
  jobTemplate:
    spec:
      completions: 1
      template:
        spec:
          containers:
          - image: someimage
            name: imagename
            args:
            - php
            - /var/www/html/artisan
            - schedule:run
          - command: ["sh", "-c"]
            args:
            - /cloud_sql_proxy -instances=cloudsql_instance=tcp:3306 -credential_file=some_secret_file.json & pid=$! && (sleep 30 && kill -9 $pid 2>/dev/null)
            image: gcr.io/cloudsql-docker/gce-proxy:1.11
            imagePullPolicy: IfNotPresent
            name: cloudsql
            resources: {}
            volumeMounts:
            - mountPath: /secrets/cloudsql
              name: secretname
              readOnly: true
          restartPolicy: OnFailure
          volumes:
          - name: secretname
            secret:
              defaultMode: 420
              secretName: secretname

Und bei mir funktioniert es.
Sehen Sie einen Nachteil in diesem Ansatz?

Da ich denke, dass sie auch für CronJobs verwandt und leicht anpassbar sind, ist dies meine Lösung: https://github.com/GoogleCloudPlatform/cloudsql-proxy/issues/128#issuecomment -413444029

Es basiert auf einer der hier geposteten Problemumgehungen, verwendet jedoch preStop da es für Bereitstellungen gedacht ist. Das Einfangen des Beiwagens würde wunderbar funktionieren.

Im Anschluss an dieses Problem. Auch cloud_sql_proxy-Container als Sidecar in Cronjob verwenden
Ich habe die Timeout- Implementierung von @stiko verwendet

Das einfache Hinzufügen der von vorerst eine anständige

https://github.com/kubernetes/kubernetes/issues/25908#issuecomment -327396198

Wir haben diese KEP vorläufig genehmigt https://github.com/kubernetes/community/pull/2148 , wir müssen uns noch über ein paar Dinge einigen, aber hoffentlich wird es so weit kommen, dass die Arbeiten relativ bald beginnen können . Beachten Sie, dass KEPs am 30. nach https://github.com/kubernetes/enhancements verschoben werden. Wenn Sie also mitmachen möchten, wird es dort drüben sein.

Bis der Sidecar-Support eintrifft, können Sie eine Docker-Level-Lösung verwenden, die später leicht entfernt werden kann: https://gist.github.com/janosroden/78725e3f846763aa3a660a6b2116c7da

Es verwendet einen privilegierten Container mit einem gemounteten Docker-Socket und Standard-Kubernetes-Labels, um Container im Job zu verwalten.

Wir hatten das gleiche Problem mit Istio und seinem Beiwagen, und wir haben uns entschieden, den Pod über curl + preStop-Hook wie folgt zu löschen

Geben Sie Ihrem Job eine minimale RBAC-Regel wie diese

apiVersion: v1
kind: ServiceAccount
metadata:
  name: myservice-job
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: myservice-role
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["delete"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: myservice-job-rolebinding
subjects:
  - kind: ServiceAccount
    name: myservice-job
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: myservice-role

und POD_NAME und POD_NAMESPACE zu deinem ENV so

   env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace

und schließlich fügen Sie einen PreStop-Hook hinzu, wie

 lifecycle:
      preStop:
        exec:
          command: 
            - "/bin/bash" 
            - "-c"
            - "curl -X DELETE -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://$KUBERNETES_SERVICE_HOST/api/v1/namespaces/$POD_NAMESPACE/pods/$POD_NAME?gracePeriodSeconds=1"

Etwas chaotisch, aber ein bisschen sicherer und weniger fies als der Versuch, den richtigen Docker-Container zu töten.

Ich habe das nur hier reingeworfen, aber ich habe vor einiger Zeit einen Controller zusammengestellt, der laufende Pod-Änderungen überwachen und ein SIGTERM entsprechend an Sidecar-Container senden sollte. Es ist definitiv nicht das robusteste, und ehrlich gesagt habe ich es schon eine Weile nicht mehr benutzt, aber es kann hilfreich sein.

https://github.com/nrmitchi/k8s-controller-sidecars

Vielen Dank an @jpalomaki unter https://github.com/kubernetes/kubernetes/issues/25908#issuecomment -371469801 für den Vorschlag, cloud_sql_proxy als Bereitstellung mit dem Dienst ClusterIP auszuführen, und an @ cvallance unter https://github.com/kubernetes/kubernetes/issues/25908#issuecomment -364255363 für den Tipp zum Setzen von tcp:0.0.0.0 im cloud_sql_proxy instances Parameter, um nicht zuzulassen -lokale Verbindungen zum Prozess. Zusammen haben sie es problemlos geschafft, Cron-Jobs den Proxy verwenden zu lassen.

Langzeit-Problem (Notiz an sich selbst)

Gleicher Fehler. Auf der Suche nach einem Weg oder einer offiziellen Dokumentation zur Verwendung des GKE Cronjobs mit Cloud SQL

Randnotiz:
Google hat seine Cloud SQL -> Connecting from Google Kubernetes Engine- Dokumentation aktualisiert. Zusätzlich zu Connecting using the Cloud SQL Proxy Docker image Sie jetzt Connecting using a private IP address
Wenn Sie also aus dem gleichen Grund hier sind (wegen des cloud_sql_proxy), können Sie jetzt die neue Funktion von Private IP nutzen

Randnotiz:
Google hat seine Cloud SQL -> Connecting from Google Kubernetes Engine- Dokumentation aktualisiert. Zusätzlich zu Connecting using the Cloud SQL Proxy Docker image Sie jetzt Connecting using a private IP address
Wenn Sie also aus dem gleichen Grund hier sind (wegen des cloud_sql_proxy), können Sie jetzt die neue Funktion von Private IP nutzen

Die private IP-Funktion muss anscheinend den gesamten Cluster löschen und einen neu erstellen........?

@cropse Dies ist nur erforderlich, wenn Ihr Cluster nicht VPC-nativ ist.

Ich habe eine Problemumgehung für dieses Problem gemacht, nicht die großartige Lösung, aber sie hat funktioniert. Ich hoffe, dass diese Hilfe vor dem Hinzufügen der Funktion hilft, und VPC ist eine Möglichkeit, um langsamer zu werden, aber das Löschen des gesamten Clusters ist immer noch schmerzhaft.

Nur um meine zwei Cent hinzuzufügen: Rudertests werden auch abgebrochen, wenn die Injektion von istio-Sidecar auftritt, da die Kapsel nie abgeschlossen wird.

@dansiviter Sie können meinen Workaround überprüfen, den ich bereits in meinem Projekt mit helm getestet habe.

Ich freue mich darauf, dies umgesetzt zu sehen! :)

Wir haben das gleiche Problem mit normalen Jobs, wenn ein Istio-Proxy injiziert wird. Darüber hinaus wollen wir dies auch, weil wir CI-Jobs mit Prow ausführen möchten.
zB Rails App Container + Sidecar Datenbank Container zu Testzwecken.

@cropse Danke. Ich habe es nicht ausprobiert, da wir dies für alle Tests konfigurieren müssen. Wir lassen nur zu, dass der Pod (Helmtests erlauben Job leider nicht) fehlschlägt und verlassen uns darauf, das Protokoll manuell zu überprüfen, bis dieses Problem langfristig behoben ist. Es wird jedoch auch für andere Jobs zu einem Problem, sodass wir diese Position möglicherweise überdenken müssen.

Zu Ihrer Information, das Tracking-Problem für diese Funktion ist hier https://github.com/kubernetes/enhancements/issues/753 Wenn die Leute mitmachen möchten, haben wir ein KEP, haben einige Prototypen erstellt (es gibt einen POC-Zweig/Video ) müssen noch einige Implementierungsdetails ausgebügelt werden, bevor es in einen implementierbaren Zustand gebracht wird.

Randnotiz:
Google hat seine Cloud SQL -> Connecting from Google Kubernetes Engine- Dokumentation aktualisiert. Zusätzlich zu Connecting using the Cloud SQL Proxy Docker image Sie jetzt Connecting using a private IP address
Wenn Sie also aus dem gleichen Grund hier sind (wegen des cloud_sql_proxy), können Sie jetzt die neue Funktion von Private IP nutzen

Ich war aus dem gleichen Grund hier, unsere Cloud SQL wurde jedoch bereitgestellt, bevor diese Funktion bereit war. Ich habe frühere Vorschläge kombiniert und dies (wahrscheinlich nicht ideal, aber es funktioniert) für mein dbmate Migrator-Helmdiagramm herausgebracht.

      containers:
      - name: migrator
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        command: ["/bin/bash", "-c"]
        args:
          - |
            /cloud_sql_proxy -instances={{ .Values.gcp.project }}:{{ .Values.gcp.region }}:{{ .Values.gcp.cloudsql_database }}=tcp:5432 -credential_file=/secrets/cloudsql/credentials.json &
            ensure_proxy_is_up.sh dbmate up
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: DATABASE_URL
        volumeMounts:
          - name: cloudsql-instance-credentials
            mountPath: /secrets/cloudsql
            readOnly: true
      volumes:
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials

ensure_proxy_is_up.sh

#!/bin/bash

until pg_isready -d $(echo $DATABASE_URL); do
    sleep 1
done

# run the command that was passed in
exec "$@"

Wäre es an der Zeit, Sidecar-Container in Kubernetes zu entwickeln und Pod-Bereinigungen zuzulassen, je nachdem, ob Container ohne Sidecar fertig sind?

@ Willux Ich telefoniere mit meinem vollem Gange.

@krancour danke für das Update. Dieses Detail muss mir entgangen sein. In letzter Zeit war hier nicht viel los, also wollte ich nur sicherstellen, dass etwas im Gange ist :)

Als Referenz habe ich eine Cloud-sql-proxy-Sidecar-Version der Problemumgehung von @jmillikin-stripe erstellt, bei der eine Datei in einem freigegebenen Volume den Status an den Sidecar übermittelt.

Es funktioniert OK, ist aber bei weitem der gemeinste Hack in meiner K8s-Konfiguration :(

apiVersion: batch/v1
kind: Job
metadata:
  name: example-job
spec:
  template:
    spec:
      containers:
      - name: example-job
        image: eu.gcr.io/example/example-job:latest
        command: ["/bin/sh", "-c"]
        args:
          - |
            trap "touch /tmp/pod/main-terminated" EXIT
            run-job.sh
        volumeMounts:
          - mountPath: /tmp/pod
            name: tmp-pod
      - name: cloudsql-proxy
        image: gcr.io/cloudsql-docker/gce-proxy:1.11
        command: ["/bin/sh", "-c"]
        args:
          - |
            /cloud_sql_proxy --dir=/cloudsql -instances=example:europe-west3:example=tcp:3306 -credential_file=/secrets/cloudsql/credentials.json &
            CHILD_PID=$!
            (while true; do if [[ -f "/tmp/pod/main-terminated" ]]; then kill $CHILD_PID; echo "Killed $CHILD_PID as the main container terminated."; fi; sleep 1; done) &
            wait $CHILD_PID
            if [[ -f "/tmp/pod/main-terminated" ]]; then exit 0; echo "Job completed. Exiting..."; fi
        volumeMounts:
          - name: cloudsql-instance-credentials
            mountPath: /secrets/cloudsql
            readOnly: true
          - name: cloudsql
            mountPath: /cloudsql
          - mountPath: /tmp/pod
            name: tmp-pod
            readOnly: true
      restartPolicy: Never
      volumes:
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials
        - name: cloudsql
          emptyDir:
        - name: tmp-pod
          emptyDir: {}
  backoffLimit: 1

Kann sich jemand innerhalb des Projekts bitte zum Fortschritt dieses Problems äußern?

Kann man davon ausgehen, dass dies die beste Option für diejenigen von uns ist, die am stabilen Release-Kanal von GKE arbeiten, der Kubernetes 1.18 wahrscheinlich zumindest in einigen Monaten nicht einholen wird?

@Datamance zu diesem Zeitpunkt sieht der KEP zur Behebung dieses Problems so ausgesetzt ist .

Ich habe vor einiger Zeit diesen Kommentar gepostet, der meine alte Lösung war. Ich versuche nicht, meine eigenen Sachen hier zu veröffentlichen, nur dieser Kommentar ist in den "100 weiteren Kommentaren ..." von github verloren gegangen und dachte, es könnte wieder nützlich sein, ihn wieder aufzutauchen.

@nrmitchi danke für die erneute Veröffentlichung. Ich habe es in der Flut von Kommentaren übersehen und dies sieht nach einer fantastischen kurzfristigen Lösung aus.

Wir finden einen anderen Ansatz, wenn Sie Ihren Pod-Containern Folgendes hinzufügen:

    securityContext:
            capabilities:
                   add:
                    - SYS_PTRACE

dann können Sie das Pid in anderen Containern grepen, wir werden am Ende unseres Hauptcontainers Folgendes ausführen:
sql_proxy_pid=$(pgrep cloud_sql_proxy) && kill -INT $sql_proxy_pid

@krancour froh, dass es geholfen hat. Wenn Sie sich das Netzwerk in diesem Repository ansehen, gibt es ein paar Forks, die fast definitiv an einem besseren Ort sind als mein Original und möglicherweise besser zu bauen/zu verwenden sind.

IIRC, die Limonaden- Hq

@nrmitchi , ich habe mir den Code angeschaut, aber es ist vielleicht schneller, Sie einfach zu fragen ...

Können Sie kurz etwas zu den Voraussetzungen sagen, die in der README nicht erwähnt werden?

Erfordern beispielsweise die Bilder, auf denen Ihre Sidecars basieren, ein besonderes Bewusstsein für diese Problemumgehung? zB Müssen sie an einem bestimmten Port auf ein Signal vom Controller lauschen? Oder müssen sie vielleicht eine bestimmte Shell (Bash?)

@krancour Ich werde meine Antwort mit dem Hinweis

Es war damals so konzipiert, dass die fraglichen Container den Workaround nicht kennen mussten. Wir haben hauptsächlich Anwendungen von Drittanbietern in Sidecar verwendet (zum Beispiel glaube ich, dass Stripe/Veneur einer war) und wollten keine Forking/Modifikation

Die einzige Anforderung an die Beiwagen besteht darin, dass sie ordnungsgemäß auf ein SIGTERM-Signal hören und dann abschalten. Ich erinnere mich, dass ich einige Probleme mit Code von Drittanbietern hatte, der in Sidecars ausgeführt wurde, die ein anderes Signal erwarteten und umgangen werden mussten, aber der Controller hätte eigentlich nur zulassen sollen, dass das gesendete Signal angegeben wird (dh SIGINT statt SIGTERM).

Sie müssen keine Ports auf ein Signal abhören, da der Controller ein exec , um den Hauptprozess des Sidecars direkt zu signalisieren. IIRC zu dem Zeitpunkt, als die Funktionalität aus dem Kubernetes-Code kopiert wurde, da sie im Client nicht vorhanden war. Ich glaube, dass dies jetzt im offiziellen Client vorhanden ist und wahrscheinlich aktualisiert werden sollte.

Wir finden einen anderen Ansatz, wenn Sie Ihren Pod-Containern Folgendes hinzufügen:

    securityContext:
            capabilities:
                   add:
                    - SYS_PTRACE

dann können Sie das Pid in anderen Containern grepen, wir werden am Ende unseres Hauptcontainers Folgendes ausführen:
sql_proxy_pid=$(pgrep cloud_sql_proxy) && kill -INT $sql_proxy_pid

@ruiyang2015 danke für diesen Hack.
Wenn es jedoch jemand implementiert, sollten Sie die Auswirkungen der gemeinsamen Nutzung einer Prozess-ns zwischen den Containern verstehen

@nrmitchi

verwendet einen Exec, um den Hauptprozess des Sidecars direkt zu signalisieren

Das ist einer der Gründe, warum ich gefragt habe ... Ich frage mich, ob dies nicht für Container funktioniert, die auf Images basieren, die FROM scratch .

@krancour Fairer Punkt, ich habe es nie mit Containern getestet, die von scratch . Wenn man sich den Code ansieht (oder meine ursprüngliche Version; dies könnte sich in gegabelt geändert haben), bash abhängig sein, sollte aber in der Lage sein, geändert zu werden.

es wird von bash abhängig sein, sollte aber modifiziert werden können

Sicher, aber solange es ausgeführt wird, wird es immer von einer Binärdatei abhängen, die im Container vorhanden ist, und für einen Scratch-Container gibt es _nichts_ außer dem, was Sie dort explizit eingeben. 🤷♂.

Angesichts dieser Einschränkung kann ich dies nicht für einen Anwendungsfall verwenden, bei dem die ausgeführten Container möglicherweise völlig willkürlich sind und von einem Dritten angegeben werden. Oh-- und dann habe ich auch Windows-Container im Spiel.

Ich werde erwähnen, worauf ich mich stattdessen festlegen werde. Es ist wahrscheinlich zu schwerfällig für die meisten Anwendungsfälle, aber ich erwähne es für den Fall, dass der Anwendungsfall von jemand anderem meinem ähnlich genug ist, um damit durchzukommen ...

Ich kann mir den Luxus leisten, einfach einen Pod zu _löschen_, dessen "primärer" Container beendet wurde, solange ich zuerst den Exit-Status aufzeichne. Also werde ich am Ende einen Controller schreiben, der einen bestimmten (über Anmerkungen) Container auf Abschluss überwacht, seinen Erfolg oder Misserfolg in einem Datenspeicher aufzeichnet, der bereits den "Auftragsstatus" verfolgt, und dann den Pod vollständig löscht.

Zur Sicherheit werde ich das Löschen des Pods wahrscheinlich etwas verzögern, um die Chancen meiner zentralen Log-Aggregation zu maximieren, die letzten paar Zeilen der Ausgabe des primären Containers zu erhalten, bevor er torpediert wird.

Schwerfällig, kann aber für einige funktionieren.

@krancour Absolut wahr. So wie es ist, funktioniert der Controller nicht für beliebige Anwendungsbasen. Ehrlich gesagt bin ich nie zurückgegangen und habe versucht, einige der Implementierungen zu abstrahieren, um andere Fälle zu unterstützen, weil ich wirklich dachte, dass das zuvor erwähnte KEP zusammengeführt worden wäre und die Notwendigkeit dieser Funktionalität gegenstandslos gemacht worden wäre.

Da dieses Problem ungefähr 4 Jahre alt ist, der KEP noch nirgendwo hingegangen ist und der Stand der Technik ein hackiges Inline-Shell-Skript ist, das jeden Einstiegspunkt ersetzt, habe ich beschlossen, den „Standard“-Hack zu kodifizieren (Grabsteine ​​in einem gemeinsamen Volume ) in eine Go-Binärdatei, die mithilfe eines mehrstufigen Builds einfach in Container-Images integriert werden kann.

https://github.com/karlkfi/kubexit

Es gibt mehrere Möglichkeiten, es zu verwenden:

  1. Backe es in deine Bilder ein
  2. Laden Sie es seitlich mit einem Init-Container und einem ephemeren Volumen.
  3. Stellen Sie es auf jedem Knoten bereit und laden Sie es mithilfe eines Host-Bind-Mounts seitlich in Container

Edit: v0.2.0 unterstützt jetzt „Geburtsabhängigkeiten“ (verzögerter Start) und „Todesabhängigkeiten“ (Selbstbeendigung).

Drive-by-Kommentar: Das sieht genauso aus wie https://github.com/kubernetes/enhancements/issues/753

@vanzin Wie bereits erwähnt , ist KEP auf unbestimmte Zeit ausgesetzt .

Mein Anwendungsfall dafür ist, dass Vault Anmeldeinformationen für die Ausführung eines CronJobs bereitstellt. Sobald die Aufgabe erledigt ist, wird das Vault-Sidecar immer noch mit dem Job in einem ausstehenden Status ausgeführt, und dies veranlasst das Überwachungssystem, zu denken, dass etwas nicht stimmt. Es ist eine Schande, was mit der KEP passiert ist.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen