目录
k8s是什么
集群管理
master
node
k8s资源对象
namespace
容器
初始化容器 initContainers
Pod
Pod Volume
Endpoints
Service
Headless Service
service对象的type取值
从k8s集群外部访问Service
Deployment
Deployment对象参数说明
ReplicaSet
ingress
有状态服务与无状态服务
什么是无状态服务和有状态服务及区别
StatefulSet
Kubernetes Operator
批处理应用--Job
Job
CronJob
k8s通用配置
Label 与标签选择器
ConfigMap
业务场景
传统解决方案
k8s解决方案
Secret
自动伸缩
自动伸缩概念
HPA( Horizontal Pod Autoscaler)水平伸缩
VPA( Vertical Pod Autoscaler )垂直伸缩
Kubernetes 集群自动缩放器(CA)
存储类对象
概述
pod中如何挂载存储卷
VOL_TYPE举例:
PV自动创建实现原理
Dynamic Volume Provisioning
Background
Enabling Dynamic Provisioning
安全类对象
Secret
k8s支持的用户类型
ServiceAccout
ServiceAccount结构
Service Account准入控制器
ServiceAcount访问API Server认证过程
自定义具备cluster-admin角色的ServiceAccount并绑定到pod
角色权限相关对象
Subjects
Role/RoleBinding
ClusterRole/ClusterRoleBinding
k8s内置角色
k8s 内置cluster role(集群角色) cluster-admin、admin、 edit、 view的作用范围及区别_51CTO博客_k8s cluster api
NetworkPolicy
kublet命令
问题
如何部署一个服务
术语
Master 指的是集群的控制节点 在每个 Kubemetes 集群中都需要有一个或 组被称为
另外,在 Master 上通常还需要部署 etcd 服务。
Taint Nod和Toleration Pod:当需要节点需要运维、下线或升级时,需剔除节点上运行的服务,并防止新的pod被调度到该节点,可以通过给节点打上一种特殊的标签---污点(Taint)来实现。node一旦打了该标签,新的容器被不会被调度到该Node,但Pod可以定义可以 (短期)容忍 (Toleration )某种污点的存在,这些Pod可以继续将其调度到该 Node。Taint和Toleration 这两个术语属于Kubernetes 调度相关的重要术语和概念。
pod中包含了业务容器, Pod IP 加上这里的容器端口 (containerPort)组成了一个新的概念一 Endpoint, 代表此 Pod 里的 一个服务进程的对外通信地址。
相同的业务(pod)可以被k8s调度运行在多个主机上,形成服务集群,这些服务列表被封装在EndPoints对象中。
Service 的服务进程通常基于 Socket 通信方式对外提供服务,比如 Redis Memcached MySQL Web Server ,或者是实现了某个具体业务的特定 TCP Server 进程 。
虽然一个 Service 通常由多个相关的服务进程提供服务 每个服务进程都有一个独立的 Endpoint ( IP+Port ) 访问点,但 Kubernetes 能够让我们通过 service (ClusterIP+Service Port )连接指定的服务。
在创建Service定义中,若不指定type,则默认为ClusterIP类型的Service,这样的Service创建后,k8s会自动为其分配一个ClusterIP,Service 本身一 创建就不再变化,且在service的整个生命周期内,ClusterIP(若存在)不会改变。
ClusterIP 地址是一种虚拟 IP 地址,它有以下特点:
k8s内部的服务发现机制
在k8s内部,除了可以通过Service的ClusterIP访问Service,更希望通过service name而不是ClusterIP访问servie,因此需要k8s提供服务发现机制。
k8s通过Add-On增值包的方式引入kube-dns,为每一个Service名称生成一条dns记录,name是service名称,port为该service的port。 定义Service时若不指定port,k8s会自动为其创建随机端口,推荐让k8s自动为其创建port。
k8s内部的负载均衡实现机制
k8s在集群的每一个节点上上都运行了一套全局的虚拟负载均衡器,其实现原理是通过cube-proxy为集群内的所有service,添加并自动实时依据最新的Service Endpoint列表更新iptabless规则,结合ipvs机制,把对 Service 的请求转发到其后端对应的某个 Pod 实例上,并在内部实现服务的负载均衡与会话保待机制。
从实现原理上可以看出,k8s是交友位于请求发起端的iptables规则+ipvs实现了负载均衡能力,因此是一种客户端的负载均衡(而非将负载均衡作为一个独立的服务组件)。
除了正常的 service ,还有一种特殊的 Service--Headless Service ,只要在Service的定义中设置了clusterIP:none就定义了一个Headless Service, 它与普通Service的关键区别在于它没有ClusterIP 地址,如果解析Headless Service 的DNS域名,则返回的是该Service 对应的全部 Pod的Endpoint列表,这意味着客户端是直接与后端的Pod建立 TCP/IP连接进行通信的,没有通过虚拟ClusterIP 地址进行转发,因此通信性能最高,等同于”原生网络通信”。
Deployment用于执行pod的线上部署操作。通过Deployment可以定义哪个pod需要部署,部署几份实例,以及pod所需的运行的环境、配置信息、资源,并可以定义系统资源(CPU、内存)的配额。定义Deployment时,可同时定义Pod。
Kubemetes 集群中,只需为需要扩容的 Service 关联的 Pod 创建 Deployment
象,服务扩容以至服务升级等令人头疼的问题就都迎刃而解了 在一个 Deployment 定义
文件中包括以下 个关键信息
在创建好 Deployment 之后, Kubemetes 会根据这一定义创建符合要求的 Pod, 并且通
过在 Dep loyment 中定义的 Label 筛选出对应的 Pod 实例并实时监控其状态和数量 如果
实例数量少于定义的副本数量,则会根据在 Dep loyment 对象中定义的 Pod 模板创建一个
新的 Pod, 然后将此 Pod 调度到合适的 Node 上启动运行,直到 Pod 实例的数噩达到预定
目标。这个过程完全是自动化的,无须人工干预 有了 Deployment, 服务扩容就变成一个
纯粹的简单数字游戏了,只需修改 Deployment 中的副 本数撮即可 后续的服务升级也将
通过修改 Deployment 来自动完成。
只有一个 Pod 副本实例时,我们是否也需要 Deployment 来自动创 Pod ?在大多数情况下,这个答案是"需要“。这是因为 Deployment 除自动创建 Pod 副本外,还有一个很重要的特性:自动控制 举个例子,如果 Pod 所在的节点发生岩机事件, Kubernetes会第一时间观察到这个故障,并自动创建一个新的 Pod 象,将其调度到其他合适的节点上, Kubernetes 会实 时监控集群中目标 Pod 的副本数氮,并且尽力与 Deployment 声明的replicas 数量保持一致。
参见:
k8s-deployment常见参数说明 | 努力挣扎的生活
Deployment配置对象可配置的参数包括:
#容器挂载
volumeMounts:
#容器挂载内部目录
- mountPath: /usr/share/nginx/html/
name: nginx-dp
#集群挂载信息
volumes:
#与容器volumeMounts部分的name相同
- name: nginx-dp
#指定pvc类型
persistentVolumeClaim:
#指定pvc名
claimName: nginx-dp-pvc
Deployment 资源对象其实与 replicaSet 资源对象密切相关 k8s内部会根据Deployment 对象自动创建相关联的 plicaSet 对象,通过以下命令,我们可以看到它的命名与 Deployment 的名称有对应关系。
通过ingress对象,可以将多个k8s内部的service,以http地址的方式暴露到集群之外。不同的service的http uri不同。如外部访问http://mycompany.com/articile,就会路由到k8s内部的article服务上,当访问http://mycompany.com/vote,就会路由到k8s内部的vote服务上。
ingress对象配置示例:
#外部访问foo.bar.com时,路由到servicel
#访问bar.foo.com时,路由到service2
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: servicel
servicePort: 80
- host: bar.foo.com
http:
paths:
- backend:
serviceName: service2
servicePort: 80
ingress实现原理
k8s提供了IngressController,以DaemonSet方式,部署在k8s的所有节点上。
IngressController内置了nginx,作为反向代理服务器。
同时,还内置了一个对应的controller,通过与k8s api交互,实时、动态的去感知集群中ingress规则变化,根据最新的ingress定义,获取对应的Service和对应Endpoint列表(Endpoint列表在nginx中生成upstream),生成最新的nginx的配置,再写到nginx pod的nginx.conf,最后reload一下。
注意:写入nginx.conf的不是service地址,而是service backend的pod地址列表(nginx upstream片段),避免在service上增加一层负载均衡转发。
ingress对象定义的只是逻辑映射关系规则,IngerssController解析ingress时,并不是将各个service放到nginx的同一个upstream中,而是会从中提取出每一个service对应的Endpoint列表,为每一个service其生成访问的uri,并将其Endpoint列表放到upstream中。
参见:Ingress的概念和原理_m0_46172263的博客-CSDN博客_ingress
https://www.jianshu.com/p/1abdbe8e557d
对比维度 | 有状态服务 | 无状态服务 |
---|---|---|
配管k8s对象 | StatefulSet(对应无状态服务的Deployment)、Headless Service、Kubernete Operator | RC、Deployment、DaemonSet和Job |
唯一性 | 唯一性。 有状态服务中的每一个pod的业务角色不同,因此集群中的每个Pod都需要具有唯一、稳定的网络标识。StatefulSet里的每个Pod都有稳定、唯一的网络标识,可以用来发现集群内的其他成员。唯一性体现在: 1. 每个pod都有唯一名称:StatefulSet-序号(从0开始),如mySql-0 2. 每个pod都有唯一DNS域名:pod名称.Headless service名称,如mySql-0-mySqlService。(StatefulSet要结合Headdless Service使用,在StatefulSet定义中声明它属于哪个Headless Service,在此基础上为每一个控制的pod实例都创建了一个唯一的DNS域名) |
随机性。 |
稳定性 | 稳定。 Pod主机名,DNS地址、挂载的PV、不会随着Pod被重新调度而发生变化. |
不稳定。 pod被重新启动调度后,它的名称与IP都会发生变化 |
顺序性 | 有序性 StatefulSet控制的Pod副本的启、停、更新、删除顺序是受控的,操作第n个Pod时,前n-1个Pod已经时运行且准备好的状态 |
无序性 启动、更新、停止、删除都没有顺序要求 |
状态特性 | 有状态。 有状态服务中的每一个pod都是有状态的、各自运行不同的功能,各自在其本地独立存储不同的数据、通常会持久化数据到永久存储中。每个实例对于同一个用户请求的响应结果不一致。 如果停止集群中的某个pod服务、或对应的存储发生损坏,则业务功能会受损甚至崩溃。 |
无状态。 无状态服务不会在本地(要么共享存储、要么无存储)存储持久化数据.多个服务实例对于同一个用户请求的响应结果是完全一致的.这种多服务实例之间是没有依赖关系, 某个pod故障后,随机找一个可用的节点重新调度一个新的pod即可。 |
存储特性 | 稳定的持久化存储: StatefulSet里的Pod采用稳定的持久化存储卷,通过PV/PVC来实现,删除Pod时默认不会删除与StatefulSet相关的存储卷(为了保证数据的安全) Pod被重新调度后,仍然能挂载原有的PV,从而保证了数据的完整性和一致性. |
无存储或共享存储 |
集群规模 | 有状态服务中的集群规模是比较固定的,不能随意伸缩,需人为干预,在伸缩前后需要做大量工作。 |
业务规模可以根据访问压力自动伸缩。 |
举例 | 主从架构功能的服务,如数据库、Redis主从、 nginx、zookeeper、kafka | 比如web应用,在k8s控制器 中动态启停无状态服务的pod并不会对其它的pod产生影响. |
无状态服务与有状态服务存储对比:前者为共享存储,后者为独立存储。
用于执行一次性任务。举例如下(计算圆周率):(注意apiVersion、kind、completions、parallelism几个参数)。
apiVersion:batch/vl
kind:Job
metadata:
name:pi
spec:
template:
spec:
containers:
- name: pi
image:perl
command:["perl ", "-Mbignum=bpi ", "-wle ", "print bpi (10:J) " J
restartPolicy: Never
#两个控制并发数的参数
#表示需要运行任务数的总数
completions:5
#并发运行的个数
parallelism: 1
Label 通常在资源对象定义时确定,也可以在对象创建后动态添加或者删除。我们可以通过给指定的资湃对象捆绑一个或多个不同的 Labe] 来实现多维度的资源分组管理功能,以便灵活、方便地进行资源分配、调度 、配置、部署等管理工作,例如,部署不同版本的应用到不同的环境中,以及监控 分析应用(日志记录、监控、告警)等 一些常用的 Label 示例如下:
给某 资源对象定义一个 Label, 就相当于给它打了一个标签,随后可以通过 Label Selector (标签选择器)查询和筛选拥有某些 Label 的资源对象, Kubemetes 通过这种方式实现了类似 SQL 的简单又通用的对象查询机制 Label Selector 可以被类比为 SQL 语句中where 查询条件,例如, “name=redis-slave" 这个 Label Selector 作用于 Pod 时,可以被类比为 “select* from pod where pod's name='redis-slave'" 这样的语句 。
当前有两种 LabelSelector 表达式:基于等式的 (Equality-based) Selector 表达式和基于集合的 Set-based)Selector 表达式;
基于等式的 Selector 表达式采用等式类表达式匹配标签,下面是一些具体的例子
基于集合的 Selector 表达式则使用集合操作类表达式匹配标签,下面是一些具体的例
子。
可以通过多个 Label Selector 表达式的组合来实现复杂的条件选择 ,多个表达式之间用“,”进行分隔即可,几个条件之间是 “AND" 的关系,即同时满足多个条件,比如下面的例子:
narne=redis-slave,env!=preduction
name notin (php-frontend),env !=production
下面是一个具体的例子。
apiVersion : apps/ v l
kind: Dep.l:oyment
metadata:
name : frontend
spec :
replicas : 1
selector:
matchLabels :
tier : frontend
matchExpressions:
{key: tier, operator : In , values : [frontend]}
template :
...
每一个应用都需要一个静态配置文件提供启动参数,尤其是一个分布式应用,多个副本部署在不同的机器上,如何方便地分发它们的配置?
很多多分布式系统本身都有一个配置中心组件来解决这个问题。但配置中心通常会引入新的API,从而导致应用的耦合和侵入。
Kubernetes则采用了一种简单的方案,即ConfigMap来规避传统解决方案的问题,如图所示,具体做法如下:
Secret也用于解决应用配置的问题, 不过它解决的是对敏感信息的配置问题,比如数据库的用户名和密码、 应用的数字证书、 Token、 SSH密钥及其他需要保密的敏感配置 。对于这类敏感信息,我们可以创建一个Secret 对象,然后被Pod引用 。 Secret 中的数据要求以 BASE64编码格式存放。注意,BASE64编码并不是加密的。
在Kubernetes 1. 7版本以后, Secret中的数据才可以以加密的形式进行保存,更加安全。
什么是弹性伸缩?
弹性伸缩概述
Deployment来控制Pod,若手工伸缩,则执行命令kubectl scale命令来实现Pod扩容或缩容。
运维目标---自动化、智能化:k8s希望能动态追踪分析指定Deployment控制的所有目标Pod的负载变化情况,来确定是否需要有针对性地调整目标Pod的副本数量,做到无人值守,实现自动运维。
为此,k8s提供了HPA对象。可以将HPA理解为Pod横向自动扩容,即自动控制Pod数量的增加或减少。Kubernetes内置了基于Pod 的CPU利用率进行自动扩缩容的机制,应用开发者也可以自定义度量指标如每秒请求数, 来实现自定义的 HPA功能。
下面 是一个HPA定义的例子(副本数量限定在1-0范围,pod扩缩容的依据是CPU使用率超过了90%):
HPA问题:需要运行基准测试任务来确定 CPU 和内存请求的合适值,这通常不易确定。一是需要一定的测试,有一定的工作量,二是可能不具备相对应的投产环境(如CPU、内存、网络、存储等)条件,无法得到一个合理的基准值。
解决办法:VPA。
HPA设置的资源阈值设置多少通常不易确定,因为实际运行过程中会动态变化(比如预估1000人访问,实际可能很多或很少,如高峰时段和闲暇时不一样),VPA是根据pod在投产环境运行过程中实际占用的资源量,自动推测并设置Pod合理的CPU和内存的需求指标(在定义Deployment时可以设置请求的最小和最大资源,有了VPA,),从而更加精确地调度Pod,实现整体上节省集群资源的目标, 因为无须人为操作, 因此也进一步提升了运维自动化的水平。
VPA优势:
使用业务场景:我们从云厂商申请了1000核cpu,1T内存搭建k8s集群,随着部署的应用增多,当5个节点的资源达到瓶颈而出现pending pod时,希望云厂商能自动添加新的资源进来。
集群自动伸缩器(CA)基于待处理(状态:pedding)的pod扩展集群节点。它会定期检查是否有任何待处理的pod,如果需要更多的资源,并且扩展的集群仍然在用户提供的约束范围内,则会增加集群的大小。CA与云供应商接口,请求更多节点或释放空闲节点。它与GCP、AWS和Azure兼容。版本1.0(GA)与Kubernetes 1.8一起发布。
参见:
Kubernetes-自动扩展器HPA、VPA、CA_SRE运维充电站的博客-CSDN博客_hpa vpa
目前k8s支持的存储卷可以大致分为一下几类,它们各自有着不同的实现插件:
通常k8s内置的存储卷插件可以归类为In-Tree类型,它们通k8s源码一起发布迭代,而由存储厂商借助CSI接口扩展的独立于k8s源码的插件统称为Out-of-Tree类型,集群管理员可以根据需要创建自定义的扩展插件,CSI是比较常用的实现方式。目前k8s已经开始逐步将In-Tree类型的存储卷插件迁移到CSI,所以建议在新环境中使用CSI。
在pod.spec中声明要挂载的存储卷,然后在container中将这些存储卷挂载到指定的目录。
spec:
#声明要挂载的存储卷(可以有多个)
volumes:
- name# 存储卷名称标识,仅可使用DNS标签格式的字符,在当前Pod中必须唯一
VOL_TYPE
containers:
- name: …
image: …#将pod.spec中声明的存储卷(通过name关联)挂载到mountPath 指定的目录
volumeMounts:
- name# 要挂载的存储卷的名称,必须匹配存储卷列表中某项的定义
mountPath# 容器文件系统上的挂载点路径
readOnly# 是否挂载为只读模式,默认为“否”
subPath# 挂载存储卷上的一个子目录至指定的挂载点
subPathExpr# 挂载由指定的模式匹配到的存储卷的文件或目录至挂载点
emptyDir
kind: Pod
spec:#声明要挂载的存储卷(可以有多个)
volumes:
- name: config-file-store
emptyDir:
medium: Memory #如果要使用磁盘就使用""就可以了,但是这里只会在节点上创建一个临时存储目录
sizeLimit: 16Mi#由initContainer加载数据(比如配置信息)到挂载点,其它容器读取数据
initContainers:
- name:configInitvolumeMounts:
- name: config-file-store
mountPath: /data
containers:
- name: envoy
volumeMounts:
- name: config-file-store
mountPath: /etc/envoy
readOnly: true
NFS方式
kind: Pod
spec:
volumes:
- name: redisdata
nfs:
server: 192.168.8.30
path: /data/redis
readOnly: false
containers:
- name: redis
volumeMounts:
- mountPath: /data
name: redisdata
Persistent Volume(PV)方式
PV方式实现原理如下:
手动创建PV
在上述第1步,需要集群管理员手动方式预创建好一批PV:先由集群管理员根据配置的各类存储(如NFS、glusterFS),并结合k8s上部署的各类业务的存储场景,提前手工创建一系列对应不同存储类型、不同容量大小和访问模式的PV,一个PV对象相当于一个指定大小的存储卷。
PV手动创建的问题:
在一个大规模的Kubernetes集群里,可能有成千上万个PVC,这就意味着运维人员必须事先手工创建出这么多个PV,此外,随着项目的需要,会有新的PVC不断被提交,那么运维人员就需要不断的添加新的,满足要求的PV,否则新的Pod就会因为PVC绑定不到PV而导致创建失败。而且通过 PVC 请求到一定的存储空间也很有可能不足以满足应用对于存储设备的各种需求。
而且不同的应用程序对于存储性能的要求可能也不尽相同,比如读写速度、并发性能等。
自动创建PV
为了解决PV手动创建的问题,Kubernetes 引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用户根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。
自动创建PV方式只需要步骤2和步骤3即可,不需要第1步,因为k8s会自动根据PVC的要求创建PV。其实现原理见下一节描述。
PV方式举例,实施步骤如下:
1. 定义存储卷PV(自动挂载不需要这一步,PV是由k8s自动创建,但涉及的PV的概念、PV的配置信息都相同):
PV是对底层网络共享存储的抽象,将共享存储定义为一种“资源”,好比Node也是容器应用能够消费的资源。PV由管理员建立和配置,与共享存储的具体实现直接相关。
PV做为存储资源,主要包括存储能力、访问模式、存储类型、回收策略、后端存储类型等关键信息的设置。集群管理员可以为不同存储卷(如nfs、glusterFS)在k8s上创建多个pv(每一种存储卷可以创建多个PV)。
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-1g-pvspec:
storageClassName: nfs //存储类别
accessModes: #访问模式
- ReadWriteManypersistentVolumeReclaimPolicy: Recycle #回收策略
capacity: #存储容量
storage: 1Ginfs: #具体存储卷的配置信息
path: /root/zwf/share
server: 10.64.2.153
kubernetes支持以下PV类型:
访问模式(Access Modes): 用于描述应用对存储资源的访问权限,包括
PV生命周期:
回收策略:
2. 业务用户创建PVC
PVC由业务用户根据业务需求进行创建,是用户对存储资源的一个“申请”,主要包括请求的存储空间大小、访问模式、PV选择条件、存储类别(storageClassName)等信息的设置。
就像Pod消费Node资源同样,PVC可以消费PV资源。k8s根据PVC中的条件(StorageClass、访问模式等)查找(若PV已创建)满足条件的PV或创建(若PV是自动创建)合适的PV绑定到该PVC上。
PVC与PV一一对应。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-static-pvcspec:
storageClassName: nfs #存储类别
accessModes: #访问模式
- ReadWriteManyresources:
requests:
storage: 1Gi
3. 将PVC绑定到pod
在pod.spec.volumes中将pvc绑定到pod中,然后挂载到pod的容器中。
apiVersion: apps/v1
kind: Deployment
spec:
template:
metadata:
labels:
app: nfs-pvc-demo
spec:
volumes:
- name: nfs-pvc-volume
persistentVolumeClaim:
claimName: nfs-pvc
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-pvc-volume
mountPath: /usr/share/nginx/html/static
参见:k8s中PV、PVC、StorageClass的简单理解_可乐多点冰的博客-CSDN博客_k8s pv
k8内置(也可以使用第三方)了存储卷插件 volume plugin 即PV制备器(provisioner),由PV制备器根据PVC的条件,自动在目标存储(如NFS存储、GlusterFS)上为其创建满足条件的、大小与PVC相匹配的PV。
PV制备器只是连接目标存储执行PV创建的可执行程序,具体要操作哪一个网络存储设备(如IP地址)、相关配置参数(如映射路径、回收策略等),则需要由StorageClass来配置。
StorageClass指定了操作的PV制备器及相关配置参数,是创建PV 的模板。
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
name: glusterfs
provisioner: kubernetes.io/glusterfs #指定存储插件PV制备器
allowVolumeExpansion: true
parameters://连接参数
resturl: "http://10.111.209.188:18080"
clusterid: "6fd6bf78b84315e12abcf8b6db6b1a40"
restauthenabled: "true"
restuser: "admin"
每个 StorageClass 都有一个制备器(Provisioner),用来决定使用哪个卷插件制备 PV。 该字段必须指定。
业务用户根据业务需要创建PVC,声明希望申请的存储空间大小(resources)以及基于哪个StorageClass(通过storageClassName参数指定,早期版本通过volume.beta.kubernetes.io/storage-class参数指定)来创建PV。
k8s会根据PVC查找StorageClass,然后结合PVC和StorageClass,调用PV制备器,由PV制备器来完成PV的创建以及与PVC的绑定工作。
StorageClass 对象的命名很重要,用户使用这个命名来请求生成一个特定的类。 当创建 StorageClass 对象时,管理员设置 StorageClass 对象的命名和其他参数,一旦创建了对象就不能再对其更新。
管理员可以为没有申请绑定到特定 StorageClass 的 PVC 指定一个默认的存储类。
参见:K8S 快速入门(十六)实战篇:StorageClass(存储类)_豪犬的博客-CSDN博客_storageclass
以下参见官网:Dynamic Volume Provisioning | Kubernetes
Dynamic volume provisioning allows storage volumes to be created on-demand. Without dynamic provisioning, cluster administrators have to manually make calls to their cloud or storage provider to create new storage volumes, and then create PersistentVolume objects to represent them in Kubernetes. The dynamic provisioning feature eliminates the need for cluster administrators to pre-provision storage. Instead, it automatically provisions storage when it is requested by users.
The implementation of dynamic volume provisioning is based on the API object StorageClass
from the API group storage.k8s.io
. A cluster administrator can define as many StorageClass
objects as needed, each specifying a volume plugin (aka provisioner) that provisions a volume and the set of parameters to pass to that provisioner when provisioning. A cluster administrator can define and expose multiple flavors of storage (from the same or different storage systems) within a cluster, each with a custom set of parameters. This design also ensures that end users don't have to worry about the complexity and nuances of how storage is provisioned, but still have the ability to select from multiple storage options.
More information on storage classes can be found here.
To enable dynamic provisioning, a cluster administrator needs to pre-create one or more StorageClass objects for users. StorageClass objects define which provisioner should be used and what parameters should be passed to that provisioner when dynamic provisioning is invoked. The name of a StorageClass object must be a valid DNS subdomain name.
参考:
k8s volume存储卷、PV、PVC和存储类_TimeRovers的博客-CSDN博客_pvc存储卷
k8s之PV、PVC和StorageClass_Crazy灬峰少的博客-CSDN博客_k8s pvc storageclass
k8s 网络持久化存储之StorageClass(如何一步步实现动态持久化存储) - 渡边灬 - 博客园
k8s存储卷_林凡修的博客-CSDN博客_k8s存储卷
secret定义了在etcd中保存的一些保密信息,可以是用户名密码,也可以是秘钥
一个Secret对象的内容包含namespace、token、ca.crt三部分。
各类资源都是一个个对象,访问(一般通过API Server)需要认证和授权。
api server是集群的入口,对于kunbernetes的api server 是肯定不能随便访问。所以必须需要一些认证信息。
当用户访问集群(例如使用kubectl命令)时,apiserver 会将您认证为一个特定的 User Account(目前通常是admin,除非您的系统管理员自定义了集群配置)。
Pod 容器中的进程也可以与 apiserver 联系。 当它们在联系 apiserver 的时候,它们会被认证为一个特定的 Service Account。
因此,k8s有两类用户:
Service account是为了方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的。它与User account不同
名为ServiceAccount的准入控制器实现了服务账户的自动化,它会为每个名称空间自动生成一个名称为default的默认资源对象
k8s会在每个namespace中自动创建一个名为default的service accountapiVersion: v1 kind: ServiceAccount metadata: name#资源名称 namespace #所属名称空间 autoMountServiceAccountToken #是否让POD自动挂载API令牌 secrets: <[]Object> #以该SA运行的POD要使用的secret对象所组成的列表 apiVersion: #Secret对象所属的API群组和版本,可以省略 kind: #资源类型,secret,可省略 name: #引用的secret对象名称 namespace: #secrets所属的名称空间 uid: #secret对象标识符 imagePullSecrets <[]object>: #引用用于下载容器镜像的Secret对象列表,用于pod在拉取容器镜像时,提前完成与镜像仓库的身份认证 name #
apiVersion: v1 kind: ServiceAccount metadata: name: test namespace: default autoMountServiceAccountToken: true
可以看出一个ServiceAccount可包含两部分:
(1)名为Tokens(上面ServiceAccount没有看到Tokens定义,而是secrets,莫非是新老版本语法问题?)的Secret用于访问API Server的Secret,也被称为Service Account Secret。
(2)名为imagePullSecrets的Secret用于下载容器镜像时的认证过程,通常镜像库运行在Insecure模式下,所以这个为空
(3)用户自定义的其他Secret,用于用户的进程。
如果一个Pod在定义时没有指定spec.serviceAccountName属性,则会默认赋值为default,可进行如下指定:
创建ServiceAccout
查看创建的Service Account:
针对Pod新增或修改的请求,Service Account准入控制器会验证Pod里的Service Account是否合法:
(1)如果spec.serviceAccount域没有被设置,则Kubernetes默认为其指定名称为default的Service Account。
apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- name: podtest
image: nginx
serviceAccountName: myServiceAccount
(2)如果指定了spec.serviceAccountName并且不是default,如果此Service Account不存在,则该Pod操作失败。
(3)如果在Pod中没有指定ImagePullSecrets,那么这个spec.serviceAccount域指定的Service Account的ImagePullSecrets会自动加入到该Pod中。
(4)给Pod添加一个特殊的Volume,在该Volume中包含ServiceAccount Secret中的Token,并将Volume挂载到Pod中所有容器的指定目录下(/var/run/secrets/kubernetes.io/serviceaccount),该目录下的内容即为展开的一个Secret(一个Secret包含namespace、ca.crt、tocken这三个部分,参见Secret章节)。
其中:
为了确保k8s集群的安全,API Server都会对客户端进行安全认证。在Pod中访问API Server服务时,是以Service方式访问名为Kubernetes这个服务的,是以类似HTTP Token的新认证方式:Service Account Auth,Pod在调用API Server时,在Http Header中传递了一个Token字符串,类似于之前提到的Http Token认证方式,有以下几处不同:
(1)Token内容来自Pod前述/var/run/secrets/kubernetes.io/serviceaccount路径下的token文件,由Kubernetes Controller进程用API Server的私钥(--service-account-private-zkey-file指定的私钥)签名指定生成的一个JWT Secret。
(2)通过HTTPS方式与API Server建立连接后,会用Pod里/var/run/secrets/kubernetes.io/serviceaccount/ca.crt 验证API Server发来的证书,验证是否为CA证书签名的合法证书。
(3)API Server收到Token后,采用自身私钥(service-accountkey-file指定,如果没有指定,则默认采用tls-private-key-file指定的参数)对Token进行合法性验证。
上面的认证过程中所涉及的Pod中的以下三个文件:token、ca.crt、namespace,三个文件都在/run/secrets/kubernetes.io/serviceaccount目录下
默认的default service account 仅只能获取当前Pod自身的相关属性,无法观察到其他名称空间Pod的相关属性信息。如果想要扩展Pod,假设有一个Pod需要用于管理其他Pod或者是其他资源对象,是无法通过自身的名称空间的default serviceaccount进行获取其他Pod的相关属性信息的,此时就需要进行手动创建一个serviceaccount,并在创建Pod时进行定义。
1. 创建名为admin的ServiceAccount :
2. 将ServiceAccount 赋予cluster-admin角色
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard-admin
labels:
k8s-app: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin
namespace: kube-system
3. 创建Pod,声明使用ServiceAcount admin,该pod就具备了cluster-admin权限。
参见:
k8s认证及ServiceAccount-十五 - 走看看
k8s之ServiceAccount_上古伪神的博客-CSDN博客_serviceaccount
局限于某个命名空间的角色及将角色赋予用户(组)由 Role和 RoleBinding对象定义,作用于整个 Kubernetes 集群范围内的角色及将角色赋予用户(组)则通过 ClusterRole 和ClusterRoleBinding对象定义
Subjects表示要授权的目标主体,可以是用户、用户组或Servcie Acount。
RoleBinding(角色绑定)把角色Role的权限映射到用户或者用户组,从而让用户继承角色Role在namespace中的权限。RoleBinding也可以引用ClusterRole,对属于同一命名空间内ClusterRole定义的资源主体进行授权。
《蹲坑学K8S》之22-2:Kubernetes授权机制
K8s中ServiceAccount、Role、RoleBinding、ClusterRole、ClusterRoleBinding之间的关系_-小末的博客-CSDN博客_rolebinding
NetworkPolicy用于设定pod之间、Pod 与其他网络端点之间的网络安全规则。
在安全领域,除了以上针对API Server访问安全相关的资源对象,还有一种特殊的资源对象NetworkPolicy (网络策略),它是网络安全相关的资源对象,用于解决用户应用之间的网络隔离和授权问题。 NetworkPolicy是一种关于 Pod 间相互通信,以及Pod与其他网络端点间相互通信的安全规则设定。
NetworkPolicy资源使用标签选择Pod,并定义选定Pod 所允许的通信规则。在默认情况下, Pod 间及 Pod 与其他网络端点间的访问是没有限制的,这假设了k8s集群被一个厂商(公司/租户)独占,其中部署的应用都是相互可信的,无须相互防范。但是,如果存在多个厂商共同使用一个k8s 集群的情况,则特别是在公有云环境中,不同厂商的应用要相互隔离以增加安全性,这就可以通过 NetworkPolicy 来实现了。
kubectl create serviceaccount admin #创建一个名为admin的sa
kubectl describe sa admin
kubectl explain sa
部署一个服务需要创建pod、Deployment、Service对象,实际只需要两步:
1. 创建服务的Deployment,Deployment通过template包含了pod的定义,pod的定义包括选择的容器定义(包括镜像、容器端口、环境变量传入等))。通过Deployment定义一组pod负载,用于批量部署一组相同的pod(或负载Endpoints),同时也定义了负载副本数。
2.创建mysql服务(Service,p10) ,Service为1定义的一组负载pod提供在集群内(p10)或集群外(p12 type:NodePort)访问的统一的访问入口(通过service名称或vip:vport访问)和负载均衡能力。Service也通过pod的标签选择后端的负载pod