Ceph 기반 스토리지를 Kubernetes 클러스터에 연결하는 실제 예

CSI(컨테이너 스토리지 인터페이스)는 Kubernetes와 스토리지 시스템 간의 통합 인터페이스입니다. 우리는 이미 그것에 대해 간략하게 이야기했습니다. 말한, 오늘은 CSI와 Ceph의 조합에 대해 자세히 살펴보겠습니다. Ceph 스토리지 연결 Kubernetes 클러스터에.
이 기사는 이해하기 쉽도록 약간 단순화된 실제 사례를 제공합니다. Ceph 및 Kubernetes 클러스터 설치 및 구성은 고려하지 않습니다.

어떻게 작동하는지 궁금하신가요?

Ceph 기반 스토리지를 Kubernetes 클러스터에 연결하는 실제 예

따라서 Kubernetes 클러스터를 손쉽게 배포할 수 있습니다. 예를 들어, 쿠베스프레이. 근처에서 작동하는 Ceph 클러스터가 있습니다. 예를 들어 다음과 같이 설치할 수도 있습니다. 플레이북 세트. 그들 사이에 생산을 위해서는 최소 10Gbit/s의 대역폭을 가진 네트워크가 있어야 한다는 점은 언급할 필요가 없기를 바랍니다.

이거 다 모았으면 가자!

먼저 Ceph 클러스터 노드 중 하나로 이동하여 모든 것이 올바른지 확인하겠습니다.

ceph health
ceph -s

다음으로 RBD 디스크용 풀을 즉시 생성하겠습니다.

ceph osd pool create kube 32
ceph osd pool application enable kube rbd

Kubernetes 클러스터로 넘어가겠습니다. 먼저 RBD용 Ceph CSI 드라이버를 설치하겠습니다. 예상대로 Helm을 통해 설치하겠습니다.
차트와 함께 저장소를 추가하고 ceph-csi-rbd 차트에 대한 변수 세트를 얻습니다.

helm repo add ceph-csi https://ceph.github.io/csi-charts
helm inspect values ceph-csi/ceph-csi-rbd > cephrbd.yml

이제 cephrbd.yml 파일을 작성해야 합니다. 이렇게 하려면 Ceph에서 모니터의 클러스터 ID와 IP 주소를 찾으십시오.

ceph fsid  # так мы узнаем clusterID
ceph mon dump  # а так увидим IP-адреса мониторов

얻은 값을 cephrbd.yml 파일에 입력합니다. 동시에 PSP 정책(Pod 보안 정책) 생성을 활성화합니다. 섹션의 옵션 노드플러그인 и 제공자 이미 파일에 있는 경우 아래와 같이 수정할 수 있습니다.

csiConfig:
  - clusterID: "bcd0d202-fba8-4352-b25d-75c89258d5ab"
    monitors:
      - "v2:172.18.8.5:3300/0,v1:172.18.8.5:6789/0"
      - "v2:172.18.8.6:3300/0,v1:172.18.8.6:6789/0"
      - "v2:172.18.8.7:3300/0,v1:172.18.8.7:6789/0"

nodeplugin:
  podSecurityPolicy:
    enabled: true

provisioner:
  podSecurityPolicy:
    enabled: true

다음으로 남은 것은 Kubernetes 클러스터에 차트를 설치하는 것입니다.

helm upgrade -i ceph-csi-rbd ceph-csi/ceph-csi-rbd -f cephrbd.yml -n ceph-csi-rbd --create-namespace

좋습니다. RBD 드라이버가 작동합니다!
Kubernetes에서 새로운 StorageClass를 생성해 보겠습니다. 이를 위해서는 다시 Ceph를 약간 조작해야 합니다.

Ceph에서 새 사용자를 생성하고 그에게 풀에 쓸 수 있는 권한을 부여합니다. 큐브:

ceph auth get-or-create client.rbdkube mon 'profile rbd' osd 'profile rbd pool=kube'

이제 액세스 키가 여전히 있는지 확인해 보겠습니다.

ceph auth get-key client.rbdkube

명령은 다음과 같이 출력됩니다.

AQCO9NJbhYipKRAAMqZsnqqS/T8OYQX20xIa9A==

이 값을 Kubernetes 클러스터의 Secret에 추가해 보겠습니다(필요한 경우). 사용자 키:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-rbd-secret
  namespace: ceph-csi-rbd
stringData:
  # Значения ключей соответствуют имени пользователя и его ключу, как указано в
  # кластере Ceph. ID юзера должен иметь доступ к пулу,
  # указанному в storage class
  userID: rbdkube
  userKey: <user-key>

그리고 우리는 비밀을 만듭니다:

kubectl apply -f secret.yaml

다음으로 다음과 같은 StorageClass 매니페스트가 필요합니다.

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
   clusterID: <cluster-id>
   pool: kube

   imageFeatures: layering

   # Эти секреты должны содержать данные для авторизации
   # в ваш пул.
   csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
   csi.storage.k8s.io/provisioner-secret-namespace: ceph-csi-rbd
   csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret
   csi.storage.k8s.io/controller-expand-secret-namespace: ceph-csi-rbd
   csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
   csi.storage.k8s.io/node-stage-secret-namespace: ceph-csi-rbd

   csi.storage.k8s.io/fstype: ext4

reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
  - discard

작성해야 함 클러스터ID, 우리 팀에서 이미 배운 내용입니다. 세프 fsid을 클릭하고 이 매니페스트를 Kubernetes 클러스터에 적용합니다.

kubectl apply -f storageclass.yaml

클러스터가 어떻게 함께 작동하는지 확인하기 위해 다음 PVC(영구 볼륨 청구)를 생성해 보겠습니다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: rbd-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: csi-rbd-sc

Kubernetes가 Ceph에서 요청된 볼륨을 어떻게 생성했는지 즉시 살펴보겠습니다.

kubectl get pvc
kubectl get pv

모든 것이 좋은 것 같습니다! Ceph 쪽에서는 어떤 모습인가요?
풀의 볼륨 목록을 얻고 볼륨에 대한 정보를 봅니다.

rbd ls -p kube
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653  # тут, конечно же, будет другой ID тома, который выдала предыдущая команда

이제 RBD 볼륨 크기 조정이 어떻게 작동하는지 살펴보겠습니다.
pvc.yaml 매니페스트의 볼륨 크기를 2Gi로 변경하고 적용합니다.

kubectl apply -f pvc.yaml

변경 사항이 적용될 때까지 기다렸다가 볼륨 크기를 다시 살펴보겠습니다.

rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653

kubectl get pv
kubectl get pvc

PVC의 크기는 변하지 않은 것을 알 수 있습니다. 이유를 알아보려면 Kubernetes에 PVC의 YAML 설명을 쿼리하면 됩니다.

kubectl get pvc rbd-pvc -o yaml

문제는 다음과 같습니다.

메시지: 사용자가 포드를 (다시) 시작하여 노드에서 볼륨의 파일 시스템 크기 조정을 완료할 때까지 기다리는 중입니다. 유형: FileSystemResizePending

즉, 디스크는 커졌지만 디스크의 파일 시스템은 커지지 않았습니다.
파일 시스템을 확장하려면 볼륨을 마운트해야 합니다. 우리나라에서는 생성된 PVC/PV가 현재 어떠한 방식으로도 사용되지 않고 있다.

예를 들어 다음과 같이 테스트 Pod를 만들 수 있습니다.

---
apiVersion: v1
kind: Pod
metadata:
  name: csi-rbd-demo-pod
spec:
  containers:
    - name: web-server
      image: nginx:1.17.6
      volumeMounts:
        - name: mypvc
          mountPath: /data
  volumes:
    - name: mypvc
      persistentVolumeClaim:
        claimName: rbd-pvc
        readOnly: false

이제 PVC를 살펴보겠습니다.

kubectl get pvc

크기가 변경되었습니다. 모든 것이 정상입니다.

첫 번째 부분에서는 RBD 블록 장치(Rados Block Device의 약자)를 사용하여 작업했지만 여러 마이크로서비스가 이 디스크를 동시에 사용해야 하는 경우에는 이 작업을 수행할 수 없습니다. CephFS는 디스크 이미지보다는 파일 작업에 훨씬 더 적합합니다.
Ceph 및 Kubernetes 클러스터의 예를 사용하여 CephFS와 작동하도록 CSI 및 기타 필요한 엔터티를 구성합니다.

새로운 Helm 차트에서 필요한 값을 가져오겠습니다.

helm inspect values ceph-csi/ceph-csi-cephfs > cephfs.yml

이번에도 cephfs.yml 파일을 작성해야 합니다. 이전과 마찬가지로 Ceph 명령이 도움이 됩니다.

ceph fsid
ceph mon dump

다음과 같은 값으로 파일을 채우십시오.

csiConfig:
  - clusterID: "bcd0d202-fba8-4352-b25d-75c89258d5ab"
    monitors:
      - "172.18.8.5:6789"
      - "172.18.8.6:6789"
      - "172.18.8.7:6789"

nodeplugin:
  httpMetrics:
    enabled: true
    containerPort: 8091
  podSecurityPolicy:
    enabled: true

provisioner:
  replicaCount: 1
  podSecurityPolicy:
    enabled: true

모니터 주소는 주소:포트라는 간단한 형식으로 지정됩니다. 노드에 cephfs를 마운트하기 위해 이러한 주소는 v2 모니터 프로토콜을 사용하는 방법을 아직 모르는 커널 모듈로 전송됩니다.
Kubespray가 설치한 nginx-proxy와 충돌하지 않도록 httpMetrics용 포트를 변경합니다(Prometheus는 메트릭 모니터링을 위해 해당 포트로 이동합니다). 이것이 필요하지 않을 수도 있습니다.

Kubernetes 클러스터에 Helm 차트를 설치합니다.

helm upgrade -i ceph-csi-cephfs ceph-csi/ceph-csi-cephfs -f cephfs.yml -n ceph-csi-cephfs --create-namespace

Ceph 데이터 저장소로 이동하여 거기에 별도의 사용자를 생성해 보겠습니다. 설명서에는 CephFS 프로비저너에 클러스터 관리자 액세스 권한이 필요하다고 명시되어 있습니다. 하지만 우리는 별도의 사용자를 생성하겠습니다. fs 제한된 권리:

ceph auth get-or-create client.fs mon 'allow r' mgr 'allow rw' mds 'allow rws' osd 'allow rw pool=cephfs_data, allow rw pool=cephfs_metadata'

그리고 즉시 그의 액세스 키를 살펴보겠습니다. 나중에 필요합니다.

ceph auth get-key client.fs

Secret과 StorageClass를 별도로 생성해 보겠습니다.
새로운 것은 없습니다. 우리는 이미 RBD의 예에서 이것을 보았습니다:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-cephfs-secret
  namespace: ceph-csi-cephfs
stringData:
  # Необходимо для динамически создаваемых томов
  adminID: fs
  adminKey: <вывод предыдущей команды>

매니페스트 적용:

kubectl apply -f secret.yaml

이제 별도의 StorageClass가 있습니다.

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: csi-cephfs-sc
provisioner: cephfs.csi.ceph.com
parameters:
  clusterID: <cluster-id>

  # Имя файловой системы CephFS, в которой будет создан том
  fsName: cephfs

  # (необязательно) Пул Ceph, в котором будут храниться данные тома
  # pool: cephfs_data

  # (необязательно) Разделенные запятыми опции монтирования для Ceph-fuse
  # например:
  # fuseMountOptions: debug

  # (необязательно) Разделенные запятыми опции монтирования CephFS для ядра
  # См. man mount.ceph чтобы узнать список этих опций. Например:
  # kernelMountOptions: readdir_max_bytes=1048576,norbytes

  # Секреты должны содержать доступы для админа и/или юзера Ceph.
  csi.storage.k8s.io/provisioner-secret-name: csi-cephfs-secret
  csi.storage.k8s.io/provisioner-secret-namespace: ceph-csi-cephfs
  csi.storage.k8s.io/controller-expand-secret-name: csi-cephfs-secret
  csi.storage.k8s.io/controller-expand-secret-namespace: ceph-csi-cephfs
  csi.storage.k8s.io/node-stage-secret-name: csi-cephfs-secret
  csi.storage.k8s.io/node-stage-secret-namespace: ceph-csi-cephfs

  # (необязательно) Драйвер может использовать либо ceph-fuse (fuse), 
  # либо ceph kernelclient (kernel).
  # Если не указано, будет использоваться монтирование томов по умолчанию,
  # это определяется поиском ceph-fuse и mount.ceph
  # mounter: kernel
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
  - debug

여기서 채워보자 클러스터ID Kubernetes에 적용 가능:

kubectl apply -f storageclass.yaml

Проверка

확인하기 위해 이전 예와 같이 PVC를 생성해 보겠습니다.

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: csi-cephfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  storageClassName: csi-cephfs-sc

그리고 PVC/PV가 있는지 확인합니다.

kubectl get pvc
kubectl get pv

CephFS의 파일과 디렉터리를 보려면 이 파일 시스템을 어딘가에 마운트하면 됩니다. 예를 들어 아래와 같습니다.

Ceph 클러스터 노드 중 하나로 이동하여 다음 작업을 수행해 보겠습니다.

# Точка монтирования
mkdir -p /mnt/cephfs

# Создаём файл с ключом администратора
ceph auth get-key client.admin >/etc/ceph/secret.key

# Добавляем запись в /etc/fstab
# !! Изменяем ip адрес на адрес нашего узла
echo "172.18.8.6:6789:/ /mnt/cephfs ceph name=admin,secretfile=/etc/ceph/secret.key,noatime,_netdev    0       2" >> /etc/fstab

mount /mnt/cephfs

물론 이와 같은 Ceph 노드에 FS를 마운트하는 것은 훈련 목적에만 적합합니다. 슬럼 코스. 프로덕션 환경에서는 누구도 이런 작업을 수행하지 않을 것이라고 생각합니다. 중요한 파일을 실수로 삭제할 위험이 높습니다.

마지막으로 CephFS의 경우 볼륨 크기 조정이 어떻게 작동하는지 확인해 보겠습니다. Kubernetes로 돌아가서 PVC에 대한 매니페스트를 편집해 보겠습니다. 크기를 예를 들어 7Gi로 늘립니다.

편집된 파일을 적용해 보겠습니다.

kubectl apply -f pvc.yaml

할당량이 어떻게 변경되었는지 알아보기 위해 마운트된 디렉터리를 살펴보겠습니다.

getfattr -n ceph.quota.max_bytes <каталог-с-данными>

이 명령이 작동하려면 시스템에 패키지를 설치해야 할 수도 있습니다. 속성.

눈이 두렵고 손이

이러한 모든 주문과 긴 YAML 매니페스트는 표면적으로는 복잡해 보이지만 실제로 Slurm 학생들은 매우 빠르게 익숙해집니다.
이 기사에서 우리는 정글 속으로 깊이 들어 가지 않았습니다. 이에 대한 공식 문서가 있습니다. Kubernetes 클러스터로 Ceph 스토리지를 설정하는 세부 정보에 관심이 있는 경우 다음 링크가 도움이 될 것입니다.

볼륨 작업을 수행하는 Kubernetes의 일반 원칙
RBD 문서
Ceph 관점에서 RBD와 Kubernetes 통합
CSI 관점에서 RBD와 Kubernetes 통합
일반 CephFS 문서
CSI 관점에서 CephFS와 Kubernetes 통합

슬럼 코스에서 쿠버네티스 베이스 좀 더 나아가 CephFS를 파일 스토리지로 사용할 실제 애플리케이션을 Kubernetes에 배포할 수 있습니다. GET/POST 요청을 통해 Ceph에서 파일을 전송하고 받을 수 있습니다.

그리고 데이터 저장에 더 관심이 있다면 가입하세요. Ceph의 새로운 코스. 베타 테스트가 진행되는 동안 강좌를 할인된 가격으로 수강할 수 있으며 강좌 내용에 영향을 미칠 수 있습니다.

기사 작성자: Alexander Shvalov, 현직 엔지니어 사우스 브리지, 공인 Kubernetes 관리자, Slurm 과정의 저자 및 개발자입니다.

출처 : habr.com