

 **帮助改进此页面** 

要帮助改进本用户指南，请选择位于每个页面右侧窗格中的**在 GitHub 上编辑此页面**链接。

# 在 Linux 上部署示例应用程序
<a name="sample-deployment"></a>

在本主题中，您在 Linux 节点上的集群中部署一个示例应用程序。

## 先决条件
<a name="_prerequisites"></a>
+ 现有的 Kubernetes 集群至少有一个节点。如果没有现有 Amazon EKS 集群，可以根据 [开始使用 Amazon EKS](getting-started.md) 中的指南之一部署一个集群。
+  安装在计算机上的 `Kubectl`。有关更多信息，请参阅 [设置 `kubectl` 和 `eksctl`](install-kubectl.md)。
+  `Kubectl` 配置为与集群通信。有关更多信息，请参阅 [通过创建 kubeconfig 文件将 kubectl 连接到 EKS 集群](create-kubeconfig.md)。
+ 如果计划将示例工作负载部署到 Fargate，现有 [Fargate 配置文件](fargate-profile.md)必须包含本教程创建的相同命名空间，即 `eks-sample-app`，除非更改名称。如果使用[开始使用 Amazon EKS](getting-started.md)中的指南之一创建集群，则必须创建新配置文件或将命名空间添加到现有配置文件，因为在入门指南中创建的配置文件没有指定本教程使用的命名空间。您的 VPC 还必须具有至少一个私有子网。

尽管下列步骤中有许多变量都可以更改，但我们建议仅在指定的情况下更改变量值。更深入地了解 Kubernetes 容器组（pod）、部署和服务后，即可尝试更改其他值。

## 创建命名空间
<a name="_create_a_namespace"></a>

命名空间允许您在 Kubernetes 中对资源进行分组。有关更多信息，请参阅 Kubernetes 文档中的[命名空间](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)。如果您计划部署示例应用程序以[使用 AWS Fargate 简化计算管理](fargate.md)，请确保在[定义哪些容器组（pod）在启动时使用 `namespace` Fargate](fargate-profile.md) 中 AWS 的值为 `eks-sample-app`。

```
kubectl create namespace eks-sample-app
```

## 创建 Kubernetes 部署
<a name="_create_a_kubernetes_deployment"></a>

创建 Kubernetes 部署。此示例部署从公共存储库中提取容器映像，并将各个容器组（pod）的三个副本部署到您的集群中。有关更多信息，请参阅 Kubernetes 文档中的[部署](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)。

1. 将以下内容保存到名为 `eks-sample-deployment.yaml` 的文件中。示例应用程序中的容器不使用网络存储，但可能有需要的应用程序。有关更多信息，请参阅 [使用集群的应用程序数据存储](storage.md)。
   + `kubernetes.io/arch` 键下的 `amd64` 或 `arm64` `values` 意味着应用程序可以部署到任一硬件架构（如果集群中两者都有）。可能出现这种情况，因为此映像是一个多架构映像，但并非全部都是。可以通过查看从中提取的存储库的[映像详细信息](https://gallery.ecr.aws/nginx/nginx)，确定支持映像的硬件结构。部署不支持硬件架构类型的映像或不希望将映像部署到的映像时，请从清单中删除该类型。有关更多信息，请参阅 Kubernetes 文档中的[众所周知的标签、注释和污点](https://kubernetes.io/docs/reference/labels-annotations-taints/)。
   + `kubernetes.io/os: linux` `nodeSelector` 意味着集群中有 Linux 和 Windows 节点（例如），则该映像将只部署到 Linux 节点。有关更多信息，请参阅 Kubernetes 文档中的[众所周知的标签、注释和污点](https://kubernetes.io/docs/reference/labels-annotations-taints/)。

     ```
     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: eks-sample-linux-deployment
       namespace: eks-sample-app
       labels:
         app: eks-sample-linux-app
     spec:
       replicas: 3
       selector:
         matchLabels:
           app: eks-sample-linux-app
       template:
         metadata:
           labels:
             app: eks-sample-linux-app
         spec:
           affinity:
             nodeAffinity:
               requiredDuringSchedulingIgnoredDuringExecution:
                 nodeSelectorTerms:
                 - matchExpressions:
                   - key: kubernetes.io/arch
                     operator: In
                     values:
                     - amd64
                     - arm64
           containers:
           - name: nginx
             image: public.ecr.aws/nginx/nginx:1.23
             ports:
             - name: http
               containerPort: 80
             imagePullPolicy: IfNotPresent
           nodeSelector:
             kubernetes.io/os: linux
     ```

1. 将部署清单应用于集群。

   ```
   kubectl apply -f eks-sample-deployment.yaml
   ```

## 创建服务
<a name="_create_a_service"></a>

服务允许您通过单个 IP 地址或名称访问所有副本。有关更多信息，请参阅 Kubernetes 文档中的[服务](https://kubernetes.io/docs/concepts/services-networking/service/)。虽然没有在示例应用程序中实施，但如果应用程序需要与其他 AWS 服务交互，我们建议为容器组（pod）创建 Kubernetes 服务帐户，然后将其关联到 AWS IAM 账户。指定服务账户可使您的 Pod （一组容器）拥有为其指定的与其他服务交互的最低权限。有关更多信息，请参阅 [服务账户的 IAM 角色](iam-roles-for-service-accounts.md)。

1. 将以下内容保存到名为 `eks-sample-service.yaml` 的文件中。Kubernetes 为服务分配自己的 IP 地址，该 IP 地址只能从集群内访问。要从集群外部访问服务，请部署 [AWS Load Balancer Controller](aws-load-balancer-controller.md) 以负载均衡服务的[应用程序](alb-ingress.md)或[网络](network-load-balancing.md)流量。

   ```
   apiVersion: v1
   kind: Service
   metadata:
     name: eks-sample-linux-service
     namespace: eks-sample-app
     labels:
       app: eks-sample-linux-app
   spec:
     selector:
       app: eks-sample-linux-app
     ports:
       - protocol: TCP
         port: 80
         targetPort: 80
   ```

1. 将服务清单应用于集群。

   ```
   kubectl apply -f eks-sample-service.yaml
   ```

## 审核已创建的资源
<a name="sample-app-view-namespace"></a>

1. 查看 `eks-sample-app` 命名空间中存在的所有资源。

   ```
   kubectl get all -n eks-sample-app
   ```

   示例输出如下。

   ```
   NAME                                               READY   STATUS    RESTARTS   AGE
   pod/eks-sample-linux-deployment-65b7669776-m6qxz   1/1     Running   0          27m
   pod/eks-sample-linux-deployment-65b7669776-mmxvd   1/1     Running   0          27m
   pod/eks-sample-linux-deployment-65b7669776-qzn22   1/1     Running   0          27m
   
   NAME                               TYPE         CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
   service/eks-sample-linux-service   ClusterIP    10.100.74.8     <none>        80/TCP    32m
   
   NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
   deployment.apps/eks-sample-linux-deployment 3/3     3            3           27m
   
   NAME                                                      DESIRED   CURRENT   READY   AGE
   replicaset.apps/eks-sample-linux-deployment-776d8f8fd8    3         3         3       27m
   ```

   在输出中，可以看到之前步骤部署的示例清单中指定的服务和部署。您还可以看到三组容器。这是因为在示例清单 指定了 `3` `replicas`。有关更多信息，请参阅 Kubernetes 文档中的 [Pod](https://kubernetes.io/docs/concepts/workloads/pods/pod/)。即使没有在示例清单中指定，Kubernetes 也会自动创建 `replicaset` 资源。有关 `ReplicaSets` 的更多信息，请参阅 Kubernetes 文档中的 [ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/)。
**注意**  
Kubernetes 保持清单中指定的副本数目。如果这是生产部署，并且您希望 Kubernetes 为容器组（pod）横向扩展副本数量或纵向扩展计算资源，则按照[使用 Horizontal Pod Autoscaler 调整容器组（pod）部署](horizontal-pod-autoscaler.md)和[使用 Vertical Pod Autoscaler 调整容器组（pod）资源](vertical-pod-autoscaler.md)进行此操作。

1. 查看已部署服务的详细信息。

   ```
   kubectl -n eks-sample-app describe service eks-sample-linux-service
   ```

   示例输出如下。

   ```
   Name:              eks-sample-linux-service
   Namespace:         eks-sample-app
   Labels:            app=eks-sample-linux-app
   Annotations:       <none>
   Selector:          app=eks-sample-linux-app
   Type:              ClusterIP
   IP Families:       <none>
   IP:                10.100.74.8
   IPs:               10.100.74.8
   Port:              <unset>  80/TCP
   TargetPort:        80/TCP
   Endpoints:         192.168.24.212:80,192.168.50.185:80,192.168.63.93:80
   Session Affinity:  None
   Events:            <none>
   ```

   在前面的输出中，`IP:` 值是一个唯一 IP 地址，可以从集群内的任何节点或容器组（pod）访问，但无法从集群外部访问。`Endpoints` 值是从 VPC 内分配给属于服务一部分的容器组（pod）的 IP 地址。

1. 在上一步[查看命名空间](#sample-app-view-namespace)时，查看输出列出的一个 Pod（一组容器）的详细信息。将 *776d8f8fd8-78w66* 替换为针对其中一个容器组（pod）返回的值。

   ```
   kubectl -n eks-sample-app describe pod eks-sample-linux-deployment-65b7669776-m6qxz
   ```

   缩减的输出示例

   ```
   Name:         eks-sample-linux-deployment-65b7669776-m6qxz
   Namespace:    eks-sample-app
   Priority:     0
   Node:         ip-192-168-45-132.us-west-2.compute.internal/192.168.45.132
   [...]
   IP:           192.168.63.93
   IPs:
     IP:           192.168.63.93
   Controlled By:  ReplicaSet/eks-sample-linux-deployment-65b7669776
   [...]
   Conditions:
     Type              Status
     Initialized       True
     Ready             True
     ContainersReady   True
     PodScheduled      True
   [...]
   Events:
     Type    Reason     Age    From                                                 Message
     ----    ------     ----   ----                                                 -------
     Normal  Scheduled  3m20s  default-scheduler                                    Successfully assigned eks-sample-app/eks-sample-linux-deployment-65b7669776-m6qxz to ip-192-168-45-132.us-west-2.compute.internal
   [...]
   ```

   在上一个输出中，`IP:` 的值是唯一 IP，该 IP 从分配给节点所在子网的 CIDR 块中分配给容器组（pod）。如果您希望从其他 CIDR 块中为 Pod 分配 IP 地址，则可以更改默认行为。有关更多信息，请参阅 [使用自定义网络在备用子网中部署容器组（pod）](cni-custom-network.md)。您还可以看到 Kubernetes 调度器在 IP 地址为 *192.168.45.132* 的 `Node` 上调度容器组（pod）。
**提示**  
无需使用命令行，即可在 AWS 管理控制台中查看有关容器组（pod）、服务、部署和其他 Kubernetes 资源的许多详细信息。有关更多信息，请参阅 [在 AWS 管理控制台中查看 Kubernetes 资源](view-kubernetes-resources.md)。

## 在容器组（pod）上运行 Shell
<a name="_run_a_shell_on_a_pod"></a>

1. 在上一步中描述的 Pod（一组容器）上运行 Shell，将 *65b7669776-m6qxz* 替换为其中一个 Pod 的 ID。

   ```
   kubectl exec -it eks-sample-linux-deployment-65b7669776-m6qxz -n eks-sample-app -- /bin/bash
   ```

1. 在容器组（pod）Shell 中，查看上一步中随部署一起安装的 Web 服务器的输出。您只需指定服务名称。默认情况下，CoreDNS 将其解析为服务的 IP 地址，该地址与 Amazon EKS 集群一起部署。

   ```
   curl eks-sample-linux-service
   ```

   示例输出如下。

   ```
   <!DOCTYPE html>
   <html>
   <head>
   <title>Welcome to nginx!</title>
   [...]
   ```

1. 在 Pod（一组容器）Shell 中，查看 Pod（一组容器）的 DNS 服务器。

   ```
   cat /etc/resolv.conf
   ```

   示例输出如下。

   ```
   nameserver 10.100.0.10
   search eks-sample-app.svc.cluster.local svc.cluster.local cluster.local us-west-2.compute.internal
   options ndots:5
   ```

   在之前的输出中，`10.100.0.10` 自动分配为部署到集群的所有 Pod（一组容器）的 `nameserver`。

1. 键入 `exit`，与 Pod（一组容器）断开连接。

1. 使用完示例应用程序后，您可以使用以下命令删除示例命名空间、服务和部署。

   ```
   kubectl delete namespace eks-sample-app
   ```

## 后续步骤
<a name="sample-deployment-next-steps"></a>

部署示例应用程序后，您可能想尝试以下其中一些练习：
+  [使用应用程序负载均衡器路由应用程序和 HTTP 流量](alb-ingress.md) 
+  [使用网络负载均衡器路由 TCP 和 UDP 流量](network-load-balancing.md) 