본문 바로가기

개발하자

쿠베르네테스에서 '--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"}



답은 - 지금은 - 할 수 없다는 것이다. 다음은 쿠버네티스 문제에서 나온 몇 가지 토론 스레드입니다:

하지만, 제가 당신에게 더 잘 작동할 수 있는 다른 디자인을 제안해도 될까요?

  1. 컨테이너가 활성화되는 시점에 자산이 잠겨 있으면 볼륨과 같은 볼륨을 사용하여 활성화되는 시점에 컨텐츠를 복사할 수 있으며 컨텐츠를 이동할 필요가 전혀 없으며 공유 디렉토리에 직접 다운로드할 수 있습니다.
  2. 컨테이너가 구축되는 지점에 자산이 잠겨 있는 경우에는 Docker COPY 명령을 사용하여 해당 지점에 자산을 복사하는 것이 가장 좋습니다.
  3. 작업 방식을 고수하려면 컨텐츠를 볼륨에 복사해야 합니다. 볼륨은 원하는 대로 복사할 수 있습니다(복사할 필요가 없음).

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 빌드의 태그를 전달할 수 있다는 것입니다.




쿠베르네테스는 고유한 볼륨 유형이 있으며 가장 많이 사용되는 볼륨 유형은 다음과 같다:

  1. 빈 디어
  2. 시크릿
  3. gitRepo
  4. hostPath( --volumes-from과 유사)
  5. 구성 맵
  6. 영구 스토리지(클라우드 플랫폼에서 제공하는 스토리지 디스크)

쿠버넷 볼륨에 대한 자세한 내용은 여기에서 확인할 수 있습니다

호스트 경로 볼륨의 예:

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)가 에서 두 번째 파일을 찾아 이 디렉터리를 만듭니다.

데이터 컨테이너는 컨테이너 배열의 첫 번째이고 에 두 번째가 있어야 하므로 이 작업은 작동합니다.


반응형