收藏 分销(赏)

深入浅出Kubernetes.pdf

上传人:Stan****Shan 文档编号:1188372 上传时间:2024-04-18 格式:PDF 页数:128 大小:13.63MB
下载 相关 举报
深入浅出Kubernetes.pdf_第1页
第1页 / 共128页
深入浅出Kubernetes.pdf_第2页
第2页 / 共128页
深入浅出Kubernetes.pdf_第3页
第3页 / 共128页
深入浅出Kubernetes.pdf_第4页
第4页 / 共128页
深入浅出Kubernetes.pdf_第5页
第5页 / 共128页
点击查看更多>>
资源描述

1、理论篇4这么理解集群控制器,能行!4集群网络详解13集群伸缩原理21认证与调度28集群服务的三个要点和一种实现45镜像拉取这件小事56实践篇67读懂这一篇,集群节点不下线67节点下线姊妹篇81我们为什么会删除不了集群的命名空间?93阿里云 ACK 产品安全组配置管理104二分之一活的微服务114半夜两点 Ca 证书过期问题处理惨况总结124目录这么理解集群控制器,能行!简介:当我们尝试去理解 K8S 集群工作原理的时候,控制器肯定是一个难点。这是因为控制器有很多,具体实现大相径庭;且控制器的实现用到了一些较为晦涩的机制,不易理解。但是,我们又不能绕过控制器,因为它是集群的“大脑”。当我们尝试去

2、理解 K8S 集群工作原理的时候,控制器肯定是一个难点。这是因为控制器有很多,具体实现大相径庭;且控制器的实现用到了一些较为晦涩的机制,不易理解。但是,我们又不能绕过控制器,因为它是集群的“大脑”。今天这篇文章,我们通过分析一个简易冰箱的设计过程,来深入理解集群控制器的产生,功能以及实现方法。大图下图是 K8S 集群的核心组件,包括数据库 etcd,调度器 scheduler,集群入口APIServer,控制器 Controller,服务代理 kube-proxy 以及直接管理具体业务容器的 kubelet。这些组件逻辑上可以被分为三个部分:核心组件 etc 数据库,对 etcd进行直接操作的

3、入口组件 APIServer,以及其他组件。这里的“其他组件”之所以可以被划分为一类,是因为它们都可以被看做是集群的控制器。理论篇这么理解集群控制器,能行!这么理解集群控制器,能行!统一入口对于上边的冰箱,我们可以简单抽象成两个部分:统一的操作入口和冰箱的所有组件。在这里,用户只有通过入口,才能操作冰箱。这个入口提供给用户两个接口:开关门和调节温控器。用户执行这两个接口的时候,入口会分别调整冰箱门和温控器的状态。这么理解集群控制器,能行!这么理解集群控制器,能行!SharedInformer上边的控制器和控制器管理器,看起来已经相当不错了。但是当冰箱功能增加,势必有很多新的控制器加进来。这些控

4、制器都需要通过冰箱入口,时刻监控自己关心的组件的状态变化。比如照明系统控制器就需要时刻监控冰箱门的状态。当大量控制器不断的和入口通信的时候,就会增加入口的压力。这个时候,我们把监控冰箱组件状态变化这件事情,交给一个新的模块SharedInformer 来实现。SharedInformer 作为控制器的代理,替控制器监控冰箱组件的状态变化,并根据控制器的喜好,把不同组件状态的变化,通知给对应的控制器。通过优化,这样的 SharedInformer 可以极大的缓解冰箱入口的压力。这么理解集群控制器,能行!这么理解集群控制器,能行!假设 SharedInformer 和冰箱入口通过 http 协议通

5、信的话,那么 http 分块编码(chunkedtransferencoding)就是实现 ListWatcher 的一个好的选择。控制器通过ListWatcher 给冰箱入口发送一个查询然后等待,当冰箱组件有变化的时候,入口通过分块的 http 响应通知控制器。控制器看到 chunked 响应,会认为响应数据还没有发送完成,所以会持续等待。举例以上我们从一个简易冰箱的进化过程中,了解了控制器产生的意义,扮演的角色,以及实现的方式。现在我们回到 K8S 集群。K8S 集群实现了大量的控制器,而且在可以预见的未来,新的功能的控制器会不断出现,而一些旧的控制器也会被逐渐淘汰。目前来说,我们比较常用

6、的控制器,如 pod 控制器、deployment 控制器、service 控制器、replicaset 控制器等。这些控制器一部分是由 kubecontrollermanager 这个管理器实现和管理,而像 route 控制器和 service 控制器,则由这么理解集群控制器,能行!这么理解集群控制器,能行!路由控制器在集群网络一章中,我们提到过,当一个节点加入一个 K8S 集群的时候,集群需要在 VPC 路由表里增加一条路由,来搭建这个新加入节点到 pod 网络的主干道。而这件事情,就是路由控制器来做的。路由控制器完成这件事情的流程,与上边服务控制器的处理流程非常类似,这里不再赘述。结束语

7、基本上来说,K8S 集群的控制器,其实扮演着集群大脑的角色。有了控制器,K8S 集群才有机会摆脱机械和被动,变成一个自动、智能、有大用的系统。集群网络详解简介:阿里云 K8S 集群网络目前有两种方案,一种是 flannel 方案,另外一种是基于 calico 和弹性网卡 eni 的 terway 方案。Terway 和 flannel 类似,不同的地方在于,terway 支持 Pod 弹性网卡,以及 NetworkPolicy 功能。阿里云 K8S 集群网络目前有两种方案,一种是 flannel 方案,另外一种是基于calico 和弹性网卡 eni 的 terway 方案。Terway 和 f

8、lannel 类似,不同的地方在于,terway 支持 Pod 弹性网卡,以及 NetworkPolicy 功能。今天这篇文章,我们以 flannel 为例,深入分析阿里云 K8S 集群网络的实现方法。我会从两个角度去分析,一个是网络的搭建过程,另外一个是基于网络的通信。我们的讨论基于当前的 1.12.6 版本。鸟瞰总体上来说,阿里云 K8S 集群网络配置完成之后,如下图,包括集群 CIDR,VPC 路由表,节点网络,节点的 podCIDR,节点上的虚拟网桥 cni0,连接 Pod 和网桥的 veth 等部分。14集群网络详解类似的图,大家可能在很多文章中都看过,但是因为其中相关配置过于复杂,

9、比较难理解。这里我们可以把这些配置,分三种情况来理解:集群配置,节点配置以及 Pod 配置。与这三种情况对应的,其实是对集群网络 IP 段的三次划分:首先是集群 CIDR,接着为每个节点分配 podCIDR(即集群 CIDR 的子网段),最后在podCIDR 里为每个 Pod 分配自己的 IP。集群网络详解集群网络详解集群控制器有了这个参数,在节点 kubelet 注册节点到集群的时候,集群控制器会为每个注册节点,划分一个子网出来,即为每个节点分配 podCIDR。如上图,NodeB 的子网是 172.16.8.1/25,而 NodeA 的子网是 172.16.0.128/25。这个配置会记录

10、到集群 node 的 podCIDR 数据项里。节点阶段经过以上集群阶段,K8S 有了集群 CIDR,以及为每个节点划分的 podCIDR。在此基础上,集群会下发 flanneld 到每个阶段上,进一步搭建节点上,可以给Pod 使用的网络框架。这里主要有两个操作,第一个是集群通过 CloudControllerManager 给 VPC 配置路由表项。路由表项对每个节点有一条。每一条的意思是,如果 VPC 路由收到目的地址是某一个节点 podCIDR 的 IP 地址,那么路由会把这个网络包转发到对应的 ECS 上。第二个是创建虚拟网桥 cni0,以及与 cni0 相关的路由。这些配置的作用是,

11、从阶段外部进来的网络包,如果目的 IP 是 podCIDR,则会被节点转发到 cni0 虚拟局域网里。集群网络详解集群网络详解理解这两者的区别,有助于我们理解 flanneld 和 flannelcni 相关的配置文件的用途。比如/run/flannel/subnet.env,是 flanneld 创建的,为 flannelcni 提供输入的一个环境变量文件;又比如/etc/cni/net.d/10-flannel.conf,也是 flanneldpod(准确的说,是 pod 里的脚本 install-cni)从 pod 里拷贝到节点目录,给 flannelcni使用的子网配置文件。通信以上完

12、成 Pod 网络环境搭建。基于以上的网络环境,Pod 可以完成四种通信:本地通信,同节点 Pod 通信,跨节点 Pod 通信,以及 Pod 和 Pod 网络之外的实体通信。集群网络详解集群网络详解总结以上是阿里云 K8S 集群网络的搭建和通信原理。我们主要通过网络搭建和通信两个角度去分析 K8S 集群网络。其中网络搭建包括初始阶段,集群阶段,节点阶段以及 Pod 阶段,这么分类有助于我们理解这些复杂的配置。而理解了各个配置,集群通信原理就比较容易理解了。集群伸缩原理简介:阿里云 K8S 集群的一个重要特性,是集群的节点可以动态的增加或减少。有了这个特性,集群才能在计算资源不足的情况下扩容新的节

13、点,同时也可以在资源利用率降低的时候,释放节点以节省费用。这篇文章,我们讨论阿里云 K8S 集群扩容与缩容的实现原理。阿里云 K8S 集群的一个重要特性,是集群的节点可以动态的增加或减少。有了这个特性,集群才能在计算资源不足的情况下扩容新的节点,同时也可以在资源利用率降低的时候,释放节点以节省费用。这篇文章,我们讨论阿里云 K8S 集群扩容与缩容的实现原理。理解实现原理,在遇到问题的时候,我们就可以高效地排查并定位原因。我们的讨论基于当前的1.12.6 版本。节点增加原理阿里云 K8S 集群可以给集群增加节点的方式有,添加已有节点,集群扩容,和自动伸缩。其中,添加已有节点又可分为手动添加已有节

14、点和自动添加已有节点。节点的增加涉及到的组件有,节点准备,弹性伸缩(ESS),管控,ClusterAutoscaler以及调度器。22集群伸缩原理手动添加已有节点节点准备,其实就是把一个普通的 ECS 实例,安装配置成为一个 K8S 集群节点的过程。这个过程仅靠一条命令就可以完成。这条命令使用 curl 下载 attach_node.sh 脚本,然后以 openapitoken 为参数,在 ECS 上运行。curlhttp:/public/pkg/run/attach/attach_node.sh|bash-s-opena-pi-token这里 token 是一个对的 key,而 value

15、是当前集群的基本信息。阿里云 K8S集群的管控,在接到手动添加已有节点请求的时候,会生成这个对,并把 key 作为token 返回给用户。这个 token(key)存在的价值,是其可以让 attach_node.sh 脚本,以匿名身份在 ECS 上索引到集群的基本信息(value),而这些基本信息,对节点准备至关重要。总体上来说,节点准备就做两件事情,读和写。读即数据收集,写即节点配置。集群伸缩原理集群伸缩原理自动添加已有节点自动添加已有节点,不需要人为拷贝黏贴脚本到 ECS 命令行来完成节点准备的过程。管控使用了 ECSuserdata 的特性,把类似以上节点准备的脚本,写入ECSuserd

16、ata,然后重启 ECS 并更换系统盘。当 ECS 重启之后,会自动执行Userdata 里边的脚本,来完成节点添加的过程。这部分内容,大家其实可以通过查看节点 userdata 来确认。!/bin/bashmkdir-p/var/log/acscurlhttp:/public/pkg/run/attach/1.12.6-aliyun.1/attach_node.sh|bash-s-docker-version-token-endpoint-cluster-dns/var/log/acs/init.log这里我们看到,attach_node.sh 的参数,与前一节的参数有很大的不同。其实这里的

17、参数,都是前一节 value 的内容,即管控创建并维护的集群基本信息。自动添加已有节点省略了通过 key 获取 value 的过程。集群扩容集群扩容与以上添加已有节点不同,此功能针对需要新购节点的情形。集群扩容的实现,在添加已有节点的基础上,引入了弹性伸缩 ESS 组件。ESS 组件负责从无到有的过程,而剩下的过程与添加已有节点类似,即依靠 ECSuserdata 脚本来完成节点准备。下图是管控通过 ESS 从无到有创建 ECS 的过程。集群伸缩原理集群伸缩原理个用户数据和手动添加已有节点的脚本类似,不同的地方在于,其针对自动伸缩这种场景,增加了一些专门的标记。attach_node.sh 脚

18、本会根据这些标记,来设置节点的属性。!/bin/shcurlhttp:/public/pkg/run/attach/1.12.6-aliyun.1/attach_node.sh|bash-s-openapi-token-esstrue-labelsk8s.io/cluster-auto-scaler=true,workload_type=cpu,=true而第二个过程,是实现自动增加节点的关键。这里引入了一个新的组件Autoscaler,它以 Pod 的形式运行在 K8S 集群中。理论上来说,我们可以把这个组件当做一个控制器。因为它的作用与控制器类似,基本上还是监听 Pod 状态,以便在 Po

19、d 因为节点资源不足而不能被调度的时,去修改 ESS 的伸缩规则来增加新的节点。这里有一个知识点,集群调度器衡量资源是否充足的标准,是“预订率”,而不是“使用率”。这两者的差别,类似酒店房价预订率和实际入住率:完全有可能有人预订了酒店,但是并没有实际入住。在开启自动伸缩功能的时候,我们需要设置缩容阈值,就是“预订率”的下线。之所以不需要设置扩容阈值。是因为 Autoscaler 扩容集群,依靠的是 Pod 的调度状态:当 Pod 因为节点资源“预订率”太高无法被调度的时候,Autoscaler 就会扩容集群。节点减少原理与增加节点不同,集群减少节点的操作只有一个移除节点的入口。但对于用不同方法

20、加入的节点,其各自移除方式略有不同。首先,通过添加已有节点加入的节点,需要三步去移除:管控通过 ECSAPI 清楚 ECSuserdata;管控通过 K8SAPI 从集群中删除节点;管控通过 ECSInvoke-集群伸缩原理27Command 在 ECS 上执行 kubeadmreset 命令清理节点。其次,通过集群扩容加入的节点,则在上边的基础上,增加了断开 ESS 和 ECS关系的操作。此操作由管控调用 ESSAPI 完成。最后,经过 ClusterAutoscaler 动态增加的节点,则在集群 CPU 资源“预订率”降低的时候,由 ClusterAutoscaler 自动移除释放。其触发

21、点是 CPU“预订率”,即上图写 Metrics 的原因。总结总体上来说,K8S 集群节点的增加与减少,主要涉及四个组件,分别是 ClusterAutoscaler,ESS,管控以及节点本身(准备或清理)。根据场景不同,我们需要排查不同的组件。其中 ClusterAutoscaler 是一个普通的 Pod,其日志的获取和其他Pod 无异;ESS 弹性伸缩有其专门的控制台,我们可以在控制台排查其伸缩配置、伸缩规则等相关子实例日志和状态;而管控的日志,可以通过查看日志功能来查看;最后,对于节点的准备与清理,其实就是排查对应的脚本的执行过程。以上讲道理居多,希望对大家排查问题有所帮助。认证与调度简介

22、:不知道大家有没有意识到一个现实,就是大部分时候,我们已经不像以前一样,通过命令行,或者可视窗口来使用一个系统了。现在我们上微博、或者网购,操作的其实不是眼前这台设备,而是一个又一个集群。通常,这样的集群拥有成百上千个节点,每个节点是一台物理机或虚拟机。不知道大家有没有意识到一个现实,就是大部分时候,我们已经不像以前一样,通过命令行,或者可视窗口来使用一个系统了。现在我们上微博、或者网购,操作的其实不是眼前这台设备,而是一个又一个集群。通常,这样的集群拥有成百上千个节点,每个节点是一台物理机或虚拟机。集群一般远离用户,坐落在数据中心。为了让这些节点互相协作,对外提供一致且高效的服务,集群需要操

23、作系统。Kubernetes 就是这样的操作系统。比较 Kubernetes 和单机操作系统,Kubernetes 相当于内核,它负责集群软硬件资源管理,并对外提供统一的入口,用户可以通过这个入口来使用集群,和集群沟通。认证与调度认证与调度 w.Write(byte(This is a small app for kubernetes.n)func main()r:=mux.NewRouter()r.HandleFunc(/,about)log.Fatal(http.ListenAndServe(0.0.0.0:2580,r)使用 gobuild 命令编译这个程序,产生 app 可执行文件。这

24、是一个普通的可执行文件,它在操作系统里运行,会依赖系统里的库文件。#ldd applinux-vdso.so.1=(0 x00007ffd1f7a3000)libpthread.so.0=/lib64/libpthread.so.0(0 x00007f554fd4a000)libc.so.6=/lib64/libc.so.6(0 x00007f554f97d000)/lib64/ld-linux-x86-64.so.2(0 x00007f554ff66000)“笼子”为了让这个程序不依赖于操作系统自身的库文件,我们需要制作容器镜像,即隔离的运行环境。Dockerfile 是制作容器镜像的“菜谱

25、”。我们的菜谱就只有两个步骤,下载一个 centos 的基础镜像,把 app 这个可执行文件放到镜像中/usr/local/bin 目录中去。FROM centosADD app/usr/local/bin认证与调度认证与调度这里我们创建一个阿里云 Kubernetes 集群。登录集群管理页面,我们可以看到APIServer 的公网入口。API Server 内网连接端点:https:/xx.xxx.xxx.xxx:6443双向数字证书验证阿里云 Kubernetes 集群 APIServer 组件,使用基于 CA 签名的双向数字证书认证来保证客户端与 apiserver 之间的安全通信。这句

26、话很绕口,对于初学者不太好理解,我们来深入解释一下。从概念上来讲,数字证书是用来验证网络通信参与者的一个文件。这和学校颁发给学生的毕业证书类似。在学校和学生之间,学校是可信第三方 CA,而学生是通信参与者。如果社会普遍信任一个学校的声誉的话,那么这个学校颁发的毕业证书,也会得到社会认可。参与者证书和 CA 证书可以类比毕业证和学校的办学许可证。这里我们有两类参与者,CA 和普通参与者;与此对应,我们有两种证书,CA证书和参与者证书;另外我们还有两种关系,证书签发关系,以及信任关系。这两种关系至关重要。我们先看签发关系。如下图,我们有两张 CA 证书,三个参与者证书。其中最上边的 CA 证书,签

27、发了两张证书,一张是中间的 CA 证书,另一张是右边的参与者证书;中间的 CA 证书,签发了下边两张参与者证书。这六张证书以签发关系为联系,形成了树状的证书签发关系图。认证与调度认证与调度KubeConfig 文件登录集群管理控制台,我们可以拿到 KubeConfig 文件。这个文件包括了客户端证书,集群 CA 证书,以及其他。证书使用 base64 编码,所以我们可以使用base64 工具解码证书,并使用 openssl 查看证书文本。首先,客户端证书的签发者 CN 是集群 idc0256a3b8e4b948bb9c21e66b0e-1d9a72,而证书本身的 CN 是子账号 2527716

28、43302762862。Certificate:Data:Version:3(0 x2)Serial Number:787224(0 xc0318)Signature Algorithm:sha256WithRSAEncryption Issuer:O=c0256a3b8e4b948bb9c21e66b0e1d9a72,OU=default,CN=c0256a3b8e4b948bb9c21e66b0e1d9a72认证与调度认证与调度Certificate:Data:Version:3(0 x2)Serial Number:2184578451551960857(0 x1e512e86fcba3

29、f19)Signature Algorithm:sha256WithRSAEncryption Issuer:O=c0256a3b8e4b948bb9c21e66b0e1d9a72,OU=default,CN=c0256a3b8e4b948bb9c21e66b0e1d9a72 Validity Not Before:Nov 29 03:59:00 2018 GMT Not After:Nov 29 04:14:23 2019 GMT Subject:CN=kube-apiserver最后,客户端需要验证上边这张 APIServer 的证书,因而 KubeConfig 文件里包含了其签发者,即集

30、群 CA 证书。对比集群 CA 证书和客户端 CA 证书,发现两张证书完全一样,这符合我们的预期。Certificate:Data:Version:3(0 x2)Serial Number:786974(0 xc021e)Signature Algorithm:sha256WithRSAEncryption Issuer:C=CN,ST=ZheJiang,L=HangZhou,O=Alibaba,OU=ACS,CN=root Validity Not Before:Nov 29 03:59:00 2018 GMT Not After:Nov 24 04:04:00 2038 GMT Subje

31、ct:O=c0256a3b8e4b948bb9c21e66b0e1d9a72,OU=default,CN=c0256a3b8e4b948bb9c21e66b0e1d9a72认证与调度认证与调度行的以集群管理组件为主,这些组件包括实现集群入口的 apiserver;而 worker 节点主要负责承载普通任务。在 Kubernetes 集群中,任务被定义为 pod 这个概念。pod 是集群可承载任务的原子单元。pod 被翻译成容器组,其实是意译,因为一个 pod 实际上封装了多个容器化的应用。原则上来讲,被封装在一个 pod 里边的容器,应该是存在相当程度的耦合关系。择优而居调度算法需要解决的问题

32、,是替 pod 选择一个舒适的“居所”,让 pod 所定义的任务可以在这个节点上顺利地完成。为了实现“择优而居”的目标,Kubernetes 集群调度算法采用了两步走的策略:第一步,从所有节点中排除不满足条件的节点,即预选;第二步,给剩余的节点打分,最后得分高者胜出,即优选。认证与调度认证与调度 日志级别集群调度算法被实现为运行在 master 节点上的系统组件,这一点和 apiserver类似。其对应的进程名是 kube-scheduler。kube-scheduler 支持多个级别的日志输出,但社区并没有提供详细的日志级别说明文档。查看调度算法对节点进行筛选、打分的过程,我们需要把日志级别

33、提高到 10,即加入参数-v=10。kube-scheduler-address=127.0.0.1-kubeconfig=/etc/kubernetes/scheduler.conf-leader-elect=true-v=10创建 Pod使用 curl,以证书和 pod 配置文件等作为参数,通过 POST 请求访问 apiserver 的接口,我们可以在集群里创建对应的 pod。#curl-X POST-H Content-Type:application/json;charset=utf-8-cert./client.crt-cacert./ca.crt-key./client.key

34、https:/47.110.197.238:6443/api/v1/namespaces/default/pods-dapp.json预选预选是 Kubernetes 调度的第一步,这一步要做的事情,是根据预先定义的规则,把不符合条件的节点过滤掉。不同版本的 Kubernetes 所实现的预选规则有很大的不同,但基本的趋势,是预选规则会越来越丰富。认证与调度认证与调度这两种方式,一种倾向于选出资源使用率较低的节点,第二种希望选出两种资源使用比例接近的节点。这两种方式有一些矛盾,最终依靠一定的权重来平衡这两个因素。除了资源之外,优选算法会考虑其他一些因素,比如 pod 与节点的亲和性,或者如果一

35、个服务有多个相同 pod 组成的情况下,多个 pod 在不同节点上的分散程度,这是保证高可用的一种策略。认证与调度认证与调度点这两件事情。在分析过程中,我们弃用了一些便利的工具,比如 kubectl,或者控制台。我们用了一些更接近底层的小实验,比如拆解 KubeConfig 文件,再比如分析调度器日志来分析认证和调度算法的运作原理。希望这些对大家进一步理解 Kubernetes 集群有所帮助。集群服务的三个要点和一种实现以我的经验来讲,理解 K8S 集群服务的概念,是比较不容易的一件事情。尤其是当我们基于似是而非的理解,去排查服务相关问题的时候,会非常不顺利。这体现在,对于新手来说,ping

36、不通服务的 IP 地址这样基础的问题,都很难理解;而就算对经验很丰富的工程师来说,看懂服务相关的 iptables 配置,也是相当的挑战。今天这边文章,我来深入解释一下 K8S 集群服务的原理与实现,便于大家理解。K8S 集群服务的本质是什么概念上来讲,K8S 集群的服务,其实就是负载均衡、或反向代理。这跟阿里云的负载均衡产品,有很多类似的地方。和负载均衡一样,服务有它的 IP 地址以及前端端口;服务后边会挂载多个容器组 Pod 作为其“后端服务器”,这些“后端服务器”有自己的 IP 以及监听端口。46集群服务的三个要点和一种实现当这样的负载均衡和后端的架构,与 K8S 集群结合的时候,我们可

37、以想到的最直观的实现方式,就是集群中某一个节点专门做负载均衡(类似 LVS)的角色,而其他节点则用来负载后端容器组。这样的实现方法,有一个巨大的缺陷,就是单点问题。K8S 集群是 Google 多年来自动化运维实践的结晶,这样的实现显然与其智能运维的哲学相背离的。自带通信员边车模式(Sidecar)是微服务领域的核心概念。边车模式,换一句通俗一点的说法,就是自带通信员。熟悉服务网格的同学肯定对这个很熟悉了。但是可能比较少人注意到,其实 K8S 集群原始服务的实现,也是基于 Sidecar 模式的。集群服务的三个要点和一种实现集群服务的三个要点和一种实现把服务照进现实前边两节,我们看到了,K8S

38、 集群的服务,本质上是负载均衡,即反向代理;同时我们知道了,在实际实现中,这个反向代理,并不是部署在集群某一个节点上,而是作为集群节点的边车,部署在每个节点上的。在这里把服务照进反向代理这个现实的,是 K8S 集群的一个控制器,即 kube-proxy。关于 K8S 集群控制器的原理,请参考我另外一篇关于控制器的文章。简单来说,kube-proxy 作为部署在集群节点上的控制器,它们通过集群 APIServer 监听着集群状态变化。当有新的服务被创建的时候,kube-proxy 则会把集群服务的状态、属性,翻译成反向代理的配置。那剩下的问题,就是反向代理,即上图中 Proxy 的实现。集群服务

39、的三个要点和一种实现集群服务的三个要点和一种实现很明显,这种切开水管,增加新功能的方式是很丑陋的。因为需求可能随时会变,我们甚至很难保证,在经过一年半载之后,这跟水管还能找得到可以被切开的地方。所以我们需要重新设计。首先我们不能随便切开水管,所以我们要把水管的切口固定下来。以上边的场景为例,我们确保水管只能有一个切口位置。其次,我们抽象出对水的两种处理方式:物理变化和化学变化。集群服务的三个要点和一种实现集群服务的三个要点和一种实现在网络设备这一层,我们通过 cni0 虚拟网桥,组建出系统内部的一个虚拟局域网。Pod 网络通过 veth 对连接到这个虚拟局域网内。cni0 虚拟局域网通过主机路

40、由以及网口 eth0 与外部通信。在网络协议栈这一层,我们可以通过编程 netfilter 过滤器框架,来实现集群节点的反向代理。实现反向代理,归根结底,就是做 DNAT,即把发送给集群服务 IP 和端口的数据包,修改成发给具体容器组的 IP 和端口。参考 netfilter 过滤器框架的图,我们知道,在 netfilter 里,可以通过在 PRE-ROUTING,OUTPUT 以及 POSTROUGING 三个位置加入 NAT 规则,来改变数据包的源地址或目的地址。因为这里需要做的是 DNAT,即改变目的地址,这样的修改,必须在路由(ROUTING)之前发生以保证数据包可以被路由正确处理,所

41、以实现反向代理的规则,需要被加到 PREROUTING 和 OUTPUT 两个位置。其中,PREOURTING 的规则,用来处理从 Pod 访问服务的流量。数据包从 Pod 网络 veth 发送到 cni0 之后,进入主机协议栈,首先会经过 netfilterPREROUTING 来做处理,所以发给服务的数据包,会在这个位置做 DNAT。经过集群服务的三个要点和一种实现集群服务的三个要点和一种实现把过滤功能和管道解耦之后,所有对数据包的处理,都变成了对表的配置。而管道上的 5 个切口,仅仅变成了流量的出入口,负责把流量发送到过滤中心,并把处理之后的流量沿着管道继续传送下去。如上图,在表中,ne

42、tfilter 把规则组织成为链。表中有针对每个管道切口的默认链,也有我们自己加入的自定义链。默认链是数据的入口,默认链可以通过跳转到自定义链来完成一些复杂的功能。这里允许增加自定义链的好处是显然的。为了完成一个复杂过滤功能,比如实现 K8S 集群节点的反向代理,我们可以使用自定义链来模块化我们规则。用自定义链实现服务的反向代理集群服务的反向代理,实际上就是利用自定义链,模块化地实现了数据包的DNAT 转换。KUBE-SERVICE 是整个反向代理的入口链,其对应所有服务的总入口;KUBE-SVC-XXXX 链是具体某一个服务的入口链,KUBE-SERVICE 链会根据服务 IP,跳转到具体服

43、务的 KUBE-SVC-XXXX 链;而 KUBE-SEP-XXXX链代表着某一个具体 Pod 的地址和端口,即 endpoint,具体服务链 KUBE-SVC-XXXX 会以一定算法(一般是随机),跳转到 endpoint 链。集群服务的三个要点和一种实现55而如前文中提到的,因为这里需要做的是 DNAT,即改变目的地址,这样的修改,必须在路由之前发生以保证数据包可以被路由正确处理。所以 KUBE-SER-VICE 会被 PREROUTING 和 OUTPUT 两个默认链所调用。总结通过这篇文章,大家应该对 K8S 集群服务的概念以及实现,有了更深层次的认识。我们基本上需要把握三个要点。一、

44、服务本质上是负载均衡;二、服务负载均衡的实现采用了与服务网格类似的 Sidecar 的模式,而不是 LVS 类型的独占模式;三、kube-proxy 本质上是一个集群控制器。除此之外,我们思考了过滤器框架的设计,并在此基础上,理解使用 iptables 实现的服务负载均衡的原理。镜像拉取这件小事导读:相比K8s集群的其他功能,私有镜像的自动拉取,看起来可能是比较简单的。而镜像拉取失败,大多数情况下都和权限有关。所以,在处理相关问题的时候,我们往往会轻松的说:这问题很简单,肯定是权限问题。但实际的情况是,我们经常为一个问题,花了多个人的时间却找不到原因。这主要还是我们对镜像拉取,特别是私有镜像自

45、动拉取的原理理解不深。这篇文章,作者将带领大家讨论下相关原理。顺序上来说,私有镜像自动拉取会首先通过阿里云Acrcredentialhelper组件,再经过K8s集群的APIServer和kubelet组件,最后到docker容器运行时。但是我的叙述,会从后往前,从最基本的docker镜像拉取说起。镜像拉取这件小事为了讨论方便,我们来设想一个场景。很多人会使用网盘来存放一些文件,像照片,文档之类。当我们存取文件的时候,我们需要给网盘提供账户密码,这样网盘服务就能验证我们的身份。这时,我们是文件资源的所有者,而网盘则扮演着资源服务器的角色。账户密码作为认证方式,保证只有我们自己可以存取自己的文件

46、。这个场景足够简单,但很快我们就遇到新需求:我们需要使用一个在线制作相册镜像拉取这件小事镜像拉取这件小事这六步理解起来不容易,主要是因为安全协议的设计,需要考虑协议的易证明性,所以我们换一种方式来解释这个协议。简单来说,这个协议其实就做了两件事情:在用户授权的情况下,三方应用获取token所表示的临时访问权限;然后三方应用使用这个token去获取资源。如果用网盘的例子来说明的话,那就是用户授权网盘服务给相册应用创建临时token,然后相册应用使用这个token去网盘服务获取用户的照片。实际上OAuth2.0各个变种的核心差别,在于第一件事情,就是用户授权资源服务器的方式。镜像拉取这件小事镜像拉

47、取这件小事Docker扮演的角色大图镜像仓库Registry的实现,目前使用“把账户密码给三方应用”的方式。即假设用户对Docker足够信任,用户直接将账户密码交给Docker,然后Docker使用账户密码跟鉴权服务器申请临时token。理解 docker login首先,我们在拉取私有镜像之前,要使用dockerlogin命令来登录镜像仓库。这里的登录其实并没有和镜像仓库建立什么会话之类的关系。登录主要就做了三件事情:第一件事情是跟用户要账户密码。如下图,当执行登录命令,这个命会提示输入账户密码,这件事情对应的是大图的第一步。镜像拉取这件小事镜像拉取这件小事是账户密码的base64编码。拉取

48、镜像是怎么回事镜像一般会包括两部分内容,一个是manifests文件,这个文件定义了镜像的元数据,另一个是镜像层,是实际的镜像分层文件。镜像拉取基本上是围绕这两部分内容展开。因为我们这篇文章的重点是权限问题,所以我们这里只以manifests文件拉取为例。拉取manifests文件,基本上也会做三件事情:首先,docker直接访问镜像 manifests 的地址,以便获取Www-Authenti-cate头字段。这个字段包括鉴权服务器的地址Bearerrealm,镜像服务地址service,以及定义了镜像和操作的scope。接着,docker访问上边拿到的Bearerrealm地址来鉴权,以及

49、在鉴权之后获取一个临时的token。这对应协议大图使用账户密码获取临时token这一镜像拉取这件小事镜像拉取这件小事具体来说,步骤如下:1.创 建secret。这 个secret 的.dockerconfigjson 数 据 项 包 括 了 一 份base64编码的docker.json文件;2.创建pod,且pod编排中imagePullSecrets指向第一步创建的secret;3.Kubelet作为集群控制器,监控着集群的变化。当它发现新的pod被创建,就会通过APIServer获取pod的定义,这包括imagePullSecrets引用的secret;4.Kubelet调用docker

50、创建容器且把.dockerconfigjson传给docker;5.最后docker使用解码出来的账户密码拉取镜像,这和上一节的方法一致。进阶方式上边的功能,一定程度上解决了集群节点登录镜像仓库不方便的问题。但是我们在创建Pod的时候,仍然需要给Pod指定imagePullSecrets。K8s通过变更准入镜像拉取这件小事镜像拉取这件小事具体来说,控制器会监听acr-configuration这个configmap的变化,其主要关心acr-registry和watch-namespace这两个配置。前一个配置指定为临时账户授权的镜像仓库地址,后一个配置管理可以自动拉取镜像的命名空间。当控制器发

展开阅读全文
相似文档                                   自信AI助手自信AI助手
猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 研究报告 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        获赠5币

©2010-2024 宁波自信网络信息技术有限公司  版权所有

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服