更新时间:2024-10-14 GMT+08:00

CCE集群高可用推荐配置

为了保证应用可以稳定可靠的运行在Kubernetes里,本文介绍构建Kubernetes集群时的推荐配置。

类型

说明

高可靠配置建议

集群控制面

CCE是一项托管式的Kubernetes服务,集群控制面(即控制节点)无需由用户进行运维,您可以通过一些集群配置来提高集群整体的稳定性和可靠性。

集群数据面

在Kubernetes集群中,数据面由工作节点组成,这些节点可以运行应用程序容器并处理网络流量。在使用CCE过程中,数据面的节点需要您自行运维。为实现高可靠目标,您需要保证数据面的可扩展性及可修复性,并及时关注关键组件的运行状态。

应用层面

如果您希望应用程序始终可用,尤其是在流量高峰期间确保您的应用程序和服务不间断地运行,您需要通过可扩展且有弹性的方式运行应用,并及时关注应用的运行状态。

集群Master节点多可用区

支持多区域(Region),每个区域下又有不同的可用区(AZ,Availability Zone)。可用区是一个或多个物理数据中心的集合,有独立的风火水电。一个Region中的多个AZ间通过高速光纤相连,以满足用户跨AZ构建高可用性系统的需求。

创建集群时,您可以设置集群的高可用模式,并选择控制节点的分布方式。控制节点默认尽可能随机分布在不同可用区以提高容灾能力 。

您还可以展开高级配置自定义控制节点分布方式,支持如下2种方式。
  • 随机分配:通过把控制节点随机创建在不同的可用区中实现容灾。
  • 自定义:自定义选择每台控制节点的位置。
    • 主机:通过把控制节点创建在相同可用区下的不同主机中实现容灾。
    • 自定义:用户自行决定每台控制节点所在的位置。

集群网络选择

  • 集群网络模型选择:VPC网络、容器隧道网络模型。不同的网络模型存在性能和功能各方面的差异,请合理选择,详情请参见集群网络模型
  • VPC选择:如果您的应用需要连接其他云服务如RDS数据库等,则需要考虑将相关服务创建在同一个VPC中,因为VPC间网络是相互隔离的。如果您已经创建好实例,也可以将VPC之间通过对等连接进行互通。
  • 容器网段选择:容器网络的网段不能设置太小,如果太小会导致可创建的节点数量受限。
    • 对于VPC网络模型的集群来说,如果容器网络的网段掩码是/16,那么就有256*256个地址,如果每个节点预留的Pod数量上限是128,则最多可以支持512个节点。
    • 对于容器隧道网络模型的集群来说,如果容器网络的网段掩码是/16,那么就有256*256个地址,节点从容器网段中一次分配的IP网段默认为16,则最多可创建节点数量为65536/16=4096。
  • 服务网段选择:服务网段决定集群中Service资源的上限,调整该网段需要根据实际需求进行评估,创建后不可修改,请勿设置过小的服务网段。

关于集群网络地址段的选择详情,可参见集群网络地址段规划实践

服务转发模式

kube-proxy是Kubernetes集群的关键组件,负责Service和其后端容器Pod之间进行负载均衡转发。在使用集群时,您需要考虑服务转发模式潜在的性能问题。

CCE当前支持iptablesIPVS两种服务转发模式,各有优缺点。

  • IPVS:吞吐更高,速度更快的转发模式。适用于集群规模较大或Service数量较多的场景。
  • iptables:社区传统的kube-proxy模式。适用于Service数量较少或客户端会出现大量并发短连接的场景。当集群中超过1000个Service时,可能会出现网络延迟的情况。

关注配额限制

CCE支持设置配额限制,您设置云服务级别和集群级别的资源数量上限,以防止您过度意外使用资源。在构建创建应用时,应考虑这些限制值并定期审视,防止在应用运行过程中出现配额不足的瓶颈导致扩缩容失败。

  • 云服务配额:使用CCE时也会使用其他云服务,包括弹性云服务器、云硬盘、虚拟私有云、弹性负载均衡、容器镜像服务等。如果当前资源配额限制无法满足使用需要,您可以提交工单申请扩大配额。
  • 集群配额:集群中支持设置命名空间的配额,可限制命名空间下创建某一类型对象的数量以及对象消耗计算资源(CPU、内存)的总量,详情请参见设置资源配额及限制

监控Master指标

监控控制节点(Master节点)的指标可以帮助您深入了解控制节点性能并识别问题,运行状况不佳的控制节点可能会损害应用的可靠性。

CCE支持对Master节点的kube-apiserver、kube-controller、kube-scheduler、etcd-server组件进行监控,您需要在集群中安装kube-prometheus-stack插件。通过插件自带的grafana组件,您可以使用Kubernetes监控概述仪表盘来可视化和监控 Kubernetes API服务器请求以及延迟和etcd延迟指标。

在集群中自建Prometheus的场景,您可以手动添加指标,详情请参见Master节点组件指标监控

节点数据盘分区及大小

节点第一块数据盘默认供容器运行时及kubelet组件使用,其剩余的容量大小会影响镜像下载和容器启动及运行,数据盘的分配详情请参见数据盘空间分配说明

该数据盘默认大小为100G,您也可以根据需求调整该数据盘大小。由于镜像、系统日志、应用日志都保存在数据盘上,您需要考虑每个节点上要部署的Pod数量,每个Pod的日志大小、镜像大小、临时数据,再加上一些系统预留的值,详情请参考选择合适的节点数据盘大小

运行npd

工作节点中的故障可能会影响应用程序的可用性。npd插件是一款监控集群节点异常事件的插件,帮助您及时感知节点上可能存在的异常并及时处理。您也可以对npd插件的故障检查项进行自定义配置,包括检查的目标节点、检查周期、触发阈值等,详情请参见节点故障检测策略

配置DNS缓存

当集群中的DNS请求量增加时,CoreDNS将会承受更大的压力,可能会导致如下影响:

  • 延迟增加:CoreDNS需要处理更多的请求,可能会导致DNS查询变慢,从而影响业务性能。
  • 资源占用率增加:为保证DNS性能,CoreDNS往往需要更高规格的配置。

为了避免DNS延迟的影响,可以在集群中部署NodeLocal DNSCache来提升服务发现的稳定性和性能。NodeLocal DNSCache会在集群节点上运行DNS缓存代理,所有注入DNS配置的Pod都会使用节点上运行的DNS缓存代理进行域名解析,而不是使用CoreDNS服务,以此来减少CoreDNS服务的压力,提高集群DNS性能。

您可以安装node-local-dns插件部署NodeLocal DNSCache,详情请参见使用NodeLocal DNSCache提升DNS性能

合理部署CoreDNS

建议您在部署CoreDNS时,将CoreDNS实例分布在不同可用区、不同节点上,尽可能避免单节点、单可用区故障。

且CoreDNS所运行的节点应避免CPU、内存打满,否则会影响域名解析的QPS和响应延迟。

运行多个实例

如果你的整个应用程序在独立的Pod中运行,那么如果该Pod出现异常,应用程序将不可用。请使用Deployment或其他类型的副本集来部署应用,每当Pod失败或被终止,控制器会自动重新启动一个与之相同的新Pod,以确保指定数量的Pod始终运行。

同时,在创建工作负载时,您可以指定实例数量大于2。如果一个实例发生故障,剩余的实例仍将运行,直到Kubernetes自动创建另一个Pod来弥补损失。此外,您还可以使用使用HPA+CA实现工作负载和节点联动弹性伸缩根据工作负载需求自动进行伸缩。

使用容器隔离进程

容器可以提供进程级别的隔离,每个容器都有自己的文件系统、网络和资源分配,可以避免不同进程之间相互干扰,也可以避免恶意进程的攻击和数据泄露。使用容器隔离进程可以提高应用程序的可靠性、安全性和可移植性。

如果有几个进程需要协同工作,可以在一个Pod创建多个容器,以便它们可以共享相同的网络、存储卷和其他资源。例如init容器,init容器会在主容器启动之前运行,可以用于完成一些初始化任务,比如配置环境变量、加载数据库或数据存储以及拉取Git库等操作。

但需要注意的是,一个Pod中存在多个容器时会共享同一个Pod的生命周期。因此如果其中一个容器异常,整个Pod将被重新启动。

设置资源配额

为所有工作负载配置和调整资源请求/限制

当在一个节点上调度了太多的Pod时,会导致节点负载太高,无法正常对外提供服务。

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

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

另外所有Pod上都要声明resources。对于没有声明resources的Pod,它被调度到某个节点后,Kubernetes也不会在对应节点上扣掉这个Pod使用的资源。可能会导致节点上调度过去太多的Pod。

应用多可用区部署

您可以通过在多个可用区的节点上运行Pod,以避免应用受单个可用区故障的影响。

在创建节点时,您可以手动指定节点的可用区。

在部署应用时,您可以为Pod设置反亲和性规则,实现跨多个可用区调度Pod,详情请参见在CCE中实现应用高可用部署。示例如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
  labels:
    app: web-server
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web-server
  template:
    metadata:
      labels:
        app: web-server
    spec:
      containers:
      - name: web-app
        image: nginx
      imagePullSecrets: 
      - name: default-secret
      affinity:
        podAntiAffinity:  # 工作负载反亲和
          preferredDuringSchedulingIgnoredDuringExecution:  # 表示尽量满足规则,否则Pod数超过可用区数量时会无法调度
          - podAffinityTerm:
              labelSelector:  # Pod标签匹配规则,设置Pod与自身标签反亲和
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - web-server
              topologyKey: topology.kubernetes.io/zone  # 节点可用区拓扑域
            weight: 100

您也可以使用Pod的拓扑分布约束实现多可用区部署。

系统插件多可用区部署

与应用多可用区部署类似,CCE系统核心插件(如CoreDNS、Everest等)的无状态应用(Deployment)实例支持多种多可用区部署模式,满足不同场景下的用户诉求。

表1 插件多可用区部署说明

部署模式

配置说明

使用说明

推荐配置场景

优先模式

插件实例配置Pod间弱反亲和策略,拓扑域为可用区级别(topology.kubernetes.io/zone),反亲和类型为preferredDuringSchedulingIgnoredDuringExecution。

尽量将插件实例调度到不同可用区,但当部分可用区资源不足时,插件实例有可能调度到其他资源充足的可用区,不能完全保证实例分布在多个不同可用区。

对多可用区容灾没有强制要求,可使用默认的优先模式。

强制模式

插件实例配置Pod间强反亲和策略,拓扑域为可用区级别(topology.kubernetes.io/zone),反亲和类型为requiredDuringSchedulingIgnoredDuringExecution。

限制每个可用区最多部署一个同一组件实例,实际能够运行的实例数无法超过当前集群下节点的可用区数量,同时由于限制单个可用区最多一个实例,实例所在节点的故障后,故障实例无法自动迁移到同可用区下的其他节点。

强制模式一般用于可用区数量后续有变动场景,避免所有实例都提前调度到当前的可用区节点上。

均分模式

插件实例配置Pod拓扑分布约束,拓扑域为可用区级别(topology.kubernetes.io/zone),强限制不同拓扑域间的实例差不超过1,以达到插件实例在不同可用区间实现均衡分布效果。

该模式的效果介于优先模式和强制模式之间,既能达到实例在不同可用区部署要求,同时也支持实例数大于可用区场景,实现单可用区部署多实例。使用均分模式时需提前规划好各可用区节点资源,保证各可用区有足够的节点资源供实例部署(当单可用区的插件实例大于1时,建议各可用区可供插件实例可调度的节点数超过该可用区下实际插件实例数量1个以上),避免部分可用区节点资源不足阻塞插件实例的部署及更新过程中的整体调度。

均分模式在容灾要求较高场景推荐使用。

设置容器健康检查

Kubernetes对处于异常运行状态的Pod存在自动重启机制,可以避免一些Pod异常导致的服务中断问题,但是有的时候,即使Pod处于正常Running状态也不代表这个Pod能正常提供服务。例如,Pod里面的进程可能发生了死锁,但Pod的状态依然是Running,所以Kubernetes也不会自动重启这个Pod。因此,可以Pod上配置存活探针(Liveness Probe),探测Pod是否真的存活。如果存活探针发现了问题,Kubernetes会重启Pod。

同时,您也可以配置就绪探针(Readiness Probe),用于探测Pod是不是可以正常对外提供服务。应用在启动过程中可能会需要一些时间完成初始化,在这个过程中是没法对外提供服务的,为Pod添加过就绪探针后,当检测到Pod就绪时才会允许Service将请求转给Pod。当Pod出现问题的时候,就绪探针可以避免新流量继续转发到这个Pod。

启动探针(Startup Probe)用于探测应用程序容器启动是否成功。配置了启动探针后可以控制容器在启动成功后再进行存活性和就绪检查, 确保这些存活、就绪探针不会影响应用程序的启动。 这可以用于对启动慢的容器进行存活性检测,避免它们在启动运行之前就被终止。

您可以在创建应用时配置上述探针,YAML示例如下:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: nginx:alpine
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 80
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3
      periodSeconds: 3
    readinessProbe:
      exec:
        command:
          - cat
          - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5
    startupProbe:
      httpGet:
        path: /healthz
        port: 80
      failureThreshold: 30
      periodSeconds: 10

更多详情请参见设置容器健康检查

自动弹性伸缩

弹性伸缩功能可以根据需求自动调整应用程序的实例数和节点数,可以在流量高峰期间快速扩容,并在业务低谷时进行缩容以节约资源与成本。

一般情况下,在流量高峰期间可能会出现两种类别的弹性伸缩:

  • 工作负载伸缩:当使用Pod/容器部署应用时,通常会设置容器的申请/限制值来确定可使用的资源上限,以避免在流量高峰期无限制地占用节点资源。然而,这种方法可能会存在资源瓶颈,达到资源使用上限后可能会导致应用出现异常。为了解决这个问题,可以通过伸缩Pod的数量来分摊每个应用实例的压力。
  • 节点伸缩:在增加Pod数量后,节点资源使用率可能会上升到一定程度,导致继续扩容出来的Pod无法调度。为解决这个问题,可以根据节点资源使用率伸缩节点数量,扩容Pod可以使用的资源。

关于实现自动弹性伸缩的详情请参见使用HPA+CA实现工作负载和节点联动弹性伸缩

日志监控告警

  • 日志
    • 应用日志:应用日志是由集群内运行的Pod生成的日志,包括运行业务应用和Kubernetes系统组件(如CoreDNS)的Pod生成的日志。CCE支持配置应用日志策略,便于日志的统一收集、管理和分析,以及按周期防爆处理。
  • 监控
    • 控制面指标:控制面指标监控有助于识别控制节点的问题风险,详情请参见监控Master指标
    • 应用指标:CCE支持对集群中的应用程序进行全方位的监控。除了监控Kubernetes标准指标外,您还可以在应用程序中上报符合规范的自定义指标,以提高应用程序的可观测性。