master
kubernetes里的master指的是集群控制节点,每一个kubernetes集群里都需要一个Master节点来负责整个集群的管理和控制,基本上kubernetes所有的控制命令都是发给它,它来负责具体的执行过程,所有执行命令都是在master上运行的。Master节点通常会占据一个独立的X86服务器(或者一个虚拟机),一个主要的原因是它太重要了,他是整个集群的首脑,如果它宕机或者不可用,那么所有的控制命令都将失效。
master节点上运行着一下组关键进程
kubernetes API Server(kube-apiserver),
提供了HTTP rest接口的关键服务进程,是kubernetes里所有资源的增,删,改,查等操作的唯一入口,也是集群控制的入口进程
kubemets Controller Manager(kube-controller-manager)
kubernetes里所有资源对象的自动化控制中心,可以理解为资源对象的“大总管”
kubernetes scheduler(kube-scheduler)
负责资源调度(Pod调度)的进程,相当于公交公司的“调度室”
etcd Server 进程
kubernetes里的所有资源对象的数据全部都保存在etcd中
node
除了Master,kubernetes集群中的其他机器被称为node节点,在较早的版本中也称为Minion,与master一样,node节点可以是一台物理主机,也可以是一台虚拟机。node节点才是kubernetes集群中的工作负载节点,每个node都会被master分配一些工作负载(docker容器),当某个Node宕机时,其上的工作负载会被master自动转移到其他节点上去
每个node节点上都运行着以下一组关键进程。
kubelet:负责Pod对应的容器的创建,启停等任务,同时与master节点密切协作,实现集群管理的基本功能。
kube-proxy:实现kubernetes Service的通信与负载均衡机制的重要组件。
Docker Engine (Docker):docker引擎,负载本机的容器创建和管理工作
Node节点可以在运行期间动态增加到kubernetes集群中,前提是这个节点上已经正确安装,配置和启动了上述关键进程,在默认情况下kubelet会醒Master注册自己,着也是kubernetes推荐的node管理方式。一旦node被纳入集群管理范围,kubelet会想master节点汇报自身的情报,例如操作系统,docker版本,机器的cpu和内存情况,以及之前有哪些Pod在运行等,这样Master可以获知每个node的资源使用情况,并实现高效均衡的资源调度策略。而某个node超过指定时间不上报信息时,会被Master判定为“失联”,node的状态被标记为不可用(Not ready),随后Master会触发“工作负载大转移”的自动流程
Pod
Pod是kubernets的最重要的也最基本的概念,每个Pod都有一个特殊的被称为“根容器”的pause容器。pause容器对应的镜像属于kubernetes平台的一部分,除了Pause容器,每个Pod还包含一个或多个紧密相关的用户业务容器
pod设计的原因和特殊结构
原因一:
在一组容器作为一个单元的情况下,难以对“整体”简单地进行判断及有效地进行行动。比如,一个容器死亡了,此时算是整体死亡吗?是N/M的死亡率吗?引入业务无关并且不易死亡的Pause容器作为Pod的根容器,以它的状态代表整个容器组的状态,就简单,巧妙地解决了这个问题
原因二:
Pod里的多个业务容器共享Pause容器的IP,共享Pause容器挂载的Volume,这样既简化了密切关联的业务容器之间的通信问题,也很好地解决了它们之间的文件共享问题。
kubernetes 为每个Pod都分配了唯一的IP地址,称之为Pod IP,一个Pod里的多个容器共享Pod IP地址。kubernetes要求底层网络支持集群内任意两个pod之间的tcp/IP之间通信,这通常采用虚拟二层网络技术来实现,例如Flannel,Openvswitch等,因次我们需要牢记一点:在kubernetes里,一个pod里的容器与另外主机上的pod容器能够直接通信。
Pod其实有两种类型:普通的Pod及静态Pod(static Pod),后者比较特殊,它并不存放在kubernetes的tecd存储里,而是存放在某个具体的Node上的一个具体文件中,并且只在此Node上启动运行。而普通的Pod一旦被创建,就会被放到etcd中存储,随后会被kubernetes master调度到某个具体的Node上并进行绑定(Binding),随后改Pod被对应的Node上的kubelet进程实例化称一组相关的Docker容器并启动起来。在默认情况下,当Pod里的某个容器停止时,kubernetes会自动检测到这个问题并且重新启动这个Pod(重启Pod里的所有容器),如果Pod所在的Node宕机,则会将这个Node上的所有Pod重新调度到其他节点上。
kubernetes里所有资源对象都可以采用yml或者json格式的文件来定义获描述。
Event
Event是一个事件的记录,记录了事件的最早产生时间,最后重现时间,重复次数,发起者,类型,以及导致此事件的原因等众多信息。Event通常会关联到某个具体资源对象上,是排查故障的重要参考信息,之前我们看到Node的描述信息包括了Event,而Pod同样有Event记录,当发现某个Pod迟迟无法创建时,可以用kubectl describe pod xxxx 来查看它的描述信息,用来定位问题的原因
pod资源
每个pod都可以对其能使用的服务器上的计算机资源设置限额,当前可以设置限额的计算资源有CPU和memory两种,其中CPU的资源单位为CPU(core)的数量,是一个绝对值而非相对值
一个CPU的配额对于绝大多数容器来说是相当大的一个资源配额了,所以,在kubernetes里,通常以千分之一的CPU配额为最小单元,用m来表示。通常一个容器的CPU配额被定义为100300m,既占用010.3个cpu。由于cpu配额是一个绝对值,所以无论在拥有一个core的机器上,还是在拥有48个core的机器上,100m这个配额所代表的CPU的使用量都是一样的。与CPU配额类似,memory配额也是一个绝对值,它的单位是内存字节数。
在kubernetes里,一个计算资源进行配额限定需要设定以下两个参数:
Requests:该资源的最小申请量,系统必须满足需求
Limits:该资源最大允许使用的量,不能被突破,当容器试图使用超过这个量的资源时,可能会被kubernetes Kill 并重启
Label
Label是kubernetes系统中另一个核心概念。一个Label是一个key=value的键值对,其中key与value由用户自己指定。label可以附加到各种资源对象上,例如 Node,Pod,Sevice,RC等, 一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去,Label通常在资源对象定义是确定,也可以在对象创建后动态添加或者删除。
可以通过给定的资源对象捆绑一个或多个不同的Label来实现多维度的资源分组管理功能,以便于灵活,方便的进行资源分配,调度,配置,部署等管理工作。例如部署不同版本的应用到不同的环境中;或者监控和分析应用(日志记录,监控,告警)等。
一些常用的Label实例如下:
- 版本标签:“release”:“stable”,“release”:“canary”…
- 环境标签:“environment”:“dev”,“environment”:“qa”,“environment”:“production”
- 架构标签:“tier”:“frontend”,“tier”:“backend”,“tier”:“middleware”
- 分区标签:“partition”:“customerA”,“partition”:“costomerB”
- 质量管控标签:“track”:“daily”,“track”:“weekly”
Label 相当于我们熟悉的“标签”,给某个资源对象定义一个Label,就相当于给它打了一个标签,随后可以通过 label Selector(标签选择器)查询和筛选拥有某些Label的资源对象,kubernetes通过这种方式实现了类似sql的简单又通用的对象查询机制。
Label Select 可以被类比为sql语句中的where查询条件,例如,name=redis-slave 这个Label Selector 作用于Pod时,可以被类比为 select * from pod where pod’s name="redis-slave"这样的语句。当前有两种Label Selector 的表达式:基于等式的(Equality-based)和基于集合的(Set-BASED)
基于等式(Equality-based)
- name = radis-slave: 匹配所有具有标签name=redis-slave的资源对象。
- env !=production: 匹配所有不具有标签env=production的资源对象,比如说env=test就是满足此条件的标签之一。
基于集合(Set-based)
- name in (redis-master,redis-slave):匹配所有具有标签name=redis-maset或者name=redis-slav的资源对象
- name nor in (php-frontend):匹配所有不具有标签name=php-frontend的资源对象
也可以通过多个Label Selector 表达式的组合实现复杂的条件选择,多个表达式之间用“,”进行分隔即可,几个条件之间是“AND”的关系,既同时满足多个条件,比如下面的例子:
name=redis-slace,env!=production
name not in (php-frontend),env!=production
Label Selector在kubernetes使用场景
- kube-controller进程通过资源对象RC上定义的Label Selector 来筛选要监控的Pod副本的数量,从而实现Pod副本的数量始终符合预期设定的全自动控制流程。
- kube-peoxy进程通过Service的Label Selector 来选择对应的Pod,自动建立起每个Service对应到Pod的请求转发路由表,从而实现Service的智能负载均衡机制
- 通过对某些Node定义特定的Label,并且在Pod定义文件中使用NodeSelector这种标签调度策略,kube-scheduler进程可以实现Pod""定向调度"的特性
Replication Controller(RC)
RC是kubernetes系统中的核心概念之一,简单来说,它其实是定义了一个期望的场景,既声明某种Pod的副本数量在任意时刻都符合某个预期值,所以RC的定义包括了如下几个部分。
- Pod期待的副本数(replicas)
- 用于筛选目标Pod的Label Selector
- 当Pod的副本数量小于预期数量的时候,用于创建新Pod模板(templare)
当定义了一个RC并提交到kubernetes集群中以后,Master节点上的Controller Manager组件就得到通知,定期巡检系统中当前存活的目标Pod,并确保目标Pod实例的数量刚好等于此RC的期望值,如果有过多的Pod副本在运行,系统就会停掉一些Pod,否则系统就会在自动创建一些Pod。可以说,通过RC,kubernetes实现了用户应用集群的高可用性,并且大大减少了系统管理员在传统IT环境中需要完成的许多手工运维工作(如主机监控脚本,应用监控脚本,故障恢复脚本等)
当应用升级时,通常会通过Build一个新的Dokcer镜像,并用新的镜像版本来替代旧的版本的当时达到目的。在系统升级的过程中,希望是平华的方式比如 房钱系统中10个对应的旧版本的Pod,最佳的方式是旧版本的Pod每次停止一个,同时创建一个新版本的Pod,在这个升级过程中,此消彼长,而运行中Pod数量始终是10个,几分钟以后,当所有的Pod,在整个升级过程中。通过RC的机制,kubernetes很容易实现了这种高级实用的特性,被称为“滚动升级”
由于Replication Controller 与 kubernetes代码中模块Reolication Controller 同名,同时这个词也无法准确表达他的本意,所以在kubernetes 1.2 的时候,它就升级成了另一个新的概念-Rcplica Set ,官方解释为“下一代的RC”,它与RC当前存在唯一区别是Replica Sets 支持基于集合的Label sekector (Set-based selector),而RC支持基于等式的Label Selector (equality-baased selector),这使得Replica Set 的功能更强。kubectl命令行工具适用于RC的绝大部分都同样的使用Replica Set,此外,当前很少单独使用Replica Set,它主要被Depliyment 这个更高层次的资源对象所使用,从而形成一整套Pod创建,删除,更新的编排机制。当我们使用Deployment时,无须关心它是如何创建和维护Replica Set的。
RC(Replioca Set)
- 在大多数情况下,我们通过定义一个RC实现Pod的创建过程及副本数量的自动控制
- RC里包括完整的Pod定义模板
- RC通过Label Selector 机制实现对Pod的创建过程及副本数量的自动控制
- RC通过Label Selector 机制实现对Pod副本的自动控制
- 通过改变RC里的Pod副本数量,可以实现Pod的扩容或缩容功能。
- 通过改变RC里Pod模板中的镜像版本,可以实现Pod的滚动升级功能。
Deployment
Deployment是kubernetes1.2 引入的新概念,引入的目的是为了更好地解决Pod的编排问题。为此Deployment在内部使用了Replica Set 来实现目的,无论是Deployment的作用于目的,它的YAM定义,还是从它的具体命令行操作来看,我们都可以把它看做RC的一次升级,两者的相似度超过90%
Deployment相对于RC的一个最大升级是我们可以随时知道当前Pod“部署”的进度。实际上有一个Pod的创建,调度,绑定节点及在目标Node上启动对应的容器这一完整过程需要一定时间,所以期待系统启动N个Pod副本的目标状态,实际上是一个连续变化的“部署过程”导致的最终状态
Deployment的典型使用场景
- 创建一个Deployment对象来生成对应的Replica Set并完成Pod副本的创建过程。
- 检查Deployment的状态来看部署动作是否完成(Pod副本的数量是否达到预期的值)
- 更新Deployment以创建新的Pod(比如镜像升级)
- 如果当前Deployment 不稳定,则回滚到一个早先的Deployment版本
- 挂载或者恢复一个Deployment
kubectl get deployments
- DESIRED:Pod副本数量的期望值,既Deployment里面定义的Replica
- CURRENT:当前Replica的值,实际上是Deployment所创建的Replica Set里的Replica值,这个值不断增加,直到达到DESIRED为止,表明部署过程完成。
- UP-TO-DATE:最新版本的Pod的副本数量,用于指示在滚动升级的过程中,有多少个Pod副本已经成功升级。
- AVAILABLE:当前集群中可用的Pod副本数量,即集群中当前存活的Pod数量
Horizontal Pod Autoscaler
通过手动执行kubectl scale 命令,可以实现Pod扩容或缩容。如果仅仅到此为止,显然不符合谷歌对kubernetes的定位目标-自动化,智能化。在谷歌看来,分布式系统要能够根据当前负载的变换情况自动触犯水平扩展或缩容的行为,因为这一过程可能是频繁发生的,不可预料的,所有手动控制的方式是不现实的。
Horizontal Pod Autoscaling 简称HPA,意思是Pod横向自动扩容,与之前的RC,Deployment 一样,也属于一种kubernetes资源对象。通过追踪分析RC控制的所有目标的Pod的负载变化情况,来确定是否需要针对性的调整目标Pod的副本数,这是HPA的实现原理
HPA有两种方式作为Pod负载的度量指标
- CPUUtilizationPercentage
- 应用程序自定义的度量指标,比如服务在每秒内对应的请求数(TPS或QPS)
CPUUtilizationPercebtage是一个算术平均值,既目标Pod所有副本吱声CPU利用率的平均值。一个Pod自身的CPU利用率是该Pod当前CPU使用量除以它的Pod Request的值,比如定义一个Pod的Pod Request 为0.4,而当前Pod的cpu使用量为0.2,则它的cpu使用率为50%,这样就可以算出来一个RC控制的所有Pod副本的cpu利用率的算术平均值了。如果某一个时刻CPUUtilizationPercentage的值超过80%,则意味着当前的Pod副本数量很可能不足以支撑接下来更多的请求,需要进行动态扩容,而当前请求高峰时段过去后,Pod的Cpu利用率又会降下来,此时对应的Pod副本数应该自动减少到一个合理的水平。
CPUUitizationPercentage 计算过程中使用到的Pod的cpu使用量通常是1分钟内的平均值,目前通过查询Heapster扩展组件来得到这个值,所以需要安装部署Heapster,这样一来便增加了系统的复杂度和实施HPA特性的复杂度,因此,未来的计划是kubernetes自身实现一个基础性能数据采集模块,从而更好地支持HPA和其他需要用基础邢娜娜数据的功能模块。此外
,如果目标Pod没有定义Pod Request的值,则无法使用CPUUtilizationPercentage来实现Pod横向自动扩容的能力。除了使用CPUUtilizationPercentage
Service(服务)
概述
Srevice是kubernetes里最核心的资源对象之一,kubernetes里的每个Service其实就是微服务架构中的一个“微服务”,Pod,RC等资源其实都是为kubernetes Service服务的
kubernetes的Service定义了一个服务的访问入口地址,前端的应用(pod)通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,Service与其后端Pod副本集群之间则是通过Label Selector 来实现“无缝对接”的。而RC的作用实际上是保证Service的服务能力和服务质量始终处于预期的标准
通过分析,识别并建模系统中的所有服务为微服务-kubernetes Service,最终系统由多个提供不同业务能力又彼此独立的微服务单元所组成,服务之间通过TCP/IP进行通信,从而形成了强大而又灵活的弹性网格,拥有了强大的分布式能力,弹性扩展能力,容错能力。所以程序框架也变得简单和直观许多
每个Pod都会被分配一个单独的IP地址,而且每个Pod都提供了一个独立的Endpoint(Pod IP+ContainerPort)
客户端访问方法
一般做法部署一个负载均衡器(软件或硬件),为这组Pod开启一个对位的服务端端口如8000端口,并且将这些Endpoint列表加入8000端口的转发列表中,客户端就可以通过负载均衡器的对外IP地址+服务端口来方位词服务,而客户端的请求最后会被转发到哪个Pod,则有负载均衡器的算法所决定
kubernetes也遵循了上诉常规做法,运行在每个Node上的kube-proxy进程骑士就是一个智能的软件负载均衡器,它负责把对Service的请求转发搭配后端的某个Pod实例上,并在内部实现服务的负载均衡机制。但Kubernetes采用一下设计:
Service不是共用一个负载均衡器的IP地址,而是每个Service分配了一个全局唯一的虚拟IP地址,这个虚拟IP被成为 Cluster IP .每个服务就变成了具备唯一IP地址的“通信节点”,服务调用就变成了最基础的TCP网络通信问题
Pod的Endpoint地址会随着Pod的销毁和重新创建而发生改变,因为新Pod的IP地址与之前旧Pod不同。而Service一旦创建,kubernetes就会自动为它分配一个可用的Cluster IP, 而且在Service的整个生命周期内,它的ClusterIP不会发生改变。所以只要用Service的Name与Service的Cluster IP地址做一个DNS域名映射即可完成
Kubernetes 服务发现机制
多端口给每个端口赋值
...
spec:
ports:
- port: 8080
name:service-port
- port:8001
name: shutdown-port
...
任何分布式系统都会涉及"服务发现"这个基础问题,大部分分布式系统通过提供特定的API接口来实现服务发现的功能,但是这样做会导致平台的浸入性比较强,也增加了开发测试的困难
Kubernetes解决方法
每个Kubernetes中的Service都有一个唯一的Cluster IP 以及唯一的名字,而名字是由开发者自己定义的,部署的时候也没必要改变,所哟完全可以固定在配置中。如何通过Service的名字找到对应的Cluster IP, Kubernetes最开始采用了Linux环境变量的方式解决,即每个Service生成一些对应的Linux环境变量(ENV),并在每个Pod的容器在启动是,自动注入环境变量 ,后来采用kubernetes通过Add-on增值包的方式引入了DNS系统,把服务名作为DNS域名
外部系统方位Service
通过三个ip地址访问到Swervice
- Node IP:Node节点的IP地址
- Pod IP:Pod的IP地址
- Cluster IP:Service的IP地址
Node IP 是kubernetes集群中每个节点的物理网卡的IP地址,这是一个真实存在的物理网路,所有属于这个网络的服务器之间都能够通过这个网络直接通信,不管是否部分节点不属于这个Kubernetes集群。这也表明Kubernetes集群之外的节点访问Kubernetes集群之内的某个节点或者TCP/IP服务的时候,必须要通过Node IP进行通信
Pod IP是每个Pod的IP地址,是Docker Engine 根据docker0网桥的ip地址段进行分配的,通常是一个虚拟的二层网络,Kubernetes要求位于不同Node上的Pod能够彼此直接通信,所以kubernetes里的一个Pod里的一个容器访问另一个Pod里的容器,就是通过Pod IP所在的虚拟二层网络进行通信的,而真实的TCP/IP流量则是通过Node IP所在的物理网卡留存的
Cluster IP也是一个虚拟IP,但是更像是一个“伪造”的IP网络
- Cluster IP仅仅作用于Kubernetes Service 这个对象,并且由Kubernetes管理和分配IP地址(来源于Cluster IP)
- Cluster IP 无法被ping,因为没有一个“实体网络对象”来响应
- Cluster IP 只能结合Service Port 组成一个具体的通信端口,单独的Cluster IP 不具备TCP/IP通信的基础,并且它们属于Kubernetes集群这样一个封闭的空间,集群之外的节点如果要访问这个通信端口,则需要做一些额外的工作。
- 在kubernetes集群之内,Node IP网, Pod IP网与 Cluster IP 网之间的通信,采用的是KUbernetes设计的一种编码方式的特殊的路由规则,与IP路由不同
所以要采用NodePort
NodePort
NodePort的实现方式是在Kubernetes集群里的每个Node上位需要外部访问的Service开启一个对应的TCP监听端口,外部系统只要用任意一个Node的IP地址+具体的NodePort端口号即可访问此服务
查看NodePort端口内监听
netstat -tlp |grep 端口号
但NodePort还没有完全解决外部访问Service的所有问题,比如负载均衡 最好由一个负载均衡器,外部请求值徐访问此负载均衡器的IP地址,由负载均衡器负责转发流量到后面某个Node的NodePort上
Volume(存储卷)
Volume是Pod中能够被多个容器访问的共享目录。Kubernete的Volume概念,用途和目的与Docker的Volume比较类似,但两者不能等价,首先,Kubernetes中的Volume定义在Pod上,让后被一个Pod里的多个容器挂载到具体的文件目录下;其次,Kubernetes中的Volume与Pod的生命周期相同,但与容器的生命周期不相关,当容器终止或这重启时,Volumne中的数据也不会丢失。最后,Kubernetes支持多种类型的Volume,例如 GlusterFS,Ceph等分布式文件系统
Volume使用方法
- 现在Pod上声明一个Volume
- 然后在容器里应用该Volume并Mount到容器里的某个目录上。
...
spce:
volumes:
-name: daravo1
emptyDir: {}
containers:
-name: ubuntu
image: ubuntu
volumeMounts:
- mountPaht: /mydata
name: datavo1
...
数据卷类型
emptyDIR
emptyDir Volume 是在Pod分配到Node时创建的。它的初始化内容位空,并且无须指定到宿主机上对应的目录文件,这是Kubernetes自动分配的一个目录,当Pod从Node上移除时,emptyDir中的数据也会被永久删除
emptyDir用途如下
- 临时空间,例如用于某些应用程序运行时所需的临时目录,且无徐永久保留
- 长时间任务的中间过程CheckPoint的临时保存目录
- 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)
目前,无法控制emptyDir使用的介质种类。如果kubelet的配置时使用硬盘,那么所有的emptyDir都将创建在该硬盘上
hostPath
hostPath为在Pod上挂载宿主机上的文件或目录
通常可以用于以下几方面:
- 容器应用程序生成的日志文件需要永久保存时,可以使用宿主机的高速文件系统进行存储
- 需要访问宿主机上Docker引擎内部数据结构的容器应用时,可以通过定义hostPath为宿主机/var/lib/docker目录,使容器内部应用可以直接访问Docker的文件系统
注意事项:
- 在不同的Node上具有相同配置的Pod可能会因为宿主机上的目录和文件不同而导致对Volume上目录和文件的访问结果不一致
- 如果使用了资源配额管理,则kubernetes无法将hostPath在宿主机上使用的资源纳入管理
宿主机的/data目录定义了一个hostPath类型的Volume
volumes:
- name:"persistent-storage"
hostPath:
path: "/data"
gcePersistentDisk
使用这种类型的Volume标识使用谷歌公有云提供的永久磁盘(Persistent Disk,PD)存放Volume的数据,它与EmptyDir不同,PD上的内容会被永久保存,当Pod被删除时,PD只是被卸载(Unmount),但不会被删除。需要先创建一个永久磁盘(pd)
,才能使用gcePersistentDisk
使用gcePersistentDisk有一下限制
- Node(运行kubelet的节点)需要时GCE虚拟机
- 这些虚拟机需要与PD存在于相同的GCE项目和Zone中
awsElasticBlockStore
于GCE相似,这类型的使用亚马逊共有云提供EBS Volume存储数据
限制
- Node(运行kubelet的节点)需要时AWS EC2实例
- EBS只支持单个EC2实例mount一个volume
NFS
使用NFS网络文件系统提供的共享目录存储数据时,需要在系统中不是一个NFS Service 定义NFS类型Volume
volumes:
-name: nfs
nfs:
# 改为nfs服务器地址
service: nfs-server.localhost
path: "/"
Persustent Volume
“网络存储”是相对独立于“计算资源”而存在的一种实体资源。比如在使用虚拟机的情况下,会首先定义一个网络存储,让后从中划出一个“网盘”并挂载到虚拟机上。Persistent Volume(简称PV)和之相关的Persistent Volume Clain (简称PVC)
PV可以理解成Kubernetes集群中的某个网络存储中对应的一块存储,与Volume很类似,但是有一下区别:
- PV智能是网络存储,不属于任何Node,但可以在每个Node上访问
- PV并不是定义在Pod上,而是独立于Pod之外定义
- pv目前有 GCE Persistent Disks , NFS,RBD,GlusterFS等等
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0003
spec:
capacity:
storage:5Gi
accessModes:
- ReadWriteOnce
nfs:
path: /path
server:172.12.0.1
声明了需要5Gi存储空间 NFS类型PV
PV的accessModes属性 类型
- ReadWriteOnce:读写权限,并且智能被单个Node挂载
- ReadOnlyMany: 只读权限,允许被多个Node挂载
- ReadWriteMany: 读写权限,允许被多个Node挂载
如果某个Pod想申请某种条件的PV,则需要先定义一个PersistenVolumeClaim(PVC)对象
kind: PersistenVolumeClaim
apiVersion: v1
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
然后在Pod的Volume定义中引用上述PVC即可
volumes:
-name: mypd
PersistenVolumeClaim:
clainName:myclaim
Pv 状态
- Available:空闲状态
- Bound: 已经绑定到某个PVC上
- Released:对应的PVC已经删除,但资源还没有被回收
-Failed: PV自动回收失败
Namespace(命名空间)
Namespace(命名空间)是Kubernetes系统中的另一个非常重要的概念,Namespace在大多数情况下用于实现多租户的资源隔离。Namespace通过将集群内部的资源对象“分配“到不同的Namespace中,形成逻辑上分组的不同项目,小组或用户组,便于不同的分组在共享使用整个集群的资源的同时还能被分别管理
kubernetes集群在启动后,会创建一个命为”default“的命名空间,如果不特别知名Namespace,则用户创建的Pod,RC,Service都将被系统创建到这个默认的名为Default的Namespace
kubectl get namespace
创建Namespave
apiVersion: v1
kind: Namespace
metadata:
name: development
创建资源对象时指定 命名空间
...
metadata:
name: busybox
namespace: development
...
指明命名空间
用命令查看
kubectl get pods --namespace=development
可以给每个用户创建不同的Namespace来实现多用户的资源隔离,还能结合Kuberneres的紫云配额管理,限定不同用户能占用的资源,例如cpu使用量,内存使用量
Annotation(注解)
Annotation 与Label类似,也是使用键值对的形式定义
不同的时Label具有严格的命名规则,它定义的时kubernetes对象的元数据(Metadata),并且用于Label Selector
Annotaion则是用户任意定义的”附加“信息,以便于外部工具进行查找
Annotation记录的信息
- build信息,release信息,Docker镜像信息等
- 日志库,监控库,分析库等资源库的地址信息
- 程序调试工具信息
-团队的联系信息