北京时间2019年3月26日,Kubernetes正式发布了今年的第一个大版本 1.14。本次发布包含了大量重要更新,以可扩展性、支持更多的工作负载、安全性为主题,共增强了30多个功能。

为了帮助百度智能云的容器用户更快理解1.14新版本的变化,以及了解社区技术的演进趋势,百度智能云容器团队对新版本的特性进行了深入研究,梳理出10个最值得关注的要点。

1全面增强Windows支持

这次最令人惊喜的莫过于Kubernetes宣布Windows节点正式生产可用。1.14版本支持向集群添加Windows工作节点、调度Windows容器。相信随着Windows应用生态的加入,将再次提升Kubernetes的平台能力。对混合应用技术栈有需求的企业,可同时实现在Kubernetes上编排Windows与Linux应用。

对Windows容器的支持得益于以下3个关键点:

1、Windows Server容器网络的进步,提供了创建CNI(容器网络接口)插件的基础设施。

2、Windows Server2019发布的增强功能提供了最佳的容器支持。

3、Windows KEP提供了一组清晰且一致的目标、期望和可交付的成果。

本次对Windows容器支持的关键特性包括:

1、支持加入Windows Server 2019作为工作节点调度容器。

2、支持Azure-CNI、OVN-Kubernetes以及Flannel等第三方容器网络插件。

3、改进了对Pod、服务类型、工作负载控制器和metric/quota的支持能力,使Windows容器尽可能匹配Linux容器现有能力。

不过仍旧需要关注以下限制:

  • 节点OS版本限制:Windows Server 2019/1809。
  • Docker版本限制:Docker EE-basic 18.09。
  • 提供两种容器实现方案:Hyper-V和Native容器,Native容器的安全隔离很有限,Hyper-V隔离方案仍然是alpha特性,需要持续完善。
  • 依赖GPU、GUI的应用支持未被生产环境验证。整体能力相对弱于Linux容器。
  • 目前支持5种不同的网络模式,性能和成熟度仍需验证。
  • Windows容器的基础镜像体积较大,用户在没有中国区CDN场景下下载镜像耗时久。
  • 目前Master组件不能部署在Windows系统中,因此集群必须包含Linux系统的Master节点。
  • 目前Windows容器并不支持Pod优雅删除。
  • 对单文件映射、特权容器、大页内存支持等能力尚未提供支持。

2本地持久化数据卷(Local PV)正式可用

本地持久化存储卷(Local PV)可以使本地存储设备成为Kubernetes的持久化存储卷。虽然之前的Kubernets版本已经提供了多种PV,但是本次存储相对于其余使用远程存储的PV,在时延和稳定性上具有明显的优势。

对于期望使用Local PV的用户,也有两个问题需要提前关注:

1、易用性:Local PV需要提前创建对应路径,PV当前需要手动创建。kubernets-sig下的 Provisioner虽然目前支持动态创建PV, 但存储卷依旧需要手动提供。

2、容错性:Local PV依赖本地存储,而本次存储通常无法有效应对磁盘故障,因此无法获得网络存储所提供的可用性保障。

3支持进程数量限制

进程资源(Process Resources)是Linux的基本资源。如果不在Pod中对进程数量限制,可能会在容器内任意fork进程过多,导致主机上的进程资源耗尽,引起主机上的守护进程(如: kubelet、docker、kube-proxy等)运行不稳定。

容器是通过cgroup实现进程、CPU、Memory、 I/O 等资源的使用限制。Docker从1.11版本之后,已经支持限制容器内进程数量,启动容器的时候,加入启动参数-pids-limit,即可以控制容器内最大的进程数量。

对进程数量的限制也一直是社区内的强烈需求。本次更新对Kubernetes进程数量限制包括两个方面:

  • Pod to Pod pid隔离。kueblet增加启动参数pod-max-pids,用于限制Pod内最大的进程数量。该feature在v1.14 版本中作为beta版发布。
  • Node to Pod pid 隔离。支持限制pid在Node Allocatable Level,可以为kube预留pid数量。该feature在v1.14 版本中作为Alpha版发布。

4设置Pod优先级&抢占机制

在中型和大型集群中,为了提高资源利用率,Kubernetes允许工作负载的总量超过集群可以提供的资源总量,这种情况被称为“过度承诺”。过度承诺在节点数量固定的集群中非常常见,在公有云中,客户可以选择过度运行其集群以节约成本。

Pod优先级可以帮助管理员在过度运行集群时,为各种类型的工作负载定义其重要程度,从而在集群资源不足时选择更加重要的工作负载优先运行。当然,影响Kubernetes对工作负载重要程度的判断不仅限于优先级,也包括QoS和其它特定于集群的度量标准的组合。

在过度运行的前提下,当重要的工作负载无法获得足够资源运行时,Kubernetes将会通过抢占机制为Pod腾出足够资源。抢占由调度程序执行,通过释放重要性低的Pod来实现。执行抢占的组件必须具有为待处理的Pod找到正确节点的逻辑,它还必须具有检查待抢占的“空间”是否允许调度待处理Pod的逻辑。这些要求组件具有谓词和优先级功能的知识。

让调度程序执行抢占有以下好处:

  • 避免复制另一个组件中的所有调度逻辑。
  • 降低Pod抢占和待处理Pod调度之间的竞争条件风险。 如果这两个都由调度程序执行,则调度程序可以串行执行它们(尽管当前不是原子的)。 如果由不同的组件执行抢占,则调度程序可能在其Pod被抢占的节点上调度不同的Pod(而不是抢占者)。
  • 如果有多个调度程序,竞争条件仍然存在。

5Pod readiness gates

Pod readiness gates为Kubernetes的Pod就绪状态检查提供了灵活的外部反馈扩展点。在Kubernetes中,通过就绪检查来判断Container、Pod、Endpoint的状态是否就绪。在之前的版本中,这些对象的就绪条件如下:

  • Container Readiness:Container ready = Container running并且readinessprobe检测成功。
  • Pod Readiness:Pod ready = All containers ready。
  • Endpoint Readiness: Endpoint ready = Pod ready。

在传统的做法中,只要容器主进程处于ready状态,并且readinessProbe检查成功,则container和Pod将会进入就绪状态。但是此时Pod依赖的相关服务(如网络策略、负载均衡器等)可能还未就绪。

通过1.14发布的readinessGates功能,可以通过接入Pod所依赖的外部指标来更好地确定Pod是否处于就绪状态,readinessGates通过将用户定义的额外的状态反馈注入到PodStatus,来为判断Pod的ready状态添加可扩展性。

其主要实现方式为在pod readines上添加附加属性readinessGates,使得Pod ready = All containers ready并且 readinessGates中的条件都检测为True。在pod spec上新增readinessGates属性,值为conditionType:string 列表,conditionType值指向pod status中的pod condition列表中的一项,依据该status来判定ready情况,若不存在则默认为false。

使用readinessGates的用户需要注意:

  • readinessGates只能在创建Pod时定义。
  • readinessGates一旦创建不可更新。
  • ConditionType必须符合自定义pod condition的命名约定。

6原生应用管理能力Kustomize

1.14 版本的kubectl添加了子命令kustomize,同时为apply/delete/get子命令添加了-k参数,实现了Kustomize工具提供的应用资源YAML管理功能。

Kustomize允许用户使用一个或多个声明了KUBERNETES API资源的YAML文件作为base,通过overlay的方式将patch应用于base YAML生成目标YAML。这种方式可以方便地将一套YAML文件在不同环境下或不同用户中进行复用,而不需要将YAML文件拷贝多份,再各自进行修改。该工具帮助用户使用fork/modify/rebase工作流来复用KUBERNETES资源YAML,而不需要使用模板语言或脚本等侵入式方案进行资源管理。

Kustomize接受一个包含原始KUBERNETES API资源YAML文件和kustomization.yaml文件的目录,根据kustomization.yaml文件内容得到目标KUBERNETES API资源的YAML格式输出。一个合法的kustomization.yaml中声明了作为base的YAML文件,以及需要应用在base YAML文件上的patch内容,并支持namePrefix、commonLabels等字段以支持对name和label的批量修改。

7默认rbac发现机制加固

1.14版本之前,system:discovery和system:basic-user的ClusterRoleBindings都会包含system:unauthenticated主体。为了提升CRD的隐私性和集群安全状况,默认RBAC不再授予未经身份验证的用户对发现和权限检查API的访问权限。同时保留对当前API的非敏感子集的未经身份验证的访问(例如 GET /healthz,GET /version)。

升级的集群会保留原先的行为,如果集群管理员希望在新集群中授予未经身份验证的用户访问权限,需要明确选择暴露发现、权限检查API。

  • kubectl createclusterrolebinding anonymous-discovery —clusterrole=system:discoverygroup=system:unauthenticated
  • kubectl create clusterrolebinding anonymous-access-review —clusterrole=system:basic-user —group=system:unauthenticated

8让Kubectl用户更友好

1.14版本对kubectl的使用进行了一些优化,使得kubectl的用户体验更加友好。

kubectl插件机制GA

  • kubectl插件机制允许使用独立的二进制文件来发布自定义的 kubectl 子命令。这可以用于扩展kubectl具有更高级别的功能,如:添加set-ns命令来快速切换命名空间。
  • 插件必须具有kubectl-的命名前缀,并保存在用户PATH中,为了GA,插件机制已经被大大简化了,目前有点类似Git的插件系统。
  • 修复kubectl plugin list存在的问题。

kubectl命令优化

  • kubectl logs命令可以组合使用-f 和-l命令,实现筛选+持续输出日志。
  • 增加kubectl auth can-i —list命令,允许用户查看在特定命名空间下可以执行哪些操作。
  • 用户可以使用kubectl delete {source} —all-namespaces来进行统一的资源删除操作。

kubectl将废弃的命令

  • kubectl的—show-all参数,之前是deprecated状态,这次更新中正式去掉。
  • kubectl的convert命令,变成deprecated状态,将在v1.17中被去掉。
  • kubectl get中的—export参数,变成deprecated状态,将在1.18中被去掉。

9优化稳定性

新版本提高了稳定性。此次1.14许多修复优化都是围绕稳定性展开,下面列举一些比较重要的提升点:

1、在极端情况下Pod会在controller给新增节点打上污点之前被scheduler调度在新增节点上,为避免此类情况出现,Kubernetes新增TaintNodesByCondition准入插件,该插件用于给新加入集群的节点打上”not ready”的污点。

2、当创建大量引用configmap或者secret的Pod时,集群的调度速度会变慢直至node状态变成notready而无法调度。Kubernetes1.14针对该问题进行了修复。

3、Kubelet会在重启或者删除容器前尝试停止处于unknown状态的容器。

4、镜像如果只有一个tag但是关联了多个仓库,此类镜像在回收的过程中不会再出现删除失败。

5、之前版本可能因为处理事件的channel满导致死锁,新版本通过丢弃来不及处理的事件来避免出现死锁的情况。

6、修复kubectl describe无法获取静态Pod事件的问题。

7、驱逐Pod时默认采用优雅删除模式,该修复使得Pod的退出更加优雅。

8、历史版本某些情况下会出现daemonSet创建的Pod被调度在不存在的节点上,增加对此类Pod的删除机制。

9、apiserver增加进程的优雅退出机制,该机制确保apiserver在退出前处理已建立的连接。

10、历史版本中某些情况下apiserver会在后端服务就绪之前去创建service的后端,出现服务不可访问的异常情况,针对此类情况作了修复。

10大规模场景下性能优化

除了稳定性外,1.14对于大规模场景下的性能也进行优化,具体包括:

  • Scheduler组件的缓存快照算法得到优化,提高了调度的吞吐量,目前能达到在5000节点的集群中平均每秒调度100个Pod(100是受limit限制,实际可能更高)。这是一个重要的里程碑。
  • 提高了Scheduler组件的鲁棒性,以保证未调度的Pod能够在适当的时候被重新调度。
  • Kubectl遍历APIServer的资源改为了并行模式,性能提升了10倍以上。
  • Api-server的单个json patch操作个数不能多于10000个,否则就返回413,不处理该请求。

关于Kubernetes 1.14更新的更多信息,大家可以关注百度智能云微信公众号,进行详细查阅。

百度智能云也将在对新版本进行全面的验证和测试之后,正式提供CCE对Kubernetes 1.14版本的支持,敬请期待。

本文作者:百度智能云CCE团队