k8s学习(CNCF × Alibaba 云原生技术公开课)(一)

docker的出现解决了微服务的部署问题,k8s的出现解决了docker的集群问题

https://www.cnblogs.com/wangyongqiang/articles/12564373.html

----->kubernetes.io/zh/docs/tutorials/kubernetes-basics/

Master 管理集群,Node 用于托管正在运行的应用。

    Master 负责管理整个集群。 Master 协调集群中的所有活动,例如调度应用、维护应用的所需状态、应用扩容以及推出新的更新。

    Node 是一个虚拟机或者物理机,它在 Kubernetes 集群中充当工作机器的角色 每个Node都有 Kubelet , 它管理 Node 而且是 Node 与 Master 通信的代理。 Node 还应该具有用于??处理容器操作的工具,例如 Docker 或 rkt 。处理生产级流量的 Kubernetes 集群至少应具有三个 Node 。

    在 Kubernetes 上部署应用时,您告诉 Master 启动应用容器。 Master 就编排容器在集群的 Node 上运行。 Node 使用 Master 暴露的 Kubernetes API 与 Master 通信。终端用户也可以使用 Kubernetes API 与集群 交互。

    Deployment 指挥 Kubernetes 如何创建和更新应用程序的实例。创建 Deployment 后,Kubernetes master 将应用程序实例调度到集群中的各个节点上。创建应用程序实例后,Kubernetes Deployment 控制器会持续监视这些实例。 如果托管实例的节点关闭或被删除,则 Deployment 控制器会将该实例替换为群集中另一个节点上的实例。 这提供了一种 自我修复机制来解决机器故障维护问题。 扩展 Deployment 将创建新的 Pods,并将资源调度请求分配到有可用资源的节点上,收缩 会将 Pods 数量减少至所需的状态。Kubernetes 还支持 Pods 的自动缩放。 除了应用容器,Pod 还可以包含在 Pod 启动期间运行的 ( Init 容器是一种特殊容器,在   内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本) 。 你也可以在集群中支持  ( 临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启, 因此不适用于构建应用程序, 当由于容器崩溃或容器镜像不包含调试工具而导致  kubectl exec  无用时, 临时容器对于交互式故障排查很有用。)的情况外,为调试的目的注入临时性容器。

    创建 Deployment 时, Kubernetes 添加了一个 Pod 来托管你的应用实例。 Pod 是 Kubernetes 抽象出来的,表示一组一个或多个应用程序容器(如 Docker), Pod 的共享上下文包括一组 Linux 名字空间、控制组(cgroup)和可能一些其他的隔离 方面,即用来隔离 Docker 容器的技术。 在 Pod 的上下文中,每个独立的应用可能会进一步实施隔离。 这些 共享资源包括:

  • 共享存储,当作卷(Pod 中的所有容器都可以访问该共享卷,从而允许这些容器共享数据)

  • 网络,作为唯一的集群 IP 地址( 共享网络名字空间 pod中的多个容器有一样的ip,mac和port, Pod 内  的容器可以使用  localhost  互相通信)

  • 有关每个容器如何运行的信息,例如容器映像版本或要使用的特定端口。

重启 Pod 中的容器不应与重启 Pod 混淆。 Pod 不是进程,而是容器运行的环境。 在被删除之前,Pod 会一直存在。

     通常你不需要直接创建 Pod,甚至单实例 Pod。 相反,你会使用诸如   或   这类工作负载资源 来创建 Pod。 每个 Pod 都有一个唯一的 IP 地址,但是如果没有 Service ,这些 IP 不会暴露在群集外部。你也可以在创建 Deployment 的同时用 --expose创建一个 Service 。

更新应用程序

用户希望应用程序始终可用,而开发人员则需要每天多次部署它们的新版本。在 Kubernetes 中,这些是通过滚动更新(Rolling Updates)完成的。 滚动更新 允许通过使用新的实例逐步更新 Pod 实例,零停机进行 Deployment 更新。新的 Pod 将在具有可用资源的节点上进行调度。


1、应用部署方式:

    传统的应用部署方式是通过插件或脚本来 安装应用。这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,当然也可以通过创建虚拟机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。
优势::

    新的方式是通过 部署容器方式实现,每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进行迁移。容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间成一对一关系也使容器有更大优势,使用容器可以在build或release 的阶段,为应用创建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,这使得从研发到测试、生产能提供一致环境。类似地,容器比虚拟机轻量、更“透明”,这更便于监控和管理。

2、pod内部容器之间通信

一组容器的集合pod,pod中的容器共享网络命名空间与存储,这种情况下容器通讯比较简单,因为 k8s pod内部容器是共享网络空间的,所以容器直接可以使用localhost访问其他容器。k8s在启动容器的时候会先启动一个pause容器,这个容器就是实现这个功能的。

Pod 是 Kubernetes 中最基本的构造模块,是 Kubernetes 对象模型中你可以创建或部署的 最小、最简单元。你不可以在同一 Pod 中部署 Windows 和 Linux 容器。 Pod 中的所有容器都会被调度到同一节点(Node),而每个节点代表的是一种特定的平台 和体系结构。

3、service实现了后端pod的负载均衡,Service Cluster IP ( 只能在集群内访问)是一个虚拟 IP,是由 Kubernetes 节点上的 iptables 规则管理的。 Cluster 的每一个节点都配置了相同的 iptables 规则,这样就确保了整个 Cluster 都能够通过 Service 的 Cluster IP 访问 Service。

LoadBalancer(metallb)

LB后端绑定每个节点的 NodePort,LB 接收外界流量,转发到其中一个节点的 NodePort 上,再通过 Kubernetes 内部的负载均衡,使用 iptables 或 ipvs 转发到 Pod。

—— IPVS LVS 项目的一部分,是一款运行在Linux kernel当中的4层负载均衡器,性能异常优秀。 根据 这篇文章 的介绍,使用调优后的内核,可以轻松处理每秒10万次以上的转发请求。目前在中大型互联网项目中, IPVS被广泛的使用,用于承接网站入口处的流量。

4、k8s statefulSet 有状态应用和无状态应用区别

无状态服务:

    就是没有特殊状态的服务,各个请求对于服务器来说统一无差别处理,请求自身携带了所有服务端所需要的所有参数(服务端自身不存储跟请求相关的任何数据,不包括数据库存储信息)。无状态的服务器程序,最著名的就是WEB服务器。每次HTTP请求和以前都没有啥关系,只是获取目标URI。得到目标内容之后,这次连接就被杀死,没有任何痕迹。在后来的发展进程中,逐渐在无状态化的过程中,加入状态化的信息,比如COOKIE。服务端在响应客户端的请求的时候,会向客户端推送一个COOKIE,这个COOKIE记录服务端上面的一些信息。客户端在后续的请求中,可以携带这个COOKIE,服务端可以根据这个COOKIE判断这个请求的上下文关系。COOKIE的存在,是无状态化向状态化的一个过渡手段,他通过外部扩展手段,COOKIE来维护上下文关系。

有状态服务:

    有状态服务 可以说是需要数据存储功能的服务、或者指多线程类型的服务,队列等。(mysql数据库、kafka、zookeeper等)每个实例都需要有自己独立的持久化存储,并且在k8s中是通过申明模板来进行定义。持久卷申明模板在创建pod之前创建,绑定到pod中,模板可以定义多个。

5、Kubernetes 对 Windows 的支持

    若要在 Kubernetes 中启用对 Windows 容器的编排,只需在现有的 Linux 集群中包含 Windows 节点。在 Kubernetes 上调度   中的 Windows 容器与调用基于 Linux 的容器一样简单、一样容易。为了运行 Windows 容器,你的 Kubernetes 集群必须包含多个操作系统, 控制面 节点运行 Linux, 工作节点则可以根据负载需要运行 Windows 或 Linux。 Windows Server 2019 是唯一被支持的 Windows 操作系统.

--->kubernetes.io/zh/docs/setup/production-environment/windows/


6、阿里云大学《 CNCF × Alibaba 云原生技术公开课》笔记

    “云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格(Service Mesh)、微服务、不可变基础设施和声明式API。这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。”

云原生计算使用的开源技术栈包括:

    容器化:每个部分(应用、流程等等)都打包在自己的容器中,这有助于提升复用性、透明度以及改善资源隔离。动态编排。容器受到有效的调度和管理,以便优化资源利用。

    以微服务为导向:应用被分割到不同的微服务中,这种分割可以显著的提高应用的整体敏捷性和可维护性。

    

    容器就是一个视图隔离、资源可限制、独立文件系统的进程集合。所谓“视图隔离”就是能够看到部分进程以及具有独立的主机名等;控制资源使用率则是可以对于内存大小以及 CPU 使用个数等进行限制。容器就是一个进程集合,它将系统的其他资源隔离开来,具有自己独立的资源视图。容器具有一个独立的文件系统,因为使用的是系统的资源,所以在独立的文件系统内不需要具备内核相关的代码或者工具,我们只需要提供容器所需的二进制文件、配置文件以及依赖即可。只要容器运行时所需的文件集合都能够具备,那么这个容器就能够运行起来。 将这些容器运行时所需要的所有的文件集合称之为容器镜像。

容器的生命周期和 initial 进程的生命周期是一样的( 容器是一组具有隔离特性的进程集合,在使用 docker run 的时候会选择一个镜像来提供独立的文件系统并指定相应的运行程序。这里指定的运行程序称之为 initial 进程因为容器内不只有这样的一个 initial 进程,initial 进程本身也可以产生其他的子进程或者通过 docker exec 产生出来的运维操作,也属于 initial 进程管理的范围内。

1)Kubernetes 架构是一个比较典型的二层架构和 server-client 架构。Master 作为中央的管控节点,会去与 Node 进行一个连接。K8s设计是面向状态机的。不同状态之间的转化都会在相应的K8s对象上面留下来类似像status或者像conditions的一些字段来进行表示。

2)etcd 保证整个 Kubernetes 的 Master 组件的高可用性。e tcd 使用 raft 协议来维护集群内各个节点状态的一致性。简单说,etcd 集群是一个分布式系统,由多个节点相互通信构成整体对外服务,每个节点都存储了完整的数据,并且通过 Raft 协议保证每个节点维护的数据是一致的。raft是一个共识算法(consensus algorithm),所谓共识,就是多个节点对某个事情达成一致的看法,即使是在部分节点故障、网络延时、网络分割的情况下。这些年最为火热的加密货币(比特币、区块链)就需要共识算法,而在分布式系统中,共识算法更多用于提高系统的容错性,比如分布式存储中的复制集(replication)

3)etcd 是一个分布式、可靠 key-value 存储的分布式系统。当然,它不仅仅用于存储,还提供共享配置及服务发现。 从逻辑角度看,etcd 的存储是一个扁平的二进制键空间,物理视图是 持久化的 B+ 树 提供配置共享和服务发现  (Service Discovery) 的系统比较多,其中最为大家熟知的是 Zookeeper,而 etcd 可以算得上是后起之秀了。在项目实现、一致性协议易理解性、运维、安全等多个维度上,etcd 相比 zookeeper 都占据优势。 etcd 使用 Raft 协议,Zookeeper 使用 ZAB(类PAXOS协议)etcd 提供 HTTP+JSON, gRPC 接口( 语言中立、平台中立、开源的远程过程调用(RPC)系统: 客户端 应用可以像调用本地对象一样直接调用另一台不同的机器上 服务端 应用的方法,使得您能够更容易地创建分布式应用和服务),跨平台跨语言,Zookeeper 需要使用其客户端

4)关于服务发现:

如果有一个让系统可以动态调整集群大小的需求,那么首先就要支持服务发现。就是说当一个新的节点启动时,可以将自己的信息注册到 master,让 master 把它加入到集群里,关闭之后也可以把自己从集群中删除。这个情况,其实就是一个 membership protocol,用来维护集群成员的信息。

整个代码的逻辑很简单,worker 启动时向 etcd 注册自己的信息,并设置一个带 TTL 的租约,每隔一段时间更新这个 TTL,如果该 worker 挂掉了,这个 TTL 就会 expire 并删除相应的 key。发现服务监听 workers/ 这个 etcd directory,根据检测到的不同 action 来增加,更新,或删除 worker。

5)Pod 这个抽象也给这些容器提供了一个共享的运行环境,它们会共享同一个网络环境,这些容器可以用 localhost 来进行直接的连接。 Pod 里面的容器是“超亲密关系” 而 Pod 与 Pod 之间,是互相有 isolation 隔离的。Deployment 是在 Pod 这个抽象上更为上层的一个抽象,它可以定义一组 Pod 的副本数目、以及这个 Pod 的版本。一般大家用 Deployment 这个抽象来做应用的真正的管理,而 Pod 是组成 Deployment 最小的单元。Service 提供了一个或者多个 Pod 实例的稳定访问地址。

    Namespace 是用来做一个集群内部的逻辑隔离的,它包括鉴权、资源管理等。Kubernetes 的每个资源,比如刚才讲的 Pod、Deployment、Service 都属于一个 Namespace,同一个 Namespace 中的资源需要命名的唯一性,不同的 Namespace 中的资源可以重名。

6) label 是可以被 selector,也就是选择器所查询的。这个能力实际上跟我们的 sql 类型的 select 语句是非常相似的,通过 label,kubernetes 的 API 层就可以对这些资源进行一个筛选,那这些筛选也是 kubernetes 对资源的集合所表达默认的一种方式。

7)Pod 要解决这个问题,核心就在于如何让一个 Pod 里的多个容器之间最高效的共享某些资源和数据。因为容器之间原本是被 Linux Namespace 和 cgroups 隔开的,所以现在实际要解决的是怎么去打破这个隔离,然后共享某些事情和某些信息。这就是 Pod 的设计要解决的核心问题所在。 所以说具体的解法分为两个部分:网络和存储。

    共享 Network Namespace。在 Kubernetes 里的解法是这样的:它会在每个 Pod 里,额外起一个 Infra container 小容器来共享整个 Pod 的  Network Namespace。 Infra container 是一个非常小的镜像,大概 100~200KB 左右,是一个汇编语言写的、永远处于“暂停”状态的容器。由于有了这样一个 Infra container 之后,其他所有容器都会通过 Join Namespace 的方式加入到 Infra container 的 Network Namespace 中。 所以说一个 Pod 里面的所有容器,它们看到的网络视图是完全一样的。即:它们看到的网络设备、IP地址、Mac地址等等,跟网络相关的信息,其实全是一份,这一份都来自于 Pod 第一次创建的这个 Infra container。这就是 Pod 解决网络共享的一个解法。 由于需要有一个相当于说中间的容器存在,所以整个 Pod 里面,必然是 Infra container 第一个启动。并且整个 Pod 的生命周期是等同于 Infra container 的生命周期的,与容器 A 和 B 是无关的。这也是为什么在 Kubernetes 里面,它是允许去单独更新 Pod 里的某一个镜像的,即:做这个操作,整个 Pod 不会重建,也不会重启,这是非常重要的一个设计。

    每一个容器里可以直接声明:要挂载 shared-data 这个 volume,只要你声明了你挂载这个 volume,你在容器里去看这个目录,实际上大家看到的就是同一份。这个就是 Kubernetes 通过 Pod 来给容器共享存储的一个做法。


请使用浏览器的分享功能分享到微信等