云原生技术专题 | 云原生容器编排问题盘点,总结分享年度使用Kubernetes的坑和陷阱

简介: 随着云原生的兴起,越来越多的应用选择基于Kubernetes进行部署,可以说Kubernetes 是最流行的容器编排和部署平台。它的强大功能特性,可以保障在生产中可靠地运行容器化应用程序,相关的DevOps等工具也应运而生,下面就是小编简单化了一个Kubernetes的逻辑架构图。

Kubernetes与云原生

随着云原生的兴起,越来越多的应用选择基于Kubernetes进行部署,可以说Kubernetes 是最流行的容器编排和部署平台。它的强大功能特性,可以保障在生产中可靠地运行容器化应用程序,相关的DevOps等工具也应运而生,下面就是小编简单化了一个Kubernetes的逻辑架构图。

如何开发面向Kubernetes部署和运维的微服务应用是很多开发者与架构师要解决的问题。通过本文的阅读,作者介绍了在Kubernetes体系下构建高效、可靠的微服务应用所遇到的种种问题。希望这篇文章能够对您有所帮助。

总体问题大纲分布如下说是:

在接下来的内容中,我们将探讨今年个人遇到的5个常见的Kubernetes问题和错误。通过识别并避免这些挑战,您将能够提高应用程序的可扩展性、可靠性和安全性,同时更好地控制集群及其部署。

性能问题:忽略节点选择器导致调度效率低下

整个集群效能的表现关键在于Pod是否能被精准地部署至适宜的节点上。在众多的集群配置中,常常包含多样化的节点类型,比如那些专为常规应用程序设计的小型内存和低配CPU节点以及针对高密度后台服务所配置的大型内存和高配CPU节点

问题排查和分析

  • 首先,我们一定要侧重分析当前节点池的利用率和资源分配情况,确定是否存在未充分利用的较小节点。
  • 如果存在未充分利用的较小节点,使用自动化工具进行节点重分配。将该节点上运行的负载迁移到其他节点上,以实现节点资源的最优使用。
  • 最后,在节点迁移之前,需再三确保目标节点有足够的资源来承载额外的负载。

注意:考虑负载迁移对运行中应用的影响,并确保其在迁移过程中不会中断

解决方案

为了避免出现这个问题,我们可以使用一种有效的方法来管理Pod的调度,即通过在节点上设置标签,并使用节点选择器将Pod分配给兼容的节点。这种方法可以确保Pod被正确地调度到具备所需资源和能力的节点上。

案例介绍

首先,我们为节点设置适当的标签。标签可以根据节点的特性、硬件配置或其他自定义需求进行定义。

例如,可以为具备高性能GPU的节点设置一个标签,或者为具备特定版本的软件组件的节点设置一个标签。

接下来,在Pod的定义中添加一个节点选择器。节点选择器是一组标签键值对,用于指定Pod所需的节点属性或条件。

例如,可以指定Pod需要运行在具备某个特定标签的节点上。

当调度程序接收到新的Pod创建请求时,它将根据Pod的节点选择器进行匹配,并将Pod分配给满足条件的节点。这样,Pod就能够被正确、高效地调度到合适的节点上,避免了资源浪费和性能问题。

apiVersion: v1
kind: Pod
metadata:
  name: pod-node-selector-sample
spec:
  containers:
    - name: tomcat
      image: tomcat:latest
  nodeSelector:
    node-class: middleLevel

为了确保Pod只会调度到设置了标签的节点(例如node-class: middleLevel),我们可以使用kubectl命令在匹配的节点上设置标签。

首先我们先使用kubectl命令列出当前可用的节点

kubectl get nodes

之后,找到您想要为其添加标签的特定节点。使用kubectl命令在该节点上设置标签。你可以使用以下命令格式:

kubectl label nodes <节点名称> <标签键>=<标签值>

此外,如果节点的名称是node-1,要将标签node-class设置为middleLevel,您可以运行以下命令:

kubectl label nodes node-1 node-class=middleLevel

这将在节点node-1上设置了一个标签node-class,其值为middleLevel。

配置问题:应用服务端口与Service(KubectlProxy)控制的端口不一致

在我们的运行环境中,确保Service将流量路由到对应的Pod上的正确端口非常重要。为了解决这个问题,您需要确保Service的端口定义与Pod容器的端口一致。

以下是一个错误的配置Service和Pod的配置文件:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  labels:
    app: test-app
spec:
  image: tomcat:latest
  ports:
    - containerPort: 8081

---

apiVersion: v1
kind: Service
metadata:
  name: test-service
spec:
  selector:
    app: test-app
  ports:
    - protocol: TCP
      port: 9000
      targetPort: 8082

在上述示例中,Service的目标端口(targetPort)设置为8081,与Pod容器的实际端口(containerPort:8081)不一致。通过调整Service的配置,确保正确路由流量到Pod的适当端口,将有助于保证应用程序的正常运行和可靠性。

正确的配置如下所示:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  labels:
    app: test-app
spec:
  image: tomcat:latest
  ports:
    - containerPort: 8081

---

apiVersion: v1
kind: Service
metadata:
  name: test-service
spec:
  selector:
    app: test-app
  ports:
    - protocol: TCP
      port: 9000
      targetPort: 8081

隔离问题:容器组件部署到K8S集群错误的命名空间或者默认空间(建议)

Kubernetes命名空间在集群中提供了一定程度的隔离,将一组服务逻辑分组在一起。在使用命名空间时,请记住为每个服务和kubectl命令指定目标命名空间。如果没有指定目标命名空间,将默认使用default命名空间。

如果服务没有部署在合适的命名空间下,就会导致相关的服务器请求无法到达,在这里给大家看一个逻辑结构图就可以了解到:

为了避免这个问题,请确保在部署和管理服务时,建议大家始终使用正确的命名空间。在执行kubectl命令时,可以使用--namespace参数来指定目标命名空间。例如:

kubectl get pods --namespace=test-namespace

这将列出位于test-namespace命名空间下的Pods。此外,在创建和管理服务时,也要确保正确指定目标命名空间。例如,在创建Deployment时,可以在yaml文件中使用namespace字段指定目标命名空间:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-app
  namespace: test-namespace
...

确保Deployment部署在test-namespace命名空间下。通过正确使用命名空间,可以保证每个服务被正确隔离,并且相关的服务器请求可以顺利到达。

资源问题:不进行设置资源请求和限制的Pod(命名空间也没有控制)

在Kubernetes集群中,正确地管理资源对于保持整个集群的稳定性非常重要。默认情况下,Pod并没有任何资源限制,除非我们显式地对其进行适当的配置,否则可能会导致Node节点的CPU和内存资源耗尽。

解决方案

在所有的Pod上设置适当的资源请求和限制,以减少资源竞争的问题。通过指定资源请求,Kubernetes可以为我们的Pod预留特定数量的资源,从而避免将其调度到无法提供足够容量的节点上。

设置资源限制

限制Pod使用的最大资源量,当Pod超过CPU或内存限制时,Kubernetes会对其进行限制,例如,限制超过CPU限制的Pod的处理能力,或者当达到内存限制时触发内存不足 (OOM) 来终止Pod的运行。下面是一个示例,展示如何在Pod的配置中设置资源请求和限制的参数:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: test-server
    image: test-image
    resources:
      requests:
        cpu: "0.5"
        memory: "1Gi"
      limits:
        cpu: "1"
        memory: "2Gi"

参数解释:

  • limits:Pod对CPU和内存的最大限制。
  • requests:Pod对CPU和内存的最小需求
    • cpu: 0.5 或 500m:表示0.5个CPU核心或500毫核(mCPU)的CPU资源请求/限制。
    • 1:表示1个整数CPU核心的CPU资源请求/限制。

注意:请根据具体需求和应用程序的资源消耗情况,来设置适当的资源请求和限制,以确保集群的稳定性和有效的资源利用。

状态问题:优化和使用Liveness和Readiness探针

Kubernetes探针是一种能够增加应用程序弹性的重要工具。它们可以向Kubernetes Pod报告应用程序的健康状况。

Liveness探针

当容器出现问题时(例如内存溢出)或Liveness探针的请求超时,Liveness探针会通知Kubernetes重新启动容器,以确保应用程序的可用性。

Readiness探针

Kubernetes提供了Readiness探针来发现并处理这些情况。容器所在的Pod会报告其未就绪状态的信息,并且将不接收来自Kubernetes Service的流量。

例如:应用程序在启动时可能需要加载大量数据或配置文件,或者在启动后需要等待外部服务。在这种情况下,我们既不希望停止应用程序的运行,也不希望将请求发送到它。

通过合理配置 Liveness 和 Readiness 探针,我们能够更好地监测和管理应用程序的状态,提高应用程序的可用性,并确保容器在适当的时候进行重新启动,从而提高整体系统的稳定性。

以下是一个示例,展示了如何在 Pod 的配置中设置 Liveness 和 Readiness 探针:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: test-server
    image: test-image
    livenessProbe:
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 5
    readinessProbe:
      httpGet:
        path: /readiness
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 10

所以首先探针一定要配置,此外要应对IO密集型以及CPU密集型等场景进行设置对应的参数值,切勿一套配置Cover主全场,那是不可能的。
对此我深有体会,总是出现服务负荷过高的时候,总是被探针Kill掉。

我的建议是:对于敏感度不高,且不是核心数据服务(无状态化的),可以酌量调大一些。肺腑之言。

最后总结

以上是作者根据个人经验和使用中出现的一些问题和错误的总结。希望其他开发者能够从中受益,避免犯类似的错误。我们选择使用Kubernetes的原因之一就是它具备弹性扩容的能力。正确的配置可以使Kubernetes在需求高峰期自动添加新的Pod和节点,实现动态的水平扩容和垂直扩容。然而,不幸的是,许多团队在自动扩容方面存在一些不可预测性的问题。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
8月前
|
运维 Kubernetes Cloud Native
智联招聘 × 阿里云 ACK One:云端弹性算力颠覆传统 IDC 架构,打造春招技术新范式
在 2025 年春季招聘季的激战中,智联招聘凭借阿里云 ACK One 注册集群与弹性 ACS 算力的深度融合,成功突破传统 IDC 机房的算力瓶颈,以云上弹性架构支撑千万级用户的高并发访问,实现招聘服务效率与稳定性的双重跃升。
|
8月前
|
存储 容器
46.[HarmonyOS NEXT RelativeContainer案例三] 打造自适应容器:内容驱动的智能尺寸调整技术
在HarmonyOS NEXT的UI开发中,创建能够根据内容自动调整尺寸的容器是实现灵活布局的关键。RelativeContainer结合自适应尺寸设置,可以实现内容驱动的智能尺寸调整,使UI更加灵活且易于维护。本教程将详细讲解如何创建自适应尺寸的RelativeContainer,帮助你掌握这一实用技术。
265 5
|
5月前
|
存储 Kubernetes 网络安全
关于阿里云 Kubernetes 容器服务(ACK)添加镜像仓库的快速说明
本文介绍了在中国大陆地区因网络限制无法正常拉取 Docker 镜像的解决方案。作者所在的阿里云 Kubernetes 集群使用的是较旧版本的 containerd(1.2x),且无法直接通过 SSH 修改节点配置,因此采用了一种无需更改 Kubernetes 配置文件的方法。通过为 `docker.io` 添加 containerd 的镜像源,并使用脚本自动修改 containerd 配置文件中的路径错误(将错误的 `cert.d` 改为 `certs.d`),最终实现了通过多个镜像站点拉取镜像。作者还提供了一个可重复运行的脚本,用于动态配置镜像源。虽然该方案能缓解镜像拉取问题,
607 2
|
7月前
|
NoSQL Redis Docker
使用Docker Compose工具进行容器编排的教程
以上就是使用Docker Compose进行容器编排的基础操作。这能帮你更有效地在本地或者在服务器上部署和管理多容器应用。
632 11
|
6月前
|
Kubernetes Cloud Native 持续交付
Docker:轻量级容器化技术解析
Docker:轻量级容器化技术解析
|
6月前
|
运维 测试技术 Docker
Docker:轻量级容器化技术革命
Docker:轻量级容器化技术革命
|
10月前
|
弹性计算 Java Maven
从代码到容器:Cloud Native Buildpacks技术解析
Cloud Native Buildpacks(CNB)是一种标准化、云原生的容器镜像构建系统,旨在消除手动编写Dockerfile,提供可重复、安全且高效的构建流程。它通过分层策略生成符合OCI标准的镜像,实现应用与基础镜像解耦,并自动化依赖管理和更新。阿里云应用管理支持通过CNB技术一键部署应用至ECS,简化构建和运行流程。
|
11月前
|
存储 运维 Kubernetes
容器数据保护:基于容器服务 Kubernetes 版(ACK)备份中心实现K8s存储卷一键备份与恢复
阿里云ACK备份中心提供一站式容器化业务灾备及迁移方案,减少数据丢失风险,确保业务稳定运行。
|
存储 Cloud Native 数据处理
从嵌入式状态管理到云原生架构:Apache Flink 的演进与下一代增量计算范式
本文整理自阿里云资深技术专家、Apache Flink PMC 成员梅源在 Flink Forward Asia 新加坡 2025上的分享,深入解析 Flink 状态管理系统的发展历程,从核心设计到 Flink 2.0 存算分离架构,并展望未来基于流批一体的通用增量计算方向。
442 0
从嵌入式状态管理到云原生架构:Apache Flink 的演进与下一代增量计算范式
|
6月前
|
运维 监控 Cloud Native
从本土到全球,云原生架构护航灵犀互娱游戏出海
本文内容整理自「 2025 中企出海大会·游戏与互娱出海分论坛」,灵犀互娱基础架构负责人朱晓靖的演讲内容,从技术层面分享云原生架构护航灵犀互娱游戏出海经验。
588 16

相关产品

  • 容器服务Kubernetes版
  • 推荐镜像

    更多