kubernetes生产化集群管理

生产化集群管理

计算节点相关

生产化集群的考量

计算节点
  • 如何批量安装和升级计算节点的操作系统

  • 如何管理和配置计算节点的网络信息

  • 如何管理不同的SKU的计算节点

  • 如何快速下架故障的计算节点

  • 如何快速扩缩集群的规模

控制平面
  • 如何从主节点上下载,安装和升级控制平面组件和所需的组件

  • 如何确保集群所需要的其他组件

  • 如何准备控制平面组件的各种安全证书

  • 如何快速升级固件或是回滚组件的的版本

操作系统的选择

  • 通用操作系统

    • ubuntu

    • centOS

    • fedora

  • 专为容器优化的操作系统

    • coreOS

    • redHat Aotmic

    • Snappy ubuntu core

    • rancherOS

操作系统的评估和选择

  • 是否有成熟的生态系统

  • 内核版本

  • 对运行时的支持

  • init system

  • 包管理和系统升级

  • 安全

云原生的原则

  • 可变基础设施风险

    • 在灾难发生的时候,难以重新构建服务,持续过的手工操作,没有记录

    • 在服务运行过程中,持续修改服务器,持续引入变量,导致不可预知的风险

  • 不可变基础设施

    • 不可变的容器镜像

    • 不可变的主机操作系统

atomic
  • 由redHat支持的软件包系统

  • 多种distro

    • redora

    • centOS

    • RHEL

  • 优势

    • 不可变操作系统,面向容器化的基础设施

      • 灵活性和安全性较好

      • 只有/etc/ /var/可以修改,其他目录均为只读

    • 基于rpm-ostree管理系统包

      • Rpm-ostree是一个开源项目,使得生产系统中构建镜像非常简单

      • 支持操作系统升级和回滚的原子操作

最小华操作系统

原则

  • 最小化主机操作系统

  • 只安装必要的工具

    • 必要:支持系统运行的最小工具集

    • 任何调试工具,比如性能排查,网络排查工具,均可以后期以容器的形式运行

  • 意义

    • 性能

    • 稳定性

    • 安全保证

Ostree

提供一个共享库和一些列命令行,提供和git命令行一致的体验,可以提交或是下载一个完整的可启动的文件系统树,提供将ostree部署到bootloader的机制

  • 构建ostree

    • Rpm-ostree

      基于treefile将rpm包构建成ostree管理ostree和bootloader配置

    • treefile

      • Refer: 分支名(版本,CPU架构)

      • Repo: rmp package repositories

      • Packages: 待安装的组件

  • 加载ostree

    • 初始化项目

    • 导入ostree repo

    • 拉取ostree

    • 部署os

操作系统加载
  • 物理机

    • 通过foreman启动,foreman通过pxe boot,并加载kickstart

    • Kickstart 通过ostree deploy完成操作系统的部署

  • 虚拟机

    • 通过镜像工具将ostree构建成 qcow2格式,vhd,raw等格式

节点资源管理

  • 状态汇报

  • 资源预留

  • 防止节点资源耗尽的防御机制

  • 容器和系统资源的配置

状态上报

kubelet周期调度周期性向API Server进行汇报,更新节点的相关信息

  • 节点基础信息,包括IP地址,操作系统,内核,kubelet kube-proxy版本信息

  • 节点资源信息包括CPU,内存,HugePage,临时存储,GPU注册信息,以及这些资源中可以分配给容器使用的部分

  • 调度器在Pod选节点的时候会将这些信息作为参考依据

图片.png
lease

通过lease对象来保存健康信息,在默认的40s的nodeLeaseDurationSeconds周期呢,如果lease对象没有被更新,则对应的节点被判定为不健康

资源预留

计算节点除了用户容器外,还有很多支撑系统运行的基础服务,为了保证服务进程可以正常运行,在确保他们任务任何时候都可以获取足够的资源,需要对这些进程预留资源

kubele可以通过众多启动参数为系统服务预留出CPU,内存,PID等资源,比如:SystemReserved,KubeReserved等

Capacity 和Allocatable

  • Capacity:是说kubelet获取的计算节点当前的资源信息

    • Cpu: /proc/cpuinfo

    • Memory: /proc/memoryinfo

    • Ephemeral-storage:是说节点根分区的大小

  • Allocatable:用户Pod可用的资源,是资源容量减去分配给系统的资源剩余价值部分

节点磁盘管理

  • 系统分区:nodes

    • 工作目录和容器日志
  • 容器运行时分区:imagefs

    • 用户镜像和容器可写层

    • 容器运行时分区是可选的,可以合并到系统分区中。

驱逐管理

  • kubelet会在系统资源不够的时候中止一些容器进程,以空出系统资源,保证节点的稳定性

  • kubelet发起的驱逐只是停止pod的所有容器进程,并不会直接删除pod

    • pod的status.phase会被标记为Failed

    • Status.reason:会被标记为evicted

    • Status:message会被记录为被标记为驱逐的原因

资源可用额的监控

  • Kubelet 依赖内嵌的开源软件cAdvisor,周期性检查节点资源的使用情况

  • CPU是可压缩资源,根据不同的进程分配时间配额和权重,CPU可以被多个进程竞争相使用

  • 驱逐策略是基于磁盘和内存的资源使用量进行的,因为两者属不可压缩的资源,当此类资源使用耗尽的时候将无法在使用

检查类型 说明
Memory.available 节点当前的可用内存说明
Nodefs.available 节点根分区的可用磁盘大小
nodefs.inodesFree 节点根分区的可使用的inode
Images.inodesFree 节点运行时分区的可使用inode
Images.available 节点运行时饿分区的可使用大小,如果节点没有运行时分区,就没有想过监控

驱逐策略

Kubelet获得节点的可用额信息后,会结合节点的容量信息来判断当前节点运行的Pod是否满足驱逐条件。

驱逐条件可以是绝对值或是百分比,当监控资源的可使用额度少于设定的百分比的时候,kubelet就会发起驱逐操作

kubelet参数evictionMinimumReclaim可以设置每次回收的资源的最小值,以防止小资源多次被回收

kubelet参数 分类 驱逐方式
evictionSoft 软驱逐 当检测到当前资源达到软驱逐的阈值的时候,并不会立刻启动驱逐哦操作,而是要等待一个宽限期,这个宽限期选取evictionSoftGracePeriod和Pod指定的TerminationGracePeriodSeconds中较小的值
evictionHard 硬驱逐 没有宽限期,一旦检测到满足硬件驱逐的条件,就直接终止容器来释放紧张的资源

基于内存压力的驱逐

  • Memory.avaiable表示当前系统的内存可用情况

  • kubelet默认了设置了memory.avaiable < 100Mi的硬件驱逐条件

  • 当kubelet检测到当前节点可用内存资源紧张并满足驱逐条件的时候,会将节点的MemoryPressure的状态设置为True,调度器会阻止BestEffort Pod调度到内存承压的节点上

  • Kubelet启动对内存不足的驱逐操作的时候,会依照如下顺序选取目标pod

    • 判断Pod所有容器的内存使用量总和是否超过请求的内存量,超出请求资源的Pod会成为备选目标

    • 查询pod的调度优先级,低优先级的Pod会被优先驱逐

    • 计算Pod所有容器的内存使用量和pod请求的内存量的差值,差值越小,越不容易被驱逐。

基于磁盘压力的驱逐

以下任何一项满足驱逐条件时,它会将节点的DiskPressure的状态设置为true,调度器不会在调度任何Pod到节点上

  • Nodefs.available:可用空间

  • Nodes.inodesFree : inode可用空间

  • imagefs.available

  • imagefs.inodesFree

驱逐行为

  • 有容器运行时分区

    • Nodefs 达到驱逐阈值,那么kubelet删除已经退出的容器

    • Imagesfs达到驱逐阈值,那么kubelet删除所有未使用的镜像

  • 无容器运行时分区

    • kubelet同时删除未运行的容器和未使用镜像。
  • 回收已经退出的容器以及未使用的容器后,如果节点依然满足驱逐条件,kubelet就会开始驱逐正在运行的Pod,进一步释放磁盘空间

    • 判断pod的磁盘使用量是否超过了请求的大小,超过请求资源的pod会成为备选目标

    • 查询pod的调度优先级,低优先级的pody优先被驱逐

    • 根据磁盘使用超过请求的数量进行排序,差值越小,越不容易被驱逐。

容器资源配置

针对不同的Qos class的pod,kubenetes按照如下Hierarchy组织cgroup的cpu子系统

  • /sys/fs/cgroup/cpu

    • Kubepods.slice

      • Kubepods-besteffort.slice

        • Kubepods-pod.slice

          • docker.scope

          • docker.scope

      • Kubepods-burstable.slice

        • Kubepods-pod.slice

          • docker.scope

          • docker.scope

      • Kubepods-pod.slice

        • docker.scope

        • docker.scope

Cpu 的cgroup的配置

Cgroup 参数 Qos类型
容器cgroup Cpu.shares bestEffort 2
Burstable Requests.cpu *1024
Guaranteed Requests.cpu *1024
Cpu.cfs_quota_us bestEffort -1
Burstable Limit.cpu*100
Guaranteed Limit.cpu*100
pod的Group Cpu.shares bestEffort 2
Burstable pod中容器的合集
Guaranteed pod中容器的合集
Cpu.cfs.quota_us bestEffort -1
Burstable pod中容器的合集
Guaranteed pod中容器的合集

针对不同的Qos class的pod,kubenetes按照如下Hierarchy组织cgroup的memory子系统

  • /sys/fs/cgroup/memory

    • Kubepods.slice

      • Kubepods-besteffort.slice

        • Kubepods-pod.slice

          • docker.scope

          • docker.scope

      • Kubepods-burstable.slice

        • Kubepods-pod.slice

          • docker.scope

          • docker.scope

      • Kubepods-pod.slice

        • docker.scope

        • docker.scope

类型 参数 Qos类型
容器的group Memory.limit_in_bytes bestEffort 9223372036854771712
Burstable Limits.memory
Guaranteed Limits.memory
pod的cgroup Memory.limit_in_bytes bestEffort 9223372036854771712
Burstable pod中容器的合集
Guaranteed pod中容器的合集

日志管理

节点上需要通过运行logrotate的定时任务对系统服务日志进行rotate清理,以防止系统日志占用大量磁盘空间。

  • 同时配置日志的rotate条件,在日志不占用太多空间的情况下,保证有足够的日志可供查看

  • docker

    • 除了基于系统logrotate管理日志,还可以依赖Docker自带的日志管理功能来设置日志的数量和每个日志的大小

    • Docker写入数据之前会对日志大小进行检查和rotate操作,确保日志文件不会超过配置的数量和大小

  • Containerd

    • 日志的管理的通过kubelet定期执行du命令,来检查容器的日志数量和文件大小

    • 每个容器日志的大小和保留的文件个数,可以通过kubelet的配置参数container-log-max-szie 和container-log-max-files进行调整。

Docker卷管理

  • 在构建容器镜像的时候,可以在dockerFile中通过volume指令申明一个存储卷,目前kubernetes尚未将其纳入管控范围内,不建议使用

  • 如果容器进程在可写层或是emptyDir卷进行大量读写操作,会推高磁盘i/o,从而导致其他其他容器有问题

  • Docker和Containerd运行时都基于CGROUPV1,对于块设备,只支持Direct I/O 的限速 而对于Buffer I/O 还不具备有效的支持,因此,针对设备限速问题,目前没有比较好的方案,对于有特殊 I/O需求的容器,建议使用独立的磁盘空间。

网络资源

由网络插件通过linux Traffic Control为Pod限制带宽,可以利用CNI社区提供的bandwith插件

进程数

kubelet默认不限制pode可以创建的子进程数,但是可以通过启动参数的podPidsLimit开启限制,还可以由reserved参数为系统进程预留进程数。

  • Kubelet通过系统调用的周期性的获得当前系统的PID使用情况,并读取/proc/sys/kernel/pid_max 获取系统支持pid的上限。

  • 如果当前的可用进程数少于设定的阈值,那么kubelet会将节点对象的PIDPressure标记为true

  • Kube-scheduler在进行调度的时候,会从备选节点中对处于NodeUnderPIDPressure状态的节点进行过滤。

节点异常检测

kubernetes集群可能存在以下的问题

  • 基础架构守护进程的问题:NTP服务关闭等

  • 硬件问题:CPU,磁盘损坏

  • 内核问题:内核死锁,文件系统损坏

  • 容器运行时问题:运行时无响应

Node-problem-detector

为了解决节点检测的问题,社区引入了守护进程node-problem-detector,从各个守护进程收集节点问题,并使它们对上游层可见。

kubernetes节点诊断的工具,可以将节点的异常进行上报

  • runtime无反应

  • Linux kernel 无反应

  • 网络异常

  • 文件描述符异常

  • 硬件问题比如CPU,内存,磁盘问题

Problem daemon types nodeCondition Description Configs
系统日志监控 KernelDeadLock,ReadOnlyFileSystem FrequentKubeletRestart FrequentDockerRestart FrequentContainerRestart 通过系统监控日志来汇报问题并输出系统指标 Filelog,kmsg, kernel abre systemd
customPluginsMonitor 按需定义 自定义插件监控运行用户自定义监控脚本 比如NTP服务
healthCheck KubeletUnhealthy ContainerRuntimeUnhealthy 针对kubelet和运行时的健康检查 kubelet docker
问题汇报手段

Node-proble-detector通过nodeCondition或者创建event对象来汇报问题

  • nodeCondition:针对永久性故障,会通过nodeCondition来改变节点状态

  • Event:临时故障通过event来提醒相关对象

安装过程
  • 代码: https://github.com/kubernetes/node-problem-detector

  • 安装:

    • Helm repo add deliveryhero https://charts.deliveryhero.io/

    • Helm install delivery hero/node-proble-detetor

常用节点问题排查手段

查看日志

针对使用systemd拉起服务

  • Journalctl aft kubelet -S "2019-08-26 15:00:00" -u unit. // 对应的systemd拉起的组件,比如kubelet -f follow //跟踪最新的日志 -a show all // 显示所有的日志列 -S since // 从某一个时刻的日志

对于标准的容器日志

  • kubectl logs -f -c

  • kubectl logs -f --all-containers

  • kubectl logs -f -c --previous

  • Kubectl exec -it xxx --tail -f /path/to/log

基于extended resources 扩展节点资源

扩展资源时kubernetes.io域名之外的标准资源名称,它们使得集群管理员能够颁布非kubernetes内置资源,而用户可以使用他们

自定义扩展资源无法使用kubernetes.io作为资源域名。

管理扩展资源

  • 节点级扩展资源

    • 节点级扩展资源绑定到节点
  • 设备插管管理的资源

    • 发布到各节点上由设备插件所管理的资源,比如GPU,智能网卡

为节点配置资源

  • 集群操作员可以向API服务器提交PATCH HTTP请求,以在集群中节点的status.capacity中为其配置可用数量

  • 完成此操作后,节点的status.capacity字段中将包含新的资源

  • kubelet会异步的对status.allocatable字段执行自动更新操作,使之包含新的资源。

  • 调度器在评估Pod是否在适合在某个节点上执行时会使用节点的status.allocatable值,在更新节点容量使之包含新资源之后和请求该资源的第一个pod被调度到该节点之间,可能会有段短暂的延迟

  • 使用扩展资源

构建和管理高可用集群

图片.png

高可用数据中心

  • 多地部署

  • 每个数据中心需要划分成具有独立供电,制冷,网络设备的高可用区

  • 每个高可用区管理独立的硬件资产,包括机架,计算节点,存储,负载均衡,防火墙等硬件设备

Node的生命周期管理

运营kubernetes集群,除了搭建外,还需要对所有节点的生命周期负责

  • 集群搭建

  • 集群扩容/缩容

  • Node生命周期

    • Onboard

      • 物理资产上架

      • 操作系统安装

      • 网络配置

      • kubernetes组件安装

      • 创建Node对象

    • 故障处理

      • 临时故障:重启

      • 永久故障:节点下架

    • Offboard

      • 删除Node对象

      • 物理资产下架

生产化集群管理

  • 如何设定单个集群的规模

    • 单一集群可支持达到5000节点
  • 如何根据地域划分集群

    • 不同地域的计算节点划分到同一个集群

    • 将同一地域节点划分到同一集群

  • 如何规划集群网络

    • 企业办公环境,测试环境,预发环境,生产环境如何进行网络分离

    • 不同租户之间如何进行网络隔离

  • 如何自动化搭建集群

    • 如何自动化搭建和升级集群,包括自动化部署控制面板和数据平面的核心组件

    • 如何同企业公关服务集成

企业公共服务

  • 需要同企业认证平台集成

  • 集成企业的域名服务,负载均衡,提供集群服务对外的发布和访问入口

  • 对于不能异步的请求,需要设置超时时间

  • 有些失败是短暂的,可以增加重试机制

控制平面高可用

  • 针对大规模的集群,应该为控制平面组件划分单独的节点,减少业务容器对控制平面或事守护进程的干扰和资源抢占

  • 控制平面的所在节点,应该确保是在不同的机架上,防止某些硬件问题,导致所有的节点不可用。

  • 保证控制平面每个组件有足够的CPU,内存和磁盘资源,过于严格的资源限制会导致系统效率低下

  • 应该尽可能的将控制平面和数据平面解耦,确保控制平台组件故障的时候,将业务影响降到最低

高可用集群

图片.png

集群安装方法

安装工具 方式 优势 缺点
二进制 下载二进制文件,并通过设置systemd来管理 灵活度高 需要关心每一个组件
Kubeadm kubeadm是一个搭建集群的命令行的工具 控制版面组件的安装和配置被封装起来,管理集群的生命后期,比如升级,证书管理 操作系统层面的配置无自动化运行时安装等复杂步骤的,CNI插件需要手动安装
Kubespray 通过sensible-playbook安装 自动完成操作系统层面的配置,利用了kubeadm作为集群管理工具 缺少声明式API的支持
KOPS 基于声明式API的集群管理工具 基于社区标准的clusterAPI进行集群管理,节点的操作系统安装等完全自动化 同云环境高度集成,灵活性差

kubespray 搭建高可用集群

图片.png

基于声明式API管理集群

集群管理部只是包括集群搭建,还需要支持以下功能

  • 集群扩缩容

  • 节点健康检查和自动修复

  • 操作系统升级

  • kubernetes升级

kubernetes cluster api
图片.png
参与角色
  • 管理集群

    • 管理workload集群的集群,用来存放Cluster API对象的地方
  • Workload集群

    • 真正开放给用户来运行应用的集群,由管理集群管理
  • Infrastructure provider

    • 提供不同的云的基础架构管理,包括计算节点,网络等,目前流行的公有云多同cluster API集成
  • Bootstrap provider

    • 证书生成

    • 控制板面组件安装和初始化,监控节点的创建

    • 将主节点和计算节点加入集群

  • Control plane

    • kubernetes控制平面组件
涉及模型
  • machine

    • 计算节点,用来描述可以运行的kubernetes组件的机器对象

    • 一个新的machine被创建后,对应的控制器会创建一个计算节点,安装好操作系统并更新machine状态

    • 当一个machine被删除后,对应的控制器会创建一个计算节点,安装好操作系统并更新machine的状态

    • 当一个machine属性更新以后,对应的控制器会删除旧节点并创建新的节点

  • machine immutability

    • 不可变基础架构
  • machineDeployment

    • 提供针对machine和machineSet声明式更新,类似于kubernetes deployment
  • machineSet

    • 维护一个稳定机器合集
  • machineHealthCheck

    • 定义节点应该被标记为不可用的状态

Cluster Autoscaler

工作机制

  • 扩容

    • 由于资源不足,pod调度失败
  • 缩容

    • node资源利用率较低,持续10分钟低于50%

    • 此node上存在的pod都能被重新调度到其他node上运行

cluster autoscaler 架构

图片.png

架构

  • Autoscaler: 核心模块,负责整体的扩缩容

  • Estimator: 负责评估计算扩容的节点

  • Simulator: 负责模拟调度,计算缩容节点

  • Cloud-provider:同云交互进行节点的增删改查,每个支持CA的主流厂商都实现自己的plugin实现动态缩放

扩展机制

为了自动创建和初始化Node,Cluster Autoscaler要求node必须属于某个node group

当集群中有多个node group时,可以通过 --expander=

  • Random: 随机选择

  • Most-pods:选择容量大的

  • Least-waste:以最小浪费原则,即选择有最少的可用资源的node group

多租户集群管理

租户

  • 租户是指一组拥有访问特定软件资源权限的用户合集,在多租户的环境中,它还包括共享的应用,服务,数据和各项配置

  • 多租户集群必须架构租户彼此隔离,以最大限度的减少租户和租户,租户和集群之间的影响

  • 集群需要在租户之间公平的分配集群资源,通过多租户共享集群资源,有效降低集群管理成本,提高集群资源利用率。

隔离

  • 权限隔离:

    • 普通用户的容器默认不具备priviledged sys_admin net_admin等高级管理权限,以阻止对宿主机以及其他用户的容器进行读取,写入操作
  • 网络隔离

    • 不同的pod,运行在不同的network namespace中,拥有独立的网络协议栈,pod之间只能通过容器开放的端口进行通信,不能通过其他方式进行访问
  • 数据隔离

    • 容器之间利用namespace进行隔离

隔离手段

  • Namespace:Namespace属于且仅属于一个租户

  • 权限定义:定义内容包括命令空间中的Role和RoleBinding。这些资源表示目前租户在归属于自己的民命空间中定义了什么权限,以及授权给了哪些用户

权限隔离

  • 基于namespace的权限隔离

    • 创建一个namespace-admin clusterRole,拥有所有对象的所有权限

    • 为用户开辟新的namespace,并在该namespace创建rolebingding绑定namespace-admin clusterRole,用户即可拥有当前的namespace所有的操作权限

  • 自动化解决方案

    • 当namespace创立的时候,通过mutatingwebhook的方式将namespace变形,将用户信息记录到namespace annotation中

    • 创建一个控制器 监控namespace创建rolebinding 为该用户绑定namespace-admin权限

节点资源隔离

通过为节点设置不同的taint来识别不同的租户的计算资源

你可能感兴趣的:(kubernetes生产化集群管理)