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:
/tmp/assets
auf dem Knoten vorhanden ist, ist er leer/app/<app-name>/public
im App-Container ist ebenfalls leerAls 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"}
[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.
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: {}
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?
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. 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
Kubernetes hat eigene Volume-Typen, und diese sind am häufigsten verwendeten Volume-Typen:
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.
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.
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.