1.0 环境版本控制
序号 | 名称 | 版本 | 备注 |
---|---|---|---|
01 | Kubernetes | 1.25 | |
01 | kubeasz | 3.4.1 | |
02 | Docker | 20.10.21 | |
03 | Java | 1.17 | |
04 | Harbor | 2.0.2 | |
05 | Prometheus | 2.40.3 | |
06 | Istio | 1.16.0 |
注意:
在新版本Kubernetes环境(1.24以及以上版本)下官方不在支持docker作为容器运行时
2.0 什么是Kubernetes
2.1 命名、logo等设计概念
Kubernetes单词起源于古希腊,是舵手的意思。logo既像一张渔网,又像一个罗盘、船舵
另一层意思,Google想表达的是,docker的logo是一条满载货物在大海中遨游的鲸鱼,Kubernetes捕获和引导docker的运行。
2.2 技术概念
Kubernetes,也称为K8s,是一个用于自动化部署、扩展和管理集装箱应用程序的开源系统。它将组成应用程序的容器分组为逻辑单元,以便于管理和发现。
一个不太合适的理解:k8s 相当于 docker 容器的管理平台。
3.0 Kubernetes特征
- 一切以服务为中心(在什么地方运行,都是无差别的)
- 自动化(k8s中的服务可以自动扩容、升级、更新、部署等)
4.0 Kubernetes和Docker的关系
Kubernetes,可以看成Docker的上层架构。
以Docker标准的架构为基础,打造的一个分布式架构系统。
但Kubernetes不一定要依赖于Docker,Docker只是一个产品,但Docker技术是一系列的标准。
5.0 Kubernetes的核心概念
假设一个普通的docker容器,Container。
容器中放置各种镜像。
5.1 pod概念
pod:第一个介绍的就是k8s中新的概念,k8s 的最小调度单元,相当于逻辑主机的概念。
pod特征:
pod里面可以多个容器。
里面的所有容器都运行在一台机器上。
容器都有自己唯一的id
每个pod内都会有一个容器——Pause,会有一个自己固定的镜像,作用:根容器,目的主要是将其他容器关联到根容器上,附带共享资源(共享存储、网络、运行信息等)。
5.2 ReplicaSet(Rs)概念
pod的上一层,叫ReplicaSet(Rs)(副本集),副本集会管理多个pod。
ReplicaSet的作用就是当一个pod出现问题,就会调度起另一个pod运行,保障服务稳定。
5.3 Deployment概念
ReplicaSet(Rs)(副本集)的上一层,叫Deployment(部署)。
比如,一个旧的应用,运行了2个实例(pod),当想要更新这个应用。此时就相当于更新Deployment容器。
Deployment会自动创建一个新的ReplicaSet(Rs)(副本集)。
滚动先启动一个新的pod。新的pod和 旧的一模一样,当然,id会更新。
通过健康检查后,此时会有3个实例。
然后会删掉旧版本,这时候运行一个新版本和一个旧版本实例。
旧版本删除一个以后,新的ReplicaSet(Rs)(副本集)会创建另一个pod,并管理起来。
然后删掉旧的ReplicaSet(Rs)(副本集)
此时,
服务更新
的过程就完成了。
以上Deployment操作才是人为层面参与进行的,Deployment下的ReplicaSet(Rs)(副本集)和pod的操作由k8s自动完成。
5.4 Service概念
Service概念涉及到label(标签)概念。
k8s中很多概念都可以打标签,比如Deployment(部署)可以打标签,pod也可以打标签。
比如,我们运用了一个单点登录的服务,可以打标签app:login
。
此时我们创建一个Service,Service可以配置Selector,表明这个Service负责管理的标签为app=login
的对象。
Service对外,会有一个ClusterIP。
Client(客户端)可以通过ClusterIP访问到Service,进行一些操作。
6.0 Kubernetes的架构设计
6.1 节点(Node)概念
k8s肯定会需要很多的服务器(节点)。
服务器分为2种角色。
一种叫做master节点(Node)(主节点),一种叫做work节点(Node)。
master负责去管理各种work节点。
6.2 组件——EDCD
k8s当然也有自己的数据存储持久化(比如文件存储、数据库存储、中间件存储等),这写信息就需要放在一个地方,k8s选择的组件叫EDCD
(EDCD集群)。
比如:
- master节点上,有一个组件
ApiServer
,是操作k8s的唯一入口。ApiServer
接到客户端请求后,通过k8s的另一个组件Scheduler(调度器)
获取信息。Scheduler
会收集每一个work节点
的详细信息(比如资源、内存、CPU、节点上运行了什么样的服务等)。Scheduler
通过策略、算法(主要是预选策略、优选策略),最终选择一个最优的work节点
,将work节点
和pod
建立起关系。Scheduler
告诉ApiServer
,这个pod
可以运行在某个work节点
上。ApiServer
把这个信息存到EDCD
中,实现数据存储持久化。
6.3 Controller Manager
pod和work节点绑定之后,需要将pod真正启动起来。这时候需要另一个组件ControllerManager
,ControllerManager
,集群内部控制中心,负责维护各种k8s对象。
Controller Manager 由 kube-controller-manager 和 cloud-controller-manager 组成,是 Kubernetes 的大脑,它通过 apiserver 监控整个集群的状态,并确保集群处于预期的工作状态。
Controller Manager通过 apiserver ,获取EDCD
存储的节点信息的变化,使pod运行起来。
kube-controller-manager 由一系列的控制器组成
序号 | 名称 | 说明 |
---|---|---|
1 | Certificate Controller | |
2 | ClusterRoleAggregation Controller | |
3 | Node Controller | |
4 | CronJob Controller | |
5 | Daemon Controller | |
6 | StatefulSet Controller | |
7 | Endpoint Controller | |
8 | Endpointslice Controller | |
9 | Garbage Collector | |
10 | Namespace Controller | |
11 | Job Controller | |
12 | Pod AutoScaler | |
13 | PodGC Controller | |
14 | ReplicaSet Controller | |
15 | Service Controller | |
16 | ServiceAccount Controller | |
17 | Volume Controller | |
18 | Resource quota Controller | |
19 | Disruption Controller |
cloud-controller-manager 在 Kubernetes 启用 Cloud Provider 的时候才需要,用来配合云服务提供商的控制,也包括一系列的控制器,如
序号 | 名称 | 说明 |
---|---|---|
1 | Node Controller | |
2 | Node Lifecycle Controller | |
3 | Route Controller | |
4 | Service Controller |
6.4 pod怎么在work节点上运行起来
每一个work节点需要装好一个服务——Kubelet
。
Kubelet:主要负责维护pod的生命周期,容器的mem、网络等,最终Kubelet会调用本地的docker,运行起容器、和各种pod。
7.0 Kubernetes的认证密码学原理
我们已经知道k8s中,所有的资源,都是通过组件ApiServer来实现。
k8s集群关键在于,ApiServer如何去实现客户端的身份,通过身份(认证)去访问权限的授权授权()。
密码学的2个概念。
- 对称加密:加密解密同一个秘钥
- 非对称加密:加密解密2个秘钥且不相同。
这2个秘钥称为密钥对,加密的就叫公钥,解密的叫私钥。
非对称加密的缺点就是算法复杂,加密和解密消耗非常大。
密码学解决方案:
ServiceX(服务X)将对称加密的秘钥A,
通过非对称加密的公钥B加密后,
发送给另一台服务ServiceY(服务Y),
ServiceY(服务Y)非对称加密的私钥C进行解密,
获得对称加密的秘钥A。
接下来2个服务通过对称加密进行通讯即可。
这种解决方案,就是鼎鼎大名的SSL/TLS
协议。(https就是通过这2个协议进行加密实现的)
这样协议还是有风险的。
截获ServiceY(服务Y)发送到ServiceX(服务X)的公钥。
ServiceX(服务X)拿到公钥后加密自己的私钥
ServiceX(服务X)传输时,被截取数据,拿截取的公钥当成私钥解密,得到对称加密的私钥。
此时,数据就已经不安全了。
当然,以上的技术实现难度很高。
新的解决方案就是通过CA(证书认证)实现。
使用 CA ,证书认证机构,所有合法的网站的证书,都保存在 CA。
ServiceX(服务X)拿到公钥后,向CA认证证书请求,判断公钥是否合法。合法后再去通讯,保证公钥是一个正常的公钥。
这个就是 https 的实现机制,所有的 https 网站相当于ServiceB, 公开声明一个公钥,而且这个公钥要注册到证书认证机构。
8.0 Kubernetes的认证和授权
8.1 认证
k8s用到的CA证书是自己颁发给自己的自定义CA。
k8s提供的认证方式有:
- 集群外部访问APiServer
- 客户端证书认证(TLS双向认证)
- BearerToken:相当于一个复杂的密码,定义在ApiServer中,客户端每次请求带上这个密码,就可以进行通讯。
- k8s内部进行通讯,比如pod和ApiServer进行通讯
- ServiceAccount(namespace、token、ca)
8.2 授权
k8s中有一系列鉴权的机制。
比如:
ABAC
WebHook
RBAC(k8s 1.6 引入)(全称:Role Based Access Control,基于角色的访问控制)
RBAC是最新的一种授权策略,相对于其他两种,目前RBAC也是一种更好地选择。
因此只需要了解掌握RBAC即可。
8.3 RBAC
RBAC权限系统遵循这样一种三层结构。
user(用户) Role (角色) Authority(权限)
User
User层面上分为2种用户。
User:普通用户
ServiceAccount:集群内部访问ApiServer的用户
Role
name:名字
resourse:哪些权限
Verbs(动作 ):拥有哪些操作
Authority
权限也分为2种
Resource:资源维度
Verbs:可以理解为增删改查(CURD)维度。
k8s没有数据库,通过RolBinding
资源实现一种类似于数据库关系绑定的建立。
k8s中有个非常重要的概念——namespace,namespace作用主要是对k8s中的资源起到隔离的作用。
如果一个角色,只能访问某个或者某几个命名空间下的资源,当下权限就不兼容了,因为不包含命名空间体系参与。
因此,k8s将角色放入一个namespace下,如果拥有某个角色,则只能拥有当前这个命名空间下的角色。
如果用户需要整个集群得到角色,则需要用到如下的定义:
ClusterRole:集群的角色。
ClusterRoleBinding:集群的角色绑定。
8.4 API 对象
Role
、
ClusterRole
、
RoleBinding
、
ClusterRoleBinding
。
- Role 总是用来在某个名字空间内设置访问权限; 在你创建 Role 时,你必须指定该 Role 所属的名字空间。
- Role 和 ClusterRole只能选其中一个。
如果希望在名字空间内定义角色,应该使用 Role;
如果希望定义集群范围的角色,应该使用 ClusterRole。
- ClusterRole为以下资源授予访问权限:
- 集群范围资源(比如节点(Node))
- 非资源端点(比如
/healthz
)- 跨名字空间访问的名字空间作用域的资源(如 Pod)
RoleBinding 和 ClusterRoleBinding的区别:
https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding
AdmisionControl
AdmisionControl:准入控制
准入控制可以理解为一个个的小插件,各种小插件独立存在,没有任何关系,依次执行各种准入策略,如果通了,那就表示准入成功。
常见的几种AdmisionControl:
AlwaysAdmit:总是允许所有的请求
此插件已被弃用,因其行为与没有准入控制器一样。AlwaysDeny:总是拒绝所有的请求(一般用于测试)
由于它没有实际意义,已被弃用。ServiceAccount:总是允许所有的请求,和上面说的ServiceAccount完全不是同一个概念。
作用是给ServiceAccount提供自动化,辅助ServiceAccount去做一些事情。
比如某些pod,没有ServiceAccount,它会自动去添加当前命名空间默认的一个ServiceAccount。
确保ServiceAccount在每个pod都存在。
PS:强烈推荐为 Kubernetes 项目启用此准入控制器。 如果你打算使用 Kubernetes 的 ServiceAccount 对象,你应启用这个准入控制器。DenyEscolatingExec:用于拒绝所有的Exec和tech到我们的具有一些特权的POD上,用于限制登录到我们的容器里执行命令的一个安全层面的插件
9.0 集群搭建方案对比
9.1 社区方案
- 杂乱
非常的杂,非常的多,五花八门的,一些是个人做的方案,一些是一些小团队出的方案,有点方案是单机部署的,有的方案是部署集群的,还有一些是高可用的方案,还有一些是非高可用的方案。
- 不可靠
一方面体现在虽然大部分的解决方案都号称简化,但其实它们并不简单,如果安装过程中出现任何的问题都是出于字面很难定位原因,非常的难以解决,如果对方案涉及到的技术(如Linux Shell)不是很懂 ,出现问题基本上是搞不定。
- 升级难
比如使用了一个方案,半年前是1.0版本,现在想升级到1.3,你可定还是用之前使用的那个方案,因为你比较熟悉了。但是很有可能你发现之前那个方案就停留在了1.0,不支持更高级版本的安装,所以你只能用另外的方式做了。
综上,社区方案不推荐。
9.2 kubeadm(官方推荐)
优点:
- 优雅
使用kubeadm去安装几乎所有的组件都是运行在容器中的,并且都是运行k8s的pod里面,这个是它非常优雅的一个地方
- 简单
安装的过程非常的简单,配上一个配置文件,运行一个命令kubeadm-init,它几乎会帮你做所有的事情,过程还是非常简单的。
- 支持高可用
不但支持非高可用的集群安装,也支持高可用的集群安装
- 升级方便
升级可以说是随时随地,只要拿到了kubeadm的命令,肯定是可以部署最新的k8s的集群,官方出的,肯定会跟k8s同步更新。
缺点:
- 不易维护
对容器不太熟悉,或者是说对k8s机制不太熟悉的运维人员,维护可能非常的困难的。传统的运维去运维Kubernetes的POD,很难上手
- 文档不够细致
如果直接按照官方的文档去做,很多时候会卡主,或者是出现什么问题,很有可能不知道说的这一步是什么意思,一些变量不知道该如何去替换,有的时候文档里面会有一些错误。曾经1.1的文档中kubectl中的yum配置文件在的内容是有缺失的,就导致很多用户花费很长时间去解决这个问题。
9.3 Binary
优点:
- 易于维护
所有都是通过进程直接运行的,并需要一点一点去配置,手动去运行起来,这样会非常清楚每个组件怎么运行,有什么样的调用关系,非常易于去理解。
- 灵活
不管搭建单机,还是高可用,需要一个模块一个模块的去运行起来的,你想怎么配置就怎么配置,控制你来非常的灵活
- 升级方便
这个跟Kubeadm一样,可以一点点去升级,不会对真个集群造成太大影响。
缺点
- 没有文档
在官方文档里,都没有发现关于二进制的安装和配置的一些文档。
- 安装复杂
一方面原因跟没有文档有一定的关系,还有个重要的原因是每一个组件都需要手动去进行配置,包括数字证书、认证授权CA都需要一步步的生成。
9.4 方案的选择
官方的方案有两种:kubeadm、Binary(二进制),都有各自有各自的优缺点,可以根据自身情况做选择。
目前生产环境中,大部分的公司使用Binary(二进制)的方式比较多。