توی این قسمت میریم سراغ اینکه بررسی کنیم چطوری میتونیم یه کلاستر کوبرنتیز رو با استفاده از kubespray ستاپ کنیم و بیاریم بالا. روشی که میتونیم باهاش کلاستر پروداکش رو ستاپ و نگهداری کنیم.

خب یه مروری کنیم پستهای قبلی رو:
دواپس چیه و چرا لازمه؟ اینجا در مورد دواپس و ضرورت استفاده از آن صحبت کردم.
چطور اپلیکیشن مناسب کلاد آماده کنیم؟ و اینجا توضیح دادم که چطور میتونیم یه اپلیکیشن مناسب کلاد توسعه بدیم.
چه عمقی از لینوکس برای دواپس لازمه؟ و اینجا توضیح دادم که کدوم موارد لینوکس برای دواپس الزامی هست که اول سراغ اون موارد بریم.
خودکارش کن,مشکلاتت حل میشه در اینجا در مورد اتومیشن و اینکه انسیبل چیه و چه کمکی به ما میکنه صحبت کردم.
در مسیر دواپس اینبار اجزای اصلی انسیبل تو این پست اجزای انسیبل رو معرفی کردم و آنها را شرح دادم.
در مسیر دواپس به داکر رسیدیم (قسمت اول) تو این پست داکر رو شروع کردیم و اونو معرفی کردیم.
در مسیر دواپس اینبار: پشت داکر چه خبره؟ (قسمت دوم) توی این پست در مورد تکنولوژی هایی که داکر ازشون استفاده میکنه توضیح دادیم.
تست نوشتن و شروع مسیر CI/CD (قسمت اول) توی این پست انواع تست رو بررسی کردیم و با ابزارهای CI/CD آشنا شدیم و یه مقایسه بین گیتلب و جنکینز داشتیم.
در مسیر CI/CD گیت رو بررسی میکنیم (قسمت دوم) توی این پست قبل ورود به گیتلب نیاز بود که گیت و ورژن کنترل سیستم ها رو یه بررسی کنیم.
در مسیر CI/CD شناخت گیتلب (قسمت سوم) توی این پست اجزای گیتلب رو بررسی کردیم و با کامپوننتهای مختلفی که داره بیشتر آشنا شدیم.
در مسیر CI/CD پایپلاین و رانر گیتلب (قسمت چهارم) توی این پست پایپلاین و رانر گیتلب رو بررسی کردیم.
در مسیر CI/CD وریبل، گیتآپس و جمعبندی (قسمت پنجم) توی این پست وریبلهای گیتلب رو بررسی کردیم و یه معرفی کوتاه از گیتآپس و آتودواپس کردیم و در انتها یه مقدار تجربههای خودم رو در گیتلب باهاتون به اشتراک گذاشتم.
در مسیر Observability، الک (قسمت دوم) توی این پست استک قدرتمند ELK رو بررسی کردیم.
در مسیر Observability، جمع بندی استک الک (قسمت سوم) توی این پست بقیه کامپوننتهای استک الک رو بررسی کردیم و fluentd و fluentbit رو مقایسه کردیم و نهایتا یه معرفی هم روی opensearch داشتیم.
در مسیر Observability، استک پرومتئوس (قسمت چهارم) توی این پست یه معرفی اولیه داشتیم روی استک پرومتئوس.
در مسیر Observability، استک پرومتئوس (قسمت پنجم) توی این پست یه مقدار کامپوننت های استک پرومتئوس رو بیشتر بررسی کردیم.
در مسیر Observability، استک ویکتوریا (قسمت ششم) توی این پست استک ویکتوریا رو معرفی کردیم و سعی کردیم با پرومتئوس مقایسهاش کنیم.
در مسیر Observability، میمیر (قسمت هفتم) توی این پست در مورد ابزار میمیر از ابزارهای گرافانا توضیح دادیم و کاربردش رو بررسی کردیم.
در مسیر Observability، لوکی (قسمت هشتم) توی این پست در مورد ابزار گرافانا برای مدیریت لاگ یعنی لوکی توضیح دادیم و آخرشم یه معرفی کوتاه رو graylog داشتیم.
در مسیر Observability، تمپو (قسمت نهم) توی این پست در مورد تریسینگ توضیح دادیم و گرافانا تمپو رو بررسی کردیم و یه معرفی کوتاه روی Jaeger داشتیم
در مسیر Observability، گرافانا (قسمت دهم) توی این پست در مورد گرافانا و HA کردنش و همچنین یه سری از ابزارهاش مثل alloy , incident, on-call توضیح دادیم.
آغاز مسیر کوبر (قسمت اول) تو این قدم به معرفی ابزارهای ارکستریشن پرداختیم و مدارک کوبرنتیز رو بررسی کردیم.
کوبر سینگل ( قسمت دوم ) توی این قدم در مورد kubectl , kubeconfig توضیح دادیم و تعدادی ابزار رو معرفی کردیم که به کمک اونها میتونیم یک کوبرنتیز دمهدستی واسه تستهامون داشته باشیم.
کامپوننتهای کوبر ( قسمت سوم ) توی این پست کامپوننتهای مختلف کوبرنتیز رو بررسی کردیم و اجزای نودهای مستر و ورکر رو دونه دونه بررسی کردیم و توضیح دادیم.
پادها و مدیریت اونها در کوبرنتیز (قسمت چهارم) توی این پست در مورد پاد توی کوبرنتیز توضیح دادیم و موارد مربوط به اون رو بررسی کردیم.
ورکلودهای کوبر و مدیریت منابع کوبر (قسمت پنجم) توی این پست در مورد namespaceها توی کوبر توضیح دادیم و انواع ورکلود کوبر رو بررسی کردیم.
اگه لازم شد کوبر خودش گنده میشه! ( قسمت ششم ) توی این پست در مورد سه نوع ورکلود مرتبط با scaling به صورت خودکار در کوبرنتیز توضیح دادیم.
نتورک کوبر (قسمت هفتم) توی این قسمت انواع سرویس توی کوبرنتیز رو بررسی کردیم و در مورد مفاهیم اینگرس و نتورک پالیسی توضیح دادیم.
استورج کوبرنتیز (قسمت هشتم) توی این قسمت در مورد انواع استورج توی کوبرنتیز توضیح دادیم و مفاهیم PV و PVC و Storage Class رو بررسی کردیم.
پراب، ریکوئست و لیمیت (قسمت نهم) توی این قسمت موارد مربوط به محدود کردن منابع کانتینر توی کوبرنتیز رو بررسی کردیم و در مورد انواع probe ها توی کوبرنتیز توضیح دادیم.
پاد تو نود (قسمت دهم) توی این قسمت درمورد فرآیند انتقال پاد به نود مناسب مفاهیم پیشرفتهتری مثل affinity و anti-affinity و taint و toleration رو بررسی کردیم.
اولویت پاد و امنیت (قسمت یازدهم) توی این قسمت در مورد تعیین اولویت برای پادها و جنبههای مختلف امنیت در کوبرنتیز توضیح دادیم.
کنترل دسترسی به کوبر (قسمت دوازدهم) توی این قسمت در مورد مراحل دسترسی به api کوبرنتیز صحبت کردیم و بعدش مفاهیمی مثل سرویس اکانت رو توضیح دادیم.
دیزاین کلاستر (قسمت سیزدهم) توی این قسمت در مورد طراحی و دیزاین یک کلاستر و روشهای مختلفی که داره توضیح دادیم و همچنین تفاوت روشهای مختلف تقسیم منابع در کلاسترها را بررسی کردیم.
مالتی تننسی در کوبر (قسمت چهاردهم) توی این قسمت چالشهای مربوط به داشتن چند مستاجر بر روی کلاستر کوبرنتیز توضیح دادیم.
هلم (قسمت پانزدهم) توی این قسمت پکیج منیجر معروف کوبرنتیز یعنی Helm رو بررسی کردیم و در موردش ویژگیها و کاربردهاش توضیح دادیم.
سی آر دی و اُپراتور (قسمت شانزدهم) توی این قسمت در مورد اینکه چطوری یه ریسورس کاستوم شده به کلاستر اضافه کنیم توضیح دادیم و مفهوم اُپراتور رو توی کوبر بررسی کردیم.
نصب کلاستر با kubeadm (قسمت هفدهم) توی این قسمت قدم به قدم نحوه نصب یک کلاستر کوبرنتیز رو با استفاده از ابزار kubeadm توضیح دادیم.
نصب کلاستر با kubespray (قسمت هجدهم) توی این قسمت نحوه نصب کلاستر با یه پروژه خیلی خوب به نام کیوب اسپری که یه انسیبل خفن برای ستاپ کلاستر رائه میده رو توضیح دادیم.
نصب کلاستر با rancher (قسمت نوزدهم) توی این قسمت توضیح دادیم که چطور با استفاده از ابزار RKE یک کلاستر کوبرنتیز راهاندازی کنیم.
توصیه میکنم که حتما این پستها رو هم مطالعه کنید. بریم که ادامه بدیم.

توی این بلاگ پست میریم به سراغ بررسی یه ابزار بسیار قدرتمند به اسم kubespray و یاد میگیریم که چجوری میتونیم باهاش یه کلاستر کوبرنتیز رو نصب کنیم. البته ابزار نمیشه بهش گفت. در حقیقت یه انسیبل خیلی بزرگ و کارا هست که میتونیم باهاش کوبرنتیز رو به با مدلهای مختلفی نصب و کانفیگ کنیم.
کیوباسپری در واقع یه کلاس درس تمام عیار برای انسیبل هست، این پروژه انسیبلی هست که به کمک اون میتونیم روی بسترهای مختلف کلاستر کوبرنتیز رو نصب کنیم و آپدیت و ... که نیاز داریم رو به صورت automated انجام بدیم.
ابزار kubeadm دانش حوزهای درباره مدیریت چرخه حیات کلاستر کوبرنتیز را فراهم میکند؛ از جمله پیکربندیهای خودمیزبان (self-hosted layouts)، خدمات کشف پویا (dynamic discovery services) و موارد دیگر. اگر این ابزار در دنیای جدید «اپراتورها» قرار میگرفت، ممکن بود بهعنوان Kubernetes cluster operator نامگذاری شود.
از سوی دیگر، Kubespray وظایف عمومی مدیریت پیکربندی را از دنیای «اپراتورهای سیستمعامل» و Ansible انجام میدهد، علاوه بر اینکه بخشی از فرایند اولیه ایجاد کلاستر کوبرنتیز (بههمراه پلاگینهای شبکه) و راهاندازی control plane را بر عهده دارد.
ابزار Kubespray از نسخه v2.3 به بعد شروع به استفاده درونی از kubeadm برای ایجاد خوشه کرده است تا از دانش حوزهای مدیریت چرخه حیات آن بهره ببرد و وظایف عمومی پیکربندی سیستمعامل را از آن جدا کند.
توی قدم اول باید پروژه رو با تگ مشخص اون ورژنی که میخوایم clone کنیم، دقت کنید که برنچ master رو نگیرید و حتما از ورژنهای استیبل استفاده کنید. اگر از برنچ master استفاده کنید استیبل نیست و آخرین نسخه هست که معمولا با خطاهای زیادی مواجهه میشید.

برای مثال از قسمت Tags گزینه v2.27.0 را انتخاب میکنیم و در این برنچ فایلی با نام requirements.txt وجود دارد به شکل زیر:

در این فایل ورژن انسیبلی که نیاز داریم نوشته شده که در اینجا مثلا 9.13.0 هست، همچنین ورژن سایر پکیجهایی که نیاز دارید در venv مربوطه نصب کنیم نوشته شده. این طوری تمام اون نیازمندی که برای نصب و کانفیگ توسط kubespray داریم رو همون نسخه که نیاز داره رو نصب میکنیم. حتما توصیه میکنم که از virtual env استفاده کنیم که اگر نسخهی دیگهای داریم اونها رو خراب نکنه.
نیازمندی دیگری که داریم این هست که در حالت عادی سرورهامون باید دسترسی به اینترنت برای دریافت ایمیجهای داکر و باینریهای که نیاز داره رو داشته باشند مگر اینکه بخوایم از روشهای نصب برای محیطهای آفلاین استفاده کنیم. اگر بخواهیم این کار رو کنیم باید سرورهای ما دسترسی به ریپوهای آفلاین داشته باشه.
با توجه به مشکلاتی که تو دریافت پکیجها و ایمیجها تو ایران داریم توصیه میکنم یه Nexus بالای دست کلاستر کوبرنتیز خودمون داشته باشیم تا همهی پکیجها و ایمیجهایی که لازم داره رو از اون بگیره.
نیازمندی بعدی این هست که سرورهامون رو کانفیگ کنیم که IPv4 forwarding بر روی اونها به صورت مجاز باشد، همچنین اگه از IPv6 برای سرویسها و پادهاتون استفاده میکنید اون هم باید allowed کنید.
نکته مهم دیگه اینکه این پروژه انسیبل فایروال شما رو مدیریت نمیکنه و خودتون بایستی که تنظیماتی که لازم دارید رو انجام بدید که در این مورد توی پست قبلی یه روشی پیشنهادی رو توضیح دادیم.
دقت کنید که اگر انسیبل رو با کاربری غیر از root ران میکنید بایستی دسترسیهای لازم رو بهش بدید و فلگ become رو ست کنید حتما و کامندتون رو با b- بزنید.
حداقل برای نود مستر 1500MB و برای ورکر 1024MB رم نیاز هست که معمولا اگر برای پروداکشن بخوایم استفاده کنیم اعداد خیلی بیشتر از اینهاست و بسته به اپلیکیشن و نیازمندی که داریم متفاوت هست.
پس کیوباسپری رو کلون میکنیم :)
git clone -b release-2.27 https://github.com/kubernetes-sigs/kubespray.git
بهتره که یه environment پایتونی ایجاد کنیم و مواردیکه توی requirements.txt هست رو توی اون نصب کنیم:
VENVDIR=kubespray-venv KUBESPRAYDIR=kubespray apt install python3.10-venv python3 -m venv $VENVDIR source $VENVDIR/bin/activate cd $KUBESPRAYDIR
# Install requirements package pip install -U -r requirements.txt
یه کپی از فایل سمپلی که توی inventory پروژه هست میگیریم تا تغییراتی که لازم داریم رو توش انجام بدیم:
# Copy inventory/sample as inventory/MeCan cp -rfp inventory/sample inventory/MeCan
توی این فایل سرورها به سه تا گروه زیر تقسیم میشن:
گروه kube_node: لیست همه نودهای کلاستر توی این قسمت قرار میگیره.
گروه kube_control_plane: این قسمت لیست سرورهایی هست که کامپوننتهای نودهای مستر یا control plane روی اونها بالا میاد یعنی api-server و scheduler و controller manager.
گروه etcd: توی این قسمت هم لیست نودهایی که روی اونها etcd بالا میاد رو میذاریم که برای پروداکشن حداقل باید سه تا باشن.
# This inventory describe a HA typology with stacked etcd (== same nodes as control plane) # and 3 worker nodes # See https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html # for tips on building your # inventory # Configure 'ip' variable to bind kubernetes services on a different ip than the default iface # We should set etcd_member_name for etcd cluster. The node that are not etcd members do not need to set the value, # or can set the empty string value.
node1 ansible_host=192.168.200.11 node2 ansible_host=192.168.200.12 node3 ansible_host=192.168.200.13 node4 ansible_host=192.168.200.14 node5 ansible_host=192.168.200.15 node6 ansible_host=192.168.200.16
[kube_control_plane]
node1 node2 node3
[etcd:children]
kube_control_plane
[kube_node]
node1 node2 node3 node4 node5 node6
بعد از اینکه inventory رو درست کردیم حالا میرسه زمان استفاده از playbookهای پروژه، اینجا میتونید یه لیستی از تگ های انسیبلی که این پروژه داره ببینید.
برای مثال کامند زیر فقط تسک های مربوط به DNS configuration رو انجام میده و بقیه موارد رو اسکیپ میکنه:
ansible-playbook -i inventory/MeCan/hosts.ini cluster.yml --tags preinstall,facts --skip-tags=download,bootstrap-os
یا مثلا با استفاده از کامند زیر میتونید DNS resolver ip رو از روی نودهای کلاستر و مسیر etc/resolv.conf/ پاک کنید:
ansible-playbook -i inventory/MeCan/hosts.ini -e dns_mode='none' cluster.yml --tags resolvconf
شناخت انسیبل کیوباسپری مهمه، مخصوصا اینکه بدونید تگی که دارید استفاده میکنید یا skipش میکنید چه کاری رو انجام میده. دستور زیر ایمیجهای مورد نظر رو به صورت locally آماده میکنه، بدون اینکه نصب یا آپگریدی رو انجام بده:
ansible-playbook -i inventory/MeCan/hosts.ini cluster.yml \ -e download_run_once=true -e download_localhost=true \ --tags download --skip-tags upload,upgrade
توی قدم بعدی باید یه سری وریبلهارو تنظیم کنیم که توی فایل group_vars/all/all.yml
هستن.
برای کانفیگ لودبالانسری که برای api-server ها گذاشتیم به شکل زیر عمل میکنیم:
## External LB example config
apiserver_loadbalancer_domain_name: "vip.kubespray.mecan.ir" loadbalancer_apiserver: address: 192.168.200.10 port: 6443
همچنین برای لودبالانسر داخلی میتونیم از این کانفیگ استفاده کنیم:
## Internal loadbalancers for apiservers loadbalancer_apiserver_localhost: true # valid options are "nginx" or "haproxy" loadbalancer_apiserver_type: nginx
اگه میخواید که http_proxy ست کنید برای آپدیت پکیجها و گرفتن ایمیجها میتونید موارد زیر رو اضافه کنید:
http_proxy: "PROXY_ADDRESS:PROXY_PORT" https_proxy: "PROXY_ADDRESS:PROXY_PORT" # https_proxy_cert_file: ""
به مسیر roles/kubespray-defaults/defaults/main.yml هم مراجعه کنید قبل از اینکه تغییری رو در no_proxy ایجاد کنید. حتما لازمه که کانفیگ درستی برای NO_PROXY تنظیم کنید که درخواستهایی که نیاز نیست از روی پروکسی عبور نکنه.
# no_proxy: "10.233.0.0/18,10.233.64.0/18"
همچنین گزینه زیر رو هم true کنید تا cache رو به درستی انجام بده و همینطور گزینه های بعدی برای دیپلوی کردن container engine و مسیر فایل sysctl:
download_container: true # Set false if you want to deploy container engine manually. deploy_container_engine: true sysctl_file_path: "/etc/sysctl.d/99-sysctl.conf"
توی قدم بعدی بایستی که تغییراتی رو در وریبلهای مسیر group_vars/all/containerd.yml ایجاد کنیم و رجیستری های میرور خودمون رو برای container runtime که داریم استفاده میکنیم یعنی containerd ست کنیم:
# Registries defined within containerd.
containerd_registries_mirrors:
- prefix: docker.io
mirrors:
- host: https://hub.mecan.ir
capabilities: ["pull", "resolve"]
- prefix: registry.k8s.io
mirrors:
- host: https://k8s.mecan.ir
capabilities: ["pull", "resolve"]
- prefix: quay.io
mirrors:
- host: https://quay.mecan.ir
capabilities: ["pull", "resolve"]
در گام بعدی باید وریبلهای مرتبط با etcd رو ست کنیم که اینجا هم میتونید داکیومنتش رو ببینید، برای مشخص کردن مسیر دایرکتوری که دیتای etcd در آن ذخیره میشود داریم:
etcd_data_dir: /var/lib/etcd
برای مشخص کردن کانتینر رانتایم مون داریم:
## docker for docker, crio for cri-o and containerd for containerd.
## Additionally you can set this to kubeadm if you want to install etcd using kubeadm
## Kubeadm etcd deployment is experimental and only available for new deployments
## If this is not set, container manager will be inherited from the Kubespray defaults
## and not from k8s_cluster/k8s-cluster.yml, which might not be what you want.
## Also this makes possible to use different container manager for etcd nodes.
container_manager: containerd
و ستینگ برای نحوه دیپلوی شدن etcd که روی kubeadm میذاریم:
# It is possible to deploy etcd with three methods. To change the default deployment method (host), use the etcd_deployment_type variable. Possible values are host, kubeadm, and docker.
etcd_deployment_type: kubeadm
اگه میخواید که پورتی رو برای متریکهای etcd مشخص کنید به شکل زیر عمل میکنیم:
etcd_metrics_port: 2381
و برای url ش هم اگه میخوای که overrideش کنیم به شکل زیر عمل میکنیم:
etcd_listen_metrics_urls: "http://0.0.0.0:2381"
توی گام بعدی میریم سراغ انجام کانفیگهای مرتبط با addon هایی که میخوایم اضافه کنیم به کلاستر در مسیر group_vars/k8s_cluster/addons.yml:
هلم رو enable میکنیم و بعدی برای متریک سرور کانفیگ رو انجام میدیم:
helm_enabled: true
# Metrics Server deployment metrics_server_enabled: true metrics_server_container_port: 10250 metrics_server_kubelet_insecure_tls: true metrics_server_metric_resolution: 15s metrics_server_kubelet_preferred_address_types: "InternalIP,ExternalIP,Hostname" metrics_server_host_network: false metrics_server_replicas: 1
اگر بخواهید میتونید مابقی ادآنهای کوبرنتیز رو هم با استفاده از این کانفیگ انجام بدید. من معمولا مابقی ادآنها رو خودم با Helm و Argo میزنم و از اینجا استفاده نمیکنم.
در قدم بعدی به سراغ فایل group_vars/k8s_cluster/k8s-cluster.yml میرویم. میتونیم بگیم که این فایل مهمترین وریبلها رو داخل خودش داره و کلا کلاسترمون با استفاده از این وریبلها کانفیگ میشه.
اگه میخواید که ورژن دیگهای از کوبرنتیز رو داشته باشید مثلا یه نسخه بتا میتونید به شکل زیر وریبل رو تغییر بدید:
kube_version: v1.31.4
پلاگین نتورک رو مشخص میکنیم بعدش که هم میتونید برای cloud ستش کنید و مواردی مثل cilium, calico, kube-ovn, weave or flannel:
kube_network_plugin: calico
برای تنظیمات مربوط به شبکه داخلی و نتورک سرویسها و پادها داریم:
# Kubernetes internal network for services, unused block of space. kube_service_addresses: 10.233.0.0/18
# internal network. When used, it will assign IP # addresses from this range to individual pods. # This network must be unused in your network infrastructure! kube_pods_subnet: 10.233.64.0/18
مود kube-proxy رو هم اینجا مشخص میکنیم که ما اینجا از iptables استفاه میکنیم:
# Can be ipvs, iptables kube_proxy_mode: iptables
کانفیگ بعدی که اضافه میکنیم مربوط به این هست که پادها به صورت graceful و در چه زمانی خاموش بشن:
# Graceful Node Shutdown (Kubernetes >= 1.21.0), see https://kubernetes.io/blog/2021/04/21/graceful-node-shutdown-beta/
# kubelet_shutdown_grace_period had to be greater than kubelet_shutdown_grace_period_critical_pods to allow
# non-critical podsa to also terminate gracefully
kubelet_shutdown_grace_period: 60s
kubelet_shutdown_grace_period_critical_pods: 20s
کانتینر رانتایم رو هم مشخص میکنیم که برای ما containerd هست:
## docker for docker, crio for cri-o and containerd for containerd. ## Default: containerd container_manager: containerd
خوبه که پالیسی گرفتن ایمیجها رو هم عوض کنیم که در صورتیکه موجود بود دیگه دوباره ایمیج رو pull نکنه:
k8s_image_pull_policy: IfNotPresent
لاگ رو هم true میکنیم که لاگ audit رو هم بتونیم داشته باشیم:
kubernetes_audit: true
توی k8s_cluster هم گزینه زیر رو فعال میکنیم تا یه کپی از کیوب کانفیگ رو به هاست اضافه کنه:
kubeconfig_localhost: true
خوبه که این فضای رزرو رو هم برای kube daemons مشخص کنید:
kube_reserved: true
## Uncomment to override default values
## The following two items need to be set when kube_reserved is true
kube_reserved_cgroups_for_service_slice: kube.slice
kube_reserved_cgroups: "/{{ kube_reserved_cgroups_for_service_slice }}"
kube_memory_reserved: 256Mi
kube_cpu_reserved: 100m
kube_ephemeral_storage_reserved: 2Gi
kube_pid_reserved: "1000"
# Reservation for master hosts
kube_master_memory_reserved: 512Mi
kube_master_cpu_reserved: 200m
kube_master_ephemeral_storage_reserved: 2Gi
kube_master_pid_reserved: "1000"
همینطور رزرو منابع برای سیستمعامل:
system_reserved: true
## Uncomment to override default values
## The following two items need to be set when system_reserved is true
system_reserved_cgroups_for_service_slice: system.slice
system_reserved_cgroups: "/{{ system_reserved_cgroups_for_service_slice }}"
system_memory_reserved: 512Mi
system_cpu_reserved: 500m
system_ephemeral_storage_reserved: 2Gi
## Reservation for master hosts
system_master_memory_reserved: 256Mi
system_master_cpu_reserved: 250m
system_master_ephemeral_storage_reserved: 2Gi
آدرس های تکمیلی که می توانند در کلیدهای kubernetes ssl اضافه شوند. اگر این آدرسها رو به درستی تنظیم نکنیم ممکنه خطای x509 بگیریم و نتونیم با certificate که ساخته شده ارتباط بگیرم.
## That can be useful for example to setup a keepalived virtual IP
supplementary_addresses_in_ssl_keys:
- 192.168.200.10
- 192.168.200.11
- 192.168.200.12
- 192.168.200.13
- vip.kube.mecan.ir
- master1
- master2
- master3
- master1.kube.mecan.ir
- master2.kube.mecan.ir
- master3.kube.mecan.ir
میتونیم ورژن tls هم که ساپورت کنه رو هم تعیین کنیم که گزینههای مختلفی مثل VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13 رو داریم:
tls_min_version: "VersionTLS12"
یا مثلا براش تعیین کنیم که به صورت خودکار در زمانهای مشخصی در هر ماه سرتیفیکیتهای control-plane رو renew کنه:
auto_renew_certificates: true
# First Monday of each month
auto_renew_certificates_systemd_calendar: "Mon *-*-1,2,3,4,5,6,7 03:{{ groups['kube_control_plane'].index(inventory_hostname) }}0:00"
برای آپگرید سیستم هم گزینههای زیر رو ست میکنیم:
system_upgrade: true
system_upgrade_reboot: never
توی فایل group_vars/k8s_cluster/k8s-net-calico.yml هم وریبلهای مربوط به calico رو کانفیگ میکنیم:
# * can-reach=DESTINATION
# * interface=INTERFACE-REGEX
# see https://docs.projectcalico.org/reference/node/configuration
calico_ip_auto_method: "interface=eth.*"
calico_ip6_auto_method: "interface=eth.*"
مود اضافه کردن rule های iptables رو هم میتونیم مشخص کنیم:
calico_felix_chaininsertmode: Insert
برای فعال کردن wireguard که ترافیک calico رو رمزگذاری کنه داریم:
calico_wireguard_enabled: true
همچنین خوبه که liveness و readiness پراب رو هم ست کنیم:
calico_node_livenessprobe_timeout: 10
calico_node_readinessprobe_timeout: 30
تقریبا چیزهایی که لازم بود و خیلی کاربردی بود رو کانفیگ کردیم. مابقی وریبلها هم اگر نیاز داشتید میتونید کانفیگ کنید.
توی بلاگ پست قبلی هم توضیح دادیم، پورتهای لازم رو بین نودها باید باز کنید و یا اینکه میتونید مثل روش زیر نودهای کلاستر رو توی فایروال همدیگه کلا باز کنید:
iptables -A INPUT -s 192.168.200.10/32 -j ACCEPT -m comment --comment "The Trusted lb server"
iptables -A INPUT -s 192.168.200.11/32 -j ACCEPT -m comment --comment "The Trusted master1 server"
iptables -A INPUT -s 192.168.200.12/32 -j ACCEPT -m comment --comment "The Trusted master2 server"
iptables -A INPUT -s 192.168.200.13/32 -j ACCEPT -m comment --comment "The Trusted master3 server"
iptables -A INPUT -s 192.168.200.14/32 -j ACCEPT -m comment --comment "The Trusted worker1 server"
iptables -A INPUT -s 192.168.200.15/32 -j ACCEPT -m comment --comment "The Trusted worker2 server"
iptables -A INPUT -s 192.168.200.16/32 -j ACCEPT -m comment --comment "The Trusted worker3 server"
iptables -A INPUT -s 10.233.0.0/18 -j ACCEPT -m comment --comment "Kubernetes internal network for services"
iptables -A INPUT -s 10.233.64.0/18 -j ACCEPT -m comment --comment "Kubernetes internal network for pod"
اول با کامند زیر ایمیج های لازم رو دانلود میکنیم:
# download tag: Fetching container images to a delegate host
# The option `--become` is required, as for example writing SSL keys in /etc/,
# installing packages and interacting with various systemd daemons.
# Without --become the playbook will fail to run!
ansible-playbook -i inventory/MeCan/inventory.ini cluster.yml --tags=download
بعد از اینکه ایمیجها آماده شد، playbook کلاستر رو با دسترسی root ران میکنیم:
# The option `--become` is required, as for example writing SSL keys in /etc/,
# installing packages and interacting with various systemd daemons.
# Without --become the playbook will fail to run!
ansible-playbook -i inventory/MeCan/hosts.yaml --become --become-user=root cluster.yml
بعد از این مرحله با توجه به سرعت ارتباطی که با سرورها دارید و اینترنتی که در اختیار دارید یه زمانی طول میکشه تا کلاستر شما نصب و کانفیگ بشه.
از یکی از نودهای مستر فایل kubeconfig رو بر میداریم و برای دسترسی به کلاستر به عنوان ادمین از روی لپتاپ خودمون فایل رو با دسترسیها لازم در مسیر مشخص به شکل زیر قرار میدیم:
sudo chown -R $USERNAME:$USERNAME /etc/kubernetes/admin.conf cat /etc/kubernetes/admin.conf > ~/.kube/config
برای اینکه بتونیم با این کانفیگ به کلاستر وصل شیم نیازه که آی پی داخلی و پرایوت که توی کانفیگ هست رو عوض کنیم و به آی پی external مربوط به api-server تغییر دهیم.
بررسی کنیم که آیا متریک سرور به درستی اضافه شده به کلاستر:
kubectl top nodes
نتورک کلاستر رو تست کنیم که ببینیم پادهامون اینترنت دارن یا نه:
kubectl run test-pod-1 -it --rm --image busybox -- ping google.com
یه دیپلویمنت nginx هم با لیبل app=nginx میاریم بالا و تست میکنیم:
kubectl create deployment nginx --image=nginx kubectl get pods -l app=nginx
پورت فوروارد رو انجام میدیم و اکسس به اپلیکیشن رو چک میکنیم:
POD_NAME=$(kubectl get pods -l app=nginx -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 8080:80
لاگ پادمون رو چک میکنیم:
kubectl logs $POD_NAME
یه کامندم توش اجرا میکنیم:
kubectl exec -ti $POD_NAME -- nginx -v
حالا وقتشه که یه سرویس بیاریم بالا که بدون پورت فروارد هم بتونیم ببینیم این پادمون رو، اینجا برای تست از نوع nodeport یه سرویس ایجاد میکنیم:
kubectl expose deployment nginx --port 80 --type NodePort
فایروالم چک میکنیم که باز باشه اون پورت و یه کرل بهش میزنیم :
NODE_PORT=$(kubectl get svc nginx \
--output=jsonpath='{range .spec.ports[0]}{.nodePort}')
curl -I http://${EXTERNAL_IP}:${NODE_PORT}
برای چک کردن DNS هم به شکل زیر عمل میکنیم یه دیپلویمنت busybox میسازیم و پادهاش رو لیست میکنیم:
kubectl run busybox --image=busybox --command -- sleep 3600
kubectl get pods -l run=busybox
اسم پاد رو در میاریم و سرویس کوبرنتیز رو از توی پاد سعی میکنیم چک کنیم:
POD_NAME=$(kubectl get pods -l run=busybox -o jsonpath="{.items[0].metadata.name}")
kubectl exec -ti $POD_NAME -- nslookup kubernetes
در ادامه چک میکنیم که آیا DNS built-in کوبرنتیز بین namespaceهای مختلف هم به درستی کار میکنه یا نه؟ پس به namespace ایجاد میکنیم:
kubectl create namespace dev
حالا یه دیپلویمنت nginx توی این namespace ایجاد میکنیم و پورتش رو اکسپوز میکنیم به بیرون بعدش از توی یه پاد دیگه توی namespace دیفالت سعی میکنیم بهش وصل شیم:
kubectl create deployment nginx --image=nginx -n dev
kubectl expose deployment nginx --port 80 --type ClusterIP -n dev
kubectl run curly -it --rm --image curlimages/curl:7.70.0 -- /bin/sh
curl --head http://nginx.dev:80
میدونیم که موقعی که یه secret توی کوبرنتیز ایجاد میکنیم به صورت رمزگذاری شده در etcd ذخیره میشود نهایتا که اصطلاحا میگیم encryption at rest یعنی موقعیکه دیتا میره توی دیتابیس ذخیره میشه استیبل میشه میخواد استراحت کنه! اونجا رمزگذاری میشه، توی تست بعدی میاییم یه secret درست میکنیم و بعدش به یکی از نودهای کنترلر وصل میشیم و به کمک دستور etcdctl سعی میکنیم اون دیتا رو از دیتابیس بگیریم و ببینیم به چه صورت هست:
kubectl create secret generic kubernetes-the-hard-way --from-literal="mykey=mydata"
لاگین میکنیم به یکی از نودها که etcd روی اون هست، بعدش:
sudo ETCDCTL_API=3 etcdctl get \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
/registry/secrets/default/kubernetes-the-hard-way | hexdump -C
# sample output
00000000 2f 72 65 67 69 73 74 72 79 2f 73 65 63 72 65 74 |/registry/secret|
00000010 73 2f 64 65 66 61 75 6c 74 2f 6b 75 62 65 72 6e |s/default/kubern|
00000020 65 74 65 73 2d 74 68 65 2d 68 61 72 64 2d 77 61 |etes-the-hard-wa|
00000030 79 0a 6b 38 73 00 0a 0c 0a 02 76 31 12 06 53 65 |y.k8s.....v1..Se|
00000040 63 72 65 74 12 db 01 0a bf 01 0a 17 6b 75 62 65 |cret........kube|
00000050 72 6e 65 74 65 73 2d 74 68 65 2d 68 61 72 64 2d |rnetes-the-hard-|
00000060 77 61 79 12 00 1a 07 64 65 66 61 75 6c 74 22 00 |way....default".|
00000070 2a 24 36 32 34 62 32 62 37 62 2d 33 62 30 35 2d |*$624b2b7b-3b05-|
00000080 34 38 66 35 2d 61 62 33 38 2d 31 64 39 39 63 36 |48f5-ab38-1d99c6|
00000090 33 37 33 33 63 65 32 00 38 00 42 08 08 94 a1 d3 |3733ce2.8.B.....|
000000a0 b8 06 10 00 8a 01 62 0a 0e 6b 75 62 65 63 74 6c |......b..kubectl|
000000b0 2d 63 72 65 61 74 65 12 06 55 70 64 61 74 65 1a |-create..Update.|
000000c0 02 76 31 22 08 08 94 a1 d3 b8 06 10 00 32 08 46 |.v1".........2.F|
000000d0 69 65 6c 64 73 56 31 3a 2e 0a 2c 7b 22 66 3a 64 |ieldsV1:..,{"f:d|
000000e0 61 74 61 22 3a 7b 22 2e 22 3a 7b 7d 2c 22 66 3a |ata":{".":{},"f:|
000000f0 6d 79 6b 65 79 22 3a 7b 7d 7d 2c 22 66 3a 74 79 |mykey":{}},"f:ty|
00000100 70 65 22 3a 7b 7d 7d 42 00 12 0f 0a 05 6d 79 6b |pe":{}}B.....myk|
00000110 65 79 12 06 6d 79 64 61 74 61 1a 06 4f 70 61 71 |ey..mydata..Opaq|
00000120 75 65 1a 00 22 00 0a |ue.."..|
00000127
و میبینیم که دیتا به صورت رمزگذاری شده در دیتابیس هست.
گام های بعدی رو به صورت لینک از داکیومنتهایی که توی گیتهاب قرار دادیم براتون میذارم اگه دوست داشتید میتونید اونها رو هم انجام بدید.
توی بلاگ پستهای بعدی مطالب مربوط به کوبرنتیز رو ادامه میدیم و بیشتر با هم یاد میگیریم.
مراقب خودتون باشید. 🌹🐳🌹

خوبه که داکرمی رو تو جاهای مختلف فالو کنید. پذیرای نظرات شما هستیم.
🫀 Follow DockerMe 🫀
🔔 Follow YouTube 🔔
📣 Follow Instagram 📣
🖇 Follow LinkedIn DockerMe🖇
🔎 Follow Linkedin Ahmad Rafiee 🔎
🕊 Follow Twitter 🕊