۱. خوش آمدید
از اینکه در آزمایشگاه کد Istio Multi Cloud Burst گوگل به ما پیوستید متشکریم. این آزمایشگاه کد نیاز به تجربه عملی در سطح مبتدی با Kubernetes، Node و Go دارد. آنچه شما نیاز خواهید داشت
|
|
آنچه یاد خواهید گرفت
- نحوه ایجاد یک کلاستر Kubernetes در GKE
- نحوه نصب Istio روی خوشه Kubernetes با Helm
- نحوه نصب Istio Multicluster با Helm
- استقرار یک برنامه وب از منبع به Kubernetes
- نوشتن و اعمال قوانین مسیریابی ترافیک به Istio
- معیارهای پرومتئوس
- ساخت و قرار دادن تصاویر کانتینر در داخل یک کلاستر Kubernetes
۲. راهاندازی
میتوانید این آزمایشگاه کد را در هر یک از موارد زیر دنبال کنید:
- پوسته ابری گوگل (توصیه میشود) : پوسته درون مرورگر، همراه با ابزارهای نصبشده
- لپتاپ شما (دستورالعملهای زیر را دنبال کنید)
با پلتفرم ابری گوگل شروع کنید
- اگر حساب GCP ندارید، کارت حساب کاربری رایگان خود را از مربی دریافت کنید.
- به کنسول گوگل کلود بروید و روی «انتخاب پروژه» کلیک کنید:

- «شناسه» پروژه را جایی یادداشت کنید ، سپس برای انتخاب آن روی پروژه کلیک کنید:

گزینه ۱: استفاده از Google Cloud Shell (توصیه میشود)
Cloud Shell یک پوسته خط فرمان در مرورگر شما فراهم میکند که ابزارهای مورد نیاز شما را نصب کرده و به طور خودکار به حساب Google Cloud Platform شما اعتبارسنجی میکند. (اگر نمیخواهید این تمرین را روی Cloud Shell اجرا کنید، به بخش بعدی بروید.)
به Cloud Console بروید و روی «Activate Cloud Shell» در نوار ابزار بالا سمت راست کلیک کنید:

افزودن ابزارها به Cloud Shell
- نصب
kubectx****: با دانلود اسکریپتهای bash از اینجا و قرار دادن آنها در مکانی در $PATH. - نصب
helm****: طبق این دستورالعملها عمل کنید.
روش دیگر این است که این دستورات را اجرا کنید تا هر دو را در ~/.bin نصب کنید و آن را به $PATH خود اضافه کنید:
mkdir -p ~/.bin && \
cd ~/.bin && \
curl -LO https://raw.githubusercontent.com/ahmetb/kubectx/master/kubectx && \
chmod +x kubectx && \
curl -LO https://raw.githubusercontent.com/ahmetb/kubectx/master/kubens && \
chmod +x kubens && \
curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.12.0-linux-amd64.tar.gz && \
tar xzf helm-v2.12.0-linux-amd64.tar.gz && \
rm helm-v2.12.0-linux-amd64.tar.gz && \
mv linux-amd64/helm ./helm && \
rm -r linux-amd64 && \
export PATH=${HOME}/.bin:${PATH}
چند نکته سریع که میتواند استفاده از Cloud Shell را آسانتر کند:
۱. پوسته را در یک پنجره جدید جدا کنید: |
|
۲. استفاده از ویرایشگر فایل: برای اجرای ویرایشگر فایل درون مرورگر، روی آیکون مداد در بالا سمت راست کلیک کنید. این گزینه برای شما مفید خواهد بود زیرا ما قطعه کدها را در فایلها کپی خواهیم کرد. |
|
۳. شروع تبهای جدید: اگر به بیش از یک دستور ترمینال نیاز دارید. |
|
۴. متن را بزرگتر کنید: اندازه فونت پیشفرض در Cloud Shell میتواند برای خواندن خیلی کوچک باشد. | Ctrl-+ در لینوکس/ Windows⌘-+ در macOS. |
گزینه ۲: لپتاپ خود را آماده کنید (توصیه نمیشود)
اگر در استفاده از محیط کاری خودتان نسبت به Cloud Shell احساس راحتی بیشتری میکنید، ابزارهای زیر را تنظیم کنید:
- نصب
gcloud:(از قبل روی Cloud Shell نصب شده است.) دستورالعملها را برای نصبgcloudروی پلتفرم خود دنبال کنید. ما از این برای ایجاد یک کلاستر Kubernetes استفاده خواهیم کرد. - نصب
kubectl:(از قبل روی Cloud Shell نصب شده است.) دستور زیر را برای نصب اجرا کنید:
gcloud components install kubectl
دستور زیر را برای تأیید اعتبار gcloud اجرا کنید. از شما خواسته میشود که با حساب گوگل خود وارد شوید. سپس، پروژه از پیش ایجاد شده (که در بالا مشاهده میکنید) را به عنوان پروژه پیشفرض انتخاب کنید. (میتوانید از پیکربندی منطقه محاسباتی صرف نظر کنید):
gcloud init
- نصب
curl:روی اکثر سیستمهای لینوکس/مک از قبل نصب شده است. احتمالاً شما آن را از قبل دارید. در غیر این صورت، نحوه نصب آن را در اینترنت جستجو کنید. - نصب
kubectx****: با دانلود اسکریپتهای bash از اینجا و قرار دادن آنها در مسیری در $PATH - نصب
helm****: طبق این دستورالعملها عمل کنید.
۳. راهاندازی پروژه GCP
APIهای GKE (موتور کوبرنتیز گوگل)، GCR (ثبت کانتینر گوگل) و GCB (ساخت ابری گوگل) را در پروژه خود فعال کنید:
gcloud services enable \ cloudapis.googleapis.com \ container.googleapis.com \ containerregistry.googleapis.com \ cloudbuild.googleapis.com
تنظیم متغیرهای محیطی
ما در طول راهاندازی به طور گسترده با پروژه Google Cloud خود کار خواهیم کرد، بیایید یک متغیر محیطی برای مراجعه سریع تنظیم کنیم.
export GCLOUD_PROJECT=$(gcloud config get-value project)
ما در طول این کارگاه تعدادی کد و فایلهای پیکربندی ایجاد خواهیم کرد، بنابراین بیایید یک دایرکتوری پروژه ایجاد کنیم و به آن تغییر دهیم.
mkdir -p src/istio-burst && \ cd src/istio-burst && \ export proj=$(pwd)
۴. ایجاد خوشه "اولیه" Kubernetes
شما به راحتی میتوانید با استفاده از موتور گوگل کوبرنتیز (GKE) خوشه مدیریتشدهی کوبرنتیز ایجاد کنید.
دستور زیر یک کلاستر Kubernetes ایجاد میکند:
- به نام "اولیه"
- در منطقهی غرب آمریکا،
- آخرین نسخه Kubernetes موجود است،
- با ۴ گره اولیه
export cluster=primary
export zone=us-west1-a
gcloud container clusters create $cluster --zone $zone --username "admin" \
--cluster-version latest --machine-type "n1-standard-2" \
--image-type "COS" --disk-size "100" \
--scopes "https://www.googleapis.com/auth/compute",\
"https://www.googleapis.com/auth/devstorage.read_only",\
"https://www.googleapis.com/auth/logging.write",\
"https://www.googleapis.com/auth/monitoring",\
"https://www.googleapis.com/auth/servicecontrol",\
"https://www.googleapis.com/auth/service.management.readonly",\
"https://www.googleapis.com/auth/trace.append" \
--num-nodes "4" --network "default" \
--enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias
(این کار ممکن است حدود ۵ دقیقه طول بکشد. میتوانید مراحل ایجاد کلاستر را در Cloud Console مشاهده کنید.)
پس از ایجاد کلاستر Kubernetes، gcloud kubectl با اعتبارنامههایی که به کلاستر اشاره میکنند، پیکربندی میکند.
gcloud container clusters get-credentials $cluster --zone=$zone
اکنون باید بتوانید kubectl با کلاستر جدید خود استفاده کنید.
دستور زیر را برای فهرست کردن گرههای Kubernetes کلاستر خود اجرا کنید (آنها باید وضعیت "آماده" را نشان دهند):
kubectl get nodes
تغییر نامهای Kubeconfig برای سهولت استفاده
ما مرتباً بین contextها جابجا خواهیم شد، بنابراین داشتن یک نام مستعار کوتاه برای خوشههایمان مفید است.
این دستور، ورودی kubeconfig که ایجاد کردهاید را به primary تغییر نام میدهد.
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
تنظیم مجوزها:
برای استقرار Istio لازم است که شما مدیر خوشه باشید. این دستور ایمیل مرتبط با حساب Google Cloud شما را به عنوان مدیر خوشه تنظیم میکند.
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
۵. ایجاد خوشه "burst"
دستور زیر یک کلاستر Kubernetes ایجاد میکند:
- به نام "انفجار"
- در منطقهی غرب آمریکا،
- آخرین نسخه Kubernetes موجود است،
- با ۱ گره اولیه
- قابلیت مقیاسبندی خودکار تا ۵ گره
export cluster=burst
export zone=us-west1-a
gcloud container clusters create $cluster --zone $zone --username "admin" \
--cluster-version latest --machine-type "n1-standard-2" \
--image-type "COS" --disk-size "100" \
--scopes "https://www.googleapis.com/auth/compute",\
"https://www.googleapis.com/auth/devstorage.read_only",\
"https://www.googleapis.com/auth/logging.write",\
"https://www.googleapis.com/auth/monitoring",\
"https://www.googleapis.com/auth/servicecontrol",\
"https://www.googleapis.com/auth/service.management.readonly",\
"https://www.googleapis.com/auth/trace.append" \
--num-nodes "1" --enable-autoscaling --min-nodes=1 --max-nodes=5 \
--network "default" \
--enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias
(این کار ممکن است حدود ۵ دقیقه طول بکشد. میتوانید مراحل ایجاد کلاستر را در Cloud Console مشاهده کنید.)
پس از ایجاد کلاستر Kubernetes، gcloud kubectl با اعتبارنامههایی که به کلاستر اشاره میکنند، پیکربندی میکند.
gcloud container clusters get-credentials $cluster --zone=$zone
اکنون باید بتوانید kubectl با کلاستر جدید خود استفاده کنید.
دستور زیر را برای فهرست کردن گرههای Kubernetes کلاستر خود اجرا کنید (آنها باید وضعیت "آماده" را نشان دهند):
kubectl get nodes
تغییر نامهای Kubeconfig برای سهولت استفاده
این دستور ورودی kubeconfig که برای burst ایجاد کردهاید را تغییر میدهد.
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
تنظیم مجوزها:
برای استقرار Istio Remote لازم است که شما مدیر خوشه باشید. این دستور ایمیل مرتبط با حساب Google Cloud شما را به عنوان مدیر خوشه تنظیم میکند.
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
۶. اعمال قوانین فایروال
برای اینکه دو کلاستر ما بتوانند با یکدیگر ارتباط برقرار کنند، باید یک قانون فایروال ایجاد کنیم.
دستورات زیر را اجرا کنید تا یک قانون فایروال در پلتفرم ابری گوگل ایجاد کنید که به خوشههای ما امکان برقراری ارتباط را میدهد.
function join_by { local IFS="$1"; shift; echo "$*"; }
ALL_CLUSTER_CIDRS=$(gcloud container clusters list \
--filter="(name=burst OR name=primary) AND zone=$zone" \
--format='value(clusterIpv4Cidr)' | sort | uniq)
ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}"))
ALL_CLUSTER_NETTAGS=$(gcloud compute instances list \
--filter="(metadata.cluster-name=burst OR metadata.cluster-name=primary) AND metadata.cluster-location=us-west1-a" \
--format='value(tags.items.[0])' | sort | uniq)
ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))
gcloud compute firewall-rules create istio-multicluster-test-pods \
--allow=tcp,udp,icmp,esp,ah,sctp \
--direction=INGRESS \
--priority=900 \
--source-ranges="${ALL_CLUSTER_CIDRS}" \
--target-tags="${ALL_CLUSTER_NETTAGS}" --quiet
ما هر دو کلاستر خود را راهاندازی کردهایم و آمادهایم تا برنامه و Istio خود را روی آنها مستقر کنیم!
۷. مقدمهای بر ایستیو
ایستیو چیست؟
Istio یک صفحه کنترل مش سرویس است که هدف آن "اتصال، ایمنسازی، کنترل و مشاهده سرویسها" است. این کار را به روشهای مختلفی انجام میدهد، اما در درجه اول با قرار دادن یک کانتینر پروکسی ( Envoy ) در هر یک از Kubernetes Pod های مستقر شما. کانتینر پروکسی تمام ارتباطات شبکه بین میکروسرویسها را به همراه یک خط مشی عمومی و هاب تلهمتری ( Mixer ) کنترل میکند.

این سیاستها میتوانند مستقل از Kubernetes Deployments و Services شما اعمال شوند، به این معنی که اپراتور شبکه میتواند فعالیت شبکه را مشاهده کند، سیاستهای شبکه را محدود، تغییر مسیر یا بازنویسی کند بدون اینکه برنامههای مرتبط را مجدداً مستقر کند.
برخی از ویژگیهای مدیریت ترافیک Istio Supports عبارتند از:
- قطع کننده مدار
- تقسیم ترافیک مبتنی بر درصد
- بازنویسی URL
- خاتمه TLS
- بررسیهای بهداشتی
- متعادلسازی بار
برای اهداف این کارگاه، ما بر تقسیم ترافیک مبتنی بر درصد تمرکز خواهیم کرد.
شرایط همکاری ما
خدمات مجازی
یک سرویس مجازی مجموعهای از قوانین مسیریابی ترافیک را تعریف میکند که هنگام آدرسدهی به یک میزبان اعمال میشوند.
دروازه
یک دروازه (Gateway) یک متعادلکننده بار (load balancer) است که در لبه شبکه (mesh) عمل میکند و اتصالات HTTP/TCP ورودی یا خروجی را دریافت میکند. دروازهها میتوانند پورتها، پیکربندیهای SNI و غیره را مشخص کنند.
قانون مقصد
یک DestinationRule سیاستهایی را تعریف میکند که پس از مسیریابی، بر ترافیک در نظر گرفته شده برای یک سرویس اعمال میشوند. این سیاستها پیکربندی مربوط به متعادلسازی بار، اندازهی مخزن اتصال از محفظهی کناری و تنظیمات تشخیص دادههای پرت را مشخص میکنند.
چندخوشهای ایستیو
شاید متوجه شده باشید که وقتی دو خوشه خود را ایجاد کردیم، خوشه primary ما ۴ گره بدون مقیاسبندی خودکار بود و خوشه burst ما ۱ گره با مقیاسبندی خودکار تا ۵ گره بود.
دو دلیل برای این پیکربندی وجود دارد.
ابتدا، میخواهیم سناریوی «رویداد آنلاین» به فضای ابری را شبیهسازی کنیم. در یک محیط روی رویداد آنلاین، به دلیل زیرساخت ثابت، به کلاسترهای مقیاسپذیر خودکار دسترسی ندارید.
دوم، حداقل الزامات برای اجرای Istio، راهاندازی ۴ گره (مطابق تعریف بالا) است. این سوال مطرح میشود: اگر Istio به حداقل ۴ گره نیاز دارد، خوشه burst ما چگونه میتواند Istio را با ۱ گره اجرا کند؟ پاسخ این است که Istio Multicluster مجموعه بسیار کوچکتری از سرویسهای Istio را نصب میکند و با نصب Istio در خوشه اصلی ارتباط برقرار میکند تا قوانین سیاست را بازیابی کرده و اطلاعات تلهمتری را منتشر کند.
۸. بررسی اجمالی معماری برنامه
بررسی اجمالی اجزا
ما یک برنامه سه لایه را با استفاده از NodeJS و Redis مستقر خواهیم کرد.
کارگر
برنامهی کارگر با استفاده از NodeJS نوشته شده است و به درخواستهای ورودی POST HTTP گوش میدهد، عملیات هشینگ را روی آنها انجام میدهد و اگر متغیر محیطی به نام PREFIX تعریف شده باشد، آن مقدار را به هش اضافه میکند. پس از محاسبهی هش، برنامه نتیجه را به کانال " calculation " در سرور Redis مشخص شده ارسال میکند.
ما بعداً از متغیر محیطی PREFIX برای نمایش عملکرد چندخوشهای استفاده خواهیم کرد.
برای مرجع: اینها بستههایی هستند که برنامه از آنها استفاده میکند.
-
body-parser:به ما اجازه میدهد درخواستهای http خود را تجزیه و تحلیل کنیم. -
cors:امکان استفاده از اشتراکگذاری منابع بینمنبعی (Cross Origin Resource Sharing) را فراهم میکند. -
dotenv:تجزیه آسان متغیرهای محیطی -
express:میزبانی وب آسان -
ioredis:کتابخانه کلاینت برای ارتباط با پایگاههای داده Redis -
morgan:گزارشهای ساختاریافتهی خوبی ارائه میدهد
ظاهر (فرانتاند)
فرانتاند ما نیز یک برنامه NodeJS است که با استفاده از اکسپرس، یک صفحه وب را میزبانی میکند. این برنامه فرکانس ورودی کاربر را دریافت کرده و درخواستها را با همان نرخ به برنامه worker ما ارسال میکند. این برنامه همچنین در پیامهای یک کانال Redis به نام " calculation " مشترک میشود و نتایج را در یک صفحه وب نمایش میدهد.
این برنامه از وابستگیهای زیر استفاده میکند.
-
body-parser:به ما اجازه میدهد درخواستهای http خود را تجزیه و تحلیل کنیم. -
dotenv:تجزیه آسان متغیرهای محیطی -
express:میزبانی وب آسان -
ioredis:کتابخانه کلاینت برای ارتباط با پایگاههای داده Redis -
morgan:لاگهای ساختاریافتهی خوبی ارائه میدهد -
request:امکان ایجاد درخواستهای HTTP را فراهم میکند. -
socket.io:امکان ارتباط دو طرفه از صفحه وب به سرور را فراهم میکند.
این صفحه وب از بوتاسترپ برای استایلدهی استفاده میکند و هنگام اجرا، به شکل زیر خواهد بود:

نمودار معماری

نمودار استقرار
ما برنامه نهایی خود را در دو کلاستری که ایجاد کردهایم، مستقر خواهیم کرد. کلاستر primary تمام کامپوننتها ( frontend ، worker و Redis) را در خود مستقر خواهد کرد، اما کلاستر burst فقط برنامه worker را مستقر خواهد کرد.
در اینجا نموداری وجود دارد که دو خوشه را توصیف میکند. کادرهای قرمز رنگ نشاندهنده سرویسهای Kubernetes و کادرهای آبی رنگ نشاندهنده استقرارهای Kubernetes هستند. کادرهای زرد رنگ نشاندهنده نصب Istio هستند.
توجه کنید که چگونه کلاستر burst هنوز سرویسی برای Redis مستقر در خود دارد، حتی با وجود اینکه هیچ Deployment برای Redis در کلاستر وجود ندارد. ما باید این سرویس را در کلاستر داشته باشیم تا Kubernetes DNS بتواند درخواست را حل کند، اما وقتی درخواست واقعاً ارسال میشود، Istio Proxy درخواست را به Redis مستقر در کلاستر primary دوباره مسیریابی میکند.
برنامه نهایی یک Deployment اضافی در کلاستر primary به نام istiowatcher. این همان چیزی است که به ما امکان میدهد وقتی ترافیک ما از یک آستانه مشخص عبور میکند، به صورت پویا و خودکار ترافیک را به burst تغییر مسیر دهیم.

۹. ایجاد فایلهای استقرار برنامه
برای استقرار برنامه خود باید مجموعهای از مانیفستهای Kubernetes ایجاد کنیم.
به دایرکتوری ریشه پروژه بروید و یک پوشه جدید به نام kubernetes ایجاد کنید.
mkdir ${proj}/kubernetes && cd ${proj}/kubernetes
نوشتن frontend.yaml
این کار هم Kubernetes Deployment و هم Service را برای دسترسی به تصویر frontend ما ایجاد میکند.
کد زیر را در frontend.yaml وارد کنید.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend-deployment
labels:
app: frontend
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: gcr.io/istio-burst-workshop/frontend
ports:
- containerPort: 8080
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8080
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/"
port: 8080
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-liveness-probe"
env:
- name: PORT
value: "8080"
- name: PROCESSOR_URL
value: "http://worker-service"
- name: REDIS_URL
value: "redis-cache-service:6379"
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
type: ClusterIP
selector:
app: frontend
ports:
- name: http
port: 80
targetPort: 8080
نکات کلیدی که باید در Deployment به آنها توجه کرد
- ما پورتی را که برنامه روی آن اجرا خواهد شد،
8080تعیین کردهایم. - ما آدرس ورکر را "
http://worker-service" قرار دادهایم و از ویژگی DNS داخلی Kubernetes برای حل مشکل سرویس حاصل استفاده خواهیم کرد. - ما آدرس
REDIS_URLخود را روی "redis-cache-service:6379" تنظیم کردهایم و از ویژگی DNS داخلی Kubernetes برای حل آدرسهای IP حاصل استفاده خواهیم کرد. - ما همچنین کاوشگرهای
livenessوreadinessبرای کانتینر تنظیم کردهایم تا به Kubernetes در مورد زمان راهاندازی و اجرای کانتینر اطلاع دهیم.
نوشتن worker-service.yaml
ما تعریف سرویس Kubernetes را در فایلی جداگانه از تعریف Deployment مینویسیم، زیرا قرار است از این سرویس در چندین خوشه دوباره استفاده کنیم، اما برای هر خوشه یک Deployment متفاوت خواهیم نوشت.
موارد زیر را در worker-service.yaml وارد کنید
apiVersion: v1
kind: Service
metadata:
name: worker-service
spec:
type: ClusterIP
selector:
app: worker
ports:
- name: http
port: 80
targetPort: 8081
فایل worker-primary.yaml را بنویسید.
این همان استقرار worker ای خواهد بود که ما به کلاستر اصلی ارسال خواهیم کرد.
کد زیر را در worker-primary.yaml وارد کنید.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: worker-deployment
labels:
app: worker
spec:
replicas: 1
selector:
matchLabels:
app: worker
template:
metadata:
labels:
app: worker
cluster-type: primary-cluster
spec:
containers:
- name: worker
image: gcr.io/istio-burst-workshop/worker
imagePullPolicy: Always
ports:
- containerPort: 8081
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-liveness-probe"
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
توجه داشته باشید که در این مورد، ما از همان الگوی ارائه کاوشگرهای liveness و readiness و همچنین مشخص کردن متغیرهای محیطی PORT و REDIS_URL برای استفاده برنامه خود پیروی میکنیم.
نکتهی دیگری که در این پیادهسازی باید به آن توجه کرد، عدم وجود متغیر محیطی PREFIX است. این بدان معناست که نتایج محاسبات ما هشهای خام خواهند بود (هیچ پیشوندی برای آنها وجود ندارد).
نکته کلیدی نهایی این پیادهسازی، برچسب cluster-type: primary-cluster است. ما بعداً هنگام انجام مسیریابی ترافیک در Istio Multicluster از آن استفاده خواهیم کرد.
نوشتن redis.yaml
ارتباط از worker ما به frontend از طریق کانال Redis است و به همین دلیل باید یک برنامه Redis را در کلاستر خود مستقر کنیم.
کد زیر را در redis.yaml وارد کنید:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: redis-cache
spec:
template:
metadata:
labels:
app: redis-cache
spec:
containers:
- name: redis
image: redis:alpine
ports:
- containerPort: 6379
readinessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
livenessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
volumeMounts:
- mountPath: /data
name: redis-data
resources:
limits:
memory: 256Mi
cpu: 125m
requests:
cpu: 70m
memory: 200Mi
volumes:
- name: redis-data
emptyDir: {}
این یک پیادهسازی نیمهاستاندارد از یک برنامه Redis است. این یک کانتینر بر اساس تصویر redis:alpine ایجاد میکند، پورتهای مناسب را در معرض نمایش قرار میدهد و محدودیتهای منابع معقولی را تعیین میکند.
نوشتن redis-service.yaml
ما برای ارتباط با برنامه Redis خود به یک سرویس Kubernetes نیاز داریم.
موارد زیر را در redis-service.yaml وارد کنید
apiVersion: v1
kind: Service
metadata:
name: redis-cache-service
spec:
type: ClusterIP
selector:
app: redis-cache
ports:
- port: 6379
targetPort: 6379
این سرویسی به نام redis-cache-service برای دسترسی به Redis Deployment ما فراهم میکند.
۱۰. استقرار برنامه
حالا که ایمیجهایمان به GCR منتقل شده و مانیفستهای Kubernetes نوشته شدهاند، زمان خوبی است که برنامهمان را مستقر کنیم و ببینیم چطور کار میکند!
برای استقرار برنامه، دستورات زیر را اجرا کنید
- مطمئن شوید که در خوشه درست قرار داریم
kubectx primary
- استقرار حافظه نهان Redis
kubectl apply -f redis.yaml
- استقرار سرویس Redis
kubectl apply -f redis-service.yaml
- استقرار فرانتاند
kubectl apply -f frontend.yaml
- استقرار کارگر
kubectl apply -f worker-primary.yaml
- استقرار سرویس Worker
kubectl apply -f worker-service.yaml
ما برنامه خود را در GKE مستقر کردیم. تبریک!
تست
صبر کنید تا پادها آنلاین شوند
kubectl get pods -w
وقتی همه پادها "در حال اجرا" شدند، Ctrl + C را بزنید
NAME READY STATUS RESTARTS AGE frontend-deployment-695d95fbf7-76sd8 1/1 Running 0 2m redis-cache-7475999bf5-nxj8x 1/1 Running 0 2m worker-deployment-5b9cf9956d-g975p 1/1 Running 0 2m
متوجه خواهید شد که ما frontend خود را از طریق LoadBalancer در معرض دید قرار ندادیم. دلیلش این است که بعداً از طریق Istio به برنامه دسترسی خواهیم داشت. برای آزمایش اینکه همه چیز در حال اجرا است، kubectl port-forward. دستور زیر را اجرا کنید تا پورت 8080 را روی دستگاه محلی (یا Cloud Shell) خود به پورت 8080 که در حال اجرای استقرار frontend است، هدایت کنید.
kubectl port-forward \
$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}') \
8080:8080
اگر به صورت محلی اجرا میکنید : یک مرورگر وب باز کنید و به آدرس http://localhost:8080 بروید.
اگر در Cloud Shell اجرا میکنید: روی دکمهی «پیشنمایش وب» کلیک کنید و «پیشنمایش روی پورت ۸۰۸۰» را انتخاب کنید.

شما باید ظاهر برنامه را ببینید! و اگر عددی را در کادر "تعداد دفعات" وارد کنید، باید شاهد ظاهر شدن هشتگها باشید.

تبریک میگویم؛ همه چیز روبراه شد!
برای متوقف کردن فوروارد کردن پورت، Ctrl+C را فشار دهید.
۱۱. پاکسازی برنامهی مستقر
ما قصد داریم Istio را روی کلاستر خود اعمال کنیم و سپس برنامه خود را مجدداً مستقر کنیم، بنابراین ابتدا برنامه فعلی خود را پاکسازی میکنیم.
دستورات زیر را اجرا کنید تا تمام Deploymentها و سرویسهایی که ایجاد کردهاید حذف شوند.
-
redis-cache-serviceحذف کنید
kubectl delete -f redis-service.yaml
- حذف
redis
kubectl delete -f redis.yaml
- حذف
frontend
kubectl delete -f frontend.yaml
- حذف
worker
kubectl delete -f worker-primary.yaml
- حذف
worker-service
kubectl delete -f worker-service.yaml
۱۲. نصب Istio روی کلاستر اصلی
دریافت ایستیو
نسخههای Istio در GitHub میزبانی میشوند. دستورات زیر نسخه ۱.۰.۰ istio را دانلود و از حالت فشرده خارج میکنند.
- به ریشه پروژه خود تغییر دهید
cd ${proj}
- بایگانی را دانلود کنید
curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
- بایگانی را استخراج و حذف کنید
tar xzf istio-1.0.0-linux.tar.gz && rm istio-1.0.0-linux.tar.gz
ایجاد الگوی Istio
اجرای دستور Helm زیر، الگویی برای نصب Istio در کلاستر شما ایجاد میکند.
helm template istio-1.0.0/install/kubernetes/helm/istio \ --name istio --namespace istio-system \ --set prometheus.enabled=true \ --set servicegraph.enabled=true > istio-primary.yaml
این دستور فایلی با نام istio-primary.yaml در دایرکتوری فعلی شما ایجاد میکند که شامل تمام تعاریف و مشخصات مورد نیاز برای استقرار و اجرای Istio است.
به دو پارامتر --set توجه کنید. این دو پارامتر، پشتیبانی از Prometheus و ServiceGraph را به سیستم Istio اضافه میکنند. ما بعداً در این آزمایشگاه از سرویس Prometheus استفاده خواهیم کرد.
استقرار Istio
برای استقرار istio، ابتدا باید یک فضای نام به نام istio-system ایجاد کنیم که Istio Deployments and Services بتواند در آن اجرا شود.
kubectl create namespace istio-system
و در نهایت فایل istio-primary.yaml که با Helm ایجاد کردیم را اعمال کنید.
kubectl apply -f istio-primary.yaml
فضای نام پیشفرض برچسب
Istio با تزریق یک سرویس پروکسی sidecar به هر یک از Deployment های شما کار میکند. این کار به صورت اختیاری انجام میشود، بنابراین باید فضای نام default خود را با istio-injection=enabled برچسبگذاری کنیم تا Istio بتواند به طور خودکار sidecar را برای ما تزریق کند.
kubectl label namespace default istio-injection=enabled
تبریک! ما یک کلاستر راهاندازی شده و در حال اجرا با Istio داریم که آمادهی استقرار برنامهی ماست!
۱۳. اپلیکیشن خود را با Istio Traffic Management مستقر کنید
ایجاد فایلهای پیکربندی مدیریت ترافیک Istio
Istio مشابه Kubernetes عمل میکند، زیرا از فایلهای yaml برای پیکربندی استفاده میکند. در همین راستا، ما باید مجموعهای از فایلها را ایجاد کنیم که به Istio بگویند چگونه ترافیک ما را افشا و مسیریابی کند.
یک دایرکتوری با نام istio-manifests ایجاد کنید و به آن بروید.
mkdir ${proj}/istio-manifests && cd ${proj}/istio-manifests
نوشتن frontend-gateway.yaml
این فایل، کلاستر Kubernetes ما را به شیوهای مشابه GKE LoadBalancer در معرض نمایش قرار میدهد و تمام ترافیک ورودی را به سرویس frontend ما هدایت میکند.
یک فایل با نام frontend-gateway.yaml ایجاد کنید و موارد زیر را در آن قرار دهید.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: frontend-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: frontend-ingress-virtual-service
spec:
hosts:
- "*"
gateways:
- frontend-gateway
http:
- route:
- destination:
host: frontend-service
port:
number: 80
نوشتن redis-virtualservice.yaml
یک فایل با نام redis-virtualservice.yaml ایجاد کنید و کد زیر را در آن قرار دهید:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: redis-virtual-service
spec:
hosts:
- redis-cache-service
gateways:
- mesh
tcp:
- route:
- destination:
host: redis-cache-service.default.svc.cluster.local
نوشتن worker-virtualservice.yaml
یک فایل با نام worker-virtualservice.yaml ایجاد کنید و کد زیر را در آن قرار دهید:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
port:
number: 80
استقرار سیاستهای مدیریت ترافیک Istio
استقرار سیاستهای Istio به همان شیوهی سایر منابع Kubernetes انجام میشود، با این تفاوت که kubectl apply
- درگاه ما را اعمال کنید
kubectl apply -f frontend-gateway.yaml
- سرویس مجازی Redis ما را اعمال کنید
kubectl apply -f redis-virtualservice.yaml
- خدمات مجازی کارگر ما را اعمال کنید
kubectl apply -f worker-virtualservice.yaml
استقرار برنامه
- به دایرکتوری
kubernetesخود برگردید
cd ${proj}/kubernetes
- استقرار حافظه نهان Redis
kubectl apply -f redis.yaml
- استقرار سرویس Redis
kubectl apply -f redis-service.yaml
- استقرار فرانتاند
kubectl apply -f frontend.yaml
- استقرار کارگر
kubectl apply -f worker-primary.yaml
- استقرار سرویس Worker
kubectl apply -f worker-service.yaml
تأیید
در این مرحله، ما برنامه خود را روی کلاستری با Istio و سیاستهای مدیریت ترافیک مجدداً مستقر کردهایم.
بیایید صبر کنیم تا همه کارهایمان آنلاین شوند
وقتی همه آنها آنلاین شدند، IngressGateway را که در frontend-ingressgateway.yaml پیکربندی کردهایم، دریافت کنید.
$ kubectl -n istio-system get svc istio-ingressgateway NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.36.3.112 35.199.158.10 80:31380/TCP,
یا آدرس <EXTERNAL-IP> را مرور کنید، یا آن را curl کنید تا ظاهر (frontend) را ببینید!
$ curl 35.199.158.10
<!doctype html>
<html>
<head>
<title>String Hashr</title>
<!-- Bootstrap -->
...
۱۴. نصب Istio روی کلاستر "burst"
ما زمان زیادی را صرف راهاندازی و استقرار در کلاستر primary خود کردهایم، اما یک کلاستر کامل دیگر هم برای استقرار در آن داریم!
در این بخش باید متغیرهای پیکربندی را در هر دو خوشه خود دریافت کنیم، بنابراین به دقت توجه کنید که برای هر دستور به کدام خوشه ارجاع داده شدهایم.
ایجاد مانیفست ریموت Istio
درست مانند زمانی که Istio را در کلاستر primary مستقر کردیم، قرار است از Helm برای الگوسازی استقرار istio remote در کلاستر burst استفاده کنیم. با این حال، قبل از انجام این کار، باید اطلاعاتی در مورد کلاستر primary خود به دست آوریم.
جمعآوری اطلاعات خوشه اولیه
تغییر به خوشه primary
kubectx primary
دستورات زیر آدرسهای IP مربوط به پادهای مختلف در کلاستر اصلی را بازیابی میکنند. این آدرسها توسط Istio Remote برای برقراری ارتباط با کلاستر اصلی استفاده میشوند.
export PILOT_POD_IP=$(kubectl -n istio-system get pod -l istio=pilot -o jsonpath='{.items[0].status.podIP}')
export POLICY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=policy -o jsonpath='{.items[0].status.podIP}')
export STATSD_POD_IP=$(kubectl -n istio-system get pod -l istio=statsd-prom-bridge -o jsonpath='{.items[0].status.podIP}')
export TELEMETRY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=telemetry -o jsonpath='{.items[0].status.podIP}')
export ZIPKIN_POD_IP=$(kubectl -n istio-system get pod -l app=jaeger -o jsonpath='{range .items[*]}{.status.podIP}{end}')
ایجاد الگوی از راه دور
حالا ما helm برای ایجاد فایلی به نام istio-remote-burst.yaml استفاده خواهیم کرد که میتوانیم آن را در کلاستر burst مستقر کنیم.
تغییر به ریشه پروژه
cd $proj
helm template istio-1.0.0/install/kubernetes/helm/istio-remote --namespace istio-system \
--name istio-remote \
--set global.remotePilotAddress=${PILOT_POD_IP} \
--set global.remotePolicyAddress=${POLICY_POD_IP} \
--set global.remoteTelemetryAddress=${TELEMETRY_POD_IP} \
--set global.proxy.envoyStatsd.enabled=true \
--set global.proxy.envoyStatsd.host=${STATSD_POD_IP} \
--set global.remoteZipkinAddress=${ZIPKIN_POD_IP} > istio-remote-burst.yaml
نصب Istio Remote روی burst Cluster
برای نصب Istio روی کلاستر burst خود، باید همان مراحل نصب روی کلاستر primary را دنبال کنیم، اما به جای آن باید از فایل istio-remote-burst.yaml استفاده کنیم.
kubecontext را به burst تغییر دهید
kubectx burst
ایجاد فضای نام istio-system
kubectl create ns istio-system
istio-burst.yaml را اعمال کنید
kubectl apply -f istio-remote-burst.yaml
برچسب فضای نام پیشفرض
یک بار دیگر، باید فضای نام default را برچسبگذاری کنیم تا پروکسی بتواند به طور خودکار تزریق شود.
kubectl label namespace default istio-injection=enabled
تبریک! در این مرحله ما Istio Remote را روی کلاستر burst راهاندازی کردهایم. با این حال، در این مرحله، کلاسترها هنوز قادر به برقراری ارتباط نیستند. ما باید یک فایل kubeconfig برای کلاستر burst ایجاد کنیم که بتوانیم آن را در کلاستر primary مستقر کنیم تا آنها را به هم پیوند دهد.
ایجاد kubeconfig برای کلاستر "burst"
تغییر به خوشه انفجاری
kubectx burst
محیط را تنظیم کنید
برای ایجاد یک فایل kubeconfig برای کلاستر، باید اطلاعاتی در مورد آن جمعآوری کنیم.
- نام خوشه را دریافت کنید
CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
- نام سرور کلاستر را دریافت کنید
SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
- نام رمز حساب سرویس
istio-multiرا از مرجع صدور گواهینامه دریافت کنید
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
- دادههای مرجع صدور گواهی ذخیرهشده در رمز قبلی را دریافت کنید
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
- توکن ذخیره شده در راز قبلی را دریافت کنید
TOKEN=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['token']}" | base64 --decode)
ایجاد فایل kubeconfig
با تنظیم تمام متغیرهای محیطی، باید فایل kubeconfig خود را ایجاد کنیم.
cat <<EOF > burst-kubeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ${CA_DATA}
server: ${SERVER}
name: ${CLUSTER_NAME}
contexts:
- context:
cluster: ${CLUSTER_NAME}
user: ${CLUSTER_NAME}
name: ${CLUSTER_NAME}
current-context: ${CLUSTER_NAME}
kind: Config
preferences: {}
users:
- name: ${CLUSTER_NAME}
user:
token: ${TOKEN}
EOF
این دستور یک فایل جدید به نام burst-kubeconfig در دایرکتوری فعلی شما ایجاد میکند که میتواند توسط کلاستر primary برای احراز هویت و مدیریت کلاستر burst مورد استفاده قرار گیرد.
بازگشت به خوشه اصلی
kubectx primary
با ایجاد یک راز و برچسبگذاری آن، kubeconfig را برای "burst" اعمال کنید.
kubectl create secret generic burst-kubeconfig --from-file burst-kubeconfig -n istio-system
رمز را برچسبگذاری کنید تا Istio بداند که از آن برای احراز هویت چندخوشهای استفاده کند.
kubectl label secret burst-kubeconfig istio/multiCluster=true -n istio-system
تبریک! ما هر دو کلاستر را احراز هویت کردهایم و از طریق Istio Multicluster با یکدیگر ارتباط برقرار میکنیم. بیایید برنامه خود را به صورت Cross-Cluster مستقر کنیم.
۱۵. یک برنامه چندخوشهای (Cross-Cluster Application) مستقر کنید
ایجاد استقرارها
به دایرکتوری kubernetes بروید
cd ${proj}/kubernetes
ایجاد استقرار کارگر برای خوشه "burst": worker-burst.yaml
یک فایل با نام worker-burst.yaml ایجاد کنید و موارد زیر را در آن وارد کنید:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: worker-deployment
labels:
app: worker
spec:
replicas: 1
selector:
matchLabels:
app: worker
template:
metadata:
labels:
app: worker
cluster-type: burst-cluster
spec:
containers:
- name: worker
image: gcr.io/istio-burst-workshop/worker
imagePullPolicy: Always
ports:
- containerPort: 8081
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-liveness-probe"
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
- name: PREFIX
value: "bursty-"
توجه کنید که این تقریباً مشابه worker-primary.yaml است که قبلاً ایجاد کردیم. دو تفاوت کلیدی وجود دارد.
اولین تفاوت کلیدی این است که ما متغیر محیطی PREFIX را با مقدار " bursty- " اضافه کردهایم.
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
- name: PREFIX
value: "bursty-"
این یعنی worker ما در burst cluster، تمام hash هایی که ارسال میکند را با پیشوند " bursty- " شروع میکند. میتوانیم از این موضوع برای اطمینان از اینکه برنامه ما واقعاً بین خوشه ای است، استفاده کنیم.
دومین تفاوت کلیدی این است که ما برچسب cluster-type را در این استقرار از primary-cluster به burst-cluster تغییر دادهایم.
labels:
app: worker
cluster-type: burst-cluster
ما بعداً هنگام بهروزرسانی سرویس مجازی خود از این برچسب استفاده خواهیم کرد.
اصلاح سرویسهای Istio
در حال حاضر سرویسهای Istio ما از هر دو پیادهسازی ما استفاده نمیکنند. ۱۰۰٪ ترافیک ما به خوشه "اصلی" هدایت میشود. بیایید این را تغییر دهیم.
به دایرکتوری istio-manifests خود بروید
cd ${proj}/istio-manifests
worker-virtualservice.yaml را ویرایش کنید تا DestinationRules را نیز شامل شود.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 50
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 50
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: worker-destination-rule
spec:
host: worker-service
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: primary
labels:
cluster-type: primary-cluster
- name: burst
labels:
cluster-type: burst-cluster
میتوانید ببینید که ما یک مقصد دوم به VirtualService خود اضافه کردهایم. این مقصد هنوز به همان میزبان ( worker-service.default.svc.cluster.local) ارجاع میدهد، اما ۵۰٪ از ترافیک به زیرمجموعه primary و ۵۰٪ دیگر به زیرمجموعه burst هدایت میشود.
ما زیرمجموعه primary را به عنوان استقرارهایی تعریف کردهایم که برچسب cluster-type: primary-cluster دارند و زیرمجموعه burst را به عنوان استقرارهایی تعریف کردهایم که برچسب cluster-type: burst-cluster دارند.
این به طور موثر ترافیک ما را به صورت ۵۰/۵۰ بین دو خوشه تقسیم میکند.
استقرار در خوشه
redis-service.yaml را در کلاستر burst مستقر کنید.
تغییر به burst kubeconfig
kubectx burst
به ریشه پروژه ما تغییر دهید
cd ${proj}
سپس مستقر شوید
redis-service.yaml را در کلاستر burst مستقر کنید.
kubectl apply -f kubernetes/redis-service.yaml
worker-burst.yaml را در کلاستر burst مستقر کنید.
kubectl apply -f kubernetes/worker-burst.yaml
worker-service.yaml را در کلاستر burst مستقر کنید.
kubectl apply -f kubernetes/worker-service.yaml
خدمات مجازی Istio را اعمال کنید
تغییر به kubeconfig primary
kubectx primary
سپس مستقر کنید
kubectl apply -f istio-manifests/worker-virtualservice.yaml
تأیید کنید که کار میکند
برای تأیید کارکرد آن، به نقطه Istio Ingress خود مراجعه کنید و توجه کنید که حدود ۵۰٪ از هشها با پیشوند "burst-" شروع میشوند.

این یعنی ما با موفقیت در حال صحبت در مورد خوشههای متقاطع هستیم! سعی کنید وزنها را روی سرویسهای مختلف تغییر دهید و فایل worker-virtualservice.yaml را اعمال کنید. این یک روش عالی برای متعادل کردن ترافیک بین خوشهها است، اما اگر بتوانیم این کار را به صورت خودکار انجام دهیم چه؟
۱۶. استفاده از معیارهای پرومتئوس
مقدمهای بر پرومتئوس
پرومتئوس ، یک جعبه ابزار متنباز برای نظارت و هشداردهی به سیستمهای مختلف است که در ابتدا در ساوندکلاود ساخته شده است. این جعبه ابزار یک مدل داده چندبعدی با دادههای سری زمانی دارد که با نام معیار و جفتهای کلید/مقدار شناسایی میشوند.
برای مرجع، نمودار معماری پرومتئوس در اینجا آمده است:

Istio، هنگامی که با Prometheus مستقر میشود، به طور خودکار معیارهای مختلفی را به سرور Prometheus گزارش میدهد. ما میتوانیم از این معیارها برای مدیریت خوشههای خود در لحظه استفاده کنیم.
بررسی معیارهای پرومتئوس ما
برای شروع، باید Prometheus Deployment را نمایش دهیم.
به برگه Workloads در GKE بروید، و به حجم کار "prometheus" بروید.

پس از مشاهده جزئیات استقرار، به Actions -> Expose بروید.

پورت 9090 را برای ارسال انتخاب کنید و عبارت "Load balancer" را تایپ کنید.

و "افشا" را انتخاب کنید
این یک سرویس روی یک آدرس IP عمومی ایجاد میکند که میتوانیم از آن برای بررسی معیارهای پرومتئوس خود استفاده کنیم.
صبر کنید تا نقطه پایانی عملیاتی شود و پس از آن، روی آدرس IP کنار "نقاط پایانی خارجی" کلیک کنید. 
حالا باید به رابط کاربری Prometheus نگاه کنید.

پرومتئوس معیارهای کافی برای تبدیل شدن به یک کارگاه مستقل را ارائه میدهد. فعلاً، ما با بررسی معیار istio_requests_total شروع میکنیم.
اجرای آن کوئری مجموعهای از دادهها را برمیگرداند. این دادهها، معیارهایی برای تمام درخواستهایی هستند که از شبکه سرویس Istio عبور میکنند و این مقدار زیادی است! ما عبارت خود را تغییر میدهیم تا آنچه را که واقعاً به آن علاقهمند هستیم، فیلتر کنیم:
درخواستهایی که سرویس مقصد آنها worker-service.default.svc.cluster.local و منبع آنها frontend-deployment است که به ۱۵ ثانیه آخر محدود شده است.
آن کوئری به این شکل است:
istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s]
و به ما مجموعهای بسیار قابل مدیریتتر از دادهها برای کار میدهد

اما هنوز کمی پیچیده است. ما میخواهیم تعداد درخواستها در هر ثانیه را بدانیم، نه همه درخواستها را.
برای بدست آوردن آن، میتوانیم از تابع داخلی rate استفاده کنیم.
rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])

این ما را به هدف نزدیکتر میکند، اما باید این معیارها را کمی بیشتر در یک گروه منطقی خلاصه کنیم.
برای انجام این کار میتوانیم از کلمات کلیدی sum و by برای گروهبندی و جمعبندی نتایج خود استفاده کنیم.
sum(rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])) by (source_workload,
source_app, destination_service)

عالیه! ما میتونیم معیارهای دقیقی که نیاز داریم رو از پرومتئوس بگیریم.
آخرین سوال ما در مورد پرومتئوس
با تمام آموختههایمان، آخرین سوالی که باید از پرومتئوس بپرسیم این است که
sum(rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])) by (source_workload,
source_app, destination_service)
حالا میتوانیم از HTTP API آنها برای دریافت معیار استفاده کنیم.
ما میتوانیم با ارسال یک درخواست http GET مانند زیر، از api آنها با کوئری خودمان کوئری بگیریم. <prometheus-ip-here> را جایگزین کنید.
curl http://<prometheus-ip-here>/api/v1/query?query=sum\(rate\(istio_requests_total%7Breporter%3D%22destination%22%2C%0Adestination_service%3D%22worker-service.default.svc.cluster.local%22%2C%0Asource_workload%3D%22frontend-deployment%22%7D%5B15s%5D\)\)%20by%20\(source_workload%2C%0Asource_app%2C%20destination_service\)
در اینجا یک پاسخ نمونه آورده شده است:
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"destination_service": "worker-service.default.svc.cluster.local",
"source_app": "frontend",
"source_workload": "frontend-deployment"
},
"value": [
1544404907.503,
"18.892886390062788"
]
}
]
}
}
حالا میتوانیم مقدار متریک خود را از JSON استخراج کنیم.
پاکسازی
ما باید سرویسی را که برای نمایش پرومتئوس استفاده کردیم، حذف کنیم. در کنسول ابری گوگل، به بالای سرویسی که ایجاد کردهایم بروید و روی «حذف» کلیک کنید.

مراحل بعدی:
پس از یافتن راهی برای کشف چگونگی و نرخ ترافیک در حال عبور از خوشه، گام بعدی ما نوشتن یک فایل باینری کوچک است که به صورت دورهای از prometheus پرسوجو میکند و اگر تعداد درخواستها در هر ثانیه به worker از یک آستانه مشخص بالاتر رفت، وزنهای مقصد مختلفی را روی سرویس مجازی worker خود اعمال میکنیم تا تمام ترافیک را به burst cluster ارسال کند. به محض اینکه تعداد درخواستها در هر ثانیه از یک آستانه پایینتر پایینتر آمد، تمام ترافیک را به primary ارسال میکنیم.
۱۷. یک انفجار خوشه متقاطع ایجاد کنید
راهاندازی
تمام ترافیک مربوط به worker-service را به کلاستر اصلی اختصاص دهید.
ما تمام ترافیکی که برای worker-service در نظر گرفته شده و به خوشه primary هدایت میشود را به عنوان وضعیت "پیشفرض" برنامه خود در نظر خواهیم گرفت.
$proj/istio-manifests/worker-virtualservice.yaml را ویرایش کنید تا به شکل زیر درآید:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 100
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 0
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: worker-destination-rule
spec:
host: worker-service
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: primary
labels:
cluster-type: primary-cluster
- name: burst
labels:
cluster-type: burst-cluster
مطمئن شوید که به خوشه primary متصل هستید
kubectx primary
اعمال istio-manifests/worker-virtualservice.yaml
kubectl apply -f istio-manifests/worker-virtualservice.yaml
نوشتن دیمن istiowatcher
ما از Go برای نوشتن این سرویس به دلیل سرعت و قابلیت حمل آن استفاده خواهیم کرد. جریان کلی برنامه به این صورت خواهد بود که هر ثانیه، prometheus را اجرا و پرس و جو میکند،
یک دایرکتوری جدید در src با نام istiowatcher ایجاد کنید.
mkdir -p ${proj}/src/istiowatcher && cd ${proj}/src/istiowatcher
ما istioctl از درون کانتینر خود فراخوانی خواهیم کرد تا صفحه کنترل Istio را از درون خوشه دستکاری کنیم.
بنویسید istiowatcher.go
یک فایل در آن دایرکتوری با نام istiowatcher.go ایجاد کنید و موارد زیر را در آن قرار دهید.
package main
import (
"github.com/tidwall/gjson"
"io/ioutil"
"log"
"net/http"
"os/exec"
"time"
)
func main() {
//These are in requests per second
var targetLow float64 = 10
var targetHigh float64 = 15
// This is for the ticker in milliseconds
ticker := time.NewTicker(1000 * time.Millisecond)
isBurst := false
// Our prometheus query
reqQuery := `/api/v1/query?query=sum(rate(istio_requests_total{reporter="destination",destination_service="worker-service.default.svc.cluster.local",source_workload="frontend-deployment"}[15s]))by(source_workload,source_app,destination_service)`
for t := range ticker.C {
log.Printf("Checking Prometheus at %v", t)
// Check prometheus
// Note that b/c we are querying over the past 5 minutes, we are getting a very SLOW ramp of our reqs/second
// If we wanted this to be a little "snappier" we can scale it down to say 30s
resp, err := http.Get("http://prometheus.istio-system.svc.cluster.local:9090" + reqQuery)
if err != nil {
log.Printf("Error: %v", err)
continue
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
val := gjson.Get(string(body), "data.result.0.value.1")
log.Printf("Value: %v", val)
currentReqPerSecond := val.Float()
log.Printf("Reqs per second %f", currentReqPerSecond)
if currentReqPerSecond > targetHigh && !isBurst {
applyIstio("burst.yaml")
log.Println("Entering burst mode")
isBurst = true
} else if currentReqPerSecond < targetLow && isBurst {
applyIstio("natural.yaml")
log.Println("Returning to natural state.")
isBurst = false
}
}
}
func applyIstio(filename string) {
cmd := exec.Command("istioctl", "replace", "-f", filename)
if err := cmd.Run(); err != nil {
log.Printf("Error hit applying istio manifests: %v", err)
}
}
نوشتن داکرفایل
یک فایل جدید با نام Dockerfile ایجاد کنید و کد زیر را در آن قرار دهید.
FROM golang:1.11.2-stretch as base
FROM base as builder
WORKDIR /workdir
RUN curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
RUN tar xzf istio-1.0.0-linux.tar.gz
RUN cp istio-1.0.0/bin/istioctl ./istioctl
FROM base
WORKDIR /go/src/istiowatcher
COPY . .
COPY --from=builder /workdir/istioctl /usr/local/bin/istioctl
RUN go get -d -v ./...
RUN go install -v ./...
CMD ["istiowatcher"]
این داکرفایل چند مرحلهای، نسخه ۱.۰.۰ Istio را در مرحله اول دانلود و استخراج میکند. مرحله دوم همه چیز را از دایرکتوری ما در ایمیج کپی میکند، سپس istioctl از مرحله ساخت به /usr/local/bin کپی میکند (تا بتواند توسط برنامه ما فراخوانی شود)، وابستگیها را دریافت میکند، کد را کامپایل میکند و CMD روی " istiowatcher " تنظیم میکند.
نوشتن burst.yaml
این فایلی است که istiowatcher زمانی که تعداد درخواستها در هر ثانیه به worker از frontend از ۱۵ بیشتر شود، اعمال خواهد کرد.
یک فایل جدید با نام burst.yaml ایجاد کنید و کد زیر را در آن قرار دهید.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 0
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 100
بنویسید natural.yaml
ما این را حالت «طبیعی» در نظر میگیریم که وقتی تعداد درخواستها در ثانیه از frontend به worker کمتر از 10 میشود، به آن برمیگردیم. در این حالت، 100٪ ترافیک به خوشه primary هدایت میشود.
یک فایل جدید با نام natural.yaml ایجاد کنید و کد زیر را در آن قرار دهید.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 100
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 0
ساخت و ارسال istiowatcher
دستور زیر را اجرا کنید تا دایرکتوری فعلی به Google Could Build (GCB) ارسال شود، که تصویر را در GCR ساخته و برچسبگذاری میکند.
gcloud builds submit -t gcr.io/${GCLOUD_PROJECT}/istiowatcher
استقرار istiowatcher
به دایرکتوری kubernetes خود بروید
cd ${proj}/kubernetes/
نوشتن یک فایل استقرار: istiowatcher.yaml
فایلی با نام istiowatcher.yaml ایجاد کنید و کد زیر را در آن قرار دهید (به جای <your-project-id> بنویسید).
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: istiowatcher-deployment
labels:
app: istiowatcher
spec:
replicas: 1
selector:
matchLabels:
app: istiowatcher
template:
metadata:
labels:
app: istiowatcher
spec:
serviceAccountName: istio-pilot-service-account
automountServiceAccountToken: true
containers:
- name: istiowatcher
image: gcr.io/<your-project-id>/istiowatcher
imagePullPolicy: Always
استقرار
مطمئن شوید که در کلاستر اصلی در حال اجرا هستیم
kubectx primary
istiowatcher.yaml در فضای نام istio-system مستقر کنید.
kubectl apply -n istio-system -f istiowatcher.yaml
نکتهی مهم این است که دستورالعملهای serviceAccountName و automountServiceAccountToken در yaml وجود دارند. این دستورالعملها اعتبارنامههای لازم برای اجرای istioctl از درون کلاستر به ما میدهند.
ما همچنین باید این را در فضای نام istio-system مستقر کنیم تا مطمئن شویم که اعتبارنامههای مربوط به istio-pilot-service-account داریم (این حساب در فضای نام default وجود ندارد).
تماشا کنید که ترافیک به طور خودکار تغییر میکند!
حالا برای لحظه جادویی! بیایید به بخش فرانتاند خود برویم و req/second را به 20 افزایش دهیم.
توجه کنید که چند ثانیه طول میکشد، اما ما آن را به سرعت افزایش میدهیم و همه هشهای ما پیشوند "bursty-" را دارند!
دلیل این امر این است که ما از پرومتئوس در محدوده 15s نمونهبرداری میکنیم که باعث میشود زمان پاسخ ما کمی تأخیر داشته باشد. اگر میخواستیم محدوده بسیار محدودتری داشته باشیم، میتوانستیم درخواست خود را به پرومتئوس 5s.
۱۸. قدم بعدی چیست؟
پاکسازی
اگر از حساب موقت ارائه شده برای این کارگاه استفاده میکنید، نیازی به پاکسازی ندارید.
میتوانید کلاسترهای Kubernetes، قانون فایروال و تصاویر موجود در GCR را حذف کنید.
gcloud container clusters delete primary --zone=us-west1-a
gcloud container clusters delete burst --zone=us-west1-a
gcloud compute firewall-rules delete istio-multicluster-test-pods
gcloud container images delete gcr.io/$GCLOUD_PROJECT/istiowatcher
رفتن به جلو
- در برخی از گفتگوهای Istio شرکت کنید!
- دریافت گواهینامه: برنامه بعدی خود را با Kubernetes + Istio بسازید
- سخنرانی اصلی: Kubernetes، Istio، Knative: پشته ابری باز جدید - آپارنا سینها، مدیر گروه محصول Kubernetes، گوگل
- آموزش: استفاده از Istio - لی کالکوت و گیریش رانگاناتان، SolarWinds
- Istio - نمای بسته - مت ترنر، Tetrate
- آیا Istio جدیدترین فایروال نسل بعدی است که تاکنون ساخته شده است؟ - جان مورلو، Twistlock
- مستندات Istio را مطالعه کنید
- به گروههای کاری Istio بپیوندید
- در توییتر @IstioMesh را دنبال کنید




