מדריך: תמיכה במספר סביבות קוברנטס עם Kustomize
פוסט זה כולל טיפ קצר על Docker. אם אתם רוצים ללמוד יותר לעומק על פיתוח עם Docker, Docker Compose או Kubernetes תשמחו לשמוע שבניתי קורס וידאו מקיף בנושא זה.
למידע נוסף והצטרפות לקורס בקרו בדף קורס Docker כאן באתר.
כשאנחנו בונים אפליקציה שצריכה לרוץ על קלאסטר קוברנטס הרבה פעמים נרצה להיות מסוגלים להריץ את האפליקציה על קלאסטרים שונים לסביבות שונות: קלאסטר לסביבת בדיקות, קלאסטר של סביבת פיתוח וכמובן קלאסטר הפרודקשן.
לפעמים הקלאסטרים האלה יהיו זהים במאפיינים שלהם אבל בדרך כלל האפליקציה תצטרך קצת להשתנות בין הקלאסטרים: לדוגמה אולי ג'וב מסוים צריך לרוץ רק בסביבת פרודקשן ולא בסביבת הפיתוח, מיפוי Volume מסוים ישתמש בתיקיה מקומית בסביבת פיתוח אבל באחסון רשת בסביבת הבדיקות או הפרודקשן וכך הלאה.
המנגנון המובנה ב kubectl לניהול שינויים בין סביבות נקרא kustomize. בפוסט זה אציג דוגמה פשוטה לפרויקט שמשתמש ב kustomize כדי לייצר קבצי yaml שונים לסביבות השונות.
1. איך זה עובד
קסטומייז מחלק את קבצי ה yaml של קוברנטס ל-3 תיקיות מרכזיות:
תיקיית base שם נמצאים קבצי ה yaml ה"בסיסיים", לפני שהתאמנו אותם לסביבות מסוימות. זה בעצם החלק שמשותף לכל הסביבות. בתיקיה זו יהיה קובץ בשם kustomization.yaml שמהווה סוג של אינדקס לכל הקבצים בתיקיה.
תיקיית components, בתוכה אפשר ליצור תיקיה לכל "פיצ'ר" של הקלאסטר, ובתוך תיקיית הפיצ'ר יהיו כל קבצי ה yaml של אותו הפיצ'ר (או הקומפוננט).
תיקיית overlays שבתוכה תהיה תיקיה לכל סביבה. בתוך כל תיקיית סביבה יהיה קובץ kustomization.yaml שמכיל הוראות להתאמה של קבצי ה yaml מ base ומ components עבור סביבה זו.
זה אומר שאם יש לי פרויקט שבסביבת פרודקשן צריך איזה ג'וב מיוחד שלא קיים בסביבת פיתוח, אני יכול ליצור תת תיקיה בתוך components עם השם של הג'וב, בתוכה לשים את קובץ ה yaml המתאים לג'וב הזה, ואז בתוך overlays/production/kustomization.yaml
לבקש להוסיף את הקומפוננטה של הג'וב להגדרות הבניה בסביבת פרודקשן.
או אם אני צריך ליצור יותר replications בסביבת production, אז יהיה לי בקובץ overlays/production/kustomization.yaml
הוראה שאומרת שצריך לשנות את שדה replication של אוביקט deployment מסוים לערך גבוה יותר.
2. דוגמה - פרויקט שכולל מיפוי תיקיה רק בסביבת פרודקשן
נראה את זה דרך דוגמה פשוטה של סרביס רדיס שבסביבת פרודקשן מכיל מיפוי ווליום כדי שהמידע יישמר, אבל בסביבת פיתוח מגיע בלי המיפוי כדי שכל פעם שנפעיל את השרת נקבל מצב חדש ונקי.
מבנה התיקיות של הפרויקט נראה כך:
.
├── base
│ ├── kustomization.yaml
│ ├── redis-deployment.yaml
│ └── redis-service.yaml
├── components
│ └── datavolume
│ ├── data-persistentvolumeclaim.yaml
│ ├── kustomization.yaml
│ └── redis-deployment.yaml
├── docker-compose.yml
└── overlays
├── dev
│ └── kustomization.yaml
└── production
└── kustomization.yaml
6 directories, 9 files
תיקיית הבסיס כוללת את שני ה yaml-ים של redis שנדרשים בשביל להפעיל את השרת.
בתיקיית components יש לי תת-תיקיה שנקראת datavolume ובתוכה קובץ yaml שיוצר Volume ולידו קובץ yaml באותו שם של קובץ yaml בסיסי (נקרא redis-deployment.yaml) שיכלול רק את השינויים בקובץ ה deployment שיופעלו אם "קומפוננטה" זו משולבת בבניה.
ובתיקיית overlays יש לי תיקיות עבור כל סביבה dev
ו production
.
3. תיקיית base
עכשיו נראה את הקבצים בכל תיקיה. תחילה ב base הקובץ הכי מעניין הוא kustomization.yaml
שמהווה סוג של אינדקס על תיקיית הבסיס:
resources:
- redis-deployment.yaml
- redis-service.yaml
כל מה שיש בקובץ זה מפתח יחיד בשם resources שמכיל מערך של קבצי yaml ששייכים לפרויקט.
תוכן הקובץ redis-deployment.yaml
הוא:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert -f ../docker-compose.yml
kompose.version: 1.25.0 (a70f80cc)
creationTimestamp: null
labels:
io.kompose.service: redis
name: redis
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: redis
strategy:
type: Recreate
template:
metadata:
annotations:
kompose.cmd: kompose convert -f ../docker-compose.yml
kompose.version: 1.25.0 (a70f80cc)
creationTimestamp: null
labels:
io.kompose.service: redis
spec:
containers:
- image: redis:6.2
name: redis
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
ports:
- containerPort: 6379
resources: {}
restartPolicy: Always
status: {}
ותוכן הקובץ redis-service.yaml
הוא:
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert -f ../docker-compose.yml
kompose.version: 1.25.0 (a70f80cc)
creationTimestamp: null
labels:
io.kompose.service: redis
name: redis
spec:
ports:
- name: "6379"
port: 6379
targetPort: 6379
selector:
io.kompose.service: redis
status:
loadBalancer: {}
4. תיקיית components/datavolume
התיקיה השניה היא הקומפוננטה אותה נרצה לשלב בבניה בסביבה מסוימת. אפשר לבנות כמה קומפוננטות שאתם רוצים בתור תתי תיקיות של תיקיית components. לכל קומפוננטה יש קובץ kustomization.yaml
ושלי נראה כך:
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
resources:
- data-persistentvolumeclaim.yaml
patchesStrategicMerge:
- redis-deployment.yaml
הקובץ אומר שאם אתם משלבים קומפוננטה זו אתם צריכים להוסיף את הקובץ data-persistentvolumeclaim.yaml
ובנוסף אליו צריכים לעשות Merge לערכים מהקובץ redis-deployment.yaml
שנמצא אצלי בתיקיה. הקובץ redis-deployment.yaml
הוא המעניין בין השניים אז נתחיל איתו:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
template:
spec:
containers:
- name: redis
volumeMounts:
- mountPath: /data
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: data
ואנחנו רואים שזה לא קובץ Deployment מלא אלא רק החלק מהקובץ שמתעסק עם ה mount של ה volume החדש. מה שמאוד חשוב בקובץ זה שה metadata.name יהיה זהה לאותו deployment אותו רוצים לעדכן.
הקובץ האחרון בקומפוננטה הוא data-persistentvolumeclaim.yaml
ותוכנו הוא:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
labels:
io.kompose.service: data
name: data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
status: {}
זה כבר קובץ yaml מלא שיוצר PersistentVolumeClaim. בגלל שהוא בתוך הקומפוננטה ולא בתוך base, אז רק סביבות שישתמשו בקומפוננטה זו יפעילו אותו.
5. תיקיית overlays/dev
הסביבה הראשונה היא dev והיא מכילה רק קובץ kustomization.yaml
יחיד. זה התוכן שלו:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
והוא למעשה מציין סביבה זהה לגמרי ל base. בסביבת הפיתוח אין שום תוספת ושום שינוי.
6. תיקיית overlays/production
סביבת הייצור זה כבר סיפור אחר כי היא צריכה להוסיף את הקומפוננטה שיצרנו. הנה הקובץ overlays/production/kustomization.yaml
שמתאר את הסביבה:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
components:
- ../../components/datavolume
הפעם בנוסף ל resources יש לנו מפתח חדש בשם components שכולל מערך של כל הקומפוננטות ששייכות לסביבה. בגלל שכתבתי כאן את הקומפוננטה אז כשאבנה את ההגדרות לסביבת הפרודקשן הן יכללו את כל base וגם את הקומפוננטה.
7. איך לבנות קבצי הגדרות לקלאסטר
אחרי שכל ה yaml-ים במקום אני יכול להריץ:
$ kubectl kustomize overlays/production
ולקבל למסך במכה אחת את כל הגדרות ה yaml של סביבת production. הרבה פעמים אנחנו לא נרצה אפילו לכתוב את ההגדרות האלה לקובץ אלא פשוט נשלח אותן ישר לקלאסטר באופן הבא:
$ kubectl kustomize overlays/production | kubectl apply -f -
או אם אתם מעדיפים להעלות את המערכת בגירסת פיתוח אז תצטרכו לעדכן את קונפיגורציית kubectl שלכם שיתחבר לקלאסטר הפיתוח ואז להפעיל:
$ kubectl kustomize overlays/dev | kubectl apply -f -
8. איפה לומדים עוד
התיעוד של קוברנטס כולל כמה פרקים על kustomize אז אם אתם אוהבים לקרוא את התיעוד של קוברנטס זה יכול לשמח אתכם. הדף הרלוונטי הוא בקישור הזה: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/.
אני מוצא שבעבודה עם קוברנטס הרבה יותר קל לי להסתכל על דוגמאות עובדות ועם kustomize זה קל כי יש תיקיית דוגמאות די טובה בדף הגיטהאב של הפרויקט בקישור: https://github.com/kubernetes-sigs/kustomize/tree/master/examples.