본문 바로가기

개발하자

쿠버네티스 포드 간에 스토리지를 공유하는 방법은 무엇인가요?

반응형

쿠버네티스 포드 간에 스토리지를 공유하는 방법은 무엇인가요?

나는 쿠버네티스를 우리의 새로운 애플리케이션의 플랫폼으로 평가하고 있다. 지금은, 그것이 모두 매우 흥미로워 보입니다! 하지만, 나는 문제에 봉착했어요: 나는 GCE에서 내 클러스터를 호스팅하고 있고 나는 지속적인 통합 서버와 내 애플리케이션 서버라는 두 포드 간에 스토리지를 공유할 수 있는 메커니즘이 필요하다. 쿠버네티스로 이것을 하는 가장 좋은 방법은 무엇인가요? 하나의 포드가 디스크에 기록해야 하는 경우 GCE 디스크를 공유할 수 없기 때문에 볼륨 유형 중 어떤 것도 내 필요에 맞지 않는 것 같다. NFS는 완벽하겠지만, 쿠버네티스 클러스터를 위한 특별한 빌드 옵션이 필요한 것 같다?

편집: 스토리지 공유는 지금 쿠버네티스를 사용하면서 여러 번 직면한 문제인 것 같다. 하나의 볼륨을 가지고 여러 포드에 연결하고 싶은 여러 사용 사례가 있습니다(쓰기 액세스 권한 포함). 나는 이것이 일반적인 사용 사례가 될 것이라고 추측할 수밖에 없다, 그렇지 않니?

편집2: 예를 들어, Elastic 검색 클러스터를 설정하는 방법을 설명하지만 영구 스토리지로 연결하는 것은 불가능합니다(). 이는 약간 무의미해집니다. :(




업데이트: 최상의 선택은 관리 NFS 시스템인 Cloud Filesstore일 것입니다. 이것은 업로드/다운로드만 지원하는 GCS와는 달리 파일에 대한 완전한 랜덤 읽기/쓰기 액세스를 제공합니다. 문서를 참조하십시오.

원본: 해봤어요? 를 사용하여 네트워크 디스크처럼 매핑할 수도 있습니다.




디스크에 기록하려는 것이 로그라면 로그스팟을 확인하는 것이 좋습니다. 이것은 각 포드의 로깅을 수집하고 fluidd를 사용하는 구글 클라우드 플랫폼의 상당히 새로운 로깅 서비스를 사용할 수 있다. 이렇게 하면 각 포드의 모든 로그가 한 곳에 수집됩니다.

일반적으로 데이터베이스나 그런 성격의 데이터라면 데이터베이스를 실행하는 쿠버네티스 클러스터 외부에 별도의 서버를 두는 것을 추천한다.

편집

포드 간에 파일을 공유하려면 kubernetes 클러스터의 각 노드에 구글 클라우드 스토리지 드라이브를 마운트한 다음 드라이브가 아닌 마운트된 디렉토리에 마운트되는 각 포드에 볼륨으로 설정하는 것이 좋습니다. 각 노드에 마운트하는 것은 포드가 지정된 노드에서 실행되지 않기 때문에 좋으므로 이 경우 중앙 집중화하는 것이 가장 좋습니다.




NFS는 내장된 볼륨 플러그인으로 여러 포드 기록기를 지원합니다. NFS를 Kube에서 작동시키기 위한 특별한 빌드 옵션은 없습니다.

나는 쿠버네티스의 레드햇에서 일하고 있으며 주로 저장에 중점을 두었다.




@Marco - 메이븐 관련 질문과 관련하여 나의 조언은 이것을 중앙 집중식 스토리지 문제로 보는 것을 그만두고 아마도 서비스 문제로 생각하라는 것이다.

나는 과거에 HTTP 아래에서 메이븐 저장소를 실행한 적이 있다(읽기 전용). 나는 단순히 메이븐 레포를 만들어 해당 포드에만 필요한 전용 스토리지가 있는 자체 포드(도커 컨테이너)에서 Apache/Nginx를 통해 노출한 다음 서비스 검색을 사용하여 애플리케이션에 연결하고 시스템을 구축합니다.




먼저, 여러 명의 독자/작가가 필요합니까?

내가 Kubernetes / micro-service architecture (MSA)를 경험한 바에 따르면, 이 문제는 종종 당신의 디자인 패턴과 더 관련이 있다. MSA를 이용한 기본적인 설계 패턴 중 하나는 서비스의 적절한 캡슐화이며, 여기에는 각 서비스가 소유한 데이터가 포함된다.

OOP와 마찬가지로 서비스는 해당 영역과 관련된 데이터를 관리해야 하며 인터페이스를 통해 다른 서비스에 이 데이터에 액세스할 수 있어야 합니다. 이 인터페이스는 API, 직접 또는 중개 서비스를 통해 처리되는 메시지, 또는 프로토콜 버퍼와 gRPC를 사용하는 메시지일 수 있다. 일반적으로 데이터에 대한 다중 서비스 액세스는 OOP 및 대부분의 프로그래밍 언어에서 글로벌 변수와 유사한 안티 패턴이다.

예를 들어, 로그를 작성하려는 위치에 있는 경우 로그 서비스를 제공해야 합니다. 각 서비스는 로그에 기록해야 하는 관련 데이터를 가지고 호출할 수 있습니다. 공유 디스크에 직접 쓴다는 것은 로그 디렉터리 구조를 변경하거나 특정 유형의 오류에 대한 전자 메일 전송과 같은 추가 기능을 추가할 경우 모든 컨테이너를 업데이트해야 한다는 것을 의미합니다.

대부분의 경우 파일 시스템을 사용할 때 의도하지 않은 부작용을 피하기 위해 파일 시스템을 사용하기 전에 최소한의 인터페이스를 사용해야 합니다. 서비스 간에 적절한 인터페이스/계약이 없으면 유지보수가 가능하고 탄력적인 서비스를 구축할 수 있는 능력이 크게 저하됩니다.

네, 파일 시스템을 사용하여 상황을 해결하는 것이 상황은 파일 시스템을 사용하여 해결하는 것이 좋습니다. 여러 가지 옵션이 있습니다...

여러 개의 동시 작성자를 처리할 수 있는 파일 시스템이 더 '전통적인' MSA 통신 형태보다 우수한 솔루션을 제공할 때가 분명히 있습니다. 쿠버네티스는 발견할 수 있는 많은 볼륨 유형을 지원한다. 이 목록은 상당히 길지만, 이러한 볼륨 유형의 대부분은 여러 작성자(Kubernetes라고도 함)를 지원하지 않습니다.

지원하는 볼륨 유형은 AzureFile, CephFS, Glusterfs, Quobyte, NFS 및 PortworxVolume입니다.

강력하고 몇 가지 훌륭한 기능을 제공하는 인기 있는 것과 같은 운영자도 있지만, 간단한 해결책을 원하고 계속해서 전진할 때 그러한 시스템의 학습 곡선은 어려운 상승이 될 수 있다.

가장 간단한 방법입니다.

내 경험으로는 최고의 초기 옵션은 NFS입니다. 이것은 Kubernetes 스토리지에 대한 기본적인 아이디어를 배울 수 있는 좋은 방법이며, 대부분의 사용 사례에 도움이 되며 구현이 가장 쉽습니다. 멀티 서비스 지속성에 대한 실무 지식을 쌓은 후에는 구현에 더 많은 작업이 필요한 기능이 풍부한 제품을 사용하기 위해 더 많은 정보를 바탕으로 의사 결정을 내릴 수 있습니다.

NFS 설정에 대한 세부 사항은 클러스터가 실행되는 방법 및 위치와 NFS 서비스에 대한 세부 사항에 따라 다릅니다. 앞서 AWS NFS에 대한 NFS 설정 및 사용 방법에 대한 기사를 두 개 작성했습니다. 이 두 기사는 특정 상황에서 어떻게 다른 구현을 제공할 수 있는지에 대한 좋은 대비를 제공합니다.

최소한의 예를 들어, NFS 서비스가 먼저 필요합니다. 빠른 테스트를 수행하거나 SLO 요구 사항이 낮은 경우 Ubuntu에서 NFS를 설정하는 데 유용한 빠른 프라이머는 다음과 같습니다. NFS를 제공하고 클러스터에서 액세스할 수 있는 기존 NAS가 있는 경우에도 이 기능을 사용할 수 있습니다.

NFS 서비스를 사용하면 다음과 유사한 영구 볼륨을 생성할 수 있습니다:

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-name
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  nfs:
    server: 255.0.255.0 # IP address of your NFS service
    path: "/desired/path/in/nfs"

여기서 주의할 점은 노드에서 NFS를 사용하려면 이진 파일을 설치해야 한다는 것입니다. 이에 대해서는 기사에서 자세히 설명했습니다. 노드가 NFS에 연결할 수 없기 때문에 EKS에서 실행할 때 EFS를 사용해야 하는 이유이기도 합니다.

영구 볼륨을 설정하면 다른 볼륨처럼 사용할 수 있습니다.

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-name
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
        - name: p-name
          volumeMounts:
            - mountPath: /data
              name: v-name
      volumes:
        - name: v-name
          persistentVolumeClaim:
            claimName: pvc-name



쿠버네티스를 본 적이 있나요? agcePersistentDisk를 생성하려고 합니다

AgcePersistent Disk 볼륨은 GCE(Google Compute Engine) 영구 Disk를 포드에 마운트합니다. Pod를 제거하면 지워지는 emptyDir와 달리 PD의 콘텐츠는 보존되고 볼륨은 마운트 해제될 뿐이다. 이것은 PD가 데이터를 미리 입력할 수 있고, 데이터가 포드 간에 "핸드오프"될 수 있음을 의미합니다. 중요: gcloud 또는 GCE API 또는 UI를 사용하여 PD를 생성해야 사용할 수 있습니다. gcePersistentDisk를 사용할 때 몇 가지 제한 사항이 있습니다. 포드가 실행되는 노드는 해당 VM이 PD와 동일한 GCE 프로젝트 및 영역에 있어야 합니다. PD의 기능은 여러 사용자가 동시에 읽기 전용으로 마운트할 수 있다는 것입니다. 즉, 데이터 세트로 PD를 미리 채운 다음 필요한 만큼의 포드에서 병렬로 제공할 수 있습니다. 불행하게도 PD는 읽기-쓰기 모드에서 한 소비자만 장착할 수 있습니다. 동시 작성자는 허용되지 않습니다. Replication Controller에 의해 제어되는 포드에서 PD를 사용하는 것은 PD가 읽기 전용이거나 복제본 수가 0 또는 1이 아니면 실패합니다.

다양한 포드에서 여러 개의 쓰기를 지원하려면 디스크에서 읽기 및 디스크에 쓰기 메서드를 노출하는 알뜰 또는 소켓 유형 서비스를 노출하는 하나의 비프 포드를 만들어야 할 것입니다.




Google은 최근 클라우드 파일 스토어를 출시했으며, 여기에는 튜토리얼이 포함되어 있습니다:

일부 시나리오에서는 클라우드 스토리지/버킷에 대한 좋은 대안이 될 수 있습니다.




일단은. Kubernetes는 호스트 간에 스토리지를 공유하는 통합 기능이 없습니다. 아래에는 몇 가지 옵션이 있습니다. 그러나 먼저 일부 볼륨을 이미 설정한 경우 스토리지를 공유하는 방법입니다.

여러 포드 간에 볼륨을 공유하려면 액세스 모드가 있는 PVC를 만들어야 합니다. ReadWriteMany

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
    name: my-pvc
spec:
    accessModes:
      - ReadWriteMany
    storageClassName: myvolume
    resources:
        requests:
            storage: 1Gi

그런 다음 여러 포드에 마운트할 수 있습니다:

apiVersion: v1
kind: Pod
metadata:
  name: myapp1
spec:
  containers:
...
      volumeMounts:
        - mountPath: /data
          name: data
          subPath: app1
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: 'my-pvc'
---
apiVersion: v1
kind: Pod
metadata:
  name: myapp2
spec:
  containers:
...
      volumeMounts:
        - mountPath: /data
          name: data
          subPath: app2
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: 'my-pvc'

물론 네트워크를 통해 영구 볼륨에 액세스할 수 있어야 합니다. 그렇지 않으면 모든 포드가 해당 볼륨의 노드로 예약되어 있는지 확인해야 합니다.

이에 적합하고 클라우드 공급자와 연결되지 않는 볼륨 유형은 다음과 같습니다:

  • NFS
  • RBD(Ceph 블록 장치)
  • CephFS
  • 글러스터프
  • Portworx 볼륨

물론, 볼륨을 사용하려면 먼저 볼륨이 있어야 합니다. 즉, NFS를 사용하려면 K8s 클러스터의 모든 노드에 NFS를 설정해야 합니다. Ceph를 소비하려면 Ceph 클러스터 등을 설정해야 합니다.

Kubernetes를 즉시 지원하는 유일한 볼륨 유형은 Portworks입니다. 에 대한 설명이 있다.

K8s에서 Ceph 클러스터를 설정하기 위해 개발 중인 프로젝트가 있습니다.

그러나 한 노드의 폴더를 다른 노드에서 사용할 수 있도록 하려면 이는 모두 오버킬입니다. 이 경우 NFS 서버만 설정할 수 있습니다. 다른 볼륨 유형을 프로비저닝하는 것보다 어렵지 않고 CPU/메모리/디스크 리소스를 훨씬 적게 사용합니다.




조타: 조타를 사용하여 전개하는 경우

RWO만 지원하는 PVC가 있고 동일한 PVC에서 여러 포드를 읽고 해당 저장소를 공유하려면 클라우드 공급자가 RWX 액세스 모드를 지원하지 않는 경우 헬름 차트를 설치할 수 있습니다.

이 차트는 Digital Ocean과 같이 RWO만 지원하는 클라우드 공급자에서 기본 PVC에 액세스하는 RWX 액세스 모드를 사용하여 "Out-of-Tree" 스토리지 PVC를 프로비저닝합니다.

In your pods, you mount the PVC provisioned by the nfs server and you can scale them while they read and write from the same PVC.

Important!

You have to modify the values file to add configuration suited to your deployment like your storage class.

For more information on the chart: https://github.com/helm/charts/tree/master/stable/nfs-server-provisioner




I just achieve this with an application made with 3 containerized micro-services, I have one of this that is responsible to store and share files, so the application is storing files and retrieving them on a folder, this folder is passed via application property. There is a secured rest entry point that is allowing submission and retrieving of files (basically at every submission it is creating a unique id that is returned and can be used to scan the folder for a file). Passing this application from docker-compose to kubernetes I had your same problem : I need a global disk so I can have multiple replica of the container, so when the other micro-services will send a request to one of the replica, they will always be able to send any submitted file, not only the replica file managed at submission. I solved by creating a persistent volume, associated to an persistent volume claim, this volume claim is associated to a deployment (note: not a Statefulset, that it will create a disk for every pod), at this point you have to associate the mounted volume path with the container storing folder path.

So what is important is just the persistent volume claim name and the fact that PV has more available memory of PVC, and obviously the matching with the deployment with the right labels. Then in the deployment you can pass in the spec:

volumes:
      - name: store-folder
        persistentVolumeClaim:
          claimName: [pvc_name]

into the container settings:

volumeMounts:
        - name: store-folder
          mountPath: "/stored-files"

and in env. block:

containers:
....
      - env:
        - name: any-property-used-inside-the-application-for-saving-files
          value: /stored-files

So, from volume, you bind the pvc to the deployment, then from volume mounts, you bind the disk to a directory, then via environment variable you are able to pass the persistent disk directory. It is fundamental that your declare both PVC and PV, without PV it will work like any pods has its own folder.


반응형