初始化
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
kubeadm安装
root用户执行以下命令
#yum -y install socat conntrack-tools
kubeadm init --image-repository registry.aliyuncs.com/google_containers \
--pod-network-cidr=10.244.0.0/16 \
--ignore-preflight-errors=Swap
执行完后,可以看到已经安装成功
切换到非root用户
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
#此时非root用户可以执行kubelet命令
#安装flannel网络附加组件
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
此时kubernate启动成功
到其他节点,以root用户,使用kubeadm join加入集群
kubeadm join 10.150.31.115:6443 --token doz94r.6xebnfstr9nfz7tg \
--discovery-token-ca-cert-hash sha256:a5e181604418fc6531e928e3a614c3b4882598f2de1a13efbdc8d939945ca5b7
此时节点加入成功。如果该节点要执行kubelet命令,可以把上面.kube/config文件复制到本节点的对应路径
minkube
curl -LO [https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64](https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64)
sudo install minikube-linux-amd64 /usr/local/bin/minikube
minikube start
yum install conntrack
镜像处理:
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/echoserver:1.4
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/echoserver:1.4 k8s.gcr.io/echoserver:1.4
docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/echoserver:1.4
作者将gcr.io相关镜像pull下来,然后push到docker官方仓库
gcr.io/namespace/image_name:image_tag
# 等价于
anjia0532/namespace.image_name:image_tag
eg.
gcr.io/google-samples/node-hello:1.0
-> anjia0532/google-samples.node-hello:1.0
Demo
创建Deployment
Deployment指挥k8s如何创建和更新应用程序的实例。创建Deployment后,k8s master将应用程序实例调度到集群中的各个节点上。
创建应用程序实例后,k8s Deployment控制器会持续监视这些实例。如果托管实例的节点关闭或被删除,则Deployment控制器会将实例替换为集群中另一个节点上的实例。这提供了一种自我修复机制来解决机器故障维护问题。
创建管理Pod的Deployment,该Pod根据提供的Docker镜像运行Container
kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.4
#kubectl create deployment hello-node --image=registry.aliyuncs.com/google_containers/echoserver:1.4
查看Deployment
kubectl get deployments
查看Pod
kubectl get pods
查看集群事件
kubectl get events
查看kubectl配置
kubectl config view
创建Service
Service下的一组Pod通常由LabelSelector来标记。
尽管每个Pod都有一个唯一的IP地址,但是如果没有Service,这些IP不会暴露在集群外部。Service运行应用程序接收流量
类型:
-
ClusterIP (默认) - 在集群的内部IP上公开Service。这种类型使得Service只能从集群内访问
-- Headless (无头服务) spec.clusterIP: None。服务DNS名称会直接解析为Pod的IP地址 - NodePort - 使用NAT在集群中每个选定Node的相同端口上公开Service。使用<NodeIP>:<NodePort>从集群外部访问Service。是ClusterIP的超集
- LoadBalancer - 在当前云中创建一个外部负载均衡器(如果支持),并为Service分配一个固定的外部IP。是NodePort的超集
-
ExternalName - 通过返回带有该名称的CNAME记录,使用任意名称(spec中的externalName指定)公开Service。不使用代理
默认情况下,Pod只能通过k8s集群中的内部IP地址访问,要使得hello-node容器可以从k8s虚拟网络的外部访问,必须将Pod暴露为k8s Service
使用kubectl expore将Pod暴露给公网
kubectl expose deployment hello-node --type=LoadBalancer --port=8080
--type=LoadBalancer表示希望将Service暴露到集群外部
镜像k8s.gcr.io/echoserver中的应用程序代码仅监听TCP8080端口
查看创建的Service
kubectl get services
打标签
kubectl label pod $POD_NAME app=v1
根据标签获取pods
kubectl get pods -l app=v1
清理
kubectl delete service hello-node
kubectl delete deployment hello-node
缩放应用
查看Deployment创建的ReplicaSet(副本集),会展示:[DEPLOYMENT-NAME]-[RANDOM-STRING]。例如:kubernetes-bootcamp-765bf4c7b4
kubectl get rs
扩展到4倍
kubectl scale deployments/kubernetes-bootcamp --replicas=4
滚动更新应用
设置镜像
镜像和之前不一样的话,会触发重新部署
kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
回滚到上个版本
kubectl rollout undo deployments/kubernetes-bootcamp
配置
k8s设置docker容器环境变量的方式:
Dockerfile、kubernetes.yml、Kubernetes ConfigMaps和Kubernetes Secrets
环境变量的值将会注入到微服务里
使用ConfigMaps和Secrets的好处是他们能在多个容器间复用,比如赋值给不同的容器中的不同环境变量
ConfigMaps是存储非机密键值对的API对象
Secrets针对机密/敏感数据存储键值对,存储格式为Base64编码
创建ConfigMap(名称为sys-app-name,--from-literal直接指定键值对,还有--from-file和 --from-env-file)
kubectl create configmap sys-app-name --from-literal name=my-system
创建Secret(generic表示不是一个特定类型的secret)
kubectl create secret generic sys-app-credentials --from-literal username=bob --from-literal password=bobpwd
配置文件(configMapKeyRef,secretKeyRef)
apiVersion: apps/v1
kind: Deployment
metadata:
name: system-deployment
labels:
app: system
spec:
selector:
matchLabels:
app: system
template:
metadata:
labels:
app: system
spec:
containers:
- name: system-container
image: system:1.0-SNAPSHOT
ports:
- containerPort: 9080
# Set the APP_NAME environment variable
env:
- name: APP_NAME
valueFrom:
configMapKeyRef:
name: sys-app-name
key: name
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: inventory-deployment
labels:
app: inventory
spec:
selector:
matchLabels:
app: inventory
template:
metadata:
labels:
app: inventory
spec:
containers:
- name: inventory-container
image: inventory:1.0-SNAPSHOT
ports:
- containerPort: 9080
# Set the SYSTEM_APP_USERNAME and SYSTEM_APP_PASSWORD environment variables
env:
- name: SYSTEM_APP_USERNAME
valueFrom:
secretKeyRef:
name: sys-app-credentials
key: username
- name: SYSTEM_APP_PASSWORD
valueFrom:
secretKeyRef:
name: sys-app-credentials
key: password
---
apiVersion: v1
kind: Service
metadata:
name: system-service
spec:
type: NodePort
selector:
app: system
ports:
- protocol: TCP
port: 9080
targetPort: 9080
nodePort: 31000
---
apiVersion: v1
kind: Service
metadata:
name: inventory-service
spec:
type: NodePort
selector:
app: inventory
ports:
- protocol: TCP
port: 9080
targetPort: 9080
nodePort: 32000
删除旧的deployment,部署更新后的deployment
kubectl replace --force -f kubernetes.yaml
使用ConfigMap配置Redis
创建kustomization.yaml文件,包含一个ConfigMap生成器,一个使用ConfigMap的Pod资源配置
使用kubectl apply -k ./ 应用整个路径的配置
验证配置
redis-config
maxmemory 2mb
maxmemory-policy allkeys-lru
redis-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis:5.0.4
command:
- redis-server
- "/redis-master/redis.conf"
env:
- name: MASTER
value: "true"
ports:
- containerPort: 6379
resources:
limits:
cpu: "0.1"
volumeMounts:
- mountPath: /redis-master-data
name: data
- mountPath: /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap:
name: example-redis-config
items:
- key: redis-config
path: redis.conf
kustomization.yaml
configMapGenerator:
- name: example-redis-config
files:
- redis-config
resources:
- redis-pod.yaml
应用整个文件夹以创建ConfigMap和Pod对象
kubectl apply -k .
检查
> kubectl get -k .
NAME DATA AGE
configmap/example-redis-config-dgh9dg555m 1 52s
NAME READY STATUS RESTARTS AGE
pod/redis 1/1 Running 0 52s
验证配置
kubectl exec -it redis -- redis-cli
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "2097152"
127.0.0.1:6379> CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-lru"
删除
kubectl delete pod redis
无状态应用程序
- 运行Hello World应用程序的五个实例
- 创建一个公开外部IP地址的Service对象
- 使用Service对象访问正在运行的应用程序
load-balancer-example.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: load-balancer-example
name: hello-world
spec:
replicas: 5
selector:
matchLabels:
app.kubernetes.io/name: load-balancer-example
template:
metadata:
labels:
app.kubernetes.io/name: load-balancer-example
spec:
containers:
- image: anjia0532/google-samples.node-hello:1.0
name: hello-world
ports:
- containerPort: 8080
显示Deployment的信息
kubectl get deployments hello-world
kubectl describe deployments hello-world
显示ReplicaSet对象的信息
kubectl get replicasets
kubectl describe replicasets
创建公开Deployment的Service对象
kubectl expose deployment hello-world --type=LoadBalancer --name=my-service
显示有关Service的信息
kubectl get services my-service
kubectl describe services my-service
清理
kubectl delete services my-service
kubectl delete deployment hello-world
解决k8s.gcr.io无法拉取镜像问题
docker pull registry.cn-hangzhou.aliyuncs.com/go ogle_containers/{}
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/{} k8s.gcr.io/{}
docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/{}
Kubernates
可移植,可扩展的开源平台,管理容器化的工作负载和服务,方便了声明式配置和自动化。
组件
控制平面组件(Control Plane Components)
对集群作出全局决策(e.g.调度),检测和响应集群事件(e.g. 不满足部署的replicas时,启动新的pod)
kube-apiserver
k8s控制面的前端
etcd
键值数据库,保存k8s所有集群数据的后台数据库
kube-scheduler
监视那些新创建的未指定运行节点的Pod,并选择节点让Pod在上面运行
kube-controller-manager
在主节点上运行控制器的组件
包括:
节点控制器(Node Controller)、副本控制器(Replication Controller)、端点控制器(Endpoints Controller)、服务账号和令牌控制器(Service Account & Token Controllers)
cloud-controller-manager
Node组件
在每个节点上运行,维护运行的Pod并提供Kubernetes运行环境
kubelet
在集群中每个节点上运行的代理。保证容器都运行在Pod中
kube-proxy
集群中每个节点上运行的网络代理。维护节点上的网络规则
kube-proxy
负责为 Service 实现了一种 VIP(虚拟 IP)的形式,而不是 ExternalName
的形式
容器运行时(Container Runtime)
负责容器运行的软件。Docker、containerd、CRI-O
插件(Addons)
插件使用k8s资源(DaemonSet、Deployment等)实现集群功能
DNS
Web界面(仪表盘 Dashboard)
容器资源监控
集群层面日志
关系
-
Pod
一个或多个容器的组合,这些容器共享存储、网络和命名空间,以及如何运行的规范。是k8s的最小可部署单元
Pod的中文为豌豆荚,docker容器就像豆子运行在豌豆荚内 -
ReplicaSet
Replication Controller的作用是确保Pod以指定的副本个数运行。ReplicaSet是Replication Controller的升级版。Replication Controller只支持基于等式的selector(env=dev或environment!=qa),但ReplicaSet还支持新的,基于集合的selector(version in (v1,v2)) -
Deployment
用于管理Pod、ReplicaSet,可实现滚动升级和回滚应用、扩容和缩容 -
Service
每个Pod都有自己的ip,前端请求不知道这个pod的ip是什么,Service定义了一个服务的访问入口地址,前端的应用通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,来自外部的访问请求被负载均衡到后端的各个容器应用上。Service与后端Pod副本集群之间通过Label Selector实现关联。
前端请求不是直接发送给Pod,而是发送给Service,Service再将请求转发给Pod
-
总结
Pod被ReplicaSet管理,ReplicaSet控制Pod的数量;ReplicaSet被Deployment管理,Deployment控制Pod应用的升级、回滚,当然也能控制Pod的数量。Service提供一个统一固定入口,负责将前端请求转发给Pod
port, targetPort, nodePort的关系
- port
k8s中服务之间访问的端口 - targetPort
容器暴露出来的端口
targetPort是pod上的端口,从port和nodePort上到来的数据最终经过kube-proxy流入到后端pod的targetPort上 - nodePort
外部机器可以访问的端口
port和nodePort都是service的端口,前者暴露给集群内客户访问服务,后者暴露给集群外客户访问服务。从这两个端口到来的数据都需要经过反向代理kube-proxy流入后端pod的targetPort,从而到达pod上的容器内
Pods
Pod是可以在k8s中创建和管理的、最小的可部署的计算单元
Pod是一组(一个或多个)容器;这些容器共享存储、网络以及怎样运行这些容器的声明。Pod中的内容总是并置的并且一同调度,在共享的上下文中运行
Pod的共享上下文包括一组Linux命名空间、控制组(cgroup)和可能一些其他的隔离方面,即用来隔离Docker容器的技术
Pod类似共享命名空间和文件系统卷的一组Docker容器
使用Pod
不需要直接创建Pod,使用诸如Deployment或Job这类工作负载资源来创建Pod。如果Pod需要跟踪状态,可以考虑StatefulSet资源
用法:
- 运行单个容器的Pod。“每个Pod一个容器”模型是最常见的k8s用例;可以将Pod看作单个容器的包装器,并且k8s直接管理Pod,而不是容器
- 运行多个协同工作的容器的Pod。Pod封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序。这些位于同一位置的容器可能形成单个内聚的服务单元--一个容器将文件从共享卷提供给公众,而另一个单独的“挂斗”(sidecar)容器则刷新或更新这些文件。Pod将这些容器和存储资源打包成一个可管理的实体
每个Pod都旨在运行给定应用程序的单个实例。如果希望横向扩展应用程序,则应该使用多个Pod,每个实例使用一个Pod
Pod天生地为其成员容器提供了两种共享资源:网络和存储
Pod不是进程,而是容器运行的环境
Pod模板
负载资源的控制器通常使用Pod模板(Pod Template)来创建Pod并管理它们
Pod模板是包含在工作负载对象中的规范,用来创建Pod。这些负载资源包括Deployment、Job和DaemonSets等
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
# 这里是 Pod 模版
spec:
containers:
- name: hello
image: busybox
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
# 以上为 Pod 模版
修改Pod模板或者切换到新的Pod模板都不会对已存在的Pod起作用
e.g. Demployment控制器针对每个Deployment对象确保运行中的Pod与当前的Pod模板匹配。如果模板被更新,则Deployment必须删除现有的Pod,基于更新后的模板创建新的Pod
资源共享和存储
Pod使它的成员容器间能够进行数据共享和通信
一个Pod可以设置一组共享的存储卷,Pod中的所有容器都可以访问该共享卷,从而允许这些容器共享数据
每个Pod都在每个地址族中获得一个唯一的IP地址,Pod中的每个容器共享网络命名空间,包括IP地址和网络端口。Pod内的容器可以使用localhost互相通信
Pod的生命周期
起始于Pending阶段,如果至少有一个主要容器正常启动,则进入Running,之后取决于是否有容器以失败状态结束而进入Succeeded或者Failed阶段
Pod在其生命周期中只会被调度一次。一旦Pod被调度(分派)到某个节点,会一直在该节点运行,直到Pod停止或被终止
Pod生命期
Pod和一个个独立的应用容器一样,也被认为是相对临时性的实体。Pod会被创建、赋予一个唯一的ID(UID),并被调度到节点,并在终止或删除之前一个运行在该节点
Pod自身不能自愈,如果被调度到某节点而该节点之后失效,或者调度操作本身失效,Pod会被删除;Pod无法在节点资源耗尽或者节点维护期间继续存活。k8s使用控制器,来管理这些相对而言可随时丢弃的Pod实例
任何给定的Pod(由UID定义)不会被重新调度到不同的节点;相反,这Pod可以被一个新的、几乎完全相同的Pod替换掉。新Pod的名字可以不变,但UID会不同
Pod阶段
status字段是一个PodStatus对象,其中包含一个phase字段。是Pod在其生命周期中所处位置的简单宏观概述
取值 | 描述 |
---|---|
Pending(悬决) | Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间 |
Running(运行中) | Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态 |
Succeeded(成功) | Pod 中的所有容器都已成功终止,并且不会再重启 |
Failed(失败) | Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止 |
Unknown(未知) | 因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败 |
如果某节点死掉或者与集群中其他节点失联,k8s会将失去的节点上运行的所有Pod的phase置为Failed
容器状态
可以使用容器生命周期回调来在容器生命周期中的特定时间点触发事件
一个调度器将Pod分派给某个节点,kubelet就通过容器运行时开始为Pod创建容器。
检查Pod中容器的状态:kubectl describe pod <pod 名称>
容器的状态有三种:
- Waiting (等待)
如果容器不处在Running或Terminated状态之一,它就处于Waiting状态。处于Waiting状态的容器仍在运行它完成启动所需要的操作 - Running (运行中)
表明容器正在执行状态并且没有问题发生。如果配置了postStart回调,那么该回调已经执行且已完成 - Terminated (已终止)
已经开始执行并且或者正常结束或者因为某些原因失败。如果配置了preStop回调,则该回调会在容器进入Terminated状态之前执行
容器重启策略
Pod的spec中包含一个restartPolicy字段,可能取值:Always(默认)\OnFailure\Never
Pod状况
Pod有一个PodStatus对象,其中包含一个PodConditions数组
- PodScheduled: Pod已经被调度到某节点
- ContainersReady: Pod中所有容器都已就绪
- Initialized: 所有的Init容器都已成功启动
- Ready: Pod可以为请求提供服务,并且应该被添加到对应服务的负载均衡池中
字段名称 | 描述 |
---|---|
type | Pod 状况的名称 |
status | 表明该状况是否适用,可能的取值有 "True", "False" 或 "Unknown" |
lastProbeTime | 上次探测 Pod 状况时的时间戳 |
lastTransitionTime | Pod 上次从一种状态转换到另一种状态时的时间戳 |
reason | 机器可读的、驼峰编码(UpperCamelCase)的文字,表述上次状况变化的原因 |
message | 人类可读的消息,给出上次状态转换的详细信息 |
容器探针
Probe是由kubelet对容器执行的定期诊断。要执行诊断,kubelet调用由容器实现的Handler(处理程序)。有三种类型的处理程序:
- ExecAction 在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功
- TCPSocketAction 对容器的IP地址上的指定端口执行TCP检查。如果端口打开,则诊断被认为是成功的
- HTTPGetAction 对容器的IP地址上指定端口和路径执行HTTP Get请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的
每次探测都将获得以下三种结果之一:
- Success (成功):容器通过了诊断
- Failure (失败):容器未通过诊断
- Unknown (未知):诊断失败,因此不会采取任何行动
探针类型:
- livenessProbe :指示容器是否正在运行。如果存活态探测失败,则kubelet会杀死容器,并且容器将根据重启策略决定未来。如果容器不提供存活探针,则默认为Success
- readinessProbe:指示容器是否准备好为请求提供服务。如果就绪态探测失败,端点控制器将从与Pod匹配的所有服务的端点列表中删除该Pod的IP地址。初始延迟之前的就绪态的状态值默认为Failure。如果不提供就绪态探针,默认为Success
- startupProbe:指示容器是否已经启动。如果提供了启动探针,则所有其他探针都会被禁用,直到此探针成功为止。如果启动探测失败,kubelet将杀死容器,而容器根据重启策略进行重启。如果没有提供启动探测,默认为Success
何时使用存活态探针?
如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活态探针;kubelet将根据Pod的restartPolicy自动执行修复操作
如果希望容器在探测失败时被杀死并重新启动,那么请指定一个存活态探针,并制定restartPolicy为"Always"或"OnFailure"
何时使用就绪态探针?
如果要仅在探测成功时才开始向Pod发送请求流量,请指定就绪态探针。规约中的就绪态探针的存在意味着Pod将在启动阶段不接收任何数据,并且只有在探测成功后才开始接收数据
如果容器需要加载大规模的数据、配置文件或在启动期间执行迁移操作,可以添加一个就绪态探针
如果希望容器能够自行进入维护状态,也可以指定一个就绪态探针,检查某个特定于就绪态不同于存活态探测的端点
在删除Pod时,Pod会自动将自身置为未就绪状态,无论就绪态探针是否存在。等待Pod中的容器停止期间,Pod会一直处于未就绪状态
何时该使用启动探针?
对于所包含的容器需要较长时间才能启动就绪的Pod而言,启动探针是有用的。不再需要配置一个较长的存活态探测时间间隔,只需要设置另一个独立的配置选定,对启动期间的容器执行探测,从而允许使用远远超出存活态时间间隔所允许的时长
如果容器启动时间通常超出initialDelaySeconds + failureThreshold × periodSeconds总值,应该设置一个启动探测。periodSeconds的默认值是30秒,应该将failureThreshold设置得足够高,以便容器有充足的时间完成启动,并且避免更改存活态探针所使用的默认值
Pod的终止
Pod所代表的是在集群中节点上运行的进程,当不再需要这些进程时允许其体面地终止是很重要的,不应武断地使用KILL信号终止,导致这些进程没有机会完成清理操作
通常容器运行时会发送一个TERM信号到每个容器中的主进程。很多容器运行时都能注意到容器镜像中STOPSIGNAL的值,并发送该信号而不是TERM。一旦超出了体面终止限期,容器运行时会向所有剩余进程发送KILL信号,之后Pod就会被从API服务器上移除。如果kubelet或者容器运行时的管理服务在等待进程终止期间被重启,集群会从头开始重试,赋予Pod完整的体面终止限期
强制终止Pod
默认所有删除操作都有30秒的宽限期。kubectl delete支持--grace-period=<seconds>选项重载默认值
宽限期设置为0意味着立即从API服务器删除Pod。如果Pod仍然运行于某节点上,强制删除会触发kubelet立即执行清理操作
失效Pod的垃圾收集
对于已失效的Pod,对应的API对象仍然会保留在集群的API服务器上,直到用户或者控制器进程显式将其删除
控制器组件会在Pod个数超出所配置的阈值(kube-controller-manager的terminated-pod-gc-threshold设置)时删除已终止的Pod(阶段值为Succeeded或Failed)
存储
Persistent Volumes
PersistentVolume(PV)是集群里的一部分存储,由管理员或者使用Storage Classes动态供应。它是集群里的一种资源,就像node是一个集群的资源。
PersistentVolumeClaim(PVC)是用户对存储的请求。它类似于Pod。Pods消费节点资源,PVCs消费PV资源。Pods可以请求特定级别的资源(CPU和内存),Claims可以请求特定大小和访问模式(ReadWriteOnce, ReadOnlyManly,ReateWriteMany)
volume和claim的生命周期
PVs是集群里的资源。PVCs是这些资源的请求,还充当对这些资源的检查。
Provisioning 供应
- Static
集群管理员创建一定数量的PVs。它们包含真实存储的详细信息,可供集群用户使用 - Dynamic
当没有管理员创建的静态PVs匹配用户的PVC,集群可能会动态为PVC提供一个卷。此资源调配基于StorageClasses:PVC必须请求一个存储类,并且管理员必须创建并配置了该类,以便进行动态资源调配。
Binding 绑定
主节点上的控制循环监听新的PVCs,找到一个匹配的PV(如果可以),将它们绑定在一起。如果一个PV是为一个PVC动态供应的,那么循环将始终将该PV绑定到PVC。或者用户将至少获得它们请求的量,volume可能超出请求的量。
PVC到PV的绑定是一对一的映射,使用ClaimRef,它是PersistentVolume和PersistentVolumeClaim的双向绑定
如果没有匹配的volume存在,Claims将一直保持未绑定。
Using 使用
Pods使用claims作为volumes。集群检查claim以找到绑定的volume,并为Pods挂载该volume
Reclaiming 回收
PV的回收策略告诉集群在其claim释放后该如何处理volume。
- Retain
之前的数据还保留在volume上 - Recycled(弃用,推荐使用dynamic provisioning)
- Deleted
Storage Classes
为管理员提供了一种描述他们提供的存储“类”的方法。不同的类可能映射到服务质量级别、备份策略或集群管理确定的任意策略。Kubernetes本身并不关心类代表什么。其他存储系统中,此概念有时称为“profiles”
StorageClass 资源
包含字段:provisioner、parameters、reclaimPolicy,当需要动态配置属于该类的PV时使用。
Dynamic Volume Provisioning 动态卷供应
允许存储卷按需创建。如果没有动态供应,集群管理员必须手动调用云或存储供应商来创建新的存储卷,然后创建PV对象以在k8s中表示它们。
动态卷供应的实现是基于API组storage.k8s.io中的API对象StorageClass。集群管理员可以定义根据需要定义许多StorageClass对象,每个都指定一个卷插件(provisioner),该插件提供一个卷和一组参数,以便在设置时传给该参数。