محسن میرزانیا
محسن میرزانیا
خواندن ۵ دقیقه·۴ سال پیش

کانتینرهای init

کانتینرهای اینیت کانتینرهایی هستن که قبل از اپلیکیشن اصلی داخل یک پاد اجرا می‌شن؛ یکسری کار انجام میدن و پس از مدتی اجراشون تموم میشه. همونطور که میدونیم یک پاد میتونه از یک یا چند کانتینر تشکیل شده باشه که در کنار هم اجرا میشن. اما کانتینرهای اینیت قبل از کانتینرهای دیگه اجرا میشن و پس از مدتی که اجراشون به پایان رسید، نوبت به اجرای کانتینرهای دیگه میرسه. اما اجرای این کانتینرها چه فایده‌ای داره؟ معمولا این کانتینرها شامل ابزارها یا اسکریپت‌هایی میشن که در image اپلیکیشن وجود نداره و لزومی نداره که وجود داشته باشه.

پس کانتینرهای اینیت مثل بقیه‌ی کانتینرها هستن با دو تفاوت اصلی:

  • اجراشون همیشه به پایان میرسه.
  • هر کدام از کانتینرهای اینیت باید با موفقیت به پایان برسن تا کانتینرهای دیگه بتونن شروع به کار کنن.

بنابراین اگه اینیت با موفقیت به پایان نرسه، کوبرنتیز تا زمانی که این اتفاق بیوفته پاد رو restart میکنه. هرچند اگه restartPolicy پاد Never باشه کوبرنتیز پاد رو restart نمیکنه.

اما به جز اون دو تفاوت اصلی که بیان شد، این کانتینرها دیگه چه فرق‌هایی با کانتینرهای معمولی دارن؟ این کانتینرها موارد زیر رو پشتیبانی نمیکنن:

  • lifecycle
  • livenessProbe
  • readinessProbe
  • startupProbe

دلیل اصلیش اینه که این کانتینرها قراره که اجراشون تموم بشه. بنابراین معنی نداره که مثلا برای این کانتینر livenessProbe تعریف کنیم.



استفاده از کانتینرهای اینیت

اگر چند اینیت کانتینر تعریف کنین، Kubelet اونها رو به صورت متوالی اجرا میکنه. یعنی اجرای یک اینیت کانتینر باید با موفقیت به پایان برسه تا اجرای اینیت کانتینر بعدی شروع بشه. و وقتی که اجرای همه‌ی اینیت کانتینرها تمام شد، Kubelet کانتینرهای اپلیکیشن رو شروع به اجرا میکنه.

اهداف کلی از اجرای اینیت کانتینرها چیه؟

  • اینیت کانتینرها میتونن شامل ابزاری باشن که معمولا در image اپلیکیشن وجود نداره. مثلا شما به هر دلیلی اگر بخواید از sed یا awk استفاده کنید، دلیلی نداره که توی قسمت FROM داکرفایل ایپلیکیشن از یک image دیگه استفاده کنید. این کار رو میتونید به عهده‌ی اینیت بسپرید.
  • اینیتن کانتیرها میتونن view متفاوتی نسبت به کانتینرهای اپلیکیشن نسبت به فایل‌سیستم داشته باشن. مثلا میشه به اونها دسترسی به Secretهایی داد که اپلیکیشن نباید بهشون دسترسی داشته باشه.
  • از اونجایی که قبل از اجرای اپلیکیشن اجرای اینیت کانتینرها باید تموم شده باشه، میشه از این قضیه به عنوان یک مکانیزم برای اجرای با تاخیر اپلیکیشن استفاده کرد. فایده‌ی این کار اینه که میتونیم مطمئن بشیم یکسری پیش‌شرطها و نیازمندی‌ها که برای اجرای اپلیکیشن مورد نیازه، برطرف شده.
  • اینیت کانتینرها میتونن شامل ابزار یا کدهایی باشن که اگه در image اپلیکیشن وجود داشته باشن امنیت اونها رو پایین میارن. بنابراین با جدا کردن این ابزارهای غیر ضروری میتونیم “attack surface” یک اپلیکیشن رو محدود کنیم.

یک مورد که میشه از اینیت کانتینرها استفاده کرد:

یک مدت زمانی صبر کنیم تا سرویس مورد نظرمون ایجاد بشه بعد کانتینر اپلیکیشن رو شروع کنیم. این مورد با یک خط اسکریپت بش قابل پیاده‌سازیه:

for i in {1..100};
do
sleep 1
if dig service
then
exit 0
fi
done
exit 1

فایل پایین که مشخصات یک پاد رو مشخص میکنه شامل دو اینیت کانتینر هست. اینیت اول منتظر سرویس myservice میشه و اینیت دوم منتظر mydb. وقتی که هر دوی اینیت کانتینرها اجراشون با موفقیت به پایان رسید، پاد اجرای کانتینر اپ رو شروع میکنه.

apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', &quotuntil nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done&quot]
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', &quotuntil nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done&quot]

با اجرای این فایل وضعیت پاد در ابتدا به شکل زیر میشه

همونطور که در قسمت STATUS مشخصه دو کانتینر Init وجود داره که اجرای هیچکدومشون به پایان نرسیده.

اگر لاگ اینیت کانتینر اول رو بررسی کنیم (kubectl logs myapp-pod -c init-myservice)، از اونجایی که سرویس myservice زو نمیتونه ریزالو کنه، اجراش به پایان نمیرسه:

اما اگه سرویس‌های مد نظر اینیت کانتینرها رو ایجاد کنیم، اجراشون به پایان میرسه و کانتینر اصلی اپ شروع به اجرا میکنه:

---

apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377

حالا اگه وضعیت پاد رو بررسی کنیم:

خب طبق تصویر بالا مشخصه که اجرای کانتینر اصلی پاد شروع شده.




kubernetesinit containersکوبرنتیز
شاید از این پست‌ها خوشتان بیاید