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

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 随着云原生的兴起,越来越多的应用选择基于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和节点,实现动态的水平扩容和垂直扩容。然而,不幸的是,许多团队在自动扩容方面存在一些不可预测性的问题。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
8天前
|
人工智能 弹性计算 运维
ACK Edge与IDC:高效容器网络通信新突破
本文介绍如何基于ACK Edge以及高效的容器网络插件管理IDC进行容器化。
|
14天前
|
Kubernetes Cloud Native 微服务
探索云原生技术:容器化与微服务架构的融合之旅
本文将带领读者深入了解云原生技术的核心概念,特别是容器化和微服务架构如何相辅相成,共同构建现代软件系统。我们将通过实际代码示例,探讨如何在云平台上部署和管理微服务,以及如何使用容器编排工具来自动化这一过程。文章旨在为开发者和技术决策者提供实用的指导,帮助他们在云原生时代中更好地设计、部署和维护应用。
|
11天前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
141 77
|
9天前
|
人工智能 运维 监控
阿里云ACK容器服务生产级可观测体系建设实践
本文整理自2024云栖大会冯诗淳(花名:行疾)的演讲,介绍了阿里云容器服务团队在生产级可观测体系建设方面的实践。冯诗淳详细阐述了容器化架构带来的挑战及解决方案,强调了可观测性对于构建稳健运维体系的重要性。文中提到,阿里云作为亚洲唯一蝉联全球领导者的容器管理平台,其可观测能力在多项关键评测中表现优异,支持AI、容器网络、存储等多个场景的高级容器可观测能力。此外,还介绍了阿里云容器服务在多云管理、成本优化等方面的最新进展,以及即将推出的ACK AI助手2.0,旨在通过智能引擎和专家诊断经验,简化异常数据查找,缩短故障响应时间。
阿里云ACK容器服务生产级可观测体系建设实践
|
9天前
|
运维 Kubernetes 调度
阿里云容器服务 ACK One 分布式云容器企业落地实践
阿里云容器服务ACK提供强大的产品能力,支持弹性、调度、可观测、成本治理和安全合规。针对拥有IDC或三方资源的企业,ACK One分布式云容器平台能够有效解决资源管理、多云多集群管理及边缘计算等挑战,实现云上云下统一管理,提升业务效率与稳定性。
|
19天前
|
开发框架 安全 开发者
Docker 是一种容器化技术,支持开发者将应用及其依赖打包成容器,在不同平台运行而无需修改。
Docker 是一种容器化技术,支持开发者将应用及其依赖打包成容器,在不同平台运行而无需修改。本文探讨了 Docker 在多平台应用构建与部署中的作用,包括环境一致性、依赖管理、快速构建等优势,以及部署流程和注意事项,展示了 Docker 如何简化开发与部署过程,提高效率和可移植性。
46 4
|
19天前
|
负载均衡 网络协议 算法
Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式
本文探讨了Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式,以及软件负载均衡器、云服务负载均衡、容器编排工具等实现手段,强调两者结合的重要性及面临挑战的应对措施。
47 3
|
21天前
|
运维 Kubernetes Docker
深入理解容器化技术:Docker与Kubernetes的协同工作
深入理解容器化技术:Docker与Kubernetes的协同工作
43 1
|
16天前
|
人工智能 Kubernetes Cloud Native
荣获2024年AI Cloud Native典型案例,阿里云容器产品技术能力获认可
2024全球数字经济大会云·AI·计算创新发展大会,阿里云容器服务团队携手客户,荣获“2024年AI Cloud Native典型案例”。
|
9天前
|
存储 Kubernetes 关系型数据库
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
本文源自2024云栖大会苏雅诗的演讲,探讨了K8s集群业务为何需要灾备及其重要性。文中强调了集群与业务高可用配置对稳定性的重要性,并指出人为误操作等风险,建议实施周期性和特定情况下的灾备措施。针对容器化业务,提出了灾备的新特性与需求,包括工作负载为核心、云资源信息的备份,以及有状态应用的数据保护。介绍了ACK推出的备份中心解决方案,支持命名空间、标签、资源类型等维度的备份,并具备存储卷数据保护功能,能够满足GitOps流程企业的特定需求。此外,还详细描述了备份中心的使用流程、控制台展示、灾备难点及解决方案等内容,展示了备份中心如何有效应对K8s集群资源和存储卷数据的灾备挑战。

相关产品

  • 容器服务Kubernetes版