21、Kubernetes 容器部署全攻略

Kubernetes 容器部署全攻略

1. 容器部署到 Kubernetes

在使用 Kubernetes Dashboard 时,可利用特定文件在仪表板中直接创建新 Pod,但这里暂不详细探讨此方法,有兴趣的话可以自行探索。

1.1 验证资源创建

运行 kubectl apply 命令后,可通过 kubectl get pods 验证资源是否创建成功,执行该命令后会有相应输出。

1.2 Pod 状态

Pod 的状态(即 Pod 的阶段)有以下几种:
- Pending :Pod 正在创建,尚未运行。通常意味着容器正在从容器注册表中拉取,或者仍在启动中。
- Running :Pod 正在运行,其容器也在运行。
- Succeeded :对于非持续运行的 Pod,此状态表示 Pod 已成功完成。
- Failed :表示 Pod 运行失败。
- Unknown :由于某些原因,无法获取 Pod 的状态。

一般来说,几分钟后 NGINX 容器镜像应该能成功运行。若未运行,可使用 kubectl describe pod <pod - name> kubectl logs <pod - name> 来调查 Pod。NGINX 容器镜像非常成熟,容器本身不太可能出错,但我们为 Python 和 Node.js 项目构建的容器可能并非如此。

1.3 访问 NGINX 默认页面

Pod 资源使容器运行起来后,若要访问面向互联网的 NGINX 默认页面,就需要引入第一个 Service 资源。

2. 第一个 Service

与虚拟机上未发布的容器类似,Pod 若不进行额外配置,就无法与外界通信,Pod 之间的通信也需要额外配置。在实现集群内部通信之前,先通过 Kubernetes Service 资源将 Pod 暴露到互联网。要实现这一点,需创建一个包含 Service 资源( kind: Service )的新清单,将 NGINX Pod 暴露到互联网。

2.1 Kubernetes Service 类型

Kubernetes 有以下几种基本的 Service 类型:
| 类型 | 描述 |
| ---- | ---- |
| NodePort(外部流量) | 集群有三个节点(虚拟机),每个节点都有 ISP 和 Akamai Connected Cloud 提供的静态公共 IP 地址。使用 NodePort Service 资源可将 Pod 暴露到 K8s 集群中每个可用节点的特定端口,如 30007。 |
| LoadBalancer(外部流量) | 这是一种很实用的 Service 类型,它会自动为 K8s Service 资源配置一个基于云的负载均衡器,并分配一个静态公共 IP 地址。在 Akamai Connected Cloud 中,Linode Kubernetes Engine 会通过名为 Linode NodeBalancers 的基于云的负载均衡服务为我们提供一个公共静态 IP 地址。 |
| ClusterIP(仅内部集群流量) | 使用此 Service 类型可让 Kubernetes 集群中的其他容器与我们的 Pod(或 Deployments)进行通信,实现集群内的容器间通信。更准确地说,ClusterIP 用于集群内的 Pod 到 Pod 或 Deployment 到 Deployment 的通信。对于不需要暴露到互联网的 Pod 或 Deployment,如数据库、内部 API 等,ClusterIP 非常适用。 |

这里我们先从 NodePort 开始,因为它无需在集群或云提供商中添加其他内容,便于快速测试。

2.2 更新 Pod 清单

在创建 Service 资源之前,需要更新 Pod 清单,以便 Service 能更轻松地找到并关联到它。在 Pod 清单( your - first - pod.yaml )的 metadata 块中添加一个标签,示例如下:

apiVersion: v1
kind: Pod
metadata:
  name: first - pod - nginx
  label:
    app: my - nginx

若 Pod 或 Deployment 没有标签,Service 资源将无法正常工作。更新 Pod 清单后,使用 kubectl apply - f my - first - pod.yaml 应用更改。然后运行 kubectl get pods 确保 Pod 仍在运行,再运行 kubectl get pods my - nginx - o yaml 查看更多 Pod 详细信息,包括验证标签是否存在。

2.3 元数据标签与选择器

在任何 Kubernetes 清单中,无论其类型(Pod、Service、Deployment 等),都可以为资源应用元数据标签。元数据标签是键值对,可用于过滤任何 Kubernetes 资源。例如,更新后的 Pod 资源使用 app: my - nginx 标签,可使用 kubectl get pods - l app = my - nginx 命令查看匹配该选择器的 Pod 列表,可能会列出匹配的 Pod 或没有任何 Pod。

选择器(过滤器)用于缩小任何给定 Kubernetes 资源的结果列表,使用 -l --selector 标志,例如 kubectl get <resource> - l <key>=<value> kubectl get <resource> --selector <key>=<value> 。以下是一些选择器过滤的示例:
- kubectl get pods - l my - label = my - value
- kubectl get pods - l app = my - nginx
- kubectl get pods --l app = nginx
- kubectl get services - l app = my - nginx
- kubectl get deployments - l sugar = spice
- kubectl get deployments - l maverick = pilot

元数据标签的键和值可以是任意的,资源的元数据标签键值(如 Pod 清单中的 app: )对 Kubernetes 本身没有特殊意义,只是一个惯用名称。只需记住使用的键值对将作为资源的选择器值。

2.4 Service 关键声明

spec: 块中,为 Service 定义以下关键声明:
- type: :选择要使用的 Kubernetes Service 类型,如 NodePort、LoadBalancer 或 ClusterIP。
- selector: :选择器是 Service 最重要的部分。Service 将根据此处定义的匹配键值对自动负载均衡请求。若使用的键值对没有过滤结果(如 kubectl get pods - l incorrect:data ),则该 Service 无效。
- ports :类似于 Docker 的 publish 参数( -p --publish ),在 kind = NodePort 的情况下,需定义三个端口值:
- port :供集群内部通信访问此 Service。
- targetPort :由 Pod 或 Deployment 定义的运行容器的端口,类似于 Docker 中的映射端口。
- nodePort :要在集群中每个节点上暴露的端口,如 http://<node - static - public - ip>:<nodePort>

2.5 创建 Service 清单

在创建 Service 之前,先做如下检查:
- 节点使用的端口为 30007( nodePort: 30007 )。
- 用于集群内部通信的端口为 5050( port: 5050 )。
- 容器期望的端口作为 targetPort ,如 80( targetPort: 80 )。
- Pod 有 app: my - nginx 标签,Service 可使用该选择器找到 Pod。

基于以上信息,在 roadtok8s - kube 目录中创建一个名为 my - first - service.yaml 的文件,内容如下:

apiVersion: v1
kind: Service
metadata:
  name: first - service - nginx
spec:
  type: NodePort
  ports:
  - port: 5050
    targetPort: 80
    nodePort: 30007
  selector:
    app: my - nginx

使用 kubectl apply - f my - first - service.yaml 配置此 Service。配置完成后,可使用 kubectl get service kubectl get svc 验证 Service 是否可用并列出。列出的 Services 应包含我们创建的 first - service - nginx 和默认的 Kubernetes Service。默认的 Kubernetes Service 用于集群与托管 Kubernetes API 通信,此 API 即控制平面,是资源运行的核心。

2.6 验证 NodePort

要验证 NodePort 是否正常工作,需获取每个节点的公共静态 IP 地址,可通过以下两种方式:
- 登录 Akamai Connected Cloud 控制台查看。
- 运行 kubectl get nodes - o wide 命令,该命令会列出内部和外部 IP 地址。

找到节点的公共静态 IP 地址后,访问 http://<your - node - public - ip>:30007 ,就能看到 NGINX 的欢迎页面,这意味着已成功在 Kubernetes 上部署第一个连接到互联网的容器。

2.7 从 Pod 到 Deployments

Deployment 资源是将容器部署到 Kubernetes 最常用的方式,它能让我们扩展 Pod,进而扩展容器。Deployment 允许在集群的各个节点和虚拟机上运行同一容器应用的多个实例。扩展 Deployment 后,Service 资源会自动将流量负载均衡到每个可用且准备好接收流量的 Pod。

Deployment 本质上是 Pod 的集合,其清单基本是 Pod 清单在 spec: 块中增加了一些声明:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    A(Deployment):::process --> B(replicas):::process
    A --> C(selector):::process
    A --> D(template):::process
    D --> E(metadata):::process
    D --> F(spec):::process
    E --> G(labels):::process
    F --> H(containers):::process
  • replicas: :此 Deployment 要运行的 Pod 数量。若未指定,默认为 1。
  • selector: :预先定义标签选择器以匹配 Pod,该选择器也会在 Pod 模板中使用。
  • template: :这就是去掉 kind apiVersion 声明的 Pod 清单,可直接复制粘贴 metadata spec 值。在 metadata 值中,要确保标签的键值对与 Deployment 的 selector: 块中的选择器匹配。
  • apiVersion: :对于 Deployment,使用 apps/v1 作为 apiVersion

roadtok8s - kube 目录中创建一个名为 my - first - deployment.yaml 的新文件,内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx - deployment
spec:
  replicas: 15
  selector:
    matchLabels:
      app: my - nginx
  template:
    metadata:
      labels:
        app: my - nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest

使用 kubectl apply - f my - first - deployment.yaml 应用更改,然后使用 kubectl get deployments kubectl get deploy 验证 Deployment。示例中设置了 15 个副本,若运行 kubectl get pods --selector app = my - nginx ,应该能看到至少 15 个 Pod 在运行(可能因为之前的 Pod 资源清单有 16 个)。

副本数量是 Kubernetes Deployment 资源的期望状态,Kubernetes 会持续部署 Pod,直到达到清单中定义的 15 个且都健康运行。若有 Pod 失败,Kubernetes 会自动推出新的 Pod,直到达到副本数量。默认情况下,推出过程是分层的,更新 Deployment 清单时,每次只会更新几个 Pod,这有助于在不造成停机的情况下部署容器的新版本,并确保失败的容器对 Service 的影响最小。

Pod 资源没有副本数量的概念,若 Pod 清单(如 kind: Pod )中的容器失败,开发者需手动干预。使用配置好的 Deployment 清单时,无需更改 Service 清单,因为 Deployment 和 Pod 使用了相同的选择器,Service 会自动将流量负载均衡到 Deployment 资源的 15 个 Pod 和 Pod 资源的 1 个 Pod 上,总共 16 个 Pod 可供 Service 资源调用。最后,可使用以下命令删除所有三个资源:
- kubectl delete - f my - first - pod.yaml
- kubectl delete - f my - first - deployment.yaml
- kubectl delete - f my - first - service.yaml

2.8 使用 ConfigMaps 自定义 NGINX

ConfigMaps 资源可作为卷或环境变量附加到 Deployment(或直接附加到 Pod 资源),是在不重建容器镜像的情况下修改容器默认配置的好方法。

roadtok8s - kube 目录中创建一个名为 custom - nginx 的新文件夹,在该文件夹中创建 1 - configmap.yaml 文件,内容如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx - configmap
data:
  index.html: |
    <html>
      <head>
        <title>Hello World</title>
      </head>
      <body>
        <h1>Hello World</h1>
      </body>
    </html>

ConfigMap 资源使用 data: 而不是 spec: 来定义我们选择使用的键值对,非常灵活。这里使用 index.html 作为键,其值是一个多行的简单 HTML。

为了覆盖 NGINX 容器镜像自带的默认 index.html 值,在 Deployment 中会使用 data: 里的 index.html: 键值。为此,将 ConfigMap 作为卷挂载到 Deployment 清单中。在 Deployment 上挂载卷时,挂载的是只读卷,因为 ConfigMap 不打算被容器修改。若需要挂载读写卷,Deployment 或 Pod 可使用持久卷。

custom - nginx 文件夹中创建 2 - deployment.yaml 文件,内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: custom - nginx - deploy
spec:
  replicas: 15
  selector:
    matchLabels:
      app: custom - nginx
  template:
    metadata:
      labels:
        app: custom - nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        volumeMounts:
        - name: my - configmap - volume
          mountPath: /usr/share/nginx/html
          readOnly: true
      volumes:
      - name: my - configmap - volume
        configMap:
          name: nginx - configmap

再为这个 Deployment 创建一个新的 Service。在 custom - nginx 文件夹中创建 3 - service.yaml 文件,内容如下:

apiVersion: v1
kind: Service
metadata:
  name: custom - nginx - svc
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 80
    nodePort: 30008
  selector:
    app: custom - nginx

注意,这里的 port nodePort 与之前的 Service 不同,是为了避免端口冲突。现在 custom - nginx 文件夹有以下文件:
- 1 - configmap.yaml
- 2 - deployment.yaml
- 3 - service.yaml

文件的显示顺序很重要,因为 Deployment 依赖于 ConfigMap,Service 依赖于 Deployment。若顺序错误,部分或所有这些 Services 可能无法正确配置,可能需要多次配置才能正常工作。可使用以下命令配置这些文件:
- kubectl apply - f custom - nginx/1 - configmap.yaml
- kubectl apply - f custom - nginx/2 - deployment.yaml
- kubectl apply - f custom - nginx/3 - service.yaml

或者简单地使用 kubectl apply - f custom - nginx/ ,它会按文件夹中文件的显示顺序配置所有文件,这就是为什么给文件加上 1 - 2 - 3 - 前缀的原因。打开任意节点公共 IP 地址上的 nodePort (如 30008),就能看到自定义的页面。

3. 配置与部署总结

3.1 资源配置顺序总结

在 Kubernetes 中,不同资源之间存在依赖关系,因此配置顺序至关重要。以下是之前操作中涉及的资源及其配置顺序:
| 资源类型 | 文件名 | 依赖关系 | 配置命令 |
| ---- | ---- | ---- | ---- |
| ConfigMap | 1 - configmap.yaml | 无 | kubectl apply - f custom - nginx/1 - configmap.yaml |
| Deployment | 2 - deployment.yaml | 依赖 ConfigMap | kubectl apply - f custom - nginx/2 - deployment.yaml |
| Service | 3 - service.yaml | 依赖 Deployment | kubectl apply - f custom - nginx/3 - service.yaml |

为了确保配置顺序正确,我们给文件添加了前缀,也可以使用 kubectl apply - f custom - nginx/ 按文件夹中文件的显示顺序进行配置。

3.2 验证与访问总结

在完成资源配置后,需要进行验证和访问操作,确保部署成功。以下是验证和访问的步骤总结:
1. 验证 Pod 状态 :使用 kubectl get pods 命令查看 Pod 的运行状态,确保 Pod 正常运行。
2. 验证 Service 状态 :使用 kubectl get service kubectl get svc 命令查看 Service 的状态,确认 Service 可用。
3. 获取节点 IP 地址 :可以通过登录 Akamai Connected Cloud 控制台或运行 kubectl get nodes - o wide 命令获取节点的公共静态 IP 地址。
4. 访问应用 :根据配置的 nodePort ,访问 http://<your - node - public - ip>:<nodePort> 查看应用的运行情况。

3.3 资源清理总结

在不需要这些资源时,需要进行清理操作,避免资源浪费。可以使用以下命令删除之前创建的资源:
- kubectl delete - f my - first - pod.yaml
- kubectl delete - f my - first - deployment.yaml
- kubectl delete - f my - first - service.yaml
- kubectl delete - f custom - nginx/1 - configmap.yaml
- kubectl delete - f custom - nginx/2 - deployment.yaml
- kubectl delete - f custom - nginx/3 - service.yaml

4. 深入理解 Kubernetes 资源

4.1 不同资源的作用对比

Kubernetes 中有多种资源类型,如 Pod、Service、Deployment 和 ConfigMap,它们各自有不同的作用。以下是这些资源的作用对比:
| 资源类型 | 作用 | 特点 |
| ---- | ---- | ---- |
| Pod | 是 Kubernetes 中最小的可部署单元,用于运行容器 | 单个容器或多个相关容器的组合,不具备自动扩展能力 |
| Service | 为 Pod 提供稳定的网络访问方式,实现负载均衡 | 可以将流量分发到多个 Pod,有不同的类型(NodePort、LoadBalancer、ClusterIP) |
| Deployment | 用于管理 Pod 的副本数量和滚动更新,实现容器的扩展和升级 | 可以自动创建和管理多个 Pod 副本,支持滚动更新和回滚 |
| ConfigMap | 用于存储配置数据,可作为卷或环境变量挂载到 Pod 中 | 可以在不重建容器镜像的情况下修改容器的配置 |

4.2 选择器的重要性

选择器在 Kubernetes 中起着至关重要的作用,它用于过滤和匹配资源。通过选择器,Service 可以找到对应的 Pod,Deployment 可以管理特定的 Pod 副本。以下是选择器的使用示例:
- kubectl get pods - l app = my - nginx :查找带有 app: my - nginx 标签的 Pod。
- kubectl get services - l app = my - nginx :查找带有 app: my - nginx 标签的 Service。

选择器的使用使得资源的管理和调度更加灵活和高效。

4.3 副本数量与自动修复机制

Deployment 资源中的副本数量定义了要运行的 Pod 数量,Kubernetes 会自动确保实际运行的 Pod 数量达到副本数量。如果某个 Pod 失败,Kubernetes 会自动创建新的 Pod 来替换它,实现自动修复。这种机制保证了应用的高可用性和稳定性。

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    A(Deployment):::process --> B(replicas: 15):::process
    B --> C{Pod 数量是否达到 15?}:::process
    C -->|是| D(正常运行):::process
    C -->|否| E(创建新 Pod):::process
    E --> C

5. 常见问题与解决方案

5.1 Pod 无法正常运行

如果 Pod 无法正常运行,可能是由于以下原因:
- 镜像拉取失败 :检查镜像的名称和版本是否正确,确保镜像仓库可访问。
- 资源不足 :检查节点的资源使用情况,确保节点有足够的 CPU、内存等资源。
- 配置错误 :检查 Pod 清单中的配置是否正确,如端口号、环境变量等。

解决方案:
- 使用 kubectl describe pod <pod - name> 命令查看 Pod 的详细信息,定位问题。
- 使用 kubectl logs <pod - name> 命令查看 Pod 的日志,获取更多错误信息。

5.2 Service 无法访问

如果 Service 无法访问,可能是由于以下原因:
- 选择器配置错误 :检查 Service 的 selector 配置是否与 Pod 的标签匹配。
- 端口配置错误 :检查 port targetPort nodePort 的配置是否正确。
- 网络问题 :检查节点的网络连接是否正常,防火墙是否允许访问。

解决方案:
- 使用 kubectl get service <service - name> - o yaml 命令查看 Service 的详细配置,确保配置正确。
- 使用 kubectl get pods - l <selector> 命令查看匹配的 Pod 是否正常运行。

5.3 Deployment 滚动更新失败

如果 Deployment 滚动更新失败,可能是由于以下原因:
- 新镜像有问题 :检查新镜像的版本和配置是否正确,确保新镜像可正常运行。
- 资源不足 :检查节点的资源使用情况,确保节点有足够的资源来创建新的 Pod。
- 配置冲突 :检查 Deployment 清单中的配置是否与现有资源冲突。

解决方案:
- 使用 kubectl rollout status deployment <deployment - name> 命令查看滚动更新的状态。
- 使用 kubectl rollout undo deployment <deployment - name> 命令回滚到上一个版本。

6. 总结与展望

6.1 总结

通过本文的介绍,我们学习了如何将容器部署到 Kubernetes,包括创建 Pod、Service、Deployment 和 ConfigMap 等资源。了解了不同资源的作用和配置方法,以及如何使用选择器进行资源过滤和匹配。同时,还介绍了常见问题的解决方案,帮助我们在实际操作中快速定位和解决问题。

6.2 展望

Kubernetes 作为容器编排领域的领导者,不断发展和完善。未来,我们可以进一步探索 Kubernetes 的高级特性,如 StatefulSet、DaemonSet、Ingress 等,实现更复杂的应用部署和管理。同时,结合云原生技术,如微服务、DevOps 等,构建更加高效、稳定和可扩展的应用架构。

希望本文能帮助你更好地理解和使用 Kubernetes,在实际项目中取得更好的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值