kubernetes入门:核心概念的梳理

举报
didiplus 发表于 2023/05/26 11:49:51 2023/05/26
【摘要】 Pod是k8s系统中国可以创建和管理的最小单元,是资源对象模型中又用户创建或部署的最小资源对象模型,也是在k8s上运行容器化应用的资源对象,其他的资源对象都是用来支撑或者扩展Pod对象功能的,比如控制器对象是用来管控Pod对象的,

Pod

Pod概述

Pod是k8s系统中国可以创建和管理的最小单元,是资源对象模型中又用户创建或部署的最小资源对象模型,也是在k8s上运行容器化应用的资源对象,其他的资源对象都是用来支撑或者扩展Pod对象功能的,比如控制器对象是用来管控Pod对象的,Service或者Ingress资源对象是用来暴露Pod引用对象的,PersistenVolume资源对象是用来为Pod提供存储等等,k8s不会直接处理容器,而是Pod,Pod是由一个或多个container组成。

Pod是Kubernetes的最重要概念,每个Pod都有一个特殊的被称为“根容器”的Pause容器。Pause容器对应的镜像属于Kubernetes平台的一部分,除了Pause容器,每个Pod还包含一个或多个紧密相关的用户业务容器。

  • Pod vs应用

每个 Pod 都是应用的一个实例, 有专用的 IP

  • Pod vs 容器

一个 Pod 可以有多个容器, 彼此间共享网络和存储资源, 每个 Pod 中有一个 Pause 容器保存所有的容器状态, 通过管理 pause 容器, 达到管理 pod 中所有容器的效果 。

  • Pod vs 节点

同一个 Pod 中的容器总会被调度到相同 Node 节点, 不同节点间 Pod 的通信基于虚拟二层网络技术实现

  • Pod vs Pod
    普通的 Pod 和静态 Pod

Pod特性

1、资源共享

一个 Pod 里的多个容器可以共享存储和网络, 可以看作一个逻辑的主机。 共享的如
namespace,cgroups 或者其他的隔离资源。
多个容器共享同一 network namespace, 由此在一个 Pod里的多个容器共享 PodIP 和端口 namespace, 所以一个Pod 内的多个容器之间可以通过localhost 来进行通信,所需要注意的是不同容器要注意不要有端口冲突即可。 不同的 Pod 有不同的 IP,不同 Pod 内的多个容器之前通信, 不可以使用 IPC(如果没有特殊指定的话)通信, 通常情况下使用 PodIP 进行通信。
一个 Pod 里的多个容器可以共享存储卷, 这个存储卷会被定义为 Pod 的一部分, 并且可以挂载到该Pod里的所有容器的文件系统上。

2、生命周期短暂

Pod 属于生命周期比较短暂的组件, 比如, 当 Pod 所在节点发生故障, 那么该节点上的 Pod会被调度到其他节点, 但需要注意的是, 被重新调度的 Pod 是一个全新的 Pod,跟之前的Pod 没有半毛钱关系。

3、平坦的网络

K8s 集群中的所有 Pod 都在同一个共享网络地址空间中, 也就是说每个 Pod 都可以通过其他 Pod 的 IP 地址来实现访问。

Pod 定义

1、下面是 yaml 文件定义的 Pod 的完整内容。

apiVersion: v1
kind: Pod
metadata: //元数据
name: string
namespace: string
labels:
-name: string
annotations:
-name: string
spec:containers: //pod 中的容器列表, 可以有多个容器
- name: string //容器的名称
image: string //容器中的镜像
imagesPullPolicy: [Always|Never|IfNotPresent]//获取镜像的策略, 默认值为Always, 每次都尝试重新下载镜像
command: [string] //容器的启动命令列表(不配置的话使用镜像内部的命令) args:[string] //启动参数列表
workingDir: string //容器的工作目录 volumeMounts: //挂载到到容器内部的存储卷设置
-name: string
mountPath: string //存储卷在容器内部 Mount 的绝对路径 readOnly: boolean //默认值为读写
ports: //容器需要暴露的端口号列表
-name: string
containerPort: int //容器要暴露的端口
hostPort: int //容器所在主机监听的端口(容器暴露端口映射到宿主机的端口, 设置hostPort 时同一台宿主机将不能再启动该容器的第 2 份副本)
protocol: string //TCP 和 UDP, 默认值为 TCP env: //容器运行前要设置的环境列表
-name: string value: string
resources:
limits: //资源限制, 容器的最大可用资源数量 cpu: Srting
memory: string
requeste: //资源限制, 容器启动的初始可用资源数量 cpu: string
memory: string
livenessProbe: //pod 内容器健康检查的设置 exec:
command: [string] //exec 方式需要指定的命令或脚本 httpGet: //通过 httpget 检查健康
path: string port: number host: string scheme: Srtring httpHeaders:
- name: Stirng value: string
tcpSocket: //通过 tcpSocket 检查健康
port: number initialDelaySeconds: 0//首次检查时间 timeoutSeconds: 0 //检查超时时间
periodSeconds: 0 //检查间隔时间
successThreshold: 0
failureThreshold: 0 securityContext: //安全配置
privileged: falae
restartPolicy: [Always|Never|OnFailure]//重启策略, 默认值为 Always
nodeSelector: object //节点选择, 表示将该 Pod 调度到包含这些 label 的 Node 上, 以key:value 格式指定
imagePullSecrets:
-name: string
hostNetwork: false //是否使用主机网络模式, 弃用 Docker 网桥, 默认否
volumes: //在该 pod 上定义共享存储卷列表
-name: string emptyDir: {} hostPath:
path: string secret:
secretName: string item:
-key: string path: string
configMap: name: string items:
-key: string
path: string

Pod 的基本使用方法

kubernetes 中对运行容器的要求为: 容器的主程序需要一直在前台运行, 而不是后台运行。 应用需要改造成前 台运行的方式。 如果我们创建的 Docker 镜像的启动命令是后台执行程序, 则在 kubelet 创建包含这个容器的 pod 之 后运行完该命令, 即认为 Pod 已经结束,将立刻销毁该 Pod。 如果为该 Pod 定义了 RC, 则创建、 销毁会陷入一个无 限循环的过程中。Pod 可以由 1 个或多个容器组合而成。
**1、一个容器组成的 Pod 的 yaml 示例 **

apiVersion: v1
kind: Pod
metadata:
   name: mynginx
   labels:
      app: mynginx
spec:
 containers:
   - name: mynginx
     image: reg.harbor.com/public/nginx:latest
     ports:
      - containerPort: 80

**2、多个容器组成的 Pod 的 yaml 示例 **

apiVersion: v1
kind: Pod
metadata:
   name: nginx-mysql
   labels:
      app: nginx-mysql
spec:
 containers:
   - name: ningx
     image: reg.harbor.com/public/nginx:latest
     ports:
      - containerPort: 80
   - name: mysql
     image: reg.harbor.com/public/mysql:5.7.17
     ports:
      - containerPort: 3306
     env:
      - name: MYSQL_ROOT_PASSWORD
        value: "123456"

3、创建

#进入yaml文件所在的目录下执行
kubectl create -f xxx.yaml 或者 kubectl apply -f xxx.yaml

[root@master1 pod]# kubectl apply  -f nginx_mysql.yaml
pod/nginx-mysql created

4、查看

kubectl get pod/po <Pod_name>
kubectl get pod/po <Pod_name> -o wide 
kubectl describe pod/po <Pod_name> 

5、删除

kubectl delete -f pod pod_name.yaml
kubectl delete pod [pod_name]
kubectl delete pod --all #删除默认命名空间下的所有Pod资源

Pod的分类

1、普通Pod
普通 Pod 一旦被创建, 就会被放入到 etcd 中存储, 随后会被 Kubernetes Master 调度到某个具体的 Node 上并进行绑定, 随后该 Pod对应的 Node 上的 kubelet 进程实例化成一组相关的 Docker 容器并启动起来。 在默认情 况下, 当 Pod 里某个容器停止时, Kubernetes 会自动检测到这个问题并且重新启动这个 Pod 里某所有容器, 如果 Pod 所在的 Node 宕机,则会将这个 Node 上的所有 Pod 重新调度到其它节点上。

2、静态Pod
静态 Pod 是由 kubelet 进行管理的仅存在于特定 Node上的 Pod,它们不能通过API Server进行管理, 无法与 ReplicationControllerDeploymentDaemonSet 进行关联, 并且kubelet也无法对它们进行健康检查。

Pod生命周期和重启策略

1、Pod 的状态

状态值 说明
Pending API Server已经创建该Pod,但Pod中的一个或多个容器镜像还没创建,包括镜像下载过程
Running Pod内所有容器已创建,且至少一个容器处于运行状态、正在启动状态或正在重启状态
Completed Pod内所有容器均成功执行退出,且不会重启
Failed Pod内所有容器均已退出,但至少一个容器退出失败
Unknown 由于某种原因无法获取Pod状态,例如网络通信不通

2、Pod重启策略

Pod 的重启策略包括 AlwaysOnFailureNever, 默认值是 Always

重启策略 说明
Always 当容器失效时,由kubelet自动重启该容器
OnFailure 当容器终止运行且退出码不为0时,由kubelet自动重启该容器
Never 不论容器运行状态如何,kubelet都不会重启该容器

Pod资源配置

每个Pod 都可以对其能使用的服务器上的计算资源设置限额, Kubernetes中可以设置限额的计算资源有CPUMemory 两种, 其中CPU的资源单位为CPU数量,是一个绝对值而非相对值。 Memory配额也是一个绝对值, 它的单位是内存字节数。

Kubernetes里, 一个计算资源进行配额限定需要设定以下两个参数: Requests该资源最小申请数量, 系统必须满足要求Limits该资源最大允许使用的量, 不能突破, 当容器试图使用超过这个量的资源时, 可能会被 Kubernetes Kill并重启。

apiVersion: v1
kind: Pod
metadata:
   name: mynginx
   labels:
      app: mynginx
spec:
 containers:
   - name: mynginx
     image: reg.harbor.com/public/nginx:latest
     ports:
      - containerPort: 80
     resources:
      requests:
       memory: "64Mi"
       cpu: '250m'
      limits:
       memory: "128Mi"
       cpu: "500m"

上述代码表明Nginx容器申请最少 0.25 个CPU以及64MiB内存, 在运行过程中容器所能使用的资源配额为 0.5 个CPU以及128MiB内存。

Controller控制器

Replication Controller

Replication Controller(RC)Kubernetes系统中核心概念之一, 当我们定义了一个 RC并提交到 Kubernetes 集群中以后, Master节点上的 Controller Manager组件就得到通知,定期检查系统中存活的 Pod,并确保目标 Pod实例的数量刚好等于 RC 的预期值, 如果有过多或过少的 Pod 运行, 系统就会停掉或创建一些 Pod.此外我们也可以通过修改 RC 的副本数量, 来实现 Pod 的动态缩放功能。
1、创建nginx的RC yaml文件

apiVersion: v1
kind: ReplicationController
metadata:
  name: myweb
spec:
  replicas: 2
  selector:
    app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
       - name: myweb
         image: reg.harbor.com/public/nginx:1.18.0
         imagePullPolicy: IfNotPresent
         ports:
         - containerPort: 80

2、创建RC资源

[root@master1 rc]# ls
nginx_rc.yaml
[root@master1 rc]# kubectl create -f nginx_rc.yaml
replicationcontroller/myweb created
[root@master1 rc]# kubectl get rc myweb
NAME    DESIRED   CURRENT   READY   AGE
myweb   2         2         2       22s
[root@master1 rc]# kubectl get pod
NAME          READY   STATUS    RESTARTS   AGE
myweb-flbpm   1/1     Running   0          40s
myweb-td2ql   1/1     Running   0          40s
[root@master1 rc]#

Pod和Controller的关系:
Pod是通过Controller实现应用的运维比如伸缩、滚动升级等等
Pod和Controller之间是通过label标签建立关系

由于Replication Controller 与 Kubernetes 代码中的模块 Replication Controller 同名,所以在 Kubernetes v1.2 时, 它就升级成了另外一个新的概念 Replica Sets,官方解释为下一代的 RC, 它与 RC 区别是:Replica Sets 支援基于集合的 Label selector,而 RC 只支持基于等式的 Label Selector。 我们很少单独使用 Replica Set,它主要被 Deployment 这个更高层面的资源对象所使用, 从而形成一整套 Pod 创建、 删除、 更新的编排机制。 最好不要越过 RC 直接创建 Pod, 因为 Replication Controller 会通过 RC 管理 Pod 副本, 实现自动创建、 补足、 替换、 删除 Pod 副本, 这样就能提高应用的容灾能力, 减少由于节点崩溃等意外状况造成的损失。 即使应用程序只有一个 Pod副本, 也强烈建议使用 RC 来 定义 Pod``

Replicat Set

ReplicaSetReplicationController 没有本质的不同, 只是名字不一样, 并且ReplicaSet支持集合式的 selectorReplicationController仅支持等式) 。Kubernetes官方强烈建议避免直接使用 ReplicaSet, 而应该通过 Deployment 来创建 RSPod。 由于 ReplicaSetReplicationController的代替物, 因此用法基本相同, 唯一的区别在于 ReplicaSet 支持集合式的 selector

Deployment

DeploymentKubenetes v1.2 引入的新概念, 引入的目的是为了更好的解决 Pod 的编排问题, Deployment内部使用了 Replica Set 来实现。 Deployment 的定义与 Replica Set 的定义很类似, 除了 API声明与 Kind类型有所区别:
使用如下命令导出deployment的yaml模板:

kubectl create deployment nginx-deploy --image=nginx --dry-run -o yaml > nginx_deploy.ymal
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deploy
  name: nginx-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-deploy
  template:
    metadata:
      labels:
        app: nginx-deploy
    spec:
      containers:
      - image: reg.harbor.com/public/nginx:1.18.0
        name: nginx
        ports:
        - containerPort: 80

Service

Service 概述

ServiceKubernetes最核心概念, 通过创建 Service,可以为一组具有相同功能的容器应用提供一个统一的入口地 址, 并且将请求负载分发到后端的各个容器应用上。

Service的类型

Service的定义

1、yaml格式的Service定义文件

apiVersion: v1            #必须
kind: Service             #必须
metadata:                 #必须
  name: string              #必须
  namespace: string        #必须
  labels:
    - name: string
  annotations:
    - name: string
spec:                   #必须
  selector:            #必须
    key: volume        #必须
  type: string         #必须
  clusterIP: string
  sessionAffinity: string
  ports:
    - name: string
      protocol: string
      port: int
      targetPort: int
      nodePort: int
status:
  loadBalancer:
    ingress:
      ip: string
      hostname: string

Service基本用法

一般来说, 对外提供服务的应用程序需要通过某种机制来实现, 对于容器应用最简便的方式就是通过 TCP/IP 机制及 监听 IP 和端口号来实现。 创建一个基本功能的 Service

apiVersion: v1
kind: ReplicationController
metadata:
  name: mytomcat
spec:
  replicas: 2
  selector:
    app: mytomcat
  template:
    metadata:
      labels:
        app: mytomcat
    spec:
      containers:
       - name: mytomcat
         image: reg.harbor.com/public/tomcat:latest
         imagePullPolicy: IfNotPresent
         ports:
         - containerPort: 8080

上述是创建一个RC资源的yaml文件,通过执行如下命令创建RC资源

[root@master1 rc]# kubectl apply -f mytomcat.yml
replicationcontroller/mytomcat created

我们可以通过配置文件来定义 Service, 再 通过kubectl create 来创建, 这样可以通过 Service 地址来访问后端的 Pod

apiVersion: v1
kind: Service
metadata:
  labels:
    app: mytomcat
  name: web2
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: mytomcat
  type: NodePort
status:
  loadBalancer: {}

[root@master1 rc]# kubectl apply -f web2.yaml
service/web2 created
[root@master1 rc]# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.1.0.1       <none>        443/TCP          22d
web2         NodePort    10.1.90.208    <none>        8080:35485/TCP   9s

这样可以通过访问Node节点的IP:35485去访问tomcat业务。
多端口Service
有时一个容器应用也可能需要提供多个端口的服务, 那么在 Service的定义中也可以相应地设置为将多个端口对应 到多个应用服务。

apiVersion: v1
kind: Service
metadata:
  labels:
    app: myapp
  name: web3
spec:
  ports:
  - port: 8080
    name: web
    protocol: TCP
    targetPort: 8080
  - port: 8081
    name: management
    protocol: TCP
    targetPort: 8081
  selector:
    app: myapp
  type: NodePort
status:
  loadBalancer: {}

Volume

Volume概述

VolumePod中能够被多个容器访问的共享目录。 KubernetesVolume定义在 Pod 上,它被一个Pod中的多个容 器挂载到具体的文件目录下。 VolumePod的生命周期相同,但与容器的生命周期不相关, 当容器终止或重启时, Volume 中的数据也不会丢失。 要使用volumepod需要指定 volume 的类型和内容(字段) , 和映射到容器的位置(字段) 。Kubernetes支持多种类型的 Volume,包括: emptyDirhostPathgcePersistentDiskawsElasticBlockStorenfsiscsifl``ockerglusterfsrbdcephfsgitReposecretpersistentVolumeClaimdownwardAPIazureFileVolumeazureDiskvsphereVolumeQuobytePortworxVolumeScaleIOemptyDirEmptyDir类型的 volume创建于 pod被调度到某个宿主机上的时候, 而同一个 pod内的容器都能读写 EmptyDir中的同一个文件。 一旦这个 pod离开了这个宿主机, EmptyDir中的数据就会被永久删除。 所以目前 EmptyDir类型的 volume主要用作临时空间, 比如 Web服务器写日志或者 tmp 文件
需要的临时目录。

EmptyDir

yaml示例如下

apiVersion: v1
kind: Pod
metadata:
   name: mynginx
   labels:
      app: mynginx
spec:
 containers:
   - name: mynginx
     image: reg.harbor.com/public/nginx:latest
     ports:
      - containerPort: 80
     volumeMounts:
     - mountPath: /cache
       name: cache-volume
 volumes:
  - name: cache-volume
    emptyDir: {}

hostPath

HostPath属性的 volume使得对应的容器能够访问当前宿主机上的指定目录。 例如, 需要运行一个访问 Docker系统目录的容器, 那么就使用/var/lib/docker 目录作为一个HostDir类型的 volume; 或者要在一个容器内部运行 CAdvisor, 那么就使用/dev/cgroups目录作为一个 HostDir类型的 volume。 一旦这个 pod离开了这个宿主机, HostDir中的数据虽然不会被永久删除, 但数据也不会随 pod 迁移到其他宿主机上。 因此, 需要注意的是,由于各个宿主机上的文件系统结构和内容并不一定完全相同, 所以相同 podHostDir 可能会在不 同的宿主机上表现出不同的行为。 yaml示例如下:

apiVersion: v1
kind: Pod
metadata:
   name: mynginx2
   labels:
      app: mynginx2
spec:
 containers:
   - name: mynginx2
     image: reg.harbor.com/public/nginx:latest
     ports:
      - containerPort: 80
     volumeMounts:
     - mountPath: /test-pd
       name: test-volume
 volumes:
  - name: test-volume
    hostPath:
       path: /data

NFS

NFS 类型 volume。 允许一块现有的网络硬盘在同一个 pod内的容器间共享。 yaml示例如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mynginx3
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mynginx3
  template:
    metadata:
      labels:
        app: mynginx3
    spec:
      containers:
      - image: reg.harbor.com/public/nginx:1.18.0
        name: mynginx3
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html/
      volumes:
      - name: html
        nfs:
          path: /nfs/data
          server: 10.91.74.201

PVC 和 PV

基本概念

管理存储是管理计算的一个明显问题。 该 PersistentVolume 子系统为用户和管理员提供了一个 API, 用于抽象如何根据消费方式提供存储的详细信息。 为此, 我们引入了两个新的API 资源: PersistentVolumePersistentVolumeClaim
PersistentVolume(PV) 是集群中由管理员配置的一段网络存储。 它是集群中的资源, 就像节点是集群资源一样。 PV 是容量插件, 如 Volumes, 但其生命周期独立于使用 PV的任何单个 pod。 此 API对象捕获存储实现的详细信息, 包括 NFSiSCSI或特定于云提供程序的存储系统。
PersistentVolumeClaim(PVC) 是由用户进行存储的请求。 它类似于 podPod消耗节点资源, PVC消耗 PV 资源。 Pod可以请求特定级别的资源(CPU和内存) 。 声明可以请求特定的大小和访问模式(例如, 可以一次读/写或多次只读) 。
    虽然 PersistentVolumeClaims 允许用户使用抽象存储资源, 但是 PersistentVolumes 对于不同的问题, 用户通常需要具有不同属性(例如性能) 。 群集管理员需要能够提供各种PersistentVolumes不同的方式, 而不仅仅是大小和访问模式, 而不会让用户了解这些卷的实现方式。 对于这些需求, 有 StorageClass资源。StorageClass为管理员提供了一种描述他们提供的存储的“类” 的方法。 不同的类可能映射到服务质量级别, 或备份策略, 或者由群集管理员确定的任意策略。 Kubernetes 本身对于什么类别代表是不言而喻的。 这个概念有时在其他存储系统中称为“配置文件” 。PVCPV 是一一对应的。

生命周期

PV是群集中的资源。 PVC是对这些资源的请求, 并且还充当对资源的检查。 PVPVC之间的相互作用遵循以下生命周期:Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling
**供应准备 ****Provisioning**—通过集群外的存储系统或者云平台来提供存储持久化支持。

  • 静态提供 Static: 集群管理员创建多个 PV。 它们携带可供集群用户使用的真实存储的详细信息。 它们存在于 Kubernetes API 中, 可用于消费。
  • 动态提供 Dynamic: 当管理员创建的静态 PV都不匹配用户的 PersistentVolumeClaim时, 集群可能会尝试为 PVC动态配置卷。 此配置基于 StorageClassesPVC必须请求一个类, 并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用动态配置 。

**绑定 ****Binding**—用户创建 pvc并指定需要的资源和访问模式。 在找到可用 pv之前, pvc会保持未绑定状态。
       **使用 ****Using**—用户可在 pod中像 volume一样使用 pvc
**释放 ****Releasing**—用户删除 pvc来回收存储资源, pv将变成“released” 状态。 由于还保留着之前的数据, 这些数据需要根据不同的策略来处理, 否则这些存储资源无法被其他pvc使用。
**回收 ****Recyclin**gpv 可以设置三种回收策略: 保留(Retain) , 回收(Recycle) 和删除(Delete) 。

  • 保留策略: 允许人工处理保留的数据。
  • 删除策略: 将删除 pv和外部关联的存储资源, 需要插件支持。
  • 回收策略: 将执行清除操作, 之后可以被新的 pvc使用, 需要插件支持

PV卷阶段状态

  • Available---- 资源尚未被claim使用
  • Bound----卷已经被绑定到claim了。
  • Releasedclaim被删除, 卷处于释放状态, 但未被集群回收。
  • Failed– 卷自动回收失败

演示:创建PV

第一步:编写 yaml 文件, 并创建 pv 。
创建 5 个 pv, 存储大小各不相同, 是否可读也不相同 。

apiVersion: v1
kind: PersistentVolume
metadata:
    name: pv001
    labels:
      name: pv001
spec:
    capacity:
      storage: 2Gi
    accessModes:
      - ReadWriteOnce
      - ReadWriteMany
    nfs:
      path: /nfs/pv001
      server: 10.91.74.201

---
apiVersion: v1
kind: PersistentVolume
metadata:
    name: pv002
    labels:
      name: pv002
spec:
    capacity:
      storage: 5Gi
    accessModes:
      - ReadWriteOnce
    nfs:
      path: /nfs/pv002
      server: 10.91.74.201

---
apiVersion: v1
kind: PersistentVolume
metadata:
    name: pv003
    labels:
      name: pv003
spec:
    capacity:
      storage: 20Gi
    accessModes:
      - ReadWriteOnce
      - ReadWriteMany
    nfs:
      path: /nfs/pv003
      server: 10.91.74.201
---
apiVersion: v1
kind: PersistentVolume
metadata:
    name: pv004
    labels:
      name: pv004
spec:
    capacity:
      storage: 10Gi
    accessModes:
      - ReadWriteOnce
      - ReadWriteMany
    nfs:
      path: /nfs/pv004
      server: 10.91.74.201
---
---
apiVersion: v1
kind: PersistentVolume
metadata:
    name: pv005
    labels:
      name: pv005
spec:
    capacity:
      storage: 15Gi
    accessModes:
      - ReadWriteOnce
      - ReadWriteMany
    nfs:
      path: /nfs/pv005
      server: 10.91.74.201

第二步:执行创建命令

[root@master1 pv]# kubectl apply  -f pv_test.yaml
persistentvolume/pv001 created
persistentvolume/pv002 created
persistentvolume/pv003 created
persistentvolume/pv004 created
persistentvolume/pv005 created

第三步:查询验证

[root@master1 pv]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv001   2Gi        RWO,RWX        Retain           Available                                   7s
pv002   5Gi        RWO            Retain           Available                                   7s
pv003   20Gi       RWO,RWX        Retain           Available                                   7s
pv004   10Gi       RWO,RWX        Retain           Available                                   7s
pv005   15Gi       RWO,RWX        Retain           Available                                   7s

演示:创建PVC,绑定PV

第一步:编写yaml文件,并创建PVC。创建一个pvc, 需要6G存储; 所以不会匹配pv001、pv002、pv003 。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: mypvc
    labels:
      name: pv001
spec:
    accessModes:
     - ReadWriteMany
    resources:
      requests:
        storage: 6Gi

---

apiVersion: v1
kind: Pod
metadata:
   name: myweb
   labels:
      app: myweb
spec:
 volumes:
 - name: html
   persistentVolumeClaim:
     claimName: mypvc
 containers:
   - name: nginx
     image: reg.harbor.com/public/nginx:latest
     ports:
      - containerPort: 80
     resources:
      requests:
       memory: "64Mi"
       cpu: '250m'
      limits:
       memory: "128Mi"
       cpu: "500m"
     volumeMounts:
     - name: html
       mountPath: /usr/share/nginx/html/

第二步:执行命令创建

[root@master1 pv]# kubectl apply  -f vol-pvc-demo.yaml

第三步:查询验证

[root@master1 pv]# kubectl get pv,pvc
NAME                     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM           STORAGECLASS   REASON   AGE
persistentvolume/pv001   2Gi        RWO,RWX        Retain           Available                                           35m
persistentvolume/pv002   5Gi        RWO            Retain           Available                                           35m
persistentvolume/pv003   20Gi       RWO,RWX        Retain           Available                                           35m
persistentvolume/pv004   10Gi       RWO,RWX        Retain           Bound       default/mypvc                           35m
persistentvolume/pv005   15Gi       RWO,RWX        Retain           Available                                           35m

NAME                          STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/mypvc   Bound    pv004    10Gi       RWO,RWX                       20m
[root@master1 pv]#

Lable

Lable概述

LabelKubernetes系统中另一个核心概念。 一个Label是一个key=value的键值对, 其中keyvalue由用户自己指定。Label可以附加到各种资源对象上, 如NodePodServiceRC,一个资源对象可以定义任意数量的Label, 同一个Label也可以被添加到任意数量的资源对象上, Label通常在资源对象定义时确定, 也可以在对象创建后动态添加或删除。
Label的最常见的用法是使用metadata.labels字段, 来为对象添加Label, 通过spec.selector 来引用对象。

案例演示

apiVersion: v1
kind: ReplicationController
metadata:
  name: myweb
spec:
  replicas: 2
  selector:
    app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
       - name: myweb
         image: reg.harbor.com/public/nginx:1.18.0
         imagePullPolicy: IfNotPresent
         ports:
         - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: myweb
  name: myweb
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myweb
  type: NodePort
status:
  loadBalancer: {}

Label附加到 Kubernetes集群中各种资源对象上, 目的就是对这些资源对象进行分组管理,而分组管理的核心就是 Label SelectorLabelLabel Selector都是不能单独定义,必须附加在一些资源对象的定义文件上, 一般附加 在 RCService的资源定义文件中。

探针

探针类型

K8s中存在两种类型的探针:Liveness Probereadiness probe

liveness probe(存活探针)

用于判断容器是否存活, 即 Pod是否为 running状态, 如果 LivenessProbe探针探测到容器不健康, 则 kubelet 将 kill掉容器, 并根据容器的重启策略是否重启。 如果一个容器不包含 LivenessProbe探针, 则 Kubelet 认为容器的 LivenessProbe探针的返回值永远成功。有时应用程序可能因为某些原因(后端服务故障等) 导致暂时无法对外提供服务, 但应用软件没有终止, 导致 K8S无法隔离有故障的 pod, 调用者可能会访问到有故障的 pod, 导致业务不稳定。 K8S提供 livenessProbe 来检测应用程序是否正常运行, 并且对相应状况进行相应的补救措施。

readiness probe(就绪探针)

用于判断容器是否启动完成, 即容器的 Ready是否为 True, 可以接收请求, 如果ReadinessProbe探测失败, 则容器的 Ready将为 False, 控制器将此 PodEndpoint从对应的 serviceEndpoint列表中移除, 从此不再将任何请求调度此 Pod上, 直到下次探测成功。 通过使用 Readiness探针, Kubernetes能够等待应用程序完全启动, 然后才允许服务将流量发送到新副本。

每类探针都支持三种探测方法

  1. exec: 通过执行命令来检查服务是否正常, 针对复杂检测或无 HTTP 接口的服务, 命令返回值为 0 则表示容器健康。
  2. httpGet: 通过发送 http 请求检查服务是否正常, 返回 200-399 状态码则表明容器健康 .
  3. tcpSocket: 通过容器的 IPPort执行 TCP检查, 如果能够建立 TCP 连接, 则表明容器健康。

探针探测的结果

  1. Success: Container 通过了检查。
  2. Failure: Container 未通过检查。
  3. Unknown: 未能执行检查, 因此不采取任何措施。

案例演示

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec-wfq
spec:
  containers:
  - name: liveness
    image: reg.harbor.com/public/busybox:latest
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

探针(Probe)有许多可选字段, 可以用来更加精确的控制 Liveness 和 Readiness 两种探针的行为。 这些参数包括:
initialDelaySeconds: 容器启动后第一次执行探测是需要等待多少秒。
periodSeconds: 执行探测的频率。 默认是 10 秒, 最小 1 秒。
timeoutSeconds: 探测超时时间。 默认 1 秒, 最小 1 秒。
successThreshold: 探测失败后, 最少连续探测成功多少次才被认定为成功。 默认是 1。对于 liveness 必须是 1。 最小值是 1。
failureThreshold: 探测成功后, 最少连续探测失败多少次才被认定为失败。 默认是 3。
最小值是 1。

ConfigMap

ConfigMap描述信息

ConfigMap功能在kubernetes1.2版本中引入,许多应用程序会从配置文件、命令参数或环境变量中读取配置信息。ConfigMap API给我们提供了向容器中注入配置信息的机制。ConfigMap可以被用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制大对象。

ConfigMap的创建

Ⅰ、使用目录创建

[root@k8s-master1 kubectl]# ls -l /home/k8s/confgmap/kubectl/
总用量 8
-rw-r--r-- 1 root root 164 918 11:43 game.properties
-rw-r--r-- 1 root root  82 918 11:44 ui.properties
[root@k8s-master1 kubectl]#
[root@k8s-master1 kubectl]# cat game.properties
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=nogcdrotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
[root@k8s-master1 kubectl]# cat ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyice
[root@k8s-master1 kubectl]#

[root@k8s-master1 kubectl]# kubectl create configmap game-config --from-file=/home/k8s/confgmap/kubectl
configmap/game-config created
[root@k8s-master1 kubectl]#

--from-file指定在目录下的所有文件都会被用在ConfigMap里面创建一个键值对,建的名称就是文件名,值就是文件内容。

可以通过kubectl get cm -o yaml或者 kubectl describe  cm game-config查看。

Ⅱ、使用文件创建

只要指定为一个文件就可以从单个文件中创建ConfigMap.

[root@k8s-master1 kubectl]# kubectl create configmap game-config-2 --from-file=/home/k8s/confgmap/kubectl/game.properties
configmap/game-config-2 created
[root@k8s-master1 kubectl]# kubectl get configmap game-config-2 -o yaml

–form-file这个参数可以使用多次,你可以使用两次分别指定上个实例中的那两个配置文件,效果就跟指定整个目录一样的。

Ⅲ、使用字面值创建

使用文件值创建,利用–form-literal参数传递配置信息,该参数可以使用多次,格式如下:

[root@k8s-master1 kubectl]# kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
configmap/special-config created
[root@k8s-master1 kubectl]# kubectl get configmap special-config -o yaml
apiVersion: v1
data:
  special.how: very
  special.type: charm
kind: ConfigMap
metadata:
  creationTimestamp: "2020-09-18T04:04:59Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:special.how: {}
        f:special.type: {}
    manager: kubectl
    operation: Update
    time: "2020-09-18T04:04:59Z"
  name: special-config
  namespace: default
  resourceVersion: "258004"
  selfLink: /api/v1/namespaces/default/configmaps/special-config
  uid: d0b947f4-2c03-4647-9195-e0bcb1a7277e

Pod中使用ConfigMap

Ⅰ、使用ConfigMap来替代环境变量

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-conifig
  namespace: default
data:
  special.how: very
  special.type: charm
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
	log_level: INFO

新创建一个pod,调用上面创建的ConfigMap,Pod的yaml文件如下

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: azukiapp/dig:latest
      command: ["/bin/sh",'-c',"env"]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type
      envFrom:
        - configMapRef:
            name: env-config
  restartPolicy: Never

SPECIAL_LEVEL_KEY环境变量对应special-config的special.how的值very
SPECIAL_TYPE_KEY环境变量对应special-config的special.type的值charm

执行如下命令,创建pod。

[root@k8s-master1 confgmap]# kubectl create -f api_test_pod.yaml

Pod创建完之后,可以通过执行kubectl logs环境变量

[root@k8s-master1 confgmap]# kubectl logs dapi-test-pod
...省略
SPECIAL_LEVEL_KEY=very
log_level=INFO
MYWEB_PORT_80_TCP=tcp://10.1.153.198:80
KUBERNETES_PORT_443_TCP=tcp://10.1.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
PWD=/
KUBERNETES_SERVICE_HOST=10.1.0.1
BIND_VERSION=9.10.3

Ⅱ、用ConfigMap设置命令行参数

创建另外一个Pod,Pod的名称为cmd_test_pod,yaml文件如下:

apiVersion: v1
kind: Pod
metadata:
  name: cmd-test-pod
spec:
  containers:
    - name: test-container
      image: azukiapp/dig:latest
      command: ["/bin/sh",'-c',"echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)"]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type
      envFrom:
        - configMapRef:
            name: env-config
  restartPolicy: Never

执行完之后,通过查看日志文件可以查看输入两个环境变量的值

[root@k8s-master1 confgmap]# kubectl logs cmd-test-pod
very charm

Ⅲ、通过数据卷插件使用ConfigMap

在数据卷里面使用这个COnfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: azukiapp/dig:latest
      command: ["/bin/sh",'-c',"cat /etc/config/special.how"]
      volumeMounts:
        - name: config-volume
          mountPath: /etc/config
      volumes:
        - name: config-volume
          configMap:
            name: special-config
  restartPolicy: Never

执行完之后,通过查看日志文件可以查看输入两个环境变量的值.

[root@k8s-master1 confgmap]# kubectl logs dapi-test-pod
very[root@k8s-master1 confgmap]#

Ⅳ、ConfigMap的热更新


apiVersion: v1
kind: ConfigMap
metadata:
  name: log-config
  namespace: default
data:
  log_level: INFO
---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-nginx
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx:1.13
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-volume
          mountPath: /etc/config
      volumes:
        - name: config-volume
          configMap:
            name: log-config

创建完之后,执行如下命令查看

[root@k8s-master1 confgmap]# kubectl exec my-nginx-699f668fbb-dchhr -it -- cat /etc/config/log_level
INFO[root@k8s-master1 confgmap]#

修改ConfigMap

root@k8s-master1 confgmap]# kubectl edit configmap log-config
configmap/log-config edited

修改log_level的值为DEBUG等待大概10秒钟时间,再次查看环境变量的值。

[root@k8s-master1 confgmap]#  kubectl exec my-nginx-699f668fbb-dchhr -it -- cat /etc/config/log_level
DEBUG[root@k8s-master1 confgmap]#

特别注意configMap 如果以ENV的方式挂载到容器,修改configMap并不会实现热更新

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。