vps主机上搭建网站,互联网招商平台,aspcms是网站什么漏洞,高端企业网站建设制作概述
不知道大家有没有意识到一个现实#xff0c;就是大部分时候#xff0c;我们已经不像以前一样通过命令行#xff0c;或者可视窗口来使用一个系统了现在我们上微博、或者网购#xff0c;操作的其实不是眼前这台设备#xff0c;而是一个又一个集群 通常#xff0c;这样…概述
不知道大家有没有意识到一个现实就是大部分时候我们已经不像以前一样通过命令行或者可视窗口来使用一个系统了现在我们上微博、或者网购操作的其实不是眼前这台设备而是一个又一个集群 通常这样的集群拥有成百上千个节点每个节点是一台物理机或虚拟机集群一般远离用户坐落在数据中心为了让这些节点互相协作对外提供一致且高效的服务集群需要操作系统Kubernetes 就是这样的操作系统比较 Kubernetes 和单机操作系统Kubernetes 相当于内核它负责集群软硬件资源管理并对外提供统一的入口用户可以通过这个入口来使用集群和集群沟通 而运行在集群之上的程序与普通程序有很大的不同这样的程序是“关在笼子里”的程序它们从被制作到被部署再到被使用都不寻常。我们只有深挖根源才能理解其本质
“关在笼子里”的程序 1 ) 代码
我们使用 go 语言写了一个简单的 web 服务器程序 app.go这个程序监听在 2580 这个端口通过 http 协议访问这个服务的根路径服务会返回“This is a small app for kubernetes…”字符串
package main
import (github.com/gorilla/muxlognet/http
)func about(w http.ResponseWriter, r *http.Request) {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))
}使用 go build 命令编译这个程序产生 app 可执行文件 这是一个普通的可执行文件它在操作系统里运行会依赖系统里的库文件 # ldd app
linux-vdso.so.1 (0x00007ffd1f7a3000)
libpthread.so.0 /lib64/libpthread.so.0 (0x00007f554fd4a000)
libc.so.6 /lib64/libc.so.6 (0x00007f554f97d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f554ff66000)2 ) “笼子” 为了让这个程序不依赖于操作系统自身的库文件我们需要制作容器镜像即隔离的运行环境, Dockerfile 是制作容器镜像的“菜谱” 我们的菜谱就只有两个步骤下载一个 centos 的基础镜像把 app 这个可执行文件放到镜像中 /usr/local/bin 目录中去 FROM centos
ADD app /usr/local/bin3 ) 地址
制作好的镜像存再本地我们需要把这个镜像上传到镜像仓库里去这里的镜像仓库相当于应用商店我们使用阿里云的镜像仓库上传之后镜像地址是 : registry.cn-hangzhou.aliyuncs.com/kube-easy/app:latest镜像地址可以拆分成四个部分仓库地址 / 命名空间 / 镜像名称 : 镜像版本显然镜像上边的镜像在阿里云杭州镜像仓库使用的命名空间是 kube-easy镜像名 : 版本是 app:latest 至此我们有了一个可以在 Kubernetes 集群上运行的“关在笼子里”的小程序
得其门而入 1 ) 入口
Kubernetes 作为操作系统和普通的操作系统一样有 API 的概念有了API集群就有了入口有了 API我们使用集群才能得其门而入Kubernetes 的 API 被实现为运行在集群节点上的组件 API Server这个组件是典型的 web 服务器程序通过对外暴露 http(s) 接口来提供服务 这里我们创建一个阿里云 Kubernetes 集群登录集群管理页面我们可以看到API Server 的公网入口API Server 内网连接端点 https://xx.xxx.xxx.xxx:6443
2 ) 双向数字证书验证
阿里云 Kubernetes 集群 API Server 组件使用基于 CA 签名的双向数字证书 认证来保证客户端与 api server 之间的安全通信。这句话很绕口对于初学者不太好理解我们来深入解释一下。从概念上来讲数字证书是用来验证网络通信参与者的一个文件这和学校颁发给学生的毕业证书类似在学校和学生之间学校是可信第三方 CA而学生是通信参与者如果社会普遍信任一个学校的声誉的话那么这个学校颁发的毕业证书也会得到社会认可参与者证书和 CA 证书可以类比毕业证和学校的办学许可证这里我们有两类参与者CA 和普通参与者与此对应我们有两种证书CA 证书和参与者证书另外我们还有两种关系证书签发关系以及信任关系这两种关系至关重要我们先看签发关系如下图我们有两张 CA 证书三个参与者证书其中最上边的 CA 证书签发了两张证书 一张是中间的 CA 证书另一张是右边的参与者证书中间的 CA 证书签发了下边两张参与者证书这六张证书以签发关系为联系形成了树状的证书签发关系图 然而证书以及签发关系本身并不能保证可信的通信可以在参与者之间进行以上图为例假设最右边的参与者是一个网站最左边的参与者是一个浏览器浏览器相信网站的数据不是因为网站有证书也不是因为网站的证书是 CA 签发的而是因为浏览器相信最上边的 CA也就是信任关系理解了 CA证书参与者证书签发关系以及信任关系之后我们回过头来看“基于 CA 签名的双向数字证书认证”客户端和 API Server 作为通信的普通参与者各有一张证书而这两张证书都是由 CA 签发我们简单称它们为集群CA 和客户端 CA客户端信任集群 CA所以它信任拥有集群 CA 签发证书的 API Server反过来 API Server 需要信任客户端 CA它才愿意与客户端通信阿里云 Kubernetes 集群集群 CA 证书和客户端 CA 证书实现上其实是一张证书所以我们有这样的关系图 3 KubeConfig 文件 登录集群管理控制台我们可以拿到 KubeConfig 文件 这个文件包括了客户端证书集群 CA 证书以及其他 证书使用 base64 编码所以我们可以使用base64 工具解码证书并使用 openssl 查看证书文本。 首先客户端证书的签发者 CN 是集群 id c0256a3b8e4b948bb9c21e66b0e-1d9a72 而证书本身的 CN 是子账号 252771643302762862 Certificate:Data:Version: 3 (0x2)Serial Number: 787224 (0xc0318)Signature Algorithm: sha256WithRSAEncryptionIssuer: Oc0256a3b8e4b948bb9c21e66b0e1d9a72, OUdefault, CNc0256a3b8e4b948bb9c21e66b0e1d9a72ValidityNot Before: Nov 29 06:03:00 2018 GMTNot After : Nov 28 06:08:39 2021 GMTSubject: Osystem:users, OU, CN252771643302762862其次只有在 API Server 信任客户端 CA 证书的情况下上边的客户端证书 才能通过 API Server 的验证 kube-apiserver 进程通过 client-ca-file 这个参数指定其信任的客户端 CA 证书其指定的证书是 /etc/kubernetes/pki/apiserver-ca.crt 这个文件实际上包含了两张客户端 CA 证书其中一张和集群管控有关系 这里不做解释另外一张如下它的 CN 与客户端证书的签发者 CN 一致
Certificate:Data:Version: 3 (0x2)Serial Number: 787224 (0xc0318)Signature Algorithm: sha256WithRSAEncryptionIssuer: Oc0256a3b8e4b948bb9c21e66b0e1d9a72, OUdefault, CNc0256a3b8e4b948bb9c21e66b0e1d9a72ValidityNot Before: Nov 29 06:03:00 2018 GMTNot After : Nov 28 06:08:39 2021 GMTSubject: Osystem:users, OU, CN252771643302762862再 次API Server 使 用 的 证 书 由 kube-apiserver 的 参 数 tls-cert-file决定 这个参数指向证书 /etc/kubernetes/pki/apiserver.crt。这个证书的CN 是 kube-apiserver 签 发 者 是 c0256a3b8e4b948bb9c21e66b0e-1d9a72即集群 CA 证书 Certificate:Data:Version: 3 (0x2)Serial Number: 2184578451551960857 (0x1e512e86fcba3f19)Signature Algorithm: sha256WithRSAEncryptionIssuer: Oc0256a3b8e4b948bb9c21e66b0e1d9a72, OUdefault, CNc0256a3b8e4b948bb9c21e66b0e1d9a72ValidityNot Before: Nov 29 03:59:00 2018 GMTNot After : Nov 29 04:14:23 2019 GMTSubject: CNkube-apiserver最后客户端需要验证上边这张 API Server 的证书因而 KubeConfig 文件里包含了其签发者即集群 CA 证书 对比集群 CA 证书和客户端 CA 证书发现两张证书完全一样这符合我们的预期 Certificate:Data:Version: 3 (0x2)Serial Number: 786974 (0xc021e)Signature Algorithm: sha256WithRSAEncryptionIssuer: CCN, STZheJiang, LHangZhou, OAlibaba, OUACS, CNrootValidityNot Before: Nov 29 03:59:00 2018 GMTNot After : Nov 24 04:04:00 2038 GMTSubject: Oc0256a3b8e4b948bb9c21e66b0e1d9a72, OUdefault, CNc0256a3b8e4b948bb9c21e66b0e1d9a724 访问 理解了原理之后我们可以做一个简单的测试 我们以证书作为参数使用 curl访问 api server并得到预期结果 # curl --cert ./client.crt --cacert ./ca.crt --key ./client.key https://xx.xx.xx.xxx:6443/api/
{kind: APIVersions,versions: [v1],serverAddressByClientCIDRs: [{clientCIDR: 0.0.0.0/0,serverAddress: 192.168.0.222:6443}]
}择优而居
1 ) 两种节点一种任务
如开始所讲Kubernetes 是管理集群多个节点的操作系统这些节点在集群中的角色却不必完全一样Kubernetes 集群有两种节点master 节点和 worker 节点这种角色的区分实际上就是一种分工master 负责整个集群的管理其上运行的以集群管理组件为主这些组件包括实现集群入口的 api server而 worker 节点主要负责承载普通任务在 Kubernetes 集群中任务被定义为 pod 这个概念pod 是集群可承载任务的原子单元pod 被翻译成容器组其实是意译因为一个 pod 实际上封装了多个容器化的应用原则上来讲被封装在一个 pod 里边的容器应该是存在相当程度的耦合关系 2 ) 择优而居
调度算法需要解决的问题是替 pod 选择一个舒适的“居所”让 pod 所定义的任务可以在这个节点上顺利地完成为了实现“择优而居”的目标Kubernetes 集群调度算法采用了两步走的策略 第一步从所有节点中排除不满足条件的节点即预选第二步给剩余的节点打分最后得分高者胜出即优选 下边我们使用文章开始的时候制作的镜像创建一个 pod并通过日志来具体分析一下这个 pod 怎么样被调度到某一个集群节点
3 ) Pod 配置
首先我们创建 pod 的配置文件配置文件格式是 json这个配置文件有三个地方比较关键分别是镜像地址命令以及容器的端口
{apiVersion: v1,kind: Pod,metadata: {name: app},spec: {containers: [{name: app,image: registry.cn-hangzhou.aliyuncs.com/kube-easy/app:latest,command: [app],ports: [{containerPort: 2580}]}]}
}4 ) 日志级别 集群调度算法被实现为运行在 master 节点上的系统组件这一点和 api server类似 其对应的进程名是 kube-scheduler。kube-scheduler 支持多个级别的日志输出 但社区并没有提供详细的日志级别说明文档。查看调度算法对节点进行筛选、打分的过程 我们需要把日志级别提高到 10即加入参数 --v10 kube-scheduler --address127.0.0.1 --kubeconfig/etc/kubernetes/scheduler.conf --leader-electtrue --v105 ) 创建 Pod 使用 curl以证书和 pod 配置文件等作为参数通过 POST 请求访问 api server 的接口 我们可以在集群里创建对应的 pod # curl -X POST -H Content-Type: application/json;charsetutf-8 --cert ./
client.crt --cacert ./ca.crt --key
./client.key https://47.110.197.238:6443/api/v1/namespaces/default/pods -d
app.json6 ) 预选
预选是 Kubernetes 调度的第一步这一步要做的事情是根据预先定义的规则把不符合条件的节点过滤掉不同版本的 Kubernetes 所实现的预选规则有很大的不同但基本的趋势是预选规则会越来越丰富比较常见的两个预选规则是 PodFitsResourcesPred 和 PodFitsHostPortsPred前一个规则用来判断一个节点上的剩余资源是不是能够满足 pod 的需求而后一个规则检查一个节点上某一个端口是不是已经被其他 pod 所使用了下图是调度算法在处理测试 pod 的时候输出的预选规则的日志这段日志记录了预选规则 CheckVolumeBindingPred 的执行情况某些类型的存储卷PV只能挂载到一个节点上这个规则可以过滤掉不满足 pod 对 PV 需求的节点从 app 的编排文件里可以看到pod 对存储卷并没有什么需求所以这个条件并没有过滤掉节点 7 ) 优选
调度算法的第二个阶段是优选阶段这个阶段kube-scheduler 会根据节点可用资源及其他一些规则给剩余节点打分目前CPU 和内存是调度算法考量的两种主要资源但考量的方式并不是简单的剩余 CPU、内存资源越多得分就越高日志记录了两种计算方式 LeastResourceAllocationBalancedResourceAllocation 前一种方式计算 pod 调度到节点之后节点剩余 CPU 和内存占总 CPU 和内存的比例比例越高得分就越高第二种方式计算节点上 CPU 和内存使用比例之差的绝对值绝对值越大得分越少 这两种方式一种倾向于选出资源使用率较低的节点第二种希望选出两种资源使用比例接近的节点 这两种方式有一些矛盾最终依靠一定的权重来平衡这两个因素 除了资源之外优选算法会考虑其他一些因素 比如 pod 与节点的亲和性或者如果一个服务有多个相同 pod 组成的情况下多个 pod 在不同节点上的分散程度 这是保证高可用的一种策略 8 ) 得分
最后调度算法会给所有的得分项乘以它们的权重然后求和得到每个节点最终的得分因为测试集群使用的是默认调度算法而默认调度算法把日志中出现的得分项所对应的权重都设置成了 1所以如果按日志里有记录得分项来计算最终三个节点的得分应该是 29,28 和 29 之所以会出现日志输出的得分和我们自己计算的得分不符的情况是因为日志并没有输出所有的得分项猜测漏掉的策略应该是 NodePreferAvoidPodsPriority这个策略的权重是 10000每个节点得分 10所以才得出最终日志输出的结果
总结
我们以一个简单的容器化 web 程序为例着重分析了客户端怎么样通过 Kubernetes 集群 API Server 认证以及容器应用怎么样被分派到合适节点这两件事情在分析过程中我们弃用了一些便利的工具比如 kubectl或者控制台我们用了一些更接近底层的小实验比如拆解 KubeConfig 文件再比如分析调度器日志来分析认证和调度算法的运作原理