wake-up-neo.com

Wie man '--volumes-from' in Kubernetes nachahmt

Ich suche nach einem Muster, mit dem Volumes zwischen zwei Containern gemeinsam genutzt werden können, die in Kubernetes auf demselben Pod ausgeführt werden.

Mein Anwendungsfall ist: Ich habe eine Ruby on Rails-Anwendung, die in einem Docker-Container ausgeführt wird . Das Docker-Image enthält statische Assets im /app/<app-name>/public-Verzeichnis, und ich muss auf diese Assets über den Nginx-Container zugreifen, der im selben Verzeichnis läuft pod.

In 'Vanilla' Docker hätte ich --volumes-from flag benutzt, um dieses Verzeichnis zu teilen:

docker run --name app -v /app/<app-dir>/public <app-image>
docker run --volumes-from app nginx

Nach dem Lesen dieses Dokuments: https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/volumes.md .__ habe ich Folgendes versucht (nur relevante Einträge werden angezeigt):

spec:
  containers:
    - image: <app-image>
      name: <app-name>
      volumeMounts:
        - mountPath: /app/<app-name>/public
          name: assets
    - image: nginx
      name: nginx
      volumeMounts:
        - mountPath: /var/www/html
          name: assets
          readOnly: true
    volumes:
      - name: assets
        hostPath:
          path: /tmp/assets

Aber:

  • Obwohl /tmp/assets auf dem Knoten vorhanden ist, ist er leer
  • /app/<app-name>/public im App-Container ist ebenfalls leer

Als Problemumgehung versuche ich, das freigegebene Verzeichnis aufzufüllen, wenn der Anwendungscontainer aktiv ist (einfach cp /app/<app-name>/public/* zum freigegebenen Verzeichnis), aber diese Vorstellung gefällt mir nicht.

Frage: wie man --volumes-from in Kubernetes nachahmt, oder wenn es kein direktes Gegenstück gibt, wie kann ich Dateien von einem Container zu einem anderen Container teilen, der in demselben Pod läuft?

apiVersion: v1beta3

Client Version: version.Info{Major:"0", Minor:"17", GitVersion:"v0.17.0", GitCommit:"82f8bdac06ddfacf493a9ed0fedc85f5ea62ebd5", GitTreeState:"clean"}
Server Version: version.Info{Major:"0", Minor:"17", GitVersion:"v0.17.0", GitCommit:"82f8bdac06ddfacf493a9ed0fedc85f5ea62ebd5", GitTreeState:"clean"}
40
cthulhu

[update-2016-8] In der neuesten Version von Kubernetes können Sie eine sehr schöne Funktion namens init-container verwenden, um den postStart-Teil in meiner Antwort unten zu ersetzen.

enter image description here

NOTE: initContainer ist immer noch eine beta-Funktion. Die Arbeitsversion dieses yaml sieht also wie folgt aus: http://kubernetes.io/docs/user-guide/production-pods/ # handling-initialization , beachten Sie den pod.beta.kubernetes.io/init-containers-Teil.

--- ursprüngliche Antwort beginnt ---

Eigentlich kannst du. Sie müssen den Container-Lebenszyklus-Handler verwenden, um zu steuern, welche Dateien/Verzeichnisse Sie für andere Container freigeben möchten. Mögen:

---
apiVersion: v1
kind: Pod
metadata:
    name: server
spec:
    restartPolicy: OnFailure
    containers:
    - image: resouer/sample:v2
      name: war
      lifecycle:
        postStart:
          exec:
            command:
              - "cp"
              - "/sample.war"
              - "/app"
      volumeMounts:
      - mountPath: /app
        name: hostv1 
    - name: peer
      image: busybox
      command: ["tail", "-f", "/dev/null"]
      volumeMounts:
      - name: hostv2
        mountPath: /app/sample.war
    volumes:
    - name: hostv1
      hostPath:
          path: /tmp
    - name: hostv2
      hostPath:
          path: /tmp/sample.war

Bitte überprüfen Sie meine Gist für weitere Details:

https://Gist.github.com/resouer/378bcdaef1d9601ed6aa

Und natürlich können Sie emptyDir verwenden. Daher kann der Kriegscontainer seine /sample.war für den Peer-Container ohne das App-Verzeichnis des Peer-Peers freigeben.

Wenn wir tolerieren können, dass die App außer Kraft gesetzt wurde, wird es viel einfacher sein:

---
apiVersion: v1
kind: Pod
metadata:
  name: javaweb-2
spec:
  restartPolicy: OnFailure
  containers:
  - image: resouer/sample:v2
    name: war
    lifecycle:
      postStart:
        exec:
          command:
            - "cp"
            - "/sample.war"
            - "/app"
    volumeMounts:
    - mountPath: /app
      name: app-volume
  - image: resouer/mytomcat:7.0
    name: Tomcat
    command: ["sh","-c","/root/Apache-Tomcat-7.0.42-v2/bin/start.sh"]
    volumeMounts:
    - mountPath: /root/Apache-Tomcat-7.0.42-v2/webapps
      name: app-volume
    ports:
    - containerPort: 8080
      hostPort: 8001 
  volumes:
  - name: app-volume
    emptyDir: {}
34
harryz

Die Antwort ist - jetzt können Sie nicht. Hier sind ein paar Diskussionsfäden aus den Kubernetes-Ausgaben:

Kann ich jedoch vorschlagen, dass Sie ein alternatives Design haben, das möglicherweise besser funktioniert? 

  1. Wenn Ihre Assets zu dem Zeitpunkt gesperrt sind, an dem der Container live geschaltet wird, könnten Sie gitRepo Volume verwenden, das es zum Zeitpunkt der live-Aktivierung in eine emptyDir kopiert Verschieben Sie den Inhalt um all, laden Sie ihn einfach direkt in das freigegebene Verzeichnis herunter. 
  2. Wenn Ihre Assets an der Stelle des Containers, der gerade erstellt wird, gesperrt sind, empfiehlt es sich, sie zu diesem Zeitpunkt mit dem Docker COPY-Befehl Zu kopieren.
  3. Wenn Sie wirklich bei der Vorgehensweise bleiben möchten, müssen Sie den Inhalt auf das Volume emptyDir kopieren, das genau für das bestimmt ist, wonach Sie suchen (abzüglich der Tatsache, dass Sie es nicht kopieren müssen).

NFS [1] -Datenträger könnten auch Ihr Problem lösen, sind jedoch möglicherweise zu komplex.

Außerdem würde ich empfehlen, dass diese beiden Dienste in unterschiedlichen Pods vorhanden sind, sodass Sie die Dienste separat skalieren können. Sie können einen Service-Endpunkt erstellen, um bei Bedarf zu kommunizieren.

[1] https://github.com/GoogleCloudPlatform/kubernetes/blob/master/examples/nfs/nfs-web-pod.yaml

9
aronchick

Kubernetes hat eigene Volume-Typen, und diese sind am häufigsten verwendeten Volume-Typen:

  1. emptyDir
  2. geheimnis
  3. gitRepo
  4. hostPath (ähnlich wie --volumes-from)
  5. config Maps
  6. permanenter Speicher (Speicherplatten, die von Cloud-Plattformen bereitgestellt werden)

Weitere Informationen zu den Volumes von kubernets finden Sie hier - https://kubernetes.io/docs/concepts/storage/volumes/

ein Beispiel für ein Hostpfad-Volume:

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on Host
      path: /data
      # this field is optional
      type: Directory

hostpath mounten das Host/node-Verzeichnis in das Containerverzeichnis. Mehrere Container in einem Pod können unterschiedliche oder dieselben Volumes verwenden. Sie müssen es in jedem Container angeben. _ pod, sollten Sie HostPath vermeiden.

1
shubham_asati

Weiteres Update vom future:

Es gibt jetzt ein FlexVol-Plugin für Docker-Volumes: https://github.com/dims/docker-flexvol

Zum Zeitpunkt des Schreibens ist FlexVol jedoch immer noch ein Alpha-Feature, so die Einschränkung des Problems.

1
coderanger

Wenn Sie Docker v17.0.5 oder höher verwenden, können Sie einen mehrstufigen Build verwenden, um Dateien von einem Ihrer Container in den anderen Container zu kopieren. Dies ist eine großartige Einführung in die erweiterten Funktionen unter https://medium.com/@tonistiigi/advanced-multi-stage-build-patterns-6f741b852fae

So habe ich statische Assets aus meinem Backend-Container in den Nginx-Proxy kopiert

ARG API_BACKEND_CONTAINER="api:backend"
FROM $API_BACKEND_CONTAINER as source

FROM nginx:mainline-Alpine

ARG NGINX_ROOT=/usr/share/nginx/html/
COPY --from=source  /var/share/api/static/ ${NGINX_ROOT}

Das Tolle daran ist, dass API_BACKEND_CONTAINER ein Build-Argument ist, das ich im Tag des neuesten API-Builds übergeben kann.

0