Kubernetes从⼊门到进阶实战教程(2020最新万字⼲货版)作者:oonamao ⽑江云,腾讯 CSIG 应⽤开发⼯程师
写在前⾯
笔者今年 9 ⽉从端侧开发转到后台开发,第⼀个系统开发任务就强依赖了 K8S,加之项⽬任务重、排期紧,必须马上对K8S 有概念上的了解。然⽽,很多所谓“K8S ⼊门概念”的⽂章看的⼀头雾⽔,对于⼤部分新⼿来说并不友好。经历了⼏天痛苦地学习之后,回顾来看,K8S 根本不复杂。于是,决⼼有了这⼀系列的⽂章:⼀⽅⾯希望对新⼿同学有帮助;另⼀⽅⾯,以⽂会友,希望能够有机会交流讨论技术。
本⽂组织⽅式:
1. K8S 是什么,即作⽤和⽬的。涉及 K8S 架构的整理,Master 和 Node 之间的关系,以及 K8S ⼏个重要的组件:API Server、Scheduler、Controller、etcd 等。
2. K8S 的重要概念,即 K8S 的 API 对象,也就是常常听到的 Pod、Deployment、Service 等。
3. 如何配置 kubectl,介绍kubectl⼯具和配置办法。
pilot是什么意思
4. 如何⽤kubectl 部署服务。
5. 如何⽤kubectl 查看、更新/编辑、删除服务。
6. 如何⽤kubectl 排查部署在K8S集群上的服务出现的问题
fy
I. K8S 概览1.1 K8S 是什么?
K8S 是Kubernetes的全称,官⽅称其是:
Kubernetes is an open source system for managing containerized applications across multiple hosts. It provides basic mechanisms for deployment, maintenance, and scaling of applications.
⽤于⾃动部署、扩展和管理“容器化(containerized)应⽤程序”的开源系统。
翻译成⼤⽩话就是:“ K8S 是负责⾃动化运维管理多个 Docker 程序的集群”。那么问题来了:Docker 运⾏可⽅便了,为什么要⽤ K8S,它有什么优势?
插⼀句题外话:
•
为什么 Kubernetes 要叫 Kubernetes 呢?维基百科已经交代了(⽼美对星际是真的痴迷):
Kubernetes(在希腊语意为“舵⼿”或“驾驶员”)由 Joe Beda、Brendan Burns 和 Craig McLuckie 创⽴,并由其他⾕歌⼯程师,包括 Brian Grant 和 Tim Hockin 等进⾏加盟创作,并由⾕歌在 2014 年⾸次对外宣布。该系统的开发和设计都深受⾕歌的 Borg 系统的影响,其许多顶级贡献者之前也是 Borg 系统的开发者。在⾕歌内
部,Kubernetes 的原始代号曾经是Seven,即星际迷航中的 Borg(博格⼈)。Kubernetes 标识中舵轮有七个轮辐就是对该项⽬代号的致意。
•
为什么 Kubernetes 的缩写是 K8S 呢?我个⼈赞同Why Kubernetes is Abbreviated k8s中说的观点“嘛,写全称也太累了吧,不如整个缩写”。其实只保留⾸位字符,⽤具体数字来替代省略的字符个数的做法,还是⽐较常见的。
1.2 为什么是 K8S?
1.2 为什么是 K8S?
试想下传统的后端部署办法:把程序包(包括可执⾏⼆进制⽂件、配置⽂件等)放到服务器上,接着运⾏启动脚本把程序跑起来,同时启动守护脚本定期检查程序运⾏状态、必要的话重新拉起程序。
有问题吗?显然有!最⼤的⼀个问题在于:**如果服务的请求量上来,已部署的服务响应不过来怎么办?**传统的做法往往是,如果请求量、内存、CPU 超过阈值做了告警,运维马上再加⼏台服务器,部署好服务之后,接⼊负载均衡来分担已有服务的压⼒。
问题出现了:从监控告警到部署服务,中间需要⼈⼒介⼊!那么,有没有办法⾃动完成服务的部署、更新、卸载和扩容、缩容呢?
这,就是 K8S 要做的事情:⾃动化运维管理 Docker(容器化)程序。
1.3 K8S 怎么做?
我们已经知道了 K8S 的核⼼功能:⾃动化运维管理多个容器化程序。那么 K8S 怎么做到的呢?这⾥,我们从宏观架构上来学习 K8S 的设计思想。⾸先看下图,图⽚来⾃⽂章Components of Kubernetes Architecture:
K8S 是属于主从设备模型(Master-Slave 架构),即有 Master 节点负责核⼼的调度、管理和运维,Slave 节点则在执⾏⽤户的程序。但是在 K8S 中,主节点⼀般被称为 Master Node 或者 Head Node(本⽂采⽤ Master Node 称呼⽅式),⽽从节点则被称为 Worker Node 或者 Node(本⽂采⽤ Worker Node 称呼⽅式)。
要注意⼀点:Master Node 和 Worker Node 是分别安装了 K8S 的 Master 和 Woker 组件的实体服务器,每个 Node 都对应了⼀台实体服务器(虽然 Master Node 可以和其中⼀个 Worker Node 安装在同⼀台服务器,但是建议 Master Node 单独部署),所有 Master Node 和 Worker Node 组成了 K8S 集群,同⼀个集群可能存在多个 Master Node 和Worker Node。
⾸先来看 Master Node都有哪些组件:
•
API Server。 K8S 的请求⼊⼝服务。API Server 负责接收 K8S 所有请求(来⾃ UI 界⾯或者 CLI 命令⾏⼯具),然后,API Server 根据⽤户的具体请求,去通知其他组件⼲活。
•
Scheduler。 K8S 所有 Worker Node 的调度器。当⽤户要部署服务时,Scheduler 会选择最合适的 Worker
Node(服务器)来部署。
•
Controller Manager。 K8S 所有 Worker Node 的监控器。Controller Manager 有很多具体的 Controller,在⽂章Components of Kubernetes Architecture中提到的有 Node Controller、Service Controller、Volume Controller 等。
Controller 负责监控和调整在 Worker Node 上部署的服务的状态,⽐如⽤户要求 A 服务部署 2 个副本,那么当其中⼀个服务挂了的时候,Controller 会马上调整,让 Scheduler 再选择⼀个 Worker Node 重新部署服务。
•
etcd。 K8S 的存储服务。etcd 存储了 K8S 的关键配置和⽤户配置,K8S 中仅 API Server 才具备读写权限,其他组件必须通过 API Server 的接⼝才能读写数据(见Kubernetes Works Like an Operating System)。
会议桥
接着来看 Worker Node的组件,笔者更赞同HOW DO APPLICATIONS RUN ON KUBERNETES⽂章中提到的组件介绍:
•
Kubelet。 Worker Node 的监视器,以及与 Master Node 的通讯器。Kubelet 是 Master Node 安插在
Worker Node 上的“眼线”,它会定期向 Worker Node 汇报⾃⼰ Node 上运⾏的服务的状态,并接受来⾃ Master Node 的指⽰采取调整措施。
调整措施。
•
Kube-Proxy。 K8S 的⽹络代理。私以为称呼为 Network-Proxy 可能更适合?Kube-Proxy 负责 Node 在 K8S 的⽹络通讯、以及对外部⽹络流量的负载均衡。
•
stableContainer Runtime。 Worker Node 的运⾏环境。即安装了容器化所需的软件环境确保容器化程序能够跑起来,⽐如Docker Engine。⼤⽩话就是帮忙装好了 Docker 运⾏环境。
•
Logging Layer。 K8S 的监控状态收集器。私以为称呼为 Monitor 可能更合适?Logging Layer 负责采集 Node 上所有服务的 CPU、内存、磁盘、⽹络等监控项信息。
•
Add-Ons。 K8S 管理运维 Worker Node 的插件组件。有些⽂章认为 Worker Node 只有三⼤组件,不包含 Add-On,但笔者认为 K8S 系统提供了 Add-On 机制,让⽤户可以扩展更多定制化功能,是很不错的亮点。
总结来看, K8S 的 Master Node 具备:请求⼊⼝管理(API Server),Worker Node 调度(Scheduler),监控和⾃动调节(Controller Manager),以及存储功能(etcd);⽽ K8S 的 Worker Node 具备:状态和监控收集(Kubelet),⽹络和负载均衡(Kube-Proxy)、保障容器化运⾏环境(Container Runtime)、以及定制化功能(Add-Ons)。
到这⾥,相信你已经对 K8S 究竟是做什么的,有了⼤概认识。接下来,再来认识下 K8S 的 Deployment、Pod、Replica Set、Service 等,但凡谈到 K8S,就绕不开这些名词,⽽这些名词也是最让 K8S 新⼿们感到头疼、困惑的。II. K8S 重要概念2.1 Pod 实例
官⽅对于 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 究竟长什么样⼦,具体包括哪些资源?
passwords must matchK8S 中所有的对象都通过 yaml 来表⽰,笔者从官⽅⽹站摘录了⼀个最简单的 Pod 的 yaml:
apiVersion:v1
kind:Pod
metadata:
metadata:
name:memory-demo
namespace:mem-example
spec:
containers:
-name:memory-demo-ctr
image:polinux/stress
resources:
limits:
memory:"200Mi"
requests:
memory:"100Mi"
command:["stress"]
args:["--vm","1","--vm-bytes","150M","--vm-hang","1"]
volumeMounts:
-name:redis-storage
mountPath:/data/redis
volumes:
-name:redis-storage
emptyDir:{}
看不懂不必慌张,且耐⼼听下⾯的解释:
•
apiVersion 记录 K8S 的 API Server 版本,现在看到的都是 v1 ,⽤户不⽤管。
•
kind 记录该 yaml 的对象,⽐如这是⼀份 Pod 的 yaml 配置⽂件,那么值内容就是 Pod 。
•
metadata 记录了 Pod ⾃⾝的元数据,⽐如这个 Pod 的名字、这个 Pod 属于哪个 namespace(命名空间的概念,后⽂会详述,暂时理解为“同⼀个命名空间内的对象互相可见”)。
jintai•
•
spec 记录了 Pod 内部所有的资源的详细信息,看懂这个很重要:
•
containers 记录了 Pod 内的容器信息, containers 包括了: name 容器名, image 容器的镜像地址, resources 容器需要的 CPU、内存、GPU 等资源, command 容器的⼊⼝命令, args 容器的⼊⼝参数, volumeMounts 容器要挂载的 Pod 数据卷等。可以看到,上述这些信息都是启动容器的必要和必需的信息。
考研步骤
•
volumes 记录了 Pod 内的数据卷信息,后⽂会详细介绍 Pod 的数据卷。
2.2 Volume 数据卷
K8S ⽀持很多类型的 volume 数据卷挂载,具体请参见K8S 卷。前⽂就“如何理解 volume”提到:“ 需要⼿动 mount 的磁盘”,此外,有⼀点可以帮助理解:数据卷 volume 是 Pod 内部的磁盘资源。
iceberg
其实,单单就 Volume 来说,不难理解。但是上⾯还看到了 volumeMounts ,这俩是什么关系呢?
volume 是 K8S 的对象,对应⼀个实体的数据卷;⽽ volumeMounts 只是 container 的挂载点,对应 container 的其中⼀个参数。但是, volumeMounts 依赖于 volume,只有当 Pod 内有 volume 资源的时候,该 Pod 内部的 container 才可能有 volumeMounts。
2.3 Container 容器
本⽂中提到的镜像 Image、容器 Container,都指代了 Pod 下的⼀个 container 。关于 K8S 中的容器,在 2.1Pod 章节都已经交代了,这⾥⽆⾮再啰嗦⼀句:⼀个 Pod 内可以有多个容器 container。
在 Pod 中,容器也有分类,对这个感兴趣的同学欢迎⾃⾏阅读更多资料:
•
英语四级试题下载标准容器 Application Container。
•huangwang
初始化容器 Init Container。
•
边车容器 Sidecar Container。
•
临时容器 Ephemeral Container。
⼀般来说,我们部署的⼤多是标准容器( Application Container)。
2.4 Deployment 和 ReplicaSet(简称 RS)
除了 Pod 之外,K8S 中最常听到的另⼀个对象就是 Deployment 了。那么,什么是 Deployment 呢?官⽅给出了⼀个要命的解释:
⼀个 Deployment 控制器为 Pods 和 ReplicaSets 提供声明式的更新能⼒。
你负责描述 Deployment 中的⽬标状态,⽽ Deployment 控制器以受控速率更改实际状态,使其变为期望状态。你可以定义 Deployment 以创建新的 ReplicaSet,或删除现有 Deployment,并通过新的 Deployment 收养其资源。
翻译⼀下: Deployment 的作⽤是管理和控制 Pod 和 ReplicaSet,管控它们运⾏在⽤户期望的状态中。哎,打个形象