במאמר הזה מוסבר איך לפרוס אפליקציה ב-Google Distributed Cloud.
לפני שמתחילים
כדי לפרוס עומס עבודה, צריך שיהיה לכם אשכול משתמשים, אשכול היברידי או אשכול עצמאי שיכול להריץ עומסי עבודה.
יצירת פריסה
השלבים הבאים יוצרים פריסה באשכול:
מעתיקים את קובץ המניפסט הבא לקובץ בשם
my-deployment.yaml:apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment spec: selector: matchLabels: app: metrics department: sales replicas: 3 template: metadata: labels: app: metrics department: sales spec: containers: - name: hello image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"משתמשים ב-
kubectl applyכדי ליצור את הפריסה:kubectl apply -f my-deployment.yaml --kubeconfig CLUSTER_KUBECONFIGמחליפים את CLUSTER_KUBECONFIG בנתיב של קובץ ה-kubeconfig של האשכול.
כדי לוודא שהפריסה נוצרה בהצלחה, אפשר לקבל מידע בסיסי על הפריסה:
kubectl get deployment my-deployment --kubeconfig CLUSTER_KUBECONFIGהפלט מראה שלפריסת ה-Deployment יש שלושה Pods שכולם זמינים:
NAME READY UP-TO-DATE AVAILABLE AGE my-deployment 3/3 3 3 27sמציגים ברשימה את ה-Pods בפריסה:
kubectl get pods --kubeconfig CLUSTER_KUBECONFIGהפלט מראה שלפריסת ה-Deployment יש שלושה פודים פעילים:
NAME READY STATUS RESTARTS AGE my-deployment-869f65669b-5259x 1/1 Running 0 34s my-deployment-869f65669b-9xfrs 1/1 Running 0 34s my-deployment-869f65669b-wn4ft 1/1 Running 0 34sקבלת מידע מפורט על הפריסה:
kubectl get deployment my-deployment --output yaml --kubeconfig CLUSTER_KUBECONFIGבפלט מוצגים פרטים על מפרט הפריסה והסטטוס:
apiVersion: apps/v1 kind: Deployment metadata: ... generation: 1 name: my-deployment namespace: default ... spec: ... replicas: 3 revisionHistoryLimit: 10 selector: matchLabels: app: metrics department: sales ... spec: containers: - image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0 imagePullPolicy: IfNotPresent name: hello resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 status: availableReplicas: 3 conditions: - lastTransitionTime: "2023-06-29T16:17:17Z" lastUpdateTime: "2023-06-29T16:17:17Z" message: Deployment has minimum availability. reason: MinimumReplicasAvailable status: "True" type: Available - lastTransitionTime: "2023-06-29T16:17:12Z" lastUpdateTime: "2023-06-29T16:17:17Z" message: ReplicaSet "my-deployment-869f65669b" has successfully progressed. reason: NewReplicaSetAvailable status: "True" type: Progressing observedGeneration: 1 readyReplicas: 3 replicas: 3 updatedReplicas: 3תארו את הפריסה:
kubectl describe deployment my-deployment --kubeconfig CLUSTER_KUBECONFIGהפלט מציג פרטים בפורמט נוח לקריאה על הפריסה, כולל ReplicaSet המשויך:
Name: my-deployment Namespace: default CreationTimestamp: Thu, 29 Jun 2023 16:17:12 +0000 Labels: <none> Annotations: deployment.kubernetes.io/revision: 1 Selector: app=metrics,department=sales Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=metrics department=sales Containers: hello: Image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0 Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: my-deployment-869f65669b (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 6m50s deployment-controller Scaled up replica set my-deployment-869f65669b to 3
יצירת שירות מהסוג LoadBalancer
אחת הדרכים לחשוף את ה-Deployment ללקוחות מחוץ לאשכול היא ליצור שירות Kubernetes מסוג LoadBalancer.
כדי ליצור שירות מסוג LoadBalancer:
מעתיקים את קובץ המניפסט הבא לקובץ בשם
my-service.yaml:apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: metrics department: sales type: LoadBalancer ports: - port: 80 targetPort: 8080אלה הדברים החשובים שכדאי להבין לגבי השירות בתרגיל הזה:
כל Pod עם התווית
app: metricsוהתוויתdepartment: salesהוא חבר בשירות. ל-Pods ב-my-deploymentיש את התוויות האלה.כשלקוח שולח בקשה לשירות ביציאת TCP
80, הבקשה מועברת אל Pod חבר ביציאת TCP8080.לכל Pod של חבר חייב להיות מאגר שמקשיב ליציאת TCP
8080.
כברירת מחדל, ה-container
hello-appמאזין ליציאת TCP8080. אפשר לראות את הגדרת היציאה הזו בקובץ ה-Dockerfile ובקוד המקור של האפליקציה.משתמשים ב-
kubectl applyכדי ליצור את השירות באשכול:kubectl apply -f my-service.yaml --kubeconfig CLUSTER_KUBECONFIGמחליפים את CLUSTER_KUBECONFIG בנתיב של קובץ ה-kubeconfig של האשכול.
צפייה בשירות:
kubectl get service my-service --output yaml --kubeconfig CLUSTER_KUBECONFIGהפלט אמור להיראות כך:
apiVersion: v1 kind: Service metadata: ... name: my-service namespace: default ... spec: allocateLoadBalancerNodePorts: true clusterIP: 10.96.2.165 clusterIPs: - 10.96.2.165 externalTrafficPolicy: Cluster internalTrafficPolicy: Cluster ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - nodePort: 31565 port: 80 protocol: TCP targetPort: 8080 selector: app: metrics department: sales sessionAffinity: None type: LoadBalancer status: loadBalancer: ingress: - ip: 192.168.1.13בפלט שלמעלה אפשר לראות שלשירות יש
clusterIPוכתובת IP חיצונית. יש בו גםnodePort,portו-targetPort.המידע על
clusterIPלא רלוונטי לתרגיל הזה. כתובת ה-IP החיצונית (status.loadBalancer.ingress.ip) מגיעה מטווח הכתובות שציינתם כשקבעתם מאגרי כתובות של מאזן עומסים (spec.loadBalancer.addressPools) בקובץ התצורה של האשכול.לדוגמה, נניח שהערכים שמוצגים בפלט הקודם של השירות הם:
- כתובת IP חיצונית:
192.168.1.13 port:80nodePort: 31565targetPort:8080
לקוח שולח בקשה אל
192.168.1.13ביציאת TCP80. הבקשה מנותבת למאזן העומסים, ומשם היא מועברת ל-Pod של חבר ביציאת TCP8080.- כתובת IP חיצונית:
מתקשרים לשירות:
curl INGRESS_IP_ADDRESSמחליפים את INGRESS_IP_ADDRESS בכתובת ה-IP של הכניסה בקטע
statusשל השירות שאוחזר בשלב הקודם (status.loadBalancer.ingress).הפלט יציג את ההודעה
Hello, world!:Hello, world! Version: 2.0.0 Hostname: my-deployment-869f65669b-wn4ft
מגבלות יציאות של LoadBalancer
הסוג LoadBalancer הוא הרחבה של הסוג NodePort. לכן לשירות מסוג LoadBalancer יש כתובת IP של אשכול וערך אחד או יותר של nodePort.
כברירת מחדל, Kubernetes מקצה יציאות צומת לשירותים מסוג LoadBalancer.
ההקצאות האלה יכולות לנצל במהירות את יציאות הצמתים הזמינות מתוך 2,768 שהוקצו לאשכול. כדי לשמור את יציאות הצמתים, משביתים את הקצאת יציאות הצמתים של איזון העומסים על ידי הגדרת השדה allocateLoadBalancerNodePorts לערך false במפרט השירות LoadBalancer. ההגדרה הזו מונעת מ-Kubernetes להקצות יציאות צמתים לשירותי LoadBalancer. מידע נוסף זמין במאמר השבתת הקצאה של NodePort למאזן עומסים במאמרי העזרה של Kubernetes.
זוהי מניפסט ליצירת שירות שלא משתמש ביציאות של צמתים:
apiVersion: v1
kind: Service
metadata:
name: service-does-not-use-nodeports
spec:
selector:
app: my-app
type: LoadBalancer
ports:
- port: 8000
# Set allocateLoadBalancerNodePorts to false
allocateLoadBalancerNodePorts: false
מחיקת השירות
כדי למחוק את השירות:
משתמשים בפקודה
kubectl deleteכדי למחוק את השירות מהאשכול:kubectl delete service my-service --kubeconfig CLUSTER_KUBECONFIGכדי לוודא שהשירות נמחק:
kubectl get services --kubeconfig CLUSTER_KUBECONFIGהפלט לא יכלול יותר את
my-service.
מחיקת הפריסה
כדי למחוק את הפריסה:
משתמשים בפקודה
kubectl deleteכדי למחוק את הפריסה מהאשכול:kubectl delete deployment my-deployment --kubeconfig CLUSTER_KUBECONFIGמוודאים שהפריסה נמחקה:
kubectl get deployments --kubeconfig CLUSTER_KUBECONFIGהפלט לא יכלול יותר את
my-deployment.