部署应用

本文档举例说明了如何在使用 Google Distributed Cloud for VMware(纯软件)创建的用户集群中部署应用。

准备工作

对于本文档提供的示例,您需要一个使用捆绑式 MetalLB 负载均衡的用户集群。如需了解如何创建使用 MetalLB 的最小用户集群,请参阅创建基本集群

您可以使用 Google Cloud 控制台或在管理员工作站上使用命令行工具 kubectl 来部署应用。

控制台

  1. 在控制台中,进入 Google Kubernetes Engine 集群概览页面。

    转到 GKE 集群

  2. 在集群列表中,点击用户集群,并验证您已登录该集群。

    如果您尚未登录用户集群,请按照通过 Google Cloud 控制台管理集群中的说明登录。

容器

  1. 新建容器下,选择现有容器映像

  2. 映像路径字段中,输入 us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0

  3. 点击继续

配置

  1. 部署名称字段中,输入 my-deployment

  2. 命名空间字段中,输入 default

  3. 输入以下两个标签:

    • 键 1app值 1metrics
    • 键 2department值 2sales
  4. Kubernetes 集群下拉列表中,选择您的集群。

  5. 点击继续

公开

  1. 勾选将部署作为新服务公开

  2. 端口 1 字段中,输入 80

  3. 目标端口 1 字段中,输入 8080。此值是适当的值,因为 hello-app 容器默认监听 TCP 端口 8080。您可以通过查看应用的 Dockerfile 和源代码来查看此信息。

  4. 协议 1 字段中,选择 TCP

  5. 服务类型字段中,选择 LoadBalancer

点击页面底部的部署按钮。

查看 Deployment 和 Service 详情

  1. Deployment 准备就绪后,Deployment 详情页面会在 Google Cloud 控制台的 Kubernetes 工作负载部分中打开。在此页面上,您可以查看有关 Deployment 及其三个 Pod 的详细信息。

  2. 公开服务下,点击公开 Deployment 的 Service 的名称。在本练习中,该名称为 my-deployment-service

  3. 此时会打开 Service 详情页面。在此页面上,您可以查看有关 Service 的详细信息。例如,您可以看到任何具有标签 app: metricsdepartment: sales 的 Pod 都是 Service 的成员。之前提到,my-deployment 中的 Pod 具有这些标签。

您还可以查看负载均衡器 IP 的值。系统已在集群负载均衡器上自动配置负载均衡器 IP。

Service 的转发

假设集群外部的客户端在 TCP 端口 80 上向负载均衡器 IP 发送请求。请求会路由到集群负载均衡器。负载均衡器将请求转发到 TCP 端口 8080 上的成员 Pod。之前提到,my-deployment 中的每个 Pod 都有一个监听 TCP 端口 8080 的容器。

测试 Service

前往负载均衡器 IP 可路由到的机器。

如需调用 Service,请在浏览器中输入负载均衡器 IP,或者使用 curl 之类的命令。例如:

curl [LOAD_BALANCER_IP]:80

输出会显示 Hello, world! 消息。例如:

curl 203.0.113.1:80
Hello, world!
Version: 2.0.0
Hostname: my-deployment-dbd86c8c4-9wpbv

删除 Deployment

进入控制台,前往 Kubernetes Engine 部分中的工作负载页面。

转到“工作负载”页面

在 Deployment 列表中,选择 my-deployment

点击页面顶部的删除。此操作会同时删除 Deployment 和公开的 Service。

命令行

连接到管理员工作站

与管理员工作站建立 SSH 连接。 在管理员工作站上执行以下步骤。

创建 Deployment

以下是 Deployment 的清单:

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"

将此清单复制到名为 my-deployment.yaml 的文件,然后创建该 Deployment:

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

其中,USER_CLUSTER_KUBECONFIG 是用户集群的 kubeconfig 文件的路径。

获取有关 Deployment 的基本信息:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get deployment my-deployment

输出结果显示 Deployment 有三个可用的 Pod:

NAME            READY   UP-TO-DATE   AVAILABLE   AGE
my-deployment   3/3     3            3           27s

列出 Deployment 中的 Pod:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get pods

输出结果显示 Deployment 有三个正在运行的 Pod:

NAME                             READY   STATUS    RESTARTS   AGE
my-deployment-54944c8d55-4srm2   1/1     Running   0          6s
my-deployment-54944c8d55-7z5nn   1/1     Running   0          6s
my-deployment-54944c8d55-j62n9   1/1     Running   0          6s

获取有关 Deployment 的详细信息:

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

输出结果显示有关 Deployment 规范和状态的详细信息:

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: "2019-11-11T18:44:02Z"
    lastUpdateTime: "2019-11-11T18:44:02Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  ‑ lastTransitionTime: "2019-11-11T18:43:58Z"
    lastUpdateTime: "2019-11-11T18:44:02Z"
    message: ReplicaSet "my-deployment-54944c8d55" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  observedGeneration: 1
  readyReplicas: 3
  replicas: 3
  updatedReplicas: 3

描述您的 Deployment:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG describe deployment my-deployment

输出结果显示有关 Deployment 的精确格式详细信息,包括关联的 ReplicaSet

Name:                   my-deployment
Namespace:              default
CreationTimestamp:      Mon, 11 Nov 2019 10:43:58 -0800
Labels:                 
...
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:         
    Host Port:    
    Environment:  
    Mounts:       
  Volumes:        
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  
NewReplicaSet:   my-deployment-54944c8d55 (3/3 replicas created)

创建 LoadBalancer 类型的 Service

将 Deployment 公开给集群外部客户端的一种方法是创建类型为 LoadBalancer 的 Kubernetes Service

以下是 LoadBalancer 类型的 Service 的清单:

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 和源代码来查看此信息。

将此清单保存到名为 my-service.yaml 的文件,然后创建该 Service:

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

其中,USER_CLUSTER_KUBECONFIG 是用户集群的 kubeconfig 文件的路径。

当您创建 Service 时,Google Distributed Cloud 会自动在集群负载均衡器上配置 loadBalancerIP 地址。

查看您的 Service:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get service my-service --output yaml

输出类似于以下内容:

kind: Service
metadata:
  ...
  name: my-service
  namespace: default
  ...
spec:
  allocateLoadBalancerNodePorts: true
  clusterIP: 10.96.1.39
  clusterIPs:
  - 10.96.1.39
  externalTrafficPolicy: Cluster
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - nodePort: 31184
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: metrics
    department: sales
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.1

在上面的输出结果中,您可以看到您的 Service 有一个 clusterIP 和一个 loadBalancerIP。它还具有 porttargetPort

clusterIP 与此练习无关。loadBalancerIP 是集群外部的客户端可用于调用 Service 的 IP 地址。

以上面的输出结果中显示的值为例。也就是说,假设 Service 的 loadBalancerIP = 203.0.113.1,port = 80,targetPort = 8080。

客户端将请求发送到 TCP 端口 80 上的 203.0.113.1。请求会路由到集群负载均衡器。负载均衡器将请求转发到 TCP 端口 8080 上的成员 Pod。

调用您的 Service:

curl LOAD_BALANCER_IP

输出结果会显示 Hello, world! 消息:

curl 203.0.113.1
Hello, world!
Version: 2.0.0
Hostname: my-deployment-dbd86c8c4-9wpbv

删除 Service

删除 Service:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete service my-service

验证您的 Service 是否已删除:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get services

输出结果不再显示 my-service

删除 Deployment

删除 Deployment:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete deployment my-deployment

验证您的 Deployment 是否已删除:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get deployments

输出结果不再显示 my-deployment

后续步骤

创建 Service 和 Ingress