مستندات فنی

دسترسی به تمامی مستندات محصولات ابر آروان

دسته‌بندی‌های سایت مشاهده دسته‌بندی‌ها بستن دسته‌بندی‌ها

نصب کلاستر Elasticsearch روی پلتفرم ابری آروان

۷ دقیقه
۱۴ بهمن ۹۸

در این مطلب، به مراحل ایجاد یک کلاستر elasticsearch، روی سرویس پلتفرم ابری آروان پرداخته داده شده است. برای این کار از image مربوط به نسخه‌ی 7.5.2 elasticsearch روی repository به آدرس docker.elastic.co استفاده شده است.

هدف از این مقاله، آموزش استفاده از پلتفرم ابری آروان برای ایجاد برنامه‌های کاربردی، مانند پایگاه‌داده‌های توزیع شده یا برنامه‌هایی است که نیاز به حافظه دایمی و تعداد بالایی از instance دارند. بنابراین وارد جزییات مربوط به شیوه‌ی استفاده و پیکربندی elasticsearch نمی‌شود.

پیش‌نیازها

تنها پیش نیاز، ساخت حساب کاربری در پنل ابر آروان و سپس ورود به این حساب است. برای ساخت حساب کاربری به سایت ابر آروان بروید و از قسمت ثبت‌نام یک حساب کاربری جدید بسازید یا اگر از پیش حساب کاربری در پنل ابر آروان دارید، با کمک بخش ورود، به آن وارد شوید. سپس به بخش تنظیمات بروید و در زبانه‌ی کلیدهای API، برای خود یک API KEY جدید بسازید و آن را در جایی ذخیره کنید.

برای انجام مراحل این مقاله نیاز است که از command line ابر آروان استفاده کنید. پس از دانلود (در صورت نیاز آن را در PATH خود قرار دهید) و با خط فرمان لاگین کنید:

arvan login

سپس API KEY که از سایت دریافت کردید را در اینجا کپی کنید.

اجزای مورد نیاز

برای ایجاد کلاستر elasticsearch روی پلتفرم ابری آروان اجزایی نیاز است که در ادامه شیوه‌ی ایجاد، ساختار و کار با هریک توضیح داده می‌شود.

معماری سیستم از دید پلتفرم ابری آروان به شکل زیر است که در اینجا تنها برای درک بهتر آورده شده است. در ادامه شیوه‌ی ایجاد هر یک از این اجزا بیان شده است.

 

همان‌طور که در شکل بالا مشخص است، کلاستر شامل سه node داده است که همه‌ی nodeها master-eligible هستند.

ایجاد StatefulSet

StatefulSet یکی از اجزای اصلی است که وظیفه‌ی مدیریت podهایی را که هریک فضای ذخیره‌سازی پایدار جداگانه‌ای دارند، برعهده دارد.

دلیل استفاده از statefulset امکاناتی است که در deployment وجود ندارد و سبب می‌شود تا بتوان به کمک این امکانات (که در ادامه توضیح مختصری درباره‌ی آن‌ها داده می‌شود) مجموعه‌ای از podهای مشابه ولی با فضای ذخیره‌سازی جداگانه‌ را مدیریت کرد.

فایل زیر شامل تمام تنظیمات مربوط به Statefulset برای elasticsearch است. خطوط زیر را کپی و در فایلی به نام elasticsearch-Statefulset.yaml ذخیره کنید.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app: elastic
  name: elastic
spec:
  selector:
    matchLabels:
      app: elastic 
  serviceName: "elastic"
  replicas: 3 
  template:
    metadata:
      labels:
        app: elastic 
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: elastic
        env:
        - name: "pod_name"
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: "node.name"
          value: "$(pod_name).elastic"
        - name: "cluster.name"
          value: "arvan-cluster"
        - name: ES_JAVA_OPTS
          value: "-Xms2048m -Xmx2048m"
        - name: "node.data"
          value: "true"
        - name: "cluster.initial_master_nodes"
          value: "elastic-0.elastic,elastic-1.elastic,elastic-2.elastic"
        - name: "discovery.seed_hosts"
          value: "elastic-0.elastic,elastic-1.elastic,elastic-2.elastic"
        - name: "node.master"
          value: "true"
        - name: "discovery.zen.minimum_master_nodes"
          value: "1"
        image: docker.elastic.co/elasticsearch/elasticsearch:7.5.2
        ports:
        - containerPort: 9200
          name: db
        - containerPort: 9300
          name: transport
        resources:
          limits:
            cpu: '2'
            ephemeral-storage: 4G
            memory: 4G
          requests:
            cpu: '2'
            ephemeral-storage: 4G
            memory: 4G
        volumeMounts:
        - name: elastic-data
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: elastic-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "standard"
      resources:
        requests:
          storage: 10Gi

نکته: توجه کنید که indentation در فایل‌های yaml مهم است و کوچک‌ترین جابه‌جایی می‌تواند سبب برگرداندن خطا یا تنظیمات ناخواسته شود.

توضیح فیلدهای بالا به شرح زیر است:

spec.replica: این فیلد مشخص‌کننده‌ی تعداد podهایی است که به‌وسیله‌ی این StatefulSet ساخته می‌شود. شیوه‌ی نام‌گذاری podها در StatefulSet به‌شکل زیر است:

[statefulset name]-[ordinal number]

spec.serviceName: این فیلد مشخص‌کننده‌ی نام سرویسی است که امکان دسترسی به nodeهای elastic را فراهم می‌کند. نام این فیلد باید معادل metadata.name سرویسی باشد که در بخش بعد ایجاد می‌کنید.

spec.replicas: این فیلد مشخص‌کننده‌ی آن است که چه تعداد pod را این Statefulset بالا می‌آورد. در این مثال تنها به یک کلاستر که دارای سه node است و هرکدام نیز، هم نقش master و هم نقش data دارند، اکتفا شده است.

spec.template.spec.containers.env: مشخص‌کننده‌ی مجموعه‌ای از متغیرهای محیطی است که تنظیمات مرتبط با هریک از instanceهای elasticsearch را ارایه می‌کند. توضیح تعدادی از این متغیرها در ادامه آمده است:

متغیر node.name نام هر کدام از nodeهای elasticsearch را مشخص می‌کند. مقدار این متغیر به‌شکل پیش‌فرض معادل نام pod (یا در نصب معمول روی یک سرور لینوکسی معادل نام Host) قرار می‌گیرد (برای نمونه elastic-0). چون نیاز است تا نام nodeها در کلاستر elasticsearch، قابل دسترس به‌وسیله‌ی سایر nodeها باشد، بنابراین این مقدار معادل نام دامنه‌ای است که به‌وسیله‌ی service ایجاد میکنیم. برای نمونه اگر نام یک instance (یا pod) معادل elastic-0 باشد، نام دامنه‌ای که آن pod در کلاستر به‌وسیله‌ی آن دردسترس خواهد بود، elastic-0.elastic است. بر همین اساس، متغیر node.name هم باید معادل همین مقدار باشد.

بخش اول نام با استفاده از fieldRef و از metadata.name که با نام pod ارجاع می‌شود، قابل دسترس است. برای افزودن .elastic به انتهای این نام برمبنای روش پیشنهادی در پاسخ این سوال، از یک متغیر میانجی (pod_name) استفاده شده است تا مقدار نهایی node.name با استفاده از آن به‌شکل elastic-0.elastic (یا مقادیر 1 یا 2 و …) و مجزا برای هر pod ثبت شود.

برای مقدار متغیرهای discovery.seed_hosts و cluster.initial_master_nodes، نام دامنه‌ی تمامی nodeها (nodeهایی که می‌توانند نقش master داشته باشند) ارایه شده است.

spec.template.spec.containers.volumeMounts: این فیلد مشخص‌کننده‌ی نام دیسک دایمی است که قرار است به container متصل شود. هم‌چنین باید مسیر درون container که قرار است داده‌های آن persist شوند، در این فیلد مشخص شود. برای elasticsearch، طبق راهنمای docker image، این مسیر /data است.

spec.volumeClaimTemplates: با ارایه‌ی این فیلد، دیگر نیازی به تعریف جداگانه persistentVolumeClaim نیست و این بخش برای هر یک از podها یک volumeClaim جداگانه می‌سازد و در اختیار pod قرار می‌دهد. میزان درخواستی در این‌جا 10 GB برای هر pod است.

ایجاد service

نوع serviceای که در این بخش تعریف می‌شود، تفاوت اندکی با serviceای دارد که برای deployment ساخته می‌شود. به این نوع از serviceها Headless Service می‌گویند. تفاوت اصلی این نوع، عدم وجود spec.type  و مقداردهی spec.clusterIP برابر با none است. این service دامنه‌های مورد نیاز برای هر pod را جداگانه ایجاد می‌کند.

فایل زیر شامل تمام تنظیمات مربوط به service برای Statefulset کلاستر elasticsearch است. خطوط زیر را کپی و در فایلی با نام elasticsearch-service.yaml ذخیره کنید.

apiVersion: v1
kind: Service
metadata:
  name: elastic
  labels:
    app: elastic
spec:
  ports:
  - port: 9200
    name: db
  - port: 9300
    name: transport
  clusterIP: None
  selector:
    app: elastic

نکته: توجه کنید که indentation در فایل‌های yaml مهم است و کوچک‌ترین جابه‌جایی می‌تواند سبب برگرداندن خطا و یا تنظیمات ناخواسته شود.

در این Headless Service که به ازای هر pod ساخته شده است یک دامنه‌ی مجزا ساخته شده که داخل کلاستر و به‌وسیله‌ی طریق الگوی زیر دردسترس است:

تا کنون تمام اجزای مورد نیاز کلاستر elasticsearch تعریف شده است و می‌توان به هر یک از nodeهای کلاستر elasticsearch از درون پروژه و روی port های 9200و 9300 دسترسی داشت. اما، جهت مدیریت کلاستر elasticsearch و visualize کردن داده‌ها، نیاز به یک kibana است که به کلاستر elasticsearch دسترسی داشته باشد.

اجزای مورد نیاز برای راه‌اندازی kibana عبارت‌اند از:

ایجاد deployment برای kibana

deployment یکی از اجزای اصلی است که وظیفه‌ی مدیریت podها را برعهده دارد. فایل زیر شامل تمام تنظیمات مربوط به deployment برای وبلاگ است. خطوط زیر را کپی و در فایلی با نام kibana-deployment.yaml ذخیره کنید.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: kibana
  name: kibana
spec:
  Strategy: 
    type: Recreate
  selector:
    matchLabels:
      app: kibana
  replicas: 1
  template:
    metadata:
      labels:
        app: kibana
    spec:
      containers:
      - image: docker.elastic.co/kibana/kibana:7.5.2
        env:
        - name: ELASTICSEARCH_HOSTS
          value: "http://elastic-0.elastic:9200"
        imagePullPolicy: IfNotPresent
        name: kibana
        ports:
        - containerPort: 5601
          name: http
        resources:
          limits:
            cpu: '1'
            ephemeral-storage: 2G
            memory: 2G
          requests:
            cpu: '1'
            ephemeral-storage: 2G
            memory: 2G
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
    dnsPolicy: ClusterFirst
    restartPolicy: Always

نکته: توجه کنید که indentation  در فایل‌های yaml مهم است و کوچک‌ترین جابه‌جایی می‌تواند سبب برگرداندن خطا و یا تنظیمات ناخواسته شود.

در ادامه فیلدهای مربوطه توضیح داده می‌شود.

spec.template.spec.containers.env: با متغیر محیطی، url یکی از podهای کلاستر elasticsearch به kibana، برای اتصال، ارایه می‌شود (هم‌چنین می‌توان به‌جای نام دامنه‌ی یکی از podها از نام دامنه‌ی service استفاده کرد. مثال: http://elastic:9200.com)

چون kibana داده‌های خود را در index مربوطه در elasticsearch قرار می‌دهد، نیازی به استفاده از دیسک دایمی برای این deployment نیست.

ایجاد service

چون لازم است از بیرون کلاستر به pod kibana درخواست زده شود، برای دسترسی بیرونی باید یک route تعریف شود. اما خود route نمی‌تواند به‌شکل مستقیم به container درخواست بزند و نیاز به تعریف یک service است.

فایل زیر شامل تمام تنظیمات مربوط به service برای deployment kibana است. خطوط زیر را کپی و در فایلی با نام kibana-service.yaml ذخیره کنید.

apiVersion: v1
kind: Service
metadata:
  labels:
    app: kibana
  name: kibana-service
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 5601
  selector:
    app: kibana
  type: ClusterIP

نکته: توجه کنید که indentation در فایل‌های yaml مهم است و کوچک‌ترین جابه‌جایی می‌تواند سبب برگرداندن خطا و یا تنظیمات ناخواسته شود.

ایجاد route

در انتها برای دسترسی وبلاگ از خارج پلتفرم ابری آروان و از اینترنت لازم است یک دامنه مشخص شود و به service مربوط به deployment kibana متصل شود.

فایل زیر شامل تمام تنظیمات مربوط به route برای deployment kibana است. خطوط زیر را کپی و در فایلی با نام kibana-route.yaml ذخیره کنید.

kind: Route
apiVersion: route.openshift.io/v1
metadata:
  name: kibana
  labels:
    app: kibana-route
  annotations:
spec:
  host: kibana-example-project.apps.ir-thr-at1.arvan.run
  port:
    targetPort: http
  tls:
    insecureEdgeTerminationPolicy: Allow
    termination: edge
  to:
    kind: Service
    name: kibana-service
    weight: 100
  wildcardPolicy: None
          

 

تمامی فایل‌های مورد نیاز برای ساخت یک وبلاگ روی پلتفرم ابری آروان تعریف شده است. ساختار نهایی فایل‌های مورد نیاز به شکل زیر است.

حال با دستورات زیر این فایل‌ها را که در واقع مشخص‌کننده‌ی ماهیت اجزایی مورد نیاز است، به پلتفرم ارایه کنید.

arvan paas apply -f elasticsearch-service.yaml
arvan paas apply -f elasticsearch-Statefulset.yaml
arvan paas apply -f kibana-deployment.yaml
arvan paas apply -f kibana-service.yaml
arvan paas apply -f kibana-route.yaml

پس از چند لحظه تمامی اجزا ساخته شده، و از url مشخص شده به آدرس

http://kibana-example-project.apps.ir-thr-at1.arvan.run

می‌توانید پنل kibana خود را مشاهده کنید.

هم‌چنین پس از انجام تمامی مراحل بالا می‌توان تعداد nodeهای کلاستر elasticsearch را به سادگی افزایش داد.

دستور زیر، تعداد nodeهای کلاستر را از ۳ به ۴ عدد افزایش می‌دهد.

arvan paas scale sts elastic --replicas 4

پس از اعمال دستور بالا، statefulset یک pod دیگر بالا می‌آورد و اگر تنظیمات مربوط به elasticsearch درست باشد، node به‌شکل خودکار به کلاستر elasticsearch اضافه می‌شود.

توجه کنید که دستور افزایش تعداد instanceها تنها جهت نمایش دادن کارایی سیستم آورده شده است و تغییر در تعداد nodeهای کلاستر elasticsearch نیازمند مجموعه‌ای از اقدامات در سطح مدیریت کلاستر، پیش و پس از تغییر تعداد nodeها، است. چون این اقدامات مربوط به مدیریت کلاستر elasticsearch است، در حوزه‌ی مطالب این مقاله نیست و مطالعه‌ی آن وابسته به علاقه‌ی کاربر است.