部署應用程式

本文說明如何在 Google Distributed Cloud 上部署應用程式。

事前準備

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

可建立部署作業

下列步驟會在叢集上建立 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 類型的服務

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

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

  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 位址。此外,還包含 nodePortporttargetPort

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

    舉例來說,請從上述輸出內容中,取得服務的值:

    • 外部 IP 位址:192.168.1.13
    • port80
    • nodePort31565
    • targetPort8080

    用戶端會將要求傳送至 TCP 通訊埠 80 上的 192.168.1.13。要求會先傳送至負載平衡器,再從負載平衡器轉送至 TCP 通訊埠 8080 上的成員 Pod。

  4. 呼叫您的服務:

    curl INGRESS_IP_ADDRESS
    

    INGRESS_IP_ADDRESS 替換為您在上一個步驟中擷取的 Service status 區段中的 Ingress IP 位址 (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 個可用節點通訊埠。如要節省節點通訊埠,請在 LoadBalancer 服務規格中將 allocateLoadBalancerNodePorts 欄位設為 false,停用負載平衡器節點通訊埠分配。這項設定可防止 Kubernetes 將節點通訊埠分配給 LoadBalancer 服務。詳情請參閱 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. 確認服務已刪除:

    kubectl get services --kubeconfig CLUSTER_KUBECONFIG
    

    輸出內容不再顯示 my-service

刪除部署作業

如要刪除部署作業,請按照下列步驟操作:

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

    kubectl delete deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    確認 Deployment 已刪除:

    kubectl get deployments --kubeconfig CLUSTER_KUBECONFIG
    

    輸出內容不再顯示 my-deployment

後續步驟

建立 Service 和 Ingress