部署應用程式

Kubernetes Deployment 可讓您在 Google Distributed Cloud 執行容器化工作負載,而 LoadBalancer 類型的 Service 則可讓您從叢集外部存取這些工作負載。在本文件中,您將部署範例應用程式,並透過叢集負載平衡器位址集區中的外部 IP 位址公開該應用程式。

事前準備

如要部署工作負載,您必須具備可執行工作負載的使用者、混合或獨立叢集。

建立 Deployment

請按照下列步驟在叢集上建立 Deployment:

  1. 將下列資訊清單複製到名為 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"
    
  2. 使用 kubectl apply 建立 Deployment:

    kubectl apply -f my-deployment.yaml --kubeconfig CLUSTER_KUBECONFIG
    

    將 CLUSTER_KUBECONFIG 替換為叢集的 kubeconfig 檔案路徑。

  3. 取得 Deployment 的基本資訊,確認已成功建立:

    kubectl get deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    輸出內容顯示 Deployment 有三個 Pod,且都可使用:

    NAME            READY   UP-TO-DATE   AVAILABLE   AGE
    my-deployment   3/3     3            3           27s
    
  4. 列出 Deployment 中的 Pod:

    kubectl get pods --kubeconfig CLUSTER_KUBECONFIG
    

    輸出內容顯示 Deployment 有三個執行中的 Pod:

    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
    
  5. 取得 Deployment 的詳細資訊:

    kubectl get deployment my-deployment --output yaml --kubeconfig CLUSTER_KUBECONFIG
    

    輸出內容會顯示 Deployment 規格和狀態的詳細資料:

    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
    
  6. 說明部署作業:

    kubectl describe deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    輸出內容會顯示 Deployment 的詳細資料,包括相關聯的 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 類型的 Service

如要向叢集外的用戶端公開 Deployment,其中一種方法是建立 LoadBalancer 類型的 Kubernetes Service。

如要建立 LoadBalancer 類型的 Service,請按照下列步驟操作:

  1. 將下列資訊清單複製到名為 my-service.yaml 的檔案:

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      selector:
        app: metrics
        department: sales
      type: LoadBalancer
      ports:
      - port: 80
        targetPort: 8080
    

    以下是本練習中關於 Service 的重要事項:

    • 任何具有 app: metrics 標籤和 department: sales 標籤的 Pod 都是 Service 的成員。my-deployment 中的 Pod 具有這些標籤。

    • 當用戶端將要求傳送至 TCP 通訊埠 80 上的 Service 時,要求會轉送至 TCP 通訊埠 8080 上的成員 Pod。

    • 每個成員 Pod 都必須有一個容器,用於監聽 TCP 通訊埠 8080。

    根據預設,hello-app 容器會監聽 TCP 通訊埠 8080。您可以查看應用程式的 Dockerfile 和原始碼,瞭解這項通訊埠設定。

  2. 使用 kubectl apply 在叢集上建立 Service:

    kubectl apply -f my-service.yaml --kubeconfig CLUSTER_KUBECONFIG
    

    將 CLUSTER_KUBECONFIG 替換為叢集的 kubeconfig 檔案路徑。

  3. 查看 Service:

    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
    

    在上述輸出內容中,您可以看到 Service 具有 clusterIP 和外部 IP 位址。此外,還有 nodePort、port 和 targetPort。

    clusterIP 與本練習無關。外部 IP 位址 (status.loadBalancer.ingress.ip) 來自您在叢集設定檔中定義負載平衡器位址集區 (spec.loadBalancer.addressPools) 時指定的位址範圍。

    舉例來說,請查看上述 Service 輸出內容中顯示的值:

    • 外部 IP 位址:192.168.1.13
    • port:80
    • nodePort:31565
    • targetPort:8080

    用戶端透過 TCP 通訊埠 80 將要求傳送至 192.168.1.13。要求會轉送至負載平衡器,然後從該處轉送至 TCP 通訊埠 8080 上的成員 Pod。

  4. 呼叫服務:

    curl INGRESS_IP_ADDRESS
    

    將 INGRESS_IP_ADDRESS 替換為您在先前步驟 (status.loadBalancer.ingress) 中擷取的 Service status 區段中的輸入 IP 位址。

    輸出結果會顯示一則 Hello, world! 訊息:

    Hello, world!
    Version: 2.0.0
    Hostname: my-deployment-869f65669b-wn4ft
    

LoadBalancer 通訊埠限制

LoadBalancer 類型是 NodePort 類型的延伸,因此,LoadBalancer 類型的 Service 具有叢集 IP 位址和一或多個 nodePort 值。根據預設,Kubernetes 會將節點通訊埠分配給 LoadBalancer 類型的 Service。這些分配作業可能會快速耗盡叢集分配到的 2,768 個可用節點通訊埠。如要節省節點通訊埠,請在 LoadBalancer Service 規格中將 allocateLoadBalancerNodePorts 欄位設為 false,停用負載平衡器節點通訊埠分配功能。這項設定可防止 Kubernetes 將節點通訊埠分配給 LoadBalancer Service。詳情請參閱 Kubernetes 說明文件中的「停用負載平衡器 NodePort 分配」。

以下資訊清單可用來建立不使用任何節點通訊埠的 Service:

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

刪除服務

如要刪除服務,請按照下列步驟操作:

  1. 使用 kubectl delete 從叢集刪除 Service:

    kubectl delete service my-service --kubeconfig CLUSTER_KUBECONFIG
    
  2. 確認 Service 已刪除:

    kubectl get services --kubeconfig CLUSTER_KUBECONFIG
    

    輸出內容不會再顯示 my-service。

刪除 Deployment

如要刪除 Deployment,請按照下列步驟操作:

  1. 使用 kubectl delete 從叢集刪除 Deployment:

    kubectl delete deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    確認 Deployment 已刪除:

    kubectl get deployments --kubeconfig CLUSTER_KUBECONFIG
    

    輸出內容不會再顯示 my-deployment。

後續步驟

建立 Service 和 Ingress