פריסות של Kubernetes מאפשרות להריץ עומסי עבודה בקונטיינרים ב-Google Distributed Cloud, ושירותים מסוג LoadBalancer מאפשרים לגשת לעומסי העבודה האלה מחוץ לאשכול. במאמר הזה תפרסו אפליקציה לדוגמה ותחשפו אותה בכתובת IP חיצונית ממאגר הכתובות של מאזן העומסים באשכול.
לפני שמתחילים
כדי לפרוס עומס עבודה, צריך אשכול משתמש, אשכול היברידי או אשכול עצמאי שיכול להריץ עומסי עבודה.
יצירת פריסה
כדי ליצור פריסה באשכול:
מעתיקים את המניפסט הבא לקובץ בשם
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הפלט מראה שלפריסה יש שלושה Pods שכולם זמינים:
NAME READY UP-TO-DATE AVAILABLE AGE my-deployment 3/3 3 3 27sמציגים ברשימה את ה-Pods בפריסה:
kubectl get pods --kubeconfig CLUSTER_KUBECONFIGבפלט אפשר לראות שבפריסה יש שלושה Pods פועלים:
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
אחת מהדרכים לחשוף את הפריסה ללקוחות מחוץ לאשכול היא ליצור שירות של 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.
כברירת מחדל, הקונטיינר
hello-appמאזין ליציאת TCP8080. אפשר לראות את הגדרת היציאה הזו בקובץ Docker ובקוד המקור של האפליקציה.משתמשים ב-
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.