Kubernetes基本概念和术语

前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除

目录

一、资源对象

二、集群类

1、Master

2、Node

三、应用类

1、Service与Pod

​2、Label与标签选择器

3、Pod与Deployment

4、Service与ClusterIP地址

5、Service的外网访问问题

6、有状态的应用集群

7、批处理应用

8、应用的配置问题

9、应用的运维问题

四、存储类

1、emptyDir

2、hostPath

3、公有云Volume

4、其他类型的Volume

动态存储管理

五、安全类

ServiceAccount

Role和ClusterRole

NetworkPolicy

致谢


一、资源对象

Kubernetes中的基本概念和术语大多围绕资源对象来说的,而资源对象在总体上分以下两类:

  • 某种资源的对象(例如:节点、Pod、服务、存储卷)
  • 与资源相关的事物与动作(例如:标签、注解、命名空间、部署、HPA、PVC)

资源对象一般包括几个通用属性:版本、类别、名称、标签、注解

  • 版本信息里包括:此对象所属的资源组,一些资源对象的属性会随版本的升级而变化,需要注意
  • 类别:定义资源对象的类型
  • 名称、标签、注解属于资源对象的元数据
    • 名称唯一
    • 用标签来表明资源对象的特征、类别,以及通过标签筛选不同的资源对象并实现对象之间的关联、控制或协作功能
    • 注解:一种特殊的标签,更多的是与程序挂钩,实现资源对象属性的自定义扩展

可采用YAMLJSON格声明(定义或创建)一个K8s资源对象,每个资源对象都有自己的特定结构定义(可理解为数据库中一个特定的表),并且统一保存在etcd这种非关系型数据库中,以实现最快的读写速度。所有资源对象都可通过K8s提供的kubetcl工具或者API编程调用)执行增删改查等操作

一些资源对象有自己的生命周期及相应的状态;这里按照功能或用途进行分类—集群类、应用类、存储类和安全类

二、集群类

集群(Cluster)表示一个由Master和Node组成的K8s集群

1、Master

Master指的是集群的控制节点。在每个K8s集群中都需要一个或一组被称为Master的节点,来负责整个集群的管理和控制。Master通常占据一个独立的服务器,是整个集群的"大脑";

在Master上运行着以下关键进程:

  • Kubernetes API Server:提供HTTP RESTful API接口的主要服务,是K8s里对所有资源进行增删改查等操作的唯一入口,也是集群控制的入口进程;
  • Kubernetes Controller Manager:K8s里所有资源对象的自动化控制中心;
  • Kubernetes Scheduler:负责资源调度(Pod调度)的进程,相当于公交公司的调度室;

另外,在Master上通常还需要部署etcd服务

2、Node

K8s集群中除Master外的其他服务被称为Node,Node在早期被称为Minion。与Master一样,Node可以是一台物理机,也可以是一台虚拟机。Node是K8s集群中的工作负载节点,每个Node都会被Master分配一些工作负载(Docker容器),当某个Node宕机时,其上的工作负载会被Master自动转移到其他Node上。在每个Node上都运行着以下关键进程:

  • Kubelet:负责Pod对应容器的创建、启停等任务,同时与Master密切合作,实现集群管理
  • Kube-proxy:实现Kubernetes Service的通信与负载均衡机制的服务
  • 容器运行时(如Docker):负责本机的容器创建和管理

Node可以在运行期间动态增加到K8s集群中,前提是正确配置、启动和安装了关键进程。默认情况下,Kubelet会向Master注册自己,这也是K8s推荐的Node管理方式。一旦Node被纳入集群管理范畴,Kubelet进程就会定时向Master汇报自己的情报(例操作系统、主机CPU和内存使用情况,以及当前有哪些Pod在运行,实现高效均衡的资源调度策略);当某个Pod在超时时间不上报信息,会被Master判定为"失联",该Node的状态就会被标记为不可以,随后触发"工作负载大转移"的自动流程。

查看信息

可运行下述命令查看在集群中有多少个Node:

 # kubectl get nodes

然后通过kubectl describe node <node_name>命令查看某个Node的详细信息

 # kubectl describe node k8s-node-1

污点与容忍

若一个Node存在问题,则为其打上特殊标签—污点(Taint)避免新的容器被调度到该Node上

若某些Pod可以(短期)容忍(Toleration)某种污点的存在,则可以继续将其调度到该Node上。

命名空间

用于实现多租户的资源隔离,典型的一种思路就是给每个租户都分配一个命名空间。

命名空间属于Kubernetes集群范畴的资源对象,在一个集群里可以创建出多个命名空间,每个命名空间都是相互独立的存在,属于不同命名空间的资源对象从逻辑上相互隔离

在K8s集群安装且正常运行后,Master会自动创建两个命名空间:默认的(default)系统级的(kube-system);用户创建资源对象默认放在default中;而系统相关资源对象如网络组件、DNS组件、监控类组件等,被安装在kube-system命名空间中;

通过命名空间将集群内部的资源对象"分配"到不同的命名空间中,形成逻辑上分组的不同项目、小组或用户组,便于管理;还可结合k8s的资源配额管理,限定不同租户能占用的资源;

命名空间的创建示例:下面YAML文件定义名为development的命名空间:

 apiVersion: v1
 kind: Namespace
 metadata:
     name: development

指定资源对象属于哪个命名空间:定义一个名为busybox的Pod,将其放入development命名空间:

 apiVersion: v1
 kind: Pod
 metadata:
   name: busybox 
   namespace: development
 spec:
     containers:
     - image: busybox
       command:
         - sleep
         - "3600"
         name: busybox

在kubectl get命令中加入--namespace参数来操作某个命名空间中的对象:

 # kubectl get pods --namespace=development
 NAME        READY       STATUS      RESTARTS        AGE
 busybox     1/1         Running     0               1m

三、应用类

K8s中应用类的概念和相应的资源对象最多,重点学习

1、Service与Pod

在Kubernetes中,Service是一个可以是无状态或有状态的组件,它通过分配一个全局唯一的虚拟ClusterIP地址来实现服务的访问。这个ClusterIP在Service生命周期内保持不变,允许客户端通过IP加端口或DNS名称来访问服务。Kubernetes的这种设计不仅简化了服务发现的问题,还通过ClusterIP实现了服务的透明负载均衡故障自动恢复功能。

通过将系统中的所有服务转化为Kubernetes中的微服务,我们的系统由多个独立且提供不同业务功能的微服务单元组成。这些服务通过TCP/IP通信,形成了一个强大、灵活且具有弹性的分布式网络,具备显著的扩展性和容错能力,同时简化了程序架构。

Pod是Kubernetes中的核心概念,每个Pod包含一个基础的Pause容器和至少一个用户业务容器,其中Pause容器是Kubernetes平台的一部分,用于支持Pod的生命周期管理。

Kubernetes设计了Pod概念,因为它提供了一个抽象模型使得多个应用进程可以作为一个单位进行调度和伸缩。Pod由一个基础的Pause容器和多个用户业务容器组成,这些容器共享IP地址和存储卷简化了通信和文件共享。Kubernetes还为每个Pod分配了唯一的IP地址,确保了集群内任意两个Pod之间的直接TCP/IP通信,通常通过虚拟二层网络技术如Flannel或OpenvSwitch实现。

Kubernetes的Pod分为两种类型:普通Pod静态Pod

  • 普通Pod存储在Kubernetes的etcd中,由Kubernetes Master调度到特定Node上,并通过kubelet实例化为容器
  • 静态Pod则存储在Node的文件系统中,仅在该Node上启动和运行。
  • Pod共享PodIP,容器间通信和文件共享得到简化
  • Pod的容器若停止,Kubernetes会尝试重启Pod;若Node故障,则Pod会被重新调度到其他Node。

示例:

 apiVersion: v1
 kind; Pod       # 说明这是Pod类型的资源对象
 metadata:       
   name; myweb   # Pod的名称
   labels:   
     name: myweb # 声明myweb的标签
   spec:         # spec部分定义容器组
     containers:
     - name: myweb   # 定义名为myweb且对应镜像xxx的容器
     image: kubeguide/tomcat-app:v1
     ports;  
     - containerPort: 8080       # 端口为8080

Pod的IP加上这里的容器端口组成了一个新的概念—Endpoint,代表此Pod里的一个服务进程的对外通信地址。一个Pod存在具有多个Endpoint的情况;

在Kubernetes中,Pod Volume 是一种存储资源,定义在Pod上并被其内的容器挂载,用于在容器间共享数据。简单来说,它是一个在Pod内挂载的文件目录

Kubernetes中的Event是一种记录,详细记载了事件的发生时间、重现频率、发起者类型以及原因等信息。这些记录通常与特定的资源对象相关联,是诊断问题的关键资源。例如,当Pod创建遇到问题时,可以通过kubectl describe pod xxxx命令查看其Event记录,帮助定位故障原因;

Pod及Pod周边对象的示意图:

2、Label与标签选择器

在Kubernetes中,Label是一种用于资源对象分类和识别的键值对标记。用户可以自定义key和value,并将这些标签附加到诸如Node、Pod、Service等资源对象上。一个对象可以拥有多个标签,且一个标签也可以应用于多个对象。标签的使用有助于资源的分组管理,便于进行资源分配、调度、配置和部署。例如,通过标签可以实现不同版本应用的部署和监控。

  • 版本标签:release:stable和release:cannary
  • 环境标签:environment:dev、environment:qa和environment:production
  • 架构标签:tier:fronted、tier:backed和tier:middleware
  • 分区标签:partition:customerA和partition:customerB
  • 质量管控标签:track:daily和track:weekly

在Kubernetes中,Label Selector标签选择器允许基于标签对资源对象进行查询和筛选。类似于SQL查询中的where条件,例如使用"name=redis-slave"可以筛选出名称为"redis-slave"的Pod。Kubernetes提供了两种类型的标签选择器表达式:基于等式的(Equality-based)基于集合的(Set-based

基于等式的Selector表达式采用等式类表达式匹配标签,下面示例:

  • name=redis-slave:匹配所有具有name=redis-slave标签的资源对象
  • env !=production:匹配所有不具有env=production标签的资源对象

基于集合的Selector表达式则使用集合操作类表达式匹配标签,下面示例:

  • name in(redis-master,redis-slave):匹配所有具有name=redis-master标签或者name=redis-slave标签的资源对象
  • name not in(php-frontend):匹配所有不具有name=php-fronted标签的资源对象

可通过多个标签表达式组合来实现复杂的条件选择,之间用","进行分隔,几个条件之间是"AND"关系,即同时满足多个条件,示例:

 name=redis-slave,env!=production
 name notin(php-frontend),env!=production

Label也是Pod的重要属性之一,其重要性仅次于Pod的端口,我们几乎见不到没有Label的Pod。以myweb Pod为例:

 apiVersion: v1
 kind: Pod
 metadata:
   name: myweb
   labels:
     app: myweb

对应的Service myweb就是通过下面的标签选择器与myweb Pod发生关联的:

 spec:
   selector:
     app: myweb

Service一个重要的属性就是标签选择器,若不小心把标签写错,可能会出现指鹿为马的闹剧;

3、Pod与Deployment

通过使用Pod模板自动创建和管理指定数量的Pod副本,简化了服务的部署和扩展;使得服务能够以无状态的方式运行;看一个Deployment例子:

 apiVersion: apps/v1
 kind: Deployment
 spec:
   replicas: 2       # Pod的副本数量
   selector:
     matchLabels:
       app: myweb
   template:
     metadata:
       labels:
         app: myweb
     spec:

只有一个Pod副本也要使用Deployment;因为除了自动创建Pod外,Deployment还负责自动控制和故障恢复。例如,当Pod所在的节点发生故障时,Kubernetes会立即检测并创建新的Pod,确保副本数量与Deployment中指定的数量一致。

示例:创建一个名为tomcat-deploment.yaml的Deployment描述文件:

 apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: frontend
 spec:
   replicas: 1
   selector:
     matchLabels:
       tier: frontend
     matchExpressions:
       - {key: tier, operator: In, values: [frontend]}
     template:
       metadata:
         labels:
           app: app-demo
           tier: frontend
       spec:
         containers:
         - name: tomcat
           imagePullPolicy: IfNotPresent
           ports:
           - containerPort: 8080

运行以下命令创建Deployment对象

 # kubectl create -f tomat-deployment.yaml
 deployment "tomat-deploy" created

运行以下命令查看Deployment的信息

 # kubectl get deployments
 NAME        DESIRED     CURRENT     UP-TO-DATA      AVALIABLE       AGE
 tomcat      1           1           1               1               4m
 ​
 # 各含义如下
 '''
 DESIRED:Pod副本数量的期望值,即在Deployment里定义的replicas。
 CURRENT:当前replics的值,此值不断增加直到达到DESIRED为止
 UP-TO-DATA:最新版本的Pod的副本数量
 AVALIABLE:当前集群可用Pod副本数量
 '''

Deployment资源对象还与ReplicaSet资源对象密切相关,K8s内部会根据Deployment对象自动创建相关联的ReplicaSet对象

 # kubectl get replicaset
 NAME                        DESIRED     CURRENT     AGE
 tomcat-deploy-16402423      1           1           1m

发现Pod的命名也是以Deployment对应的ReplicaSet对象的名称为前缀的,这表明了一个ReplicaSet对象创建了哪些Pod。对于Pod滚动升级(Pod Rolling update)这种复杂的操作过程来说,易排查错误:

 # kubectl get pods
 NAME                        REDAY       STATUS      RESTARTS        AGE
 tomcat-deploy-164024-zhrsc1/1           RUNING      0               3m

Deployment的典型使用场景:

  • 创建一个Deployment对象来完成相应Pod副本数量的创建
  • 检查Deployment的状态来看部署动作是否完成(Pod副本数量是否达到预期值)
  • 更新Deployment以创建新的Pod,不稳定则回滚到一个早先的Deployment版本
  • 扩展Deployment以应对高负载

4、Service与ClusterIP地址

在K8s中,多个Pod副本组成的集群通过Service来对外提供服务。Service充当负载均衡器的角色,将客户端的请求转发到后端的Pod实例;具体来说:

  • Service:创建一个Service对象,K8s会自动为它分配一个全局唯一的虚拟IP地址(ClusterIP),这个地址在整个Service生命周期内保持不变。
  • 负载均衡:Service通过内部机制(如iptables或IPVS)将请求转发到后端的Pod实例,实现负载均衡。
  • 访问方式:客户端可以通过Service的ClusterIP和端口访问服务,而无需关心后端Pod的具体IP地址和端口。
  • 动态更新:即使Pod的IP地址发生变化,Service的ClusterIP保持不变,确保服务的连续性和稳定性。

K8s通过Service对象还解决了分布式系统中的服务发现问题,具体方法如下:

  • DNS域名映射:将Service的名称与ClusterIP地址关联,形成DNS域名,例如mydbserver:3306
  • 虚拟IP地址:ClusterIP是Kubernetes为Service分配的虚拟IP地址,仅在集群内部有效,不与物理网络相关。
  • 访问方式:应用通过Service名称和端口直接访问服务,无需额外API获取IP和端口信息。
  • 限制:ClusterIP地址无法被外部网络访问,集群外的节点需要通过其他机制(如NodePort或Ingress)来访问Service。

下面是名为tomcat-service.yaml的Service定义文件,内容如下:

 apiVersion: v1
 kind: Service       # 定义类型为Service
 metadata:
   name: tomcat-service
 spec: 
   ports:
   - port: 8080
   selector:         # 拥有tier=frontend的标签的所有Pod实例都属于它
     tier: frontend

运行下面命令进行创建:

 # kubectl create -f tomcat-service.yaml
 service "tomcat-service" created

之前的tomcat-deployment.yaml里定义的Tomcat的Pod刚好拥有这个标签,所以刚才创建的tomcat-service已经对应一个Pod实例;查看tomcat-service的Endpoint列表,其中172.17.1.3是Pod的IP地址,8080是Container暴露的端口:

 # kubectl get endpoint
 NAME            ENDPOINTS               AGE
 kubernetes      192.168.18.131:6443     15d
 tomcat-service  172.17.1.3:8080         1m

运行下面命令查看tomcat-service被分配的ClusterIP地址及更多的信息:

 # kubectl get svc tomcat-service -o yaml
 apiVersion: v1
 kind: Service
 spec:
   clusterIP: 10.245.85.70
   ports:
   - port: 8080          # Service服务的端口
     protocol: TCP   
     targetPort: 8080    # 容器暴露的端口号
   selector:
     tier: frontend
   sessionAffinity: None
   type: ClusterIP
 status:
   loadBalancer: {}

Headless Service是Kubernetes中一种特殊的服务类型,其定义时通过设置clusterIP: None来标识。与普通Service不同,Headless Service不提供ClusterIP地址,而是直接返回其后端Pod的Endpoint列表。这意味着客户端可以直接与Pod建立TCP/IP连接,无需通过虚拟ClusterIP地址转发,从而实现更高性能的通信,类似于“原生网络通信”。

接下来是Service的多端口问题;K8s Service支持多个Endpoint,在存在多个Endpoint的情况,要求每个Endpoint都定义一个名称进行区分。下面举例:

 apiVersion: v1
 kind: Service
 metadata:
   name: tomcat-service
 spec:
   ports:
   - port: 8080
     name: service-port
   - port: 8005
     name: shutdown-port
   selector:
     tier: frontend

5、Service的外网访问问题

为了让集群外的应用访问Kubernetes集群内的服务,需要了解以下三种IP:

  • Node IP:每个节点的物理网卡IP,用于集群内外节点的直接通信。
  • Pod IP:每个Pod的IP,通常在虚拟二层网络中分配,用于集群内Pod间的通信。
  • Service IP(ClusterIP):服务的虚拟IP,仅在集群内部有效。

为了使集群外的应用能够访问集群内的服务,Kubernetes引入了NodePort概念。通过将Service的端口映射到节点的物理IP上,外部应用可以通过Node IP和NodePort访问集群内的服务。这种方法是实现集群外访问的直接且常见的解决方案。

以tomcat-service为例,在Service的定义里做如下扩展即可:

 apiVersion: v1
 kind: Service       
 metadata:
   name: tomcat-service
 spec: 
   type: NodePort    # 增加类型
   ports:
   - port: 8080
     nodePort: 31002 # 手动指明tomcat-service的NodePort为31002;
   selector: 
     tier: frontend

在浏览器访问http://<nodePort IP>:31002/,即可看到Tomcat的欢迎界面;

在K8s集群的每个Node上都为需要外部访问的Service开启一个对应的TCP监听端口),外部系统只需要一个Node的IP地址+NodePort端口号即可访问此服务,在任意Node上运行netstat命令,就可以看到有NodePort端口被监听:

 # netstat -tlp | grep 31002
 tcp 6 0 0 [::]:31002        [::]:*          LISTEM          1125/kube-proxy 

但NodePort没有解决全部问题,比如负载均衡;

Kubernetes通过提供自动化的负载均衡解决方案简化了服务的外部访问。以下是关键点:

  • 外部负载均衡器:通常为硬件或软件(如HAProxy或Nginx)实现,用于将流量转发到K8s集群的节点。
  • 自动化配置:在公有云如谷歌云GCE上,只需将Service的类型从NodePort改为LoadBalancer,Kubernetes会自动创建并配置负载均衡器实例,并提供其IP地址供外部访问。
  • 私有集群解决方案:如MetalLB,为私有k8s集群提供负载均衡功能,确保服务的高可用性和外部访问。

这种方法减少了手动配置负载均衡器的工作量,降低了出错概率,同时提高了集群的灵活性和可扩展性。

Ingress资源对象解决让多个Service共用一个对外端口,可理解为基于Nginx的支持虚拟主机的HTTP代理;示例:

 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: 
         servicePort: 80

在这个定义中,到虚拟域名first.bar.com请求的流量会被路由到service1,到second.foo.com请求的流量会被路由到service2;

6、有状态的应用集群

有状态服务如ZooKeeper、MySQL和Kafka集群通过Kubernetes的StatefulSet进行自动部署和管理。StatefulSet为每个节点提供固定身份ID,确保集群成员可以相互发现并通信,同时保证节点的有序启动和关闭,以及持久化数据存储。对于更复杂的应用,Kubernetes Operator提供了更强大的管理能力。

StatefulSet是K8s中专门用于有状态服务的资源对象,它为每个Pod提供唯一、稳定的网络标识和持久化存储,确保集群成员的有序启动和停止。通过与Headless Service结合,StatefulSet为每个Pod实例创建了可预测的DNS域名,这个域名格式为:

 $(podname).$(headless service name)

Kubernetes Operator框架为平台开发者提供了一种开发自定义控制器的方法,使得他们能够实现复杂的有状态集群应用的自动部署、故障发现和运维管理,超越了StatefulSet的建模能力。未来,有状态集群的部署和管理将越来越多地依赖于Operator。

7、批处理应用

一个或多个进程处理一组数据(图像、文件、视频等),K8s引入了新的资源对象—Job,下面是一个计算圆周率的经典例子:

 apiVersion: batch/v1
 kind: Job
 metadata:
   name: pi
 spec:
   template:
     spec:
       containers:
       - name: pi
         image: perl
         command: ["perl","-Mbignum=bpi","-wle","print bpi(100)"]
       restartPolicy: Never
   parallelism: 1        # 并发运行的个数
   completions: 5        # 运行的任务总数

K8s中的Job用于运行一次性任务,它控制的Pod副本是短暂运行的,每个容器仅执行一次。一旦所有Pod副本完成任务,Job也随之结束。与Deployment等不同,Job生成的Pod不自动重启,其restartPolicy设置为Never。此外,Kubernetes还引入了CronJob,用于周期性执行任务。

8、应用的配置问题

初步立即了三种应用建模的资源对象:

  • 无状态服务的建模:Deployment
  • 有状态集群的建模:StatefulSet
  • 批处理应用的建模:Job

ConfigMap和Secret可以解决应用需要在不同的环境中修改配置的问题。

ConfigMap在Kubernetes中用于管理应用配置,它允许将配置文件存储为键值对,并将这些配置挂载到Pod中。当ConfigMap内容更新时,Kubernetes会自动在目标节点上刷新配置文件,确保应用获取最新的配置,从而简化了分布式应用的配置管理。

Secret是Kubernetes中用于管理敏感信息的资源对象,比如数据库密码、证书和密钥。通过创建Secret对象并将其挂载到Pod中,应用可以安全地访问这些敏感配置。自Kubernetes 1.7版本起,Secret中的数据支持加密存储,增强了安全性。

9、应用的运维问题

HPA水平自动扩缩容器)是Kubernetes中用于自动管理Pod副本数量的高级功能。它通过分析指定Deployment的Pod负载变化,自动决定是否需要增加或减少Pod副本数。Kubernetes内置了基于CPU利用率的自动扩缩容机制,同时支持自定义度量指标(如每秒请求数),以实现更灵活的扩缩容策略。这样,系统能够根据实际需求自动调整资源,提高效率和响应性。示例:

 apiVersion: autoscaling/v1
 kind: HorizontalPodAutoscaler
 metadata:
   name: php-apache
   namespace: default
 spec:
   maxReplicas: 10
   minReplicas: 1
   scaleTargetRef:
     kind: Deployment
     name: php-apache
   targetCPUUtilizationPercentage: 90
   
 # 根据上面的定义,我们可以知道这个HPA控制的目标对象是一个名为php-apache的Deployment里的Pod副本,当这些Pod副本的CPU利用率的值超过90%时,会触发自动动态扩容,限定Pod的副本数量为1~10。

VPA垂直Pod自动扩缩器)是Kubernetes中用于自动调整Pod资源需求(CPU和内存)的特性。它基于容器的实际使用率来推测并设置合适的资源指标,帮助精确调度Pod,节省集群资源,并提高运维自动化水平。作为一项较新的功能,VPA目前不能与HPA共同操作同一组Pod,但预计两者未来将实现更深入的融合。

四、存储类

存储类的资源对象主要包括Volume、Persistent Volume、PVC和StorageClass

Volume是Pod内多个容器共享的目录,它与Pod生命周期相同,与容器生命周期无关。这意味着即使容器重启,Volume中的数据也不会丢失。用户可以通过声明一个Volume并将其挂载到容器的指定目录来使用它,例如在Tomcat Pod中增加一个名为datavol的Volume并挂载到/mydata-data目录。Kubernetes支持多种类型的Volume,如GlusterFS、Ceph等分布式文件系统。

 template:
   metadata:
     labels:
       app: app-demo
       tier: frontend
   spec:
     volumes:
       - name: datavol
         emptyDir: {}
       containers:
       - name: tomcat-demo
         image: tomcat
         volumeMounts:
           - mountPath: /mydata-data
             name: datavol
         imagePullPolicy: IfNotpresent

K8s提供丰富的Volume类型供容器使用,例如临时目录、宿主机目录、共享存储等;下面说明:

1、emptyDir

EmptyDir是K8s中在Pod分配到节点时自动创建的临时存储目录,其初始内容为空,并且无需指定宿主机上的对应目录。当Pod被移除时,EmptyDir中的数据将被永久删除;其一些用途如下:

  • 临时空间
  • 长时间任务执行过程中使用的临时目录
  • 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)

默认情况下,emptyDir使用节点的存储介质,如磁盘或网络存储。通过设置emptyDir.medium属性为“Memory,可以启用基于内存的后端存储,从而提高速度。但需注意,这种基于内存的存储会作为容器内存消耗的一部分,受到资源限制和配额的约束。

2、hostPath

hostPath在Pod上挂载宿主机的文件或目录,通常用于以下几个方面:

  • 在容器应用程序生成的日志文件需要永久保存时,可以使用宿主机的高速文件系统对其进行存储
  • 需要访问宿主机Docker引擎内部数据的容器应用时;通过定义hostPath为宿主机/var/lib/docker目录,是容器内部的应用可以直接访问Docker的文件系统
  • 在不同的Node上具有相同配置的Pod,可能会因宿主机上的目录和文件不同,而导致对Volume上目录和文件的访问结果不一致
  • 若使用资源配额管理,则K8s无法将hostPath在宿主机上使用的资源纳入管理

示例:使用宿主机的/data目录定义一个hostPath类型的Volume:

 volumes:
 - name: "persistent-storage"
   hostPath:
     path: "/data"

3、公有云Volume

公有云提供的Volume类型包括谷歌公有云提供的GCEPersistentDisk、亚马逊公有云提供的AWS Elastic Block Store(EBSVolume)等。当我们的Kubernetes集群运行在公有云上或者使用公有云家提供的Kubernetes集群时,就可以使用这类Volume。

4、其他类型的Volume

  • iscsi:将iSCSI存储设备上的目录挂载到Pod中。
  • nfs:将NFS Server上的目录挂载到Pod中:
  • glusterfs:将开源GlusterFs网络文件系统的目录挂载到Pod中。
  • rbd:将Ceph块设备共享存储(RadosBlockDevice)挂载到Pod中。
  • gitRepo:通过挂载一个空目录,并从Git库克隆(clone)一个git repository以供Pod使用。
  • confgmap:将配置数据挂载为容器内的文件。
  • secret:将Secret数据挂载为容器内的文件。

动态存储管理

Volume属于静态管理的存储,即事先定义然后挂载使用,典型弊端如下:

  • 配置参数繁琐
  • 预定义的静态Volume可能不符合目标应用的需求

因此动态存储管理;核心有三:Persistent Volume(PV)、StorageClassPVC

Persistent Volume (PV) 是 K8s中一种预先或动态创建的存储资源,类似于 Volume,但它是独立于 Pod 定义的。PV 可以被理解为集群中某个网络存储的一块存储区域 ;支持的类型有许多;

StorageClass用来描述和定义某种存储系统的特征;示例:

 apiVersion: storage.k8s.io/v1
 kind: StorageClass
 metedata:
   name: standard
 provisioner: kubenetes.io/aws-ebs       # 创建PV的第三方存储插件
 parametes:      # 创建PV必要参数
   type: gp2
 reclaimPolicy: Retain       # PV回收策略:删除或保留
 allowVolumeExpansion: true
 mountOptions:
   - debug
   volumeBindingMode: Immediate

注意StorageClass的名称会在PVC(PV Claim)中出现,示例:

 apiVersion: v1
 kind: PersistentVolumeClaim
 metadata:
   name: cliam1
 spec:
   accessModes:
     - ReadWriteOne
   storageClassName: standard
   resources:
     requests:
       storage: 30Gi

Persistent Volume Claim (PVC) 是用户定义的存储请求,它指定了所需的存储访问模式、存储类和资源规格。利用基于 StorageClass 和 PVC 的动态 PV 管理机制,用户可以轻松地在 Pod 中引用 PVC,实现存储卷的自动化管理和使用。示例:

 spec:
   containers:
   - name: myapp
     image: tomcat: 8.5.38-jre8
     volumeMounts:
       - name: tomcatedata
         mountPath: "/data"
   volumes:
     - name: tomcatedata
       persistentVolumeClaim:
         claimName: claim1

除了动态创建PV,PV动态扩容、快照及克隆的能力也是Kubermetes社区正在积极研发的高级特性。

五、安全类

安全是Kubernetes发展中的核心议题。作为一个多用户共享资源的系统,Kubernetes管理着Pod、Service、Deployment等资源对象。只有经过认证的用户才能通过API Server来操作这些资源。Kubernetes的用户主要分为两类:一类是运行在Pod中的应用,它们需要通过API Server来访问和管理资源;另一类是普通用户,通常是运维人员使用kubectl等命令行工具。

ServiceAccount

为了确保Pod应用能够安全地访问API Server,K8s引入了ServiceAccount资源对象代表Pod应用的身份进行认证。在ServiceAccount的基础上,K8s实现了基于角色的访问控制权限系统(RBAC),以精细化地控制不同用户和应用对资源的访问权限。

默认情况下,K8s在每个命名空间中都会创建一个默认名称为default的Service Account,因此其不能全局使用,只能在其所在的命名空间中的Pod使用;通过以下命令查看集群中的所有Service Account:

 # kubectl get sa --all-namespaces
 NAMESPACE       NAME        SECRETS     AGE
 default         default     1           32d
 kube-system     default     1           32d

Service Account是K8s中用于标识 Pod 应用身份的账号,其凭证通过 Secret 保存包括 CA 根证书和签名的 Token。Token 中包含 Service Account 名称,使 API Server 能识别身份。默认情况下,Pod 绑定所在命名空间的 default Service Account。Kubernetes将这些凭证信息持久化到容器的本地文件中,使得容器内应用可通过 Kubernetes 客户端 API 自动进行身份认证。认证成功后,访问授权则由基于角色的访问控制(RBAC)系统处理。

Role和ClusterRole

RoleClusterRole 是 K8s中定义权限的两种资源对象。Role限定在特定命名空间内,而 ClusterRole 则适用于整个 Kubernetes 集群。Role 定义了一组权限规则,允许用户对特定资源执行操作;

示例:一个 Role 可以授予用户在默认命名空间"default"中对Pod资源的读取权限,包括get、watch和list操作:

 kind: Role
 apiVersion: rabc.authorization.k8s.io/v1
 metadata:
   namespace: default
   name: pod-reader
 rules:
 - apiGroups: [""]   # 空字符串""表明使用core API group
   resources: ["pods"]
   verbs: ["get","watch","list"]

接下来通过RoleBindingClusterRoleBinding来将Role与具体用户绑定(用户授权);示例:在命名空间default中将“pod-reader”角色授予用户“Caden”,结合对应的Role的定义,表明这一权将允许用户“Caden”从命名空间default中读取pod:

 kind: RoleBinding
 apiVersion: rabc.authorization.k8s.io/v1
 metadata:
   name: read-pods
   namespace: default
 subjects:       # (目标主体)来表示要授权的对象
 - kind: User    # Group(用户组)、User(某个具体用户)和Service Account(Pod应用所使用的账号)
   name: Caden
   apiGroup: rabc.authorization.k8s.io
 roleRef:
   kind: Role
   name: pod-reader
   apiGroup: rabc.authorization.k8s.io

NetworkPolicy

NetworkPolicy是K8s中用于网络安全的资源对象,它定义了Pod间以及Pod与其他网络端点间的通信规则,通过标签选择器来应用这些规则。默认情况下,Pod 间的通信不受限制,适用于单一厂商独占集群且应用间相互信任的场景。然而,在多厂商共享的 Kubernetes 集群,特别是公有云环境中,使用 NetworkPolicy 实现应用间的网络隔离是提高安全性的关键措施。

致谢

在此,我要对所有为知识共享做出贡献的个人和机构表示最深切的感谢。同时也感谢每一位花时间阅读这篇文章的读者,如果文章中有任何错误,欢迎留言指正。 

学习永无止境,让我们共同进步!!

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李学不完

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值