一、K8S概念
1. k8s一个用于容器集群的自动化部署、扩容以及运维的开源平台。通过Kubernetes,可以快速有效地响应用户需求;快速而有预期地部署你的应用;极速地扩展你的应用;无缝对接新应用功能;节省资源,优化硬件资源的使用。为容器编排管理提供了完整的开源方案。
2. K8S解决的问题
- 服务器环境
- 服务器资源管理
- 服务容灾恢复
- 硬件资源利用
- 服务资源创建
- 可视化管理
- 服务资源监控
- 资源整合管理
3. K8S特性
自动部署应用容器、自我修复、水平扩展(增加实例)、服务发现,负载均衡、滚动更新、版本回退、密钥和配置管理、存储编排、批处理,提供一次性任务,定时任务,满足批量数据处理和分析的场景
二、K8S架构
1. 组件结构
1.1 master节点
- etcd:配置存储中心,存储api-server的数据
- API-server:RESTfulAPI模式,通过kubectl与客户端交互,与K8S集群、K8S内部进行通信、鉴权、数据校验、数据交互、资源配置、安全机制
- controller-manager:它是整个集群的大脑,内部有很多控制器组成,通过api-server监控整个集群的状态,故障检测,自动扩展
- scheduler:接收调度pod到合适的运算节点,pod的节点选择,资源的调度
1.2 node 节点
- kubelet: 管理本机的容器,定时从API-server中获取节点上的pod的期望运行状态(副本数量、网络、存储如何配置),并将节点pod的状态给api-server,并且及时清理容器,自动修复pod功能
- proxy:service接收到请求后,通过proxy转发到pod上、建立了pod网络与集群网络的关系
三、pod
1. pod来源
1.1 自主式pod:利用yaml文件生成,删除后不会重建:kubectl create -f 、kubectl delete -f
1.2.控制器生成的pod: 通过控制器创建的pod,pod删除后会再自动创建
pod控制器是管理pod的中间层,使用了pod控制器后,在控制器的yaml文件中设置想要运行的pod,如果pod出现问题,控制器后根据指定策略重启或者重建pod
常见的控制器类型:
1. 企业常用
Deployment(无状态服务:pod无顺序要求,无node要求,随意伸缩和扩展):通过控制ReplicaSet资源来控制pod,并支持滚动升级、版本回退等,绑定节点,选择节点部署pod等,挂载文件,控制资源大小
StatefulSet(有状态服务:pod有顺序,考虑在那个节点运行,每个pod都是独立,保持pod启动顺序,持久存储):
1.稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现 2.稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现 3.有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现 4.有序收缩,有序删除(即从N-1到0)
DaemonSet:守护进程(每个node都运行着同一个pod)
2. 其他的控制器:
1.3 pod内部的知识
1. Pod内包含的容器运行在同一宿主机上,使用相同的网络命名空间、IP地址和端口,能够通过localhost进行通信
2. Pod可以指定一组共享存储。Volumes Pod中,Pod中的所有容器都可以访问共享卷,从而使这些容器可以共享数据
pause容器:
1)每个Pod中都有一个pause容器,pause容器做为Pod的网络接入点
2)属于同一个Pod的所有容器共享网络的namespace
3)一个Pod里的容器与另外主机上的Pod容器能够直接通信(lo) 4)属于同一个Pod的所有容器共享Volume挂载卷
2. pod生命周期
Pod 的生命周期 | Kubernetes
pod在其生命周期中只会被调度一次, 一旦 Pod 被调度(分派)到某个节点,Pod 会一直在该节点运行,直到 Pod 停止或者 被终止
2.1 pod生命周期
Pod 会被创建、赋予一个唯一的 ID(UID), 并被调度到节点,并在终止(根据重启策略)或删除之前一直运行在该节点,如果该节点死掉,该节点的pod在超时期限后被删除。
pod重启后,或者重新部署后,它的UID不同。
pod生命周期中的值 | 具体原因 |
Pending (悬决) |
Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间, |
Running (运行中) |
Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。 |
Succeeded (成功) |
Pod 中的所有容器都已成功终止,并且不会再重启。 |
Failed (失败) |
Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。 |
Unknown (未知) |
因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。 |
2.2 容器状态
Kubernetes 会跟踪 Pod 中每个容器的状态,就像它跟踪 Pod 总体上的阶段一样
kubectl describe pod <pod 名称>: 其输出中包含 Pod 中每个容器的状态,里面有一个字段status会显示当前容器的状态
|
处于 Waiting 状态的容器仍在运行它完成启动所需要的操作:例如,从某个容器镜像 仓库拉取容器镜像,或者向容器应用 Secret 数据等等 |
|
Running 状态表明容器正在执行状态并且没有问题发生。 如果配置了 postStart 回调,那么该回调已经执行且已完成。 如果你使用 kubectl 来查询包含 Running 状态的容器的 Pod 时,你也会看到 关于容器进入 Running 状态的信息 |
|
处于 Terminated 状态的容器已经开始执行并且或者正常结束或者因为某些原因失败。 |
2.3 容器重启策略
Kubernetes 中定义了如下三种重启策略,可以通过字段在 Pod 定义中进行设置。
Always | 表示一直重启,这也是默认的重启策略。Kubelet 会定期查询容器的状态,一旦某个容器处于退出状态,就对其执行重启操作 |
OnFailure | 表示只有在容器异常退出,即退出码不为 0 时,才会对其进行重启操作 |
Never | 正常情况下pod运行完退出之后状态为Completed |
2.4 pod状况
Pod 有一个 PodStatus 对象,其中包含一个 PodConditions 数组。Pod 可能通过也可能未通过其中的一些状况测试。
-
PodScheduled
:Pod 已经被调度到某节点; -
ContainersReady
:Pod 中所有容器都已就绪; -
Initialized
:所有的 Init 容器 都已成功启动; -
Ready
:Pod 可以为请求提供服务,并且应该被添加到对应服务的负载均衡池中
2.5 容器探针
探针状态:
-
Success
(成功):容器通过了诊断。 -
Failure
(失败):容器未通过诊断。 -
Unknown
(未知):诊断失败,因此不会采取任何行动。
kubelet
可以选择是否执行以下三种探针:
livenessProbe 存活态探针 |
指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 希望容器在探测失败时被杀死并重新启动,那么请指定一个存活态探针, 并指定 |
readinessProbe 就绪态探针 |
指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 如果你的容器需要加载大规模的数据、配置文件或者在启动期间执行迁移操作,可以添加一个 就绪态探针 |
startupProbe、 启动探针 |
指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,kubelet 将杀死容器,而容器依其 重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success 。 |
2.6 pod的终止
删除一个Pod会发生什么事情?
Kube-apiserver会接受到用户的删除指令,默认有30秒时间等待优雅退出,超过30秒会被标记为死亡状态,此时Pod的状态Terminating,kubelet看到pod标记为Terminating就开始了关闭Pod的工作;
关闭流程如下: 1、 pod从service的endpoint列表中被移除; 2、 如果该pod定义了一个停止前的钩子,其会在pod内部被调用,停止钩子一般定义了如何优雅的结束进程; 3、 进程被发送TERM信号(kill -14) 4、 当超过优雅退出的时间后,Pod中的所有进程都会被发送SIGKILL信号(kill -9)。
四、网络知识
1. 容器之间:通过localhost地址和容器端口通信, pod中的每个容器在一个网络命名空间中,ip、端口、还有网络配置都和pod一样,主要通过一种机制就是,docker的一种网络模式,container,新创建的Docker容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。
2. pod之间:pod之间通过service机制访问, Service是Kubernets最核心的概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求进行负载均衡分发到后端的各个容器应用上。
Service是一个虚拟的概念,真正实现Service功能的是kube-proxy,kube-proxy起到一个代理和负载均衡的作用
service3种不同的方式:
1. ClusterIP: 虚拟服务IP地址,由系统动态分配,该地址用于Kubernetes集群内部的Pod访问,在Node上kube-proxy通过设置的iptables规则进行转发
ClusterIP服务是Kubernetes默认的服务类型。如果用户在集群内创建一个服务,
则在集群内部的其他应用程序可以对这个服务进行访问,但是不具备集群外部访问的能力
2. NodePort:
<1> 使用宿主机的端口,使能够访问各Node的外部客户端,使用物理IP:port, 通过Node的IP地址和端口号就能访问服务
<2>两个pod之间通过域名进行绑定,这样就会互相访问到
NodePort就是在所有节点或者虚拟机上开放特点的端口,该端口的流量将被转发到对应的服务
总结来讲: 在具有集群内部IP的基础上,在集群的每个节点上的端口(每个节点上的相同端口)上公开服务。用户可以在任何< Node IP >:NodePort地址*问
NodePort方式的缺点主要有:
1)每个服务占用一个端口
2)可以使用的范围端口为30000~32767
3)如果节点/虚拟机IP地址发生更改,需要进行相关处理
3. LoadBalancer
LoadBalancer服务是暴露服务至互联网最标准的方案,除了具有集群内部IP以及在NodePort上公开服务之外,还要求云提供商负载均衡将请求转发到每个Node节点的NodePort端口商
4. Ingress
ingress是将服务的接口暴漏在外面,然后可以直接通过物理IP:port去访问,访问的时候ingress绑定了一个域名,通过解析,找到对应的service服务,再将请求转发到pod中。
ingress是K8S集群里工作在OSI网络参考模型下,第7层的应用,对外暴漏的接口
Ingress并不是服务类型的一种,它位于多个服务的前端,充当一个智能路由表或者集群的入口点,GKE默认的Ingress控制器将启动一个HTTP(S)的负载均衡器,这将使用户可以基于访问路径和子域名将流量路由到后端服务
例如下图,我们可以将下的流量转发到服务A,将路径下的流量转发到服务B
使用ingress:ingress单独安装,单独部署ingress controller,创建ingress规则
ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到ingress-controller,而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名哪些path要转发到哪些服务等等
五、资源清单
1. K8S中所有的内容都抽象为资源,资源实例化之后,叫做对象
2. K8S中的资源:
2.1 这些资源都是配置在名称空间级别
- 工作负载型资源(workload):Pod、ReplicaSet、Deployment、StatefulSet、DaemonSet、Job、CronJob
- 服务发现及负载均衡型资源(ServiceDiscovery LoadBalance):Service、Ingress、...
- 配置与存储型资源:Volume(存储卷)、CSI(容器存储接口,可以扩展各种各样的第三方存储卷)
- 特殊类型的存储卷:ConfigMap(当配置中心来使用的资源类型)、Secret(保存敏感数据)、DownwardAPI(把外部环境中的信息输出给容器)
2.2 集群级资源:Namespace、Node、Role、ClusterRole、RoleBinding(角色绑定)、ClusterRoleBinding(集群角色绑定)
2.3 元数据型资源:HPA(Pod水平扩展)、PodTemplate(Pod模板,用于让控制器创建Pod时使用的模板)、LimitRange(用来定义硬件资源限制的)
2.4 资源清单:在k8s中,一般使用yaml格式的文件来创建符合我们预期期望的pod,这样的yaml文件我们一般称为资源清单
创建资源的方法:apiserver 仅接受JSON格式的资源定义;yaml格式提供配置清单,apiserver 可自动将其转为JSON格式,而后再提交;
六、ConfigMap和Secret
1. ConfigMap:
ConfigMap API资源提供了将配置注入容器的机制,ConfigMap可用于存储细粒度信息如单个属性,或粗粒度信息如整个配置文件或JSON对象。
ConfigMap API资源存储键/值对配置数据,这些数据可以在pods里使用。ConfigMap跟Secrets类似,但是ConfigMap可以更方便的处理不包含敏感信息的字符串。
2. ConfigMap的使用:
- 通过环境变量的方式,直接传递给pod
- 通过在pod的命令行下运行的方式(启动命令中)
- 作为volume的方式挂载到pod内
3. ConfigMap的热更新
更新 ConfigMap 后:
使用该 ConfigMap 挂载的 Env 不会同步更新
使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新
当ConfigMap以数据卷的形式挂载进Pod时,更新ConfigMap(或删掉重建ConfigMap),Pod内挂载的配置信息会热更新,但使用环境变量方式加载到pod,则不会自动更新(ENV 是在容器启动的时候注入的,启动之后 kubernetes 就不会再改变环境变量的值)。且同一个 namespace 中的 pod 的环境变量是不断累加的
1. secret资源
Secret资源的功能类似于ConfigMap,但它专门用于存放敏感数据,比如密码、数字证书、私钥、令牌和SSH key等。主要有两种用途:
- 作为存储卷注入到Pod上由容器应用程序所用
- 用于kubelet为Pod里的容器拉取镜像时向私有仓库提供认证信息(后面使用ServiceAccount资源自建的Secret对象是一种更安全的方式)
有4种类型:
- Opaque:自定义数据内容,base64编码;存储密码、证书等数据。类型标识为generic
- /service-account-token:Service Account的认证信息,在创建Service Account时由Kubernetes自动创建
- /dockerconfigjson:用来存储Docker镜像仓库的认证信息,类型标识为docker-registry
- /tls:用于为SSL通信模式存储证书和私钥文件,类型标识为tls
七、存储卷-Volume、PV、PVC
1. Volume是Pod中能够被多个容器共享的磁盘目录
- Kubernetes中的Volume与Pod的生命周期相同,但与容器的生命周期不相关。当容器终止或重启时,Volume中的数据也不会丢失。
- 当Pod被删除时,Volume才会被清理。并且数据是否丢失取决于Volume的具体类型,比如emptyDir类型的Volume数据会丢失,而PV类型的数据则不会丢失。
常见的存储卷类型有:
emptyDir | 当Pod生命周期结束后,存储卷会被一并删除,这种通常会存放一些临时数据,数据是存放在pod中的 |
hostPath | 宿主机目录映射,数据不属于container,所以当Pod生命周期结束的时候,数据不会丢失 |
nfs |
NFS挂载是在其中一个node之上将共享的目录发布出来,并且在各个node之上都安装好nfs-utils工具,只要在创建Pod的时候指定要挂载的文件系统为nfs,和挂载点、权限即可自动完成挂载操作,并且能实现数据同步。 在创建Pod之前要做好nfs的配置 |
2. PV、PVC
1. PV:pv是集群中由管理员配置的一段网络存储,它是集群中的资源,就像节点是集群资源,PV是容量插件,如Volumes,但其生命周期独立于使用pv的任何单个pod。
2. PVC: pvc是由用户进行的存储请求, pvc类似于pod,pod消耗节点资源,PVC消耗PV资源。
3. PV与PVC之间的联系:
PV是群集中的资源。PVC是对这些资源的请求,并且还充当对资源的检查。PV和PVC之间的相互作用遵循以下生命周期:Provisioning (供应准备)——-> Binding (绑定)——–>Using(使用)——>Releasing(释放)——>Recycling(回收)
供应准备:通过集群外的存储系统或者云平台来提供存储持久化支持,创建PV
绑定: 用户创建PVC并指定需要的资源和访问模式,在找到PV之前,PVC会保持未绑定状态
使用:用户在pod中像使用卷一样使用PVC
释放:用户删除pvc来回收存储资源,pv将变成“released”状态。由于还保留着之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他pvc使用。
回收:pv可以设置三种回收策略:保留(Retain),回收(Recycle)和删除(Delete)
注:目前只有NFS和HostPath类型卷支持回收策略,AWS EBS,GCE PD,Azure Disk和Cinder支持删除(Delete)策略。
实际使用:
1. 查看K8S中的pv:
kubectl get pv
kubectl get pv -o yaml 通过这个命令就可以查看到pv与本地主机是怎么绑定存储的
PVC是通过标签来连接PV:
2. StorageClass:作用是创建PV模板
创建StorageClass里面需要定义PV属性比如存储类型、大小等;另外创建这种PV需要用到存储插件。最终效果是,用户提交PVC,里面指定存储类型,如果符合我们定义的StorageClass,则会为其自动创建PV并进行绑定。
八、资源调度
1. 资源调度:Scheduler调度器做为Kubernetes三大核心组件之一, 承载着整个集群资源的调度功能,其根据特定调度算法和策略,将Pod调度到最优工作节点上,从而更合理与充分的利用集群计算资源
2. 调度pod的过程:
1. 用户通过kubectl提交创建pod的yaml文件,Kubectl 向APIServer 发送“POST”请求来创建 Pod 的请求
2. API-server收到请求后,将创建pod的信息存储到etcd中
3. 集群运行时,Scheduler 就会监控API-sevrer,Scheduler采用watch机制,一旦Etcd存储成功,就会将信息返回给API-server,API-server就会将pod创建的信息通知Scheduler
4. 调度器通过API-server查看未调度的pod列表,循环遍历未每个pod分配节点:
第一阶段:预选过程,通过设置的规则去过滤主机
第二阶段:优选过程,选择最优的机器部署pod
5. 选择好主机后,选择分数最高的主机进行binding操作,结果存储到etcd中
6. 所选节点对于的kubelet根据调度结果执行Pod创建操作。
3. pod调度
3.1 nodeName:节点选择约束的最简单方法
3.2 节点选择器:根据标签来选择运行在哪个node
-
nodeSelector:
-
nodeName: node132
3.2 节点亲和性
1. 根据节点上的标签来调度pod
硬亲和性:必须满足条件
软亲和性:尝试满足
反亲和性:使这个pod不能与某个pod部署在同一节点
3.3 污点和污点容忍
污点:它是节点的一个属性,节点设置污点之后,K8S是不会将次pod调度到这个node上,但是如果这个pod设置了污点容忍,那么K8S就会忽略node上的污点,将pod调度过去。
九、集群的安全机制
Kubernetes 集群安全机制详解_qhh0205-****博客
1. 概述:
kube-apiserver 是 k8s 整个集群的入口,是一个 REST API 服务,提供的 API 实现了 Kubernetes 各类资源对象(如 Pod,RC,Service 等)的增、删、改、查,API Server 也是集群内各个功能模块之间交互和通信的枢纽,是整个集群的总线和数据中心。
每个请求到达api-server后都会经过:认证-授权-准入控制,通过后,才会给响应
1. 认证:主要作用是识别用户身份,保证传输安全,对外不暴漏
支持的方式:<1>https证书,基于ca证书 <2> http tonken认证,通过token来识别用户 <3>http 基本认证:用户名+密码
2. 授权:授权阶段判断请求是否有相应的权限
<1>基于角色访问控制 <2>基于RBAC进行鉴权操作
3. 准入控制:准入控制判断操作是否符合集群要求,检查不通过,则 API Server 拒绝调用请求
十、helm
玩K8S不得不会的HELM - 知乎
1. 概念
helm是一个k8s包的管理工具,就像inux下的包管理工具,yun等,可以将打包好的yaml文件部署到K8S上
2. 作用:
<1>使用helm可以把yaml作为整体管理,实现yaml的高效服用,使用helm应用级别的版本管理
3. 构成
<1>Charts: Helm使用的打包格式,一个Chart包含了一组K8s资源集合的描述文件。Chart有特定的文件目录结构,如果开发者想自定义一个新的 Chart,只需要使用Helm create命令生成一个目录结构即可进行开发。
<2>Release: 通过Helm将Chart部署到 K8s集群时创建的特定实例,包含了部署在容器集群内的各种应用资源。
<3>Tiller: Helm 版本中,Helm采用Client/Server的设计,Tiller就是Helm的Server部分,需要具备集群管理员权限才能安装到K8s集群中运行。Tiller与Helm client进行交互,接收client的请求,再与K8s API Server通信,根据传递的Charts来生成Release。而在最新的Helm 中,据说是为了安全性考虑移除了Tiller。
<4>Chart Repository: Helm Chart包仓库,提供了很多应用的Chart包供用户下载使用,官方仓库的地址是,可以在上面发现很多有意思的项目。之后我们会在官方hub找一个应用做个简单的Demo。
十一、命令
K8s常用命令合集 - 知乎
-
1. 创建资源
-
kubectl apply -f /path/to/
-
kubectl run nginx_app --image=nginx:1.9.1 --replicas=3
-
2. 查看资源
-
kubectl get <resource_type>
-
kubectl get pod
-
kubectl get pod/某一个pod -o wide
-
3.将资源输出到文件中
-
kubectl get deployment/archive-manager -o json/yaml
-
kubectl get StatefulSet/etcd -o json/yaml
-
DaemonSet/nginx
-
-
-
4. 查看SVC
-
kubectl get svc -o wide
-
kubectl get ingress -o wide
-
-
映射端口允许外部访问
-
kubectl expose deployment/nginx_app --type='NodePort' --port=80
-
-
# 在创建或启动某些资源的时候没有达到预期结果,可以使用如下命令先简单进行故障定位
-
kubectl describe deployment/nginx_app
-
kubectl logs nginx_pods
-
kubectl exec nginx_pod -c nginx-app <command>
-
-
# 查看K8s支持的api版本
-
kubectl api-versions
-
helm管理命令
-
查看版本
-
-
#helm version
-
增加repo
-
-
#helm repo add stable https:///charts
-
#helm repo add --username admin --password password myharbor https:///chartrepo/charts
-
更新repo仓库资源
-
-
#helm repo update
-
charts管理
-
查看当前安装的charts
-
-
#helm list
-
将helm search hub显示所有可用图表。
-
-
#helm search hub redis
-
使用helm search repo,您可以在已添加的存储库中找到charts的名称:
-
-
#helm search repo redis
-
打印出指定的Charts的详细信息
-
-
#helm show chart stable/redis
-
下载charts到本地
-
-
#helm fetch redis
-
安装charts
-
-
#helm install redis stable/redis
-
查看charts状态
-
-
#helm status redis
-
删除charts
-
-
#helm uninstall redis
-
自定义charts
-
创建charts
-
-
#helm create helm_charts
-
检查chart语法正确性
-
-
# helm lint myapp
-
打包自定义的chart
-
-
# helm package myapp
-
查看生成的yaml文件
-
-
#helm template myapp-1.tgz
-
使用默认chart部署到k8s
-
-
helm install myapp myapp-1.tgz
-
使用包去做release部署
-
-
helm install --name example2 helm-chart-0.1.0.tgz --set service.type=NodePort
-
更新与回滚
-
查看当前chart信息
-
-
#helm list
-
更新images
-
-
#helm upgrade myapp myapp-2.tgz
-
查看版本信息
-
-
#helm history myapp
-
回滚指定版本
-
-
#helm rollback myapp 1
-
-
1. helm get --purge XXX
-
2. helm get values opensearch-master
-
3. helm del --purge opensearch-master
-
-
kubectl exec -ti opensearch-master-0 -n opensearch -- /bin/sh
-
kubectl delete pod X --force --grace-period=0
-
kubectl delete po opensearch-master-0 -n opensearch --force --grace-period=0
-
-
helm repo add ar http:///chartrepo/ar
-
helm repo list
-
helm repo update
-
helm search opensearch --devel