GlusterFS كتخزين خارجي لـ Kubernetes

صورة
يعد العثور على التخزين الأمثل عملية معقدة إلى حد ما ، كل شيء له إيجابياته وسلبياته. بالطبع ، الرائد في هذه الفئة هو CEPH ، ولكنه نظام معقد إلى حد ما ، وإن كان بوظائف غنية جدًا. بالنسبة لنا ، فإن مثل هذا النظام فائض ، نظرًا لأننا كنا بحاجة إلى تخزين بسيط منسوخ في الوضع الرئيسي الرئيسي لبضعة تيرابايت. بعد دراسة الكثير من المواد ، تقرر اختبار المنتج الأكثر أناقة في السوق للدائرة التي نهتم بها. نظرًا لعدم العثور على حل جاهز لمثل هذه الخطة ، أود أن أشارك أفضل ممارساتي حول هذا الموضوع وأن أصف المشكلات التي واجهناها في عملية النشر.

الأهداف


ماذا كنا نتوقع من المستودع الجديد:

  • القدرة على العمل مع عدد من العقد للنسخ المتماثل.
  • سهلة التركيب والإعداد والدعم
  • يجب أن يكون النظام بالغًا ومختبرًا للوقت ومستخدمًا
  • القدرة على توسيع مساحة التخزين دون توقف
  • يجب أن يكون التخزين متوافقًا مع Kubernetes
  • يجب أن يكون هناك فشل تلقائي عند تعطل إحدى العقد

حول النقطة الأخيرة لدينا الكثير من الأسئلة.

تعيين


للنشر ، تم إنشاء جهازين افتراضيين على CentOs 8. يتم توصيل كل منهما عبر قرص إضافي مع تخزين.

التحضير الأولي


بالنسبة لـ GlusterFS ، تحتاج إلى تخصيص قرص منفصل مع XFS بحيث لا يؤثر على النظام بأي شكل من الأشكال.

حدد القسم:

$ fdisk /dev/sdb
Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):  1
First sector (2048-16777215, default 2048): 
Last sector, +sectors or +size{K,M,G,T,P} (2048-16777215, default 16777215): 
 
Created a new partition 1 of type ‘Linux’ and of size 8 GiB.
Command (m for help): w 

The partition table has been altered.
Calling ioctl() to re-read partition table. Syncing disks.

التنسيق في XFS والتركيب:

$ mkfs.xfs /dev/sdb1
$ mkdir /gluster
$ mount /dev/sdb1 /gluster

ولأعلى ، أفلت الإدخال في / etc / fstab لتركيب الدليل تلقائيًا عند بدء تشغيل النظام:

/dev/sdb1       /gluster        xfs     defaults        0       0

التركيب


فيما يتعلق بالتثبيت ، تم كتابة العديد من المقالات ، وفي هذا الصدد لن نتعمق في العملية ، سننظر فقط في ما يستحق الاهتمام.

على كلا العقدتين ، قم بتثبيت أحدث إصدار glusterfs وتشغيله:

$ wget -P /etc/yum.repos.d  https://download.gluster.org/pub/gluster/glusterfs/LATEST/CentOS/glusterfs-rhel8.repo
$ yum -y install yum-utils
$ yum-config-manager --enable PowerTools
$ yum install -y glusterfs-server
$ systemctl start glusterd

بعد ذلك ، عليك أن تخبر الجلاد أين العقدة المجاورة له. يتم ذلك مع عقدة واحدة فقط. نقطة مهمة: إذا كان لديك شبكة مجال ، فيجب عليك تحديد اسم الخادم مع المجال ، وإلا سيتعين عليك في المستقبل إعادة كل شيء.

$ gluster peer probe gluster-02.example.com

إذا كان ناجحًا ، فإننا نتحقق من الاتصال بالأمر من كلا الخادمين:

$ gluster peer status
Number of Peers: 1

Hostname: gluster-02.example.com
Uuid: a6de3b23-ee31-4394-8bff-0bd97bd54f46
State: Peer in Cluster (Connected)
Other names:
10.10.6.72

الآن يمكنك إنشاء مجلد سنكتب فيه.

gluster volume create main replica 2 gluster-01.example.com:/gluster/main gluster-02.example.com:/gluster/main force

أين:

  • حجم الاسم الرئيسي
  • نسخة طبق الأصل - نوع المجلد (يمكن العثور على مزيد من التفاصيل في الوثائق الرسمية )
  • 2- عدد النسخ المتماثلة

تشغيل حجم والتحقق من أدائه:

gluster volume start main
gluster volume status main

بالنسبة لوحدة التخزين المنسوخة ، يوصى بتعيين المعلمات التالية:

$ gluster volume set main network.ping-timeout 5
$ gluster volume set main cluster.quorum-type fixed
$ gluster volume set main cluster.quorum-count 1
$ gluster volume set main performance.quick-read on

بهذه الخطوات البسيطة ، قمنا ببناء مجموعة GlusterFS. يبقى الاتصال به والتحقق من الأداء. يتم تثبيت Ubuntu على جهاز العميل ، للتثبيت تحتاج إلى تثبيت العميل:

$ add-apt-repository ppa:gluster/glusterfs-7
$ apt install glusterfs-client
$ mkdir /gluster
$ mount.glusterfs gluster-01.example.com:/main /gluster

Gluster ، عند توصيله بإحدى العقد ، يعطي عناوين جميع العقد ويتصل تلقائيًا بالجميع. إذا كان العميل متصلاً بالفعل ، فلن يؤدي فشل إحدى العقد إلى التوقف. ولكن إذا كانت العقدة الأولى غير متوفرة ، فلن يكون من الممكن الاتصال في حالة انقطاع الجلسة. للقيام بذلك ، عند التثبيت ، يمكنك تمرير معلمة backupvolfile التي تشير إلى العقدة الثانية.
mount.glusterfs gluster-01.example.com:/main /gluster -o backupvolfile-server=gluster-02.example.com

نقطة مهمة: لم تتم مزامنة الملفات بين العقد إلا إذا تم تغييرها من خلال وحدة التخزين المركبة. إذا قمت بإجراء تغييرات مباشرة على العقد ، فلن يكون الملف متزامنًا.

الاتصال Kubernetes


في هذه المرحلة ، بدأت الأسئلة: "كيف تربطها؟". وهناك عدة خيارات. اعتبرهم.

هيكيتي


الأكثر شيوعًا والموصى به هو استخدام خدمة خارجية: heketi. heketi عبارة عن طبقة بين kubernetes واللمعان ، والتي تتيح لك إدارة التخزين والعمل من خلال http. لكن heketi ستكون تلك النقطة الوحيدة من الفشل ، لأن لم يتم تجميع الخدمة. المثال الثاني من هذه الخدمة لن يتمكن من العمل بشكل مستقل ، لأنه يتم تخزين أي تغييرات في قاعدة البيانات المحلية. تشغيل هذه الخدمة في kubernetes ليس مناسبًا أيضًا إنه يحتاج إلى قرص ثابت يتم تخزين قاعدة بياناته عليه. في هذا الصدد ، تبين أن هذا الخيار هو الأكثر ملاءمة.

نقطة النهاية في Kubernetes


إذا كان لديك Kubernetes على الأنظمة مع مديري الحزم ، فهذا خيار مناسب للغاية. النقطة الأساسية هي أنه بالنسبة لجميع خوادم GlusteFS في Kubernetes ، يتم إنشاء نقطة نهاية مشتركة. تم تعليق الخدمة على نقطة النهاية هذه وسيتم تحميلنا بالفعل على هذه الخدمة. لكي يعمل هذا الخيار ، من الضروري تثبيت glusterfs-client على كل عقدة Kubernetes والتأكد من إمكانية تثبيته. في Kubernetes ، قم بنشر التكوين التالي:

apiVersion: v1
kind: Endpoints
metadata: 
  name: glusterfs-cluster
subsets:
  - addresses:
      #  ip  
      - ip: 10.10.6.71
    ports:
      #    1,    
      - port: 1
  - addresses:
      - ip: 10.10.6.72
    ports:
      - port: 1

---
apiVersion: v1
kind: Service
metadata:
  name: glusterfs-cluster
spec:
  ports:
  - port: 1

الآن يمكننا إنشاء نشر اختبار بسيط والتحقق من كيفية عمل التثبيت. فيما يلي مثال على نشر اختبار بسيط:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gluster-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gluster-test
  template:
    metadata:
      labels:
        app: gluster-test
    spec:
      volumes:
      - name: gluster
        glusterfs:
          endpoints: glusterfs-cluster
          path: main
      containers:
      - name: gluster-test
        image: nginx
        volumeMounts:
        - name: gluster
          mountPath: /gluster

هذا الخيار لا يناسبنا ، لأن لدينا حاوية لينكس على جميع عقد Kubernetes. مدير الحزم غير موجود ، لذلك لم يكن من الممكن تثبيت gluster-client للتثبيت. في هذا الصدد ، تم العثور على الخيار الثالث ، والذي تقرر استخدامه.

GlusterFS + NFS + keepalived


حتى وقت قريب ، عرض GlusterFS خادم NFS الخاص به ، ولكن الآن يتم استخدام الخدمة الخارجية nfs-ganesha لـ NFS. لقد كتب القليل جدًا عن هذا ، فيما يتعلق بهذا سنكتشف كيفية تكوينه.

يجب تسجيل المستودع يدويًا. للقيام بذلك ، في الملف /etc/yum.repos.d/nfs-ganesha.repo نضيف:

[nfs-ganesha]
name=nfs-ganesha
baseurl=https://download.nfs-ganesha.org/2.8/2.8.0/RHEL/el-8/$basearch/
enabled=1
gpgcheck=1
[nfs-ganesha-noarch]
name=nfs-ganesha-noarch
baseurl=https://download.nfs-ganesha.org/2.8/2.8.0/RHEL/el-8/noarch/
enabled=1
gpgcheck=1

وتثبيت:

yum -y install nfs-ganesha-gluster --nogpgcheck

بعد التثبيت ، نقوم بإجراء التكوين الأساسي في الملف /etc/ganesha/ganesha.conf.

# create new
NFS_CORE_PARAM {
    # possible to mount with NFSv3 to NFSv4 Pseudo path
    mount_path_pseudo = true;
    # NFS protocol
    Protocols = 3,4;
}
EXPORT_DEFAULTS {
    # default access mode
    Access_Type = RW;
}
EXPORT {
    # uniq ID
    Export_Id = 101;
    # mount path of Gluster Volume
    Path = "/gluster/main";
    FSAL {
        # any name
        name = GLUSTER;
        # hostname or IP address of this Node
        hostname="gluster-01.example.com";
        # Gluster volume name
        volume="main";
    }
    # config for root Squash
    Squash="No_root_squash";
    # NFSv4 Pseudo path
    Pseudo="/main";
    # allowed security options
    SecType = "sys";
}
LOG {
    # default log level
    Default_Log_Level = WARN;
}

نحتاج إلى بدء الخدمة ، وتمكين nfs لحجمنا والتحقق من تشغيلها.

$ systemctl start nfs-ganesha
$ systemctl enable nfs-ganesha
$ gluster volume set main nfs.disable off
$ gluster volume status main

نتيجة لذلك ، يجب أن تشير الحالة إلى أن خادم nfs بدأ لوحدة التخزين لدينا. تحتاج إلى القيام بالتحميل والتحقق.

mkdir /gluster-nfs
mount.nfs gluster-01.example.com:/main /gluster-nfs

لكن هذا الخيار لا يتسامح مع الأخطاء ، لذلك تحتاج إلى إنشاء عنوان VIP ينتقل بين العقدتين ويساعد في تبديل حركة المرور إذا سقطت إحدى العقد.

يتم تثبيت Keepalived في CentOs على الفور من خلال مدير الحزم.

$ yum install -y keepalived

نقوم بتهيئة الخدمة في الملف /etc/keepalived/keepalived.conf:

global_defs {
    notification_email {
        admin@example.com
    }
    notification_email_from alarm@example.com
    smtp_server mail.example.com
    smtp_connect_timeout 30

    vrrp_garp_interval 10
    vrrp_garp_master_refresh 30
}

#C   ,   .    , VIP .
vrrp_script chk_gluster {
    script "pgrep glusterd"
    interval 2
}

vrrp_instance gluster {
    interface ens192
    state MASTER #     BACKUP
    priority 200 #      ,  100
    virtual_router_id 1
    virtual_ipaddress {
        10.10.6.70/24
    }

    unicast_peer {
        10.10.6.72 #        
    }

    track_script {
        chk_gluster
    }
}

يمكننا الآن بدء الخدمة والتحقق من ظهور VIP على العقدة:

$ systemctl start keepalived
$ systemctl enable keepalived
$ ip addr
1: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:97:55:eb brd ff:ff:ff:ff:ff:ff
    inet 10.10.6.72/24 brd 10.10.6.255 scope global noprefixroute ens192
       valid_lft forever preferred_lft forever
    inet 10.10.6.70/24 scope global secondary ens192
       valid_lft forever preferred_lft forever

إذا نجح كل شيء بالنسبة لنا ، فسيظل إضافة PersistentVolume إلى Kubernetes وإنشاء خدمة اختبار للتحقق من العملية.

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: gluster-nfs
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: 10.10.6.70
    path: /main

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: gluster-nfs
spec:
 accessModes:
 - ReadWriteMany
 resources:
   requests:
     storage: 10Gi
 volumeName: "gluster-nfs"

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gluster-test
  labels:
    app: gluster-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gluster-test
  template:
    metadata:
      labels:
        app: gluster-test
    spec:
      volumes:
      - name: gluster
        persistentVolumeClaim:
          claimName: gluster-nfs
      containers:
      - name: gluster-test
        image: nginx
        volumeMounts:
        - name: gluster
          mountPath: /gluster

مع هذا التكوين ، في حالة سقوط العقدة الرئيسية ، سيكون خاملاً لمدة دقيقة تقريبًا حتى يسقط التثبيت في المهلة ويتحول. بسيطة لمدة دقيقة لهذا التخزين ، دعنا نقول أن هذا ليس وضعًا عاديًا ونادراً ما نلتقي به ، ولكن في هذه الحالة سيتحول النظام تلقائيًا ويستمر في العمل ، وسنكون قادرين على حل المشكلة وتنفيذ الاسترداد دون القلق بشأن البساطة.

ملخص


في هذه المقالة ، درسنا 3 خيارات ممكنة لربط GlusterFS بـ Kubernetes ، في نسختنا من الممكن إضافة موفر إلى Kubernetes ، لكننا لسنا بحاجة إليه بعد. يبقى إضافة نتائج اختبارات الأداء بين NFS و Gluster على نفس العقد.

ملفات على 1 ميجا بايت:

sync; dd if=/dev/zero of=tempfile bs=1M count=1024; sync
Gluster: 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 2.63496 s, 407 MB/s
NFS: 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 5.4527 s, 197 MB/s

ملفات على 1 كيلو بايت:

sync; dd if=/dev/zero of=tempfile bs=1K count=1048576; sync
Gluster: 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 70.0508 s, 15.3 MB/s
NFS: 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 6.95208 s, 154 MB/s

يعمل NFS بنفس الطريقة مع أي حجم ملف ، ولا يلاحظ فرق السرعة بشكل خاص ، على عكس GlusterFS ، والذي يتدهور بشدة مع الملفات الصغيرة. ولكن في نفس الوقت ، مع أحجام الملفات الكبيرة ، يُظهر NFS أداء أقل من Gluster بمعدل 2-3 مرات.

All Articles