全部产品
Search
文档中心

容器服务 Kubernetes 版 ACK:高可靠推荐配置

更新时间:Nov 27, 2023

为了保证应用可以稳定可靠地运行在Kubernetes里,本文介绍构建Kubernetes集群时的推荐配置,例如集群创建、工作负载等方面。

集群创建推荐配置

磁盘类型及大小

磁盘类型

  • 推荐选择SSD盘。

  • 对于Worker节点,创建集群时推荐选择挂载数据盘。该数据盘用于供/var/lib/docker存放本地镜像,避免后续镜像过多导致根磁盘容量不够的问题。在运行一段时间后,本地可能存在很多无用的镜像,快速解决该问题的方法是先下线这台机器,重新构建数据盘后再上线。

磁盘大小

Kubernetes节点需要足够的磁盘空间,Docker镜像、系统日志、应用日志都保存在磁盘上。创建Kubernetes集群的时候,要考虑每个节点上要部署的Pod数量,每个Pod的日志大小、镜像大小、临时数据,再加上一些系统预留的值。

Kubernetes集群中,ECS操作系统占用3G左右的磁盘空间,建议预留ECS操作系统8G的空间。剩余的磁盘空间由Kubernetes资源对象使用。

是否立即构建Worker节点

创建集群时,节点类型若选择:

  • 按量付费,可在创建集群时,构建Worker节点。

  • 包年包月,创建集群时,可先不构建Worker节点,根据后续需求,单独购买ECS添加到集群。

网络选择

  • 如果需要连接外部的一些服务,如RDS等,则需要考虑复用原有的VPC,而不是创建一个新的VPC。因为VPC间是隔离的,您可以通过创建一个新的交换机,将运行Kubernetes的机器都放在这个交换机下,从而便于管理。

  • 在Kubernetes集群创建时提供两种网络插件:Terway和Flannel,可参见Terway与Flannel对比

  • Pod网络CIDR不能设置太小,如果太小,可支持的节点数量就会受限。这个值的设置需要与高级选项中的节点Pod数量综合考虑。例如:Pod网络CIDR的网段是/16,那么就有256*256个地址,如果每个节点Pod数量是128,则最多可以支持512个节点。

使用多可用区

阿里云支持多Region(地域),每个Region下又有不同的可用区。可用区是指在同一地域内,电力和网络互相独立的物理区域。多可用区能够实现跨区域的容灾能力,同时也会带来额外的网络延时。

为节点池配置部署集

部署集是控制ECS实例分布的策略,该策略将ECS实例分散部署在不同的物理服务器上,提升业务的高可用性和底层容灾能力。通过为节点池配置部署集,能够保证节点池弹出的ECS实例不会分布于同一物理机上,并通过亲和性配置,使您的应用对底层的节点拓扑进行感知,使其均匀地分布在不同节点上。具体操作,请参见节点池部署集最佳实践

工作负载推荐配置

声明每个Pod的resource

在使用Kubernetes集群时,经常会遇到:在一个节点上调度了太多的Pod,导致节点负载过高,无法正常对外提供服务的问题。

为避免上述问题,在Kubernetes中部署Pod时,您可以指定这个Pod需要Request及Limit的资源,Kubernetes在部署这个Pod的时候,就会根据Pod的需求找一个具有充足空闲资源的节点部署这个Pod。下面的例子中,声明Nginx这个Pod需要1核CPU,1024M的内存,运行中实际使用不能超过2核CPU和4096M内存。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    resources: # 资源声明
      requests:
        memory: "1024Mi"
        cpu: "1000m"
      limits:
        memory: "4096Mi"
        cpu: "2000m"

Kubernetes采用静态资源调度方式,对于每个节点上的剩余资源,它是这样计算的:节点剩余资源=节点总资源-已经分配出去的资源,并不是实际使用的资源。如果您自己手动运行一个很耗资源的程序,Kubernetes并不能感知到。

此外,所有Pod都要声明resources。没有声明resources的Pod被调度到某个节点后,Kubernetes不会在对应节点上减去这个Pod使用的资源,继而可能导致该节点上被调度过多Pod。

启动时等待下游服务,不要直接退出

有些应用可能会有一些外部依赖,例如需要从数据库(DB)读取数据或者依赖另外一个服务的接口。应用启动的时候,外部依赖未必都能满足。手动运维时,通常采用依赖不满足立即退出的方式,也就是所谓的failfast,但在Kubernetes中,这种策略不再适用。这是因为Kubernetes中多数运维操作都是自动操作,无需人工介入。例如,部署应用时,无需自己选择节点,再到节点上启动应用;应用fail时,也无需手动重启,Kubernetes会自动重启应用;负载增高时,还可以通过HPA自动扩容。

启动时依赖不满足的场景下,可以假设有两个应用A和B,A依赖B且运行在同一个节点上,此节点因为某些原因重启,重启后,A首先启动,B还没启动,对于A来说就是依赖不满足。如果A还是按照传统的方式直接退出,当B启动之后,A也不会再启动,必须人工介入处理。

在Kubernetes集群中,推荐您启动时检查依赖,如果不满足,则进行轮询等待,而不是直接退出。可以通过 Init Container完成这个功能。

配置restart policy

Pod运行过程中进程退出十分常见。代码中存在Bug、占用内存太多等,都会导致应用进程退出,继而导致Pod退出。您可在Pod上配置restartPolicy,实现Pod退出后自动启动。

apiVersion: v1
kind: Pod
metadata:
  name: tomcat
spec:
  containers:
  - name: tomcat
    image: tomcat
    restartPolicy: OnFailure 

restartPolicy有三个可选值:

  • Always: 总是自动重启。

  • OnFailure:异常退出时自动重启 (进程退出状态非0)。

  • Never:从不重启。

配置Liveness Probe和Readiness Probe

Pod处于Running状态和Pod能正常提供服务是完全不同的概念。一个Running状态的Pod,里面的进程可能发生了死锁而无法提供服务。但是因为Pod还是Running的,Kubernetes也不会自动重启这个Pod。所以我们要在所有Pod上配置Liveness Probe,探测Pod是否真的存活,是否还能提供服务。如果Liveness Probe发现了问题,Kubernetes会重启Pod。

Readiness Probe用于探测Pod是否可以对外提供服务。应用启动过程中需要一些时间完成初始化,在这个过程中是无法对外提供服务的,通过Readiness Probe,可以告诉Ingress或者Service是否可以将流量转发到这个Pod上。当Pod出现问题的时,Readiness Probe可以避免新流量继续转发到这个Pod。

apiVersion: v1
kind: Pod
metadata:
  name: tomcat
spec:
  containers:
  - name: tomcat
    image: tomcat
    livenessProbe:
      httpGet:
        path: /index.jsp
        port: 8080
      initialDelaySeconds: 3
      periodSeconds: 3
    readinessProbe:
      httpGet:
        path: /index.jsp
        port: 8080

每个进程一个容器

很多刚刚接触容器的人喜欢按照旧习惯把容器当作虚拟机(VM)使用,在一个容器里放多个进程:监控进程、日志进程、sshd进程,甚至整个Systemd。这样操作存在两个问题:

  • 判断Pod整体的资源占用会变复杂,不方便实施前面提到resource limit。

  • 容器内只有一个进程的情况下,如果进程挂了,外部的容器引擎可以清楚地感知到,并且重启容器。如果容器内有多个进程,某个进程挂了,容器未必受影响,外部的容器引擎无法感知到容器内有进程退出,也不会对容器做任何操作,但是实际上容器已经不能正常工作了。

如果有几个进程需要协同工作,在Kubernetes里也可以实现,例如:nginx和php-fpm,通过Unix domain socket通信,我们可以用一个包含两个容器的Pod,unix socket放在两个容器的共享volume中。

确保不存在SPOF(Single Point of Failure)

如果应用只有一个实例,当实例失败的时候,虽然Kubernetes能够重启实例,但是中间不可避免地存在一段时间的不可用。甚至更新应用,发布一个新版本的时候,也会出现这种情况。在Kubernetes里,尽量避免直接使用Pod,尽可能使用Deployment/StatefulSet,并且让应用的Pod在两个以上。

组件推荐配置

您可以在创建集群的过程中选择配置特定组件,也可以为已创建集群启用特定组件,拓展集群功能。您可以参见步骤四:配置组件,并根据文档内容跳转至具体的功能文档,也可以参见组件介绍与发布记录,按照功能维度查看组件介绍与发布记录。

日常运维

  • 日志

    创建集群时,请勾选日志服务

  • 监控

    阿里云容器服务与云监控进行集成,通过配置节点监控,提供实时的监控服务。通过添加监控告警规则,节点上的资源使用量很高的时候,可快速定位问题。

    通过容器服务创建Kubernetes集群时,如您勾选使用云监控插件,系统会自动在云监控创建容器监控分组。您可以在该分组下添加报警规则,对组内所有的机器生效。后续加入的节点,也会自动归属于该组,无需额外配置报警规则。更多信息,请参见Kubernetes容器监控

    例如,您可以配置ECS资源的报警规则,对ECS服务器进行监控,日常运维请设置cpumemory磁盘等的报警规则。且推荐将/var/lib/docker放在一个独立的盘上。

合理部署Nginx Ingress Controller

在部署Nginx Ingress Controller时,请确保Nginx Ingress Controller分布在不同的节点上,避免不同Nginx Ingress Controller之间资源的抢占和单点故障。您也可以为其使用独占节点来保证性能与稳定性,具体操作,请参见使用独占节点保证Nginx Ingress性能与稳定性

建议您不要为Nginx Ingress Controller设定资源限制,避免OOM所带来的流量中断。如果确实有限制的需要,建议资源限制CPU不低于1000 Milicore(YAML配置里格式为1000m)和内存不低于2 GiB。关于Nginx Ingress Controller的更多配置建议,请参见Nginx Ingress Controller使用建议

合理部署CoreDNS

建议您在部署CoreDNS副本时,将CoreDNS副本分散在不同可用区、不同集群节点上,避免单节点、单可用区故障。CoreDNS默认配置了按节点的弱反亲和性,可能会因为节点资源不足导致部分或全部副本部署在同一节点上,如果遇到这种情况,请删除Pod重新触发其调度来进行调整。

CoreDNS所运行的集群节点应避免CPU、内存用满的情况,否则会影响域名解析的QPS和响应延迟。关于CoreDNS的更多配置建议,请参见DNS最佳实践