部署应用

本文档介绍如何在 GKE on Bare Metal 上部署应用。

准备工作

如需部署工作负载,您必须拥有能够运行工作负载的用户集群、混合集群或独立集群。

创建 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. 描述您的 Deployment:

    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 地址。它还具有 nodePortporttargetPort

    clusterIP 与此练习无关。外部 IP 地址 (status.loadBalancer.ingress.ip) 来自您在集群配置文件中定义负载均衡器地址池 (spec.loadBalancer.addressPools) 时指定的地址范围。

    以上面的 Service 输出中显示的值为例:

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

    客户端将请求发送到 TCP 端口 80 上的 192.168.1.13。请求被路由到您的负载均衡器,然后从该负载均衡器转发到 TCP 端口 8080 上的成员 Pod。

  4. 调用您的 Service:

    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 类型的 Service 具有集群 IP 地址以及一个或多个 nodePort 值。 默认情况下,Kubernetes 会将节点端口分配给类型为 LoadBalancer 的 Service。这些分配可以快速耗尽分配给集群的 2,768 个可用节点端口。如需保存节点端口,请通过将 LoadBalancer Service 规范中的 allocateLoadBalancerNodePorts 字段设置为 false 来停用负载均衡器节点端口分配。此设置可防止 Kubernetes 将节点端口分配给 LoadBalancer Service。如需了解详情,请参阅 Kubernetes 文档中的停用负载均衡器 NodePort 分配

以下清单用于创建不使用任何节点端口的服务:

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

删除 Service

如需删除您的 Service,请执行以下操作:

  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