Kubernetes入门详解

目录

前言

一、Kubernetes

1、为什么要有K8s

2、什么是K8s

3、K8s的用途

4、K8s优势和特点

4.1  K8s优势

4.2  K8s特点

二、K8s架构

三、K8s组件简介 

1、master组件

1.1  kube-apiserver

1.2  kube-scheduler

1.3  kube-controller-manager

1.4  etcd

2、node组件

2.1  kubelet

2.2  kube-proxy

3、插件简介

3.1  DNS

3.2  dashboard

3.3  容器资源监控

3.4  集群层面日志

总结


前言

本文介绍K8s的相关概念,初步了解K8s,对它的组件相关概念能理解透彻。

一、Kubernetes

1、为什么要有K8s

在看这段文字之前,我们要首先知道一个东西,那就是docker。
这里再简单的说下:
docker是容器技术的一种实现方案,同时docker也是docker公司的一个产品。目前主流的容器技术是以docker技术为标准之上的。使用docker可以无需考虑环境问题,docker可以一次构建,到处运行。

如果有很多容器需要管理,单纯使用docker命令来手动管理容器就会显得非常的麻烦,并且容易出错。docker公司提供了docker-compose和内置docker中的docker-swarm来编排服务。使用docker公司提供的编排工具对于中小项目实际上已经足够,但是对于大型分布式应用而言,仅仅对容器编排是不够的。我们需要更强大的功能来管理容器,并且除了docker这个容器实现技术之外的其他容器也是需要编排管理。这是基于docker自身提供的工具就有些力不从心了,而我们又不想自己动手开发。有没有其他容器编排工具呢?肯定有的,容器编排的工具有很多,这里面也有一些公司的开源与兴衰,以及编排容器的工具更迭,好多人都想做那个独角兽,那么选择哪个作为我们使用的工具呢?这里就说这么一个,那就是Kubernetes(K8S)了。

那为什么说这个而不用其他的呢?
这里说以下几点:
开源,背后有谷歌基金会支持;
社区活跃,中英文都有;
成熟。
PS:K8s中文社区 https://www.kubernetes.org.cn/

2、什么是K8s

k8s是 Kubernetes的简称,是一个编排容器的工具,也是管理应用的全生命周期的一个工具。
不论是从应用的创建,应用的部署,应用提供服务,扩容缩容应用,还是应用更新,都非常的方便,而且可以做到故障自愈,例如一个服务器挂了,可以自动将这个服务器上的服务调度到另外一个主机上进行运行,无需进行人工干涉。

3、K8s的用途

  • 存储系统挂载
  • Distributing secrets
  • 应用健康检测
  • 应用实例的复制
  • Pod自动伸缩/扩展
  • Naming and discovering
  • 负载均衡
  • 滚动更新
  • 资源监控
  • 日志访问
  • 调度应用程序
  • 提供认证和授权

4、K8s优势和特点

4.1  K8s优势

自动装箱,水平扩展,自我修复
服务发现和负载均衡
自动发布和回滚
集中化配置管理和密钥管理
存储编排
批处理:提供一次性任务,定时任务;满足批量数据处理和分析的场景

4.2  K8s特点

可移植:支持公有云,私有云,混合云,多重云(multi-cloud)
可扩展:可根据业务流量情况快速扩展kubernetes集群的节点数量。
自愈:自动发布,自动重启,自动复制,自动扩展
进程协同:利用复合应用保证应用和容器一对一的模型。

二、K8s架构

集群架构图

一个简单架构图,不含dashboard,只有一个master和两个node

三、K8s组件简介 

1、master组件

1.1  kube-apiserver

功能:

1)提供了集群管理的REST API接口(包括认证授权、数据校验以及集群状态变更);
2)提供其他模块之间的数据交互和通信的枢纽(其他模块通过API Server查询或修改数据,只有API Server才直接操作etcd);
3)是资源配额控制的入口;

 如何访问apiserver

k8s通过kube-apiserver这个进程提供服务,该进程运行在单个k8s-master节点上。默认有两个端口。 

本地端口

1)该端口用于接收HTTP请求;
2)该端口默认值为8080,可以通过API Server的启动参数“–insecure-port”的值来修改默认值;
3)默认的IP地址为“localhost”,可以通过启动参数“–insecure-bind-address”的值来修改该IP地址;
4)非认证或授权的HTTP请求通过该端口访问API Server。 

安全端口

 1)该端口默认值为6443,可通过启动参数“–secure-port”的值来修改默认值;
2)默认IP地址为非本地(Non-Localhost)网络端口,通过启动参数“–bind-address”设置该值;
3)该端口用于接收HTTPS请求;
4)用于基于Tocken文件或客户端证书及HTTP Base的认证;
5)用于基于策略的授权;
6)默认不启动HTTPS安全访问控制。

访问apiserver的方式

curl :

curl localhost:8080/api
curl localhost:8080/api/v1/pods
curl localhost:8080/api/v1/services
curl localhost:8080/api/v1/replicationcontrollers

kubectl proxy

Kubectl Proxy代理程序既能作为API Server的反向代理,也能作为普通客户端访问API Server的代理。通过master节点的8080端口来启动该代理程序。

kubectl客户端

命令行工具kubectl客户端,通过命令行参数转换为对API Server的REST API调用,并将调用结果输出。

apiserver参数介绍

参数 含义   默认值
–advertise-address 通过该 ip 地址向集群其他节点公布 api server 的信息,必须能够被其他节点访问    nil
–allow-privileged    是否允许 privileged 容器运行    false
–admission-control     准入控制     AlwaysAdmit
–authorization-mode    授权模式 ,安全接口上的授权    AlwaysAllow
–bind-address     HTTPS 安全接口的监听地址    0.0.0.0
–secure-port     HTTPS 安全接口的监听端口    6443
–cert-dir    TLS 证书的存放目录     /var/run/kubernetes
–etcd-prefix     信息存放在 etcd 中地址的前缀    “/registry”
–etcd-servers    逗号分割的 etcd server 地址     []
–insecure-bind-address     HTTP 访问的地址     127.0.0.1
–insecure-port HTTP    访问的端口    8080
–log-dir     日志存放的目录    
–service-cluster-ip-range     service 要使用的网段,使用 CIDR 格式,参考 kubernetes 中 service 的定义    

1.2  kube-scheduler

kube-scheduler 负责分配调度 Pod 到集群内的节

指定node节点调度

有三种方式可以指定 Pod 只运行在指定的 Node 节点上
1)nodeSelector:只调度到匹配指定 label 的 Node 上
2)nodeAffinity:功能更丰富的 Node 选择器,比如支持集合操作
3)podAffinity:调度到满足条件的 Pod 所在的 Node 上

taints和tolerations

Taints 和 tolerations 用于保证 Pod 不被调度到不合适的 Node 上,其中 Taint 应用于 Node 上,而 toleration 则应用于 Pod 上。
目前支持的 taint 类型:
1)NoSchedule:新的 Pod 不调度到该 Node 上,不影响正在运行的 Pod
2)PreferNoSchedule:soft 版的 NoSchedule,尽量不调度到该 Node 上
3)NoExecute:新的 Pod 不调度到该 Node 上,并且删除(evict)已在运行的 Pod。Pod 可以增加一个时间(tolerationSeconds)

优先级调度

从 v1.8 开始,kube-scheduler 支持定义 Pod 的优先级,从而保证高优先级的 Pod 优先调度。并从 v1.11 开始默认开启。

多调度器

如果默认的调度器不满足要求,还可以部署自定义的调度器。并且,在整个集群中还可以同时运行多个调度器实例,通过 podSpec.schedulerName 来选择使用哪一个调度器(默认使用内置的调度器)。

1.3  kube-controller-manager

Controller Manager 由 kube-controller-manager 和 cloud-controller-manager 组成,是 Kubernetes 的大脑,它通过 apiserver 监控整个集群的状态,并确保集群处于预期的工作状态。

kube-controller-manager 由一系列的控制器组成,这些控制器可以划分为三组:

1)必须启动的控制器:18个
EndpointController
ReplicationController
PodGCController
ResourceQuotaController
NamespaceController
ServiceAccountController
GarbageCollectorController
DaemonSetController
JobController
DeploymentController
ReplicaSetController
HPAController
DisruptionController
StatefulSetController
CronJobController
CSRSigningController
CSRApprovingController
TTLController

2)默认启动可选的控制器,可以通过选项设置是否开启
TokenController
NodeController
ServiceController
RouteController
PVBinderController
AttachDetachController

3)默认禁止的可选控制器,可通过选项设置是否开启
BootstrapSignerController
TokenCleanerController

高可用和高性能

在启动时设置 --leader-elect=true 后,controller manager 会使用多节点选主的方式选择主节点。只有主节点才会调用 StartControllers() 启动所有控制器,而其他从节点则仅执行选主算法。

从 Kubernetes 1.7 开始,所有需要监控资源变化情况的调用均推荐使用 Informer。Informer 提供了基于事件通知的只读缓存机制,可以注册资源变化的回调函数,并可以极大减少 API 的调用。

1.4  etcd

Etcd 是 CoreOS 基于 Raft 开发的分布式 key-value 存储,可用于服务发现、共享配置以及一致性保障(如数据库选主、分布式锁等)。etcd作为一个受到ZooKeeper与doozer启发而催生的项目,除了拥有与之类似的功能外,更专注于以下四点。
1)简单:基于HTTP+JSON的API让你用curl就可以轻松使用。
2)安全:可选SSL客户认证机制。
3)快速:每个实例每秒支持一千次写操作。
4)可信:使用Raft算法充分实现了分布式。

etcd主要功能

1)基本的 key-value 存储
2)监听机制
3)key 的过期及续约机制,用于监控和服务发现
4)原子性操作(CAS 和 CAD),用于分布式锁和 leader 选举
tips:
CAS的原理:CAS操作需要输入两个数值,一个旧值(期望操作之前的值)和一个新值,在操作期间先比较旧值有没有变化,如果没有发生变化,才交换新值,发生了变化则不交换

etcd的RAFT算法把一致性问题分解成了几个子问题

选举算法

初始启动时,节点处于 follower 状态并被设定一个 election timeout,如果在这一时间周期内没有收到来自 leader 的 heartbeat,节点将发起选举:将自己切换为 candidate 之后,向集群中其它 follower 节点发送请求,询问其是否选举自己成为 leader。
当收到来自集群中过半数节点的接受投票后,节点即成为 leader,开始接收保存 client 的数据并向其它的 follower 节点同步日志。如果没有达成一致,则 candidate 随机选择一个等待间隔(150ms ~ 300ms)再次发起投票,得到集群中半数以上 follower 接受的 candidate 将成为 leader
leader 节点依靠定时向 follower 发送 heartbeat 来保持其地位。
任何时候如果其它 follower 在 election timeout 期间都没有收到来自 leader 的 heartbeat,同样会将自己的状态切换为 candidate 并发起选举。每成功选举一次,新 leader 的任期(Term)都会比之前 leader 的任期大 1。

日志复制

当前 Leader 收到客户端的日志(事务请求)后先把该日志追加到本地的 Log 中,然后通过 heartbeat 把该 Entry 同步给其他 Follower,Follower 接收到日志后记录日志然后向 Leader 发送 ACK,当 Leader 收到大多数(n/2+1)Follower 的 ACK 信息后将该日志设置为已提交并追加到本地磁盘中,通知客户端并在下个 heartbeat 中 Leader 将通知所有的 Follower 将该日志存储在自己的本地磁盘中。

安全性

安全性是用于保证每个节点都执行相同序列的安全机制,如当某个 Follower 在当前 Leader commit Log 时变得不可用了,稍后可能该 Follower 又会被选举为 Leader,这时新 Leader 可能会用新的 Log 覆盖先前已 committed 的 Log,这就是导致节点执行不同序列;Safety 就是用于保证选举出来的 Leader 一定包含先前 commi安全tted Log 的机制;

选举安全性(Election Safety):每个任期(Term)只能选举出一个 Leader
Leader 完整性(Leader Completeness):指 Leader 日志的完整性,当 Log 在任期 Term1 被 Commit 后,那么以后任期 Term2、Term3… 等的 Leader 必须包含该 Log;Raft 在选举阶段就使用 Term 的判断用于保证完整性:当请求投票的该 Candidate 的 Term 较大或 Term 相同 Index 更大则投票,否则拒绝该请求。

失效处理

Leader 失效:其他没有收到 heartbeat 的节点会发起新的选举,而当 Leader 恢复后由于步进数小会自动成为 follower(日志也会被新 leader 的日志覆盖)
follower 节点不可用:follower 节点不可用的情况相对容易解决。因为集群中的日志内容始终是从 leader 节点同步的,只要这一节点再次加入集群时重新从 leader 节点处复制日志即可。
多个 candidate:冲突后 candidate 将随机选择一个等待间隔(150ms ~ 300ms)再次发起投票,得到集群中半数以上 follower 接受的 candidate 将成为 leader

2、node组件

2.1  kubelet

每个节点上都运行一个 kubelet 服务进程,默认监听 10250 端口,接收并执行 master 发来的指令,管理 Pod 及 Pod 中的容器。每个 kubelet 进程会在 API Server 上注册节点自身信息,定期向 master 节点汇报节点的资源使用情况,并通过 cAdvisor 监控节点和容器的资源。

节点管理
节点管理主要是节点自注册和节点状态更新:

1.Kubelet 可以通过设置启动参数 --register-node 来确定是否向 API Server 注册自己;
2.如果 Kubelet 没有选择自注册模式,则需要用户自己配置 Node 资源信息,同时需要告知 Kubelet 集群上的 API Server 的位置;
3.Kubelet 在启动时通过 API Server 注册节点信息,并定时向 API Server 发送节点新消息,API Server 在接收到新消息后,将信息写入 etcd
pod管理
1)获取pod清单
Kubelet 以 PodSpec 的方式工作。PodSpec 是描述一个 Pod 的 YAML 或 JSON 对象。 kubelet 采用一组通过各种机制提供的 PodSpecs(主要通过 apiserver),并确保这些 PodSpecs 中描述的 Pod 正常健康运行。

向 Kubelet 提供节点上需要运行的 Pod 清单的方法:
1.文件:启动参数 --config 指定的配置目录下的文件 (默认 / etc/kubernetes/manifests/)。该文件每 20 秒重新检查一次(可配置)。
2.HTTP endpoint (URL):启动参数 --manifest-url 设置。每 20 秒检查一次这个端点(可配置)。
3.API Server:通过 API Server 监听 etcd 目录,同步 Pod 清单。
4.HTTP server:kubelet 侦听 HTTP 请求,并响应简单的 API 以提交新的 Pod 清单。

2)通过apiserver获取pod清单及创建pod的过程
Kubelet 通过 API Server Client(Kubelet 启动时创建)使用 Watch 加 List 的方式监听 “/registry/nodes/$ 当前节点名” 和 “/registry/pods” 目录,将获取的信息同步到本地缓存中。

Kubelet 监听 etcd,所有针对 Pod 的操作都将会被 Kubelet 监听到。如果发现有新的绑定到本节点的 Pod,则按照 Pod 清单的要求创建该 Pod。

如果发现本地的 Pod 被修改,则 Kubelet 会做出相应的修改,比如删除 Pod 中某个容器时,则通过 Docker Client 删除该容器。 如果发现删除本节点的 Pod,则删除相应的 Pod,并通过 Docker Client 删除 Pod 中的容器。

Kubelet 读取监听到的信息,如果是创建和修改 Pod 任务,则执行如下处理:
1.为该 Pod 创建一个数据目录;
2.从 API Server 读取该 Pod 清单;
3.为该 Pod 挂载外部卷;
4.下载 Pod 用到的 Secret;
5.检查已经在节点上运行的 Pod,如果该 Pod 没有容器或 Pause 容器没有启动,则先停止 Pod 里所有容器的进程。如果在 Pod 中有需要删除的容器,则删除这些容器;
6.用 “kubernetes/pause” 镜像为每个 Pod 创建一个容器。Pause 容器用于接管 Pod 中所有其他容器的网络。每创建一个新的 Pod,Kubelet 都会先创建一个 Pause 容器,然后创建其他容器。
7.为 Pod 中的每个容器做如下处理:
为容器计算一个 hash 值,然后用容器的名字去 Docker 查询对应容器的 hash 值。若查找到容器,且两者 hash 值不同,则停止 Docker 中容器的进程,并停止与之关联的 Pause 容器的进程;若两者相同,则不做任何处理;
如果容器被终止了,且容器没有指定的 restartPolicy,则不做任何处理;
调用 Docker Client 下载容器镜像,调用 Docker Client 运行容器。

3)static pod
所有以非 API Server 方式创建的 Pod 都叫 Static Pod。Kubelet 将 Static Pod 的状态汇报给 API Server,API Server 为该 Static Pod 创建一个 Mirror Pod 和其相匹配。Mirror Pod 的状态将真实反映 Static Pod 的状态。当 Static Pod 被删除时,与之相对应的 Mirror Pod 也会被删除。

容器健康检查
Pod 通过两类探针检查容器的健康状态:
1.LivenessProbe 探针:用于判断容器是否健康,告诉 Kubelet 一个容器什么时候处于不健康的状态。如果 LivenessProbe 探针探测到容器不健康,则 Kubelet 将删除该容器,并根据容器的重启策略做相应的处理。如果一个容器不包含 LivenessProbe 探针,那么 Kubelet 认为该容器的 LivenessProbe 探针返回的值永远是 “Success”;
2.ReadinessProbe:用于判断容器是否启动完成且准备接收请求。如果 ReadinessProbe 探针探测到失败,则 Pod 的状态将被修改。Endpoint Controller 将从 Service 的 Endpoint 中删除包含该容器所在 Pod 的 IP 地址的 Endpoint 条目。
Kubelet 定期调用容器中的 LivenessProbe 探针来诊断容器的健康状况。LivenessProbe 包含如下三种实现方式:
1.ExecAction:在容器内部执行一个命令,如果该命令的退出状态码为 0,则表明容器健康;
2.TCPSocketAction:通过容器的 IP 地址和端口号执行 TCP 检查,如果端口能被访问,则表明容器健康;
3.HTTPGetAction:通过容器的 IP 地址和端口号及路径调用 HTTP GET 方法,如果响应的状态码大于等于 200 且小于 400,则认为容器状态健康

2.2  kube-proxy

每台机器上都运行一个 kube-proxy 服务,它监听 API server 中 service 和 endpoint 的变化情况,并通过 iptables 等来为服务配置负载均衡(仅支持 TCP 和 UDP)。
kube-proxy 可以直接运行在物理机上,也可以以 static pod 或者 daemonset 的方式运行。

kube-proxy 当前支持以下几种实现:

1.userspace:最早的负载均衡方案,它在用户空间监听一个端口,所有服务通过 iptables 转发到这个端口,然后在其内部负载均衡到实际的 Pod。该方式最主要的问题是效率低,有明显的性能瓶颈。
2.iptables:目前推荐的方案,完全以 iptables 规则的方式来实现 service 负载均衡。该方式最主要的问题是在服务多的时候产生太多的 iptables 规则,非增量式更新会引入一定的时延,大规模情况下有明显的性能问题
3.ipvs:为解决 iptables 模式的性能问题,v1.11 新增了 ipvs 模式(v1.8 开始支持测试版,并在 v1.11 GA),采用增量式更新,并可以保证 service 更新期间连接保持不断开
winuserspace:同 userspace,但仅工作在 windows 节点上

注意:使用 ipvs 模式时,需要预先在每台 Node 上加载内核模块 nf_conntrack_ipv4,ip_vs,ip_vs_rr,ip_vs_wrr, ip_vs_sh 等。

3、插件简介

3.1  DNS

DNS 是 Kubernetes 的核心功能之一,通过 kube-dns 或 CoreDNS 作为集群的必备扩展来提供命名服务。

CoreDNS
从 v1.11 开始可以使用 CoreDNS 来提供命名服务,并从 v1.13 开始成为默认 DNS 服务。CoreDNS 的特点是效率更高,资源占用率更小,推荐使用 CoreDNS 替代 kube-dns 为集群提供 DNS 服务。
从 kube-dns 升级为 CoreDNS 的步骤为:

$ git clone https://github.com/coredns/deployment
$ cd deployment/kubernetes
$ ./deploy.sh | kubectl apply -f -
$ kubectl delete --namespace=kube-system deployment kube-dns

kube-dns工作原理

1.kube-dns:DNS 服务的核心组件,主要由 KubeDNS 和 SkyDNS 组成
1)KubeDNS 负责监听 Service 和 Endpoint 的变化情况,并将相关的信息更新到 SkyDNS 中
2)SkyDNS 负责 DNS 解析,监听在 10053 端口 (tcp/udp),同时也监听在 10055 端口提供 metrics
3)kube-dns 还监听了 8081 端口,以供健康检查使用
2.dnsmasq-nanny:负责启动 dnsmasq,并在配置发生变化时重启 dnsmasq
dnsmasq 的 upstream 为 SkyDNS,即集群内部的 DNS 解析由 SkyDNS 负责
3.sidecar:负责健康检查和提供 DNS metrics(监听在 10054 端口)

3.2  dashboard

https://kubernetes.io/zh/docs/tasks/access-application-cluster/web-ui-dashboard/

Dashboard 是 Kubernetes 集群的通用基于 Web 的 UI。它使用户可以管理集群中运行的应用程序以及集群本身并进行故障排除。

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta4/aio/deploy/recommended.yaml

3.3  容器资源监控

容器资源监控将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中,并提供用于浏览这些数据的界面。

Prometheus,一个 CNCF 项目,可以原生监控 Kubernetes、节点和 Prometheus 本身。

3.4  集群层面日志

集群层面日志 机制负责将容器的日志数据保存到一个集中的日志存储中,该存储能够提供搜索和浏览接口.
https://kubernetes.io/zh/docs/concepts/cluster-administration/logging/

虽然Kubernetes没有为集群级日志记录提供原生的解决方案,但您可以考虑几种常见的方法。以下是一些选项:

1.使用在每个节点上运行的节点级日志记录代理。
2.在应用程序的 pod 中,包含专门记录日志的 sidecar 容器。
3.将日志直接从应用程序中推送到日志记录后端。

总结

K8S概念很是复杂,这里先简单的介绍下k8s基础概念,后续接着更新k8s部署,已及更深参次的介绍k8s。初次里面涉及的概念,定要搞清楚,偶尔面试会被问到 。


 

你可能感兴趣的:(kubernetes,容器,云原生)