一个Kubernetes集群主要是由控制节点(master)、工作节点(node)构成,每个节点都会安装不同的组件。
master:集群的控制平面,负责集群的决策
node:集群的数据平面,负责给容器提供运行环境
下面,以部署一个Nginx服务来说明Kubernetes系统各个组件调用关系:
kubernetes在集群启动之后,会默认创建几个namespace:default、kube-node-lease、kube-public、kube-system。
默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的"组",以方便不同的组的资源进行隔离使用和管理。
Pod是kubernetes集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于Pod中。Pod可以认为是容器的封装,一个Pod中可以存在一个或者多个容器。同一个Pod中的容器共享 IP 地址,进程间的通讯(IPC,Inter-Process Communication,进程间通信),主机名以及其他资源。
每一个Pod中都可以包含一个或多个容器,这些容器可以分为两类:
下面是Pod的资源清单:
- apiVersion: v1 #必选,版本号,例如:v1
- kind: Pod #必选,资源类型,例如:Pod
- metadata: #必选,元数据
- name: string #必选,Pod名称,
- namaspace: string #Pod所属命名空间,默认是“default”
- labels: #自定义标签列表
- - name: string
- annotations:
- - name: string
- spec: #必选,Pod中容器的详细定义
- containers: #必选,Pod中容器列表
- - name: string #必选,容器名称
- images: string #必选,容器镜像名称
- imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略
- command: [string] #容器的启动命令列表,如果不指定,使用打包时使用的启动命令
- args: [string] #容器的启动命令参数列表
- workingDir: string #容器的工作目录
- volumeMounts: #挂载到容器内部的存储卷位置
- - name: string #引用Pod定义的共享存储卷的名称,需要用volumns[]部分定义的卷名
- 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 #内存请求,容器启动的初始可用数量
- livenessProbe: #对Pod内各个容器健康检查的设置,当探测无响应几次后将自动重启该容器
- exec: #对Pod容器内检查方式设置为exec方式
- command: [string] #exec方式需要制定的命令或脚本
- httpGet: # 对Pod内各个容器健康检查方法设置为httpGet,需要指定path和port
- path: string
- port: int
- host: string
- scheme: string
- httpHeaders:
- - name: string
- value: string
- tcpSocket: # 对Pod内各个容器健康检查方式设置为tcpSocket
- port: int
- initialDelaySeconds: number #容器内完成首次探测的时间,单位为秒
- timeoutSeconds: number #对容器健康探测等待响应的超时时间,单位为秒,默认1秒
- periodSeconds: number #对容器健康检查定期探测时间,单位为秒,默认10秒一次
- successThreshold: 0
- failureThreshold: 0
- securityContext:
- privileged: false
- restartPolicy: [Always | Never | OnFailure] #Pod重启策略
- nodeName:
#设置nodeName表示将该Pod调度到指定名称的Node节点上 - nodeSelector: object #设置nodeSelector表示将该Pod调度到包含这个label的Node上
- imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
- - name: string
- hostNetwork: false #是够使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
- volumes: #在该Pod上定义共享存储卷列表
- - name: string #共享存储卷名称(volumns类型有很多种)
- emptyDir: {} #类型为emptyDor的存储卷,与Pod同生命周期的一个临时目录。为空值
- hostPath: #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
- path: string
- secret: #类型为secret的存储卷,表示挂载集群定义的secret对象到容器内部
- secretName: string
- items:
- - key: string
- path: string
- configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
- name: string
- items:
- - key: string
- path: string
在这里,可通过一个命令来查看每种资源的可配置项:
kubectl explain 资源类型 查看某种资源可以配置的一级属性
kubectl explain 资源类型.属性 查看属性的子属性
- [root@k8s-master01 ~]# kubectl explain pod
- KIND: Pod
- VERSION: v1
- FIELDS:
- apiVersion
- kind
- metadata
- spec
- status
-
- [root@k8s-master01 ~]# kubectl explain pod.metadata
- KIND: Pod
- VERSION: v1
- RESOURCE: metadata
- FIELDS:
- annotations
- clusterName
- creationTimestamp
- deletionGracePeriodSeconds <integer>
- deletionTimestamp
- finalizers <[]string>
- generateName
- generation <integer>
- labels
- managedFields <[]Object>
- name
- namespace
- ownerReferences <[]Object>
- resourceVersion
- selfLink
- uid
在kubernetes中基本所有资源的一级属性都是一样的,主要包含5部分:
在上面的属性中,spec是接下来研究的重点,继续看下它的常见子属性:
我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期,它主要包含下面的过程:
在整个生命周期中,Pod会出现5种状态(相位),分别如下:
pod的创建过程:
pod的终止过程:
初始化容器是在pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征:
初始化容器有很多的应用场景,下面列出的是最常见的几个:
钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码。
kubernetes在主容器的启动之后和停止之前提供了两个钩子函数:
钩子处理器支持使用下面三种方式定义动作:
Exec命令:在容器内执行一次命令
- ……
- lifecycle:
- postStart:
- exec:
- command:
- - cat
- - /tmp/healthy
- ……
TCPSocket:在当前容器尝试访问指定的socket
- ……
- lifecycle:
- postStart:
- tcpSocket:
- port: 8080
- ……
HTTPGet:在当前容器中向某url发起http请求
- ……
- lifecycle:
- postStart:
- httpGet:
- path: / #URI地址
- port: 80 #端口号
- host: 192.168.5.3 #主机地址
- scheme: HTTP #支持的协议,http或者https
- ……
容器探测用于检测容器中的应用实例是否正常工作,是保障业务可用性的一种传统机制。如果经过探测,实例的状态不符合预期,那么kubernetes就会把该问题实例" 摘除 ",不承担业务流量。kubernetes提供了两种探针来实现容器探测,分别是:
上面两种探针目前均支持三种探测方式:
Exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常
- ……
- livenessProbe:
- exec:
- command:
- - cat
- - /tmp/healthy
- ……
TCPSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常
- ……
- livenessProbe:
- tcpSocket:
- port: 8080
- ……
HTTPGet:调用容器内Web应用的URL,如果返回的状态码在200和399之间,则认为程序正常,否则不正常
- ……
- livenessProbe:
- httpGet:
- path: / #URI地址
- port: 80 #端口号
- host: 127.0.0.1 #主机地址
- scheme: HTTP #支持的协议,http或者https
- ……
一旦容器探测出现了问题,kubernetes就会对容器所在的Pod进行重启,其实这是由pod的重启策略决定的,pod的重启策略有 3 种,分别如下:
重启策略适用于pod对象中的所有容器,首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长以此为10s、20s、40s、80s、160s和300s,300s是最大延迟时长。
在默认情况下,一个Pod在哪个Node节点上运行,是由Scheduler组件采用相应的算法计算出来的,这个过程是不受人工控制的。但是在实际使用中,这并不满足的需求,因为很多情况下,我们想控制某些Pod到达某些节点上,那么应该怎么做呢?这就要求了解kubernetes对Pod的调度规则,kubernetes提供了四大类调度方式:
定向调度,指的是利用在pod上声明nodeName或者nodeSelector,以此将Pod调度到期望的node节点上。注意,这里的调度是强制的,这就意味着即使要调度的目标Node不存在,也会向上面进行调度,只不过pod运行失败而已。
其中:
NodeName用于强制约束将Pod调度到指定的Name的Node节点上。这种方式,其实是直接跳过Scheduler的调度逻辑,直接将Pod调度到指定名称的节点。
NodeSelector用于将pod调度到添加了指定标签的node节点上。它是通过kubernetes的label-selector机制实现的,也就是说,在pod创建之前,会由scheduler使用MatchNodeSelector调度策略进行label匹配,找出目标node,然后将pod调度到目标节点,该匹配规则是强制约束。
上一节,介绍了两种定向调度的方式,使用起来非常方便,但是也有一定的问题,那就是如果没有满足条件的Node,那么Pod将不会被运行,即使在集群中还有可用Node列表也不行,这就限制了它的使用场景。
基于上面的问题,kubernetes还提供了一种亲和性调度(Affinity)。它在NodeSelector的基础之上的进行了扩展,可以通过配置的形式,实现优先选择满足条件的Node进行调度,如果没有,也可以调度到不满足条件的节点上,使调度更加灵活。
Affinity主要分为三类:
首先来看一下NodeAffinity的可配置项:
- pod.spec.affinity.nodeAffinity
- requiredDuringSchedulingIgnoredDuringExecution Node节点必须满足指定的所有规则才可以,相当于硬限制
- nodeSelectorTerms 节点选择列表
- matchFields 按节点字段列出的节点选择器要求列表
- matchExpressions 按节点标签列出的节点选择器要求列表(推荐)
- key 键
- values 值
- operator 关系符 支持Exists, DoesNotExist, In, NotIn, Gt, Lt
- preferredDuringSchedulingIgnoredDuringExecution 优先调度到满足指定的规则的Node,相当于软限制 (倾向)
- preference 一个节点选择器项,与相应的权重相关联
- matchFields 按节点字段列出的节点选择器要求列表
- matchExpressions 按节点标签列出的节点选择器要求列表(推荐)
- key 键
- values 值
- operator 关系符 支持In, NotIn, Exists, DoesNotExist, Gt, Lt
- weight 倾向权重,在范围1-100。
-
- 关系符使用说明:
-
- - matchExpressions:
- - key: nodeenv # 匹配存在标签的key为nodeenv的节点
- operator: Exists
- - key: nodeenv # 匹配标签的key为nodeenv,且value是"xxx"或"yyy"的节点
- operator: In
- values: ["xxx","yyy"]
- - key: nodeenv # 匹配标签的key为nodeenv,且value大于"xxx"的节点
- operator: Gt
- values: "xxx"
NodeAffinity规则设置的注意事项:
PodAffinity主要实现以运行的Pod为参照,实现让新创建的Pod跟参照pod在一个区域的功能。
首先来看一下PodAffinity的可配置项:
- pod.spec.affinity.podAffinity
- requiredDuringSchedulingIgnoredDuringExecution 硬限制
- namespaces 指定参照pod的namespace
- topologyKey 指定调度作用域
- labelSelector 标签选择器
- matchExpressions 按节点标签列出的节点选择器要求列表(推荐)
- key 键
- values 值
- operator 关系符 支持In, NotIn, Exists, DoesNotExist.
- matchLabels 指多个matchExpressions映射的内容
- preferredDuringSchedulingIgnoredDuringExecution 软限制
- podAffinityTerm 选项
- namespaces
- topologyKey
- labelSelector
- matchExpressions
- key 键
- values 值
- operator
- matchLabels
- weight 倾向权重,在范围1-100
topologyKey用于指定调度时作用域,例如:
PodAntiAffinity主要实现以运行的Pod为参照,让新创建的Pod与参照Pod不在一个区域中的功能。
它的配置方式和选项跟PodAffinty是一样的,这里不再做详细解释。
前面的调度方式都是站在Pod的角度上,通过在Pod上添加属性,来确定Pod是否要调度到指定的Node上,其实我们也可以站在Node的角度上,通过在Node上添加污点属性,来决定是否允许Pod调度过来。
Node被设置上污点之后就和Pod之间存在了一种相斥的关系,进而拒绝Pod调度进来,甚至可以将已经存在的Pod驱逐出去。
污点的格式为:key=value:effect
, key和value是污点的标签,effect描述污点的作用,支持如下三个选项:
使用kubectl设置和去除污点的命令示例如下:
- # 设置污点
- kubectl taint nodes node1 key=value:effect
-
- # 去除污点
- kubectl taint nodes node1 key:effect-
-
- # 去除所有污点
- kubectl taint nodes node1 key-
上面介绍了污点的作用,我们可以在node上添加污点用于拒绝pod调度上来,但是如果就是想将一个pod调度到一个有污点的node上去,这时候应该怎么做呢?这就要使用到容忍。
污点就是拒绝,容忍就是忽略,Node通过污点拒绝pod调度上去,Pod通过容忍忽略拒绝。
Pod控制器是管理pod的中间层,使用Pod控制器之后,只需要告诉Pod控制器,想要多少个什么样的Pod就可以了,它会创建出满足条件的Pod并确保每一个Pod资源处于用户期望的目标状态。如果Pod资源在运行中出现故障,它会基于指定策略重新编排Pod。
Pod是kubernetes的最小管理单元,在kubernetes中,按照pod的创建方式可以将其分为两类:
在kubernetes中,有很多类型的pod控制器,每种都有自己的适合的场景,常见的有下面这些:
ReplicaSet的主要作用是保证一定数量的pod正常运行,它会持续监听这些Pod的运行状态,一旦Pod发生故障,就会重启或重建。同时它还支持对pod数量的扩缩容和镜像版本的升降级。
ReplicaSet的资源清单文件:
- apiVersion: apps/v1 # 版本号
- kind: ReplicaSet # 类型
- metadata: # 元数据
- name: # rs名称
- namespace: # 所属命名空间
- labels: #标签
- controller: rs
- spec: # 详情描述
- replicas: 3 # 副本数量
- selector: # 选择器,通过它指定该控制器管理哪些pod
- matchLabels: # Labels匹配规则
- app: nginx-pod
- matchExpressions: # Expressions匹配规则
- - {key: app, operator: In, values: [nginx-pod]}
- template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本
- metadata:
- labels:
- app: nginx-pod
- spec:
- containers:
- - name: nginx
- image: nginx:1.17.1
- ports:
- - containerPort: 80
在这里面,需要新了解的配置项就是spec
下面几个选项:
replicas:指定副本数量,其实就是当前rs创建出来的pod的数量,默认为1
selector:选择器,它的作用是建立pod控制器和pod之间的关联关系,采用的Label Selector机制,即:在pod模板上定义label,在控制器上定义选择器,就可以表明当前控制器能管理哪些pod了
template:模板,就是当前控制器创建pod所使用的模板板,里面其实就是前一章学过的pod的定义
为了更好的解决服务编排的问题,kubernetes在V1.2版本开始,引入了Deployment控制器。值得一提的是,这种控制器并不直接管理pod,而是通过管理ReplicaSet来间接管理Pod,即:Deployment管理ReplicaSet,ReplicaSet管理Pod。所以Deployment比ReplicaSet功能更加强大。
Deployment主要功能有下面几个:
- apiVersion: apps/v1 # 版本号
- kind: Deployment # 类型
- metadata: # 元数据
- name: # rs名称
- namespace: # 所属命名空间
- labels: #标签
- controller: deploy
- spec: # 详情描述
- replicas: 3 # 副本数量
- revisionHistoryLimit: 3 # 保留历史版本
- paused: false # 暂停部署,默认是false
- progressDeadlineSeconds: 600 # 部署超时时间(s),默认是600
- strategy: # 策略
- type: RollingUpdate # 滚动更新策略
- rollingUpdate: # 滚动更新
- maxSurge: 30% # 最大额外可以存在的副本数,可以为百分比,也可以为整数
- maxUnavailable: 30% # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
- selector: # 选择器,通过它指定该控制器管理哪些pod
- matchLabels: # Labels匹配规则
- app: nginx-pod
- matchExpressions: # Expressions匹配规则
- - {key: app, operator: In, values: [nginx-pod]}
- template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本
- metadata:
- labels:
- app: nginx-pod
- spec:
- containers:
- - name: nginx
- image: nginx:1.17.1
- ports:
- - containerPort: 80
在前面的课程中,我们已经可以实现通过手工执行kubectl scale命令实现Pod扩容或缩容,但是这显然不符合Kubernetes的定位目标--自动化、智能化。 Kubernetes期望可以实现通过监测Pod的使用情况,实现pod数量的自动调整,于是就产生了Horizontal Pod Autoscaler(HPA)这种控制器。
HPA可以获取每个Pod利用率,然后和HPA中定义的指标进行对比,同时计算出需要伸缩的具体值,最后实现Pod的数量的调整。其实HPA与之前的Deployment一样,也属于一种Kubernetes资源对象,它通过追踪分析RC控制的所有目标Pod的负载变化情况,来确定是否需要针对性地调整目标Pod的副本数,这是HPA的实现原理。
DaemonSet类型的控制器可以保证在集群中的每一台(或指定)节点上都运行一个副本。一般适用于日志收集、节点监控等场景。也就是说,如果一个Pod提供的功能是节点级别的(每个节点都需要且只需要一个),那么这类Pod就适合使用DaemonSet类型的控制器创建。
DaemonSet控制器的特点:
DaemonSet的资源清单文件:
- apiVersion: apps/v1 # 版本号
- kind: DaemonSet # 类型
- metadata: # 元数据
- name: # rs名称
- namespace: # 所属命名空间
- labels: #标签
- controller: daemonset
- spec: # 详情描述
- revisionHistoryLimit: 3 # 保留历史版本
- updateStrategy: # 更新策略
- type: RollingUpdate # 滚动更新策略
- rollingUpdate: # 滚动更新
- maxUnavailable: 1 # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
- selector: # 选择器,通过它指定该控制器管理哪些pod
- matchLabels: # Labels匹配规则
- app: nginx-pod
- matchExpressions: # Expressions匹配规则
- - {key: app, operator: In, values: [nginx-pod]}
- template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本
- metadata:
- labels:
- app: nginx-pod
- spec:
- containers:
- - name: nginx
- image: nginx:1.17.1
- ports:
- - containerPort: 80
Job主要用于负责批量处理(一次要处理指定数量任务)短暂的一次性(每个任务仅运行一次就结束)任务。Job特点如下:
Job的资源清单文件:
- apiVersion: batch/v1 # 版本号
- kind: Job # 类型
- metadata: # 元数据
- name: # rs名称
- namespace: # 所属命名空间
- labels: #标签
- controller: job
- spec: # 详情描述
- completions: 1 # 指定job需要成功运行Pods的次数。默认值: 1
- parallelism: 1 # 指定job在任一时刻应该并发运行Pods的数量。默认值: 1
- activeDeadlineSeconds: 30 # 指定job可运行的时间期限,超过时间还未结束,系统将会尝试进行终止。
- backoffLimit: 6 # 指定job失败后进行重试的次数。默认是6
- manualSelector: true # 是否可以使用selector选择器选择pod,默认是false
- selector: # 选择器,通过它指定该控制器管理哪些pod
- matchLabels: # Labels匹配规则
- app: counter-pod
- matchExpressions: # Expressions匹配规则
- - {key: app, operator: In, values: [counter-pod]}
- template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本
- metadata:
- labels:
- app: counter-pod
- spec:
- restartPolicy: Never # 重启策略只能设置为Never或者OnFailure
- containers:
- - name: counter
- image: busybox:1.30
- command: ["bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 2;done"]
CronJob控制器以Job控制器资源为其管控对象,并借助它管理pod资源对象,Job控制器定义的作业任务在其控制器资源创建之后便会立即执行,但CronJob可以以类似于Linux操作系统的周期性任务作业计划的方式控制其运行时间点及重复运行的方式。也就是说,CronJob可以在特定的时间点(反复的)去运行job任务。
CronJob的资源清单文件:
- apiVersion: batch/v1beta1 # 版本号
- kind: CronJob # 类型
- metadata: # 元数据
- name: # rs名称
- namespace: # 所属命名空间
- labels: #标签
- controller: cronjob
- spec: # 详情描述
- schedule: # cron格式的作业调度运行时间点,用于控制任务在什么时间执行
- concurrencyPolicy: # 并发执行策略,用于定义前一次作业运行尚未完成时是否以及如何运行后一次的作业
- failedJobHistoryLimit: # 为失败的任务执行保留的历史记录数,默认为1
- successfulJobHistoryLimit: # 为成功的任务执行保留的历史记录数,默认为3
- startingDeadlineSeconds: # 启动作业错误的超时时长
- jobTemplate: # job控制器模板,用于为cronjob控制器生成job对象;下面其实就是job的定义
- metadata:
- spec:
- completions: 1
- parallelism: 1
- activeDeadlineSeconds: 30
- backoffLimit: 6
- manualSelector: true
- selector:
- matchLabels:
- app: counter-pod
- matchExpressions: 规则
- - {key: app, operator: In, values: [counter-pod]}
- template:
- metadata:
- labels:
- app: counter-pod
- spec:
- restartPolicy: Never
- containers:
- - name: counter
- image: busybox:1.30
- command: ["bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 20;done"]
在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。
为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务。
Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程。当创建Service的时候会通过api-server向etcd写入创建的service的信息,而kube-proxy会基于监听的机制发现这种Service的变动,然后它会将最新的Service信息转换成对应的访问规则。
kube-proxy目前支持三种工作模式:
userspace模式下,kube-proxy会为每一个Service创建一个监听端口,发向Cluster IP的请求被Iptables规则重定向到kube-proxy监听的端口上,kube-proxy根据LB算法选择一个提供服务的Pod并和其建立链接,以将请求转发到Pod上。
该模式下,kube-proxy充当了一个四层负责均衡器的角色。由于kube-proxy运行在userspace中,在进行转发处理时会增加内核和用户空间之间的数据拷贝,虽然比较稳定,但是效率比较低。
iptables模式下,kube-proxy为service后端的每个Pod创建对应的iptables规则,直接将发向Cluster IP的请求重定向到一个Pod IP。
该模式下kube-proxy不承担四层负责均衡器的角色,只负责创建iptables规则。该模式的优点是较userspace模式效率更高,但不能提供灵活的LB策略,当后端Pod不可用时也无法进行重试。
ipvs模式和iptables类似,kube-proxy监控Pod的变化并创建相应的ipvs规则。ipvs相对iptables转发效率更高。除此以外,ipvs支持更多的LB算法。
Service的资源清单文件:
- kind: Service # 资源类型
- apiVersion: v1 # 资源版本
- metadata: # 元数据
- name: service # 资源名称
- namespace: dev # 命名空间
- spec: # 描述
- selector: # 标签选择器,用于确定当前service代理哪些pod
- app: nginx
- type: # Service类型,指定service的访问方式(ClusterIP、NodePort、LoadBalancer、ExternalName)
- clusterIP: # 虚拟服务的ip地址
- sessionAffinity: # session亲和性,支持ClientIP、None两个选项
- ports: # 端口信息
- - protocol: TCP
- port: 3017 # service端口
- targetPort: 5003 # pod端口
- nodePort: 31122 # 主机端口
Service常用类型:
Endpoint是kubernetes中的一个资源对象,存储在etcd中,用来记录一个service对应的所有pod的访问地址,它是根据service配置文件中selector描述产生的。
一个Service由一组Pod组成,这些Pod通过Endpoints暴露出来,Endpoints是实现实际服务的端点集合。换句话说,service和pod之间的联系是通过endpoints实现的。
负载分发策略:
对Service的访问被分发到了后端的Pod上去,目前kubernetes提供了两种负载分发策略:
在某些场景中,开发人员可能不想使用Service提供的负载均衡功能,而希望自己来控制负载均衡策略,针对这种情况,kubernetes提供了HeadLiness Service,这类Service不会分配Cluster IP,如果想要访问service,只能通过service的域名进行查询。
在之前的样例中,创建的Service的ip地址只有集群内部才可以访问,如果希望将Service暴露给集群外部使用,那么就要使用到另外一种类型的Service,称为NodePort类型。NodePort的工作原理其实就是将service的端口映射到Node的一个端口上,然后就可以通过NodeIP:NodePort来访问service了。
LoadBalancer和NodePort很相似,目的都是向外部暴露一个端口,区别在于LoadBalancer会在集群的外部再来做一个负载均衡设备,而这个设备需要外部环境支持的,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。
ExternalName类型的Service用于引入集群外部的服务,它通过externalName属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。
前面已经提到,Service对集群之外暴露服务的主要方式有两种:NotePort和LoadBalancer,但是这两种方式,都有一定的缺点:
基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求。工作机制大致如下图表示:
实际上,Ingress相当于一个7层的负载均衡器,是kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx,可以理解成在Ingress里建立诸多映射规则,Ingress Controller通过监听这些配置规则并转化成Nginx的反向代理配置 , 然后对外部提供服务。在这里有两个核心概念:
Ingress(以Nginx为例)的工作原理如下:
在前面已经提到,容器的生命周期可能很短,会被频繁地创建和销毁。那么容器在销毁时,保存在容器中的数据也会被清除。这种结果对用户来说,在某些情况下是不乐意看到的。为了持久化保存容器的数据,Kubernetes引入了Volume的概念。
Volume是Pod中能够被多个容器访问的共享目录,它被定义在Pod上,然后被一个Pod里的多个容器挂载到具体的文件目录下,Kubernetes通过Volume实现同一个Pod中不同容器之间的数据共享以及数据的持久化存储。Volume的生命周期不与Pod中单个容器的生命周期相关,当容器终止或者重启时,Volume中的数据也不会丢失。
Kubernetes的Volume支持多种类型,比较常见的有下面几个:
EmptyDir是最基础的Volume类型,一个EmptyDir就是Host上的一个空目录。
EmptyDir是在Pod被分配到Node时创建的,它的初始内容为空,并且无须指定宿主机上对应的目录文件,因为Kubernetes会自动分配一个目录,当Pod销毁时, EmptyDir中的数据也会被永久删除。 EmptyDir用途如下:
EmptyDir中数据不会被持久化,它会随着Pod的结束而销毁,如果想简单的将数据持久化到主机中,可以选择HostPath。
HostPath就是将Node主机中一个实际目录挂在到Pod中,以供容器使用,这样的设计就可以保证Pod销毁了,但是数据依据可以存在于Node主机上。
HostPath可以解决数据持久化的问题,但是一旦Node节点故障了,Pod如果转移到了别的节点,又会出现问题了,此时需要准备单独的网络存储系统,比较常用的用NFS、CIFS。
NFS是一个网络文件存储系统,可以搭建一台NFS服务器,然后将Pod中的存储直接连接到NFS系统上,这样的话,无论Pod在节点上怎么转移,只要Node跟NFS的对接没问题,数据就可以成功访问。
前面已经学习了使用NFS提供存储,此时就要求用户会搭建NFS系统,并且会在yaml配置nfs。由于Kubernetes支持的存储系统有很多,要求客户全都掌握,显然不现实。为了能够屏蔽底层存储实现的细节,方便用户使用, Kubernetes引入PV和PVC两种资源对象。
PV(Persistent Volume)是持久化卷的意思,是对底层的共享存储的一种抽象。一般情况下PV由Kubernetes管理员进行创建和配置,它与底层具体的共享存储技术有关,并通过插件完成与共享存储的对接。
PVC(Persistent Volume Claim)是持久卷声明的意思,是用户对于存储需求的一种声明。换句话说,PVC其实就是用户向Kubernetes系统发出的一种资源需求申请。
使用了PV和PVC之后,工作可以得到进一步的细分:
PV是存储资源的抽象,下面是资源清单文件:
- apiVersion: v1
- kind: PersistentVolume
- metadata:
- name: pv2
- spec:
- nfs: # 存储类型,与底层真正存储对应
- capacity: # 存储能力,目前只支持存储空间的设置
- storage: 2Gi
- accessModes: # 访问模式
- storageClassName: # 存储类别
- persistentVolumeReclaimPolicy: # 回收策略
PV 的关键配置参数说明:
存储类型
底层实际存储的类型,Kubernetes支持多种存储类型,每种存储类型的配置都有所差异
存储能力(capacity)
目前只支持存储空间的设置( storage=1Gi ),不过未来可能会加入IOPS、吞吐量等指标的配置
访问模式(accessModes)
用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:
需要注意的是,底层不同的存储类型可能支持的访问模式不同
回收策略(persistentVolumeReclaimPolicy)
当PV不再被使用了之后,对其的处理方式。目前支持三种策略:
需要注意的是,底层不同的存储类型可能支持的回收策略不同
存储类别
PV可以通过storageClassName参数指定一个存储类别
状态(status)
一个 PV 的生命周期中,可能会处于4中不同的阶段:
PVC是资源的申请,用来声明对存储空间、访问模式、存储类别需求信息。下面是资源清单文件:
- apiVersion: v1
- kind: PersistentVolumeClaim
- metadata:
- name: pvc
- namespace: dev
- spec:
- accessModes: # 访问模式
- selector: # 采用标签对PV选择
- storageClassName: # 存储类别
- resources: # 请求空间
- requests:
- storage: 5Gi
PVC 的关键配置参数说明:
选择条件(selector):通过Label Selector的设置,可使PVC对于系统中己存在的PV进行筛选
存储类别(storageClassName):PVC在定义时可以设定需要的后端存储的类别,只有设置了该class的pv才能被系统选出
资源请求(Resources ):描述对存储资源的请求
PVC和PV是一一对应的,PV和PVC之间的相互作用遵循以下生命周期:
在用户定义好PVC之后,系统将根据PVC对存储资源的请求在已存在的PV中选择一个满足条件的
PV一旦绑定到某个PVC上,就会被这个PVC独占,不能再与其他PVC进行绑定了。
Pod使用Volume的定义,将PVC挂载到容器内的某个路径进行使用。
当存储资源使用完毕后,用户可以删除PVC,与该PVC绑定的PV将会被标记为“已释放”,但还不能立刻与其他PVC进行绑定。通过之前PVC写入的数据可能还被留在存储设备上,只有在清除之后该PV才能再次使用。
对于PV,管理员可以设定回收策略,用于设置与之绑定的PVC释放资源之后如何处理遗留数据的问题。只有PV的存储空间完成回收,才能供新的PVC绑定和使用
ConfigMap是一种比较特殊的存储卷,它的主要作用是用来存储配置信息的。
在kubernetes中,还存在一种和ConfigMap非常类似的对象,称为Secret对象。它主要用于存储敏感信息,例如密码、秘钥、证书等等。
在Kubernetes中所有内容都抽象为资源,用户通过操作资源来管理Kubernetes。
资源管理方式:
类型 | 操作对象 | 适用环境 | 优点 | 缺点 |
---|---|---|---|---|
命令式对象管理 | 对象 | 测试 | 简单 | 只能操作活动对象,无法审计、跟踪 |
命令式对象配置 | 文件 | 开发 | 可以审计、跟踪 | 项目大时,配置文件多,操作麻烦 |
声明对象配置 | 目录 | 开发 | 支持目录操作 | 意外情况下难以调试 |
kubectl是Kubernetes集群的命令行工具,通过它能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。kubectl命令的语法如下:
kubectl [command] [type] [name] [flags]
command:指定要对资源执行的操作,例如create、get、delete
type:指定资源类型,比如deployment、pod、service
name:指定资源的名称,名称大小写敏感
flags:指定额外的可选参数
- # 查看所有pod
- kubectl get pod
-
- # 查看某个pod
- kubectl get pod [pod_name]
-
- # 查看某个pod,以yaml格式展示结果
- kubectl get pod [pod_name] -o yaml
-
- # 查看某个pod,展示详细信息
- kubectl get pod [pod_name] -o wide
(1)command:
基本命令:
命令 | 作用 |
---|---|
create | 创建一个资源 |
edit | 编辑一个资源 |
get | 获取一个资源 |
patch | 更新一个资源 |
delete | 删除一个资源 |
explain | 解释一个资源 |
运行和调试:
命令 | 作用 |
---|---|
run | 在集群中运行一个指定镜像 |
expose | 暴露资源给Service |
describe | 显示资源内部信息 |
logs | 输出容器在Pod中的日志 |
attach | 进入运行中的容器 |
exec | 执行容器中的一个命令 |
cp | 在Pod内外复制文件 |
rollout | 管理资源的发布 |
scale | 扩缩容Pod的数量 |
autoscale | 自动调整Pod的数量 |
高级命令:
命令 | 作用 |
---|---|
apply | 通过文件对资源进行管理 |
label | 更新资源上的标签 |
其它命令:
命令 | 作用 |
---|---|
cluster-info | 显示集群信息 |
version | 显示当前Server和Client的版本 |
(2) type:
Kubernetes中资源类型繁多,下面列举一下常用的资源,如果有需要可以通过下列命令查看资源列表:
kubectl api-resources
集群级别资源:
资源名称 | 缩写 | 资源作用 |
---|---|---|
nodes | no | 集群组成部分 |
namespace | ns | 隔离Pod |
Pod资源:
资源名称 | 缩写 | 资源作用 |
---|---|---|
pods | po | 装载容器 |
Pod资源控制器:
资源名称 | 缩写 | 资源作用 |
---|---|---|
replicationcontrollers | rc | 控制Pod资源 |
replicasets | rs | 控制Pod资源 |
deployments | ds | 控制Pod资源 |
daemonsets | ds | 控制Pod资源 |
jobs | 控制Pod资源 | |
cronjobs | cj | 控制Pod资源 |
horizontalpodautoscalers | hpa | 控制Pod资源 |
statefulsets | sts | 控制Pod资源 |
服务发现资源:
资源名称 | 缩写 | 资源作用 |
---|---|---|
services | svc | 统一Pod对外接口 |
ingress | ing | 统一Pod对外接口 |
存储资源:
资源名称 | 缩写 | 资源作用 |
---|---|---|
volumeattachments | 存储 | |
persistentvolumes | pv | 存储 |
persistentvolumeclaims | pvc | 存储 |
配置资源:
资源名称 | 缩写 | 资源作用 |
---|---|---|
configmaps | cm | 配置 |
secrets | 配置 |
下面以一个namespace、pod的创建和删除简单演示下列命令的使用:
- # 创建一个namespace
- kubectl create namespace dev
-
- # 获取namesapce
- kubectl get ns
-
- # 在dev namespace下创建并运行一个nginxPod
- kubectl run pod --image=nginx -n dev
-
- # 查看新建的Pod (只要不是对default命名空间下资源的操作都需要加上-n参数,指明操作的命名空间)
- Kubectl get pod -n dev
- NAME READY STATUS RESTARTS AGE
- pod-864f9875b9-2vdfq 1/1 Running 0 60s
-
- # 删除指定Pod
- kubectl delete pods pod-864f9875b9-2vdfq -n dev
-
- # 删除指定namespace
- kubectl delete ns dev
命令式对象配置就是使用命令配合配置文件一起来操作Kubernetes资源。
(1)创建一个nginxpod.yaml,内容如下:
- apiVersion: v1
- kind: Namespace
- metadata:
- name: dev
-
- ---
-
- apiVersion: v1
- kind: Pod
- metadata:
- name: nginxpod
- namespace: dev
- spec:
- containers:
- - name: nginx-containers
- image: nginx:1.17.1
(2)执行create命令,创建资源:
- [root@node01 ~]# kubectl create -f nginxpod.yaml
- namespace/dev created
- pod/nginxpod created
此时发现创建了两个资源,分别是namespace和pod
(3)执行get命令查看资源:
- [root@node01 ~]# kubectl get -f nginxpod.yaml
- NAME STATUS AGE
- namespace/dev Active 2m56s
-
- NAME READY STATUS RESTARTS AGE
- pod/nginxpod 1/1 Running 0 2m55s
(4)删除资源:
- [root@node01 ~]# kubectl delete -f nginxpod.yaml
- namespace "dev" deleted
- pod "nginxpod" deleted
声明式对象配置与命令式对象配置很相似,但是它只有一个命令apply,主要用于资源的创建与更新。
- # 首次执行一次kubectl apply -f nginxpod.yaml文件,代表创建资源
- [root@node01 ~]# kubectl apply -f nginxpod.yaml
- namespace/dev created
- pod/nginxpod created
-
- # 第二次执行kubectl apply -f nginxpod.yaml文件,代表更新配置,但是由于配置文件内容并没有改变,所以会显示
- namespace/dev unchanged
- pod/nginxpod unchanged
其实声明式对象配置就是使用apply描述一个资源的最终状态(在yaml文件中定义)。如果描述的资源不存在,则创建该资源;如果描述的资源存在,则尝试更新该资源。
默认情况下只能在Master节点上运行kubectl命令,我们需要将Master节点~/.kube
文件夹复制到Node节点上才能在Node节点上运行该命令:
- # 将家目录下,kube文件夹拷贝到node02节点的家目录下(这里写node02是因为hosts中配置node02的IP)
- scp ~/.kube/ node02:~/
Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。
默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的“组”,以方便不同的组的资源进行隔离使用和管理。
可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。
在集群启动后,会有几个默认的namespace:
- [root@node01 ~]# kubectl get namespace
- NAME STATUS AGE
- default Active 18h #所有未指定namespace的资源都会被分配到default命名空间中
- kube-node-lease Active 18h #集群节点间的心跳维护,从v1.13开始引入
- kube-public Active 18h #此命名空间下的资源可以被所有人访问(包括未认证用户)
- kube-system Active 18h #所有由Kubernetes系统创建的资源都处于这个命名空间
下面来看Namespace资源的具体操作:
查看namespace:
- kubectl get namespace
- kubectl get ns
-
- #查看指定Namespace
- kubectl get ns [名称]
-
- #指定输出格式
- kubectl get ns [名称] -o [wide|json|yaml]
-
- #查看namespace详情
- kubectl describe ns [名称]
-
- [root@node01 ~]# kubectl describe ns kube-system
- Name: kube-system
- Labels:
- Annotations:
- Status: Active #Active 表示命名空间正在使用,Terminating表示正在删除该命名空间
-
- No resource quota.#resource quota 针对命名空间做的资源限制
-
- No LimitRange resource. #LimitRange针对命名空间中的每个组件做资源限制
新增namespace:kubectl create ns [名称]
删除namespace:kubectl delete ns [名称]
声明式配置:
首先准备一个yaml文件:ns-dev.yaml
apiVersion: v1
kind: Namespace
metadata:
name: dev
Pod是kubernetes集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于Pod中Pod可以认为是容器的封装,一个Pod中可以存在一个或者多个容器。
Kubernetes在集群启动之后,集群中的各个组件也都是以Pod方式运行的。
创建并运行:
Kubernetes没有提供单独运行Pod的命令,都是通过Pod控制器来实现的
- # 命令格式:kubectl run [pod控制器名称] [参数]
- # --image 镜像版本
- # --port 暴露端口
- # --namespace 命名空间
-
- kubectl run nginx --image=nginx:1.17.1 --port=80 --namespace=dev
查看Pod信息:
查看Pod基本信息:kubectl get pod -n dev
查看Pod详细信息:kubectl describe pod nginx-64777cd554-8rdmn -n dev
访问Pod:
获取IP:kubectl get pod -n dev -o wide
访问Pod:curl 10.244.2.5:80
删除Pod:
删除指定Pod:kubectl delete pod nginx-64777cd554-8rdmn -n dev
删除Pod控制器:kubectl delete deployment nginx -n dev
Label是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对它们进行区分和选择。Label的特点:
可以通过Label实现资源的多维度分组,以便方便灵活地进行资源分配、调度、配置、部署等管理工作。
一些常用的Label示例如下:
- 版本标签:“version”:”release”,“version”:”stable”
- 环境标签:“env”:”dev”,“env”:”test”
标签定义完毕之后,还要考虑到标签的选择,这就是Label Selector。Label Selector用于查询和筛选拥有某些标签的资源对象。
为Pod打标签:
- # 命令格式:kubectl label pod [pod名称] [-n 命名空间] [key=value]
- [root@node01 ~]# kubectl label pod nginx-64777cd554-vblj9 -n dev version=1.0
- pod/nginx-64777cd554-vblj9 labeled
查看Pod上的标签:
- [root@node01 ~]# kubectl get pod -n dev --show-labels
- NAME READY STATUS RESTARTS AGE LABELS
- nginx-64777cd554-vblj9 1/1 Running 0 6m7s pod-template-hash=64777cd554,run=nginx,version=1.0
更新标签:
kubectl label pod nginx-64777cd554-vblj9 -n dev version=1.0 --overwrite
删除标签:
- # 在key后面紧跟一个-号即可删除标签
- [root@node01 ~]# kubectl label pod nginx-64777cd554-vblj9 -n dev version-
- pod/nginx-64777cd554-vblj9 labeled
通过标签筛选(Label Selector):
通过Label进行筛选我们需要使用到Label Selector,当前有两种Label Selector:
name=slave
:选择所有Label信息中包含key=“name”且value=“slave”的资源对象。
env!=production
:选择所有Label信息中存在key为“env”,但是这个Label的value不等于production的资源对象。
name in (master,slave)
env not in (production,test)
标签选择器可以同时使用多个,多个Label Selector之间使用逗号分割:
name=slave,env not in (production,test)
- #使用-l参数指定标签信息进行筛选
- kubel get pod -l "version=1.0" -n dev --show-labels
-
- #删除指定标签的Pod
- [root@node01 ~]# kubectl delete pod -l env=test -n dev
- pod "nginx-64777cd554-vblj9" deleted
- pod "nginx1-79d7bd676b-4tjpt" deleted
声明式配置:
- apiVersion: apps/v1
- kind: Pod
- metadata:
- name: nginx
- namespace: dev
- labels:
- version: "3.0"
- env: "test"
虽然每个Pod都会分配一个单独的IP,然而却存在如下两个问题:
Pod IP会随着Pod的重建而发生变化
Pod IP仅仅是集群内可见的虚拟IP,外部无法访问
这样外部如果需要访问这个服务就会非常困难。因此Kubernetes设计了Service来解决这个问题。
Service可以看做是一组同类Pod对外提供的访问接口。接祖Service,应用可以方便地实现服务发现和负载均衡。
创建Service:
- #命令格式:kubectl expose deployment [Pod控制器名称] --name=[service名称] --type-ClusterIP --port=[service端口] --target-port=[目标端口] -n [命名空间]
- [root@node01 ~]# kubectl expose deployment nginx --name=svc-nginx --type=ClusterIP --port=80 --target-port=80 -n dev
- service/svc-nginx exposed
查看Service:
- [root@node01 ~]# kubectl get service -n dev
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
- svc-nginx ClusterIP 10.109.216.54
80/TCP 37s
删除Service:
- [root@node01 ~]# kubectl delete service svc-nginx -n dev
- service "svc-nginx" deleted
声明式配置:
- apiVersion: apps/v1
- kind: Service
- metadata:
- name: svc-nginx
- namespace: dev
- spec:
- clusterIP: 10.109.179.231 #IP可省略,省略后会自动申请
- ports:
- - port: 80
- protocol: TCP
- targetPort: 80
- selector:
- run: nginx
- type: ClusterIP
Kubernetes作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。所谓的安全性其实就是保证对Kubernetes的各种客户端进行认证和鉴权操作。
客户端:
在Kubernetes集群中,客户端通常有两类:
认证、授权与准入控制:
ApiServer是访问及管理资源对象的唯一入口。任何一个请求访问ApiServer,都要经过下面三个流程:
Kubernetes集群安全的最关键点在于如何识别并认证客户端身份,它提供了3种客户端身份认证方式:
这种认证方式是把“用户名:密码”用BASE64算法进行编码后的字符串放在HTTP请求中的Header Authorization域里发送给服务端。服务端收到后进行解码,获取用户名及密码,然后进行用户身份认证的过程。
这种认证方式是用一个很长的难以被模仿的字符串--Token来表明客户身份的一种方式。每个Token对应一个用户名,当客户端发起API调用请求时,需要在HTTP Header里放入Token,API Server接到Token后会跟服务器中保存的token进行比对,然后进行用户身份认证的过程。
这种认证方式是安全性最高的一种方式,但是同时也是操作起来最麻烦的一种方式。
授权发生在认证成功之后,通过认证就可以知道请求用户是谁, 然后Kubernetes会根据事先定义的授权策略来决定用户是否有权限访问,这个过程就称为授权。
每个发送到ApiServer的请求都带上了用户和资源的信息:比如发送请求的用户、请求的路径、请求的动作等,授权就是根据这些信息和授权策略进行比较,如果符合策略,则认为授权通过,否则会返回错误。
API Server目前支持以下几种授权策略:
RBAC(Role-Based Access Control) 基于角色的访问控制,主要是在描述一件事情:给哪些对象授予了哪些权限
其中涉及到了下面几个概念:
RBAC引入了4个顶级资源对象:
Role、ClusterRole:
一个角色就是一组权限的集合,这里的权限都是许可形式的(白名单)。
- # Role只能对命名空间内的资源进行授权,需要指定nameapce
- kind: Role
- apiVersion: rbac.authorization.k8s.io/v1beta1
- metadata:
- namespace: dev
- name: authorization-role
- rules:
- - apiGroups: [""] # 支持的API组列表,"" 空字符串,表示核心API群
- resources: ["pods"] # 支持的资源对象列表
- verbs: ["get", "watch", "list"] # 允许的对资源对象的操作方法列表
- # ClusterRole可以对集群范围内资源、跨namespaces的范围资源、非资源类型进行授权
- kind: ClusterRole
- apiVersion: rbac.authorization.k8s.io/v1beta1
- metadata:
- name: authorization-clusterrole
- rules:
- - apiGroups: [""]
- resources: ["pods"]
- verbs: ["get", "watch", "list"]
需要详细说明的是,rules中的参数:
apiGroups: 支持的API组列表
"","apps", "autoscaling", "batch"
resources:支持的资源对象列表
"services", "endpoints", "pods","secrets","configmaps","crontabs","deployments","jobs",
"nodes","rolebindings","clusterroles","daemonsets","replicasets","statefulsets",
"horizontalpodautoscalers","replicationcontrollers","cronjobs"
verbs:对资源对象的操作方法列表
"get", "list", "watch", "create", "update", "patch", "delete", "exec"
RoleBinding、ClusterRoleBinding:
角色绑定用来把一个角色绑定到一个目标对象上,绑定目标可以是User、Group或者ServiceAccount。
# RoleBinding可以将同一namespace中的subject绑定到某个Role下,则此subject即具有该Role定义的权限
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: authorization-role-binding
namespace: dev
subjects:
- kind: User
name: heima
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: authorization-role
apiGroup: rbac.authorization.k8s.io
# ClusterRoleBinding在整个集群级别和所有namespaces将特定的subject与ClusterRole绑定,授予权限
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: authorization-clusterrole-binding
subjects:
- kind: User
name: heima
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: authorization-clusterrole
apiGroup: rbac.authorization.k8s.io
RoleBinding引用ClusterRole进行授权:
RoleBinding可以引用ClusterRole,对属于同一命名空间内ClusterRole定义的资源主体进行授权。
一种很常用的做法就是,集群管理员为集群范围预定义好一组角色(ClusterRole),然后在多个命名空间中重复使用这些ClusterRole。这样可以大幅提高授权管理工作效率,也使得各个命名空间下的基础性授权规则与使用体验保持一致。
# 虽然authorization-clusterrole是一个集群角色,但是因为使用了RoleBinding
# 所以heima只能读取dev命名空间中的资源
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: authorization-role-binding-ns
namespace: dev
subjects:
- kind: User
name: heima
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: authorization-clusterrole
apiGroup: rbac.authorization.k8s.io
通过了前面的认证和授权之后,还需要经过准入控制处理通过之后,apiserver才会处理这个请求。
准入控制是一个可配置的控制器列表,可以通过在Api-Server上通过命令行设置选择执行哪些准入控制器:
- --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,
- DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds
只有当所有的准入控制器都检查通过之后,apiserver才执行该请求,否则返回拒绝。
当前可配置的Admission Control准入控制如下:
study-notes/工具使用/Kubernetes/subfile at master · bigcoder84/study-notes · GitHub