Benteng atau bukan Benteng - itulah pertanyaannya



Awal bulan ini, 3 Mei, rilis utama "sistem manajemen untuk gudang data terdistribusi di Kubernetes" diumumkan - Rook 1.0.0 . Lebih dari setahun yang lalu, kami sudah menerbitkan tinjauan umum tentang Rook. Kemudian kami diminta untuk berbicara tentang pengalaman penggunaannya dalam praktik - dan sekarang, pada waktunya untuk tonggak sejarah yang signifikan dalam sejarah proyek, kami dengan senang hati membagikan kesan-kesan kami yang terakumulasi.

Singkatnya, Rook adalah seperangkat operator untuk Kubernetes yang mengambil kendali penuh atas penyebaran, manajemen, dan pemulihan otomatis solusi penyimpanan seperti Ceph, EdgeFS, Minio, Cassandra, CockroachDB.

Pada saat ini, solusi yang paling berkembang (dan hanya dalam tahap stabil ) adalah operator rook-ceph .

Catatan : Di antara perubahan signifikan dalam rilis Rook 1.0.0 terkait dengan Ceph, dukungan Ceph Nautilus dan kemampuan untuk menggunakan NFS untuk bucket CephFS atau RGW dapat dicatat. Antara lain, "jatuh tempo" dukungan EdgeFS ke tingkat beta menonjol.

Jadi, dalam artikel ini kita:

  • jawab pertanyaan tentang keuntungan apa yang kita lihat dalam menggunakan Rook untuk menyebarkan Ceph di kluster Kubernetes;
  • berbagi pengalaman dan kesan menggunakan Rook dalam produksi;
  • Kami akan memberi tahu Anda mengapa kami mengatakan "Ya!" Kepada Rook dan rencana kami untuknya.

Mari kita mulai dengan konsep dan teori umum.

"Aku punya keuntungan dalam satu Benteng!" (pemain catur yang tidak dikenal)




Salah satu keuntungan utama Rook adalah interaksi dengan gudang data dilakukan melalui mekanisme Kubernetes. Ini berarti Anda tidak perlu lagi menyalin perintah untuk mengkonfigurasi Ceph dari leaflet ke konsol.

- Ingin menggunakan dalam cluster CephFS? Cukup tulis file yaml!
- Apa? Ingin menggunakan objek store dengan API S3? Cukup tulis file yaml kedua!

Benteng dibuat oleh semua aturan operator biasa. Interaksi dengannya terjadi dengan bantuan CRD (Custom Resource Definition) , di mana kami menggambarkan karakteristik entitas Ceph yang kami butuhkan (karena ini adalah satu-satunya implementasi yang stabil, secara default artikel akan berbicara tentang Ceph, kecuali dinyatakan secara eksplisit sebaliknya) . Menurut parameter yang ditentukan, operator akan secara otomatis menjalankan perintah yang diperlukan untuk pengaturan.

Mari kita lihat secara spesifik menggunakan contoh membuat Object Store, atau lebih tepatnya CephObjectStoreUser .

 apiVersion: ceph.rook.io/v1 kind: CephObjectStore metadata: name: {{ .Values.s3.crdName }} namespace: kube-rook spec: metadataPool: failureDomain: host replicated: size: 3 dataPool: failureDomain: host erasureCoded: dataChunks: 2 codingChunks: 1 gateway: type: s3 sslCertificateRef: port: 80 securePort: instances: 1 allNodes: false --- apiVersion: ceph.rook.io/v1 kind: CephObjectStoreUser metadata: name: {{ .Values.s3.crdName }} namespace: kube-rook spec: store: {{ .Values.s3.crdName }} displayName: {{ .Values.s3.username }} 

Parameter yang ditunjukkan dalam daftar cukup standar dan tidak membutuhkan komentar, tetapi Anda harus memberikan perhatian khusus kepada mereka yang disorot dalam variabel template.

Skema umum pekerjaan datang ke fakta bahwa melalui file YAML kita "memesan" sumber daya, yang mana operator mengeksekusi perintah yang diperlukan dan mengembalikan kita rahasia "tidak nyata", yang dengannya kita dapat terus bekerja (lihat di bawah) . Dan dari variabel yang ditunjukkan di atas, perintah dan nama rahasia akan disusun.

Tim macam apa ini? Saat membuat pengguna untuk penyimpanan objek, pernyataan Rook di dalam pod akan melakukan hal berikut:

 radosgw-admin user create --uid="rook-user" --display-name="{{ .Values.s3.username }}" 

Hasil dari perintah ini adalah struktur JSON:

 { "user_id": "rook-user", "display_name": "{{ .Values.s3.username }}", "keys": [ { "user": "rook-user", "access_key": "NRWGT19TWMYOB1YDBV1Y", "secret_key": "gr1VEGIV7rxcP3xvXDFCo4UDwwl2YoNrmtRlIAty" } ], ... } 

Keys adalah apa yang dibutuhkan aplikasi masa depan untuk mengakses penyimpanan objek melalui API S3. Operator Rook dengan baik hati memilih mereka dan menempatkan mereka ke dalam namespace-nya sebagai rahasia dengan nama rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }} .

Untuk menggunakan data dari rahasia ini, cukup tambahkan ke wadah sebagai variabel lingkungan. Sebagai contoh, saya akan memberikan templat untuk Pekerjaan, di mana kami secara otomatis membuat keranjang untuk setiap lingkungan pengguna:

 {{- range $bucket := $.Values.s3.bucketNames }} apiVersion: batch/v1 kind: Job metadata: name: create-{{ $bucket }}-bucket-job annotations: "helm.sh/hook": post-install "helm.sh/hook-weight": "2" spec: template: metadata: name: create-{{ $bucket }}-bucket-job spec: restartPolicy: Never initContainers: - name: waitdns image: alpine:3.6 command: ["/bin/sh", "-c", "while ! getent ahostsv4 rook-ceph-rgw-{{ $.Values.s3.crdName }}; do sleep 1; done" ] - name: config image: rook/ceph:v1.0.0 command: ["/bin/sh", "-c"] args: ["s3cmd --configure --access_key=$(ACCESS-KEY) --secret_key=$(SECRET-KEY) -s --no-ssl --dump-config | tee /config/.s3cfg"] volumeMounts: - name: config mountPath: /config env: - name: ACCESS-KEY valueFrom: secretKeyRef: name: rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }} key: AccessKey - name: SECRET-KEY valueFrom: secretKeyRef: name: rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }} key: SecretKey containers: - name: create-bucket image: rook/ceph:v1.0.0 command: - "s3cmd" - "mb" - "--host=rook-ceph-rgw-{{ $.Values.s3.crdName }}" - "--host-bucket= " - "s3://{{ $bucket }}" ports: - name: s3-no-sll containerPort: 80 volumeMounts: - name: config mountPath: /root volumes: - name: config emptyDir: {} --- {{- end }} 

Semua aktivitas yang tercantum dalam Pekerjaan ini dilakukan tanpa melampaui Kubernetes. Struktur yang dijelaskan dalam file YAML dilipat ke dalam repositori Git dan digunakan kembali berulang kali. Dalam hal ini kita melihat nilai tambah yang besar untuk insinyur DevOps dan proses CI / CD secara keseluruhan.

Dengan Rook dan Rados to Joy


Menggunakan sekelompok Ceph + RBD memberlakukan batasan tertentu pada volume pemasangan ke pod.

Secara khusus, namespace harus memiliki rahasia untuk mengakses Ceph sehingga aplikasi stateful dapat berfungsi. Tidak apa-apa jika Anda memiliki 2-3 lingkungan di ruang nama Anda: Anda bisa pergi dan menyalin rahasia secara manual. Tetapi bagaimana jika setiap fitur pengembang menciptakan lingkungan yang terpisah dengan namespace-nya sendiri?

Kami memecahkan masalah ini dengan bantuan operator shell , yang secara otomatis menyalin rahasia ke namespace baru (contoh kait seperti itu dijelaskan dalam artikel ini ).

 #! /bin/bash if [[ $1 == β€œ--config” ]]; then cat <<EOF {"onKubernetesEvent":[ {"name": "OnNewNamespace", "kind": "namespace", "event": ["add"] } ]} EOF else NAMESPACE=$(kubectl get namespace -o json | jq '.items | max_by( .metadata.creationTimestamp ) | .metadata.name') kubectl -n ${CEPH_SECRET_NAMESPACE} get secret ${CEPH_SECRET_NAME} -o json | jq ".metadata.namespace=\"${NAMESPACE}\"" | kubectl apply -f - fi 

Namun, ketika menggunakan Rook, masalah ini tidak ada. Proses pemasangan berlangsung menggunakan driver Anda sendiri berdasarkan Flexvolume atau CSI (masih dalam versi beta) dan karenanya tidak memerlukan rahasia.

Rook secara otomatis memecahkan banyak masalah, yang mendorong kita untuk menggunakannya dalam proyek-proyek baru.

Pengepungan Benteng


Kami menyelesaikan bagian praktis dengan penyebaran Rook dan Ceph untuk kemungkinan melakukan percobaan kami sendiri. Untuk menyerbu menara yang tak tertembus ini, lebih mudah, para pengembang telah menyiapkan paket Helm. Mari kita unduh:

 $ helm fetch rook-master/rook-ceph --untar --version 1.0.0 

rook-ceph/values.yaml dapat menemukan banyak pengaturan berbeda di file rook-ceph/values.yaml . Yang paling penting, tentukan toleransi untuk agen dan pencarian. Mengapa Anda dapat menggunakan mekanisme noda / toleransi, kami jelaskan secara rinci dalam artikel ini .

Singkatnya, kami tidak ingin pod dengan aplikasi klien ditempatkan di node yang sama di mana disk untuk penyimpanan data berada. Alasannya sederhana: dengan cara ini kerja agen Rook tidak akan memengaruhi aplikasi itu sendiri.

Jadi, buka file rook-ceph/values.yaml editor favorit rook-ceph/values.yaml dan tambahkan blok berikut di akhir:

 discover: toleration: NoExecute tolerationKey: node-role/storage agent: toleration: NoExecute tolerationKey: node-role/storage mountSecurityMode: Any 

Untuk setiap node yang dicadangkan untuk penyimpanan data, tambahkan noda yang sesuai:

 $ kubectl taint node ${NODE_NAME} node-role/storage="":NoExecute 

Kemudian instal Helm-chart dengan perintah:

 $ helm install --namespace ${ROOK_NAMESPACE} ./rook-ceph 

Sekarang Anda perlu membuat cluster dan menunjukkan lokasi OSD :

 apiVersion: ceph.rook.io/v1 kind: CephCluster metadata: clusterName: "ceph" finalizers: - cephcluster.ceph.rook.io generation: 1 name: rook-ceph spec: cephVersion: image: ceph/ceph:v13 dashboard: enabled: true dataDirHostPath: /var/lib/rook/osd mon: allowMultiplePerNode: false count: 3 network: hostNetwork: true rbdMirroring: workers: 1 placement: all: tolerations: - key: node-role/storage operator: Exists storage: useAllNodes: false useAllDevices: false config: osdsPerDevice: "1" storeType: filestore resources: limits: memory: "1024Mi" requests: memory: "1024Mi" nodes: - name: host-1 directories: - path: "/mnt/osd" - name: host-2 directories: - path: "/mnt/osd" - name: host-3 directories: - path: "/mnt/osd" 

Periksa status Ceph - harap lihat HEALTH_OK :

 $ kubectl -n ${ROOK_NAMESPACE} exec $(kubectl -n ${ROOK_NAMESPACE} get pod -l app=rook-ceph-operator -o name -o jsonpath='{.items[0].metadata.name}') -- ceph -s 

Pada saat yang sama, periksa apakah pod dengan aplikasi klien tidak sampai ke node yang disediakan untuk Ceph:

 $ kubectl -n ${APPLICATION_NAMESPACE} get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName 

Komponen opsional lebih lanjut dikonfigurasikan. Informasi lebih lanjut tentang mereka ditunjukkan dalam dokumentasi . Untuk administrasi, kami sangat menyarankan untuk menginstal dasbor dan kotak peralatan.

Benteng dan pengait: apakah Benteng cukup untuk semuanya?


Seperti yang Anda lihat, pengembangan Rook sedang berjalan lancar. Tetapi masih ada masalah yang tidak memungkinkan kita untuk sepenuhnya meninggalkan konfigurasi manual Ceph:

  • Tidak ada driver Rook yang dapat mengekspor metrik pada penggunaan blok yang dipasang, yang menghalangi kita memantau.
  • Flexvolume dan CSI tidak tahu cara mengubah ukuran volume (tidak seperti RBD yang sama), jadi Rook kehilangan Alat yang berguna (dan terkadang sangat penting!).
  • Benteng masih tidak sefleksibel Ceph biasa. Jika kita ingin mengonfigurasi kumpulan metadata CephFS untuk disimpan di SSD, dan data itu sendiri di HDD, kita perlu mendaftarkan kelompok perangkat yang terpisah secara manual di peta CRUSH.
  • Terlepas dari kenyataan bahwa rook-ceph-operator dianggap stabil, saat ini ada masalah tertentu ketika memperbarui Ceph dari versi 13 ke 14.

Kesimpulan


"Sekarang Rook ditutup dari dunia luar oleh pion, tapi kami percaya bahwa suatu hari dia akan memainkan peran yang menentukan dalam pesta!" (kutipan diciptakan khusus untuk artikel ini)

Proyek Rook tidak diragukan lagi telah memenangkan hati kami - kami percaya bahwa [dengan semua kelebihan dan kekurangannya] itu pasti patut Anda perhatikan.

Rencana kami selanjutnya adalah menjadikan rook-ceph sebagai modul untuk addon-operator , yang akan membuatnya digunakan di banyak kluster Kubernet kami yang lebih sederhana dan lebih nyaman.

PS


Baca juga di blog kami:

Source: https://habr.com/ru/post/id451818/


All Articles