精华内容
下载资源
问答
  • Kubernetes系统架构简介

    2021-02-21 01:15:24
    Kubernetes作为Docker生态圈中重要一员,是Google多年大规模容器管理技术的开源版本,是产线实践经验的最佳表现[G1]。如UrsH?lzle所说,无论是公有云还是私有云甚至...Kubernetes是Google开源的容器集群管理系统,其提
  • 本文节选自龚正等编著的《Kubernetes权威指南》,该节主要对常用的Kubernetes系统运维操作和技巧进行详细说明。然后,通过kubectlreplace命令完成对Node状态的修改:查看Node的状态,可以观察到在Node的状态中增加了...
  • Kubernetes的现代操作系统。 Talos是一种现代操作系统,旨在实现安全,不变和最小化。 所有系统管理都是通过API完成的,没有外壳程序或交互式控制台。 Talos提供的一些功能和优势包括: 安全性:Talos通过实践最低...
  • Kubernetes是原生的容器编排管理系统,对于负载均衡、服务发现、高可用、滚动升级、自动伸缩等容器云平台的功能要求有原生支持。今天我分享一下我们在Kubernetes集群中日志管理的实践方案。在这个方案中,除了Docker...
  • 编织Kubernetes系统控制wksctl 请注意,该代码最近已从ClusterAPI v1alpha1更新到v1alpha3,结果一切都已更改当此注释位于README中时,您可能会发现代码之间以及代码,示例和文档之间存在不一致之处。 对于那个很...
  • Kubernetes,也称为K8s,是一个开放源代码系统,用于跨多个主机管理容器化的应用程序。 Kubernetes 是用于自动部署,扩展和管理容器化应用程序的开源系统。 它将组成应用程序的容器组合成逻辑单元,以便于管理和服务...
  • 2. 什么是Kubernetes Kubernetes是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用,其主要功能如下:1) 使用Docker对应用程序包装...
  • 【完整版15章】Kubernetes 入门到进阶实战,系统性掌握 K8s 生产实践(2021最新课程),课程从0开始,系统性掌握 K8s 知识体系及落地实践,基础知识+原理解析+实战贯穿,极度友好的 K8s 学习路径,全程项目贯穿,...
  • Kubernetes外部机密使您可以使用外部机密管理系统(例如或在Kubernetes中安全地添加机密。 在上了解有关Kubernetes外部秘密的设计和动机的更多信息。 该项目以及相关的Kubernetes秘密管理项目的社区和维护者使用...
  • Kubernetes入门到进阶实战,系统性掌握K8s生产实践(2021新课)视频+学习材料
  • kubernetes监控系统部署

    2019-01-10 16:12:00
    kubernetes监控系统部署,监控架构:heapster + grafana + influxdb
  • Kubecc是一个现代的Kubernetes本地分布式构建系统,适用于从事C / C ++项目的团队。 受到原始启发,Kubecc是从Go的头开始编写的,它是一个快速,并发的构建系统,该系统驻留在您的本地开发集群中,并在后台静默运行...
  • Kubernetes是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用,其主要功能如下: 使用Docker对应用程序进行包装(package)、实例化...
  • Kubernetes系统架构是怎样的?

    千次阅读 2021-11-02 22:33:53
    一个典型的 Kubernetes 集群由多个工作节点( worker node )和一个集群控制平面( control plane ,即 Master ),以及一个集群状态存储系统( etcd )组成。 其中 Master 节点负责整个集群的管理工作,为集群提供管理...

    前言

    本文隶属于专栏《1000个问题搞定大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

    本专栏目录结构和参考文献请见1000个问题搞定大数据技术体系

    正文

    一个典型的 Kubernetes 集群由多个工作节点( worker node )和一个集群控制平面( control plane ,即 Master ),以及一个集群状态存储系统( etcd )组成。

    其中 Master 节点负责整个集群的管理工作,为集群提供管理接口,并监控和编排集群中的各个工作节点。

    各节点负责以 Pod 的形式运行容器,因此,各节点需要事先配置好容器运行依赖到的所有服务和资源,如容器运行时环境等。

    Kubernetes 的系统架构如图所示。

    在这里插入图片描述

    Master 节点主要由 apiserver 、 controller - manager 和 scheduler 三个组件,以及一个用于集群状态存储的 etcd 存储服务组成,而每个 Node 节点则主要包含 kubelet 、 kube - proxy 及容器引擎( Docker 是最为常用的实现)等组件。

    此外,完整的集群服务还依赖于一些附加组件,如 KubeDNS 等。

    Master 组件

    Kubernetes 的集群控制平面由多个组件组成,这些组件可统一运行于单一 Master 节点也可以以多副本的方式同时运行于多个节点,以为 Master 提供高可用功能,甚至还可以运行于 Kubernetes 集群自身之上。

    Master 主要包含以下几个组件。

    1.API Server

    API Server 负责输出 RESTFUL 风格的 KubernetesAPI ,它是发往集群的所有 REST 操作命令的接入点,并负责接收、校验并响应所有的 REST 请求,结果状态被持久存储于 etcd 中。

    因此, APIServer 是整个集群的网关。

    2.集群状态存储( Cluster State Store )

    Kubernetes 集群的所有状态信息都需要持久存储于存储系统 etcd 中,不过, etcd 是由 Cores 基于 Raft 协议开发的分布式键值存储,可用于服务发现、共享配置以及一致性保障(如数据库主节点选择、分布式锁等)。

    因此, etcd 是独立的服务组件,并不隶属于 Kubernetes 集群自身。 生产环境中应该以 etcd 集群的方式运行以确保其服务可用性。

    etcd 不仅能够提供键值数据存储,而且还为其提供了监听( Watch )机制,用于监听和准送变更。

    Kubernetes 集群系统中, etcd 中的键值发生变化时会通知到 APIServer ,并由其通过 watchAPI 向客户端输出。

    基于 Watch 机制, Kubernetes 集群的各组件实现了高效协同。

    3. 控制器管理器( Controller Manager )

    Kubernetes 中,集群级别的大多数功能都是由几个被称为控制器的进程执行实现的,这几个进程被集成于 kube - controller - manager 守护进程中。

    由控制器完成的功能主要包括生命周期功能和 API 业务逻辑,具体如下。

    • 生命周期功能:包括 Namespace 创建和生命周期、 Event 垃圾回收、 Pod 终止相关的垃圾回收、级联垃圾回收及 Node 垃圾回收等。
    • API 业务逻辑:例如,由 ReplicaSet 执行的 Pod 扩展等。

    4.调度器( Scheduler )

    Kubernetes 是用于部署和管理大规模容器应用的平台,根据集群规模的不同,其托管运行的容器很可能会数以千计甚至更多。

    API Server 确认 Pod 对象的创建请求之后,便需要由 Scheduler 根据集群内各节点的可用资源状态,以及要运行的容器的资源需求做出调度决策。

    另外, Kubernetes 还支持用户自定义调度器。

    Node 组件

    Node 负责提供运行容器的各种依赖环境,并接受 Master 的管理。

    每个 Node 主要由以下几个组件构成。

    1.Node 的核心代理程序 kubelet

    kubelet 是运行于工作节点之上的守护进程,它从 APIServer 接收关于 Pod 对象的配置信息并确保它们处于期望的状态( desired state )。

    kubelet 会在 APIServer 上注册当前工作节点,定期向 Master 汇报节点资源使用情况,并通过 advisor 监控容器和节点的资源占用状况。

    2. 容器运行时环境

    每个 Node 都要提供一个容器运行时( Container Runtime )环境,它负责下载镜像并运行容器。

    kubelet 并未固定链接至某容器运行时环境,而是以插件的方式载入配置的容器环境。

    这种方式清晰地定义了各组件的边界。 目前, Kubernetes 支持的容器运行环境至少包括 Docker 、 RKT 、 cri - o 和 Fraki 等。

    3.kube - proxy

    每个工作节点都需要运行一个 kube - proxy 守护进程,它能够按需为 Service 资源对象生成 iptables 或 ipvs 规则,从而捕获访问当前 Service 的 Cluster 的流量并将其转发至正确的后端Pod对象。

    核心附件

    Kubernetes 集群还依赖于一组称为“附件”( ad - ons )的组件以提供完整的功能,它们通常是由第三方提供的特定应用程序,且托管运行于 Kubernetes 集群之上。

    下面列出的几个附件各自为集群从不同角度引用了所需的核心功能。

    • KubeDNS :在 Kubernetes 集群中调度运行提供 DNS 服务的 Pod ,同一集群中的其他 Pod 可使用此 DNS 服务解决主机名。 Kubernetes 自 1 . 11 版本开始默认使用 KubeDNS 项日为集群提供服务注册和服务发现的动态名称解析服务,之前的版本中用到的是 kube - dns 项目,而 SkyDNS 则是更早一代的项目。
    • Kubernetes Dashboard : Kubernetes 集群的全部功能都要基于 Web 的 UI ,来管理集群中的应用甚至是集群自身。
    • Heapster :容器和节点的性能监控与分析系统,它收集并解析多种指标数据,如资源利用率、生命周期事件等。 新版本的 Kubernetes 中,其功能会逐渐由 Prometheus 结合其他组件所取代。
    • IngressController : Service 是一种工作于传统层的负载均衡器,而 Ingress 是在应用层实现的 HTTP ( s )负载均衡机制。 不过, Ingress 资源自身并不能进行“流量穿透”,它仅是一组路由规则的集合,这些规则需要通过 Ingress 控制器 ( IngressController ) 发挥作用。 目前,此类的可用项目有 Nginx 、 Traefik 、 Envoy 及 HAProxy 等。
    展开全文
  • Kubernetes效应

    2021-02-25 04:38:58
    2.Kubernetes为基于语言的构建块增加了一个全新的维度,它提供了一组新的分布式原语和运行时环境,用于创建分布于多个进程和节点上的分布式系统。3.创建容器化应用程序的核心原则是将容器镜像当做基本的原语,把容器...
  • 火山是建立在Kubernetes上的批处理系统。 它提供了许多类别的批处理和弹性工作负载通常需要的一套机制,包括:机器学习/深度学习,生物信息学/基因组学和其他“大数据”应用程序。 这些类型的应用程序通常在与...
  • Kubernetes系统架构与设计理念

    万次阅读 2016-08-16 15:35:51
    Kubernetes与云原生应用简介 随着Docker技术的发展和广泛流行,云原生应用和容器调度管理系统也成为IT领域大热的词汇。事实上,云原生应用的思想,在Docker技术火爆之前,已经由云计算技术的领导者和分布式系统架构...

    Kubernetes与云原生应用简介

    随着Docker技术的发展和广泛流行,云原生应用和容器调度管理系统也成为IT领域大热的词汇。事实上,云原生应用的思想,在Docker技术火爆之前,已经由云计算技术的领导者和分布式系统架构的推广者广泛传播,例如云原生应用的12要素早在2011年就由Heroku的工程师提出了;只不过以虚拟机技术作为云原生应用的基础实施,由于虚拟机镜像大、镜像标准不统一以及打包流程和工具不统一,无法业界广泛接受的云原生应用标准,限制了云原生应用的流行。而Docker的出现正好解决了这些限制云原生应用构建、交付和运行的瓶颈,使得构建云原生应用成为了使用Docker的开发者自然而然的选择。

    单机的Docker引擎和单一的容器镜像只能解决单一服务的打包和测试问题。而要运行生产级的企业级应用,就需要容器调度管理系统。在这里面,Docker技术就仿佛运送系统零件的集装箱,把云原生应用的各个标准化零件交付到各个企业的不同码头,而容器调度管理系统就是企业应用的运行车间,把不同的零件组装、运行、维护起来。

    Kubernetes是为生产环境而设计的容器调度管理系统,对于负载均衡、服务发现、高可用、滚动升级、自动伸缩等容器云平台的功能要求有原生支持。由于Kubernetes在K和s间有8个字母,因此常简称K8s。事实上,随着对K8s系统架构与设计理念的了解深入,我们会发现K8s系统正是处处为运行云原生应用而设计考虑;同时,随着对K8s系统使用的加深和加广,也会有越来越多有关云原生应用的设计模式产生出来,使得基于K8s系统设计和开发生产级的复杂云原生应用变得像启动一个单机版容器服务那样简单易用。

    本系列文章将会从介绍和分析K8s系统以及云原生应用入手,逐步推出基于K8s的容器设计模式实践案例,希望对计划应用K8s的朋友有所帮助。

    Kubernetes的最新进展——发布1.3.0版

    K8s于2016年7月发布了1.3的正式版,带来了3个实验性的新功能:基于角色的权限控制RBAC,跨地区跨云的联合集群服务Federation和有状态应用微服务集合PetSet,让大家可以对K8s集群本身的技术发展趋势窥豹一斑。本文的系统架构和核心技术解析部分会包含这几项功能的详细介绍。

    Kubernetes与容器设计模式

    K8s在2016年6月的云计算大会上发表了有关容器设计模式的论文《Design patterns for container-based distributed systems》,介绍了基于K8s设计云原生应用的容器设计模式,为基于K8s的云原生应用的设计模式划定了蓝图。在K8s与云原生应用系列文章中我们会结合具体应用案例解析这些设计模式。

    Kubernetes的系统架构

    Kubernetes的系统架构

    一个K8s集群是由分布式存储(etcd)、服务节点(Minion,etcd现在称为Node)和控制节点(Master)构成的。所有的集群状态都保存在etcd中,Master节点上则运行集群的管理控制模块。Node节点是真正运行应用容器的主机节点,在每个Minion节点上都会运行一个Kubelet代理,控制该节点上的容器、镜像和存储卷等。

    (点击放大图像)

    Kubernetes的架构实现理念

    K8s在实现上述架构时要基于以下架构理念:

    • 只有API Server与存储通信,其他模块通过API Server访问集群状态。这样第一,是为了保证集群状态访问的安全。第二,是为了隔离集群状态访问的方式和后端存储实现的方式:API Server是状态访问的方式,不会因为后端存储技术etcd的改变而改变。加入以后将etcd更换成其他的存储方式,并不会影响依赖依赖API Server的其他K8s系统模块。
    • 一个工作节点被攻破不能导致整个K8s集群被攻破。这是所有分布式系统架构设计中都应该考虑的问题。
    • 考虑网络随时可能断开的情况,没有新配置声明时各模块按照之前的配置声明继续工作。在K8s集群中,所有的配置管理操作都声明式而非命令式的,因为声明式操作对于网络故障等分布式系统常见的故障情况更加稳定。
    • 各个模块在内存中缓存自己的相关状态以提高系统性能。
    • 需要监控某个系统状态来做下一步动作的时候,优先考虑观察通知模式,其次再考虑轮询模式,这也是为了提高系统的响应速度。

    Kubernetes的核心技术概念和API对象

    API对象是K8s集群中的管理操作单元。K8s集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的API对象,支持对该功能的管理操作。例如副本集Replica Set对应的API对象是RS。

    每个API对象都有3大类属性:元数据metadata、规范spec和状态status。元数据是用来标识API对象的,每个对象都至少有3个元数据:namespace,name和uid;除此以外还有各种各样的标签labels用来标识和匹配不同的对象,例如用户可以用标签env来标识区分不同的服务部署环境,分别用env=dev、env=testing、env=production来标识开发、测试、生产的不同服务。规范描述了用户期望K8s集群中的分布式系统达到的理想状态(Desired State),例如用户可以通过复制控制器Replication Controller设置期望的Pod副本数为3;status描述了系统实际当前达到的状态(Status),例如系统当前实际的Pod副本数为2;那么复制控制器当前的程序逻辑就是自动启动新的Pod,争取达到副本数为3。

    K8s中所有的配置都是通过API对象的spec去设置的,也就是用户通过配置系统的理想状态来改变系统,这是k8s重要设计理念之一,即所有的操作都是声明式(Declarative)的而不是命令式(Imperative)的。声明式操作在分布式系统中的好处是稳定,不怕丢操作或运行多次,例如设置副本数为3的操作运行多次也还是一个结果,而给副本数加1的操作就不是声明式的,运行多次结果就错了。

    微服务豆荚(Pod)

    K8s有很多技术概念,同时对应很多API对象,最重要的也是最基础的是微服务豆荚Pod。Pod是在K8s集群中运行部署应用或服务的最小单元,它是可以支持多容器的。Pod的设计理念是支持多个容器在一个Pod中共享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。Pod对多容器的支持是K8最基础的设计理念。比如你运行一个操作系统发行版的软件仓库,一个Nginx容器用来发布软件,另一个容器专门用来从源仓库做同步,这两个容器的镜像不太可能是一个团队开发的,但是他们一块儿工作才能提供一个微服务;这种情况下,不同的团队各自开发构建自己的容器镜像,在部署的时候组合成一个微服务对外提供服务。

    Pod是K8s集群中所有业务类型的基础,可以看作运行在K8集群中的小机器人,不同类型的业务就需要不同类型的小机器人去执行。目前K8s中的业务主要可以分为长期伺服型(long-running)、批处理型(batch)、节点后台支撑型(node-daemon)和有状态应用型(stateful application);分别对应的小机器人控制器为Deployment、Job、DaemonSet和PetSet,本文后面会一一介绍。

    复制控制器(Replication Controller,RC)

    RC是K8s集群中最早的保证Pod高可用的API对象。通过监控运行中的Pod来保证集群中运行指定数目的Pod副本。指定的数目可以是多个也可以是1个;少于指定数目,RC就会启动运行新的Pod副本;多于指定数目,RC就会杀死多余的Pod副本。即使在指定数目为1的情况下,通过RC运行Pod也比直接运行Pod更明智,因为RC也可以发挥它高可用的能力,保证永远有1个Pod在运行。RC是K8s较早期的技术概念,只适用于长期伺服型的业务类型,比如控制小机器人提供高可用的Web服务。

    副本集(Replica Set,RS)

    RS是新一代RC,提供同样的高可用能力,区别主要在于RS后来居上,能支持更多中的匹配模式。副本集对象一般不单独使用,而是作为部署的理想状态参数使用。

    部署(Deployment)

    部署表示用户对K8s集群的一次更新操作。部署是一个比RS应用模式更广的API对象,可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务。滚动升级一个服务,实际是创建一个新的RS,然后逐渐将新RS中副本数增加到理想状态,将旧RS中的副本数减小到0的复合操作;这样一个复合操作用一个RS是不太好描述的,所以用一个更通用的Deployment来描述。以K8s的发展方向,未来对所有长期伺服型的的业务的管理,都会通过Deployment来管理。

    服务(Service)

    RC、RS和Deployment只是保证了支撑服务的微服务豆荚的数量,但是没有解决如何访问这些服务的问题。一个Pod只是一个运行服务的实例,随时可能在一个节点上停止,在另一个节点以一个新的IP启动一个新的Pod,因此不能以确定的IP和端口号提供服务。要稳定地提供服务需要服务发现和负载均衡能力。服务发现完成的工作,是针对客户端访问的服务,找到对应的的后端服务实例。在K8集群中,客户端需要访问的服务就是Service对象。每个Service会对应一个集群内部有效的虚拟IP,集群内部通过虚拟IP访问一个服务。在K8s集群中微服务的负载均衡是由Kube-proxy实现的。Kube-proxy是K8s集群内部的负载均衡器。它是一个分布式代理服务器,在K8s的每个节点上都有一个;这一设计体现了它的伸缩性优势,需要访问服务的节点越多,提供负载均衡能力的Kube-proxy就越多,高可用节点也随之增多。与之相比,我们平时在服务器端做个反向代理做负载均衡,还要进一步解决反向代理的负载均衡和高可用问题。

    任务(Job)

    Job是K8s用来控制批处理型任务的API对象。批处理业务与长期伺服业务的主要区别是批处理业务的运行有头有尾,而长期伺服业务在用户不停止的情况下永远运行。Job管理的Pod根据用户的设置把任务成功完成就自动退出了。成功完成的标志根据不同的spec.completions策略而不同:单Pod型任务有一个Pod成功就标志完成;定数成功型任务保证有N个任务全部成功;工作队列型任务根据应用确认的全局成功而标志成功。

    后台支撑服务集(DaemonSet)

    长期伺服型和批处理型服务的核心在业务应用,可能有些节点运行多个同类业务的Pod,有些节点上又没有这类Pod运行;而后台支撑型服务的核心关注点在K8s集群中的节点(物理机或虚拟机),要保证每个节点上都有一个此类Pod运行。节点可能是所有集群节点也可能是通过nodeSelector选定的一些特定节点。典型的后台支撑型服务包括,存储,日志和监控等在每个节点上支持K8s集群运行的服务。

    有状态服务集(PetSet)

    K8s在1.3版本里发布了Alpha版的PetSet功能。在云原生应用的体系里,有下面两组近义词;第一组是无状态(stateless)、牲畜(cattle)、无名(nameless)、可丢弃(disposable);第二组是有状态(stateful)、宠物(pet)、有名(having name)、不可丢弃(non-disposable)。RC和RS主要是控制提供无状态服务的,其所控制的Pod的名字是随机设置的,一个Pod出故障了就被丢弃掉,在另一个地方重启一个新的Pod,名字变了、名字和启动在哪儿都不重要,重要的只是Pod总数;而PetSet是用来控制有状态服务,PetSet中的每个Pod的名字都是事先确定的,不能更改。PetSet中Pod的名字的作用,并不是《千与千寻》的人性原因,而是关联与该Pod对应的状态。

    对于RC和RS中的Pod,一般不挂载存储或者挂载共享存储,保存的是所有Pod共享的状态,Pod像牲畜一样没有分别(这似乎也确实意味着失去了人性特征);对于PetSet中的Pod,每个Pod挂载自己独立的存储,如果一个Pod出现故障,从其他节点启动一个同样名字的Pod,要挂在上原来Pod的存储继续以它的状态提供服务。

    适合于PetSet的业务包括数据库服务MySQL和PostgreSQL,集群化管理服务Zookeeper、etcd等有状态服务。PetSet的另一种典型应用场景是作为一种比普通容器更稳定可靠的模拟虚拟机的机制。传统的虚拟机正是一种有状态的宠物,运维人员需要不断地维护它,容器刚开始流行时,我们用容器来模拟虚拟机使用,所有状态都保存在容器里,而这已被证明是非常不安全、不可靠的。使用PetSet,Pod仍然可以通过漂移到不同节点提供高可用,而存储也可以通过外挂的存储来提供高可靠性,PetSet做的只是将确定的Pod与确定的存储关联起来保证状态的连续性。PetSet还只在Alpha阶段,后面的设计如何演变,我们还要继续观察。

    联合集群服务(Federation)

    K8s在1.3版本里发布了beta版的Federation功能。在云计算环境中,服务的作用距离范围从近到远一般可以有:同主机(Host,Node)、跨主机同可用区(Available Zone)、跨可用区同地区(Region)、跨地区同服务商(Cloud Service Provider)、跨云平台。K8s的设计定位是单一集群在同一个地域内,因为同一个地区的网络性能才能满足K8s的调度和计算存储连接要求。而联合集群服务就是为提供跨Region跨服务商K8s集群服务而设计的。

    每个K8s Federation有自己的分布式存储、API Server和Controller Manager。用户可以通过Federation的API Server注册该Federation的成员K8s Cluster。当用户通过Federation的API Server创建、更改API对象时,Federation API Server会在自己所有注册的子K8s Cluster都创建一份对应的API对象。在提供业务请求服务时,K8s Federation会先在自己的各个子Cluster之间做负载均衡,而对于发送到某个具体K8s Cluster的业务请求,会依照这个K8s Cluster独立提供服务时一样的调度模式去做K8s Cluster内部的负载均衡。而Cluster之间的负载均衡是通过域名服务的负载均衡来实现的。

    所有的设计都尽量不影响K8s Cluster现有的工作机制,这样对于每个子K8s集群来说,并不需要更外层的有一个K8s Federation,也就是意味着所有现有的K8s代码和机制不需要因为Federation功能有任何变化。

    存储卷(Volumn)

    K8s集群中的存储卷跟Docker的存储卷有些类似,只不过Docker的存储卷作用范围为一个容器,而K8s的存储卷的生命周期和作用范围是一个Pod。每个Pod中声明的存储卷由Pod中的所有容器共享。K8s支持非常多的存储卷类型,特别的,支持多种公有云平台的存储,包括AWS,Google和Azure云;支持多种分布式存储包括GlusterFS和Ceph;也支持较容易使用的主机本地目录hostPath和NFS。K8s还支持使用Persistent Volumn Claim即PVC这种逻辑存储,使用这种存储,使得存储的使用者可以忽略后台的实际存储技术(例如AWS,Google或GlusterFS和Ceph),而将有关存储实际技术的配置交给存储管理员通过Persistent Volumn来配置。

    持久存储卷(Persistent Volumn,PV)和持久存储卷声明(Persistent Volumn Claim,PVC)

    PV和PVC使得K8s集群具备了存储的逻辑抽象能力,使得在配置Pod的逻辑里可以忽略对实际后台存储技术的配置,而把这项配置的工作交给PV的配置者,即集群的管理者。存储的PV和PVC的这种关系,跟计算的Node和Pod的关系是非常类似的;PV和Node是资源的提供者,根据集群的基础设施变化而变化,由K8s集群管理员配置;而PVC和Pod是资源的使用者,根据业务服务的需求变化而变化,有K8s集群的使用者即服务的管理员来配置。

    节点(Node)

    K8s集群中的计算能力由Node提供,最初Node称为服务节点Minion,后来改名为Node。K8s集群中的Node也就等同于Mesos集群中的Slave节点,是所有Pod运行所在的工作主机,可以是物理机也可以是虚拟机。不论是物理机还是虚拟机,工作主机的统一特征是上面要运行kubelet管理节点上运行的容器。

    Kubernetes集群中与安全相关的技术概念

    秘盒对象(Secret)

    Secret是用来保存和传递密码、密钥、认证凭证这些敏感信息的对象。使用Secret的好处是可以避免把敏感信息明文写在配置文件里。在K8s集群中配置和使用服务不可避免的要用到各种敏感信息实现登录、认证等功能,例如访问AWS存储的用户名密码。为了避免将类似的敏感信息明文写在所有需要使用的配置文件中,可以将这些信息存入一个Secret对象,而在配置文件中通过Secret对象引用这些敏感信息。这种方式的好处包括:意图明确,避免重复,减少暴漏机会。

    用户帐户(User Account)和服务帐户(Service Account)

    顾名思义,用户帐户为人提供账户标识,而服务账户为计算机进程和K8s集群中运行的Pod提供账户标识。用户帐户和服务帐户的一个区别是作用范围;用户帐户对应的是人的身份,人的身份与服务的namespace无关,所以用户账户是跨namespace的;而服务帐户对应的是一个运行中程序的身份,与特定namespace是相关的。

    名字空间(Namespace)

    名字空间为K8s集群提供虚拟的隔离作用,K8s集群初始有两个名字空间,分别是默认名字空间default和系统名字空间kube-system,除此以外,管理员可以可以创建新的名字空间满足需要。

    RBAC模式授权和ABAC模式授权

    K8s在1.3版本中发布了alpha版的基于角色的访问控制(Role-based Access Control,RBAC)的授权模式。相对于基于属性的访问控制(Attribute-based Access Control,ABAC),RBAC主要是引入了角色(Role)和角色绑定(RoleBinding)的抽象概念。在ABAC中,K8s集群中的访问策略只能跟用户直接关联;而在RBAC中,访问策略可以跟某个角色关联,具体的用户在跟一个或多个角色相关联。显然,RBAC像其他新功能一样,每次引入新功能,都会引入新的API对象,从而引入新的概念抽象,而这一新的概念抽象一定会使集群服务管理和使用更容易扩展和重用。

    Kubernetes的设计理念

    Kubernetes设计理念与分布式系统

    分析和理解K8s的设计理念对设计和实现分布式系统有两方面的益处。一方面,可以使我们更深入地了解K8s系统,更好地利用它管理分布式部署的云原生应用;另一方面,K8s集群管理平台本身也是个分布式系统,分析和理解它可以让我们借鉴其在分布式系统设计方面的经验。

    Kubernetes系统API的设计原则

    对于云计算系统,系统API实际上处于系统设计的统领地位,正如本文前面所说,K8s集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的API对象,支持对该功能的管理操作,理解掌握的API,就好比抓住了K8s系统的牛鼻子。K8s系统API的设计有以下几条原则:

    1. 所有API应该是声明式的。正如前文所说,声明式的操作,相对于命令式操作,对于重复操作的效果是稳定的,这对于容易出现数据丢失或重复的分布式环境来说是很重要的。另外,声明式操作更容易被用户使用,可以使系统向用户隐藏实现的细节,隐藏实现的细节的同时,也就保留了系统未来持续优化的可能性。此外,声明式的API,同时隐含了所有的API对象都是名词性质的,例如Service、Volumn这些API都是名词,这些名词描述了用户所期望得到的一个目标分布式对象。
    2. API对象是彼此互补而且可组合的。这里面实际是鼓励API对象尽量实现面向对象设计时的要求,即“高内聚,松耦合”,对业务相关的概念有一个合适的分解,提高分解出来的对象的可重用性。事实上,K8s这种分布式系统管理平台,也是一种业务系统,只不过它的业务就是调度和管理容器服务。
    3. 高层API以操作意图为基础设计。如何能够设计好API,跟如何能用面向对象的方法设计好应用系统有相通的地方,高层设计一定是从业务出发,而不是过早的从技术实现出发。因此,针对K8s的高层API设计,一定是以K8s的业务为基础出发,也就是以系统调度管理容器的操作意图为基础设计。
    4. 低层API根据高层API的控制需要设计。设计实现低层API的目的,是为了被高层API使用,考虑减少冗余、提高重用性的目的,低层API的设计也要以需求为基础,要尽量抵抗受技术实现影响的诱惑。
    5. 尽量避免简单封装,不要有在外部API无法显式知道的内部隐藏的机制。简单的封装,实际没有提供新的功能,反而增加了对所封装API的依赖性。内部隐藏的机制也是非常不利于系统维护的设计方式,例如PetSet和ReplicaSet,本来就是两种Pod集合,那么K8s就用不同API对象来定义它们,而不会说只用同一个ReplicaSet,内部通过特殊的算法再来区分这个ReplicaSet是有状态的还是无状态。
    6. API操作复杂度与对象数量成正比。这一条主要是从系统性能角度考虑,要保证整个系统随着系统规模的扩大,性能不会迅速变慢到无法使用,那么最低的限定就是API的操作复杂度不能超过O(N),N是对象的数量,否则系统就不具备水平伸缩性了。
    7. API对象状态不能依赖于网络连接状态。由于众所周知,在分布式环境下,网络连接断开是经常发生的事情,因此要保证API对象状态能应对网络的不稳定,API对象的状态就不能依赖于网络连接状态。
    8. 尽量避免让操作机制依赖于全局状态,因为在分布式系统中要保证全局状态的同步是非常困难的

    Kubernetes系统的控制机制的设计原则

    • 控制逻辑应该只依赖于当前状态。这是为了保证分布式系统的稳定可靠,对于经常出现局部错误的分布式系统,如果控制逻辑只依赖当前状态,那么就非常容易将一个暂时出现故障的系统恢复到正常状态,因为你只要将该系统重置到某个稳定状态,就可以自信的知道系统的所有控制逻辑会开始按照正常方式运行。
    • 假设任何错误的可能,并做容错处理。在一个分布式系统中出现局部和临时错误是大概率事件。错误可能来自于物理系统故障,外部系统故障也可能来自于系统自身的代码错误,依靠自己实现的代码不会出错来保证系统稳定其实也是难以实现的,因此要设计对任何可能错误的容错处理。
    • 尽量避免复杂状态机,控制逻辑不要依赖无法监控的内部状态。因为分布式系统各个子系统都是不能严格通过程序内部保持同步的,所以如果两个子系统的控制逻辑如果互相有影响,那么子系统就一定要能互相访问到影响控制逻辑的状态,否则,就等同于系统里存在不确定的控制逻辑。
    • 假设任何操作都可能被任何操作对象拒绝,甚至被错误解析。由于分布式系统的复杂性以及各子系统的相对独立性,不同子系统经常来自不同的开发团队,所以不能奢望任何操作被另一个子系统以正确的方式处理,要保证出现错误的时候,操作级别的错误不会影响到系统稳定性。
    • 每个模块都可以在出错后自动恢复。由于分布式系统中无法保证系统各个模块是始终连接的,因此每个模块要有自我修复的能力,保证不会因为连接不到其他模块而自我崩溃。
    • 每个模块都可以在必要时优雅地降级服务。所谓优雅地降级服务,是对系统鲁棒性的要求,即要求在设计实现模块时划分清楚基本功能和高级功能,保证基本功能不会依赖高级功能,这样同时就保证了不会因为高级功能出现故障而导致整个模块崩溃。根据这种理念实现的系统,也更容易快速地增加新的高级功能,以为不必担心引入高级功能影响原有的基本功能。

    Kubernetes系统核心理念总结

    从K8s的系统架构、技术概念和设计理念,我们可以看到K8s系统最核心的两个设计理念:一个是容错性,一个是易扩展性。容错性实际是保证K8s系统稳定性和安全性的基础,易扩展性是保证K8s对变更友好,可以快速迭代增加新功能的基础。

    按照分布式系统一致性算法Paxos发明人计算机科学家Leslie Lamport的理念,一个分布式系统有两类特性:安全性Safety和活性Liveness。安全性保证系统的稳定,保证系统不会崩溃,不会出现业务错误,不会做坏事,是严格约束的;活性使得系统可以提供功能,提高性能,增加易用性,让系统可以在用户“看到的时间内”做些好事,是尽力而为的。K8s系统的设计理念正好与Lamport安全性与活性的理念不谋而合,也正是因为K8s在引入功能和技术的时候,非常好地划分了安全性和活性,才可以让K8s能有这么快版本迭代,快速引入像RBAC、Federation和PetSet这种新功能。

    展开全文
  • Kubernetes容器集群管理系统-随堂笔记.
  • Kubernetes集群上运行的石墨基础设施以及来自节点的运输指标
  • kubernetes容器编排系统介绍

    万次阅读 2016-10-18 11:12:26
    Kubernetes作为容器编排生态圈中重要一员,是Google大规模容器管理系统borg的开源版本实现,吸收借鉴了google过去十年间在生产环境上所学到的经验与教训。 Kubernetes提供应用部署、维护、 扩展机制等功能,利用...

    Kubernetes作为容器编排生态圈中重要一员,是Google大规模容器管理系统borg的开源版本实现,吸收借鉴了google过去十年间在生产环境上所学到的经验与教训。 Kubernetes提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用。当前Kubernetes支持GCE、vShpere、CoreOS、OpenShift、Azure等平台,除此之外,也可以直接运行在物理机上.kubernetes是一个开放的容器调度管理平台,不限定任何一种言语,支持java/C++/go/python等各类应用程序 。
    kubernetes是一个完备的分布式系统支持平台,支持多层安全防护、准入机制、多租户应用支撑、透明的服务注册、服务发现、内建负载均衡、强大的故障发现和自我修复机制、服务滚动升级和在线扩容、可扩展的资源自动调度机制、多粒度的资源配额管理能力,完善的管理工具,包括开发、测试、部署、运维监控,一站式的完备的分布式系统开发和支撑平台。

    一. 系统架构

    kubernetes系统按节点功能由master和node组成。

    Master
    Master作为控制节点,调度管理整个系统,包含以下组件:
    API Server作为kubernetes系统的入口,封装了核心对象的增删改查操作,以RESTful接口方式提供给外部客户和内部组件调用。它维护的REST对象将持久化到etcd。
    Scheduler:负责集群的资源调度,为新建的pod分配机器。这部分工作分出来变成一个组件,意味着可以很方便地替换成其他的调度器。
    Controller Manager:负责执行各种控制器,目前有两类:

    1. Endpoint Controller:定期关联service和pod(关联信息由endpoint对象维护),保证service到pod的映射总是最新的。
    2. Replication Controller:定期关联replicationController和pod,保证replicationController定义的复制数量与实际运行pod的数量总是一致的。

    Node
    Node是运行节点,运行业务容器,包含以下组件:
    Kubelet:责管控docker容器,如启动/停止、监控运行状态等。它会定期从etcd获取分配到本机的pod,并根据pod信息启动或停止相应的容器。同时,它也会接收apiserver的HTTP请求,汇报pod的运行状态。
    Kube Proxy:负责为pod提供代理。它会定期从etcd获取所有的service,并根据service信息创建代理。当某个客户pod要访问其他pod时,访问请求会经过本机proxy做转发。
    借用一张网图,表达功能组件之间关系:

    二.基本概念

    Node

    node是kubernetes集群中相对于master而言的工作主机,在较早版本中也被称为minion。Node可以是一台物理主机,也可以是一台虚拟机(VM)。在每个node上运行用于启动和管理pod的服务——kubelet,并能够被master管理。在node上运行的服务进程包括kubelet、kube-proxy和docker daemon。
    Node的信息如下:
    node地址:主机的IP地址或者nodeid
    node的运行状态: pending,running,terminated
    node condition: 描述running状态node的运行条件,目前只有一种条件Ready,表示node处于健康状态,可以接收master发来的创建pod的指令。
    node系统容量:描述node可用的系统资源,包括CPU、内存、最大可调度pod数量等

    Pod

    pod是kubernetes的最基本操作单元,包括一个或多个紧密相关的容器,一个pod可以被一个容器化的环境看作应用层的“逻辑宿主机”(Logical host)。一个pod中的多个容器应用通常是紧耦合的。Pod在node上被创建、启动或者销毁。
    为什么kubernetes使用pod在容器之上再封装一层呢?一个很重要的原因是,docker容器之间通信受到docker网络机制的限制。在docker的,世界中,一个容器需要通过link方式才能访问另一个容器提供的服务(端口)。大量容器之间的link将是一个非常繁重的工作。通过pod的概念将多个容器组合在一个虚拟的“主机”内,可以实现容器之间仅需通过localhost就能相互通信了。
    一个pod中的应用容器共享一组资源,如:
    pid命名空间:pod中的不同应用程序可以看到其他的进程PID
    网络命名空间:pod中的多个容器能够访问同一个IP和端口范围
    IPC命名空间:pod中的多个容器能够使用systemV ipc 或POSIX消息队列进行通信。
    UTS命名空间:pod中的多个容器共享一个主机名。
    Volumes(共享存储卷):pod中的各个容器可以访问在pod级别定义的volumes。

    Label

    label是kubernetes系统中的一个核心概念。Label以key/value键值对的形式附加到各种对象上,如pod、service、RC、Node等。Label定义了这些对象的可识别属性,用来对它们进行管理和选择。Label可以在创建对象时附加到对象上,也可以在对象创建后通过API进行管理。
    在为对象定义好label后,其他对象就可以使用label selector来定义其他作用的对象了。
    label selector的定义由多个逗号分隔的条件组成:
    “label”: {
    “key1”: ”value1”,
    “key2”: ”value2”
    }

    Resource controller(RC)

    Resource controller(RC)是kubernetes系统中的核心概念,用于定义pod副本的数量。在master的Controller manager进程通过RC的定义来完成pod的创建、监控、启停等操作。
    根据replication controller的定义,kubernetes能够确保在任意时刻都能运行用户指定的pod“副本”(replica)数量。如果有过多的的pod副本在运行,系统会停掉一些pod;如果运行的pod副本数量太少,系统就会再启动一些pod,总之,通过RC的定义,kubernetes总是保证集群中运行着用户期望副本数量。

    Service(服务)

    在kubernetes的世界里,虽然每个pod都会被分配一个单独的IP地址,但这个IP地址会随着pod的销毁而消失。这就引出一个问题:如果有一组pod组成一个集群来提供服务,那么如何来访问它们呢?
    kubernetes的service就是用来解决这个问题的核心概念。一个service可以看作一组提供相同服务的pod的对外访问接口。Service作用于哪些pod是通过label selector 来定义的。
    pod的IP地址是docker daemon根据docker0网桥的IP地址段进行分配的,但service的Cluster IP地址是kubernetes系统中的虚拟IP地址,由系统动态分配。 Service的ClusterIP地址相对于pod的IP地址来说相对稳定,service被创建时即被分配IP地址,在销毁该service之前,这个IP地址都不会再变化。
    由于service对象在Cluster IP Range池中分配到的IP只能在内部访问,所以其他pod都可以无障碍地访问到它。但如果这个service作为前端服务,准备为集群外的客户端提供服务,我们就需要给这个服务提供公共IP了。
    kubernetes支持两种对外提供服务的service的type定义:nodeport和loadbalancer。

    Volume(存储卷)

    volume是pod中能够被多个容器访问的共享目录。Kubernetes的volume概念与docker的volume比较类似,但并不完全相同。Kubernetes中的volume与pod生命周期相同,但与容器的生命周期不相关。当容器终止或重启时,volume中的数据也不会丢失。另外,kubernetes支持多种类型的volume,并且一个pod可以同时使用任意多个volume。
    (1)EmptyDir:一个EmptyDir volume是在pod分配到Node时创建的。从它的名称就可以看出,它的初始内容为空。在同一个pod中所有容器可以读和写EmptyDir中的相同文件。当pod从node上移除时,EmptyDir中的数据也会永久删除。
    (2)hostPath:在pod上挂载宿主机上的文件或目录。通常用于:
    容器应用程序生成的日志文件需要永久保存,可以使用宿主机的高速文件系统进行存储;
    需要访问宿主机上的docker引擎内部数据结构的容器应用,可以通过定义hostPath为宿主机/var/lib/docker目录,使容器内部应用可以直接访问docker的文件系统
    (3)gcePersistentDick:使用这种类型的volume表示使用谷歌计算引擎(Google Compute Engine, GCE)上永久磁盘(persistent disk,PD)上的文件。与EmptyDir不同,PD上的内容会永久保存,当pod被删除时,PD只是被卸载(unmount),但不会被删除。需要注意的是,你需要先创建一个永久磁盘(PD)才能使用gcePersistentDisk。
    (4)awsElasticBlockStore:与GCE类似,该类型的volume使用Amazon提供的Amazon Web Service(AWS)的EBS Volume,并可以挂载到pod中去。需要注意的是,需要先创建一个EBS Volume才能使用awsElasticBlockStore。
    (5)nfs:使用NFS(网络文件系统)提供的共享目录挂载到Pod中。在系统中需要一个支行中的NFS系统。
    (6)iscsi:使用iSCSI存储设备上的目录挂载到pod中。
    (7)glusterfs:使用开源BlusterFS网络文件系统的目录挂载到pod中。
    (8)rbd:使用Linux块设备共享存储(Rados Block Device)挂载到pod中。
    (9)gitRepo:通过挂载一个空目录,并从GIT库clone一个git repository以供pod使用。
    (10)secret:一个secret volume用于为pod提供加密的信息,你可以将定义在kubernetes中的secret直接挂载为文件让pod访问。Secret volume是通过tmfs(内存文件系统)实现的,所以这种类型的volume总是不会持久化的。
    (11)persistentVolumeClaim:从PV(persistentVolume)中申请所需的空间,PV通常是种网络存储,如GCEPersistentDisk、AWSElasticBlockStore、NFS、iSCSI等。

    Namespace(命名空间)

    namespace(命名空间)是kubernetes系统中另一个非常重要的概念,通过将系统内部的对象“分配”到不同的namespace中,形成逻辑上分组的不同项目、小组或用户组,便于不同的分组在共享使用整个集群的资源的同时还能分别管理。
    kubernetes集群在启动后,会创建一个名为“default”的namespace。接下来,如果不特别指明namespace,则用户创建的pod、RC、Service都将被系统创建到名为“default”的namespace中。
    使用namespace来组织kubernetes的各种对象,可以实现对用户的分组,即“多租户”管理。对不同的租房还可以进行单独的资源配额设备和管理,使得整个集群配置非常灵活、方便。

    Annotation(注解)

    annotation与label类似,也使用key/value键值对的形式进行定义。Label具有严格的全名规则,它定义的是kubernetes对象的元数据(metadata),并且用于label selector。Annotation则是用户任意定义的“附加”信息,以便于外部工具进行查找。
    用annotation来记录的信息包括:
    build信息、release信息、docker镜像信息等,如时间戳、release id号、PR号、镜像hash值、docker Controller地址等

    典型流程

    以创建一个Pod为例,kubernetes典型的流程如下图所示:

    三.组件

    Replication Controller

    为了区分Controller Manager中的Replication Controller(副本控制器)和资源对象Replication Controller,我们将资源对象简写为RC,而Replication Controller特指“副本控制器”。
    Replication Controller的核心作用是确保在任何时间集群中一个RC所关联的pod都保持一定数量的pod副本处于正常运行状态。如果该类pod的pod副本数量太多,则Replication Controller会销毁一些pod副本;反之Replication Controller会添加pod副本,直到该类pod的pod副本数量达到预设的副本数量。最好不要超过RC直接创建pod,因为Replication Controller会通过RC管理pod副本,实现自动创建、补足、替换、删除pod副本,这样就能提高系统的容灾能力,减少由于节点崩溃等意外状况造成的损失。即使应用程序只用到一个pod副本,也强烈建设使用RC来定义pod。

    Replication Controller管理的对象是pod,因此其操作与pod的状态及重启策略息息相关。
    副本控制器的常用使用模式:
    (1)重新调度:不管想运行1个副本还是1000副本,副本控制器能够确保指定pod数量的副本存在于集群中,如果节点故障或副本被终止运行等意外情况,将会重新调度直到达到预期的副本正常运行。
    (2)弹性伸缩:手动或通过自动扩容代理修改副本控制器的spec.replicas属性值,非常容易实现扩大或缩小副本的数量。
    (3)滚动更新:副本控制器被设计成通过逐个替换pod的方式来辅助服务的滚动更新。推荐的方式是创建一个新的只有一个副本的RC,若新的RC副本数量加1,则旧的RC的副本数量减1,直到这个旧的RC副本数量为零,然后删除该旧的RC。
    在滚动更新的讨论中,我们发现一个应用在滚动更新时,可能存在多个版本的release。事实上,在生产环境中一个已经发布的应用程序存在多个release版本是很正常的现象。通过RC的标签选择器,我们能很方便地实现对一个应用的多版本release的跟踪。

    node controller

    Node Controller负责发现、管理和监控集群中的各个node节点。Kubelet在启动时通过API Server注册节点信息,并定时向API Server发送节点信息。API Server接收到这些信息后,将这些信息写入etcd。存入etcd的节点信息包括节点健康状况、节点资源、节点名称、节点地址信息、操作系统版本、docker版本、kubelet版本等。节点健康状况包含“就绪(true)”、“未就绪(false)”和“未知(unknown)”三种。

    (1)Controller Manager 在启动时如果设置了—cluster-cidr参数,那么为每个没有设置spec.podCIDR的node生成一个CIDR地址,并用该CIDR设置节点的spec.PodCIDR属性,这样的目的是防止不同节点的CIDR地址发生冲突。
    (2)逐个读取节点的信息,多次尝试修改nodeStatusMap中的节点状态信息,将该节点信息和node controller的nodeStatusMap中保存的节点信息比较。如果判断中没有收到kubelet发送的节点信息、第一次收到节点kubelet发送的节点信息,或在该处理过程中节点状态变成非“健康”状态,则在nodeStatusMap中保存该节点的状态信息,并用node controller所在节点的系统时间作为探测时间和节点状态变化时间。
    如果判断出在某一段时间内没有收到节点的状态信息,则设置节点状态为“未知(unknown)”,并且通过api server保存节点状态。
    (3)逐个读取节点信息,如果节点状态变为非“就绪”状态,则将节点加入待删除队列,否则将节点从该队列中删除。如果节点状态为非“就绪”状态,且系统指定了Cloud Provider,则node controller调用Cloud Provider查看节点,若发现并节点故障,则删除etcd中的节点信息,并删除和该节点相关的pod等资源的信息。

    ResourceQuota controller

    作为容器集群的管理平台, kubernetes也提供了资源配额管理这一高级功能,资源配额管理确保指定的对象在任何时候都不会超量占用系统资源,避免了由于某些业务进程的设计或实现的缺陷导致整个系统运行紊乱甚至意外宕机,对整个集群的平稳运行和稳定性有非常重要的作用。
    目前kubernetes支持三个层次的资源配额管理:
    (1)容器级别,可以对CPU和内存的资源配额管理。
    (2)pod级别,可以对pod内所有容器的可用资源进行限制。
    (3)namespace级别,为namespace(可以用于多租户)级别的资源限制,包括:pod数量、replication Controller数量、service数量、ResourceQuota数量、secret数量、可持有的PV(persistent volume)数量。
    kubernetes的配额管理是通过准入机制(admission control)来实现的,与配额相关的两种准入控制器是LimitRanger和ResoureQuota,其中LimitRanger作用于pod和container上,ResourceQuota则作用于namespace上。此外,如果定义了资源配额,则scheduler在pod调度过程中也会考虑这一因素,确保pod调度不会超出配额限制。
    典型的资源控制流程如下图所示:

    namaspace controller

    用户通过API Server可以创建新的namespace并保存在etcd中,namespace controller定时通过api server读取这些namespace信息。如果namespace被API标识为优雅删除(设置删除期限,deletionTimestamp属性被设置),则将该namespace的状态设置为“terminating”并保存到etcd中。同时namespace controller删除该namespace下的serviceAccount、RC、Pod、Secret、PersistentVolume、ListRange、SesourceQuota和event等资源对象。
    当namespace的状态被设置为“terminating”后,由Adminssion Controller的NamespaceLifecycle插件来阻止为该namespace创建新的资源。同时,在namespace controller删除完该namespace中的所有资源对象后,Namespace Controller对该namespace执行finalize操作,删除namespace的spec.finalizers域中的信息。
    如果Namespace Controller观察到namespace设置了删除期限(即DeletionTimestamp属性被设置),同时namespacer 的spec.finalizers域值是空的,那么namespace controller将通过API Server删除该namespace资源。

    kubernetes安全控制

    ServiceAccount Controller和token Controller是与安全相关的两个控制器。ServiceAccount Controller在Controller Manager启动时被创建。它监听Service Account的删除事件和Namespace的创建、修改事件。如果在该Service Account的namespace中没有default Service Account,那么ServiceAccount Controller为该Service Account的namespace创建一个default ServiceAccount。
    在API Server的启动中添加“—admission_control=ServiceAccount”后,API Server在启动时会自己创建一个key和crt(/var/run/kubernetes/apiserver.crt和apiserver.key),然后在启动./kube-controller-manager时添加参数service_account_privatge_key_file=/var/run/kubernetes/apiserver.key,这样启动kubernetes master后,就会发现在创建Service Account时系统会自动为其创建一个secret。
    如果Controller Manager在启动时指定参数为service-account-private-key-file,而且该参数所指定的文件包含一个PEM-encoded的编码的RSA算法的私钥,那么,Controler Manager会创建token controller对象。

    Token controller

    token controller对象监听Service Account的创建、修改和删除事件,并根据事件的不同做不同的处理。如果监听到的事件是创建和修改Service Account事件,则读取该Service Account的信息;如果该Service Account没有Service Account Secret(即用于访问Api server的secret),则用前面提及的私钥为该Service Account创建一个JWT Token,将该Token和ROOT CA(如果启动时参数指定了该 ROOT CA)放入新建的secret中,将该新建的secret放入该Service Account中,同时修改etcd中Service Account的内容。如果监听到的事件是删除Service Account事件,则删除与该Service Account相关的secret。
    token controller对象同时监听secret的创建、修改和删除事件,并根据事件的不同做不同的处理。如果监听到的事件是创建和修改secret事件,那么读取该secret中annotation所指定的Service Account信息,并根据需要为该secret创建一个和其Service Account相关的token;如果监听到的事件是删除secret事件,则删除secret和相关的Service Account的引用关系。

    service controller&endpoint controller

    Kubernetes service是一个定义pod集合的抽象,或者被访问都看作一个访问策略,有时也被称为微服务。
    kubernetes中的service是种资源对象,各所有其他资源对象一样,可以通过API Server的POST接口创建一个新的实例。在下面的例子代码中创建了一个名为“MyServer”的Service,它包含一个标签选择器,通过该标签选择器选择所有包含标签为“app=MyApp”的pod作为该service的pod集合。Pod集合中的每个pod的80端口被映射到节点本地的9376端口,同时kubernetes指派一个集群IP(即虚拟IP)给该service。

    {
        “kind”: ”service”,
        “apiVersion”: ”v1”,
        “metadata”: {
            “name”: ”MyService”
        },
        “spec”: {
            “selector”: {
                “app”: ”MyApp”
            },
            “ports”: [
                {
                    “protocol”: ”TCP”,
                    “port”: 80,
                    “targetPort”: 9376
                }
            ]
        },
    }
    

    四.功能特性

    Service 集群访问流程(服务发现)

    在kubernetes集群中的每个node上都运行着一个叫“kube-proxy”的进程,该进程会观察master节点添加和删除“service”和“endpoint”的行为,如图中第1步所示。
    kube-proxy为每个service在本地主机上开一个端口(随机选择)。任何访问该端口的连接都被代理到相应的一个后端pod上。Kube-proxy根据round robin算法及service的session粘连(SessionAffinity)决定哪个后台pod被选中,如第2步所示。
    最后,如第3步所示,kube-proxy在本机的iptables中安装相应的规则,这些规则使得iptables将捕获的流量重定向到前面提及的随机端口。通过该端口流量再被kube-proxy转到相应的后端pod上。
    在创建了服务后,服务endpoint模型会创建后端pod的IP和端口列表(包含中endpoint对象中),kube-proxy就是从这个endpoint列表中选择服务后端的。集群内的节点通过虚拟IP和端口能够访问service后台的pod。
    在默认情况下,kubernetes会为server指定一个集群IP(或虚拟IP、cluster IP),但在某些情况下,希望能够自己指定该集群IP。为了给service指定集群IP,用户只需要在定义service时,在service的spec.clusterIP域中设置所需要的IP地址即可。

    Scheduler(调度)

    scheduler在整个kubernetes系统中承担了“承上启下”的重要功能,“承上”是指它负责接收Controller Manager创建的新pod,为其安排一个落脚的“家”——目标node;“启下”是指安置工作完成后,目标node上的kubelet服务进程接管后继工作,负责pod生命周期中的“下半生”。
    具体来说,scheduler的作用是将待调度的pod(API新创建的Pod、Controller Manager为补足副本而创建的pod等)按照特定的调度算法和调度策略绑定(binding)到集群中的某个合适的node上,并将绑定信息写入etcd中。在整个调度过程中涉及三个对象,分别是:待调度的pod列表、可用node列表、以及调度算法和策略。简单地说,就是通过调度算法调度,为待调度pod列表中的每个pod从node列表中选择一个最适合的node。
    随后,目标node上的kublet通过API Server监听到scheduler产生的pod绑定事件,然后获对应的取pod,下载image镜像,并启动容器。

    Scheduler(调度策略)

    scheduler当前提供的默认调度流程分为两步:
    (1)预选调度过程,即遍历所有目标node,筛选出符合要求的候选节点。为此kubernetes内置了多种预先策略(xxx predicates)供用户选择。
    (2)确定最优节点,在第一步的基础上,采用优先策略(xxx priority)计算出每个候选节点的积分,积分最高都胜出。
    scheduler的调度流程是通过插件方式加载的“调度算法提供者(AlgorithmProvider)”具体实现的。一个AlgorithmProvider其实就是包括了一组预选策略与一组优选策略的结构体,注册AlgorithmProvider的函数如下:
    func RegisterAlgorithmProvider(name string, predicateKeys, priorityKeys util.StringSet)
    它包含3个参数,name string 参数为算法名;
    predicateKeys参数为算法集合用到的预选策略集合
    priorityKeys 参数为算法用到的优选策略集合
    scheduler 中可用的预选策略包含7个,每个节点只有通过PodFitsPorts、PodFitsResources、NoDiskConflict、PodSelectorMatches、PodFitsHost 5个默认预先策略后,才能初步被选中,进入下一个流程。
    每个节点通过优选策略时都会算出一个得分,计算各项得分,最终选出得分值最大的节点作为优选的结果(也是调度算法的结果)。LeastRequestedPriority,选择资源消耗最小节点:
    (1)计算出所有备选节点上运行的pod和备选pod的CPU占用量totalMilliCPU
    (2)计算出所有备选节点上运行的pod和备选pod的内存占用量totalMomory
    (3)计算每个节点的得分,计算规则大致如下:
    score=int(((nodeCpuCapacity-totalMilliCPU)10)/nodeCpuCapacity+((nodeMemoryCapacity-totalMemory)10/nodeMemoryCapacity)/2)
    CalculateNodeLabelPriority,根据CheckNodeLabelPresence策略打分
    BalancedResourceAllocation,选择资源使用最均衡节点
    (1)计算出所有备选节点上运行的pod和备选pod的CPU占用量totalMilliCPU
    (2)计算出所有备选节点上运行的pod和备选pod的内存占用量totalMomory
    (3)计算每个节点的得分,计算规则大致如下:
    score=int(10-math.abs(totalMilliCPU/nodeCpuCapacity-totalMemory/nodeMemoryCapacity) * 10)

    节点管理

    节点管理包含节点的注册、状态上报、Pod管理、容器健康检查、资源监控等部分。

    节点注册

    在kubernetes集群中,在每个node节点上都会启动一个kubelet服务进程。该进程用于处理master节点下发到本节点的任务,管理pod及pod中的容器。每个kubelet进程会在API Server上注册节点自身信息,定期向master节点汇报节点资源使用情况,并通过cAdvisor监控容器和节点资源。
    节点通过设置kubelet的启动参数“—register-node”,来决定是否向API Server注册自己。如果该参数为true,那么kubelet将试着通过API Server注册自己。作为自注册,kubelet启动还包含下列参数:
    --api-servers,告诉kubelet API Server的位置;
    --kubeconfig,告诉kubelet在哪儿可以找到用于访问API Server的证书;
    --cloud-provider,告诉kubelet如何从云服务商(IAAS)那里读取到和自己相关的元数据。

    状态上报

    kubelet在启动时通过API Server注册节点,并定时向API Server发送节点新消息,API Server在接收到这些信息后,将这些信息写入etcd。通过kubelet的启动参数“—node-status-update-frequency”设置kubelet每隔多少时间向API Server报告节点状态,默认为10秒。

    Pod管理

    kubelet通过以下几种方式获取自身node上所要运行的pod清单:
    (1)文件:kubelet启动参数“--config”指定的配置文件目录下的文件。通过—file-check-frequency设置检查该文件目录的时间间隔,默认为20秒。
    (2)HTTP端点(URL):通过“—manifest-url”参数设置。通过—http-check-frequency设置检查该HTTP端点的数据时间间隔,默认为20秒。
    (3)API Server:kubelet通过API Server监听etcd目录,同步pod清单。
    所有以非API Server方式创建的pod都叫作static pod。Kubelet将static pod的状态汇报给API Server,API Server为static pod创建一个mirror pod和其相匹配。Mirror pod的状态将真实反映static pod的状态。当static pod被删除时,与之相对应的mirror pod也会被删除。Kubelet通过API Server client使用watch+list的方式监听“/registry/node/<当前node名称>”和“/registry/pods”目录,将获取的信息同步到本地缓存中。
    kubelet监听etcd,所有针对pod的操作将会被kubelet监听到。如果发现有新的绑定到本节点的pod,则按照pod清单的要求创建该pod。如果发现本地的pod被修改,则kubelet会做出相应的修改,如删除pod中的某个容器时,则通过docker client删除该容器。如果发现删除本节点的pod,则删除相应的pod,并通过docker client删除pod中的容器。
    kubelet读取监听到的信息,如果是创建和修改pod任务,则做如下处理:
    (1)为该pod创建一个数据目录。
    (2)从API Server读取该pod清单。
    (3)为该pod挂载外部卷(Extenal Volume)。
    (4)下载pod用到的secret。
    (5)检查已经运行在节点中的pod,如果该 pod没有容器或pause容器没有启动,则先停止pod里所有容器进程。如果在pod中有需要删除的容器,则删除这些容器。
    (6)用“kubernetes/pause”镜像为每个pod创建一个容器,该pause容器用于接管pod中所有其他容器的网络。
    (7)为pod中的每个容器做如下处理:
    为容器计算一个hash值,然后用容器的名字去docker查询对应容器的hash值。若查到容器,且两者hash值不同,则停止docker中容器进程,并停止与之关联的pause容器进程;若两者相同不做任何处理
    如果容器被中止了,且容器没有指定的restartPolicy(重启策略),则不做任何处理。
    调用docker client下载容器镜像,调用docker client运行容器。

    容器健康检查

    pod通过两类探针来检查容器的健康状态。一个是LivenessProbe探针,用于判断容器是否健康,告诉kubelet一个容器什么时候处于不健康的状态。如果LivenessProbe探针探测到容器不健康,则kubelet将删除容器,并根据容器的重启策略做相应的处理。如果一个容器不包含LivenessProbe探针,那么kubelet认为该容器的LivenessProbe探针返回的值永远是“success”.另一类是ReadinessProbe探针,用于判断容器是否启动完成,且准备接收请求。如果ReadinessProbe探针检测到失败,则pod的状态将被修改。Endpoint controller将从service的endpoint中删除包含该容器所在pod的IP地址的endpoint条目。

    展开全文
  • Kubernetes综述

    2019-07-29 10:31:16
    它的功能和架构设计自始至终地遵循了这一指导思想,构建在Kubernetes上的系统不仅可以独立运行在物理机、虚拟机集群或者企业私有云上,也可以被托管在公有云上。 kubernetes的另一个亮点是自动化。在Kubernetes的...

    Kubernetes综述

    简单总结

    在这里插入图片描述
    目前开源的Kubernetes(简称k8s)调度平台,实现基于Google内部的Borg,为容器化应用提供部署、动态伸缩、升级、编排管理等一系列功能。采用Master-Node的分布式架构方式。Kubernetes最小的调度单元为Pod,一个Pod可以包含多个容器,同一个Pod共享网络命令空间。

    Master介绍

    1. 主要作用
    2. 核心组件包括:
      • kube-apiserver:提供RESTful接口,是集群控制的入口。
      • kube-controller-manager:集群所有资源对象的控制中心。
      • kube-scheduler:负责所有容器资源调度的组件。
      • etcd:负责集群所有的数据存储。
      • coreDNS:负责集群内部所有服务的DNS解析。

    Node介绍

    1. 主要作用:Node被称为工作节点,所有的用户应用容器都在其上进行调度工作。
    2. 核心组件包括:
      • kubelet:负责Node节点的所有容器生命周期管理(Pod的创建、启动、销毁和监控),通过Kubernetes的CRI(容器运行时接口)与Docker、rkt等容器管理引擎进行交互。
      • kube-proxy:负责为Pod创建代理服务,实现路由转发,从而实现Kubernetes层的虚拟转发网络。
      • Docker:容器管理引擎之一。

    前言

    Kubernetes是将“一切以服务(Service)为中心,一切围绕服务运转”作为指导思想的创新型产品,这是它的一个亮点。它的功能和架构设计自始至终地遵循了这一指导思想,构建在Kubernetes上的系统不仅可以独立运行在物理机、虚拟机集群或者企业私有云上,也可以被托管在公有云上。

    kubernetes的另一个亮点是自动化。在Kubernetes的解决方案中,一个服务可以自我扩展、自我诊断,并且容易升级,在收到服务扩容的请求后,Kubernetes会触发调度流程,最终在选定的目标节点上启动相应数量的服务实例副本,这些服务实例副本在启动成功后会自动加入负载均衡器中并生效,整个过程无需额外的人工操作。另外,Kubernetes会定时巡查每个服务的所有实例的可用性,确保服务实例的数量始终保持为预期的数量,当它发现某个实例不可用时,会自动重启该实例或者在其他节点上重新调度、运行一个新实例,这样,一个复杂的过程无需人工干预即可全部自动完成。试想一下,如果一个包括几十个节点且运行着几万个容器的复杂系统,其负载均衡、故障检测和故障修复等都需要人工介入进行处理,其工作量将多大。

    通常,我们会把Kubernetes看做Docker的上层架构,就好像Java与J2EE的关系一样:J2EE是以Java为基础的企业级软件架构,Kubernetes则以Docker为基础打造了一个云计算时代的全新分布式系统架构。但Kubernetes与Docker之间还存在着更为复杂的关系,从表面上看,似乎Kubernetes离不开Docker,但实际上在Kubernetes的架构中,Docker只是其目前支持的两种低层容器技术之一,另一种容器技术则是Rocket,Rocket是CoreOS推出的竞争产品。

    Kubernetes是什么

    • 首先,它是一个全新的基于容器技术的分布式架构领先方案。确切的说,Kubernetes是谷歌严格保密十几年的秘密武器——Borg的一个开源版本。Borg是谷歌的一个久负盛名的内部使用的大规模集群管理系统,它基于容器技术,目的是实现资源管理的自动化,以及跨多个数据中心的资源利用率的最大化。
    • 其次,如果我们的系统设计遵循了Kubernetes的设计思想,那么传统系统架构中那些和业务没有多大关系的底层代码或功能模块,都可以立刻从我们的视线中消失,我们不必再费心于负载均衡器的选型和部署实施问题,不必再考虑引入或自己开发一个复杂的服务治理框架,不必再头疼于服务监控和故障处理模块的开发。总之,使用Kubernetes提供的解决方案,我们不仅节省了不少于30%的开发成本,还可以将精力更加集中于业务本身,而且由于Kubernetes提供了强大的自动化机制,所以系统后期的运维难度和运维成本大幅度降低。
    • 然后,Kubernetes是一个开放的开发平台。与J2EE不同,它不局限于任何一种语言,没有限定任何编程接口,所有不论是用Java、Go、C++还是用Python编写的服务,都可以被映射为Kubernetes的Service(服务),并通过标准的TCP通信协议进行交互。此外,Kubernetes平台对现有的编程语言、编程框架、中间件没有任何侵入性,因此现有的系统也很容易改造升级并迁移到Kubernetes平台上。
    • 最后,Kubernetes是一个完备的分布式系统支撑平台。Kubernetes具有完备的集群管理能力,包括多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和服务发现机制、内建的智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制,以及多粒度的资源配额管理能力。同时,Kubernetes提供了完善的管理工具,这些工具涵盖了包括开发、部署测试、运维监控在内的各个环节。

    因此,Kubernetes是一个全新的基于容器技术的分布式架构解决方案,并且是一个一站式的完备的分布式系统开发和支撑平台。

    在Kubernetes中,Service是分布式集群架构的核心,一个Service对象拥有如下关键特性

    • 拥有唯一指定的名称(比如mysql-server)。
    • 拥有一个虚拟IP(Cluster IP、Service IP 或 VIP)和端口号
    • 能够提供某种远程服务能力
    • 映射到提供这种服务能力的一组容器应用上

    Service的服务进程目前都基于Socket通信方式对外提供服务,比如Redis、Memcache、MySQL、Web Server,或者是实现了某个具体业务的特定TCP Server进程。虽然一个Service通常由多个相关的服务进程提供服务,每个服务进程都有一个独立的Endpoint(IP+Port)访问点,但Kubernetes能够让我们通过Service(虚拟Cluster IP + Service Port)连接到指定的Service。有了Kubernetes内建的透明负载均衡和故障恢复机制,不管后端有多少服务进程,也不管某个服务进程是否由于发生故障而被重新部署到其他机器,都不会影响对服务的正常调用。更重要的是,这个Service本身一旦创建就不再变化,这意味着我们再也不用为Kubernates集群中服务的IP地址变来变去的问题而头疼了。

    容器提供了强大的隔离功能,所以有必要把为Service提供服务的这组进程放入容器中进行隔离。为此,Kubernetes设计了Pod对象,将每个服务进程都包装到相应的Pod中,使其成为在Pod中运行的一个容器(Container)。为了建立Service和Pod间的关联关系,Kubernetes首先给每个Pod都贴上一个标签(Label),给运行MySQL的Pod贴上name=mysql标签,给运行PHP的node贴上name=php标签,然后给相应的Service定义标签选择器(Label Selector),比如MySQL Service的标签选择器的选择条件为name=mysql,意为该Service要作用于所有包含name=mysql Label的Pod。这样一来,就巧妙解决了Service与Pod的关联问题。

    这里先简单介绍Pod的概念。首先,Pod运行在一个被称为节点(Node)的环境中,这个节点既可以是物理机,也可以是私有云或者公有云中的一个虚拟机,通常在一个节点上运行几百个Pod;其次,在每个Pod中都运行着一个特殊的被称为Pause的容器,其他容器则为业务容器,这些业务容器共享Pause容器的网络栈和Volume挂载卷,因此它们之间的通信和数据交换更为高效,在设计时我们可以充分利用这一特性将一组密切相关的服务进程放入同一个Pod中;最后,需要注意的是,并不是每个Pod和它里面运行的容器都能被映射到一个Service上,只有提供服务(无论是对内还是对外)的那组Pod才会被映射为一个服务。

    在集群管理方面,Kubernetes将集群中的机器划分为一个Master和一些Node。在Master上运行着集群管理相关的一组进程 kube-apiserverkube-controller-managerkube-scheduler,这些进程实现了整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控和纠错等管理功能,并且都是自动完成的。Node作为集群中的工作节点,运行真正的应用程序,在Node上Kubernetes管理的最小运行单元是Pod。在Node上运行着Kubernetes的kubeletkube-proxy服务进程,这些服务进程负责Pod的创建、启动、监控、重启、销毁,以及实现软件模式的负载均衡器。

    最后,看看传统的IT系统中服务扩容和服务升级这两个难题,以及Kubernetes所提供的全新解决思路。服务的扩容设计资源分配(选择哪个节点进行扩容)、实例部署和启动等环节,在一个复杂的业务系统中,这两个难题基本上靠人工一步步操作才得以解决,费时费力又难以保证实施质量。

    在kubernetes集群中,只需为需要扩容的Service关联的Pod创建一个RC(Replication Controller),服务扩容以及服务升级等令人头疼的问题都能迎刃而解。在一个RC定义文件中包括以下3个关键信息。

    • 目标Pod的定义。
    • 目标Pod需要运行的副本数量(Replicas)。
    • 要监控的目标Pod的标签。

    在创建好RC(系统将自动创建好Pod)后,Kubernetes会通过在RC中定义的Label筛选出对应的Pod实例并实时监控其状态和数量,如果实例数量少于定义的副本数量,则会根据在RC中定义的Pod模板创建一个新的Pod,然后将此Pod调度到合适的Node上启动运行,直到Pod实例的数量达到预定目标。这个过程完全是自动化的,无需人工干预。有了RC,服务扩容就变成一个纯粹的简单数字游戏了,只需修改RC中的副本数量即可。后序的服务升级也将通过修改RC来自动完成。

    为什么要用Kubernetes

    使用Kubernetes会收获哪些好处呢?

    首先,可以“轻装上阵”地开发复杂系统。以前需要很多人一起分工协作才能设计、实现和运维的分布式系统,在采用Kubernetes解决方案之后,只需一个精悍的小团队就能轻松应对。在这个团队里,只需一名架构师负责系统中服务组建的架构设计,几名开发工程师负责业务代码的开发,一名系统兼运维工程师负责Kubernetes的部署和运维,因为Kubernetes已经帮我们做了很多。

    其次,可以全面拥抱微服务架构。微服务架构的核心是将一个巨大的单体应用分解为很多小的互相连接的微服务,一个微服务可能由多个实例副本支撑,副本的数量可以随着系统的负荷变化进行调整。微服务架构使得每个服务都可以独立开发、升级和扩展,因此系统具备很高的稳定性和快速迭代能力,开发者也可以自由选择开发技术。谷歌、亚马逊、eBay、Netflix等大型互联网公司都采用了微服务架构,谷歌更是将微服务架构的基础设施直接打包到Kubernetes解决方案中,让我们可以直接应用微服务架构解决复杂业务系统的架构问题。

    再次,可以随时随地的将系统整体“搬迁”到公有云上。Kubernetes最初的设计目标就是让用户的应用运行在谷歌自家的公有云GCE中,华为云(CCE)、阿里云(ACK)、和腾讯云(TKE)先后宣布支持Kubernetes集群。同时,在Kubernetes的架构方案中完全屏蔽了底层网络的细节,基于Service的虚拟IP地址(Cluster IP)的设计思路让架构与底层的硬件拓扑无关,我们无需改变运行期的配置文件,就能将系统从现有的物理机环境无缝迁移到公有云上。

    然后,Kubernetes内在的服务弹性扩容机制可以让我们轻松应对突发容量。在服务高峰期,我们可以选择在公有云中快速扩容某些Service的实例副本以提升系统的吞吐量,这样不仅节省了公司的硬件投入,还大大改善了用户体验。12306在客流高峰期(如节假日)就租用了阿里云进行分流。

    最后,Kubernetes系统架构超强的横向扩容能力可以让我们的竞争力大大提升。对于互联网公司来说,用户规模等价于资产,因此横向扩容能力是衡量互联网业务系统竞争力的关键指标。我们利用Kubernetes提供的工具,不用修改代码,就能将一个Kubernetes集群从只包含几个Node的小集群平滑扩展到拥有上百个Node的大集群,甚至可以在线完成集群扩容。只要微服务架构设计的合理,能够在多个云环境中进行弹性伸缩,系统就能够承受大量用户并发访问带来的巨大压力。

    展开全文
  • 涵盖Kubernetes的指南,包括使您成为更好,更高效的Kubernetes开发人员的应用程序和工具。 注意:使用此方便的扩展程序,您可以轻松地将此markdown文件转换为PDF。 目录 使用kubeadm构建高可用性(HA)集群。 资料...
  • Kubernetes上的OpenWhisk部署 Apache OpenWhisk是一个开放源代码的分布式无服务器平台,可以执行功能(fx)以响应各种规模的事件。 OpenWhisk平台支持一种编程模型,在该模型中,开发人员可以使用任何受支持的编程...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 72,829
精华内容 29,131
关键字:

最适合kubernetes的系统