K8S的内容是要比docker多很多的。
kubernetes中文官网: Kubernetes(K8S)中文文档_Kubernetes中文社区
1、认识kubernetes
1.1、什么是kubernetes?
kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,kubernetes的目标是然该部署容器化的应用简单而且高效,kubernetes提供了应用部署,规划,更新,维护的一种机制。其实提到管理容器第一想到的肯定是docker compose,只不过他是单主机的;而k8s是天然的用于多主机管理的应用,显然功能更加强大。
kubernetes这个名字源于希腊语,以为“舵手”、“飞行员”。“K8S”这个缩写是因为k和s之间有八个字符,所以这样缩写。kubernetes是谷歌开源的一个项目,其前身就是google内部使用的borg系统(borg积累了google十多年的大规模运行生产工作负载的经验)。
kubernetes的logo其实就是一个“船舵”,结合docker的鲸鱼上面背着集装箱的logo就能知道k8s是用于管理和驾驭docker的。
1.2、为什么需要kubernetes?
1.2.1、服务部署的发展历程
(1)传统部署 —— 环境不隔离
一台物理机上部署多个应用。隔离性不好,资源争夺。
(2)虚拟化部署 —— 占用资源过大
对物理机进行虚拟化,虚拟化处多个虚拟机。每个虚拟机都可以视为一个独立的机器。
优点:解决了环境隔离的问题。
缺点:虚拟化偏重资源损耗过大,创建速度较慢。
(3)容器化部署
容器用的资源是Linux原本的资源,而不是重新搞一套。没有过重的虚拟化对资源消耗明显减少了。容器的创建效率也非常高,秒级别。
1.2.2、容器化带来的新的问题
(1)容器的生命周期大大缩短。
频繁的删除重建就会给容器的网络、磁盘等资源管理(不稳定)带来很多问题;而k8s可以很好的解决这些问题。
(2)k8s提供了很多东西。
自我修复:检测到异常后自动重启;
自动伸缩:自动扩缩容;
自动部署和回滚:自动完成部署和回滚;
服务发现和负载均衡:k8s自身就有服务发现和负载均衡的功能;
机密和配置管理:对于敏感的非敏感的数据k8s都可以管理起来;
存储编排:把所有的机器的存储资源管理成一个抽象的虚拟磁盘,容器统一访问虚拟磁盘;
批处理:批量的处理;
1.3、企业级容器调度平台(同级别产品介绍)
同级别产品介绍!!!!
以前是三足鼎立,现在google一家独大。
1.3.1、Apache Mesos
Mesos:Apache的一个资源统一管控的工具,需要和Marathon结合使用。
诞生的比较早甚至早于docker,但是它一开始就不是面向容器的而是面向节点(机器)的。
1.3.2、Docker Swarm
Swarm:Docker自己的容器编排工具。
优势:和docker无缝集成;更轻量更便捷。
缺点:功能不够强大。
1.3.3、Google Kubenetes
Kubernetes:Google开源的的容器编排工具。
2、集群架构与组件
注:这些都可以在中文官网上找得到!!!!Kubernetes 组件 _ Kubernetes(K8S)中文文档_Kubernetes中文社区
先大概知道有哪些组件,后面用的时候再深挖。
我们可以在中文官网上找到这个架构图。
Kubernetes 架构 _ Kubernetes(K8S)中文文档_Kubernetes中文社区
2.1、相关组件
2.1.1、控制组件(master)
master节点的组成及同外界交互如下。
(1)etcd
一个分布式的key-value数据库,etcd保存了整个集群的状态;
老版本是基于内存的,新版本是持久化存储的;现在应该都是新版本了。
(2)kube-apiserver
提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制; 一切操作的访问入口,通过apiserver才能真正的调用到具体的应用。调度器scheduler、副本控制器、命令行、etcd、kubelet、kube-proxy、命令行工具、可视化界面等等都需要和api server交互。
最核心的组件。
(3)kube-controller-manager
controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
(4)cloud-controller-manager
云控制器管理器:第三方平台提供的控制器API对接管理功能;
(5)kube-scheduler
scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;
2.1.2、节点组件(Node)
Node节点组成如下:
(1)kubelet
kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
(2)kube-proxy
kube-proxy负责为Service提供cluster内部的服务发现和负载均衡;
(3)container runtime
Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);
容器运行的运行时环境:docker(最主流)、另外还有Containerd、CRI-O。
注:
2.1.3、附加组件
(1)kube-dns
管理整个集群的dns映射,通过名字(域名)而不是ip;
(2)Ingress-Controller
想要外部访问集群的话就需要Ingress;
(3)Prometheus
提供k8s集群的监控能力,监控更能更强大;
(4)Dashboard
控制台。就是一个可视化界面,这里是官方提供的。
(5)Federation
理解为集群间的一个调度;
(6)ELK
提供k8s集群日志统一分析平台。
2.2、分层架构
由底向上,分别是:
- 核心层:Kubernetes最核心的功能,对外提供API构建高层的应用,对内提供插件式应用执行环境
- 应用层:部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS解析等)
- 管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态Provision等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy等)
- 接口层:kubectl命令行工具、客户端SDK以及集群联邦
- 生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴
- Kubernetes外部:日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS应用、ChatOps等
- Kubernetes内部:CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等
3、服务的分类
一定要多理解,非常重要。
注:k8s对于这两种类型的服务的处理是不一样的(有状态vs无状态)。
无状态: 不会对本地环境产生任何依赖,例如不存储数据到本地磁盘。对于Nginx,删了、重建、用新服务器部署不用做任何处理功能依然正常。
有状态: 会对本地环境产生依赖,例如需要存储数据到本地磁盘。和无状态相比,就必须要有数据迁移和数据恢复的工作。例如redis,如果有了数据存储。
4、资源和对象
Linux中有个说法"一切皆文件";对应到K8S就是"一切皆资源" 。
资源和对象的关系: 资源就理解成类,对象就理解为基于类创建出来的对象。
k8s汇总所有的内容都可以抽象为资源,如Pod、Service、Node等都是资源。对象就是基于资源创建出来的实体化的对象。整个k8s就是基于这些对象实体描述的。资源的描述方式有很多,一般有json或者yaml。对于k8s而言主要用的就是yaml。
前言: 之所以做这个区分就是要清楚一个资源的作用范围究竟如何。即是否可以跨命名空间使用还是说可以集群通用,如果有这个诉求要知道怎么搞。
4.1、元数据型资源
对于资源的元数据的描述,资源的描述数据,每个资源都可以使用元数据。范围是最大的,公开的资源谁都可以访问。
(1)Horizontal Pod Autoscaler(HPA): 顾名思义就是水平自动扩容的意思。
可以根据CPU使用率、时段之类、甚至自定义的指标自动的进行扩容缩容(默认30s一次检查);解放运维人力。
(2)PodTemplate: 是关于Pod的定义。利用hpa扩容的时候其实就是用Pod模板创建新的Pod。大家都是基于一个模板创建出来的。
(3)LimitRange: 对集群的资源进行限制。例如可以配置初始内存占用2G(request),但是最多情况下可以占用4G(limit)。
总结:对Pod进行描述,满足某些条件就做某些事情。
4.2、集群级资源
作用与集群之上,集群下所有资源可以共享使用。
(1)Namespace: 命名空间本身就是资源,它属于集群。
(2)Node: 节点资源,其实就是一个服务器的概念。它和其他资源还是有些区别。物理层面node并不是由k8s创建的,k8s创建的是一个抽象对象来管理对应的资源。
(3)ClusterRole: 认证、鉴权。用于对集群的权限进行管理。
(4)ClusterRoleBinding: 上面只是声明了一个权限组但是并没有同谁绑定。这里就是把资源同角色绑定,让这个资源拥有某个权限。注:它只能对集群维度的资源进行角色绑定,不能对命名空间之类级别的资源进行绑定。
4.3、命名空间级资源
经常使用需要重点关注的资源!!!
同一个集群内部又可以划分为不同的命令空间。关于这个命令空间就可以理解为一个逻辑上的独立的概念。注:就是用命名空间对集群又做了一个划分/隔离。作用在这种命名空间之上,通常只能在命名空间内使用的资源就是"命名空间级的资源"。
4.3.1、工作负载型(Pod)
什么是Pod?
①k8s进行资源调度的最小单位(最重要概念)。
①一个pod里面可以有一个或多个容器;可以理解为装容器的容器(或者容器组)。
②Pod内部必须有一个pause容器,通过pause容器可以实现容器间的网络、数据等资源的共享。注:然后就可以通过localhost进行彼此访问。
③更多情况一个Pod只运行一个应用容器(one container per pod),除非是特别紧耦合的容器可以考虑部署在一个pod。
④Pod管理的是容器,这个容器并不一定是docker,只不过现在最主流的就是docker而已。
为什么要有容器组?
1)希望两个有强耦合关系的容器可以共享网络。如果是两个独立的容器,应用程序容器通过ip访问另一个mysql容器。但是ip是会变的。
2)当两个容器有强耦合关系的时候希望可以共享数据。注: docker也可以共享数据卷,但是是不方便的。
3)希望可以对若干个容器整体占用的资源进行限制,而不是单个限制。
4.3.2、服务发现与负载均衡
https://wiki.kubernetes.woa.com/quickstart/service_summary.html#%E7%AE%80%E4%BB%8B
4.3.2.0、解决什么问题?
当用户创建了一个 Workload 之后,Kubernetes 后端会生成多个Pod副本,那么后端这么多Pod,如何让主调用方调用到后端的 Pod IP:Port呢?
用户在k8s中可以部署各种容器。一部分通过Http、Https协议对外提供七层网络服务,另一部分是通过TCP、UDP协议提供四层网络服务。前者就是ingress的功能,后者则是Service的功能。
简单来说:Service用于在Kubernetes集群内部暴露服务,而Ingress则用于将服务暴露到集群外部,使得外部用户可以通过HTTP或HTTPS协议访问应用程序,相当于nginx的反向代理。
4.3.2.1、Service —— 提供负载均衡(四层)
k8s中定义的Service资源就是用来管理集群中四层网络的服务方案。一般情况都是集群内部的网络调用,node之间、pod之间的通信。行业黑话叫做"东西流量"。
k8s原生支持的service类型有如下三种:
https://wiki.kubernetes.woa.com/quickstart/service_l4.html#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5
(1)ClusterIP:通过集群的内部 IP 暴露服务。当您的服务只需要在集群内部被访问时,请使用该类型。该类型为默认的 ServiceType。请您选用此类型 Service 作为 Ingress 后端服务。注:外部无法访问。
(2)NodePort:通过每个集群节点上的 IP
和静态端口(NodePort)暴露服务。NodePort
服务会路由到 ClusterIP
服务,该 ClusterIP
服务会自动创建。通过请求 <NodeIP>:<NodePort>
,可从集群的外部访问该 NodePort
服务。除了测试以及非生产环境以外,不推荐在生产环境中直接通过集群节点对外甚至公网提供服务。从安全上考虑,使用该类型会直接暴露集群节点,容易受到攻击。通常认为集群节点是动态的、可伸缩的,使用该类型使得对外提供服务的地址和集群节点产生了耦合。
(3)LoadBalancer:使用腾讯云的负载均衡器CLB,可以向公网或者内网暴露服务。它依赖于公用与弹性IP的实现。LoadBalancer建立在NodePort基础上,将Service映射到一个负载均衡器的IP地址上,通常在公用云环境使用。这样,客户端就可以通过负载均衡器的IP、端口就可以访问到具体的服务,不需通过kube-proxy提供的负载均衡机制进行流量转发,可以直接将流量转发到后端pod上。
4.3.2.2、Ingress —— 提供域名转发(七层)
Ingress是允许访问到集群内Service规则的集合,您可以通过配置转发规则,实现不同URL访问到集群内不同的Service。为了使Ingress资源正常工作,集群需运行 Ingress Controller 容器服务在集群内默认启用了基于腾讯云负载均衡器实现的 TKE Ingress Controller
k8s中定义的ingress就是用来对外提供Http、Https等七层网络服务的。将k8s内部服务暴露给外网访问的服务。是一个统一的入口,将服务暴露到外网。
关于“南北流量”、“东西流量”。
不同层级的调用: 纵向流量或者南北流量。
微服务间的调用: 横向流量或者东西流量。
4.3.3、存储
- Volume: 数据卷,共享Pod中容器使用数据,用来持久化数据,比如数据库数据。
- CSI: 容器存储接口(Container Storage Interface),是由k8s、mesos、docker等社区成员联合制定的标准接口规范。
4.3.4、特殊类型配置
(1)ConfigMap: 就理解成key-value类型的配置。我们可以把key-value类型的配置信息放到configmap里面,然后configmap可以加载到pod里面。然后pod里面的容器就可以读取到configmap里面的k-v配置信息。实现了一个效果就是把容器需要的数据暴露了出来,我们在外界修改就可以作用与容器。在没有配置中心的前提下如果没有configmap我们修改任何一个配置都要重新改代码、重新打包、重新部署,显然这样太麻烦了。
(2)Secret: 和configmap完全一样,只不过多了加密的功能。更多的保证数据的安全性。
(3)DownwardAPI: 把Pod的信息共享到容器内,让我们的容器可以读取到pod的信息。总共有两种方式:
①环境变量:用于单个变量,可以将pod信息和容器信息直接注入容器内部。
②volume挂载:将pod信息生成为文件,直接挂载到容器内部去。容器内部就可以通过读取这个文件拿到对应信息了。
4.3.5、其他
(1)Role: 定义一组权限。clusterRole定义的是集群级别的权限,此处定义的是命名空间级别的权限。
(2)RoleBinding: 可以作用与Role和ClusterRole,集群级中的ClusterRoleBinding可以作用与Role或者ClusterRole。其区别是 RoleBinding 是把权限绑定到命名空间,ClusterRoleBinding 是绑定到集群。
4.4、资源清单
资源是通过配置对象的形式来描述的。
5、对象规约和状态
5.1、规约(Spec)
规约就理解为"规格",理解成期望的状态。通过spec属性去描述我们期望的属性,例如期望有几个实例。注意:这个只是期望并不是实际,例如期望是三个副本但是资源就是不够了两个副本也是可以的。另外,规约是必须的。
spec: 规格
5.2、状态(Status)
表示对象的实际的状态,由k8s自己维护。k8s由控制器控制尽可能的让实际状态与期望状态靠拢。
6、工作负载型Pod的控制器
就理解为一个内存级的对象,这个对象本质还是一个pod。只不过他的作用就是控制管理具体的业务Pod(相当于又套了一层)。如下图所示。
控制器又分为四大类。其中 有状态、无状态最重要!!!
5.1、适用无状态服务的控制器
例如nginx这个无状态的应用就可以用下面控制器去构建。包括:
(1)ReplicationController(RC): 帮助我们动态更新Pod的副本数,实现扩容缩容。
注:1.11版本之后就把RC给废掉了,替换他的就是RS。了解即可。
(2)ReplicaSet(RS): 也是用于帮助我们动态更新Pod副本数,只不过在RC的基础上做了升级。例如可以通过指定一个selector来选择对哪些Pod生效。具体来说我们先给不同的pod打上不同的标签(label),然后仅对selector指定的Pod生效。了解即可。
分析:RC只是对一个pod进行调整,但是RS可以通过选择器选择各种条件的Pod进行扩缩容。
(3)Deployment: 后续部署无状态服务我们不会直接使用RC或RS,而是用Deployment。因为RS只有扩容和缩容的功能,而Deployment基于RS做了更高层次的封装,提供了更丰富的部署相关的功能。具体来说包括:
创建Replica Set/Pod
滚动升级/回滚
平滑的扩容/缩容
暂停与恢复Deployment
其中滚动更新/升级是我们常用的功能。假设我们要对应用更新版本,流程如下:
首先,Deployment会自动创建一个新的RS,此处为RS2;
然后,在RS2中启动一个全新的Pod,启用后会将RS1中的一个Pod停用;
同理,在RS2中在启动一个Pod,启用后在将RS1中的另一个Pod停用;
至此,就完成了滚动升级过程(RS1依然会保留,后续回滚反之即可)。
5.2、适用有状态服务的控制器
参见: https://zhuanlan.zhihu.com/p/654328148
StatefulSet:例如redis就可以用StatefulSet控制器构建。
(1)有状态服务要解决的几个问题
①稳定的网络标识
②稳定的持久化存储、
③有序部署/扩展(master/slave关系)
④有序收缩/删除(master/slave关系)
(2)Headless Service:主要作用就是提供稳定的网络标识,使得Pod可以直接通过DNS名称进行访问,而无需通过Service的ClusterIP进行负载均衡。
StatefulSet中每个Pod的DNS格式为 statefulSetName-[0~N1]serviceName.namespace.svc.cluster.local 注: 这里就是给每个Pod都取了一个名字,然后我们就可以通过这个名字来访问到具体的pod了。
servicename为Headless Service的名字
0~N-1为Pod所在的序号,用于标识pod顺序性;下一个pod运行之前所有之前的pod都必须running和read状态。
statefulSetName为statefulset的名字
namespace为服务所在的命名空间 注:Headless Service和StatefulSet必须在相同的namespace
.cluster.local就是集群的域名(Cluster Domain)
headless service的概念:
1、某些场景无需对外提供访问能力,只需要在内部找到自己想找到的Pod资源时,就可以通过Headless Service来实现。
2、 这种不具有ClusterIP的Service资源就是Headless Service,该Service的流量不需要kube-proxy处理,也不会有负载均衡和路由规则,而是由ClusterDNS的域名解析机制直接去访问固定的Pod资源。
(3)volumeClaimTemplate:用于创建持久化卷的模板 —— 解决了存储问题
至此,statefulset控制器就解决了有状态服务的以上几个问题。
整体架构如下:
5.3、守护进程(DaemonSet)
例如搞一个小的进程监听微服务输出的日志信息,用作日志收集。
DaemonSet:确保所有(或某些)节点运行Pod的副本。当节点被添加到集群中时,Pod也被添加到其中。当节点从集群中移除时,这些Pod将被垃圾收集。删除DaemonSet将清理它创建的Pod。其实就是选择不同的Node安装收集容器,并选择目标Pod进行数据收集。看官网selector可以在node维度选择,也可以在pod维度选择。
典型应用场景:
①日志收集: 比如fluentd、logstash等
②系统监控: 比如Prometheus Node Exporter, collectd
③系统程序: 比如kube-proxy,kube-dns等
英文官方网站: DaemonSet | Kubernetes
整体架构如下:
5.4、任务/定时任务
希望周期性的做一些事情
Job: 一次性执行的任务,例如执行一个脚本。
CronJob: 周期性执行的任务,例如定时任务。
一个任务也是一个pod,任务执行完成后pod会被销毁。我们定义一个job或者cronjob就可以实现这些功能。
参考:
https://znunwm.top/archives/k8s-xiang-xi-jiao-cheng