kubernetes入门:核心概念的梳理
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
里的多个容器共享 Pod
的IP
和端口 namespace
, 所以一个Pod
内的多个容器之间可以通过localhos
t 来进行通信,所需要注意的是不同容器要注意不要有端口冲突即可。 不同的 Pod
有不同的 IP,不同 Pod
内的多个容器之前通信, 不可以使用 IPC
(如果没有特殊指定的话)通信, 通常情况下使用 Pod
的 IP
进行通信。
一个 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
进行管理, 无法与 ReplicationController
、 Deployment
或 DaemonSet
进行关联, 并且kubelet
也无法对它们进行健康检查。
Pod生命周期和重启策略
1、Pod 的状态
状态值 | 说明 | |
---|---|---|
Pending | API Server已经创建该Pod,但Pod中的一个或多个容器镜像还没创建,包括镜像下载过程 | |
Running | Pod内所有容器已创建,且至少一个容器处于运行状态、正在启动状态或正在重启状态 | |
Completed | Pod内所有容器均成功执行退出,且不会重启 | |
Failed | Pod内所有容器均已退出,但至少一个容器退出失败 | |
Unknown | 由于某种原因无法获取Pod状态,例如网络通信不通 |
2、Pod重启策略
Pod
的重启策略包括 Always
、 OnFailure
和 Never
, 默认值是 Always
重启策略 | 说明 | |
---|---|---|
Always | 当容器失效时,由kubelet自动重启该容器 | |
OnFailure | 当容器终止运行且退出码不为0时,由kubelet自动重启该容器 | |
Never | 不论容器运行状态如何,kubelet都不会重启该容器 |
Pod资源配置
每个Pod
都可以对其能使用的服务器上的计算资源设置限额, Kubernetes
中可以设置限额的计算资源有CPU
与 Memory
两种, 其中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
ReplicaSet
跟 ReplicationController
没有本质的不同, 只是名字不一样, 并且ReplicaSet
支持集合式的 selector
(ReplicationController
仅支持等式) 。Kubernetes
官方强烈建议避免直接使用 ReplicaSet
, 而应该通过 Deployment
来创建 RS
和Pod
。 由于 ReplicaSet
是 ReplicationController
的代替物, 因此用法基本相同, 唯一的区别在于 ReplicaSet
支持集合式的 selector
。
Deployment
Deployment
是 Kubenetes 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 概述
Service
是 Kubernetes
最核心概念, 通过创建 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概述
Volume
是 Pod
中能够被多个容器访问的共享目录。 Kubernetes
的 Volume
定义在 Pod 上,它被一个Pod
中的多个容 器挂载到具体的文件目录下。 Volume
与 Pod
的生命周期相同,但与容器的生命周期不相关, 当容器终止或重启时, Volume
中的数据也不会丢失。 要使用volume
, pod
需要指定 volume
的类型和内容(字段) , 和映射到容器的位置(字段) 。Kubernetes
支持多种类型的 Volume
,包括: emptyDir
、 hostPath
、 gcePersistentDisk
、awsElasticBlockStore
、 nfs
、 iscsi
、 fl``ocker
、 glusterfs
、 rbd
、 cephfs
、 gitRepo
、secret
、 persistentVolumeClaim
、 downwardAPI
、 azureFileVolume
、 azureDisk
、vsphereVolume
、 Quobyte
、 PortworxVolume
、 ScaleIO
。 emptyDirEmptyDir
类型的 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
迁移到其他宿主机上。 因此, 需要注意的是,由于各个宿主机上的文件系统结构和内容并不一定完全相同, 所以相同 pod
的 HostDir
可能会在不 同的宿主机上表现出不同的行为。 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 资源: PersistentVolume
和 PersistentVolumeClaim
。
PersistentVolume(PV)
是集群中由管理员配置的一段网络存储。 它是集群中的资源, 就像节点是集群资源一样。 PV 是容量插件, 如 Volumes
, 但其生命周期独立于使用 PV
的任何单个 pod
。 此 API
对象捕获存储实现的详细信息, 包括 NFS
, iSCSI
或特定于云提供程序的存储系统。
PersistentVolumeClaim(PVC)
是由用户进行存储的请求。 它类似于 pod
。 Pod
消耗节点资源, PVC
消耗 PV
资源。 Pod
可以请求特定级别的资源(CPU
和内存) 。 声明可以请求特定的大小和访问模式(例如, 可以一次读/写或多次只读) 。
虽然 PersistentVolumeClaims
允许用户使用抽象存储资源, 但是 PersistentVolumes
对于不同的问题, 用户通常需要具有不同属性(例如性能) 。 群集管理员需要能够提供各种PersistentVolumes
不同的方式, 而不仅仅是大小和访问模式, 而不会让用户了解这些卷的实现方式。 对于这些需求, 有 StorageClass
资源。StorageClass
为管理员提供了一种描述他们提供的存储的“类” 的方法。 不同的类可能映射到服务质量级别, 或备份策略, 或者由群集管理员确定的任意策略。 Kubernetes
本身对于什么类别代表是不言而喻的。 这个概念有时在其他存储系统中称为“配置文件” 。PVC
和 PV
是一一对应的。
生命周期
PV
是群集中的资源。 PVC
是对这些资源的请求, 并且还充当对资源的检查。 PV
和 PVC
之间的相互作用遵循以下生命周期:Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling
。
**供应准备 ****Provisioning**
—通过集群外的存储系统或者云平台来提供存储持久化支持。
- 静态提供
Static
: 集群管理员创建多个 PV。 它们携带可供集群用户使用的真实存储的详细信息。 它们存在于Kubernetes API
中, 可用于消费。 - 动态提供
Dynamic
: 当管理员创建的静态PV
都不匹配用户的PersistentVolumeClaim
时, 集群可能会尝试为PVC
动态配置卷。 此配置基于StorageClasses
:PVC
必须请求一个类, 并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用动态配置 。
**绑定 ****Binding**
—用户创建 pvc
并指定需要的资源和访问模式。 在找到可用 pv
之前, pvc会保持未绑定状态。
**使用 ****Using**
—用户可在 pod
中像 volume
一样使用 pvc
。
**释放 ****Releasing**
—用户删除 pvc
来回收存储资源, pv
将变成“released
” 状态。 由于还保留着之前的数据, 这些数据需要根据不同的策略来处理, 否则这些存储资源无法被其他pvc
使用。
**回收 ****Recyclin**
g—pv
可以设置三种回收策略: 保留(Retain) , 回收(Recycle) 和删除(Delete) 。
- 保留策略: 允许人工处理保留的数据。
- 删除策略: 将删除
pv
和外部关联的存储资源, 需要插件支持。 - 回收策略: 将执行清除操作, 之后可以被新的
pvc
使用, 需要插件支持
PV卷阶段状态
Available
---- 资源尚未被claim
使用Bound
----卷已经被绑定到claim了。Released
–claim
被删除, 卷处于释放状态, 但未被集群回收。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概述
Label
是Kubernetes
系统中另一个核心概念。 一个Label
是一个key=value
的键值对, 其中key
与value
由用户自己指定。Label
可以附加到各种资源对象上, 如Node
、Pod
、Service
、RC
,一个资源对象可以定义任意数量的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
Selector
。 Label
与 Label
Selector
都是不能单独定义,必须附加在一些资源对象的定义文件上, 一般附加 在 RC
和 Service
的资源定义文件中。
探针
探针类型
K8s中存在两种类型的探针:Liveness Probe
和readiness probe
。
liveness probe(存活探针)
用于判断容器是否存活, 即 Pod
是否为 running
状态, 如果 LivenessProbe
探针探测到容器不健康, 则 kubelet 将 kill
掉容器, 并根据容器的重启策略是否重启。 如果一个容器不包含 LivenessProbe
探针, 则 Kubelet 认为容器的 LivenessProbe
探针的返回值永远成功。有时应用程序可能因为某些原因(后端服务故障等) 导致暂时无法对外提供服务, 但应用软件没有终止, 导致 K8S
无法隔离有故障的 pod
, 调用者可能会访问到有故障的 pod
, 导致业务不稳定。 K8S
提供 livenessProbe
来检测应用程序是否正常运行, 并且对相应状况进行相应的补救措施。
readiness probe(就绪探针)
用于判断容器是否启动完成, 即容器的 Ready
是否为 True
, 可以接收请求, 如果ReadinessProbe
探测失败, 则容器的 Ready
将为 False
, 控制器将此 Pod
的 Endpoint
从对应的 service
的 Endpoint
列表中移除, 从此不再将任何请求调度此 Pod
上, 直到下次探测成功。 通过使用 Readiness
探针, Kubernetes
能够等待应用程序完全启动, 然后才允许服务将流量发送到新副本。
每类探针都支持三种探测方法
- exec: 通过执行命令来检查服务是否正常, 针对复杂检测或无 HTTP 接口的服务, 命令返回值为 0 则表示容器健康。
- httpGet: 通过发送 http 请求检查服务是否正常, 返回 200-399 状态码则表明容器健康 .
- tcpSocket: 通过容器的
IP
和Port
执行TCP
检查, 如果能够建立TCP
连接, 则表明容器健康。
探针探测的结果
- Success: Container 通过了检查。
- Failure: Container 未通过检查。
- 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 9月 18 11:43 game.properties
-rw-r--r-- 1 root root 82 9月 18 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并不会实现热更新
- 点赞
- 收藏
- 关注作者
评论(0)