تو این پست قراره مراحل راهاندازی کلاستری ردیس روی کوبرنتیز رو آموزش بدیم. پس ما با این پیشفرض که شما با کوبرنتیز آشنایی کافی دارید پیش میرویم.
قبل از هر چیزی معماری که مد نظرمونه، اینه که کلاستر ردیس بر روی 3 ماشین مجازی با 3 نود مستر و با 4 نود اسلیو به ازای هر مستر با پخش هر ماشین 1 مستر و 4 اسلیو و اسلیوهای هر مستر بر روی تمامی ماشین ها وجود داشته باشد.
پس برای مثال نود هایی داخل هر نود به این شکل باشد:
ماشین 1: مستر 1- اسلیو مستر 1-اسلیو مستر 1-اسلیو مستر 2-اسلیو مستر 3
ماشین 2: مستر 2- اسلیو مستر 1-اسلیو مستر 2-اسلیو مستر 2-اسلیو مستر 3
ماشین 3: مستر 3- اسلیو مستر 1-اسلیو مستر 2-اسلیو مستر 3-اسلیو مستر 3
برای این کار ما ابتدا باید 15 اینستنس ردیس بر روی تمامی نود ها ایجاد کنیم یعنی هر ماشین مجازی 5 نود ردیس را شامل شود.
پس برای این کار ابتدا namespace به نام redis میسازیم:
#file: ns.yml apiVersion: v1 kind: Namespace metadata: name: redis
سپس با کد زیر فایل yml را بر روی کلاستر اعمال میکنیم:
kubectl apply -f ns.yml
اما برای ارتباط با ردیس و ارتباط ردیس باهم دیگر ما به یک سرویس نیاز داریم. پس سرویس زیر رو خواهیم داشت:
#file: svc.yml apiVersion: v1 kind: Service metadata: name: redis-cluster namespace: redis spec: ports: - port: 6379 targetPort: 6379 name: client selector: app: redis-cluster
سپس با کد زیر فایل yml را بر روی کلاستر اعمال میکنیم:
kubectl apply -f svc.yml
با اعمال این فایل یک سرویس با نام redis-cluster بر روی namespace ردیس با هدف ارتباط پاد هایی با نام redis-cluster ساخته خواهد شد که پورت 6379 را برامون اکسپوز کنه.
قبل از اجرای instance های ردیس ما نیاز داریم تا تنظیماتی را ایجاد کنیم. برای این کار ما از ConfigMap کوبر استفاده میکنیم تا تنظیمات مورد نیاز بر روی تمام instance ها اجرا شوند:
#file: cm.yml apiVersion: v1 kind: ConfigMap metadata: name: redis-cluster namespace: redis data: update-node.sh: | #!/bin/sh REDIS_NODES="/data/nodes.conf" sed -i -e "/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/${POD_IP}/" ${REDIS_NODES} exec "$@" redis.conf: | cluster-enabled yes cluster-require-full-coverage no cluster-node-timeout 15000 cluster-config-file /data/nodes.conf cluster-migration-barrier 1 appendonly no protected-mode no requirepass پسورد tcp-keepalive 0 save 1800 1 save 86400 1
بعد از اجرای این فایل یک ConfigMap با دو فایل براتون ایجاد میشه که توضیحات هر فایل رو میدیم:
فایل update-node.sh
در کوبر زمانی که یکی از اینستنس های شما به هر دلیلی ریستارت شود یا از بین برود موقعی که دوباره اجرا شود یک ایپی جدیدی دریافت خواهد کرد و دیگر با ایپی قبلی در کلاستر شناخته نخواهد شد. با استفاده از این فایل قبل از این که اینستنس ردیس دوباره اجرا شود ایپی جدید خودش را داخل فایل /data/nodes.conf اپدیت خواهد کرد. این فایل تمام اطلاعات کلاستر را ذخیره میکند.
فایل redis.conf:
در این فایل تمام تنظیمات مورد نیاز کلاستر نوشته میشود برای این که به صورت دیفالت کلاستر ردیس شما با پسورد لاگین شود جایی که کلمه "پسورد" نوشته شده باید پسورد خودتون رو وارد کنید.
داکیومنتیشن کامل تنظیمات را داخل سایت ردیس میتوانید بخوانید.
تمام تنظیمات و سرویس های مورد نیاز ساخته شد.
اما در مقاله Redis Persisting Data خواندیم، برای این که اطلاعات ما پایدار بماند نیاز داریم تا دیتا های ما داخل هارد دیسک هاستمون پرسیست شود. ما میتوانیم pv و pvc ثابت بسازیم و داخل این ها دیتا هامون رو ذخیره کنیم. اما مشکلی که وجود داره اینه که ما بر روی یک هاست 5 اینستنس ردیس اجرا میکنیم که در این شرایط یک ادرس از هاست به 5 نود mount خواهد شد. که این اتفاق باعث میشود فقط یک اینستنس ردیس اجرا شود و باقی اینستنس ها با ارور مواجه شوند. پس ما نیاز داریم تا instance های مختلف را بر روی ادرس های تصادفی mount کنیم. به صورت پیشفرض کوبر هیچ StorageClass برای این کار وجود ندارد. ما نیاز داریم تا یک StorageClass و یک سرویسی که بتواند ادرس تصادفی ایجاد کند برای این کار از سرویس rancher local path استفاده خواهیم کرد. برای نصب این سرویس، کد زیر را اجرا کنید:
kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.23/deploy/local-path-storage.yaml
سپس نوبت ایجاد 15 پاد اینستنس ردیس رسید برای این کار statefulset زیر رو خواهیم داشت:
#file: sts.yml apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-cluster namespace: redis spec: serviceName: redis-cluster replicas: 15 persistentVolumeClaimRetentionPolicy: whenDeleted: Retain whenScaled: Retain volumeClaimTemplates: - metadata: name: redis-data-pvc spec: accessModes: - ReadWriteOnce storageClassName: local-path resources: requests: storage: 20Gi selector: matchLabels: app: redis-cluster template: metadata: labels: app: redis-cluster spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - redis1 - redis2 - redis3 containers: - name: redis image: redis:latest ports: - containerPort: 6379 command: ["/conf/update-node.sh", "redis-server", "/conf/redis.conf"] env: - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP volumeMounts: - name: conf mountPath: /conf readOnly: false - name: redis-data-pvc mountPath: /data readOnly: false volumes: - name: conf configMap: name: redis-cluster defaultMode: 0755
با اعمال این فایل یک sts با نام redis-cluster بر روی namespace ردیس ساخته خواهد شد. که این sts بر روی سرور های redis1 , redis2 , redis3 پاد هایی که شامل کانتینر redis هست و pvc , pv های مورد نیاز را خواهد ساخت.
در مقاله راه اندازی Redis (Cluster) بخش 1 ( آشنایی) ما گفتیم که در حالت کلاستر ، ردیس جوابی که در ارتباط اولیه بهمون میده دستور MOVE به یک نود با ایپی که فقط داخل شبکه کوبر در دسترس هست میده. پس ما نیاز داریم که یک سرویسی این دستورات MOVE را داخل کوبر اجرا کرده و جواب نهایی را بهمون برگرداند که به اصطلاح به این سرویس proxy گفته میشود. ما از سرویس predixy برای این منظور استفاده خواهیم کرد. پس قبل از اجرای اینستنس های ردیس پروکسی سرور را راه اندازی میکنیم.
#file: predixy.yml apiVersion: v1 kind: ConfigMap metadata: name: redis-proxy data: auth.conf: | Authority { Auth { Mode write } Auth "پسورد" { Mode admin } } latency.conf: | LatencyMonitor all { Commands { + all - blpop - brpop - brpoplpush } TimeSpan { + 100 + 200 + 300 + 400 + 500 + 600 + 700 + 800 + 900 + 1000 + 1200 + 1400 + 1600 + 1700 + 1800 + 2000 + 2500 + 3000 + 3500 + 4000 + 4500 + 5000 + 6000 + 7000 + 8000 + 9000 + 10000 } } LatencyMonitor get { Commands { + get } TimeSpan { + 100 + 200 + 300 + 400 + 500 + 600 + 700 + 800 + 900 + 1000 } } LatencyMonitor set { Commands { + set + setnx + setex } TimeSpan { + 100 + 200 + 300 + 400 + 500 + 600 + 700 + 800 + 900 + 1000 } } LatencyMonitor blist { Commands { + blpop + brpop + brpoplpush } TimeSpan { + 1000 + 2000 + 3000 + 4000 + 5000 + 6000 + 7000 + 8000 + 9000 + 10000 + 20000 + 30000 + 40000 + 50000 + 60000 + 70000 + 80000 + 90000 + 100000 } } predixy.conf: | Name PredixyExample Bind 0.0.0.0:6379 WorkerThreads 5 ClientTimeout 300 LogVerbSample 0 LogDebugSample 1 LogInfoSample 10000 LogNoticeSample 1 LogWarnSample 1 LogErrorSample 1 Include auth.conf Include try.conf Include latency.conf try.conf: | ClusterServerPool { MasterReadPriority 100 StaticSlaveReadPriority 50 DynamicSlaveReadPriority 50 RefreshInterval 1 ServerTimeout 1 ServerFailureLimit 10 ServerRetryTimeout 1 Password پسورد KeepAlive 60 Servers { + redis-cluster-0.redis-cluster:6379 + redis-cluster-1.redis-cluster:6379 + redis-cluster-2.redis-cluster:6379 + redis-cluster-3.redis-cluster:6379 + redis-cluster-4.redis-cluster:6379 + redis-cluster-5.redis-cluster:6379 + redis-cluster-6.redis-cluster:6379 + redis-cluster-7.redis-cluster:6379 + redis-cluster-8.redis-cluster:6379 + redis-cluster-9.redis-cluster:6379 + redis-cluster-10.redis-cluster:6379 + redis-cluster-11.redis-cluster:6379 + redis-cluster-12.redis-cluster:6379 + redis-cluster-13.redis-cluster:6379 + redis-cluster-14.redis-cluster:6379 } }
--- #StatefulSet apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-proxy spec: serviceName: redis-proxy selector: matchLabels: app: redis-proxy replicas: 3 template: metadata: labels: app: redis-proxy spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostnam operator: In values: - redis1 - redis2 - redis3 imagePullSecrets: - name: iranlms-key containers: - name: redis image: joyieldInc/predixy:latest ports: - containerPort: 6379 volumeMounts: - name: conf mountPath: /predixy/conf readOnly: false volumes: - name: conf configMap: name: redis-proxy defaultMode: 0755 --- apiVersion: v1 kind: Service metadata: name: redis-proxy spec: externalIPs: - 10.212.183.22 - 10.212.183.23 - 10.212.183.24 ports: - port: 6379 targetPort: 6379 name: client selector: app: redis-proxy
قبل از اجرا کردن این فایل، کلمات "پسورد" را با پسوردی که برای نود های سرویس ردیستون زدید جاگذاری کنید. سپس با زدن کد زیر این فایل را اعمال کنید:
kubectl apply -f predixy.yml
مرسی که این پست رو خوندید، امیدوارم مفید باشه براتون. خوشحال میشم فیدبک هاتون رو داشته باشم :)