쿠베르네테스에서 '--volumes-from'을 흉내내는 방법
쿠베르네테스에서 '--volumes-from'을 흉내내는 방법
쿠버네티스에서 같은 포드에서 실행되는 두 컨테이너 간에 볼륨을 공유할 수 있는 패턴을 찾고 있습니다.
나의 사용 사례는: 나는 도커 컨테이너 안에서 루비 온 레일즈 애플리케이션을 실행하고 있다. 도커 이미지는 디렉터리에 정적 자산을 포함하고 있으며, 나는 동일한 포드에서 함께 실행되는 nginx 컨테이너에서 해당 자산에 액세스해야 한다.
바닐라 도커에서 나는 이 디렉터리를 공유하기 위해 플래그를 사용했을 것이다:
docker run --name app -v /app/<app-dir>/public <app-image>
docker run --volumes-from app nginx
이 문서를 읽은 후: 다음을 시도했습니다(관련 항목만 제시됨):
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
그러나:
- 노드가 존재해도 비어 있습니다
- 앱 컨테이너 내부도 비어 있습니다
해결 방법으로 응용 프로그램 컨테이너가 실행 중일 때(단순히 공유 디렉터리로) 공유 디렉터리를 채우려고 하지만, 이 아이디어는 정말 싫어요.
쿠버네티스에서 모방하는 방법 또는 직접적인 대응물이 없는 경우, 동일한 포드에서 실행되는 한 컨테이너에서 다른 컨테이너로 파일을 공유하는 방법은 무엇입니까?
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"}
답은 - 지금은 - 할 수 없다는 것이다. 다음은 쿠버네티스 문제에서 나온 몇 가지 토론 스레드입니다:
- https://github.com/GoogleCloudPlatform/kubernetes/issues/6120
- https://github.com/GoogleCloudPlatform/kubernetes/issues/831
하지만, 제가 당신에게 더 잘 작동할 수 있는 다른 디자인을 제안해도 될까요?
- 컨테이너가 활성화되는 시점에 자산이 잠겨 있으면 볼륨과 같은 볼륨을 사용하여 활성화되는 시점에 컨텐츠를 복사할 수 있으며 컨텐츠를 이동할 필요가 전혀 없으며 공유 디렉토리에 직접 다운로드할 수 있습니다.
- 컨테이너가 구축되는 지점에 자산이 잠겨 있는 경우에는 Docker COPY 명령을 사용하여 해당 지점에 자산을 복사하는 것이 가장 좋습니다.
- 작업 방식을 고수하려면 컨텐츠를 볼륨에 복사해야 합니다. 볼륨은 원하는 대로 복사할 수 있습니다(복사할 필요가 없음).
NFS[1] 볼륨도 문제를 해결할 수 있지만 너무 복잡할 수 있습니다.
또한 이 두 서비스는 서로 다른 포드에 존재하므로 각각 별도로 확장할 수 있습니다. 필요한 경우 서비스 끝점을 생성하여 두 끝점 간에 통신할 수 있습니다.
[1]
최신 Kubernetes 릴리스에서는 아래 답변의 부품을 대체하기 위해 매우 좋은 기능을 사용할 수 있으며, 이 기능을 통해 컨테이너 주문이 확실해집니다.
apiVersion: v1
kind: Pod
metadata:
name: javaweb-2
spec:
initContainers:
- name: war
image: resouer/sample:v2
command: ["cp", "/sample.war", "/app"]
volumeMounts:
- mountPath: /app
name: app-volume
containers:
- name: tomcat
image: resouer/mytomcat:7.0
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: {}
: initContainer는 여전히 존재하기 때문에 이 yaml의 작업 버전은 실제로 다음과 같습니다. 부품에 주의하십시오.
---원래 대답 시작---
사실, 할 수 있어요. 다른 컨테이너와 공유할 파일/dir를 제어하려면 컨테이너 수명 주기 처리기를 사용해야 합니다. 예:
---
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
자세한 내용은 제 요지를 확인해 주십시오:
https://gist.github.com/resouer/378bcdaef1d9601ed6aa
그리고 물론 빈 Dir도 사용할 수 있습니다. 따라서 전쟁 컨테이너는 /샘플을 공유할 수 있다.messpeer의 /app 디렉토리가 없는 피어 컨테이너에 대한 워.
앱이 재정의되는 것을 허용할 수 있다면 훨씬 더 간단해질 것입니다:
---
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: {}
에서 추가 업데이트:
이제 도커 볼륨용 FlexVol 플러그인이 있습니다:
작성 당시 FlexVol은 여전히 알파 기능이므로 Emptor에 주의하십시오.
Docker v17.0.5 이상을 사용하는 경우 다단계 빌드를 사용하여 빌드 시간 동안 컨테이너 중 하나에서 다른 컨테이너로 파일을 복사할 수 있습니다. 이 제품은 의 고급 기능에 대한 훌륭한 입문서입니다
백엔드 컨테이너에서 Nginx 프록시로 정적 자산을 복사하기 위해 사용한 방법은
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}
훌륭한 점은 빌드 인수이기 때문에 최신 API 빌드의 태그를 전달할 수 있다는 것입니다.
쿠베르네테스는 고유한 볼륨 유형이 있으며 가장 많이 사용되는 볼륨 유형은 다음과 같다:
- 빈 디어
- 시크릿
- gitRepo
- hostPath( --volumes-from과 유사)
- 구성 맵
- 영구 스토리지(클라우드 플랫폼에서 제공하는 스토리지 디스크)
쿠버넷 볼륨에 대한 자세한 내용은 여기에서 확인할 수 있습니다
호스트 경로 볼륨의 예:
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가 호스트/노드 디렉토리를 컨테이너 디렉토리에 마운트합니다.포드 내부의 여러 컨테이너가 서로 다른 볼륨 또는 동일한 볼륨을 사용할 수 있습니다.당신은 각 용기에 그것을 언급해야 합니다. hostPath 볼륨은 포드 수명 주기와 독립적이지만 노드와 포드 간에 긴밀한 결합을 형성하므로 hostPath를 사용하지 않는 것이 좋습니다.
나는 방금 쿠버네츠에서 우연히 발견했고 이것이 이 사용 사례에 꽤 잘 어울릴 것이라고 생각했다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: datasharing
spec:
selector:
matchLabels:
app: datasharing
template:
metadata:
labels:
app: datasharing
spec:
shareProcessNamespace: true
containers:
- name: data
image: ubuntu
imagePullPolicy: IfNotPresent
command: ["/bin/bash", "-c"]
args: ["trap 'echo signal;exit 0' SIGINT; sleep infinity"]
resources:
limits:
memory: "128Mi"
cpu: "500m"
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- mkdir -p /DATA && touch /DATA/empty_test_file
- name: nginx
image: nginx:stable
imagePullPolicy: IfNotPresent
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 8080
env:
- name: GET_DATA_PROC_DIR
value: 'find /proc -maxdepth 1 -type d -regex "/proc/[0-9]*" | head -2 | tail -1'
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- ln -s $(eval $GET_DATA_PROC_DIR)/root/DATA /mnt/DATA
이 예제에서는 빈 파일을 넣기만 하면 되는 데이터 컨테이너가 있고, 다른 컨테이너(이 경우 nginx)가 에서 두 번째 파일을 찾아 이 디렉터리를 만듭니다.
데이터 컨테이너는 컨테이너 배열의 첫 번째이고 에 두 번째가 있어야 하므로 이 작업은 작동합니다.