华为CKA认证
华为云CKA认证考试知识点整理
# 华为CKA认证
# CKA认证介绍
CKA,也就是Certificated Kubernetes Administrator,这是面向K8S管理员的认证项目,用于考核日常运维K8S集群所需的知识、技能,以及熟练度。
关键信息:
- 费用:$300(含一次补考的机会)
- 在线远程监考、3小时上机实操、开卷(可查K8S手册)
- 有效期是2年
- 网络连通性、熟练度
报名的链接:https://www.cncf.io/certification/cka/
# 考纲解读
可以通过https://github.com/cncf/curriculum来查看考纲最新版本。
下面是一张关于涉及到的各个知识点所占的分值比例的介绍。
这几大知识点,作者分别通过八次课程讲解的方式来全面讲解,也就是本次CKA知识点的整理脉络所在。
第一节,讲解的是基础概念。对应考纲中的是"核心概念19%"
第二节,讲解的是调度管理实训。对应考纲中的是"调度5%"
第三节,讲解的是日志、监控与应用管理实训。对应考纲中的是"日志/监控5%","应用生命周期管理8%"。
第四节,讲解的是K8S网络实训。对应考纲中的"网络11%"。
第五节,讲解的是K8S存储管理实训。对应考纲中的是"存储7%"。
第六节,讲解的是K8S安全管理实训。对应考纲中的是"安全12%"。
第七节,讲解的是K8S集群运维实训。对应考纲中的是"集群运维11%"和"安装、配置和验证12%"。
第八节,讲解的是K8S故障排查实训。对应考纲中的是"排错10%"。
# K8S架构和工作原理
# K8S架构图如下
整体来说,K8S的架构是Master、Node的模式,Master节点上通常部署有scheduler、controller-manager、api-server,以及etcd分布式数据库。Node节点上通常运行着kubelet、kube-proxy组件,以及真正运行docker实例的Pod容器。
用户通过kubectl,经过一些列的集群的安全认证后,将所需要执行的资源清单配置文件提交给api-server,api-server会将此信息写入etcd,写入完成后,etcd向api-server发起一系列的事件信息,通过list-watch的机制,先后由controller-manager执行副本配置,scheduler完成调度node,kubelet完成落实到各自node上启动相应的pod。而kube-proxy则用于相应的Server资源转发到所关联的一系列的Pod对象上。
# K8s工作原理
如下的图示是完整的工作原理的解析,其中核心的重点概念就是list-watch的机制。
上面所有的"0"示意图,都是表示的是从k8s环境部署完毕后,各个api-server的客户端(api-server、scheduler、kubelet)都对于各个所订阅的资源对象,进行watch。
list-watch的异步消息通信机制,有效的保证了消息的可靠性、及时性、顺序性、高性能等。
# 理解K8S API原语
# K8S中的基本概念
Pod:是一组功能相关的Container的封装;共享存储和Network Namespace;是K8S调度和作业运行的基本单位(Scheduler调度,Kubelet运行);Pod容易"走失",需要workload和Service的保障。
Workloads: 有Deployment,Statefulset,DaemonSet,Job ....,实际上是一组功能相关的Pod的封装。
Service: 主要是为了让Pod "防失联",给一组Pod设置反向代理。
# K8S中API对象的基本构成
整体来说,在K8S中一个完整的API对象由四大部分组成。
typeMeta: 主要由apiVersion和kind两个构成。主要描述的是该类API资源对象的类别和版本。
objectMeta: metadata类别,涵盖该类型资源对象下的基本元数据的信息,包含一些名称、label、注解等。
spec: 这是关键的信息内容,涵盖定义的所有的期望状态信息。
status: 这个不是客户端所需要配置的,反映的是当前该类资源对象的实际的状态值。
# 使用kubectl
# 基本命令
create: 从文件或stdin创建资源。
expose: 为deployment,pod创建Service。
run: Run a particular image on the Cluster.
set: Set sepcific features on objects.
get: 最基本的查询命令。如kubectl get rs,kubectl get deploy,kubectl get svc,kubectl get rs。
explain: 查看资源定义。如kubectl explain replicaset。
edit: 使用系统编辑器编辑资源。如 kubectl edit deploy。使用系统编辑器来加载yaml文件,当get查看一个yaml文件的时候很可能会翻过头,使用edit就可以自由多了。
delete: 删除指定资源,支持文件名、资源名、label selector。如kubectl delete po -l foo=bar。
# 部署命令
rollout: Deployment,DaemonSet的升级过程管理(查看状态、操作历史、暂停升级、恢复升级、回滚等)
rolling-update: 客户端滚动升级,仅限ReplicationController
scale: 修改Deployment,ReplicaSet,ReplicationController,Job的实例数。
autoscale: 为Deploy,RS,RC配置自动伸缩规则(依赖heapster和HPA)
# 集群管理命令
certificate: Modify certificate resources.
cluster-info: 查看集群信息。
top: 查看资源占用率。
cordon: 标记节点为unschedulable。
uncordon: 标记节点为schedulable。
drain: 驱逐节点上的而应用,准备下线维护。
taint: 修改节点taint标记
# Troubleshooting and Debugging命令
describe: 查看资源详情。
logs: 查看pod内容器的日志。
attach: Attach到pod内的一个容器。
exec: 在指定容器内执行命令。
port-forward: 为pod创建本地端口映射。
proxy: 为Kubernetes API Server创建代理。
cp: 容器内外/容器间文件拷贝。
# 高级命令
apply: 从文件或stdin创建/更新资源。
patch: 使用strategic merge patch语法更新对象的某些字段。
replace: 从文件或stdin更新资源。
convert: 在不同API版本之间转换对象定义。
# Setting命令
label: 给资源设置label。
annotate: 给资源设置annotation。
completion: 获取shell自动补全脚本(支持bash和zsh)。
# 其他命令
api-versions: 打印该集群支持的API的版本,在"group/version"中。
config: 修改kubectl配置(kubeconfig文件),如context。
help: 帮助
version: 查看客户端和Server端K8S版本
# kubectl实用技巧
当kubectl命令太多太长记不住该怎么办?
查看资源缩写
$ kubectl api-resources
1配置kubectl 自动完成
$ source <(kubectl completion bash)
1
当kubectl写yaml文件太累了,找样例太麻烦?
用run 命令生成deployment的yaml配置文件
$ kubectl run --image=nginx my-deploy -o yaml --dry-run > my-deploy.yaml
1用get 命令导出
$ kubectl get statefulset/foo -o=yaml --export > new.yaml
1用explain命令
$ kubectl explain xxxx.xxxx
1
# K8S调度管理
# 大纲
整体从考试的大纲来看,有如下的考点要求。
- 理解资源限制对Pod调度的影响
- 使用label selector调度Pod
- 手动调度Pod
- 理解DaemonSet
- 调度失败原因分析
- 使用多调度器
- 了解调度器的配置
好像大致来看,也就是对K8S中scheduler调度的理解,分为资源调度、label selector调度、手动调度、高级调度等相关内容。
# K8S调度相关基础概念
调度器scheduler就是从现有的node中选择一个,来运行所需要的pod。
从下面的图示可以看出,pod m/n/j通过K8S的scheduler调度以后,分别为pod m指定了节点y,pod n指定了节点z,pod l指定了节点x。从pod的yaml清单文件中也可以观察掉,调度前nodeName选项的value是空,调度后nodeName选项的value是相应的节点的名称了。
# Node定义
既然我们了解到scheduler的目的就是为pod指向一个node,那么就必须先了解下node的定义和pod的定义。
通过执行kubectl get node/xxxx -o yaml
,其中"allocatable"表示的是一个node可以分配的资源量,作为一个节点来接收Pod资源的依据。而"capacity"表示的是一个节点固有的资源量,一般来说capacity要大于等于allocatable的资源量。毕竟node除了给pod用,还有预留一些资源给其他。
# Pod中主要属性字段
我们同样要了解pod的具体资源配置文件的定义,毕竟资源的调度是由pod的需求来发起,通过schduler来调度node来满足。
可以通过kubectl explain pod.spec
来查看到相关的字段信息,或者和前面一样通过kubectl get po/xxxx -o yaml
来查看一个既有的pod的配置信息。
其中pod.spec.containers.resources字段中"requests"字段表示的是该Pod提出的要求就是这个node最少就得满足这么多资源,可能真实运行情况下,还用不到这么多的资源,可能要比这个少,也可可能比这个多,但是在Pod用到时,必须提供这么多的资源。"requests"可以理解为请求量,是schedule资源调度的依据。
而"limits"的意思是,就是限制该Pod可以用到的最大值,实际在node上的资源使用时,node把这个pod的资源给限制死了。主要是防止pod自身的bug把node上其他资源给拖累了。
"schedulerName"字段显示的是该Pod用的是哪种调度器管理的,默认就是k8s自带的"default-scheduler"。
"nodeName"字段之前介绍过了,显示的value值就是调度后的结果。
接下来的"nodeSelector"/"affinity"/"tolerations"就是高级调度的策略用法了。
# K8S中的资源分配
K8S中默认的调度器的核心目标就是基于资源可用性将各Pod资源公平地分布于集群节点之上。目前默认的调度器通过三个步骤来完成调度操作:节点预选(Predicate)、节点优先级排序(Priority)以及节点择优(Select)。
下面有些调度内容,摘录自网上https://blog.csdn.net/qq_34857250/article/details/90259693
https://www.cnblogs.com/L-dongf/p/12327401.html
# 调度策略
- 预选策略,predicate是强制性规则,会遍历所有的node节点,依据具体的预选策略筛选出符合要求的node列表,如果没有node符合predicates策略规则,那么Pod就会被挂起,直到有node能够满足。
- 优选策略,这一步会在第一步筛选的基础上,按照优选策略为待选node打分排序,获取最优者。
# 预选策略-必选全部满足
- CheckNodeConditon: 检查node是否正常。
- GeneralPredicates: 普通判断策略
- HostName: 检测Pod对象是否定义了pod.spec.hostname,并且检查节点中是否有同名的pod而冲突。
- PodFitHostPorts: 检查pod.spec.containers.ports.hostPort属性(绑定节点上的某个端口)是否定义,并且检查节点中的节点端口是否冲突。
- MatchNodeSelector: pods.spec.nodeSelector,检查节点选择器。
- PodFitsResources: 检查Pod的资源需求request是否能被节点所满足。
- NoDiskConflict: 检测pod依赖的存储卷是否能满足需求,默认不检查。
- PodToleratesNodeTaints: pods.spec.tolerations可容忍的污点,检查Pod是否能容忍节点上的污点。
- PodToleratesNodeExecuteTanits: pod.tolerations属性中是否能接纳容忍NoExecute级别的污点,默认没有启用。
- CheckNodeLablePresence: 检测node上的标签的存在与否,默认没有启用。
- CheckServiceAffinity: 根据Pod所属的service,将相同所属的service尽可能放在同一个节点,默认不检查。
- CheckVolumeBinding: 检查节点上已绑定和未绑定的PVC是否能够满足Pod对象的存储卷需求。
- NoVolumeZoneConflict: 如果给定了区域限制,检查在此节点上部署Pod对象是否存在存储卷冲突。
- CheckNodeMemoryPressure: 检测节点内存是否存在压力,如果节点内存压力过大,则检查当前Pod是否可以调度此节点上。
- CheckNodePIDPressure: 检查节点PID数量是否存在压力。
- CheckNodeDiskPressure: 检查节点磁盘资源的压力情况。
- MatchInterPodAffinity: 检查给定节点是否能够满足Pod对象的亲和性或反亲和性条件,以用于实现Pod亲和性调度或反亲和性调度。
# 优选策略
优选过程中,调度器向每个通过预选的节点传递一系列的优选函数,来计算每个节点上各个优选函数后得到的值,调度器会给每个优选函数设定一个权重,大多数优先级默认为1。将所有优选函数得分乘以权重,然后相加从而得出节点的最终优先级分值。finaSoreNode=(weight1*priorityFunc1)+(weight2*priorityFunc2)+ ...
下面是各个优选函数的相关说明:
- LeastRequested: 节点的资源空闲率高的优选,是节点空闲资源与节点总容量的比值计算而来的。即由CPU或内存资源的总容量减去节点上已有Pod对象需求的容量总和,再减去当前要创建的Pod对象的需求容量的结果除以总容量。计算公式是:(cpu((capacity-sum(requested))*10 / capacity)+memory((capacity-sum(requested))*10 / capacity)) / 2
- BalancedResourceAllocation: 计算节点上面的CPU和内存资源被占用的比率相近程度,越接近,比分越高,平衡节点的资源使用情况。计算公式:cpu=cpu((capacity-sum(requested))*10 / capacity) mem=memory((capacity-sum(requested))*10 / capacity)
- NodePreferAvoidPodsPriority: 如果node上不存在"scheduler.alpha.kubernetes.io/preferAvoidPods"这个注解,那么不管什么pod都没有影响;如果node上存在相关的注解,那么注解中关联的Pod对象名称正好是要去调度的Pod,那么此类node分值会很低,如果关联的Pod对象名称和要调度的Pod名称没有任何关系,那么和没有注解是一样的效果。需要注意的是,在这个优先级中,优先级最高,得分会非常高。
- NodeAffinityPriority: 节点的亲和性,亲和性高,得分高。基于节点亲和性调度偏好进行的优选级评估,根据Pod资源中的nodeSelector对给定节点进行匹配度检查,成功匹配到的条目越多则节点得分越高。
- TaintTolerationPriority: 将Pod对象的spec.tolertions与节点的taints列表项进行匹配度检测,匹配的条目越多,得分越低。
- SelectorSpreading: 尽可能的把Pod分散开,也就是没有启动这个Pod的node,得分会越高。
- InterPodAffinityPriority: 遍历Pod对象的亲和性条目,匹配项越多,得分就越多。
- MostRequestedPriority: 节点中空限量越少的,得分越高,与LeastRequested不能同时使用,集中各一个机器上面跑Pod,默认没有启用。
- NodeLabelPriority: 根据node上面是否拥有特定的标签来评估得分,有标签就有分,而无论其值为何。默认没有启用。
- ImageLocalityPriority: 一个node的得分高低,是根据node上面是否有镜像,有镜像就有得分,反之就没有(根据node上已有满足需求的image的size大小之和来计算),默认没有启用。
# 调度分配机制的要点
基于Pod中容器request资源"总和"调度
- resources.limits影响Pod的运行资源上限,但是不会影响调度。
- initContainer取最大值,container取累加值,最后取大值。即Max(Max(initContainers.requests), Sum(containers.requests))
- 未指定request资源时,按0资源需求进行调度,也就是任何node都满足该pod资源。
基于资源声明量的调度,而非实际占用
- 不依赖监控,系统不会过于敏感
- 能否调度成功:能否调度成功:pod.request < node.allocatable - node.requested
K8S node的资源盒子模型
也就是说一个node的资源,要满足于很多种类型的需求,不仅仅是提供给pod的资源。
重要的一些资源分配相关算法
- GeneralPredicated(主要是PodFitsReources)
- LeastRequesterPriority
- BalancedResourceAllocation,平衡CPU/MEM的消耗比例
# Pod所需资源的计算
上面已经说到了,关于resource.requests是资源调度的依据。在计算一个Pod所需要的资源的时候,同时考虑pod中的initcontainers的资源量和containers的资源量,其中initcontainers的资源量取单个容器的最大值,而containers的资源量去所有容量的累加值。然后这两个值比较取最大值。
# K8S中的高级调度及用法
# nodeSelector
将Pod调度到特定的Node上
首选要在node上定义相应的labels,然后在pod.spec.nodeSelector中定义需要调度到的相应标签的node。类似于RDBMS中通过select node.name from xxx where node.disktype=ssd and node-flavor=s3.large.2
,也就是说pod中nodeSelector要完全匹配node上的标签。
这个匹配调度的逻辑,是之前描述的MatchNodeSelector预选调度算法,预选调度算法是必须要满足项的node。
# nodeAffinity
节点亲和性,是调度程序用来确定pod对象调度到哪个node上的一组规则,和nodeselecotr一样,也是基于节点上的自定义标签和Pod对象上指定的标签选择器来进行定义的,这是nodeSelector的升级版本。
nodeAffinity属于优选函数算法中一种。
总体来说,节点亲和性调度可以分为硬亲和(required)和软亲和(preferred)。顾名思义,硬亲和性实现的是强制性规则,它是Pod调度时必须要满足的规则,如果不满足,则Pod对象会被置于Pending状态;而软亲和则是一种柔性调度限制,它倾向于将Pod对象运行于某类特定的节点之上,而调度器也将尽量满足此需求,但是在无法满足调度需求的时候,它将退而求其次地选择一个不匹配规则的节点。
# 硬亲和
硬亲和的策略在pod中位置于pod.spec.affinity.nodeAffinity.requireDuringSchedulingIgnoreDuringExecution。"IgnoreDuringExecution"表明了,该调度策略只会对当前的pod和node标签,以及相应规则,做个调度匹配。以后要是节点标签发生了变化了,那么已经调度到了该node上的Pod对象不会做出改变,只会对新建的Pod对象生效。老人老办法,新人新规定。
在上述map的中可以包含多个value(nodeSelectorTerms字段),多个nodeSelecorTerm之间是"逻辑或"的关系,意思是有节点满足其中的一个nodeSelecorTerm就算这个node满足了。
nodeSelectorTerms下面需要可以定义多个matchExpression,多个规则彼此之间为"逻辑与"的关系,也就是说只有该nodeSelecorTerm下面的所有matchExpression定义的规则都满足,这个node才算是满足了。
标签选择器表达式(matchExpression下定义的规则),支持使用的操作符号有In、NotIn、Exsits、DoesNotExists、Lt和Gt等。In表示的是只要满足后面的集合中的一个就算是满足了条件。
# 软亲和
软亲和的策略在pod中位置于pod.spec.affinity.nodeAffinity.preferredDuringSchedulingIgnoreDuringExecution。同理是"IgnoreDuringExecution"。
在上述的map中可以包含多个规则,每个规则都可以配置weight属性以便用于定义其优先级。对于相关的节点分别计算出多个规则的权重值,最后分值高的节点胜出。
# podAffinity
pod亲和性,顾名思义,调度和判断的主体是之前已经存在的pod,而非上面所说的node。是根据已调度或将要调度的pod的所位于的node的情况,来决定后续的pod将要部署在哪些node上,反映的是后一种pod对已存在pod的一种亲和性的关系的,调度管理。
podAffinity也分为亲和性和反亲和性,每种亲和策略下又分为硬(required)亲和、软(preferred)亲和。
K8S调度器通过内建的MatchInterPodAffinity预选策略为这种调度方式完成节点预选,并基于InterPodAffinityPriority优选函数进行各节点的优选级评估。
# 为什么要有pod亲和性
出于高效通信的需要,偶尔需要把一些pod对象组织在相近的位置(同一节点、机架、区域或地区等),如某业务的前端Pod和后端Pod(表现为pod亲和性)。或者说要出于安全性或分布式的原因,需要将一些Pod对象在其运行的位置上隔离开来(表现为pod反亲和性)。
# 什么是位置拓扑topologykey
Pod亲和性调度需要各相关的Pod对象运行于"同一位置",而topologykey就恰恰定义了这个一个什么样的类别,比如区域的类别、机架的类别、主机的类别等等。
在定义Pod对象的亲和性与反亲和性时,需要借助于标签选择器来选择被依赖的Pod对象,并根据选出的Pod对象所在节点的标签来判断"同一位置"的 具体意义。
# pod亲和性和node亲和性有什么区别
- 在pod.sepc.affinity存在podAffinity和podAntiAffinity,这两种配置都是对称的。
- pod亲和性调度中labelSelector的匹配对象是Pod,而node亲和性调度中匹配的是node。
- pod亲和性调度中匹配到的是根据topologykey定义的一组node,topologykey定义了分组是什么样的一个级别,相同topologykey中的key和value的值为一组。
- 在pod亲和性中硬亲和过滤规则中,条件间只有逻辑与运算。
# pod硬亲和调度
pod的硬亲和调度的API定义于pod.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution下,通过labelSelector 这个map定义多个匹配表达式。条件间只有逻辑与的运算,这一点和node亲和性有所不同。
topologyKey: kubernetes.io/hostname是K8S中节点的内建标签,它的值就是当前节点的节点主机名称。同理还有region(地区)、zone(区域)、rack(机架)的拓扑位置的定义。
# pod软亲和调度
pod的软亲和调度的API定义于pod.spec.affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution下,和node软亲和性调度类型,可以定义多个调度规则,每个规则都可以定义一个权重。
# podAntiAffinity反亲和性
与podAffinity匹配过程相同,只是最终的结果取反。
# 手动调度和DaemonSet
当遇到调度器不工作时,需要考虑到手动调度Pod。
我们只需要在pod.spec.nodeName中直接填上需要调度到的node的名称就可以了。
# DaemonSet调度
老的版本中DaemonSet中的pod调度都是由controller-manager直接指定pod的运行节点,不经过调度器。直到1.11版本开始,DaemonSet的pod才由scheduler引入调度。
DaemonSet实际上是要求每个节点都部署一个相同的pod,通常用于部署集群中的agent,例如网络插件等。在下图的Daemonset的配置中,可以看出类似于定义了一个Deployment的清单配置文件中,对于要求一个主机上不存在相同的pod label,也就是对于Pod的反亲和性。
# 污点和容忍度
污点(taints)是定义在节点之上的键值型属性数据,用于让节点拒绝将pod调度运行于其上,除非该pod对象具有容纳节点污点的容忍度。
而容忍度(tolerations)是定义在Pod对象上的键值型属性数据,用于配置其可容忍的节点污点,而且调度器仅能将Pod对象调度至其能够容忍该节点污点的节点之上。
K8S中使用PodToleratesNodeTaints预选策略和TaintTolerationPriority优选函数来完成此类高级调度机制。
# 污点容忍度/节点选择器/节点亲和性区别
上面描述的节点选择器(nodeSelector)和节点亲和性两种调度方式都是通过在Pod对象上添加标签选择器来完成对特定类型节点标签的匹配,实现的是由Pod选择节点的机制。
而污点和容忍度则是通过向节点添加污点信息来控制Pod对象的调度结果,从而赋予了节点控制何种Pod对象能够调度与其上的主控权。
节点亲和性是使得Pod对象被吸引到一类特定的节点,而污点则相反,它提供了让节点排斥特定Pod对象的能力。
# 污点
污点(taint)的定义在 node.spec.taints下,是键值型数据,但又额外支持一个效果(effect)标识,语法格式为"key=value:effect",其中key和value的用法及格式与资源注解信息相似,而effect则用于定义对pod对象的排斥等级,它主要包含以下三种类型。
- NoSchedule: 不能容忍此污点的新Pod对象,不可调度至当前节点,属于强制型约束关系,节点上现存的Pod对象不受影响。
- PreferNoSchedule: NoSchedule的柔性约束版本,即不能容忍此污点的新Pod对象尽量不要调度至当前节点,不过无其他节点可供调度时也允许接受相应的Pod对象。节点上现存的Pod对象不受影响。
- NoExecute: 不能容忍此污点的新Pod对象,不可调度至当前节点,属于强制性约束关系,而且节点上现存的Pod对象会因节点污点变动或Pod容忍度变动而不再满足匹配规则时,Pod对象将被驱逐。
给节点添加污点标识:
$ kubectl taint nodes xxx <key>=<value>:<effect>
例如:
$ kubectl taint nodes node1 node-type=production:NoSchedule
2
3
即便是同一个键值数据,若其效用标识不同,则也分属于不同的污点信息,也就是说会增加一条污点信息,和之前的区别只是在于效用标识不同。
$ kubectl taint nodes node1 node-type=production:PreferNoSchedule
删除节点上某特定键名,特定标识的污点信息。
$ kubectl taint nodes node1 node-type=NoSchedule-
删除节点上某特定键名的所有污点信息。(也就是省略效用标识)
$ kubectl taint nodes node1 node-type-
删除节点上所有的全部的污点信息,可以使用kubectl patch命令将节点属性spec.taints的值直接置为空即可。
$ kubectl patch nodes node1 -p '{"spec":{"taints":{}}}'
# 容忍度
Pod对象的容忍度可通过其pod.spec.tolerations字段进行添加,根据使用的操作符不同,主要有两种不同的形式:一种是与污点信息完全匹配的等值关系"Equal";另一种是判断污点信息存在性的匹配方式"Exists"。其中tolerationSeconds用于定义延迟驱逐当前Pod对象的时长。
需要注意的如下信息:
- 如果节点node上有多个污点信息,那么就必须该Pod对此节点上的所有污点信息都能容忍,才能调度上去。
- 匹配逻辑和之前的pod中的nodeselector正好相反,之前的逻辑是只要是node上的一个标签满足于pod中定义的node selector就进行匹配。
- pod中定义的operator为"Equal"时,就是需要在pod的toerations中完整填写所有的key、value、effect。
- pod中定义的operator为"Exists"时(key/effect/operator项是必填的,而value项留空),可以填写value为空,表示的是匹配容忍节点node中所有关于这个key中的相应的"effect"的,所有value的污点的信息。
- pod中定义的operator为"Exists"时(key/operator项是必填,value和effect为空),表示的是匹配容忍节点node中所有关于这个key值与之相同的,所有value的所有effect的污点信息。
# 污点和容忍度的调度逻辑
一个节点可以配置使用多个污点,一个Pod对象也可以有多个容忍度,不过二者在进行逻辑检查时会遵循如下逻辑。
首先处理每个有着与之匹配的容忍度的污点。
不能匹配到的污点上,如果存在一个污点使用NoSchedule效用标识,则拒绝调度Pod对象至此节点上。
不能匹配到的污点上,若没有任何一个使用NoSchedule效用标识,但至少有一个使用了PreferNoScheduler,则应尽量避免将Pod对象调度至此节点。
如果至少有一个不匹配的污点使用了NoExecute效用标识,则节点将立即驱逐Pod对象,或者不予调度至给给定节点;另外,即便容忍度可以匹配到使用了NoExecute效用标识的污点,若在定义容忍度时还同时使用了tolerationSeconds属性定义了容忍时限,则超出时限后其也将被节点驱逐。
# 调度结果和失败原因分析
查看调度结果
$ kubectl get pod xxx -o wide
1查看调度失败原因
$ kubectl describe pod xxxx
1调度失败错误列表(可以选择相应的版本)
https://github.com/kubernetes/kubernetes/blob/release-1.17/pkg/scheduler/algorithm/predicates/error.go
# 多调度器及调度器配置
如果集群中已经启动了另外的一个调度器,那我们可以在Pod对象的清单配置文件中,指定相应的"schedulerName"的值。如果集群中存在多个调度器,那么建议将node节点划分资源池来管理,避免多个调度器管理混乱。
我们可以在新配置的调取器中加载个性化的配置文件,来修改调整我们想要的排序算法。
# K8S日志/监控/应用管理
# 监控集群组件
查看集群的整体状态
$ kubectl cluster-info
1查看更多更全的信息
该信息下会收集所有的已有的pod等资源对象的信息,event信息,调度信息等。
$ kubectl cluster-info dump > xxx.txt
1查看master组件(插件部署的)
$ kubectl get pod etcd -n kube-system $ kubectl describe pod kube-apiserver -n kube-system
1
2查看组件metrics
$ curl localhost:10250/stats/summary
1查看组件的健康状况
$ curl localhost:10250/healthz
1Heapster + cAdvisor监控集群组件
早期的版本中,k8s官方提供了Heapster、InfluxDB和Grafana的组合来对系统进行,Heapster以Pod的形式运行于集群中,已被metrics-server替代。
cAdvistor既能收集容器CPU、内存、文件系统和网络使用统计信息,还能采集节点资源使用情况。使用下面的命令,展示Node CPU/内存/存储资源消耗
$ kubectl top node {node name}
1
# 监控应用
监控应用pod详细信息
$ kubectl describe pod
1展示Pod CPU/内存/存储资源消耗
对接了heapster或metrics-server后,可以展示这些数据。相比于在pod内输入top看到的数据可能有所不同,一方面如果pod内没有做资源隔离的化,看到的是整个节点的资源情况;另一方便这个命令能看到一个区间内的资源消耗情况,而不是只能实时显示当时的情况。
$ kubectl top pod {pod name}
1持续性的观察k8s中资源的变化情况
$ kubectl get pod {pod name} --watch
1
# 管理组件日志
当位于特定的目录下的组件日志查看:
/var/log/kube-apiserver.log /var/log/kube-proxy.log /var/log/kube-controller-manager.log /var/log/kubelet.log
1
2
3
4使用systemd管理的时候
$ journalctl -u kubelet
1使用K8S插件部署的时候
$ kubectl logs -f kube-proxy
1
# 管理应用日志
从K8S的容器标准输出中截取
$ kubectl logs -f {pod name} -c {container name}
1从docker容器标准输出中截取
$ docker logs -f {docker name}
1进入到容器内查看
将日志文件挂载到主机目录中:
apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: xxxxxx/xxxx name: test-container volumeMounts: - mountPath: /log name: log-volume volumes: - name: log-volume hostPath: # 主机上面的目录 path: /var/k8s/log
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16这样可以直接进入容器内来查看日志
$ kubectl exec -it {pod} -c {container} /bin/sh $ docker exec -it {container} /bin/sh
1
2
# Deployment升级和回滚
# 创建Deployment
$ kubectl run {deployment_name} --image={image} --replicas={rep.}
$ kubectl run --image=nginx my-deploy -o yaml --dry-run > my-deploy.yaml
2
或者使用yaml文件形式,重点配置replicas和image字段
# 升级Deployment
升级deployment的镜像文件
$ kubectl set image deploy/nginx nginx=nginx:1.9.1
修改deployment的资源限制
$ kubectl set resources deploy/nginx -c=nginx --limits=cpu=200m,memory=512Mi
# 升级策略
修改deployment中的升级策略
maxSurge: 是指升级期间存在的总Pod对象数量最多可以超出期望值的个数,如果spec是3,而maxSurge为1,那么则表示Pod对象的总数不能超过4个。
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 默认25%
maxUnavailable: 1 #默认25%
2
3
4
5
6
maxUnavailable: 升级期间正常可用的Pod副本数(包括新的旧的版本)最多不能低于期望值的个数。默认值为1,如果期望值spec是3,那么升级期间至少要有2个Pod对象处于正常提供服务的状态。
# 暂停Deployment
通过以下的命令来暂停deployment,暂停deployment,意思不是说我们把deployment冻住了,而是暂停这个deploy之后,所对这个deploy做的改动不会记录到升级日志版本中去了。
$ kubectl roullout pause deployment/nginx-deployment
# 恢复Deployment
当已经处于暂停状态下的deploy,可以通过如下命令来恢复。比如说现在我们想把处于暂停状态下的deploy修改另外一个image版本,但是是想把这个记录到升级日志中去。那么可以先把这个暂停了的deploy做个恢复,随后再做修改。
$ kubectl rollout resume deployment/nginx-deployment
# 查询升级状态
通过如下的命令来查看deploy对象的升级状态
$ kubectl rollout status deployment/nginx-deployment
# 查看升级历史
查看所有的版本
$ kubectl rollout history deploy/nginx-deployment
查看指定的版本
$ kubectl rollout history deploy/nginx-deployment --revision=2
# 回滚的命令
回滚到指定的版本上
$ kubectl rollout undo deployment/nginx-deployment --t0-revision=2
# 应用弹性伸缩
直接通过scale命令来弹性伸缩副本数。
$ kubectl scale deployment nginx-deployment --replicas=10
当对接了heapster,和HPA联动后。
$ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-persent=80
# 应用自恢复
这里配置应用pod自恢复策略,通过restartPolicy(重启策略)和livenessProbe(存活性探针)来做的。
Pod Restart Policy有:Always、OnFailure、Never。
livessProbe: http/https Get、shell exec、topSocket。
下面是一个tcp socket的liveness探针+always restart例子。
apiVersion: v1
kind: Pod
metadata:
name: goproxy
spec:
restartPolicy: Always
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8080
livenessProbe:
tcpSocket:
port:8080
initialDelaySeconds: 15
periodSeconds: 20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# K8S中的安全
在K8S中安全方面,主要可以分为两大类:部署态的安全控制和运行态的安全控制。
部署态的安全控制主要体现在:当"人为"(常规账户) 或pod对象(service account)通过 kubectl 、客户端库或直接使用REST接口进行请求时,需要通过认证、鉴权、Admission(准入控制)。以及正常我们所配置的Pod的安全上下文中,用于限定pod启动的用户、组、以及特权用户等。
运行态的安全控制主要体现在:Network policy上,一般是指namespaces或pod对象之间的网络访问控制。
# 基本概念罗列
# 什么是User Account(用户账户)
是k8s的客户端,此类客户端或通过kubectl、客户端库或REST接口进行请求通信时,对应的是现实中的"人"。
User Account一般是指由独立于k8s之外的其他服务管理的用户账号,K8S中不存在此类用户账号的对象。
User Account通常用于复杂的业务逻辑管控,它作用于系统全局,所以名称必须是全局唯一。
# 什么是Service Account(服务账户)
Service Account也是K8S的客户端的类型,是指由K8S API管理的账号,用于为Pod之中的服务进程访问K8S API时提供的身份标识。
Service Account属于namespace scope,它们由API Server创建,或通过API调用手动创建,附带着一组存储为Secret的用于访问API Server的凭据。
# 用户组的概念
User Account和Service Account都可以隶属于一个或多个用户组。用户组只是用户账号的逻辑集合,它本身并没有操作权限,但是附加于组上的权限(这个用户组所拥有的权限),可以被其内部的所有用户继承。
K8S有着如下几个内建的用于特殊目的的组:
- system:unauthenticated: 未能通过任何一个插件检验的账号,即未通过认证测试的用户所属的组。
- system:authenticated: 认证成功后的用户自动加入的一个组,用于快捷引用所有正常通过认证的用户账号。
- system:serviceaccounts: 当前系统上的所有Service Account对象。
- system:serviceaccounts: <namespace>: 特定名称空间内所有的Service Account对象。
# 什么是Authentication(认证)
API Server处理请求的过程中,认证插件负责鉴定用户身份。
K8S中支持的认证方式包括客户端证书、承载令牌(bearer tokens)、身份验证打理(authenticating proxy)或HTTP basic认证。认证的过程中会以串行的方式进行,直到一种认证机制成功完成即结束。
API Server接收到访问请求时,它将调用认证插件尝试将以下属性与访问请求相关联。
- Username: 用户名,如kubenetes-admin等。
- UID: 用户的数字标签符,用于确保用户身份的唯一性。
- Groups: 用户所属的组,用于权限指派和继承。
- Extra: 键值数据类型的字符串,用于提供认证时需要用到的额外信息。
API Server支持以下几种具体的认证方式。
- X509客户端证书认证:
客户端在请求报文中携带X509格式的数字证书用于认证,认证通过后,证书中的主体标识(Subject)将被识别为用户标识,其中的CN(Common Name)字段是用户名,O(Organization)是用户所属的组,如"/CN=ilinux/O=opmasters/O=admin"中,用户名为ilinux,其属于opmasters和admin两个组。
- 静态令牌文件(static Token File):
即保存着令牌信息的文件,由kube-apiserver的命令行选项--token-auth-file加载,且服务器启动后不可更改;HTTP客户端也能使用承载令牌进行身份验证,将令牌进行编码后,通过请求报文中的Authorization首部承载传递给API Server即可。
- 引导令牌(Bootstrap Tokens):
一种动态管理承载令牌进行身份认证的方式,常用于简化新建K8S集群的节点认证过程,需要通过--experimental-bootstrap-token-auth选项启用;有新的工作节点首次加入时,Master使用引导令牌确认节点身份的合法性之后自动为其签署数字证书以用于后续的安全通信,使用kubeadm join命令将节点加入kubeadm初始化的集群时使用的就是这种认证方式;这些令牌作为Secrets存储在kube-system命名空间中时,可以动态管理和创建它们,而Controller Manager 包含一个TokenCleaner控制器,用于删除过期的引导令牌。
# 什么是Authorization(授权)
授权插件用于操作权限许可鉴别,最常用的就是RBAC(基于角色的访问控制)。
API Server是一种REST API,除了身份认证信息之外,一个请求报文还需要提供操作方法及其目标对象。如针对某Pod资源对象进行的创建、查看、修改或删除操作等。
为了核验用户的操作许可,成功通过身份认证后的操作请求还需要转交给授权插件进行许可权限检查,以确保其拥有执行相应的操作的许可。这里主要介绍的就是RBAC的授权插件。
# 什么是RBAC
简而言之,就是K8S将权限授予"角色"(role)之上,有别于传统访问控制机制中将权限直接赋予使用者的方式。
用户(User)就是一个可以独立访问计算机系统中的数据或用数据表示的其他资源的主体(Subject)。
角色是一个组织或任务中的工作或位置,代表了一种权利、资格和责任。
许可(Permission)就是允许对一个或多个客体(Object)执行的操作。
一个用户可经授权而拥有多个角色,一个角色可由多个用户构成;每个角色可以拥有多种许可,每个许可也可授权给多个不同的角色。
重点内容:
- RBAC授权插件,实现了主体(用户账号或服务账号),操作(各种权限),客体(目标实体)。
- RBAC授权插件支持Role和ClusterRole两类角色,其中Role作用于名称空间级别,ClusterRole作用于集群级别。
- Role角色需要用RoleBinding这个资源类型,将Role上面的权限绑定到一个或一组用户至上。同样作用于名称空间级别。
- ClusterRole角色需要用ClusterRoleBinding这个资源类型,将ClusterRole上面的权限绑定在一个或一组用户至上。
# 什么是Admission Control(准入控制)
准入控制则是用于在资源对象的创建、删除、更新或连接(proxy)操作时实现精细的许可检查。
# 公钥/私钥/CA/数字签名
参考的网络URL如下
https://zhuanlan.zhihu.com/p/31477508
https://zhuanlan.zhihu.com/p/113522792
https://www.jianshu.com/p/939b3039478c
https://www.cnblogs.com/handsomeBoys/p/6556336.html
# 公钥和私钥
首先是加密算法分为两种,一种是对称加密算法(私钥加密算法),一种是非对称加密算法(公钥算法)。
对称加密算法:主要有DES/AES,特点是这种算法的加密/解密用的密钥key都是一样的。也就是说用一个密钥key可以加密内容,同样也可以用这把key来解密内容。举个例子:如果总部A派出了两个间谍B和C打入敌方内部,如果他们用的都是对称加密算法的话,那么如果其中一个间谍的密钥被获得的话,那么其他间谍的所有信息都会受到暴露。
非对称加密算法:这种算法加密和解密的密码不一样,一把是公钥,一把是私钥。有如下的特征:
- 公钥和私钥成对出现。
- 公开的密钥叫做公钥,只有自己知道的叫私钥。
- 用公钥加密的数据只有对应的私钥可以解密。(B在获得了A的发出的公钥后,可以例如A的公钥对要写给A的信件进行加密,那么A收到B发出的信件后,利用A自己的私钥进行解密。理论上,只要A自己的私钥不泄露,信件都是安全的。因为其他人即使截获了B发出的加密信件内容,也由于没有A的私钥而解密)
- 用私钥加密的数据只有对应的公钥可以解密。(这一点用在了数字签名上,还是上面的案例中,如果B要求 A收到了B的信件后,要给B签名签收以示确认。那么就是A收到信件后,用A对信件中的文本进行hash函数,得到文本信件摘要,然后对摘要,用自己的私钥进行加密,进行加密得到密文(签名)。而B收到这个密文后,拿出原来A给的公钥进行解密,如果得到了文本摘要hash值,和自己用同样的hash函数文本内容得到的hash值进行比对,如果相等,那么就可以确定这是A的签名无误了,A是不能抵赖的)
# CA证书
在A向B发送信息的过程中,如果有个人C图谋不轨,偷偷把B的公钥换成了自己的公钥,然后截获了A发往B的内容,这个时候C就可以通过自己的私钥解密这个内容了。
那么这个时候,就需要一个中立的权威的机构来指明,A所拿到的B的公钥真的是B的公钥。这个权威的机构就是"证书中心CA",说白了就是为公钥做个公证。证书中心用自己的私钥,对需要公证的公钥和一些相关信息一起加密(也就是CA对这个公钥进行签名认证了),生成"数字证书"。
CA证书包括以下信息:申请者的公钥、申请者的组织信息和个人信息、签发机构CA的信息、有效时间、证书序列号等信息的明文,同时要包含一个CA机构的签名。
A向B发起请求时,B返回的是一个证书文件。A读取这个证书中的明文信息,就得到了B的公钥内容;同时A也会去相应的认可的CA中心,用CA中心提供的公钥来解析这个数字证书中CA的签名信息,以此来得到B的公钥内容。两者做个比较,来判断,是否B的公钥是否正确。
# 什么是X509
是一种行业标准或者行业解决方案,在X.509方案中,默认的加密体制是公钥密码体制,一种非常通用的证书格式。
在K8S中支持的HTTPS客户端证书认证、token认证以及HTTP basic认证几种认证方式中,基于SSL/TLS协议的客户端证书认证(遵循于X.509数字证书标准)以安全性高、易于实现,成为主要使用的认证方式。
X509证书一般会用到三类文件,key,csr,crt。
key是私用密钥,openssl格式,通常是rsa算法。
csr是证书请求文件,用于申请证书。在制作csr文件的时候,必须使用自己的私钥来签署申请,还可以设定一个密钥。
crt是CA认证后的证书文件(windows下面的csr,其实是crt),签署人用自己的key给你签署的凭证。
# Openssl生成SSL证书过程
参考网上如下URL文档整理:
https://www.cnblogs.com/qiumingcheng/p/12024280.html
# 基本概念
首先要有一个CA根证书,然后用CA根证书来签发用户证书。
用户进行证书申请:一般先生成一个私钥,然后用私钥生成证书请求(证书请求里应含有公钥信息),再利用证书服务器的CA根证书来签发证书。
特别说明:
- 自签名证书(一般用于顶级证书、根证书):证书的名称和认证机构的名称相同。
- 根证书:根证书时CA认证中心给自己颁发的证书,是信任链的起始点。任何安装CA根证书的服务器都意味着对这个CA认证中心是信任的。
- 数字证书:数字证书则是由证书认证机构(CA)对证书申请者真实身份验证之后,用CA的根证书对申请人的一些基本信息以及申请人的公钥进行签名(相当于加盖证书机构的公章)后形成的一个数字文件。数字证书包含证书中所标识的实体的公钥(就是说你的证书里有你的公钥),由于证书将公钥与特定的个人匹配,并且该证书的真实性由颁发机构保证(就是说可以让大家相信你的证书时真的),因此,数字证书为如何找到用户的公钥并知道它是否有效这一问题提供了解决方案。
# openssl中有如下后缀名的文件
.key格式:私有的密钥
.csr格式:证书签名请求(证书请求文件),含有公钥信息,certficate signing requests的缩写。
.crl格式:证书吊销列表,Certificate Revocation List的缩写。
.pem格式:用于导出,导入证书时候的证书的格式,有证书开头,结尾的格式。
# CA根证书的生成步骤
根证书,是CA自己的证书,需要在部署了CA服务的服务器上操作。
一般的流程是:生成CA私钥(.key) -->生成CA证书请求(.csr) --> 自签名得到根证书(.crt)(实际上就是CA给自己颁发的证书)。
# Generate CA private key
openssl genrsa -out ca.key 2048
# Generate CSR
openssl req -new -key ca.key -out ca.csr
# Generate Self Signed certificate(CA 根证书)
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
2
3
4
5
6
在实际的软件开发工作中,往往服务器就采用这种自签名的方式,因为毕竟找第三方签名机构是要给钱的,也需要时间。
# 用户证书的生成步骤
生成用户证书的过程,一般如下:
生成私钥(.key) --> 生成证书请求(.csr) --> 用CA根证书签名得到证书(.crt)
# private key
openssl genrsa -des3 -out server.key 1024
# generate csr
openssl req -new -key server.key -out server.csr
# generate certificate
openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key
2
3
4
5
6
# 生成pem格式证书
有时候需要用到pem格式的证书,可以用以下方式合并证书(crt)和私钥文件(key)来生成。
cat client.crt client.key > client.pem
cat server.crt server.key > server.pem
2
# SSL/TLS认证
# etcd集群内部对等节点通信:
etcd集群内各节点间的集群事务通信,默认监听于TCP的2380端口,基于SSL/TLS通信时需要peer类型的数字证书,可实现节点间的身份认证及通信安全,这些证书需要由一个专用的CA进行管理。
# etcd服务器与客户端通信:
kube-apiserver是etcd服务的主要客户端。etcd的REST API服务,默认监听于TCP的2379端口,用于接收并响应客户端请求,基于SSL/TLS通信,支持服务端认证和双向认证,而且要使用一个专用的CA来管理此类证书。
# API Server与其客户端通信:
它们之间的通信的证书可由同一个CA进行管理,其客户端大体上可以分为如下三类:
- 控制平面的kube-scheduler和kube-controller-manager。
- 工作节点组件kubelet和kube-proxy:初次接入集群时,kubelet可自动生成私钥和证书签署请求,并由Master为其自动进行证书签名和颁发,这就是所谓的tls bootstraping。
- kubelet及其他形式的客户端,如Pod对象等。
# 什么是Token
Token的意思是"令牌",是服务端生成的一串字符串,作为客户端进行请求的一个标识。当用户第一次登录后,服务器生成一个token并将此token返回给客户端,以后客户端只需要带上这个token前来请求数据即可,无需再次带上用户名和密码。
# kubeconfig的配置
# kubeconfig是干什么用的
kubeconfig是一个配置文件,里面写了有哪些k8s的集群(多套K8S集群),用户列表(不同用户,包含的ApiServer的认证信息),上下文列表(不同用户对应不同的K8S环境的列表),以及当前使用的上下文(指当前默认使用的用户对应相应集群的配置信息),集群参数和用户参数可以同时设置多对,在上下文参数中将集群参数和用户参数关联起来。
通过kubeconfig,apiserver的客户端可以通过简单切换上下文列表,来完成不同用户访问不同K8S集群的目的。
# 常见命令
打印kubeconfig文件内容
$ kubectl config view
1设置kubeconfig的clusters配置段。
kubectl config set-cluster myk8s \ --certificate-authority=/path/to/ca \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=/kubeconfig/filename
1
2
3
4
5myk8s只是一个自定义的k8s集群的名字;
--certificate-authority设置了该集群的公钥;
--embed-certs表示将--certificate-authority证书写入到kubeconfig中;也就是默认是false,也就是不会在这个定义的kubeconfig文件中写入上面的证书文件的具体内容,而是写一个对应的路径,如果改为了true,那么就会在这个定义的kubeconfig文件中写上上面的定义的具体的证书文件的内容。
--server表示的是该集群的kube-apiserver的地址;
--kubeconfig指定保存的kubeconfig文件的路径。如果没有这个文件的话,会新增,如果有的话,就会在已有的这个文件中,添加集群的信息内容。
设置kubeconfig中的用户配置参数。
kubectl config set-credentials chuck \ --client-certificate=/path/to/cert \ --client-key=/path/to/private_key \ --embed-certs=true \ --kubeconfig=/kubeconfig/filename
1
2
3
4
5chuck是定义的用户名;
--client-certificate是定义的一个以.pem结尾的证书文件;
--client-key是定义的一个私钥文件,注意客户端的证书首先要经过集群CA的签署,否则不会被集群认可。此处使用的是ca认证方式,也可以使用token认证,如kubelet的TLS Bootstrap机制下的bootstrapping使用的就是token认证方式。这里的kubectl 使用的是CA认证的方式,不需要token字段。
修改context的参数。
kubectl config set-context chuck@myk8s \ --cluster=myk8s \ --user=chuck \ --kubeconfig=/kubeconfig/filename
1
2
3
4chuck@myk8s是定义的上下文名称;
--cluster是定义的集群名称;
--user是定义的用户名称;
设置默认上下文
kubectl config use-context xxxx
1
# 实现自主控制Pod对象资源的访问权限
解析一下:首先要做访问权限的控制,必须要用到鉴权插件中RBAC中的内容,也就是说需要定义不同的Role/ClusterRole,然后通过RoleBinding或ClusterRolebinding的方式,将权限依附于对应的service account上。那就是意味着pod在创建的时候,必须指定对应的service account。
手动创建service account的时候,K8S会自动提供认证令牌Secret对象创建完成。通常挂载点有三个文件:ca.crt、namespace和token。其中token文件是保存了service account的认证token,容器就是通过它向API Server发起连接请求,进而由认证插件完成用户认证并将其用户名传递给授权插件。随后为这个service account进入RoleBinding或ClusterRolebinding,然后在创建Pod的时候,指定这个service account就可以了。
# 创建自定义权限用户
创建一个自定义基于SSL/TLS认证的的用户,配置其访问k8s集群的上下文的config,以授予非管理员级的集群资源使用权限,其配置过程由两部分组成:一是为用户创建专用的私钥和证书文件,二是将其配置于某kubeconfig中。
# 创建自定义用户
创建一个自定义用户所需要的私钥和证书文件,根据上面总结的利用openssl命令生成用户证书的过程。
生成证书的过程如下:生成私钥(.key) --> 生成证书请求(.csr) --> 用CA根证书签名得到证书(.crt)。所有的这些操作都需要在master节点上以root用户的身份来执行,注意最后用到的根证书ca.crt,以及ca的私钥ca.key的位置,默认位于master节点的/etc/kubernetes/pki的路径下。
生成私钥文件,注意其权限为600以阻止其他用户随意获取,这里在Master节点上以root用户进行操作,并将文件放置于/etc/kubernetes/pki专用目录中:
# cd /etc/kubernetes/pki # (umask 077; openssl genrsa -out kube-user1.key 2048)
1
2这里openssl是生成私钥的命令,-out是指定输出的文件名,2048指的是生成2048位的rsa私钥,默认是X509编码。
创建证书签署请求,-subj选项中CN的值将被kubeconfig作为用户名使用,O的值将被识别为用户组。
# openssl req -new -key kube-usr1.key -out kube-user1.csr -subj "/CN=kube-user1/O=kuberusers"
1req 的命令大致有3个功能:生成证书请求文件、验证证书请求文件和创建根CA。这里用到的创建证书请求文件。
-new表示的是新生成一个新的证书请求文件。
-key表示的是指定私钥文件。
-out指定输出文件。
基于kubeadm安装K8S集群时生成的CA来签署证书(对于上面创建的证书签署请求予以签署),这里设置的有效时长为3650天。
openssl x509 -req -in kube-user1.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out kube-user1.crt -days 3650
1
2
# CKA考题整理
# 第一题
Set configuration context $kubectl config use-context k8s
Monitor the logs of Pod foobar and
- Extract log lines corresponding to error file-not-found
- Write them to /opt/KULM00201/foobar
Question Weight 5%
# 第二题
Set configuration context $ kubectl config use-context k8s
List all PVs sorted by name saving the full kubectl output to /opt/KUCC0010/my_volumes.
Use kubectl's own functionally for sorting the output, and do not manipulate if any further.
Question weight 3%
# 第三题
Set configuration context $ kubectl config use-context k8s
Ensure a single instance of Pod nginx is running on each node of the kubernetes cluster where nginx also represents the image name which has to be used. Do no override any taints currently in place.
Use Daemonsets to complete this task and use ds.kusc00201 as Daemonset name.
Question weight 3%
# 第四题
Set configuration context $ kubectl config use-context k8s
Perform the following tasks.
- Add an init container to lumpy--koala(Which has been defined in spec file /opt/kucc00100/pod-spec-KUCC00100.yaml)
- The init container should create an empty file named /workdir/calm.txt
- If /workdir/calm.txt is not detected, the Pod should exit
- Once the spec file has been updated with the init container definition, the Pod should be created.
Question weight 7%
# 第五题
Set configuration context $ kubectl config use-context k8s
Create a pod named kucc4 with a single container for each of the following images running inside (there may be betwen 1 and 4 images specified): nginx + redis + memcached + consul
Question weight: 4%
# 第六题
Set configuration context $ kubectl config use-context k8s
Schedule a Pod as follows:
- Name: nginx-kusc00101
- Image: nginx
- Node selecotr: disk=ssd
# 第七题
Set configuration context $ kubectl config use-context k8s
Create a deployment as follows:
- Name: nginx-app
- Using container nginx with version 1.10.2-alpine
- The deployment should contain 3 replicas
Next, deploy the app with new version 1.13.0-alpine by perfoming a rolling update and record that update.
Finally, rollback that update to the previous version 1.10.2-alpine
Quesion weight: 4%
# 第八题
Set configuration context $ kubectl config use-context k8s
Create and configure the service front-end-service so it's accessible through NodePort and routes to the existing pod named front-end.
Question weight: 4%
# 第九题
Set configuration context $ kubectl config use-context k8s
Create a Pod as follows:
- Name: jenkins
- Using image: jenkins
- In a new Kubernetes namespace named website-frontend
Question weight: 3%
# 第十题
Set configuration context $ kubectl config use-context k8s
Create a deployment spec file that will:
- Lauch 7 replicas of the redis image with the label: app_env_stage=dev
- Deployment name: kual00201
Save a copy of this spec file to "/opt/KUAL00201/deploy_spec.yaml"(or.json)
When you are done, clean up(delete) any new k8s API objects that you produced during this task.
Question weight: 3%
# 第十一题
Set configuration context ```$ kubectl config use-context k8s``
Create a file "/opt/KUCC00303/kucc00302.txt" that lists all pods that implement Service foo in Namespace production.
The format of the file should be one pod name per line.
Question weight: 3%
# 第十二题
Set configuration context $ kubectl config use-context k8s
Create a Kubernetes Secret as follows:
- Name: super-secret
- Credential: alice or username:bob
Create a Pod named pod-secrets-via-file using the redis image which mounts a secret named super-secret at /secrets
Create a second Pod named pod-secrets-via-env using the redis image, which exports credential as TOPSECRET
Question weight: 9%
# 第十三题
Set configuration context $ kubectl config use-context k8s
Create a pod as follows:
- Name: non-persistent-redis
- Container image: redis
- Named-volume with name: cache-control
- Mount path: /data/redis
It should launch in the pre-prod namespace and the volume MUST NOT be persistent.
Question weight: 4%
# 第十四题
Set configuration context $ kubectl config use-context k8s
Scale the deployment webserver to 6 pods.
Question weight: 1%
# 第十五题
Set configuration context $ kubectl config use-context k8s
Check to see how many nodes are ready (not including nodes tainted NoSchedule) and write the number to /opt/nodenum
Question weight: 2%
# 第十六题
Set configuration context $ kubectl config use-context k8s
From the Pod label name=cpu-utilizer, find pods running high CPU workloads and write the name of the Pod consuming most CPU to the file /opt/cpu.txt(which already exists)
Question weight: 2%
# 第十七题
Set configuration context $ kubectl config use-context k8s
Create a deployment as follows
- Name: nginx-dns
- Exposed via a service: nginx-dns
- Ensure that the service & pod are accessible via their respective DNS records
- The container(s) within any Pod(s) running as a part of this deployment should use the nginx image
Next, use the utility nslookup to look up the DNS records of the service & pod and write the output to /opt/service.dns and /opt/pod.dns respectively.
Question weight: 7%
# 第十八题
No configuration context change required for this item
Create a snapshot of the etcd instance running at https://127.0.0.1:2379 saving the snapshot to the file path /data/backup/etcd-snapshot.db
The etcd instance is running etcd version 3.1.10
The following TLS certificates/key are supplied for connecting to the sever with ecdctl
- CA certificate: /opt/KUCM00302/ca/crt
- Client certificate: /opt/KUCM00303/etc-client.crt
- Clientkey: /opt/KUCM00302/etcd-client.key
Question weight: 7%
# 第十九题
Set configuration context $ kubectl config use-context ek8s
Set the node labelled with name=ek8s-node-1 as unavailable and reschedule all the pods running on it.
Question weight: 4%
# 第二十题
Set configuration context $ kubectl config use-context wk8s
A Kubernetes worker node, labelled with name=wk8s-node-0 is in state NotReady.
Investigate why this is the case, and perform any appropriate steps to bring the node to a Ready state, ensuring that any changes are made permanent.
Hints:
- Yout can ssh to the failed node using $ ssh wk8s-node-0
- You can assume elevated privileges on the node with the following command $ sudo -i
Question weight: 4%
# 第二十一题
Set configuration context $ kubectl config use-context wk8s
Configure the kubelet systemd managed service, on the node labelled with name=w8s-node-1 , to launch a Pod containing a single container of image nginx named myservice automatically. Any spec files required should be placed in the /etc/kubernetes/manifests directory on the node.
Hints:
- You can ssh to the failed node using $ ssh wk8s-node-1
- You can assume elevated privileges on the node with the following command $ sudo -i
Question weight: 4%
# 第二十二题
Set configuration context $ kubectl config use-context ik8s
In this task, you will configure a new Node, ik8s-node-0, to join a Kubernetes cluster as follows:
- Configure kubelet for automatic certificate rotation and ensure that both server and client CSRS are automatically approved and signed as appropnate via the use of RBAC.
- Ensure that the appropriate cluster-info ConfigMap is created and configured appropriately in the correct namespace so that future Nodes can easily join the cluster.
- Your bootstrap kubeconfig should be created on the new Node at /etc/kubernetes/bootstrap-kubelet.conf(do not remove this file once your Node has successfully joined the cluster)
- The appropriate cluser-wide CA certificate is located on the node at /etc/kubernetes/pki/ca.crt. You should ensure that any automatically issued certificates are installed to the node at /var/lib/kubelet/pki and that the kubeconfig file for kubelet will be rendered at /etc/kubernetes/kubelet.conf upon successful bootstrapping.
- Use an additional group for bootstrapping Nodes attempting to join the cluster which should be called system:bootstrappers:cka:default-node-token
- Solution should start automatically on boot, with the systemd service unit file for kubelet available at /etc/systemd/system/kubelet.service
To test your solution, create the appropriate resources from the spec file located at /opt/.../kube-flannel.yaml . This will create the necessary supporting resources as well as the kube-flannel-ds DaemonSet. You should ensure that this DaemonSet is correctly deployed to the single node in the cluster.
Hists:
- kubelet is not configured or running on ik8s-master-0 for this task, and you should not attempt to configure it.
- You will make use of TLS bootstrapping to complete this task.
- You can obtain the IP address of the Kubernetes API server via the following command $ ssh ik8s-node-0 getent hsots ik8s--master-0
- The API server is listening on the usual port, 6443/tcp, and will only server TLS requests .
- The kubelet binary is already installed on ik8s-node-0 at /usr/bin/kublet. You will not need to deploy kube-proxy to the cluster during this task.
- You can ssh to the new worker node using $ ssh ik8s-node-0
- You can ssh to the master node with the following command $ ssh ik8s-master-0
- No further configuration of control plane services running on ik8s-master-0 is required.
- You can assume elevated privileges on both nodes with the follwing command $ sudo -i
- Docker is already installed and running on ik8s-node-0
Question weight: 8%
# 第二十三题
Set configuration context $ kubectl config use-context bk8s
Given a partially-functioning Kubernetes cluster, identify symptoms of failure on the cluster. Determine the node, the failing service and take actions to bring up the failed service and restore the health of the cluster. Ensure that any changes are made permanently.
The worker node in this cluster is labelled with name=bk8s-node-0
Hints:
- You can ssh to the relevant nodes using $ ssh $(NODE) where $(NODE) is one of bk8s-master-0 or bk8s-node-0
- You can assume elevated privileges on any node in the cluster with the following command $ sudo -i
Question weight: 4%
# 第二十四题
Set configuration context $ kubectl config use-context hk8s
Create a persistent volume with name app-config of capacity 1Gi and access mode ReadWriteOnce. The type of volume is hostPath and its location is /srv/app-config.
Question weight: 3%