1. master node组件

master:
api server 整体控制中心存数据所有的交互都以api中心 https服务
controller manager:让k8s所有功能得以实现的控制中心,有很多controller打包成了一个整体,单一运行,由大量的controller组成
scheduler:调度pod,寻找最适合的node节点进行调度运行容器,时刻观察当前集群节点资源可用量,以及为了更好运行pod中的应用所需的环境,让二者做个最佳匹配
node:
下面3个组件都与api server进行通信交互,结果都是controller manager和scheduler下发的结果

  • kubelet:看到api server中的改变
  • kube-proxy:创建和删除service的操作,在当前节点创建对应的规则,以便运行在本地的pod能够被负载均衡所调度,为了运行在各个节点上的pod访问时能够被调度,管理当前iptables、ipvs规则的
  • container

    2. k8s创建pod

    apiserver收到kubectl需要运行容器的请求,apiserver先把信息存储到etch当中,scheduler看到容器还没有被调度。从node节点中找到最适合调度的node节点,返回给apiserver并将信息存储到etcd,kubelet收到了与自己节点有关的pod创建就运行启动容器,并将容器信息发送到apiserver由apiserver将信息存储到etcd,kubelet始终监视着与自己有关的事件,看到某个pod是与自己节点相关就拿过来进行操作

    3. CNI网络k8s网络

    flannel:仅实现了网络,没有实现网络策略,网络隔离策略,比如名称空间A B 间可以通信
    calico:可以进行网络可以,支持bgp三层网络协议,性能更强大
    canal:使用flannel网络,使用calico网络策略

Kubernetes主要存在4种类型的通信:
C-to-C:发生在Pod内部,借助于lo实现;
Pod-to-Pod:Pod间的通信,k8s自身并未解决该该类通信,而是借助于CNI接口,交给第三方解决方案;CNI之前的接口叫kubenet;
Service-to-Pod:借助于kube-proxy生成的iptables或ipvs规则完成;
ExternalClients-to-Service:引入集群外部流量,hostPort、hostNetwork、nodeport/service、loadbalancer/service、externalIP/service、Ingress;

Flannel, Calico

构建出虚拟网络:
Overlay Network:叠加网络,覆盖网络
Underlay Network:承载网络
将容器接入虚拟网络,
虚拟网桥
多路复用
单根网络(硬件交换)

3.1. VXLAN

VLAN最多支持4095个
节点在本地维护一个路由表,当pod对其他节点pod比如10.244.1.0/24 网段的请求时,根据本地维护的路由表找到对应的节点,其他节点将请求发送给对应pod

flannel负责报文的封装解封,联系到etcd的数据,生成本地的路由表
image.png

3.2. flannel

flannel:仅实现了网络,没有实现网络策略,网络隔离策略,比如名称空间A B 间可以通信
flannel负责报文的封装解封,联系到etcd的数据,生成本地的路由表
没有控制中心,所有节点平等

Flannel支持三种Pod网络模型,每个模型在flannel中称为一种“backend”:
vxlan:Pod与Pod经由隧道封装后通信,各节点彼此间能通信就行,不要求在同一个二层网络;

vxlan directrouting: 位于同一个二层网络上的、但不同节点上的Pod间通信,无须隧道封装;但非同一个二层网络上的节点上的Pod间通信,仍须隧道封装;

host-gw:Pod与Pod不经隧道封装而直接通信,要求各节点位于同一个二层网络;

flannel VXLAN模型
默认VXLAN模型 flannel VXLAN模型
image.png

本节点pod不需要通过flannel.1网卡通信了,cni0通信
跨节点需要通过flannel.1
image.png
本地保存的路由规则
image.png
image.png


flannel DirectRouting模型
需要在同一个二层网络
image.png
不在需要flanneld进行封装,走flannel.1了
image.png

host-gateway模型
host-gateway需要在同一个二层网络
通过维护的路由表直接通信,不需要VXLAN虚拟通道
image.png

不需要flanneld进行封装,走flannel.1了
image.png

3.3. Calico

具有控制中心,管理所有节点

3.4. NetworkPolicy入站出战流量管理

尽管功能上日渐丰富,但k8s自己的NetworkPolicy资源仍然具有相当的局限性,例如它没有明确的拒绝规则、缺乏对选择器高级表达式的支持、不支持应用层规则,以及没有集群范围的网络策略等。为了解决这些限制,Calico等提供了自有的策略CRD,包括NetworkPolicy和GlobalNetworkPolicy等,其中的NetworkPolicy CRD比Kubernetes NetworkPolicy API提供了更大的功能集,包括支持拒绝规则、规则解析级别以及应用层规则等,但相关的规则需要由calicoctl创建。

apiVersion: networking.k8s.io/v1 # 资源隶属的API群组及版本号
kind: NetworkPolicy # 资源类型的名称,名称空间级别的资源;
metadata: # 资源元数据
name # 资源名称标识
namespace # NetworkPolicy是名称空间级别的资源
spec: # 期望的状态
podSelector #当前规则生效的同一名称空间中的一组目标Pod对象,必选字段;
# 空值表示当前名称空间中的所有Pod资源
policyTypes <[]string> # Ingress表示生效ingress字段;Egress表示生效
# egress字段,同时提供表示二者均有效
ingress <[]Object> # 入站流量源端点对象列表,白名单,空值表示“所有”
- from <[]Object> # 具体的端点对象列表,空值表示所有合法端点
- ipBlock # IP地址块范围内的端点,不能与另外两个字段同时使用
- namespaceSelector # 匹配的名称空间内的端点
podSelector #由Pod标签选择器匹配到的端点,空值表示
ports <[]Object> # 具体的端口对象列表,空值表示所有合法端口
egress <[]Object> # 出站流量目标端点对象列表,白名单,空值表示“所有”
- to <[]Object> # 具体的端点对象列表,空值表示所有合法端点,格
image.png

拒绝所有入站、出战流量
image.png

4. CRI

runtime 运行时 docker 容器

5. CSI

Storage 存储 volume

6. k8s 3个网络

节点网络、pod网络、service网络
service网络:只出现在iptables、IPVS的规则当中,作为服务的endpoint(网络端点)使用的,由kube-proxy管理的。

7. 容器存在关系

亲密:ELK的边车模式
共享:共享 network、IPC、UTS、共享一组存储卷mount
UTS(主机名和域名)、IPC(消息队列)、NET(网络栈)
不共享文件系统。共享一组存储卷
只有不通过lo接口、不通过共享存储卷,就无法协同的才会认为是亲密关系的
pause基础容器,基础设施容器
pod内共享的
image.png

非紧密:
pod to pod:网络插件
pod to service:iptables、ipves规则
kube-proxy会基于配置模型,把集群上每一个service的定义转换为本地的IPVS或者iptables规则
External client -> service or pod

大使模式:
更好接入外部环境而设定的
访问数据

8. kubelet

kubelet监视着当前节点的每一个pod是否健康,把健康状态随时报告给apiserver,deployment也监视着apiserver,发现了不健康的,就重新创建一个,删除不健康的
当节点宕机,apiserver收不到kubelet信息,意味着节点没了有问题,将pod标记为删除,deployment发现并重新创建pod

8.1. 节点租约

1.13以前bubelet每隔10s向apiserver报告自己还存活正常,如果节点数量大的话,非常占用网络资源,累计4次apiserver没有收到某个节点发来的心跳时,就会置为notready,此前在该节点运行的pod,也会在其他节点重新创建
1.13之后引入node status 同时协调工作,更加轻便可扩展的,叫做节点租约,节点租约保存在 kube-node-lease名称空间
kubelet每10s更新一次kube-node-lease中数据,每10s计算一次node status但不上报,node status当发生变化时才上报
节点租约:
image.png

8.2. 调用容器

k8s仅是放弃对dockershim接口的支持、维护
直接调用CRI-plugin
image.png
image.png

9. 控制器

控制器:负载确保将实际状态设定不断逼近或者等同于期望状态
create、delete、change
deployment:滚动更新、
daemonset:节点采集器
statefulset:
job、cronjob

负责应用编排的控制器有如下几种:

ReplicationController:最早期的Pod控制器;已弃用

RelicaSet:副本集,负责管理一个应用(Pod)的多个副本;
Deployment:部署,它不直接管理Pod,而是借助于ReplicaSet来管理Pod;最常用的无状态应用控制器;

DaemonSet:守护进程集,用于确保在每个节点仅运行某个应用的一个Pod副本;节点只能运行一个,不能超过一个。守护进程而言通常只需要一个

StatefulSet:功能类似于Deployment,但StatefulSet专用于编排有状态应用;

Job:有终止期限的一次性作业式任务,而非一直处于运行状态的服务进程;
CronJob:有终止期限的周期性作业式任务;

RelicaSet:并不直接控制pod。而控制自己的控制器资源对象,控制所有RelicaSet资源,而资源上定义了pod,然后借助于kubelet和apiserver来确保pod得以实现
Controller Manager —> ReplicaSet Control Loop —> ReplicaSet Object —> 向API Server请求管理Pod对象(标签选择器选定的)—> 作用之一:以Pod模板向API Server请求创建Pod对象 —> 由Scheduler调度并绑定至某节点 —> 由相应节点kubelet负责运行。

9.1. ReplicaSet

RelicaSet 创建
RelicaSet:并不直接控制pod。而控制自己的控制器资源对象,控制所有RelicaSet资源,而资源上定义了pod,然后借助于kubelet和apiserver来确保pod得以实现

Controller Manager —> ReplicaSet Control Loop —> ReplicaSet Object —> 向API Server请求管理Pod对象(标签选择器选定的)—> 作用之一:以Pod模板向API Server请求创建Pod对象 —> 由Scheduler调度并绑定至某节点 —> 由相应节点kubelet负责运行。

ReplicaSet的更新机制:
删除式更新:删除老版本的(或现有的)Pod,
单批次删除所有Pod,一次完成所有更新;服务会中断一段时间;(这里人工删除不会自动删除更新)
分批次删除(删除其中一部分),待一批次就绪之后,才删除下一批;滚动更新;(这里人工删除不会自动删除更新)
更新yaml文件镜像版本并不会更新容器中的镜像版本,只有删除了镜像才会重新创建镜像,使用新版本镜像

set image:更新应用版本,但对于replicaset来说,仅能更新API Server中的定义;

示例:

  1. apiVersion: apps/v1
  2. kind: ReplicaSet
  3. metadata:
  4. name:
  5. namespace:
  6. spec:
  7. minReadySeconds <integer> # Pod就绪后多少秒内,Pod任一容器无crash方可视为“就绪”
  8. replicas <integer> # 期望的Pod副本数,默认为1
  9. selector: # 标签选择器,必须匹配template字段中Pod模板中的标签;如果匹配不到将会一直创建pod
  10. matchExpressions <[]Object> # 标签选择器表达式列表,多个列表项之间为“与”关系
  11. matchLabels <map[string]string> # map格式的标签选择器
  12. template: # Pod模板对象
  13. metadata: # Pod对象元数据
  14. labels: # 由模板创建出的Pod对象所拥有的标签,必须要能够匹配前面定义的标签选择器,
  15. spec: # Pod规范,格式同自主式Pod

蓝绿更新
优点:便于回滚
image.png

滚动更新
优点:节省资源
缺点:新旧版本并存问题,使用高级策略Strategy
image.png

9.2. deployment

apiVersion: apps/v1  # API群组及版本
kind: Deployment  # 资源类型特有标识
metadata:
  name <string>  # 资源名称,在作用域中要唯一
  namespace <string>  # 名称空间;Deployment隶属名称空间级别
spec:
  minReadySeconds <integer>  # Pod就绪后多少秒内任一容器无crash方可视为“就绪”
  replicas <integer> # 期望的Pod副本数,默认为1
  selector <object> # 标签选择器,必须匹配template字段中Pod模板中的标签
  template <object>  # Pod模板对象

  revisionHistoryLimit <integer> # 滚动更新历史记录数量,默认为10
  strategy <Object> # 滚动更新策略
    type <string>  # 滚动更新类型,可用值有Recreate(重建)和RollingUpdate(滚动更新 默认);
    rollingUpdate <Object>  # 滚动更新参数,专用于RollingUpdate类型
      maxSurge <string>  # 更新期间可比期望的Pod数量多出的数量或比例;默认25%
      maxUnavailable <string>  # 更新期间可比期望的Pod数量缺少的数量或比例,10, 默认25%
  progressDeadlineSeconds <integer> # 滚动更新故障超时时长,默认为600秒
  paused <boolean>  # 是否暂停部署过程

设置示例
先减去1个再加pod,不增加pod数量,不能同时为0
image.png

Deployment金丝雀发布
#滚动发布时,暂停,此时只有一部分pod的是新版本
image.png
# 检查新老版本都有
image.png
# 恢复滚动更新
image.png

借助于replicaset
image.png

9.3. daemonset

在集群每个节点上运行一个
在节点上打上标签,使用标签选择器,在匹配上的节点上运行一个
不在有污点的节点上运行,除非容忍污点

apiVersion: apps/v1  # API群组及版本
kind: DaemonSet  # 资源类型特有标识
metadata:
  name <string>  # 资源名称,在作用域中要唯一
  namespace <string>  # 名称空间;DaemonSet资源隶属名称空间级别
spec:
  minReadySeconds <integer>  # Pod就绪后多少秒内任一容器无crash方可视为“就绪”
  selector <object> # 标签选择器,必须匹配template字段中Pod模板中的标签
  template <object>  # Pod模板对象;

  revisionHistoryLimit <integer> # 滚动更新历史记录数量,默认为10;
  updateStrategy <Object> # 滚动更新策略
    type <string>  # 滚动更新类型,可用值有OnDelete(删除式)和RollingUpdate(滚动更新);
    rollingUpdate <Object>  # 滚动更新参数,专用于RollingUpdate类型
      maxUnavailable <string>  # 更新期间可比期望的Pod数量缺少的数量或比例

9.4. job

一次性作业
将一个作业串行执行多次
单批多次执行

Job的配置规范

apiVersion: batch/v1  # API群组及版本
kind: Job  # 资源类型特有标识
metadata:
  name <string>  # 资源名称,在作用域中要唯一
  namespace <string>  # 名称空间;Job资源隶属名称空间级别
spec:
  selector <object> # 标签选择器,必须匹配template字段中Pod模板中的标签
  template <object>  # Pod模板对象
  completions <integer> # 期望的成功完成的作业次数,成功运行结束的Pod数量
  ttlSecondsAfterFinished  <integer> # 终止状态作业的生存时长,超期将被删除
  parallelism  <integer>  # 作业的最大并行度,默认为1
  backoffLimit <integer>  # 将作业标记为Failed之前的重试次数,默认为6
  activeDeadlineSeconds  <integer> # 作业启动后可处于活动状态的时长

9.5. cronjob

周期性作业,cronjob借助于job控制器来控制pod

CronJob的配置规范

apiVersion: batch/v1beta1  # API群组及版本
kind: CronJob  # 资源类型特有标识
metadata:
  name <string>  # 资源名称,在作用域中要唯一
  namespace <string>  # 名称空间;CronJob资源隶属名称空间级别
spec:
  jobTemplate  <Object>  # job作业模板,必选字段
    metadata <object>  # 模板元数据
    spec <object>  # 作业的期望状态
  schedule <string>  # 调度时间设定,必选字段
  concurrencyPolicy  <string> # 并发策略,可用值有Allow(允许)、Forbid(禁止)和Replace(新的替换老的),指上过没有运行完成是否启动下一个pod运行
  failedJobsHistoryLimit <integer> # 失败作业的历史记录数,默认为1,失败的保存1个
  successfulJobsHistoryLimit  <integer> # 成功作业的历史记录数,默认为3,成功的保存3个
  startingDeadlineSeconds  <integer> # 因错过时间点而未执行的作业的可超期时长
  suspend  <boolean> # 是否挂起后续的作业,不影响当前作业,默认为false

image.png# 重启策略
# 示例
image.png

cronjob借助于job控制器来控制pod
image.png

9.6. 有状态 无状态

无状态:
无状态应用客户端每一次链接都可以被独立处理,一次请求和相关响应就构成了完整的事务,不受完成的链接或现有其他连接影响。
一次请求和他收到的响应就组成了一次完整的事务,不受已经完成的连接或现有其他连接影响,彼此间没有影响,并且意外中断或关闭时,只需要重建连接就可以了
所以无状态应用中的pod实例,可被同类的统一模板的pod实例无缝取代,

有状态:
mysql正在执行事务,有两个连接,连接只有互相影响,
客户端每次连接都在先前事务的上下文中执行,前面执行过的对后面有影响,还会受到该上下文的影响,事务意外中断时其上下文和历史很可能会被进程存储以便恢复
所以能够对事务的中间状态加以存储,当同一客户端连接上来,能够继续后的操作,这种就是有状态应用
如果某个应用启动多个实例,这个应用多个实例彼此间能否互相取代

9.7. statefulset

statefulset通用的有状态应用控制器:
每个pod都有自己的唯一标识,故障时,他只能被拥有同一标识的新实例所取代
如果有必要,可以为每个pod配置专用的存储卷

StatefulSet是为了解决有状态服务的问题,其应用场景包括:
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)

可以为每个pod配置专用的存储卷
image.png

StatefulSet配置规范:

apiVersion: apps/v1  # API群组及版本;
kind: StatefulSet  # 资源类型的特有标识
metadata:
  name <string>  # 资源名称,在作用域中要唯一
  namespace <string>  # 名称空间;StatefulSet隶属名称空间级别
spec:
  replicas <integer> # 期望的Pod副本数,默认为1
  selector <object> # 标签选择器,须匹配Pod模板中的标签,必选字段
  template <object>  # Pod模板对象,必选字段
  revisionHistoryLimit <integer> # 滚动更新历史记录数量,默认为10
  updateStrategy <Object> # 滚动更新策略
    type <string>  # 滚动更新类型,可用值有OnDelete和Rollingupdate
    rollingUpdate <Object>  # 滚动更新参数,专用于RollingUpdate类型
      partition <integer>  # 分区指示索引值,默认为0
  serviceName  <string>  # 相关的Headless Service的名称,必选字段
  volumeClaimTemplates <[]Object>  # 存储卷申请模板
    apiVersion <string>  # PVC资源所属的API群组及版本,可省略
    kind <string>  # PVC资源类型标识,可省略
    metadata <Object>  # 卷申请模板元数据
    spec <Object>  # 期望的状态,可用字段同PVC
  podManagementPolicy  <string> # Pod管理策略,默认的“OrderedReady”表示顺序创
                                     #建并逆序删除,另一可用值“Parallel”表示并行模式

10. 服务发现和负载均衡

service、ingress

11. 配置和存储卷

configmap、secret(私密的、敏感信息的)
PV/PVC
downward API
role、rolebinding

12. 元数据类型

LimitRange

13. pod状态(相位)

常见状态5个
running:运行中
Pending:挂起、悬空、未调度成功、仍处于下载镜像过程种,下载镜像比较慢
succeeded:成功终止,主要是job的pod,
Failed:至少有一个没能成功终止,就会处于Failed状态
unknown:apiserver无法正常获取到pod的信息,通常是由于没有办法与pod所在节点的kubelet通信所导致的
containerCreating:容器创建中
其他状态:
这里一般都是pod内部容器的状态
CrashLoopBackOff:第1次失败0s重启,第2次失败10s重启,3 —20,4—40,5—80,6—160,7—300,不再重启——>每次重启的状态显示为CrashLoopBackOff
Error:

14. 探针

  • post start hook:启动前执行
  • startup probe:启动探针,启动时执行一定的时长,偏于用户使用同startup probe不同的参数或阀值,启动完成后才会执行liveness和read探针
  • liveness probe:存活探针,周期性执行,检查未通过,根据restartPolicy定义的来决定是否重启,未定义时,只要容器未终止,即认为健康
  • readiness probe:就绪性探针,等待程序所有资源都加载成功了,周期性执行,检测未通过,将该pod从service中删除,直到就绪后添加到services中,只要容器未终止,即认为健康
  • pre start hook:结束后执行

探针方式:
ExecActioin:执行命令,命令成功返回表示探,测成功
TCPSocketAction:向tcp端口发起请求,有回应表示成功,第一次握手即可
HTTPGetAction:向指定的path发HTTP请求,2xx,3xx的响应表示成功

pod配置
image.png
image.png

探针配置port的http,并不是代表http80,这里代表上面容器中定义的ports的name的http的端口
image.png

15. 钩子

容器启动和停止的钩子,容器启动应用前执行钩子,关闭应用前执行钩子
和探针一样有3种方式,exec、http、tcosocket
image.png

钩子探针顺序
image.png

16. ENV

ENV是容器级别的参数,设置容器的环境变量

17. k8s网络类型

hostNetwork Pod使用宿主机上的网络,此时可能端口冲突。 hostPort 宿主机上的端口与Pod的目标端口映射。 NodePort 通过Service访问Pod,并给Service分配一个ClusterIP。

18. pod 容器安全上下文

image.png
image.png

18.1. 容器内核权限容器增加iptables规则去除指定权限

add: [‘NET_ADMIN’]
drop: [‘CHOWN’]
image.png

18.2. 容器内核优化

image.png
bubelet为容器设置内核参数
net.core.somaxconn 等待列队长度等待入站队列最大长度默认128
net.ipv4-ip_unprivileged_port_start 非特权用户使用端口从80开始,而不是从1024开始
image.png

在Kubernetes集群下运行的容器的内核参数是默认的,但是对于某型类型的应用如Nginx Ingress controller而言,默认的内核参数配置是不够的,需要做出调整,例如somaxconn是限制了接收新 TCP 连接侦听队列的大小,它的默认值是128,但是对于反向代理的服务器而言,这个配置实在是太小了。那么我们自然想到需要去调整这个应用的容器的内核配置参数。
net.core.somaxconn=65535

pod的yaml文件也需要配置
image.png

19. 集群级别的资源

namespace、node、role、clusterrole

20. 资源限制

request:确保节点至少为pod或者容器预留的资源最小量
CPU、memory、卷空间

CPU,可压缩型
memory,不可压缩型

cpu单位:多少CPU核心,1核=1000m
memory:1Ki 1Mi

request:node节点最少需要,下阈值
limit:最多使用,上阈值,超过上限容器状态出现oomkill,出现CrashLoopBackOff状态进行重启

即便为容器做了资源限制,但是容器内部显示的内存、cpu还是和运行的节点的宿主机一样的
image.png
有些程序、进程可能,默认使用的资源根据系统所显示的资源来设定,而不是容器资源限定的值
downwardAPIs:是一种存储卷,告诉容器内部的进程真实的资源可用,而不是系统所显示的资源量

limitranger: 为Pod添加默认的计算资源需求和计算资源限制;以及存储资源需求和存储资源限制;支持分别在容器和Pod级别进行限制;
resourcequota:限制资源数量,限制计算资源总量,存储资源总量;资源类型名称ResourceQuota
podsecuritpolicy:在集群级别限制用户能够在Pod上可配置使用的securityContext。

20.1. limitranger名称空间内pod 容器 pvc限制

名称空间下容器限制,超过或低于设置的都不能创建,容器未指定时使用默认值
image.png
image.png

20.2. resourcequota限制名称空间中处于非终止状态的所有Pod对象的资源

ResourceQuota资源可限制名称空间中处于非终止状态的所有Pod对象的计算资源需求及计算资源限制总量。
 cpu或requests.cpu:CPU资源相关请求的总量限额;
 memory或requests.memory:内存资源相关请求的总量限额;
 limits.cpu:CPU资源相关限制的总量限额;
 limits.memory:内存资源相关限制的总量限额;

ResourceQuota资源还支持为本地名称空间中的PVC存储资源的需求总量和限制总量提供限额,它能够分别从名称空间中的全部PVC、隶属于特定存储类的PVC以及基于本地临时存储的PVC三个类别分别进行定义。

 requests.storage:所有PVC存储需求的总量限额;空间限制;
 persistentvolumeclaims:可以创建的PVC总数限额;数量限制;
.storageclass.storage.k8s.io/requests.storage:特定的存储类上可使用的所有PVC存储需求的总量限额;
.storageclass.storage.k8s.io/persistentvolumeclaims:特定的存储类上可使用的PVC总数限额;
 requests.ephemeral-storage:所有Pod可以使用的本地临时存储资源的requets总量;
 limits.ephemeral-storage:所有Pod可用的本地临时存储资源的limits总量。

在v1.9版本之前的Kubernetes系统上,ResourceQuota仅支持在有限的几种资源集上设定对象计数配额,例如pods、services和configmaps等,而自v1.9版本起开始支持以count/.的格式支持对所有资源类型对象的计数配额,例如count/deployments.apps、count/deployments.extensions和 count/services等。
image.png

20.3. podsecuritpolicy

默认未启用,限制规则很严格(未经精心配置容易导致容器无法运行),所以默认未启用,创建psp资源也没有用,要首先启用psp

podsecuritpolicy:在集群级别限制用户能够在Pod上可配置使用的securityContext。

apiVersion: policy/v1beta1  # PSP资源所属的API群组及版本
kind: PodSecurityPolicy  # 资源类型标识
metadata:
  name <string>  # 资源名称
spec:  
  allowPrivilegeEscalation  <boolean>  # 是否允许权限升级
  allowedCSIDrivers <[]Object>  #内联CSI驱动程序列表,必须在Pod规范中显式定义
  allowedCapabilities <[]string>  # 允许使用的内核能力列表,“*”表示all
  allowedFlexVolumes <[]Object>  # 允许使用的Flexvolume列表,空值表示“all
  allowedHostPaths <[]Object>  # 允许使用的主机路径列表,空值表示all
  allowedProcMountTypes <[]string> # 允许使用的ProcMountType列表,空值表示默认
  allowedUnsafeSysctls <[]string> # 允许使用的非安全sysctl参数,空值表示不允许
  defaultAddCapabilities  <[]string>  # 默认即添加到Pod对象的内核能力,可被drop
  defaultAllowPrivilegeEscalation <boolean> # 是否默认允许内核权限升级
  forbiddenSysctls  <[]string> # 禁止使用的sysctl参数,空表示不禁用
  fsGroup <Object>  # 允许在SecurityContext中使用的fsgroup,必选字段
    rule <string>  # 允许使用的FSGroup的规则,支持RunAsAny和MustRunAs
    ranges <[]Object> # 允许使用的组ID范围,需要与MustRunAs规则一同使用
      max  <integer>  # 最大组ID号
      min  <integer>  # 最小组ID号
  hostIPC <boolean> # 是否允许Pod使用hostIPC
  hostNetwork <boolean> # 是否允许Pod使用hostNetwork
  hostPID <boolean> # 是否允许Pod使用hostPID
  hostPorts <[]Object>  # 允许Pod使用的主机端口暴露其服务的范围
    max  <integer>  # 最大端口号,必选字段
    min  <integer>  # 最小端口号,必选字段
  privileged  <boolean>  # 是否允许运行特权Pod
  readOnlyRootFilesystem  <boolean>  # 是否设定容器的根文件系统为“只读”
  requiredDropCapabilities <[]string> # 必须要禁用的内核能力列表  
  runAsGroup  <Object>  # 允许Pod在runAsGroup中使用的值列表,未定义表示不限制
  runAsUser <Object> # 允许Pod在runAsUser中使用的值列表,必选字段
    rule <string>  # 支持RunAsAny、MustRunAs和MustRunAsNonRoot
    ranges <[]Object> # 允许使用的组ID范围,需要跟“MustRunAs”规则一同使用
      max  <integer>  # 最大组ID号
      min  <integer>  # 最小组ID号
  runtimeClass <Object> # 允许Pod使用的运行类,未定义表示不限制
    allowedRuntimeClassNames <[]string> # 可使用的runtimeClass列表,“*”表示all
    defaultRuntimeClassName <string> # 默认使用的runtimeClass
  seLinux <Object> # 允许Pod使用的selinux标签,必选字段
    rule <string>  # MustRunAs表示使用seLinuxOptions定义的值;RunAsAny表示可使用任意值
    seLinuxOptions  <Object>  # 自定义seLinux选项对象,与MustRunAs协作生效
  supplementalGroups  <Object> # 允许Pod在SecurityContext中使用附加组,必选字段  volumes <[]string>  # 允许Pod使用的存储卷插件列表,空表示禁用,“*”表示全部

21. Qos Class服务质量类别

Qos Class服务质量类别代表了pod的资源被优先满足的类别
image.png
Kubernetes根据Pod中Containers Resource的request和limit的值来定义Pod的QoS Class。其中,指定容器request,代表系统确保能够提供的资源下限值。指定容器limit,代表系统允许提供的资源上限值。
对于每一种Resource都可以将容器分为3中QoS Classes: Guaranteed, Burstable, Best-Effort,它们的QoS级别依次递减。K8S底层实际上是通过 limit和request值来实现不同等级QoS的划分。

22. services

services借助中间组件endpoint,不但能够对标签中pod加入到后端端点,还能对后端pod状态做就绪性检测,非就绪状态会移除
真正绑定services的是有endpoint进行的,services只负责进行调度,endpoint找到所有就绪的pod告诉services,services进行调度,
services动态的为一组pod提供一个固定的访问入口 —> clusterIP(cluster Network)

控制器触发apiserver上面的或者控制平面上的调度器绑定到某个节点上,触发bublet去运行起来
services controller
endpoint controller

kube-proxy,services controller位于各节点上agent

22.1. services选择pod 标签

service识别标签选择器 label selector,标签匹配条件,满足条件pod都是调度对象满足调整的后端ip:port称为endpoint
services监控着apiserver,监控着满足的条件的pod

22.2. services代理模式

userSpace模式:已经不支持
pod—>service,iptables拦截规则,但直接不调度

iptables模式:
iptables规则直接调度请求到pod
缺点:生成大量规则

ipvs模式:需要内核启用ipvs

22.3. service类型

clusterIP:
通过集群内部IP地址暴露服务,但该ip地址仅在集群内部可见、可达,无法被集群外部客户端访问,默认类型

nodePort:
NodePort是clusterIP的增强类型
不仅能被集群内部可见,还可以被集群外部可见
它会与clusterIP的功能之外,在每个节点上使用一个相同端口号将外部流量引入到该service上

LoadBalancer:
Iaas云上适用
LB是nodePort的增强类型
要借助于Iaas云服务上的LBaas产品来按需管理LoadBalancer

ExternalName:
借助集群上kubeDNS来实现,服务的名称会被解析为一个CNAME记录,而CNAME名称会被DNS解析为集群外部的服务的IP地址,从而让集群内部能够访问集群外部的服务
这种的service既不会有clusterIP也不会有NodePort

22.4. service资源定义格式

image.png
image.png
image.png

22.5. 访问流量

集群内部
cluster: client —> clusterIP:ServicePort —> PodIP:targetPort
out cluster:client —> NodeIP:NodePort —> PodIP:targetPort

externalTrafficPolicy:外部流量访问NodePort时,local表示由当前节点的pod处理,Cluster表示进行调度
local表示由当前节点的pod处理(这样不用在访问到其他节点减少消耗,比访问到其他节点更快性能更好),如果当前节点没有对应的pod访问失败、服务不可达
image.png

22.6. 创建endpoint绑定集群外部服务IP:端口

endporin绑定一个集群外部服务器IP:端口,比如mysql,集群内部可以通过service进行访问
image.png

只要有相同的资源名,service和endpoint会自动关联,不需要通过标签选择器
image.png

23. clusterIP

23.1. iptables

image.png

23.2. IPVS

nat类型:仅需借助极少量的iptables规则完成源地址转换等功能
kube-ipvs0网卡名,将所有clusterIP绑定在该接口,而后将每个Service定义为虚拟服务器

24. 服务发现 DNS解析coreDNS

将传统的DNS服务直接提供一个云原生解决方案,他支持从apiserver动态加载相关的service及端点信息,并自动生成资源记录
服务注册和发现的总线:kubeDNS,实现方案上,有三代:SkyDNS、kubeDNS、CoreDNS

24.1. 容器内部自动生成ip的环境变量

kubernetes Service环境变量
docker link环境变量
image.png

24.2. DNS解析

image.png
image.png

24.3. dns解析-service域名解析

service名称.namespace名称.svc.cluster.local.
svc (固定搭配)
cluster.local (coreDNS中设定的)
image.png

24.4. dns解析-service端口解析-SRV

http.tcp.namespace名称.svc.cluster.local.
image.png

24.5. dns解析-反向解析-ip解析得到域名-PTR

image.png

24.6. coreDNS配置上级域名解析地址

image.png

24.7. headless Service

image.png

25. 存储卷

共享式存储设备:
多路并行读写
多路只读
单路读写
pod使用volume步骤:
1、在pod上定义存储卷,并关联值目标存储服务上
2、在所需用到存储卷的容器上,挂载其所属的pod存储卷
image.png
kubelet —>Container Engine
管理存储卷的功能,也是kubelet实现
volume Plugin:卷插件

存储卷类型:
host级别:hostPath、Local
网络级别:
NFS、GlusterFS、Ceph(文件系统)、rbd(块设备)、awsEBS、NAS、SAN(Storage Area Network)、
SDS(Software Defined)、Ceph(rbd cephfs)
临时存储:emptyDIR

25.1. emptyDIR 内存临时存储卷

medium:为”” 时,为磁盘类型
image.png

25.2. hostpath本地存储

image.png

25.3. PV和PVC

PVC和PV
PVC: Persistent Volume Claim,持久卷申请,简称PVC;k8s上标准的资源类型之一;由用户使用;名称空间级别;
PV: Persistent Volume,持久卷,可被PVC绑定;而PV一定要与某个真正的存储空间(一般是网络存储服务上的存储空间)对应起来,才能真正存储数据。由集群管理员负责管理。集群级别。
PVC创建完成后,需要找到最为匹配的PV,并与之绑定。
在哪儿找:
二者要么都不属于任何StorageClass资源,要么属于同一个StorageClass资源;
怎么找:
PV、PVC:将存储消费,存储创建的职能分离开来,
PV:由管理员定义的,将真正的存储设备上的一段存储空间抽象成的k8s的对象;集群级别;
NFS exported 目录;
PVC:由用户定义出存储消费需求,而后根据需求条件与现有各PV进行匹配检测,找出一个最佳的使用。名称空间级别,Pod只能调用与自己在同一名称空间中的PVC;
pvc:pod通过pvc插件调用pvc在到pv
Pod(pvc plugin) -> PVC(同一名称空间) -> PV(集群级别)

Pod使用这类存储的步骤:
Admin:创建好PV;
User: 按需创建PVC,而后创建Pod,在Pod调用persistentVolumeClaim类型的存储卷插件调用同一个名称空间中的PVC资源;

除了存储卷插件之外,PersistentVolume资源规范Spec字段主要支持嵌套以下几个通用字段,它们用于定义PV的容量、访问模式和回收策略等属性。

  • capacity :指定PV的容量;目前,Capacity仅支持存储容量设定,将来还应该可以指定IOPS和吞吐量(throughput)。
  • accessModes <[]string>:指定当前PV支持访问模式;存储系统支持存取能力大体可分为ReadWriteOnce(单路读写)、ReadOnlyMany(多路只读)和ReadWriteMany(多路读写)三种类型,某个特定的存储系统可能会支持其中的部分或全部的能力。
  • persistentVolumeReclaimPolicy :PV空间被释放时的处理机制(PV空间回收策略);可用类型仅为Retain(默认)(保留)、Recycle(回收:清空PVC数据)或Delete(删除pvc PV也删除)。目前,仅nfs和hostPath支持Recycle策略,也仅有部分存储系统支持Delete策略。
  • volumeMode :该PV的卷模型,用于指定此存储卷被格式化为文件系统使用还是直接使用裸格式的块设备;默认值为Filesystem,仅块设备接口的存储系统支持该功能。
  • storageClassName :当前PV所属的StorageClass资源的名称,指定的存储类需要事先存在;默认为空值,即不属于任何存储类。
  • mountOptions :挂载选项组成的列表,例如ro、soft和hard等。
  • nodeAffinity :节点亲和性,用于限制能够访问该PV的节点,进而会影响到使用与该PV关联的PVC的Pod的调度结果。

    定义PVC时,用户可通过访问模式(accessModes)、数据源(dataSource)、存储资源空间需求和限制(resources)、存储类、标签选择器、卷模型和卷名称等匹配标准来筛选集群上的PV资源,其中,resources和accessModes是最重的筛选标准。PVC的Spec字段的可嵌套字段有如下几个。

    • accessModes <[]string>:PVC的访问模式;它同样支持RWO、RWX和ROX三种模式;
    • dataSources :用于从指定的数据源恢复该PVC卷,它目前支持的数据源包括一个现在卷快照对象(snapshot.storage.k8s.io/VolumeSnapshot)、一个既有PVC对象(PersistentVolumeClaim)或一个既有的用于数据转存的自定义资源对象(resource/object);
    • resources :声明使用的存储空间的最小值(requests)和最大值(limits);目前,PVC的资源限定仅支持空间大小一个维度;
    • selector :筛选PV时额外使用的标签选择器(matchLabels)或匹配条件表达式(matchExpressions);
    • storageClassName :该PVC资源隶属的存储类资源名称;指定了存储类资源的PVC仅能在同一个存储类下筛选PV资源,否则,就只能从所有不具有存储类的PV中进行筛选;
    • volumeMode :卷模型,用于指定此卷可被用作文件系统还是裸格式的块设备;默认值为Filesystem;
    • volumeName :直接指定要绑定的PV资源的名称。
    • pv示例
      image.png

      PVC示例:
      image.png
      设置标签匹配的能进行绑定
      image.png

      pod使用PVC
      1099设置容器userID
      image.png

      25.4. StorageClass:模板

      StorageClass:模板, 简称SC;PV和PVC都可属于某个特定的SC;
      模拟为名称空间:一个PVC只能够在自己所处的SC内找PV;或者,一个不属于任何SC的PVC只能够在不属于任何SC的PV中进行筛选;
      创建PV的模板:可以将某个存储服务与SC关联起来,并且将该存储服务的管理接口提供给SC,从而让SC能够在存储服务上CRUD(Create、Read、Update和Delete)存储单元;
      因而,在同一个SC上声明PVC时,若无现存可匹配的PV,则SC能够调用管理接口直接创建出一个符合PVC声明的需求的PV来。这种PV的提供机制,就称为Dynamic Provision。

      StorageClass创建Ceph
      image.png

      26. configMap

      如何为容器化应用提供配置信息:
      启动容器时,直接向应用程序传递参数,args: []
      将定义好的配置文件焙进镜像之中;
      通过环境变量向容器传递配置数据:有个前提要求,应用得支持从环境变量加载配置信息;
      制作镜像时,使用entrypoint脚本来预处理变量,常见的做法就是使用非交互式编辑工具,将环境变量的值替换到应用的配置文件中;
      基于存储卷向容器传递配置文件;
      运行中的改变,需要由应用程序重载;

      ConfigMap,以k/v格式保存配置项的名称和配置数据;

      而后,由Pod中的容器以环境变量的方式从ConfigMap中加载特定的键的值;
      第二种方式,可以让Pod直接将ConfigMap以存储卷的形式进行附加,而由容器挂载至指定目录下,从而获取到完整的配置文件。

      示例:
      单个文件
      image.png
      整个目录为configMap
      image.png
      configMap变量形式
      image.png

      26.1. configMap变量形式示例

      true 非必选的值,当没有定义值时,不会报错
      false 没有定义会报错
      image.png

      26.2. configMap文件与变量形式 示例

      image.png
      image.png
      挂载仅需要的配置文件
      image.png

      26.3. configMap更新

      配置文件链接..data目录中,..data链接一个带有详细时间的目录,当confiMap更新
      ..data链接新的带有详细时间的目录,配置文件由于链接的..data目录,所以也会更新
      服务/应用是否会更新,取决于改服务是否会自动加载新配置
      image.png
      configMap跟更新后,..data链接的目录改变为一个新的带有详细时间的目录
      image.png

      27. secret加密

      ConfigMap的配置信息基本没有类别之分,但Secret有所不同,根据其用户存在类型的概念;
      docker-registry:专用于让kubelet启动Pod时从私有镜像仓库pull镜像时,首先认证到Registry时使用;
      tls:专门用于保存tls/ssl用到证书和配对儿的私钥;
      generic:余下的通用类型;可以存在子类型
      —type=”kubernetes.io/basic-auth”
      —type=”kubernetes.io/rbd”
      —type=”kubernetes.io/ssh-auth”
      另外,保存有专用于ServiceAccount的相关的token信息的Secret资源会使用资源注解来保存其使用场景。

          kind: Secret
      metadata:
             annotations:
               kubernetes.io/service-account.name: node-controller
               kubernetes.io/service-account.uid: b9f7e593-3e49-411c-87e2-dbd7ed9749c0
      

      资源的元数据:除了name, namespace之外,常用的还有labels, annotations;
      (1)annotation的名称遵循类似于labels的名称命名格式,但其数据长度不受限制;
      (2)它不能用于被标签选择器作为筛选条件;但常用于为那些仍处于Beta阶段的应用程序提供临时的配置接口;
      (3)管理命令:kubectl annotate TYPE/NAME KEY=VALUE, kubectl annotate TYPE/NAME KEY-
      TLS类型是一种独特的类型,在创建secret的命令行中,除了类型标识的不同之外,它还需要使用专用的选项—cert和—key。
      无论证书和私钥文件名是什么,它们会统一为:
      tls.crt
      tls.key

      Docker Registry类型,也是独特类型:
      kubectl create secret docker-registry my-secret —docker-server=DOCKER_REGISTRY_SERVER \
      —docker-username=DOCKER_USER —docker-password=DOCKER_PASSWORD —docker-email=DOCKER_EMAIL

      也能够从docker的认证文件中加载信息,这时使用—from-file选项;
      $HOME/.dockercfg, ~/.docker/config.json

      Secret资源,使用环境变量

      containers:
      - name: …
        image: …
        env:
        - name: <string>       # 变量名,其值来自于某Secret对象上的指定键的值;
          valueFrom:            # 键值引用; 
            secretKeyRef:       
              name: <string>    # 引用的Secret对象的名称,需要与该Pod位于同一名称空间;
              key: <string>     # 引用的Secret对象上的键,其值将传递给环境变量;
              optional: <boolean> # 是否为可选引用;
        envFrom:                 # 整体引用指定的Secret对象的全部键名和键值;
        - prefix: <string>     # 将所有键名引用为环境变量时统一添加的前缀;
      secretRef:        
        name: <string>     # 引用的Secret对象名称;
        optional: <boolean> # 是否为可选引用;
      

      27.1. generic类型

      示例
      image.png
      查看加密后的内容
      image.png
      image.png
      pod示例
      image.png

      27.2. TLS类型

      TLS类型是一种独特的类型,在创建secret的命令行中,除了类型标识的不同之外,它还需要使用专用的选项—cert和—key。
      无论证书和私钥文件名是什么,它们会统一为:
      tls.crt
      tls.key
      image.png
      pod示例
      image.png

      27.3. docker-registry类型

      Docker Registry类型,也是独特类型:
      kubectl create secret docker-registry my-secret —docker-server=DOCKER_REGISTRY_SERVER \
      —docker-username=DOCKER_USER —docker-password=DOCKER_PASSWORD —docker-email=DOCKER_EMAIL

      也能够从docker的认证文件中加载信息,这时使用--from-file选项;<br />    $HOME/.dockercfg, ~/.docker/config.json
      
      何时引用,以及如何引用<br />pod.spec.imagePullSecrets<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/1698198/1655113909791-a483e2e0-5569-4d6d-a8e0-0e17edfe834c.png#clientId=ucd8c8f72-624c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=60&id=u6a8113bd&margin=%5Bobject%20Object%5D&name=image.png&originHeight=60&originWidth=1588&originalType=binary&ratio=1&rotation=0&showTitle=false&size=87835&status=done&style=none&taskId=u4a1af3da-eff3-478a-913f-d61aad882fc&title=&width=1588)
      

      28. downwardAPI

      downwardAPI存储卷类型,从严格意义上来说,downwardAPI不是存储卷,它自身就存在,原因在于,它引用的是Pod自身的运行环境信息,这些信息在Pod启动手就存在。

      类似于ConfigMap或Secret资源,容器能够在环境变量中在valueFrom字段中嵌套fieldRef或resourceFieldRef字段来引用其所属Pod对象的元数据信息。不过,通常只有常量类型的属性才能够通过环境变量注入到容器中,毕竟,在进程启动完成后无法再向其告知变量值的变动,于是,环境变量也就不支持中途的更新操作。容器规范中可在环境变量配置中的valueFrom通过内嵌字段fieldRef引用的信息包括如下这些:
      metadata.name:Pod对象的名称;
      metadata.namespace:Pod对象隶属的名称空间;
      metadata.uid:Pod对象的UID;
      metadata.labels[‘‘]:Pod对象标签中的指定键的值,例如metadata.labels[‘mylabel’],仅Kubernetes 1.9及之后的版本才支持;
      metadata.annotations[‘‘]:Pod对象注解信息中的指定键的值,仅Kubernetes 1.9及之后的版本才支持。

      容器上的计算资源需求和资源限制相关的信息,以及临时存储资源需求和资源限制相关的信息可通过容器规范中的resourceFieldRef字段引用,相关字段包括requests.cpu、limits.cpu、requests.memory和limits.memory等。另外,可通过环境变量引用的信息有如下几个:
      status.podIP:Pod对象的IP地址
      spec.serviceAccountName:Pod对象使用的ServiceAccount资源名称
      spec.nodeName:节点名称
      status.hostIP:节点IP地址

      另外,还可以通过resourceFieldRef字段引用当前容器的资源请求及资源限额的定义,因此它们包括requests.cpu、requests.memory、requests.ephemeral-storage、limits.cpu、limits.memory和limits.ephemeral-storage这6项。

      28.1. 直接引用pod自身属性

      不需要单独定义,直接引用pod yanl中自身的属性信息
      # 示例
      image.png

      28.2. 使用volumes模式

      volume模式挂载到容器指定目录下
      image.png
      查看挂载目录下的信息
      image.png

      29. envsubst设置yaml中变量

      image.png
      image.png

      30. 认证授权和准入控制

      Authn
      Authz
      Admission:
      检验、变异,只发挥”写请求”上
      审计,独特的功能补全默认字段,检查用户提交的字段是否合规

      认证方式:<br />        X509数字证书认证;<br />        证书中的Subject中的<br />        CommonName, CN: 用户名;<br />        Orgnization, O:组名;
      

      引导令牌(Token):
      静态令牌:存储于API Server进程可直接加载到的文件中保存的令牌,该文件内容会由API Server缓存于内存中;
      静态密码:存储于API Server进程可直接加载到的文件中保存的账户和密码令牌,该文件内容会由API Server缓存于内存中;
      ServiceAccount令牌:
      OpenID Connect令牌:OIDC令牌, OAuth 2
      Webhook令牌
      代理认证

      授权方式:
      Node
      ABAC:Attribution,属性
      RBAC: Role-Based AC, 基于角色的访问控制
      Webhook

      准入控制器:
      LimitRanger
      ResourceQuota
      PSP: PodSecurityPolicy

      30.1. ServiceAccount

      认证:

      ServiceAccount令牌认证:<br />        K8S自动为每个Pod注入一个ServiceAccount,令牌,确保pod可以回溯到apiserver上查询pod自身相关信息
      
          在每个名称空间中,会自动存在(由ServiceAccount准入控制器负责)一个ServiceAccount,将被该空间下的每个Pod共享使用。
      
      认证令牌保存于该空间下的一个Secret对象中,该对象中共有三个信息:<br />        namespace<br />        ca.crt<br />        token
      

      每个名称空间都有一个ServiceAccount
      image.png
      在创建pod如果没指定ServiceAccount,ServiceAcount则默认是该名称空间下的ServiceAccount的default作为自己的ServiceAccount
      image.png

      创建serviceaccount认证到apiserver上,创建的每一个serviceaccount自动附加认证信息,认证到k8s上并代表可以做任何事
      认证自动生成,保存在secret中
      找到serviceaccount的token。serviceaccount名字,找到secret,在secret中找到token
      image.png

      secrets信息存储在pod中
      image.png

      apiVersion: v1  # ServiceAccount所属的API群组及版本
      kind: ServiceAccount  # 资源类型标识
      metadata:
        name <string>  # 资源名称
        namespace <string>  # ServiceAccount是名称空间级别的资源
      automountServiceAccountToken <boolean>  # 是否让Pod自动挂载API令牌
      secrets <[]Object>   # 以该SA运行的Pod所要使用的Secret对象组成的列表
        apiVersion <string>  # 引用的Secret对象所属的API群组及版本,可省略
        kind <string>  # 引用的资源的类型,这里是指Secret,可省略
        name <string>  # 引用的Secret对象的名称,通常仅给出该字段即可
        namespace <string>  # 引用的Secret对象所属的名称空间
        uid  <string>  # 引用的Secret对象的标识符;
      imagePullSecrets <[]Object> # 引用的用于下载Pod中容器镜像的Secret对象列表
        name <string>  # docker-registry类型的Secret资源的名称
      

      30.2. kubconfig 生成

      kubconfig
      image.png
      image.png
      kubeconfig配置文件:
      将用户名、认证信息等组织一起,便于认证到API Server上的认证信息文件;
      支持一个文件中保存m个集群的n个认证信息;

      静态密码文件:
      password,user,uid,”group1,group2,group3”

      为了核验用户的操作许可,成功通过身份认证后的操作请求还需要转交给授权插件进行许可权限检查,以确保其拥有执行相应的操作的许可。API Server主要支持使用四类内建的授权插件来定义用户的操作权限:

      • Node:基于Pod资源的目标调度节点来实现对kubelet的访问控制;
      • ABAC:Attribute-based access control,基于属性的访问控制;
      • RBAC:Role-based access control,基于角色的访问控制;
      • Webhook:基于http回调机制通过外部REST服务检查确认用户授权的访问控制。

      第一步,以客户端的身份,生成目标用户账号mason的私钥及证书签署请求,保存于用户家目录下的.certs目录中。
      1)生成私钥文件,注意其权限应该为600以阻止其他用户读取;
      ~$ mkdir $HOME/.certs
      ~$ (umask 077; openssl genrsa -out $HOME/.certs/mason.key 2048)
      2)创建证书签署请求,-subj选项中CN的值将被API Server识别为用户名,O的值将被识别为用户组;
      ~$ openssl req -new -key $HOME/.certs/mason.key \
      -out $HOME/.certs/mason.csr \
      -subj “/CN=mason/O=developers”

      第二步,以kubernetes-ca的身份签署ikubernetes的证书请求,这里直接读取相关的CSR文件,并将签署后的证书仍然保存于当前系统用户家目录下的.certs中。
      1)基于kubernetes-ca签署证书,并为其设置合理的生效时长,例如365天;
      ~$ sudo openssl x509 -req -days 365 -CA /etc/kubernetes/pki/ca.crt \
      -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial \
      -in $HOME/.certs/mason.csr -out $HOME/.certs/mason.crt
      Signature ok
      subject=CN = mason, O = developers
      Getting CA Private Key
      2)必要时,还可以验证生成的数字证书的相关信息(可选)。
      ~$ openssl x509 -in $HOME/.certs/mason.crt -text -noout

      第三步,将ikubernetes的身份凭据生成kubeconfig配置,这次选择将其保存于kubectl默认搜索路径指向的$HOME/.kube/config文件中。另外,因指向当前集群的配置项已经存在,它是位于clusters配置段中kubernetes,这里直接复用该集群定义。
      1)根据X509证书及私钥创建身份凭据,列表项名称同目标用户名;
      ~$ kubectl config set-credentials mason —embed-certs=true \
      —client-certificate=$HOME/.certs/mason.crt \
      —client-key=$HOME/.certs/mason.key
      User “mason” set.
      2)配置context,以mason的身份凭据访问已定义的kubernetes集群,该context的名称为mason@kubernetes;
      ~$ kubectl config set-context mason@kubernetes —cluster=kubernetes —user=mason
      Context “mason@kubernetes” created.
      3)将当前上下文切换为mason@kubernetes,或直接在kubectl命令上使用“—context= ‘mason@kubernetes’”临时以完成该用户的认证测试,下面的命令选择了以第二种方式进行,错误信息是提示权限错误,但mason用户已然可被API Server正确识别;
      ~$ kubectl get namespaces/default —context=’mason@kubernetes’
      Error from server (Forbidden): namespaces “default” is forbidden: User “mason” cannot get resource “namespaces” in API group “” in the namespace “default”
      以上,我们通过创建自定义的数字证书,实现了将mason用户认证到API Server,并将该用户的身份凭据保存于至kubeconfig文件中。

      30.3. RBAC

      授权谁能干什么,没有授权不能干什么

      授权:
      DAC、MAC、RBAC、ABAC
      RBAC:Role-Based Access Control
      Role —> Verbs —> Objects
      ClusterRole —> Verbs —> Objects
      Subject —> RoleBinding —> Roles #与RoleBinding 和Roles 绑定起来
      Subject —> ClusterRoleBinding —> ClusterRoles
      Subject —> RoleBinding —> ClusterRoles

      API Server: RESTful风格的http/https服务

      HTTP METHOD:
      GET, POST, PUT, DELETE, PATCH, …

      Action

      Object:资源对象

      什么Action能施加到哪些对象上;

      GET Pods

      DELETE Namespaces

      四个资源类型:
      Role: 角色,名称空间级别;
      ClusterRole:集群角色,全局级别;

      RoleBinding:"角色绑定",指是将用户与角色关联起来,意味着,用户仅得到了特定名称空间下的Role的权限,作用范围也限于该名称空间;<br />    ClusterRoleBinding:集群角色绑定,让用户扮演指定的集群角色;意味着,用户得到了是集群级别的权限,作用范围也是集群级别;
      
      User --> Rolebindig --> ClusterRole(用户绑定到角色,角色绑定到集群角色):权限降级,ClusterRole,用户得到的权限仅是ClusterRole的权限在Rolebinding所属的名称空间上的一个子集;<br />    User是集群级别,k8s不管理用户User授权角色后变成名称空间级别
      

      能接受施加Verb的目标有三类:
      resources:资源类型,该类型下的所有对象都是目标, pods;所有pod
      resourceNames:特定的对象个体,pods/mypod;只能对特定pod操作
      nonResourceURLs:非资源型的URL,/status,

      对应权限
      Verbs:
      create、get、list、delete、patch、update
      User 与 default/myrole

      admin:名称空间级别资源的管理员权限
      cluster-admin:集群管理员,若有账号绑定了,也会具有该权限
      image.png

      给每一个名称空间一个管理员,在每一个名称空间创建一个ServiceAccount使用Rolebindig 绑定ClusterRole admin

      31. RBAC

      31.1. 在指定namespace创建账户

      kubectl create serviceaccount laomao -n linux39

      31.2. 创建role规则

      创建角色的权限规则角色linux39-role
      image.png

      31.3. 将规则与账户进行绑定

      将角色的规则与用户绑定用户laomao
      image.png

      31.4. 获取token名称获取用户token

      kubectl get secret -n linux39 | grep laomao
      laomao-token-cd4b9 kubernetes.io/service-account-token 3 5m37s

      获取用户token
      kubectl describe secrets laomao-token-bzctt -n linux39
      image.png

      31.5. 使用base加密获取用户token

      # kubectl get secret laomao-token-cd4b9 -o jsonpath={.data.token} -n linux39 |base64 -d
      eyJhbGciOiJSUzI1NiIsImtpZCI6IkR5eEg0ckg0VFlTYkdEcUtTUzFad3R6OEJzOVJHdFRsZ0tGTGVUUFJiTncifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJsaW51eDM5Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Imxhb21hby10b2tlbi1jZDRiOSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJsYW9tYW8iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJhNTQyZTlkYy1mMDYyLTQwNmMtOWUwZi05NzA5MjQ2MWNlOTYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6bGludXgzOTpsYW9tYW8ifQ.BK9bv8gqDxeN_ilJiDBm3COf7t2ybE0QM1M56JnGmEnzRRMJCs6uzCds9b9bB-XgVvJwqNi6W8vOj6r2iW4rMdqS9pbJrWOSl9mR756wlMSbLdAUsgHB_ywzy0L20ew13590mor_BPAvTOF5We-_2MwswNgQtUaEU6Yixpg-73Cq1UyZaCILi0h_oLqusEFwxkkunI4dmsUF3QkJ96d_TOerizizWwR716tUm_jGb05izobUjghoL526ngIdzYtND-QQM4_039vzC9WW-yobeNypM-BQADqfvD4g6g_tKiXe61SuegOyobQYQ7jom-dcqVbOU5uVDK_oHg6frHYaLQ
      

      31.6. 登录dashboard测试

      31.7. 基于kube-config文件登录

      2.1:创建csr文件:
      # cat laomao-csr.json

      {
        "CN": "jack",
        "hosts": [],
        "key": {
          "algo": "rsa",
          "size": 2048
        },
        "names": [
          {
            "C": "CN",
            "ST": "BeiJing",
            "L": "BeiJing",
            "O": "k8s",
            "OU": "System"
          }
        ]
      }
      

      2.2:签发证书:

      # cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem  -ca-key=/etc/kubernetes/ssl/ca-key.pem -config=/etc/kubernetes/ssl/ca-config.json -profile=kubernetes laomao-csr.json | cfssljson -bare  laomao
      
      # ls laomao*
      laomao.csr  laomao-csr.json  laomao-key.pem  laomao.pem
      

      2.3:生成普通用户kubeconfig文件:

      # kubectl config set-cluster cluster1 --certificate-authority=/etc/kubernetes/ssl/ca.pem --embed-certs=true --server=https://172.31.7.188:6443 --kubeconfig=laomao.kubeconfig
      

      2.4:设置客户端认证参数:

      # cp *.pem /etc/kubernetes/ssl/
      # kubectl config set-credentials laomao \
      --client-certificate=/etc/kubernetes/ssl/laomao.pem \
      --client-key=/etc/kubernetes/ssl/laomao-key.pem \
      --embed-certs=true \
      --kubeconfig=laomao.kubeconfig
      

      2.5:设置上下文参数添加认证信息

      kubectl config set-context cluster1 \
      --cluster=cluster1 \
      --user=laomao \
      --namespace=linux39 \
      --kubeconfig=laomao.kubeconfig
      

      2.6: 设置默认上下文添加上下文

      kubectl config use-context cluster1 --kubeconfig=laomao.kubeconfig
      

      2.7:获取token:
      # kubectl describe secrets laomao-token-cd4b9 -n linux39

      Name:         laomao-token-cd4b9
      Namespace:    linux39
      Labels:       <none>
      Annotations:  kubernetes.io/service-account.name: laomao
                    kubernetes.io/service-account.uid: a542e9dc-f062-406c-9e0f-97092461ce96
      
      Type:  kubernetes.io/service-account-token
      
      Data
      ====
      ca.crt:     1350 bytes
      namespace:  7 bytes
      token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IkR5eEg0ckg0VFlTYkdEcUtTUzFad3R6OEJzOVJHdFRsZ0tGTGVUUFJiTncifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJsaW51eDM5Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Imxhb21hby10b2tlbi1jZDRiOSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJsYW9tYW8iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJhNTQyZTlkYy1mMDYyLTQwNmMtOWUwZi05NzA5MjQ2MWNlOTYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6bGludXgzOTpsYW9tYW8ifQ.BK9bv8gqDxeN_ilJiDBm3COf7t2ybE0QM1M56JnGmEnzRRMJCs6uzCds9b9bB-XgVvJwqNi6W8vOj6r2iW4rMdqS9pbJrWOSl9mR756wlMSbLdAUsgHB_ywzy0L20ew13590mor_BPAvTOF5We-_2MwswNgQtUaEU6Yixpg-73Cq1UyZaCILi0h_oLqusEFwxkkunI4dmsUF3QkJ96d_TOerizizWwR716tUm_jGb05izobUjghoL526ngIdzYtND-QQM4_039vzC9WW-yobeNypM-BQADqfvD4g6g_tKiXe61SuegOyobQYQ7jom-dcqVbOU5uVDK_oHg6frHYaLQ
      

      2.8:将token写入用户kube-config文件:
      image.png

      3.9:dashboard登录测试:
      https://172.31.7.201:30002/#/pod?namespace=linux39

      32. 调度策略及应用

      32.1. 默认调度策略选择过程

      image.png
      image.png
      预选
      排除剔除不对应的,排除不符合运行要求的节点
      image.png
      image.png
      image.png

      对匹配节点打分,选出得分高运行pod
      image.png

      32.2. 自己配置调度策略

      配置调度器:

      apiVersion: kubescheduler.config.k8s.io/v1alpha2 # v1alpha2版本
      kind: KubeSchedulerConfiguration
      AlgorithmSource:  # 指定调度算法配置源,v1alpha2版本起该配置进入废弃阶段
        Policy:  # 基于调度策略的调度算法配置源
          File: 文件格式的调度策略
            Path <string>: 调度策略文件policy.cfg的位置
          ConfigMap:   # configmap格式的调度策略
            Namespace <string>  # 调度策略configmap资源隶属的名称空间
            Name <string>  # configmap资源的名称
        Provider <string>  # 配置使用的调度算法的名称,例如DefaultProvider
      LeaderElection: {}  # 多kube-scheduler实例并在时使用的领导选举算法
      ClientConnection: {}  # 与API Server通信时提供给代理服务器的配置信息
      HealthzBindAddress <string>  # 响应健康状态检测的服务器监听的地址和端口
      MetricsBindAddress <string>  # 响应指标抓取请求的服务器监听地址和端口
      DisablePreemption <bool>  # 是否禁用抢占模式,false表示不禁用
      PercentageOfNodesToScore <int32>  # 需要过滤出的可用节点百分比
      BindTimeoutSeconds  <int64>  # 绑定操作的超时时长,必须使用非负数
      PodInitialBackoffSeconds  <int64>  # 不可调度Pod的初始补偿时长,默认值为1
      PodMaxBackoffSeconds <int64>  # 不可调度Pod的最大补偿时长,默认为10
      Profiles <[]string>  # 加载的KubeSchedulerProfile配置列表,v1alpha2支持多个
      Extenders <[]Extender>  # 加载的Extender列表
      
      apiVersion: kubescheduler.config.k8s.io/v1beta1
      kind: KubeSchedulerConfiguration
      clientConnection:
        kubeconfig: "/etc/kubernetes/scheduler.conf"
      profiles:
      - schedulerName: default-scheduler
      - schedulerName: demo-scheduler
        plugins:
          filter:
            disabled:
            - name: NodeUnschedulable
          score:
            disabled:
            - name: NodeResourcesBalancedAllocation
              weight: 1
            - name: NodeResourcesLeastAllocated
              weight: 1
            enabled:
            - name: NodeResourcesMostAllocated
              weight: 5
      

      /etc/kubernetes/manifests/kube-scheduler.yaml

      spec:
        containers:
        - command:
          - kube-scheduler
          - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
          - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
          - --config=/etc/kubernetes/scheduler/kubeschedconf-v1alpha2-demo.yaml
      
      
          volumeMounts:
          - mountPath: /etc/kubernetes/scheduler.conf
            name: kubeconfig
            readOnly: true
          - mountPath: /etc/kubernetes/scheduler
            name: schedconf
            readOnly: true
        hostNetwork: true
        priorityClassName: system-node-critical
        volumes:
        - hostPath:
            path: /etc/kubernetes/scheduler.conf
            type: FileOrCreate
          name: kubeconfig
        - hostPath:
            path: /etc/kubernetes/scheduler
            type: DirectoryOrCreate
          name: schedconf
      

      32.3. Kubernetes的高级调度功能

      节点亲和调度;
      Pod亲和调度;
      节点污点和Pod容忍度
      拓扑分布式调度

      节点亲和:
      pods.spec:

      nodeName:选择固定的node节点指定<br />    nodeSelector:节点选择器<br />    affinity.nodeAffinity:节和亲和,对节点更有倾向性<br />    亲和(尽可能运行该节点),反亲和(尽可能不运行)<br />    硬亲和(必须满足的亲和关系),软亲和(尽量满足的亲和关系满足条件节点存在运行该节点不存在选择其他的)<br />    亲和:可以根据参照pod标签进行选择
      

      Pod亲和:Pod彼此间运行于同一位置的倾向性;
      什么是同一位置:同一节点、机架、row、room(同一机房) 认为是同一位置

      节点污点和Pod容忍度
      拓扑分布式调度

      • requiredDuringSchedulingIgnoredDuringExecution
        表示pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。其中IgnoreDuringExecution表示pod部署之后运行的时候,如果节点标签发生了变化,不再满足pod指定的条件,pod也会继续运行。
      • requiredDuringSchedulingRequiredDuringExecution
        表示pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。其中RequiredDuringExecution表示pod部署之后运行的时候,如果节点标签发生了变化,不再满足pod指定的条件,则重新选择符合要求的节点。
      • preferredDuringSchedulingIgnoredDuringExecution
        表示优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署。
      • preferredDuringSchedulingRequiredDuringExecution
        表示优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署。其中RequiredDuringExecution表示如果后面节点标签发生了变化,满足了条件,则重新调度到满足条件的节点。

      pod硬亲和实例
      image.png

      pod软亲和
      image.png

      反亲和
      image.png

      32.4. 污点容忍度

      节点污点和Pod容忍度
      拓扑分布式调度

      效用标识主要由以下3种类型。
       NoSchedule:不能容忍此污点的Pod对象不可调度至当前节点,属于强制型约束关系,但添加污点对节点上现存的Pod对象不产生影响。
       PreferNoSchedule:NoSchedule的柔性约束版本,即调度器尽量确保不会将那些不能容忍此污点的Pod对象调度至当前节点,除非不存在其他任何能够容忍此污点的节点可用;添加该类效用的污点同样对节点上现存的Pod对象不产生影响。
       NoExecute:不能容忍此污点的新Pod对象不可调度至当前节点,属于强制型约束关系,而且节点上现存的Pod对象因节点污点变动或Pod容忍度变动而不再满足匹配条件时,Pod对象将会被驱逐。

      此外,在Pod对象上定义容忍度时,它支持两种操作符,一种是等值比较,表示容忍度与污点必须在key、value和effect三者之上完全匹配,另一种是存在性判断(Exists),表示二者的key和effect必须完全匹配,而容忍度中的value字段要使用空值。
      一个节点可以配置使用多个污点,而一个Pod对象也可以有多个容忍度,将一个Pod对象的容忍度套用到特定节点的污点之上进行匹配度检测时,时将遵循如下逻辑:
      1)首先处理每个有着与之匹配的容忍度的污点;
      2)对于不能匹配到容忍度的所有污点,若存在一个污点使用了NoSchedule效用标识,则拒绝调度当前Pod至该节点;
      3)对于不能匹配到容忍度的所有污点,若都不具有NoSchedule效用标识,但至少有一个污点使用了PreferNoScheduler效用标准,则调度器会尽量避免将当前Pod对象调度至该节点。
      4)如果至少有一个不能匹配容忍度的污点使用了NoExecute效用标识,节点将立即驱逐当前Pod对象,或者不允许该Pod调度至给定的节点;而且,即便容忍度可以匹配到使用了NoExecute效用标识的污点,若在Pod上定义容忍度时同时使用tolerationSeconds属性定义了容忍时限,则在超出时限后当前脚Pod也将会被节点所驱逐。

      Kubernetes自1.6起支持使用污点自动标识问题节点,它通过节点控制器在特定条件下自动为节点添加污点信息实现。它们都使用NoExecute效用标识,因此非能容忍此类污点的现在Pod对象也会遭到驱逐。目前,内建使用的此类污点有如下几个。
       node.kubernetes.io/not-ready:节点进入NotReady状态时被自动添加的污点。
       node.alpha.kubernetes.io/unreachable:节点进入NotReachable状态时被自动添加的污点。
       node.kubernetes.io/out-of-disk:节点进入OutOfDisk状态时被自动添加的污点。
       node.kubernetes.io/memory-pressure:节点内存资源面临压力。
       node.kubernetes.io/disk-pressure:节点磁盘资源面临压力。
       node.kubernetes.io/network-unavailable:节点网络不可用。
       node.cloudprovider.kubernetes.io/uninitialized:kubelet由外部的云环境程序启动时,它自动为节点添加此污点,待到云控制器管理器中的控制器初始化此节点时再将其删除。
      不过,Kubernetes的核心组件通常都要容忍此类的污点,以确保其相应的DaemonSet控制器能够无视此类污点于节点上部署相应的关键Pod对象,例如kube-proxy或kube-flannel等。

      示例
      image.png

      32.5. 拓扑分布式调度

      Pod资源规范中的拓扑分布约束嵌套定义在.spec.topologySpreadConstraints字段中,它用来指示调度器如何根据集群中现有的Pod放置待调度的该Pod规范的实例。
       topologyKey :拓扑键,用来划分拓扑结构的节点标签,在指定的键上具有相同值的节点归属为同一拓扑;必选字段。
       labelSelector :Pod标签选择器,用于定义该Pod需要针对哪类Pod对象的位置来确定自身可放置的位置。
       maxSkew :允许Pod分布不均匀的最大程度,也就是可接受的当前拓扑中由labelSelector匹配到的Pod数量与所有拓扑中匹配到的最少Pod数量的最大差值,可简单用公式表示为max(count(current_topo(matched_pods))-min(topo(matched_pods))),其中的topo是表示拓扑关系伪函数名称。
       whenUnsatisfiable :拓扑无法满足maxSkew时采取的调度策略,默认值DoNotSchedule是一种强制约束,即不予调度至该区域,而另一可用值ScheduleAnyway则是柔性约束,无法满足约束关系时仍可将Pod放入该拓扑中。

      32.6. pod优先级调度

      PriorityClass

      apiVersion: scheduling.k8s.io/v1 # 资源隶属的API群组及版本
      kind: PriorityClass # 资源类别标识符
      metadata:
      name # 资源名称
      value # 优先级,必选字段
      description # 该优先级描述信息
      globalDefault # 是否为全局默认优先级
      preemptionPolicy # 抢占策略,Never为禁用,默认为PreemptLowerPriority允许,资源不足时抢占优先级低的pod,

      33. 扩展k8s Api

      k8s Api扩展源码基础上二开

      开发独立的api server通过扩展点扩展

      使用CRD

      apiVersion: apiextensions.k8s.io/v1  # API群组和版本
      kind: CustomResourceDefinition  # 资源类别
      metadata:
        name <string>  # 资源名称
      spec:
          conversion <Object>  # 定义不同版本间的格式转换方式
             trategy <string>  # 不同版本间的自定义资源转换策略,有None和Webhook两种取值
             webhook <Object>  # 如何调用用于进行格式转换的webhook
          group <string>  # 资源所属的API群组
          names <Object>  # 自定义资源的类型,即该CRD创建资源规范时使用的kind
            categories  <[]string>  # 资源所属的类别编目,例如”kubectl get all”中的all
            kind <string>  # kind名称,必选字段
            listKind <string>  # 资源列表名称,默认为"`kind`List"
            plural <string>  # 复数,用于API路径`/apis/<group>/<version>/.../<plural>`
            shortNames <[]string>  # 该资源的kind的缩写格式
            singular <string>  # 资源kind的单数形式,必须使用全小写字母,默认为小写的kind名称
          preserveUnknownFields <boolean>  # 预留的非知名字段,kind等都是知名的预留字段
          scope <string>  # 作用域,可用值为Cluster和Namespaced
          versions <[]Object>  # 版本号定义
            additionalPrinterColumns <[]Object>  # 需要返回的额外信息
            name <string>  # 形如vM[alphaN|betaN]格式的版本名称,例如v1或v1alpha2等
            schema <Object>  # 该资源的数据格式(schema)定义,必选字段
              openAPIV3Schema  <Object>  # 用于校验字段的schema对象,格式请参考相关手册
            served <boolean>  # 是否允许通过RESTful API调度该版本,必选字段
            storage <boolean>  # 将自定义资源存储于etcd中时是不是使用该版本
            subresources <Object>  # 子资源定义
              scale <Object>  # 启用scale子资源,通过autoscaling/v1.Scale发送负荷
              status <map[string]>   # 启用status子资源,为资源生成/status端点
      

      目前,扩展Kubernetes API的常用方式有3种:使用CRD(CustomResourceDefinitions)自定义资源类型、开发自定义的API Server并聚合至主API Server,以及定制扩展API Server源码。这其中,CRD最为易用但限制颇多,自定义API Server更富于弹性但代码工作量偏大,而仅在必须添加新的核心类型才能确保专用的Kubernetes集群功能正常,才应该定制系统源码。

      34. ingress

      Ingress:集群外部注入集群内部的流量
      Egress:集群内部流出到集群外部的流量

      集群外部注入集群内部的流量方法:
      Service NodePort
      Service externalIP

      Service的代理模式:无法实现SSL会话的卸载因为工作在传输层
      iptables
      IPVS
      Service从集群外部引入流量缺陷:
      在集群到处打洞开端口而且不具有连续性,无法管理

      Ingress:标准的资源类型
      Ingress Controller:Ingress控制器七层代理http/TCP代理服务

      正常情况下ingress不会吧流量转给service再转给pod,
      service将pod归组,ingress需要借助于service识别pod,知道了pod有哪些,ingress进行代理,流量不再由service调度,直接由ingress调度

      v1beta1 Ingress资源规范

      apiVersion: extensions/v1beta1   # 资源所属的API群组和版本
      kind: Ingress   # 资源类型标识符
      metadata:  # 元数据
        name <string>  # 资源名称
        annotations:   # 资源注解,v1beta1使用下面的注解来指定要解析该资源的控制器类型
          kubernetes.io/ingress.class: <string>    # 适配的Ingress控制器类别
        namespace <string>  # 名称空间
      spec:
        rules <[]Object>   # Ingress规则列表;
        - host <string>   # 虚拟主机的FQDN,支持“*”前缀通配,不支持IP,不支持指定端口
          http <Object>
            paths <[]Object>   # 虚拟主机PATH定义的列表,由path和backend组成
            - path <string>   # 流量匹配的HTTP PATH,必须以/开头,URL匹配的进入到该service
              pathType <string>  # 匹配机制,支持Exact、Prefix和ImplementationSpecific
              backend <Object>   # 匹配到的流量转发到的目标后端
                resource <Object>   # 引用的同一名称空间下的资源,与下面两个字段互斥
                serviceName <string>   # 引用的Service资源的名称
                servicePort <string>   # Service用于提供服务的端口
        tls <[]Object>   # TLS配置,用于指定上rules中定义的哪些host需要工作HTTPS模式
        - hosts <[]string>   # 使用同一组证书的主机名称列表
          secretName <string>   # 保存于数字证书和私钥信息的secret资源名称
        backend <Object>   # 默认backend的定义,可嵌套字段及使用格式跟rules字段中的相同
        ingressClassName  <string>   # ingress类名称,用于指定适配的控制器
      

      v1 Ingress资源规范

      apiVersion: networking.k8s.io/v1   # 资源所属的API群组和版本
      kind: Ingress   # 资源类型标识符
      metadata:  # 元数据
        name <string>  # 资源名称
        annotations:   # 资源注解,v1beta1使用下面的注解来指定要解析该资源的控制器类型
          kubernetes.io/ingress.class: <string>    # 适配的Ingress控制器类别
        namespace <string>  # 名称空间
      spec:
        rules <[]Object>   # Ingress规则列表
        - host <string>   # 虚拟主机的FQDN,支持“*”前缀通配,不支持IP,不支持指定端口
          http <Object>
            paths <[]Object>   # 虚拟主机PATH定义的列表,由path和backend组成
            - path <string>   # 流量匹配的HTTP PATH,必须以/开头
              pathType <string>  # 支持Exact(精确匹配)、Prefix(前置匹配)和ImplementationSpecific,必选
              backend <Object>   # 匹配到的流量转发到的目标后端
                resource <Object>   # 引用的同一名称空间下的资源,与下面两个字段互斥
                service <object>  # 关联的后端Service对象
                  name <string>  # 后端Service的名称
                  port <object>  # 后端Service上的端口对象
                    name <string>   # 端口名称
                    number <integer>   # 端口号
        tls <[]Object>   # TLS配置,用于指定上rules中定义的哪些host需要工作HTTPS模式
        - hosts <[]string>   # 使用同一组证书的主机名称列表
          secretName <string>   # 保存于数字证书和私钥信息的secret资源名称
        backend <Object>   # 默认backend的定义,可嵌套字段及使用格式跟rules字段中的相同
        ingressClassName  <string>   # ingress类名称,用于指定适配的控制器
      

      ingres-nginx示例 v1beta1
      如果不使用www.ik8s.io域名访问无法访问404
      image.png
      ingres-nginx示例 v1
      image.png

      34.1. ingress-nginx https

      scretName secret类型名称
      image.png
      创建需要k8s secret 加密类型资源
      image.png

      34.2. ingress dashboard

      image.png

      32.3 ingres nginx访问认证

      生成secret资源
      image.png
      image.png

      35. contour envoy

      35.1. HTTPProxy

      image.png
      根据访问方式进行调度
      image.png
      流量权重
      image.png
      HTTPProxy服务弹性

      spec:
        routes <[]Route> 
          timeoutPolicy <TimeoutPolicy>   # 超时策略
            response <String>   # 等待服务器响应报文的超时时长
            idle <String>   # 超时后,Envoy维持与客户端之间连接的空闲时长
          retryPolicy <RetryPolicy>   # 重试策略
            count <Int64>   # 重试的次数,默认为1
            perTryTimeout <String>   # 每次重试的超时时长
          healthCheckPolicy <HTTPHealthCheckPolicy>   # 主动健康状态检测
            path <String>   # 检测针对的路径(HTTP端点)
            host <String>   # 检测时请求的虚拟主机
            intervalSeconds <Int64>   # 时间间隔,即检测频度,默认为5秒
            timeoutSeconds <Int64>   # 超时时长,默认为2秒
            unhealthyThresholdCount <Int64>   # 判定为非健康状态的阈值,即连续错误次数
            healthyThresholdCount <Int64>   # 判定为健康状态的阈值
      

      36. yaml

      apiVersion: v1     #必选,版本号,例如v1
      kind: Pod         #必选,资源类型,例如 Pod
      metadata:         #必选,元数据
        name: string     #必选,Pod名称
        namespace: string  #Pod所属的命名空间,默认为"default"
        labels:           #自定义标签列表
          - name: string                 
      spec:  #必选,Pod中容器的详细定义
        containers:  #必选,Pod中容器列表
        - name: string   #必选,容器名称
          image: string  #必选,容器的镜像名称
          imagePullPolicy: [ Always|Never|IfNotPresent ]  #获取镜像的策略 
          command: [string]   #容器的启动命令列表,如不指定,使用打包时使用的启动命令
          args: [string]      #容器的启动命令参数列表
          workingDir: string  #容器的工作目录
          volumeMounts:       #挂载到容器内部的存储卷配置
          - name: string      #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
            mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符
            readOnly: boolean #是否为只读模式
          ports: #需要暴露的端口库号列表
          - name: string        #端口的名称
            containerPort: int  #容器需要监听的端口号
            hostPort: int       #容器所在主机需要监听的端口号,默认与Container相同
            protocol: string    #端口协议,支持TCP和UDP,默认TCP
          env:   #容器运行前需设置的环境变量列表
          - name: string  #环境变量名称
            value: string #环境变量的值
          resources: #资源限制和请求的设置
            limits:  #资源限制的设置
              cpu: string     #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
              memory: string  #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
            requests: #资源请求的设置
              cpu: string    #Cpu请求,容器启动的初始可用数量
              memory: string #内存请求,容器启动的初始可用数量
          lifecycle: #生命周期钩子
      postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启
      preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止
          livenessProbe:  #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器
            exec:         #对Pod容器内检查方式设置为exec方式
              command: [string]  #exec方式需要制定的命令或脚本
            httpGet:       #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
              path: string
              port: number
              host: string
              scheme: string
              HttpHeaders:
              - name: string
                value: string
            tcpSocket:     #对Pod内个容器健康检查方式设置为tcpSocket方式
               port: number
             initialDelaySeconds: 0       #容器启动完成后首次探测的时间,单位为秒
             timeoutSeconds: 0          #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
             periodSeconds: 0           #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
             successThreshold: 0
             failureThreshold: 0
             securityContext:
               privileged: false
        restartPolicy: [Always | Never | OnFailure]  #Pod的重启策略
        nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上
        nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上
        imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
        - name: string
        hostNetwork: false   #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
        volumes:   #在该pod上定义共享存储卷列表
        - name: string    #共享存储卷名称 (volumes类型有很多种)
          emptyDir: {}       #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
          hostPath: string   #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
            path: string                #Pod所在宿主机的目录,将被用于同期中mount的目录
          secret:          #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部
            scretname: string  
            items:     
            - key: string
              path: string
          configMap:         #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
            name: string
            items:
            - key: string
              path: string
      

      37. Prometheus

      image.png
      Prometheus的时序数据库默认保存时长有时限(好像是一个月),如果想要保存更久的时间,需要使用其他时序数据库InfluxDB
      image.png
      image.png

      37.1. 组件介绍

      image.png
      image.png

      37.2. 数据模型

      image.png

      37.3. 指标类型

      image.png

      37.4. 作业(job)和实例(Instance)

      Instance:接入的地址:端口
      job:所属jobimage.png
      image.png
      image.png

      37.5. Prometheus配置

      image.png
      image.png

      37.6. 动态发现节点服务发现

      target
      image.png

      37.7. 指标抓取的生命周期

      image.png

      37.8. 可集成的服务发现机制

      image.png

      37.8.1. 基于文件的服务发现

      Prometheus持续的监控着该文件,每隔一段时间当检测的到文件修改,会重载配置,就不需要重启Prometheus
      image.png
      image.png

      37.8.2. 基于DNS的服务发现

      对nds域名进行持续检测,
      依赖于DNS的SRV资源记录
      image.png

      37.8.3. 基于kubernetes API的服务发现

      基于kubernetes API的服务发现,将api server中node、service、Endpoint、Pod、Ingress等资源类型下相应的资源对象视作target

      使用DaemonSet控制部署node-exporter发现各节点,node-exporter比kubelet监控更加丰富
      image.png
      image.png
      image.png
      image.png
      image.png
      image.png
      image.png
      image.png
      image.png
      image.png
      image.png
      image.png

      37.9. 对target重新打标

      image.png
      定义在relabel_config中
      image.png
      image.png
      配置示例
      image.png

      37.10. 样本数据格式

      image.png

      37.11. promQL的数据类型

      image.png

      37.12. 向量

      37.12.1. 时间序列选择器

      即时向量选择器:一段时间范围内
      范围向量选择器:时间序列范围内的数据样本
      image.png

      37.12.2. 向量表达式使用要点

      image.png

      37.13. alterManager

      37.13.1. alertmanager去重、分组、抑制、静默、路由

      image.png

      37.13.2. alertmanager配置

      Prometheus配置alertmanager
      image.png
      alertmanager配置邮件
      image.png
      image.png

      37.13.3. 告警规则配置

      Prometheus指向alertmanager,Prometheus定义好告警规则
      image.png
      image.png

      37.14. alert告警路由

      image.png
      image.png
      image.png

      37.15. Prometheus监控kubernetes

      配置k8s的toke和ca证书
      image.png
      从k8s API获取指标数据
      https://kubernetes.default.svc:443/api/v1/nodes/node01/proxy/metrics
      image.png
      对pod抓取
      pod
      prometheus.io/scrape: true/false

      __meta_kubernetes_pod_annotation_prometheus_io_scrape = true|false

      __meta_kubernetes_pod_annotation_prometheus_io_path = /metrics

      __meta_kubernetes_pod_annotation_prometheus_io_port = 80
      http://10.244.1.6:80/metrics

      38. ELK

      image.png
      日志收集:
      logstash:java ruby语言体量非常大
      filebeat:较小的内存就能完成,轻巧便捷、适配能力弱
      beats:较小的内存就能完成,轻巧便捷、适配能力弱

      filebeat、beats —> logstash —> ElasticSearch
      filebeat、beats数据发送到logstash,logstash利用自己的转换功能,将信息输出到ElasticSearch
      上面这种结构弊端:
      如果日志量请求非常大,一个logstash可能难以完成所有的转换,导致大量的阻塞和数据请求被丢弃
      解决方案:
      filebeat 到logstash中增加redis、kafka,logstash从kafak读取数据,数据来不及处理,放kafka中缓冲一会,在数据低估期间逐渐处理完成

      38.1. NoSQL存储系统基础与ElasticSearch

      image.png

      38.1.1. ElasticSearch分片

      ElasticSearch把logs index索引,切成多个分片(shard),每一个分片就是一个独立而完整的索引,
      正常是一个完整数据,把数据集组织为多个分片,而每个分片都是一个完整的索引,每一个索引都有一个节点来存储和使用。
      默认分成5个片(shard)

      分片的主从:
      Primary Shard 主分片
      Replicas Shard 副本分片

      38.1.2. ElasticSearch端口

      9300 Cluster Peer集群内部通信
      9200 Client API 客户端连接

      38.2. ElasticSearch index内部结构

      index:Database(独立数据库存很多类型的数据)
      Type:Table 把数据分到不同的Type中
      Document:Row 数据存放

      38.3. ES搜索引擎

      image.png
      image.png

      38.4. ES状态接口获取ES集群状态

      获取ElasticSearch集群状态信息
      image.png
      status:red有个索引的主分片副分片异常,yellow有副本残缺
      number_of_nodes:集群节点数量
      number_of_data_nodes:集群数据节点数量
      active_primary_shards:活动的主分片数量
      active_shards:活动的分片数量
      relocating_shars:迁移分片数量
      initializing_shards:正在初始化分片,一般是刚创建的分片
      unassigned_shards:已经在集群中的分片,但在集群中又找不到
      delayed_unassigned_shards:延迟未分配的分片
      number_of_pending_tasks:处于挂起状态的任务数
      number_of_in_flight_fetch:处于快速存取的

      单个节点信息
      image.png
      还包括了jvm数据信息
      image.png
      集群状态信息
      image.png
      获取集群数据index信息
      image.png
      每个索引状态信息
      image.png
      汇总出来的所有索引的信息,和每个索引的信息
      image.png

      38.5. logstash

      grok插件
      能把客户端送了的信息,所有的字段,基于内建的模式做文档化
      文档化完成后删除message,自动完成匹配后给每个字段加上key
      image.png
      rename
      修改字段名称
      image.png
      geoip
      基于mmdb的数据库,识别客户端的ip属于哪个地区,保存到geoip字段中
      image.png
      修改key的名称
      image.png
      image.png
      将message的内容,自动完成匹配后给每个字段加上key
      image.png
      date match 修改时间的格式
      rename 修改key的名字修改字段名字
      image.png
      geopip mmdb
      geopip找到存有ip地址的字段—>clientip,将ip地址抽取出来转换成地理位置信息,将转换后的结构存放的geoip当中
      image.png
      geoip结果
      image.png

      38.6. nginx日志json格式

      image.png

      38.7. ElasticSearch节点类型节点作用

      image.png

      38.8. ES的重要配置参数

      gateway.recover_after_nodes
      集群中的节点至少恢复了3个,才开始数据恢复,否则不启动数据恢复,只是要等待其他节点启动
      gateway.recover_after_time
      等待超时时间
      gateway.expected_nodes
      期望节点数量
      image.png

      39. k8s部署ELK Fluent-bit

      架构模式
      image.png
      image.png

      39.1. Fluent-bit数据管道

      input:指定的文件进行收集
      parser:做分析
      Filter:过滤、移除不需要的项
      output:输出
      image.png

      39.2. Fluent-bit配置

      # kind -- DaemonSet or Deployment
      kind: DaemonSet
      
      image:
        repository: fluent/fluent-bit
        pullPolicy: IfNotPresent
      
      service:
        type: ClusterIP
        port: 2020
        annotations:
          prometheus.io/path: "/api/v1/metrics/prometheus"
          prometheus.io/port: "2020"
          prometheus.io/scrape: "true"
      
      resources: {}
        # limits:
        #   cpu: 100m
        #   memory: 128Mi
        #requests:
        #  cpu: 100m
        #  memory: 128Mi
      
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
      
      config:
        service: |
          [SERVICE]
              Flush 3
              Daemon Off
              #Log_Level info
              Log_Level debug
              Parsers_File custom_parsers.conf
              Parsers_File parsers.conf  #分析器配置文件
              HTTP_Server On
              HTTP_Listen 0.0.0.0  #监听地址
              HTTP_Port 2020
      
        inputs: |
          [INPUT]
              Name tail
              Path /var/log/containers/*.log  #读取哪些文件
              Parser cri
              Tag kube.*
              Mem_Buf_Limit 5MB  #数据缓冲空间大小
              Skip_Long_Lines On  #跳过特别长的日志 
              Refresh_Interval  10
      
          [INPUT]
              Name systemd
              Tag host.*
              Systemd_Filter _SYSTEMD_UNIT=kubelet.service
              Systemd_Filter _SYSTEMD_UNIT=docker.service
              Systemd_Filter _SYSTEMD_UNIT=node-problem-detector.service
              Read_From_Tail On
      
        filters: |
          [FILTER]
              Name                kubernetes
              Match               kube.*  #标签匹配
              Kube_URL            https://kubernetes.default.svc:443  #apiserver访问入口
              Kube_CA_File        /var/run/secrets/kubernetes.io/serviceaccount/ca.crt  #加载证书
              Kube_Token_File     /var/run/secrets/kubernetes.io/serviceaccount/token
              Kube_Tag_Prefix     kube.var.log.containers.
              Merge_Log           On  #日志合并功能
              Merge_Parser        catchall
              Keep_Log            Off  #将日志合并后就不保留原有字段
              K8S-Logging.Parser On  #打开k8s内置的日志分析器,对日志分析完后,对相应字段加上key
              K8S-Logging.Exclude On  #pod通过注解排除日志
      
        outputs: |
          [OUTPUT]
              Name es
              Match kube.*  #匹配的标签
              Host es-elasticsearch-coordinating-only.logging.svc.cluster.local.
              Logstash_Format On
              Logstash_Prefix k8s-cluster
              Type  flb_type
              Replace_Dots On
      
          [OUTPUT]
              Name es
              Match host.*
              Host es-elasticsearch-coordinating-only.logging.svc.cluster.local.
              Logstash_Format On
              Logstash_Prefix k8s-node
              Type  flb_type
              Replace_Dots On
      
        customParsers: |
          [PARSER]  #为日志加上时间
              Name docker_no_time  #分析器名称
              Format json
              Time_Keep Off
              Time_Key time
              Time_Format %Y-%m-%dT%H:%M:%S.%L
      
          [PARSER]
              Name        ingress-nginx  #分析器
              Format      regex  #
              Regex       ^(?<message>(?<remote>[^ ]*) - (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*) "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" (?<request_length>[^ ]*) (?<request_time>[^ ]*) \[(?<proxy_upstream_name>[^ ]*)\] \[(?<proxy_alternative_upstream_name>[^ ]*)\] (?<upstream_addr>[^ ]*) (?<upstream_response_length>[^ ]*) (?<upstream_response_time>[^ ]*) (?<upstream_status>[^ ]*) (?<req_id>[^ ]*).*)$
              Time_Key    time
              Time_Format %d/%b/%Y:%H:%M:%S %z
      
          [PARSER]
              Name    catchall
              Format  regex
              Regex   ^(?<message>.*)$
      

      容器中的日志
      image.png
      image.png

      39.3. Fluent-bit部署

      image.png

      40. jenkins

      image.png

      40.1. 多分支流水线

      image.png

      40.2. pipeline是什么

      image.png

      40.3. pipeline语法初步脚本式声明式

      image.png

      40.3.1. pipeline语法组成

      image.png

      40.4. pipeline编辑器特性

      image.png

      40.5. pipeline脚本式基础及代码示例

      image.png

      40.6. 回放功能

      image.png
      image.png

      40.7. pipeline声明式的结构

      image.png
      image.png
      image.png
      image.png
      image.png
      image.png
      image.png
      image.png
      image.png

      40.8. maven简介

      image.png
      image.png

      40.9. golang构建环境

      image.png

      40.10. python构建环境方法一

      image.png

      40.11. python构建环境方法二

      image.png

      40.12. 触发任务

      自动化的pipeline会按照一定的规则自动启动并运行,这类的规则便是所谓的触发条件;
      触发的常用方法有如下三种
      对于pipeline风格的任务来说,在web界面中就可以指定触发条件;
      对于脚本式pipeline,可以在代码顶部指定一个properties代码块来定义触发条件;
      该方式定义的触发条件将会和Web界面中定义的触发条件合并处理,并且Web界面上定义的条件优先生效;
      对于声明式pipeline,可将触发条件定义在triggers{}指令定义的配置段中;
      triggers内置支持cron、pollSCM和upstream三种触发机制;
      其它触发机制可借助于插件来实现,例如基于代码仓库上webhook通知的触发等;
      注意:上述方法并不适用于多分支pipeline、Github组织等类型的项目的触发,这些类型的任务都需要有相应的Jenkinsfile进行标识;

      40.13. 周期性构建

      这是一种cron类型的构建机制,它按照预定义的时间周期启动任务;
      对于期望能够基于代码变更进行触的CI场景来说,周期性构建并非其最佳选项,但对于有些类型的任务,它却也能够通过精心编排的周期性构建来避免资源冲突;
      Jenkins cron语法遵循Unix cron语法的定义,但在细节上略有差别;
      一项cron的定义包含由空白字符或Tab分隔的5个字段,用于定义周期性的时间点;
      image.png
      Jenkins cron还可以使用以下特定字符,一次性指定多个值
      specifies all valid values
      M-N specifies a range of values
      uM-N/X or
      /X steps by intervals of X through the specified range or whole valid range(以X为步长)
      A,B,…,Z enumerates multiple values(逗号分隔的枚举值)
      此外,H也可用于任何字段,它能够在一个时间范围内对项目名称进行散列值计算出一个唯一的偏移量,以避免所有配置相同cron值的项目在同一时间启动;
      例如triggers { cron(H(0,30) ) }

      40.13.1. cron构建示例

      image.png

      40.14. pollSCM 轮询SCM 轮询检查代码仓库是否有变更

      轮询SCM指的是定期到代码仓库检查代码是否有变更,存在代码变更时就运行pipeline;
      为了能够从CI中得到更多的收益,轮询操作越频繁越好;
      显然,这种需求下的触发由SCM负责通知Jenkins最为理想,以避免给SCM带去无谓的压力;但在外部的SCM无法通知到局域网中的Jenkins时,倒也不失为一种选择;
      image.png

      40.15. upstream:由上游任务触发

      若job-x依赖于job-y的执行结果,则称为job-y为job-x的upstream(上游);
      Jenkins自2.22版本开始支持在triggers中定义upstream类型的触发条件;
      前任务依赖到的upstream任务定义在upstreamProjects参数中,多个任务彼此间以逗号分隔;
      触发条件为upstream的执行状态,它定义在threshold参数中,其值为hudson.model.Result.
      Hudson.model.Result支持以下取值
      ABORTED:任务被中止
      FAILURE:构建失败
      SUCCESS:构建成功
      UNSTABLE:不稳定,即存在失败的步骤,但尚未导致失败;
      NOT_BUILT:多阶段构建场景中,因前面阶段的问题导致后面的阶段无法执行;
      image.png

      40.16. gilab通知触发

      GitLab通知触发,是指pipeline关联的GitLab Repository上的代码出现变更时,由GitLab将相关事件通知给Jenkins,从而触发Jenkins执行构建操作;
      避免了pollSCM的频繁轮询依然存在滞后可能性的问题;
      依赖于GibLab插件和Git插件;
      image.png

      40.16.1. 整合GitLab和Jenkins

      配置要点
      前提:GitLab和Jenkins同在本地网络时,需要以管理员权限设置“外发请求”,启用“允许Webhook和服务对本地网络的请求”;
      授予Jenkins访问GitLab上仓库中特定用户的代码权限;
      uJenkins基于SSH协议获取代码仓库中的内容,因而需要事先配置Jenkins能基于SSH密钥接入GitLab;

      GitLab API访问授权
      配置GitLab API访问认证(Access Token)及操作权限;
      配置Jenkins启用/project端点认证,配置它能通过配置的Access Token接入GitLab API;

      Jenkins pipeline项目的通知授权
      创建pipeline任务,选择使用的“GitLabConnection”,并选定使用“Build when a change is pushed to GitLab.”触发器;
      而后为构建触发器生成Secret token;
      配置GitLab Repository能通过Webhook,基于该Secret Token触发构建;

      具体配置过程相关文档
      https://docs.gitlab.com/ce/integration/jenkins.html

      40.16.2. 配置GitLab允许外发

      以GitLab管理员的身份,设置系统在外发请求中,允许Webhook和服务对本地网络的请求;
      image.png

      40.16.3. 为GitLab用户添加SSH公钥

      生成SSH密钥对,将公钥保存于GitLab用户账号之上,以使得git或jenkins等客户端能使用匹配的私钥认证到GitLab服务上;
      可在Jenkins Server上以jenkins用户的身份生成;
      ~# usermod-s /bin/bash jenkins
      ~# su-jenkins
      ~# ssh-keygen -t ed25519 -C ““ 或者
      ~# ssh-keygen -t rsa -b 2048 -C “email@magedu.com”
      复制公钥文件的内容,贴在

      GitLab上的用户账号配置
      属性中;
      image.png

      40.16.4. 在Jenkins上通过凭证添加SSH私钥以认证到GitLab

      复制SSH密钥对儿的私钥信息,保存为Jenkins上的凭据;
      image.png

      40.16.5. 在GitLab上创建创建Access Token

      User Account —> Settings —> Access Tokens
      image.png

      40.16.6. 在Jenkins上授权启用/project端点以创建GitLab连接

      Manage Jenkins —> Manage Plugins
      安装GitLab插件;
      Manage Jenkins —> Configure System
      image.png

      40.16.7. 配置Jenkins项目可经由GitLab上的事件触发

      首先,在Jenkins的pipeline和freestyle类型的项目上,选择使用的GitLabconnection;
      接着,选中“Build when a change is pushed to GitLab”,并按需勾选允许的触发事件
      而后,还应该配置如何通知给GitLab;
      Freestyle项目可以选择通过

      Post-build Actions指定;
      Pipeline项目只能通过pipeline代码指定,下面是一个简单示例;
      image.png
      配置Jenkins项目可经由GitLab上的事件触发(2)
      接下来,点击如前页图中的“高级”按钮,在Jenkins项目的上生成Secret Token,该Token将被GitLab用作触发时的认证信息;
      image.png

      40.16.8. 配置Jenkins项目对应的GitLab上的代码仓库

      在GitLab上对应代码仓库的配置菜单上,Settings —> Webhooks
      创建一个Webhook,指向前面配置的Jenkins项目及其相应的Secret Token
      image.png

      40.16.9. 在Pipeline中实现GitLab trigger

      对于如上步骤中需要手动操作的部分,同样也能够在Jenkinsfile中直接实现,如右侧的代码所示;
      triggerOnPush:GitLab触发push事件时是否执行构建;
      triggerOnMergeRequest:GitLab触发mergeRequest事件时,是否执行构建;
      branchFilterType:只有符合条件的分支才会被触发;必选配置,否则将无法实现触发,支持如下值;
      NameBaseFilter:基于分支名进行过滤,多个分支名彼此间以逗号分隔;
      RegexBaseFilter:基于正则表达式模式对分支名过滤;
      All:所有分支都会被触发;
      includeBranchSpec:基于branchFilterType值,输入期望包括的分支的规则;
      excludeBranchSpec:基于branchFilterType值,输入期望排队的分支的规则

      更详细的配置参数请参考GitLab-Plugin项目的描述
      https://github.com/jenkinsci/gitlab-plugin
      image.png

      40.17. 凭证的作用域和Provider

      凭证的作用域决定了它可用的目标范围;
      系统:作用于Jenkins系统自身,仅可用于系统和后台任务,且一般用于连接到agent节点之上;
      全局:作用于Jenkins上的所有任务,以确保任务的正常执行;
      用户:作用于用户级别,仅生效于Jenkins中的线程代表该用户进行身份验证之时;

      凭证提供者(Provider)
      凭证Provider是指能够存储和获取凭证的地方,它可以Jenkins内部的凭证存储,也可以是外部的凭证库
      Jenkins共支持如下几个凭证Provider
      系统凭证Provider:支持系统和全局两个作用域的凭证;
      用户凭证Provider:用户凭证的存储机制,且每个用户仅能看到自己的凭证;
      文件夹凭证Provider:文件夹凭证存储,可作用于该文件夹及其子文件夹;
      Blue Ocean凭证插件:作用于Blue Ocean接口,以及通过该接口创建或访问的项目;

      40.18. 在Pipeline中使用凭证

      有时候,我们需要在Pipeline中为steps提供凭证,以完成steps中必要的操作步骤;

      在steps中使用凭证,依赖于Credential BindingPlugin,该插件由Jenkins自行部署;

      在Pipeline中,要使用withCredentials( ){ //code}来引用凭证,需要认证到特定系统的操作则定义在{}中;
      sername with password
      withCredentials([usernamePassword(credentialsID: ‘‘,
      passwordVariable: ‘‘,
      usernameVariable: ‘‘)])
      其中,无论用户名和密码使用变量名可自行指定,而后,Jenkins都会通过credentialsID从指定的凭证填充用户名和密码;
      下面是一个简单的示例;
      image.png

      在Pipeline中,要使用withCredentials( )来引用凭证;
      SSH密钥
      withCredentials([sshUserPrivateKey(credentialsId: ‘’,
      keyFileVariable: ‘MYKEYFILE’,
      passphraseVariable: ‘PASSPHRASE’,
      usernameVariable: ‘USERNAME’)])
      { // some block }
      另外,若安装了SSHAgent Plugin,还可以使用“sshagent([]) { }”代码块;
      image.png

      40.19. 参数化pipeline的常用参数

      声明式Pipeline中,parameters指令用于为Pipeline声明参数;该指令用于pipeline{}之中,且常见于agent指令之后;
      可用参数有如下这些
      name 参数名称
      defaultValue 默认值
      description 描述信息

      string
      A parameter of a string type, for example: parameters { string(name: ‘DEPLOY_ENV’, defaultValue: ‘staging’, description: ‘ ‘) }
      text
      A text parameter, which can contain multiple lines, for example: parameters { text(name: ‘DEPLOY_TEXT’, defaultValue: ‘One\nTwo\nThree\n’, description: ‘ ‘) }
      booleanParam 布尔型
      A booleanparameter, for example: parameters { booleanParam(name: ‘DEBUG_BUILD’, defaultValue: true, description: ‘ ‘) }
      值传递也是string类型;
      choice 选择型 单选
      A choice parameter, for example: parameters { choice(name: ‘CHOICES’, choices: [‘one’, ‘two’, ‘three’], description: ‘ ‘) }
      password 密码 不会显示出来
      A password parameter, for example: parameters { password(name: ‘PASSWORD’, defaultValue: ‘SECRET’, description: ‘A secret password’) }

      40.19.1. 使用示例:string类型的参数

      string方法默认用于定义一个字符串类型的参数,它接收三个参数
      name:参数名;
      defaultValue:默认值;
      description:参数的描述信息;
      传入的参数会放在一个名为params的对象中,该参数可以在pipeline中引用;例如下面的示例中,params.userRole就是对引用了名为userRole的参数;
      image.png
      多参数
      image.png
      image.png

      40.20. input步骤

      input步骤是Pipeline与用户交互的接口,用于实现根据用户输入改变pipeline的行为;
      遇到input步骤时,Pipeline会暂停下来并等待用户的响应;
      input步骤是特殊的参数化pipeline的方法,它常用于实现简易的审批流程,或者是手动实施后续的步骤等;
      为了接收用户输入的不同数据,Jenkins提供了不同类型的参数;
      input步骤默认打印出的表单是打印一条消息并为用户提供一个选择:Proceed或者Abort;
      执行中途,进行选择参数
      image.png
      image.png
      input步骤的参数
      input步骤的可用参数
      message,String类型;
      其内容将打印给用户,并要求用户选择Proceed或Abort;
      若input仅提供了该参数时,还可以省略message参数名称;
      id (optional),String类型;
      每个input都有一个惟一的ID标识,用于生成专用的URL,以便于根据用户输入继续或中止pipeline;
      /job/[job_name]/[build_id]/input/[input_id]/
      该URL可通过POST方法进行请求,后跟proceedEmpty表示空输入并继续,而abort则表示中止;
      未定义时,Jenkins将自动为input生成ID;
      ok (optional),String类型;
      用于自定义Proceed按钮的标签名称;例如,下面的示例中,Proceed按钮的名称为“Yes”
      input message: ‘‘, ok: ‘Yes’
      parameters (optional)
      要求用户手动输入一个或多个参数列表;
      pipeline中,parameters指令支持的参数类型仅是input步骤支持的参数类型的一个子集,因而,那些参数类型都会被input步骤所支持;
      submitter (optional),String类型;
      可以进行后续操作的用户的ID或用户组列表,彼此间以逗号分隔,且前后不允许出现空格;
      submitterParameter(optional),String类型;
      用于保存input步骤的实际操作者的用户名;

      输入等待超时
      input步骤与timeout步骤协同使用,可实现超时自动中止pipeline,以避免无限等待;
      timeout(time, activity, unit) {}
      time: The length of time for which this step will wait before cancelling the nested block. 整型数据
      activity (optional):Timeout after no activity in logs for this block instead of absolute duration. 布尔型数据
      unit (optional):The unit of the time parameter. Defaults to ‘MINUTES’ if not specified.
      Values: NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
      右侧的示例中,为input步骤指定了1分钟的等待时长;
      生产中,发布操作的等待时长通常可能会具有更长的时间,例如1小时等
      image.png

      40.21. 多分支流水线概述

      • 多分支(multi-branch)流水线是基于git分支创建Jenkins pipeline的机制,它可以自动在SCM中发现新分支,并自动为新分支创建pipeline;
      • 不期望出现在pipeline中的分支需要通过排除机制予以排除在外;
      • Jenkins的多分支流水线项目类型支持Github、GitLab和Bitbucket等;
      • 多分支pipeline基于PR(pull request)进行分支发现;
      • 有人从branch中执行PR操作时,Pipeline会自动发现分支;
      • PR上升将自动触发构建操作

      多分支和pipeline
      右图示例中的仓库共有master、develop和feature三个分支
      三个分支分别有其不同的pipeline
      master分支有完整的CI/CDpipeline
      develop分支仅有CI pipeline
      feature分支仅有单元测试的功能
      Jenkins Server会自动从仓库中发现所有分支,并提取每个分支,而后根据Jenkinsfile运行pipeline;
      之后,每当git仓库上的任何分支发生新的代码变更时,Jenkins Server将自动触发相应的pipeline

      多分支pipeline的简要工作逻辑
      基于Feature、Develop和Master分支构建内部研发工作逻辑是较为常见的工作流模型
      Developer通过具体的feature分支开发新的功能,并向feature提交代码;
      每当开发人员从feature分支提PR至develop分支时,Jenkins pipeline都应触发以运行单元测试和静态代码分析;
      feature分支中的代码测试成功后,开发人员将PR合并到develop分支;
      在将要发布代码时,开发人员将PR从develop分支提到master,此时将触发Jenkins上的pipeline运行单元测试、代码分析等,并将代码部署到dev/QA环境;

      when指令

      • when指令用于在pipeline中为stage添加自定义的执行条件
      • when指令必须包含至少一个条件,多个条件间为“与”逻辑,即所有的子条件必须返回True,stage才能执行;
      • 支持使用not、allOf和anyOf来构建更复杂的条件结构;

      内置条件

      • branch
        • 当正在构建的分支同模式中给定的分支条件匹配时,则运行该stage, 例如: when { branch ‘master’ };
        • 仅适用于多分支流水线;
      • environment
        • 在指定的环境变量值与给定的目标值匹配时,则运行该stage,例如
        • when { environment name: ‘DEPLOY_TO’, value: ‘production’ }
      • expression

        • 当指定的Groovy表达式结果为true时,则运行该stage,例如
        • when { expression { return params.DEBUG_BUILD} }

          40.22. 通知与报警

          通知与报告概述
      • Jenkins通知:将任务的执行状态、事件或信息推送给相关用户,这些通常发生在pipeline的“构建后处理(post-processing)”时期;

        • Email是Jenkins内置支持的通知方式,它也能够通过webhook扩展支持其它的即时通信媒介,例如Slack、钉钉等;
        • 可以对接收信息的用户进行分类、分组,使对应组内用户收到信息
      • Jenkins使用的许多插件或工具都会为其支持的多种任务生成HTML报告,相关的任务有如代码分析、代码覆盖率和单元测试等;
        • 其中一些工具(如SonarQube和JaCoCo等)甚至可以和Jenkins任务输出做定制集成,这些工具甚至会采用直观的图标给出相关报告的链接;
        • 对于那些在报告相关的功能方面支持的不是特别好的工具来说,我们也可以借助于HTML

      配置Jenkins的邮件通知功能
      Jenkins管理员的邮箱地址在“Jenkins Location”系统配置段中的定义
      该邮箱地址将为作为发给项目owner的通知邮件的发件人地址(From)
      image.png

      在pipeline中发送通知
      在声明式pipeline的post{}里可以使用mail这一step来发送通知
      该步骤支持有参数有如下几个
      subject:邮件主题;
      to:收件人地址;
      body:邮件正文;
      from:发件地址;
      image.png

      扩展电子邮件通知
      除了基本的email功能外,Jenkins还支持通过Extension Email插件提供更多的高级选项和控制级别,它包含有类似邮件mail插件的基础配置,并增加了其它几个功能区,如右侧的图形所示;
      emailext新增了以下几个功能区
      内容:可以动态地修改email通知的主题和正文;
      收件人:可以定义哪些角色的用户会收到email通知;
      触发器:可以指定发送email通知的条件;
      image.png

      emailext步骤
      在声明式pipeline的post{}中使用扩展email通知时要使用emailext步骤实现,它支持如下几个常用参数
      subject
      body
      attachLog(optional):是否将构建日志以附件形式发送;
      attachmentsPattern(optional):需要发送的附件的路径,要使用Ant风格的路径表达式;
      compressLog(optional):是否压缩日志;
      mimeType(optional)
      postsendScript(optional)
      presendScript(optional)
      from(optional)
      to(optional)
      recipientProviders(optional):收件人类型,列表型数据;
      replyTo(optional)

      recipientProviders
      除了指定的收件人外,emailext可支持多种不同类型的收件人
      buildUser 手动发起构建操作的
      culprits:最近一次非失败构建至今有变更提交的用户列表;
      developers
      brokenTestsSuspects:导致单元测试失败的嫌疑用户列表;
      brokenBuildSuspects:导致构建失败的嫌疑用户列表;
      recipients:项目上的recipient列表;
      requestor:触发构建的用户;push时触发构建操作的用户
      upstreamDevelopers:触发本地构建的上游项目的变更提交者;

      40.23. 钉钉通知DingTalk通知

      钉钉配置过程
      在相应的钉钉群上添加自定义类型的机器人;
      image.png
      image.png
      image.png
      image.png

      DingTalk通知
      钉钉配置过程
      为机器人选择合适的安全设置,这里以“加签”方式为例,相应的密钥信息需要在Jenkins上用到;
      image.png

      DingTalk通知
      钉钉配置过程
      最后自动生成webhook,该webhook也将会由Jenkins所使用;
      image.png

      配置Jenkins的dingtalk插件
      在Jenkins上安装dingtalk插件;
      而后配置钉钉插件:ManageJenkinsàConfigure System à钉钉
      配置完成后,建议点击测试按钮确认是否配置成功
      image.png
      image.png

      dingtalk步骤
      dingtalk是由相应插件引入的步骤,它支持以下字段;
      robot
      at (optional)
      atAll(optional)
      btnLayout(optional)
      btns(optional)
      hideAvatar(optional)
      messageUrl(optional)
      picUrl(optional)
      singleTitle(optional)
      singleUrl(optional)
      text (optional)
      title (optional)
      type (optional)
      各参数说明:https://jenkinsci.github.io/dingtalk-plugin/guide/pipeline.html#%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E
      image.png

      测试由dingtalk发送通知
      将此前示例中的email通知修改为dingtalk通知方式
      通知结果如下图中最后一条消息所示
      注意:即便是钉钉机器人引用错误,Jenkins的执行状态也不会报错
      image.png

      40.24. SonarQube简介

      SonarQube是一种自动代码审查工具,用于检测代码中的错误、漏洞和代码异味,它集成到现有的工作流程,以便在项目分支和拉取(PR)请求之间进行连续的代码检查;
      SonarQube有四个关键组件
      SonarQube Server运行三个主要进行
      Web Server:UI
      Search Server:为UI提供搜索功能,基于ElasticSearch
      Compute Engine Server:处理代码分析报告并将之存储到SonarQube Database中
      SonarQube Database:负责存储SonarQube的配置,以及项目的质量快照等
      SonarQube Plugin
      Code analysis Scanners:代码扫描器,扫描后将报告提交给SonarQube Server

      部署的先决条件(以7.9 LTS为例)
      硬件需求
      小型应用至少需要2GB的RAM
      磁盘空间取决于SonarQube分析的代码量
      必须安装在读写性能较好的磁盘上
      存储数据的目录中包含了ElasticSearch的索引,服务器启动并运行时,将会在该索引上进行大量I/O操作
      不支持32位操作系统
      支持PostgreSQL、SQL Server和Oracle,不再支持MySQL,且要求PostgreSQL必须使用9.3-9.6,或者10以上的版本;

      JVM需求
      image.png

      Linux平台要求
      将SonarQube部署于Linux系统时,必须确保满足如下需求
      vm.max_map_countis greater or equals to 262144
      fs.file-max is greater or equals to 65536
      the user running SonarQube can open at least 65536 file descriptors
      the user running SonarQube can open at least 4096 threads
      前两个参数通过sysctl系统设定;
      后两个参数需要在配置文件/etc/security/limits.conf中完成
      image.png
      对于以systemd运行SonarQube的场景,也可通过设置其unitfile文件完成
      image.png

      40.25. Jenkins和SonarQube

      Jenkins借助于SonarQube Scanner插件将SonarQube提供的代码质量检查能力集成到pipeline上,从而确保质量阈检查失败时,能够避免继续进行后续的操作,例如发布等;
      Jenkins pipeline启动;
      SonarQube Scanner分析代码,并将报告发送至SonarQube Server;
      SonarQube Server分析代码检测的结果是否符合预定义的质量阈;
      SonarQube Server将通过(passed)或者失败(failed)的结果发送回Jenkins上的SonarQube Scanner插件暴露的Webhook;
      质量域相关的阶段成功通过或可选地失败时,则Jenkins pipeline续费后面的Stage;否则,pipeline将终止;
      然而,Jenkins的SonarQube Scanner插件将代码分析报告提交给SonarQube Server时,它不会同步响应质量阈的检测结果,为此,我们必须在SonarQube Server上配置一个webhook以回调Jenkins;
      image.png

      配置Jenkins使用SonarQube
      配置Jenkins使用sonar-scanner进行代码质量扫描,并将结果报告给SonarQube Server的主要步骤如下
      首先,在Jenkins上安装SonarQube插件
      其次,配置Jenkins对接到SonarQube Server
      第三,配置Jenkins的全局工具sonar-scanner
      第四,在SonarQube上添加回调Jenkins的Webhook
      第五,在Jenkins项目上调用sonar-scanner进行代码质量扫描
      最后,通过SonarQube确认扫描结果的评估;

      在SonarQube上生成令牌
      p在SonarQube上以相应的用户生成令牌,该令牌将被Jenkins用于通过相应的URL打开SonarQube
      image.png

      将SonarQube令牌存储为Jenkins凭证
      在Jenkins上保存SonarQube的令牌为凭证,凭证类型为Secret text;
      Manage Jenkins —> Manage Credentials
      image.png

      在Jenkins上添加SonarQube Server
      在Jenkins的配置中,添加SonarQube Server,并选择打开该Server时使用的令牌凭证
      Manage Jenkins —> Configure System —> SonarQube Servers
      image.png

      为Jenkins添加sonar-scanner工具
      为Jenkins添加全局工具sonar-scanner,以便在构建任务中调用
      Manage Jenkins —> 全局工具配置
      image.png

      在SonarQube添加Jenkins的回调接口
      在SonarQube上添加webhook(网络调用),以便于Jenkins通过SonarQube Quality Gate插件调用其质量阈信息;
      image.png

      在Jenkins中使用SonarQube进行代码质量检查
      pmvn可使用sonar:sonar这一target直接调用SonarQube进行代码质量分析
      image.png
      image.png

      在Jenkins中使用SonarQube进行代码质量检查(2)
      将SonarQube的用户token配置为Jenkins的凭证,便可在Jenkins的job中直接通过链接认证到SonarQube;
      image.png

      40.26. jenkins分布式

      Master与Agent间的连接方式
      为了能让master将一个主机识别为agent,需要事先在各agent上运行特定的代理程序以使得其能够与master之间建立双向通信
      有多种方法实现master与agent之间的连接建立
      SSH连接器:首选且最稳定的双向连接机制,它依赖于Jenkins内置的SSH客户端,并要求
      各agent要部署并启动了SSH服务;
      支持基于密钥及口令的两种认证方式,但认证信息要保存为master之上的凭证;
      基于密钥认证时,master主机上私钥凭证对应的公钥要存在于各agent主机之上;
      Inbound连接器:在agent上以手动或系统服务的方式经由JNLP协议触发双向连接的建立;
      JNLP-HTTP连接器:在agent上经由JNLP协议通过HTTP建立双向连接;

      agent配置段语法介绍
      agent可接受多种形式的参数
      any:任何可用节点
      none:用于pipeline顶端时表示不定义默认的agent,这就需要为每个stage单独指定;
      label { label “