笔者今年9月从端侧开发转到后台开发,第一个系统开发任务就强依赖了K8S,加之项目任务重、排期紧,必须马上对K8S有概念上的了解。然而,很多所谓“K8S入门\概念”的文章看的一头雾水,对于大部分新手来说并不友好。经历了几天痛苦地学习之后,回顾来看,K8S根本不复杂。于是,决心有了这一系列的文章:一方面希望对新手同学有帮助;另一方面,以文会友,希望能够有机会交流讨论技术。
本文组织方式:
1.K8S是什么,即作用和目的。涉及K8S架构的整理,Master和Node之间的关系,以及K8S几个重要的组件:APIServer、Scheduler、Controller、etcd等。2.K8S的重要概念,即K8S的API对象,也就是常常听到的Pod、Deployment、Service等。3.如何配置kubectl,介绍kubectl工具和配置办法。4.如何用kubectl部署服务。5.如何用kubectl查看、更新/编辑、删除服务。6.如何用kubectl排查部署在K8S集群上的服务出现的问题
I.K8S概览1.1K8S是什么?K8S是Kubernetes的全称,官方称其是:
Kubernetesisanopensourcesystemformanagingcontainerizedapplicationsacrossmultiplehosts.Itprovidesbasicmechanismsfordeployment,maintenance,andscalingofapplications.
用于自动部署、扩展和管理“容器化(containerized)应用程序”的开源系统。
翻译成大白话就是:“K8S是负责自动化运维管理多个Docker程序的集群”。那么问题来了:Docker运行可方便了,为什么要用K8S,它有什么优势?
插一句题外话:
为什么Kubernetes要叫Kubernetes呢?维基百科已经交代了(老美对星际是真的痴迷):
Kubernetes(在希腊语意为“舵手”或“驾驶员”)由JoeBeda、BrendanBurns和CraigMcLuckie创立,并由其他谷歌工程师,包括BrianGrant和TimHockin等进行加盟创作,并由谷歌在年首次对外宣布。该系统的开发和设计都深受谷歌的Borg系统的影响,其许多顶级贡献者之前也是Borg系统的开发者。在谷歌内部,Kubernetes的原始代号曾经是Seven,即星际迷航中的Borg(博格人)。Kubernetes标识中舵轮有七个轮辐就是对该项目代号的致意。
为什么Kubernetes的缩写是K8S呢?我个人赞同WhyKubernetesisAbbreviatedk8s中说的观点“嘛,写全称也太累了吧,不如整个缩写”。其实只保留首位字符,用具体数字来替代省略的字符个数的做法,还是比较常见的。
1.2为什么是K8S?试想下传统的后端部署办法:把程序包(包括可执行二进制文件、配置文件等)放到服务器上,接着运行启动脚本把程序跑起来,同时启动守护脚本定期检查程序运行状态、必要的话重新拉起程序。
有问题吗?显然有!最大的一个问题在于:**如果服务的请求量上来,已部署的服务响应不过来怎么办?**传统的做法往往是,如果请求量、内存、CPU超过阈值做了告警,运维马上再加几台服务器,部署好服务之后,接入负载均衡来分担已有服务的压力。
问题出现了:从监控告警到部署服务,中间需要人力介入!那么,有没有办法自动完成服务的部署、更新、卸载和扩容、缩容呢?
这,就是K8S要做的事情:自动化运维管理Docker(容器化)程序。
1.3K8S怎么做?我们已经知道了K8S的核心功能:自动化运维管理多个容器化程序。那么K8S怎么做到的呢?这里,我们从宏观架构上来学习K8S的设计思想。首先看下图,图片来自文章ComponentsofKubernetesArchitecture:
K8S是属于主从设备模型(Master-Slave架构),即有Master节点负责核心的调度、管理和运维,Slave节点则在执行用户的程序。但是在K8S中,主节点一般被称为MasterNode或者HeadNode(本文采用MasterNode称呼方式),而从节点则被称为WorkerNode或者Node(本文采用WorkerNode称呼方式)。
要注意一点:MasterNode和WorkerNode是分别安装了K8S的Master和Woker组件的实体服务器,每个Node都对应了一台实体服务器(虽然MasterNode可以和其中一个WorkerNode安装在同一台服务器,但是建议MasterNode单独部署),所有MasterNode和WorkerNode组成了K8S集群,同一个集群可能存在多个MasterNode和WorkerNode。
首先来看MasterNode都有哪些组件:
APIServer。K8S的请求入口服务。APIServer负责接收K8S所有请求(来自UI界面或者CLI命令行工具),然后,APIServer根据用户的具体请求,去通知其他组件干活。Scheduler。K8S所有WorkerNode的调度器。当用户要部署服务时,Scheduler会选择最合适的WorkerNode(服务器)来部署。ControllerManager。K8S所有WorkerNode的监控器。ControllerManager有很多具体的Controller,在文章ComponentsofKubernetesArchitecture中提到的有NodeController、ServiceController、VolumeController等。Controller负责监控和调整在WorkerNode上部署的服务的状态,比如用户要求A服务部署2个副本,那么当其中一个服务挂了的时候,Controller会马上调整,让Scheduler再选择一个WorkerNode重新部署服务。etcd。K8S的存储服务。etcd存储了K8S的关键配置和用户配置,K8S中仅APIServer才具备读写权限,其他组件必须通过APIServer的接口才能读写数据(见KubernetesWorksLikeanOperatingSystem)。接着来看WorkerNode的组件,笔者更赞同HOWDOAPPLICATIONSRUNONKUBERNETES文章中提到的组件介绍:
Kubelet。WorkerNode的监视器,以及与MasterNode的通讯器。Kubelet是MasterNode安插在WorkerNode上的“眼线”,它会定期向WorkerNode汇报自己Node上运行的服务的状态,并接受来自MasterNode的指示采取调整措施。Kube-Proxy。K8S的网络代理。私以为称呼为Network-Proxy可能更适合?Kube-Proxy负责Node在K8S的网络通讯、以及对外部网络流量的负载均衡。ContainerRuntime。WorkerNode的运行环境。即安装了容器化所需的软件环境确保容器化程序能够跑起来,比如DockerEngine。大白话就是帮忙装好了Docker运行环境。LoggingLayer。K8S的监控状态收集器。私以为称呼为Monitor可能更合适?LoggingLayer负责采集Node上所有服务的CPU、内存、磁盘、网络等监控项信息。Add-Ons。K8S管理运维WorkerNode的插件组件。有些文章认为WorkerNode只有三大组件,不包含Add-On,但笔者认为K8S系统提供了Add-On机制,让用户可以扩展更多定制化功能,是很不错的亮点。总结来看,K8S的MasterNode具备:请求入口管理(APIServer),WorkerNode调度(Scheduler),监控和自动调节(ControllerManager),以及存储功能(etcd);而K8S的WorkerNode具备:状态和监控收集(Kubelet),网络和负载均衡(Kube-Proxy)、保障容器化运行环境(ContainerRuntime)、以及定制化功能(Add-Ons)。
到这里,相信你已经对K8S究竟是做什么的,有了大概认识。接下来,再来认识下K8S的Deployment、Pod、ReplicaSet、Service等,但凡谈到K8S,就绕不开这些名词,而这些名词也是最让K8S新手们感到头疼、困惑的。
II.K8S重要概念2.1Pod实例官方对于Pod的解释是:
Pod是可以在Kubernetes中创建和管理的、最小的可部署的计算单元。
这样的解释还是很难让人明白究竟Pod是什么,但是对于K8S而言,Pod可以说是所有对象中最重要的概念了!因此,我们必须首先清楚地知道“Pod是什么”,再去了解其他的对象。
从官方给出的定义,联想下“最小的xxx单元”,是不是可以想到本科在学校里学习“进程”的时候,教科书上有一段类似的描述:资源分配的最小单位;还有”线程“的描述是:CPU调度的最小单位。什么意思呢?”最小xx单位“要么就是事物的衡量标准单位,要么就是资源的闭包、集合。前者比如长度米、时间秒;后者比如一个”进程“是存储和计算的闭包,一个”线程“是CPU资源(包括寄存器、ALU等)的闭包。
同样的,Pod就是K8S中一个服务的闭包。这么说的好像还是有点玄乎,更加云里雾里了。简单来说,Pod可以被理解成一群可以共享网络、存储和计算资源的容器化服务的集合。再打个形象的比喻,在同一个Pod里的几个Docker服务/程序,好像被部署在同一台机器上,可以通过localhost互相访问,并且可以共用Pod里的存储资源(这里是指Docker可以挂载Pod内的数据卷,数据卷的概念,后文会详细讲述,暂时理解为“需要手动mount的磁盘”)。笔者总结Pod如下图,可以看到:同一个Pod之间的Container可以通过localhost互相访问,并且可以挂载Pod内所有的数据卷;但是不同的Pod之间的Container不能用localhost访问,也不能挂载其他Pod的数据卷。
对Pod有直观的认识之后,接着来看K8S中Pod究竟长什么样子,具体包括哪些资源?
K8S中所有的对象都通过yaml来表示,笔者从官方网站摘录了一个最简单的Pod的yaml:
apiVersion:v1kind:Podmetadata:name:memory-demonamespace:mem-examplespec:containers:-name:memory-demo-ctrimage:polinux/stressresources:limits:memory:"Mi"requests:memory:"Mi"