- K8s官方文档
K8s怎么来的?
- 十几年来,谷歌内部使用的大规模集群管理系统是Brog,基于容器技术实现了资源管理的自动化和跨多个数据中心的资源利用率的最大化,这项技术在外界保有盛名,但其内部员工签署了保密协议,即便离职也不能泄露Borg的内部设计,所以外界也无法了解更多信息。
- 2015年4月,K8s被谷歌首次公开,一经开源便迅速火热的称霸容器领域。
K8s火在哪儿?
- 具备很大的参考价值,提高工作效率。参考K8s底层设计思想,可以不再纠结前期业务架构选型和部署实施问题,也不必再头疼于服务监控和故障处理模块的开发,节省开发成本,可以更好的专注业务。
- 具备强大的自动化机制,降低后期的运维难度和运维成本。
- 开源开放的开发平台,编程语言和接口不局限。Java、Go、C++、Python编写的服务都可以被映射为K8s的Service服务,并通过标准的TCP通信协议进行交互。
- 便于传统架构系统迁移。K8s平台对现有的编程语言、编程框架、中间件没有任何侵入性,现有的系统很容易改造升级并迁移到Kubernetes平台上。
- 功能全面,具有完备的集群管理能力。
- 多层次的安全防护和准入机制。多租户应用支撑能力、透明的服务注册和服务发现机制。
- 内建的智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力。
- 可扩展的资源自动调度机制,多粒度的资源配额管理能力。
- 提供完善的管理工具,包括开发、部署测试、运维监控在内的各个环节。
为什么要用K8s?
- 技术先进,涵盖了架构、研发、部署、运维等全系列软件开发流程,是互联网产品及大规模系统的必选方案。
- 2020年3月,VMware官方发布vSphere 7,通过K8s重构底层,使得用户能够以ESXi管理VM虚拟机的方式来运用K8s的能力。此举一时轰动整个软件领域,也说明了K8s的重要性。
- 云原生技术的底层核心,市面上几乎所有提供云基础设施的公司都以原生形式将K8ss作为底层平台。
- 各个大厂争先恐后的引入K8s,学习K8s已是势在必行的趋势。
- 阿里云容器服务K8s版ACK。
- 腾讯自研的TKEx容器平台。
- 百度云容器引擎、深度学习平台PaddlePaddle。
- 华为云的容器引擎CCE。
使用K8s的好处:
- 减少时间人力成本,团队可以“轻装上阵”。K8s可以帮我们做很多事,团队里只需要一名架构师,几个开发人员,一个运维。
- 可以将以往微服务架构进行升级,加固增强。
- 方便系统迁移至公有云,因为K8s最初的设计目标就是让用户的应用运行在谷歌自家的公有云GCE中。
- 可以轻松应对突发流量,节省营建投入成本和人力维护人本。在服务高峰期,我们常常遇到数据暴增导致服务器宕机,而K8s内建的服务弹性扩容机制就可以很好的处理这种情形,可以选择在公有云中快速扩容某些Service的实例副本以提升系统的吞吐量。
- 系统架构横向扩容能力异常强大,可以提高业务系统的竞争力。
容器集群管理系统:常见容器编排系统:
- Kubernetes
- Swarm
- Mesos Marathon
资源对象分类:
- 宏观上可以分为两大类:某种资源的对象、与资源对象相关的事物与动作。
- 某种资源的对象:节点(Node)、Pod、服务(Service)、存储卷(Volume)。
- 与资源对象相关的事物与动作:标签(Label)、注解(Annotation)、命名空间(Namespace)、部署(Deployment)、HPA、PVC、PV。
- 也可以细分为:集群类、应用类、存储类、安全类。
资源对象通用属性:
- 版本,在版本信息里包括了此对象所属的资源组,一些资源对象的属性会随着版本的升级而变化,在定义资源对象时要特别注意这一点。
- 类别,该属性用于定义资源对象的类型。
- 资源对象的元数据,包括名称、标签、注解三个属性。
- 资源对象的名称要唯一。
- 资源对象的标签是很重要的数据,可以通过标签来表明资源对象的特征、类别,通过标签筛选不同的资源对象并实现对象之间的关联、控制或协作功能。
- 注解可被理解为一种特殊的标签,不过更多地是与程序挂钩,通常用于实现资源对象属性的自定义扩展。
如何定义资源对象?
- 可以通过kubectl工具执行增、删、改、查等操作,也可以通过API调用。
- 采用YAML或JSON格式声明资源对象,每个资源对象都有自己的特定结构定义,并且统一保存在etcd非关系型数据库中。
如何学习这块知识?
- K8s发展迅速,时至今日已到1.27版本,期间有部分的资源对象都被舍弃了,同时也有新资源对象出来,所以学习资源对象这块知识时先学核心资源,再慢慢扩展学习,一口气吃不下所有的,因为每个资源对象之间的关系错综复杂,需要彻底搞清之间的联系才能更好的在工作中运维使用。
- 有些资源对象是有生命周期和相对应的状态的,从创建使用到维护的过程中都非常多的细节和状态变更,所以运维需要重点抓着一块知识,方便故障排查。比如Pod,通过kubectl创建一个Pod并将其提交到系统中后,它就处于等待调度的状态,调度成功后为Pending状态,等待容器镜像下载和启动、启动成功后为Running状态,正常停止后为Succeeded状态,非正常停止后为Failed状态。
基本了解:
- K8s集群常常由Master和Node组成,这里的master是指集群的控制节点,node是指工作节点。
- 每个K8s集群中都需要有一个或一组被称为Master的节点,用来负责整个集群的管理和控制,通常占据一个独立的服务器,在高可用部署中至少使用3台服务器。
- Master节点是整个集群的“核心大佬”,所有的操作都需要经过它。若它发生宕机或者不可用,那么对集群内容器应用的管理都将无法实施。
Master节点上的核心进程:
kube-apiserver:集群的“最高统治者”,也是集群的统一入口,各组件协调者,提供HTTP RESTful API接口的主要服务,所有对象资源的增、删、改、查和监听操作都交给API Server处理后再提交给Etcd存储。
kube-controller-manager:资源控制器,资源对象的“大总管”,负责所有资源对象的自动化控制,处理集群中常规后台任务。
kube-scheduler:资源调度器,根据调度算法为新创建的Pod选择一个Node节点,可以任意部署,可以部署在同一个节点上,也可以部署在不同的节点上。
etcd:分布式键值存储系统,用于保存集群状态数据。部署单节点master集群时在master节点上,部署高可用集群时建议单独采用三台机器安装。
Node节点上的核心进程:
- kubelet:是Master在Node节点上的Agent,管理本机运行容器的生命周期,比如创建容器、Pod挂载数据卷、下载secret、获取容器和节点状态等工作。kubelet将每个Pod转换成一组容器。
- kube-proxy:在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作。
- 容器运行时:容器引擎,运行容器, 常见的有docker、containerd、podman。负责本机的容器创建和管理。
注意事项:
- K8s集群中,除Mater外的其他服务器都被称为Node,较早版本中也被称为Minion,是K8s集群中的工作负载节点,每个Node都会被Master分配一些工作负载(Docker容器),当某个Node宕机时,其上的工作负载会被Master自动转移到其他Node上。
- 当一台机器上已安装、配置和启动了以下核心进程,那么就可以将这台机器作为Node节点动态增加到K8s集群中。
- 默认情况下kubelet会向Master注册自己,当Node被纳入集群管理范畴,kubelet进程就会定时向Master汇报自身的情报,例如操作系统、主机CPU和内存使用情况,以及当前有哪些Pod在运行等,这样Master就可以获知每个Node的资源使用情况,并实现高效均衡的资源调度策略。
- 当某个Node在超过指定时间不上报信息时,会被Master判定为“失联”,该Node的状态就被标记为不可用(Not Ready),Master随后会触发“工作负载大转移”的自动流程。
命名空间作用:
- 很多情况下,都是用命名空间来实现多租户的资源隔离,每个命名空间都是相互独立的存在,属于不同命名空间的资源对象从逻辑上相互隔离,方便管理。
- 在每个K8s集群安装完成且正常运行之后,Master会自动创建两个命名空间,一个是默认的(default)、一个是系统级的(kube-system)。
- default命名空间:若用户创建的资源对象时没有指定命名空间,则被默认存放在default命名空间中。
- kube-system命名空间:系统相关的资源对象,比如网络组件、DNS组件、监控类组件等,都被安装在kube-system命名空间中。
- Node的基本信息:名称、标签、创建时间等。
- Node当前的运行状态:Node启动后会做一系列自检工作,比如磁盘空间是否不足(DiskPressure)、内存是否不足(MemoryPressure)、网络是否正常(NetworkUnavailable)、PID资源是否充足(PIDPressure)。在一切正常时才设置Node为Ready状态(Ready=True),表示Node处于健康状态,Master就可以在其上调度新的任务了(如启动Pod)。
- Node的主机地址与主机名。
- Node上的资源数量:描述Node可用的系统资源,包括CPU、内存数量、最大可调度Pod数量等。
- Node可分配的资源量:描述Node当前可用于分配的资源量。
- 主机系统信息:包括主机ID、系统UUID、Linux Kernel版本号、操作系统类型与版本、Docker版本号、kubelet与kube-proxy的版本号等。
- 当前运行的Pod列表概要信息。
- 已分配的资源使用概要信息,例如资源申请的最小、最大允许使用量占系统总量的百分比。
- Node相关的Event信息。
3.查看default命名空间下的pod,不指定命名空间查询时就是查的default命名空间下的。
4.查看kube-system命名空间下的pod。
一、Pod
- pod是K8s中最小单元,里面包含一个或多个容器,每组pod都有一个pause容器,简称po。
- pause容器可以让多个业务容器共享它的IP和挂载的volume,可以解决容器间的通信问题和文件共享问题。
- K8s集群中任意一个Pod里的容器与另外主机上的Pod容器都能够直接通信。
- pod分两种,普通Pod和静态Pod。
- 普通Pod一旦被创建,就会被放入etcd中存储,随后就被调度到某个Node节点上并绑定,该Pod被对应的Node上的kubelet进程实例化成一组相关的Docker容器并启动。
- 静态pod没被存放在K8ss的etcd中,而是被存放在某个具体的Node上的一个具体文件中,并且只能在此Node上启动、运行。
- 默认情况下,当Pod里的某个容器停止时,K8s默认的重启策略会自动检测到这个问题并且重新启动这个pod里的所有容器。若pod所在的Node节点宕机,就会将这个Node上的所有Pod都重新调度到其他节点上。
二、Service
- Service指的是无状态服务,与pod关系最为紧密,简称svc。
- svc具有一个全局唯一的虚拟ClusterIP地址,当svc被创建时,K8s会自动为它分配一个可用的ClusterIP地址,在它整个生命周期中,ClusterIP地址都不会改变,客户端可以通过这个虚拟IP地址+服务的端口直接访问该服务。
- 实际业务中,通过分析、识别并建模系统中的所有服务为微服务svc,系统最终由多个提供不同业务能力而又彼此独立的微服务单元组成,服务之间通过TCP/IP进行通信,从而形成强大又灵活的弹性网格,拥有强大的分布式能力、弹性扩展能力、容错能力。
三、Pod Volume
- Pod Volume的作用类似Docker Volume,是被定义在Pod上,然后被各个容器挂载到自己的文件系统中的。
- Volume简单来说就是被挂载到Pod里的文件目录。
四、Endpoint
- 简称ep,是svc与pod的关联者。
- 在定义pod容器的端口时产生的一个概念,代表此Pod里的一个服务进程的对外通信地址。
- 一个Pod也可以存在具有多个ep的情况,比如把Tomcat定义为一个Pod时,可以对外暴露管理端口与服务端口这两个ep。
五、Event
六、Label与标签选择器
- 一个Label是由用户自定义一个key=value的键值对,可以被附加到各种资源对象上,例如Node、Pod、Service、Deployment等,一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上。
- 标签的出现是为了灵活、方便地进行资源分配、调度、配置、部署等管理工作,通常在创建资源对象时定义,也可以在对象创建后动态添加或删除。而Label Selector(标签选择器)可以通过查询和筛选拥有某些Label的资源对象,Kubernetes通过这种方式实现了类似SQL的简单又通用的对象查询机制。
- name=redis-slave:匹配所有具有name=redis-slave标签的资源对象。
- env !=production:匹配所有不具有env=production标签的资源对象。
- name in(redis-master,redis-slave):匹配所有具有name=redis-master标签或者name=redis-slave标签的资源对象。
- name not in(php-frontend):匹配所有不具有name=phpfrontend标签的资源对象。
七、Deployment
- 简称deploy,是用来部署和管理Pod的。
- 当pod所在的节点发生宕机事件,K8s会第一时间观察到这个故障,并自动创建一个新的Pod对象,将其调度到其他合适的节点上,K8s会实时监控集群中目标Pod的副本数量,并且尽力与deploy中声明的replicas数量保持一致。
八、ReplicaSet
九、StatefulSet
- 简称sts,是专门针对有状态应用部署产生的。deploy只能处理无状态应用,当遇到mysql、kafka这类有状态应用时就玩不了了,此时sts就可以很好地解决这个问题。
- 无状态:deploy控制器设计原则是,管理的所有Pod一模一样,提供同一个服务,也不考虑在哪台Node运行,可随意扩容和缩容。这种应用称为“无状态”。例如Web服务集群,每个工作节点上都有一个nginx容器,它们之间不需要互相业务“交流”,具备这个特点的应用就是“无状态”。
- 有状态:像分布式应用需要部署多个实例,实例之间往往有依赖关系,例如主从关系、主备关系,这种应用称为“有状态”,例如MySQL主从、Etcd集群。
- 还有一个sts的进化版本资源对象——Kubernetes Operator框架,是面向K8s平台开发者的。开发可以借助Operator框架提供的API更方便地开发一个类似StatefulSet的控制器。在这个控制器里,开发者通过编码方式实现对目标集群的自定义操控,包括集群部署、故障发现及集群调整等方面都可以实现有针对性的操控,从而实现更好的自动部署和智能运维功能。
十、Job
- 可以批处理应用,特点是一个或多个进程处理一组数据(图像、文件、视频等),在这组数据都处理完成后,批处理任务自动结束。
- Job生成的Pod副本是不能自动重启的,对应Pod副本的restartPolicy都被设置为Never,因此,当对应的Pod副本
都执行完成时,相应的Job也就完成了控制使命。后来K8s增加了CronJob,可以周期性地执行某个任务。十一、ConfigMap
- 简称cm,是用来保存配置项(key=value)的一个Map,可以解决分布式应用需要在不同node节点上依靠静态配置文件启动问题。
- 用户将配置文件的内容保存到cm中,文件名可作为key,value就是整个文件的内容,多个配置文件都可被放入同一个cm。
- 创建应用时,在Pod里将cm定义为特殊的Volume进行挂载。当Pod被调度到某个具体Node上时,cm里的配置文件会被自动还原到本地目录下,然后映射到Pod里指定的配置目录下,这样用户的程序就可以无感知地读取配置了。
- 在cm的内容发生修改后,K8s会自动重新获取cm的内容,并在目标节点上更新对应的文件。
十二、Secret
- secret是用来存敏感信息的,比如数据库的用户名和密码、应用的数字证书、Token、SSH密钥及其他需要保密的敏感配置。
- Secret中的数据要求以BASE64编码格式存放,BASE64编码并不是加密的,在Kubernetes 1.7版本以后,Secret中的数据才可以以加密的形式进行保存,更加安全。
十三、horizontalpodautoscaler
- 简称pha,可以自动控制Pod数量的增加或减少。
- K8s内置了基于Pod的CPU利用率进行自动扩缩容的机制,可以通过追踪分析指定deploy控制的所有目标Pod的负载变化情况,来确定是否需要有针对性地调整目标Pod的副本数量。
十四、Vertical Pod Autoscaler
- 简称VPA,可以垂直Pod自动扩缩容,它根据容器资源使用率自动推测并设置Pod合理的CPU和内存的需求指标,从而更加精确地调度Pod,实现整体上节省集群资源的目标,因为无须人为操作,因此也进一步提升了运维自动化的水平。
- 特性新颖,但不能与HPA共同操控同一组目标Pod,可以关注。
一、静态存储Volume
- K8s中的Volume被定义在Pod上,被一个Pod里的多个容器挂载到具体的文件目录下。
- Volume与Pod的生命周期相同,但与容器的生命周期不相关,当容器终止或者重启时,Volume中的数据也不会丢失。
- K8s提供了非常丰富的Volume类型供容器使用,例如临时目录、宿主机目录、共享存储。
- emptyDir临时目录:
- 用于某些应用程序运行时所需的临时目录,且无须永久保留。
- 长时间任务执行过程中使用的临时目录。
- 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)。
- 在默认情况下,emptyDir使用的是节点的存储介质,例如磁盘或者网络存储。还可以使用emptyDir.medium属性,把这个属性设置为“Memory”,就可以使用更快的基于内存的后端存储了。需要注意的是,这种情况下的emptyDir使用的内存会被计入容器的内存消耗,将受到资源限制和配额机制的管理。
- hostPath宿主机目录:
- 在容器应用程序生成的日志文件需要永久保存时,可以使用宿主机的高速文件系统对其进行存储。
- 需要访问宿主机上Docker引擎内部数据结构的容器应用时,可以通过定义hostPath为宿主机/var/lib/docker目录,使容器内部的应用可以直接访问Docker的文件系统。
- 在不同的Node上具有相同配置的Pod,可能会因为宿主机上的目录和文件不同,而导致对Volume上目录和文件的访问结果不一致。
- 如果使用了资源配额管理,则K8s无法将hostPath在宿主机上使用的资源纳入管理。
- 公有云Volume:
- 公有云提供的Volume类型包括谷歌公有云提供的GCEPersistentDisk、亚马逊公有云提供的AWS Elastic Block Store(EBSVolume)等。
- 当我们的Kubernetes集群运行在公有云上或者使用公有云厂家提供的Kubernetes集群时,就可以使用这类Volume。
- 其他类型的Volume:
- iscsi:将iSCSI存储设备上的目录挂载到Pod中。
- nfs:将NFS Server上的目录挂载到Pod中。
- glusterfs:将开源GlusterFS网络文件系统的目录挂载到Pod中。
- rbd:将Ceph块设备共享存储(Rados Block Device)挂载到Pod中。
- gitRepo:通过挂载一个空目录,并从Git库克隆(clone)一个git repository以供Pod使用。
- configmap:将配置数据挂载为容器内的文件。
- secret:将Secret数据挂载为容器内的文件。
二、动态存储PVC、PV、SC
- 由于上面的静态存储有很多弊端,比如配置参数烦琐,存在大量手工操作,还需要预定义的静态Volume可能不符合目标应用的需求,比如容量问题、性能问题,所以就出现了动态自动化存储。
- 动态存储是通过一组资源对象组合来实现的,包括Persistent Volume(pv)、StorageClass(sc)和PVC。
- PV:表示由系统动态创建(dynamically provisioned)的一个存储卷,可以被理解成K8s集群中某个网络存储对应的一块存储,它与Volume类似,但PV并不是被定义在Pod上的,而是独立于Pod之外定义的。PV目前支持的类型主要有gcePersistentDisk、AWSElasticBlockStore、AzureFile、AzureDisk、FC(Fibre Channel)、NFS、iSCSI、RBD(Rados Block Device)、CephFS、Cinder、GlusterFS、VsphereVolume、Quobyte Volumes、VMware Photon、Portworx Volumes、ScaleIO Volumes、HostPath、Local等。
- StorageClass:用来描述和定义某种存储系统的特征。
- PVC:表示应用希望申请的PV规格。
- 工作中,几乎所有人都会接触到k8s集群,例如开发、测试、运维。每个人拥有的k8s集群操作权限是不能一样的,只有通过认证的用户才能通过K8s的API Server查询、创建及维护相应的资源对象。
- K8s里的用户分类:
- 针对应用的Service Account用户账号,简称sa。我们开发的Pod应用需要通过API Server查询、创建及管理其他相关资源对象。
- 针对客户端的普通用户。如kubectl命令行工具,由指定的集群管理员使用。
一、RBAC
- rbac是sa、role、rolebinding共同实现的,role定义角色,赋予角色权限;sa绑定role,用户就具备了对应权限。
- sa是通过Secret来保存对应的用户(应用)身份凭证,这些凭证信息有CA根证书数据(ca.crt)和签名后的Token信息(Token)。在Token信息中就包括了对应的sa的名称,因此API Server通过接收到的Token信息就能确定sa的身份。
- Role资源对象包括Role与ClusterRole两种类型的角色。角色定义了一组特定权限的规则,比如可以操作某类资
源对象。局限于某个命名空间的角色由Role对象定义,作用于整个K8s集群范围内的角色则通过ClusterRole对象定义。- rolebinding是将Role与用户绑定,进行用户授权。
- sa有命名空间的区分,每个命名空间中都会创建一个默认的名称为default的sa,只能被它所在命名空间中的Pod使用。
- 用户创建一个Pod时,Pod会绑定对应命名空间中的default这个sa作为其“公民身份证”。当Pod里的容器被创建时,K8s会把对应的Secret对象中的身份信息(ca.crt、Token等)持久化保存到容器里固定位置的本地文件中,因此当容器里的用户进程通过K8s提供的客户端API去访问API Server时,这些API会自动读取这些身份信息文件,并将其附加到HTTPS请求中传递给API Server以完成身份认证逻辑。此时就通过rbac对用户进行授权,然后就可以访问到对应的资源对象了。
二、NetworkPolicy
- 用NetworkPolicy是一种关于Pod间相互通信,以及Pod与其他网络端点间相互通信的安全规则设定。
- 默认情况下,集群内的所有pod都可以互相通信,这样会导致与我不相干的业务我也能访问,不安全,所以实际工作中需要通过标签来设置一定的网络策略进行限制隔离Pod,提高安全性。