一、K8s资源对象
https://kubernetes.io/zh/docs/concepts/workloads/controllers/ 核心概念的资源管理 k8s设计理念-分层结构: http://docs.kubernetes.org.cn/251.html
#k8s分层架构 云原生态系统:庞大的容器集群管理调度生态系统,可分为两类 Kubernetes外部:日志、监控、配置管理CI、CD、Workflow、FaaS、OTS应用、ChatOps等 Kubernetes内部:CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理 接口层:kubectl命令行工具,客户端SDK以及集群联邦 管理层:系统测量(如基础设施、容器和网络测量),自动化(如自动扩展、动态Provision等)以及战略管理(RBAC、Quota、PSP、NetworkPolicy等) 应用层:部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS解析等) 核心层:Kubernetes API和执行环境 容器运行时,容器网络接口、容器存储接口、镜像仓库、云供应商、身份供应商 #三个接口标准: container runtime interface CRI,容器运行时(run、rkt) container storage interface CSI,容器存储接口 container network interface CNI,网络接口 #docker info Default Runtime: runc
1、API-k8s的牛鼻子
如何管理: kubectl、API、SDK、UI
管理对象: 资源对象:Pod、ReplicaSet、ReplicationController、Deployment(运营无状态服务),StatefulSet(运营有状态服务),DaemonSet(每个节点自动运行的过程),Job(单个任务,对数据进行分类和输出时),CronJob(周期性任务),HorizontalPodAutoscaling(HPA对pod弹性伸缩),Node(运行容器的虚拟机或物理机),Namespace、Service、Ingress、Label、CustomResourceDefinition 存储对象:Volume、PersistentVolume、Secret(密钥)、ConfigMap(与镜像解耦配置) (直接挂nfs不太安全,可以看到) 策略对象:SecurityContext、ResourceQuota、LimitRange 身份对象:ServiceAccount(多账户),Role、ClusterRole
API:对象–是K8s集群中的管理操作单位 https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/
k8s的设计理念-API设计原则: https://www.kubernetes.org.cn/kubernetes设计理念 1.所有API应该是声明。 2.API对象是互补的,可以组合的。 3.高层API基于操作意图的设计。 4.低层API根据高层API需要设计控制。 5.尽量避免简单封装,不要有在外部API内部隐藏的机制无法显式知道。 6.API与对象数量成正比。 7.API对象状态不能依赖于网络连接状态。 8.尽量避免使操作机制依赖于全局,因为在分布式系统中很难保证全局同步。
k8s的几个重要概念: 对象(用k8s处理什么):K8S声明式API yaml文件(如何处理):调用声明式API
2、pod:
https://kubernetes.io/zh/docs/concepts/workloads/pods/
(1)概述: 1.pod是k8s最小单元 2.一个pod一个容器或多个容器可以运行 3.运行多个容器的话,这些容器是一起被调度的 4.Pod生命周期短,不会自愈,是用完后销毁的实体 一般我们都是通过的Controller创建和管理pod的
(2)Controller副本控制器:维持副本个数(Rc,Rs和Deployment) Replication Controller#第一代pod副本控制器(支持选择器slector = !=) https://kubernetes.io/zh/docs/concepts/workloads/controllers/replicationcontroller/ https://kubernetes.io/zh/docs/concepts/overview/working-with-objects/labels/ ReplicaSet#第二代pod副本控制器(支持选择器slector、in notin) https://kubernetes.io/zh/docs/concepts/workloads/controllers/replicaset/ Deployment#第三代pod控制器(支持选择器slector、in notin,滚动升级、回滚)(目前使用) https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/
案例case1: rc:只支持=、!= selector: app: ng-rc-80 rs:还支持in、notin selector: matchExpressions: - {
key: app, operator: In, values: [ng-rs-80,ng-rs-81]} deployment:版本升级/滚动升级或回滚也可以实现 [root@k8s-master1 case1]#vim deployment.yml image: nginx:1.16.1 [root@k8s-master1 case1]#kubectl apply -f deployment.yml [root@k8s-master1 case1]#kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-5d76cf6966-gr8mr 1/1 Running 0 2m2s nginx-deployment-5d76cf6966-p6j8v 1/1 Running 0 2m2s [root@k8s-master1 case1]#vim deployment.yml image: nginx:1.17.1 [root@k8s-master1 case1]#kubectl apply -f deployment.yml deployment.apps/nginx-deployment configured [root@k8s-master1 case1]#kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-5d76cf6966-gr8mr 1/1 Running 0 2m59s
nginx-deployment-5d76cf6966-p6j8v 1/1 Running 0 2m59s
nginx-deployment-8cbfb8fb-lh4sv 0/1 Terminating 0 37s
nginx-deployment-95ffc4469-dwrtr 0/1 ContainerCreating 0 2s
[root@k8s-master1 case1]#kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-95ffc4469-dwrtr 1/1 Running 0 62s
nginx-deployment-95ffc4469-r4d9n 1/1 Running 0 43s
(3)Pod生命周期: https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/ 初始化容器->启动前操作->就绪探针->存活探针->删除pod操作
(4)pod状态 新建–>调度–>部署启动–>结束
第一阶段:
pending:
#正在创建Pod但是pod中的容器还没有全部被创建完成,处于此状态的pod应该检查pod依赖的存储是否有权限挂载、镜像是否可以下载、调度是否正常等。
Failed
#Pod中有容器启动失败而导致pod工作异常。
Unknown
#由于某种原因无法获得pod的当前状态,通常是由于与pod所在的node节点通信错误。
Succeeded
#Pod中的所有容器都被成功终止即pod里所有的containers均已terminated。
第二阶段:
Unschedulable:
#Pod不能被调度,kube-scheduler没有匹配到合适的node节点
PodScheduled
#pod正处于调度中,在kube-scheduler刚开始调度的时候,还没有将pod分配到指定的node,在筛选出合适的节点后就会更新etcd数据,将pod分配到指定的node
Initialized
#所有pod中的初始化容器已经完成了
ImagePu11BackOff:
#Pod所在的node节点下载镜像失败
Running
#Pod内部的容器已经被创建并且启动。
Ready
#表示pod中的容器已经可以提供访问服务
Error: #pod启动过程中发生错误
NodeLost: #Pod 所在节点失联
Unkown: #Pod 所在节点失联或其它未知异常
Waiting: #Pod 等待启动
pending: #Pod 等待被调度
Terminating: #Pod 正在被销毁
CrashLoopBackoff: #Pod,但是kubelet正在将它重启
InvalidImageName: #node节点无法解析镜像名称导致的镜像无法下载
Image InspectError: #无法校验镜像,镜像不完整导致
ErrImageNeverPul1:#策略禁止拉取镜像,镜像中心权限是私有等
ImagePu11Backoff: #镜像拉取失败,但是正在重新拉取
Registryunavailab1e: #镜像服务器不可用,网络原因或harbor宕机
ErrImagePu11:#镜像拉取出错,超时或下载被强制终止
CreateContainerconfigError: #不能创建kubelet使用的容器配置
CreatecontainerError: #创建容器失败,
Prestartcontainer: #执行prestart hook报错,pod hook(钩子)是由Kubernetes管理的kubelet发起的,当容器中的进程启动前或者容器中的进程终止之前运行,比如容器创建完成后里面的服务启动之前可以检查一下依赖的其它服务是否启动,或者容器退出之前可以把容器中的服务先通过命令停止。
PoststartHookError: #执行poststart hook 报错
RunContainerError: #pod运行失败,容器中没有初始化PTD为1的守护进程等
ContainersNotInitialized: #pod没有初始化完毕
ContainersNotReady: #pod没有准备完毕
ContainerCreating: #pod正在创建中
PodInitializing: #pod正在初始化中
DockerDaemonNotReady: #node节点decker服务没有启动
NetworkpluginNotReady: #网络插件还没有完全启动
(5)pod调度过程 见k8s实战案例2.1.3:kube-scheduler
(6)pod探针 https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/
1/探针简介:
探针是由kubelet 对容器执行的定期诊断,以保证Pod的状态始终处于运行状态,要执行诊断,kubelet 调用由容器实现的Handler(处理程序),有三种类型的处理程序:
ExecAction #在容器内执行指定命令,如果命令退出时返回码为0则认为诊断成功。
TCPSocketAction #对指定端口上的容器的IP地址进行TCP检查,如果端口打开,则诊断被认为是成功的。
HTTPGetAction #对指定的端口和路径上的容器的IP地址执行HTTPGet请求,如果响应的状态码大于等于200且小于400,则诊断被认为是成功的。
每次探测都将获得以下三种结果之一:
成功:容器通过了诊断。
失败:容器未通过诊断。
未知:诊断失败,因此不会采取任何行动。
2/livenessprobe和readinessprobe探针 基于探针实现对pod的状态检测
探针类型:
livenessProbe:存活探针
检测应用发生故障时使用,不能提供服务、超时等检测失败时重启pod
readinessProbe:就绪探针
检测pod启动之后应用是否就绪,是否可以提供服务检测成功,pod才开始接收流量
livenessProbe和readinessProbe的对比: 相同点:配置参数一样 不同点: livenessProbe连续探测失败会重启、重建pod,readinessProbe不会 livenessProbe连续检测失败后会将容器置于CrashLoopBackOff且不可用,readinessProbe不会 readinessProbe连续探测失败会从service的endpointd中删除该Pod,livenessProbe不具备此功能,但是会将容器挂起livenessProbe livenessProbe用户控制是否重启pod,readinessProbe用于控制pod是否添加至service 建议:两个探针都配置
面试题:如何保证k8s服务的可用性? 通过存活探针对出现异常时重启pod;通过就绪探针对pod进行状态检查,失败后从service删掉,从而保证用户访问始终正常;再通过日志和监控进一步定位什么原因导致的异常 重启时先把pod地址从service删掉,正常启动后再加到service,使允许访问
3/探针配置: https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ 探针有很多配置字段,可以使用这些字段精确的控制存活和就绪检测的行为:
initialpelaySeconds:120 #初始化延迟时间,告诉kubelet在执行第一次探测前应该等待多少秒,默认是0秒,最小值是0 periodseconds:60 #探测周期间隔时间,指定了kubelet应该每多少秒秒执行一次存活探测,默认是10秒。最小值是1 timeoutSeconds:5 #单次探测超时时间,探测的超时后等待多少秒,默认值是1秒,最小值是1。 successThreshold:1 #从失败转为成功的重试次数,探测器在失败后,被视为成功的最小连续成功数,默认值是1,存活探测的这个值必须是1,最小值是1。 failureThreshold:3 #从成功转为失败的重试次数,当Pod启动了并且探测到失败,Kubernetes的重试次数,存活探测情况下的放弃就意味着重新启动容器,就绪探测情况下的放弃Pod会被打上未就绪的
标签,默认值是3,最小值是1。 HTTP探测器可以在httpGet上配置额外的字段: host: #连接使用的主机名,默认是pod的IP,也可以在HTTP头中设置“Host”来代替。 scheme: http #用于设置连接主机的方式(HTTP还是HTTPS),默认是HTTP path: /monitor/index.html #访问HTTP服务的路径。 httpHeaders: #请求中自定义的HTTP头,HTTP头字段允许重复。 port: 80 #访问容器的端口号或者端口名,如果数字必须在1~65535之间。
4\示例:
#1、HTTP探针示例:
#(1)探针url正确时,显示均正常
[root@k8s-master1 tanzhen]#vim nginx.yaml #存活探针正确url
livenessProbe:
httpGet:
path: /index.html
[root@k8s-master1 tanzhen]#vim nginx.yaml #就绪探针正确url
readinessProbe:
httpGet:
path: /index.html
[root@k8s-master1 tanzhen]#kubectl apply -f nginx.yaml
deployment.apps/nginx-deployment configured
service/ng-deploy-80 configured
[root@k8s-master1 tanzhen]#kubectl get pod #0重启
NAME READY STATUS RESTARTS AGE
nginx-deployment-57bf88c9db-5xhr7 1/1 Running 0 15s
[root@k8s-master1 tanzhen]#kubectl get ep #展示ENDPOINTS值
NAME ENDPOINTS AGE
ng-deploy-80 10.200.36.95:80 20s
[root@k8s-master1 tanzhen]#curl http://192.168.150.161:40012/index.html #可正常访问
#(2)存活探针错误url
[root@k8s-master1 tanzhen]#vim nginx.yaml
livenessProbe:
httpGet:
path: /index1.html
[root@k8s-master1 tanzhen]#kubectl get pod #livenessProbe控制重启,连续检测失败后状态是CrashLoopBackOff
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f655b87d7-qh6b8 1/1 Running 0 13s
[root@k8s-master1 tanzhen]#kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f655b87d7-qh6b8 1/1 Running 1 24s
[root@k8s-master1 tanzhen]#kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f655b87d7-qh6b8 1/1 Running 2 40s
[root@k8s-master1 tanzhen]#kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f655b87d7-qh6b8 0/1 CrashLoopBackOff 3 66s
[root@k8s-master1 tanzhen]#kubectl get ep #无法访问但依旧展示ENDPOINTS值,只控制重启不控制是否允许访问
NAME ENDPOINTS AGE
ng-deploy-80 10.200.36.96:80 3m20s
#(3)就绪探针错误url
[root@k8s-master1 tanzhen]#vim nginx.yaml
readinessProbe:
httpGet:
path: /index1.html
[root@k8s-master1 tanzhen]#kubectl apply -f nginx.yaml
deployment.apps/nginx-deployment created
service/ng-deploy-80 created
[root@k8s-master1 tanzhen]#kubectl get pod #检测失败但状态是Running
NAME READY STATUS RESTARTS AGE
nginx-deployment-d44c95b47-8rg9x 0/1 Running 0 18s
[root@k8s-master1 tanzhen]#kubectl get ep #不能访问,uir错误时会删除ENDPOINTS值,保证不会把请求转发给请求失败的容器
NAME ENDPOINTS AGE
ng-deploy-80 11s
#2、TCP探针示例:
#(1)探针端口正确时,显示均正常
[root@k8s-master1 tanzhen]#vim tcp.yaml #存活探针正确端口
livenessProbe:
tcpSocket:
port: 80
[root@k8s-master1 tanzhen]#vim tcp.yaml #就绪探针正确端口
readinessProbe:
tcpSocket:
port: 80
[root@k8s-master1 tanzhen]#kubectl apply -f tcp.yaml
deployment.apps/nginx-deployment configured
service/ng-deploy-80 unchanged
[root@k8s-master1 tanzhen]#kubectl get pod #0重启
NAME READY STATUS RESTARTS AGE
nginx-deployment-7bd48778d5-pfjx7 1/1 Running 0 20s
[root@k8s-master1 tanzhen]#kubectl get ep #展示ENDPOINTS值
NAME ENDPOINTS AGE
ng-deploy-80 10.200.36.100:80 36m
[root@k8s-master1 tanzhen]#curl http://192.168.150.161:40012/index.html #正常访问
#(2)存活探针错误端口
[root@k8s-master1 tanzhen]#vim tcp.yaml
livenessProbe:
tcpSocket:
port: 8080
[root@k8s-master1 tanzhen]#kubectl apply -f tcp.yaml
deployment.apps/nginx-deployment created
service/ng-deploy-80 created 38s
[root@k8s-master1 tanzhen]#kubectl get pod #多次重启,连续检测失败后状态是CrashLoopBackOff
NAME READY STATUS RESTARTS AGE
nginx-deployment-7bb4b6bd5c-46dvq 0/1 CrashLoopBackOff 3 62s
[root@k8s-master1 tanzhen]#kubectl get ep #访问异常但仍旧展示ENDPOINTS值
NAME ENDPOINTS AGE
ng-deploy-80 10.200.36.109:80 2m17s
#(3)就绪探针错误端口
[root@k8s-master1 tanzhen]#vim tcp.yaml
readinessProbe:
tcpSocket:
port: 8080
[root@k8s-master1 tanzhen]#kubectl apply -f tcp.yaml
deployment.apps/nginx-deployment created
service/ng-deploy-80 created
[root@k8s-master1 tanzhen]#kubectl get pod #0重启
NAME READY STATUS RESTARTS AGE
nginx-deployment-86c8bb75f5-mm4mm 0/1 Running 0 15s
[root@k8s-master1 tanzhen]#kubectl get ep #不能访问,错误端口时会把ENDPOINTS值删除
NAME ENDPOINTS AGE
kubernetes 192.168.150.151:6443 25d
ng-deploy-80 11s
#(4)一般写两个
[root@k8s-master1 tanzhen]#vim tcp.yaml
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
readinessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
[root@k8s-master1 tanzhen]#kubectl apply -f tcp.yaml
deployment.apps/nginx-deployment created
service/ng-deploy-80 created
[root@k8s-master1 tanzhen]#kubectl get pod #livenessProbe控制重启
NAME READY STATUS RESTARTS AGE
nginx-deployment-585c997f4c-72j9j 1/1 Running 0 8s
[root@k8s-master1 tanzhen]#kubectl get ep #readinessProbe控制访问
NAME ENDPOINTS AGE
kubernetes 192.168.150.151:6443 26d
ng-deploy-80 10.200.36.106:80 11s
#3、ExecAction探针:可以基于指定的命令对Pod进行特定的状态检查
#(1)两个探针配置正确时
[root@k8s-master1 tanzhen]#vim redis.yaml
readinessProbe:
exec:
command:
- /usr/local/bin/redis-cli
- quit
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
livenessProbe:
exec:
command:
- /usr/local/bin/redis-cli
- quit
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
[root@k8s-master1 tanzhen]#kubectl apply -f redis.yaml
deployment.apps/redis-deployment created
service/redis-deploy-6379 created
[root@k8s-master1 tanzhen]#kubectl get pod
NAME READY STATUS RESTARTS AGE
redis-deployment-775c65c67c-vbx9d 1/1 Running 0 51s
[root@k8s-master1 tanzhen]#kubectl get ep
NAME ENDPOINTS AGE
kubernetes 192.168.150.151:6443 26d
redis-deploy-6379 10.200.36.107:6379 56s
#(2)两个探针配置错误时
[root@k8s-master1 tanzhen]#vim redis.yaml
readinessProbe:
exec:
command:
- /usr/local/bin/redis-cli11111
- quit
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
livenessProbe:
exec:
command:
- /usr/local/bin/redis-cli1111
- quit
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
[root@k8s-master1 tanzhen]#kubectl apply -f redis.yaml
deployment.apps/redis-deployment created
service/redis-deploy-6379 created
[root@k8s-master1 tanzhen]#kubectl get pod #重启指定次数后仍检测失败,则状态置为CrashLoopBackOff
NAME READY STATUS RESTARTS AGE
redis-deployment-987b6f585-fxkg9 0/1 CrashLoopBackOff 5 2m54s
[root@k8s-master1 tanzhen]#kubectl get ep #该pod从service删除
NAME ENDPOINTS AGE
kubernetes 192.168.150.151:6443 26d
redis-deploy-6379 30s
(7)pod重启策略 k8s在Pod出现异常的时候会自动将Pod重启以恢复Pod中的服务。
restartPolicy:
Always:当容器异常时,k8s自动重启该容器,ReplicationController/Replicaset/Deployment。
onFailure:当容器失败时(容器停止运行且退出码不为0),k8s自动重启该容器。
Never:不论容器运行状态如何都不会重启该容器,Job或cronJob。
(8)镜像拉取策略 https://kubernetes.io/zh/docs/concepts/configuration/overview/
imagePu11Policy: IfNotPresent #node节点没有此镜像就去指定的镜像仓库拉取,node有就使用node本地镜像。
imagePullPolicy: Always #每次重建pod都会重新拉取镜像
imagePu11Policy: Never #从不到镜像中心拉取镜像,只使用本地镜像
3、Service:
Why: pod重建后ip变了,pod之间再次直接访问会有问题 What:解耦了服务和应用。 How:声明一个service对象
一般常用的service有两种:
k8s集群内的service:selector指定pod,自动创建Endpoints
k8s集群外的service:手动创建Endpoints,指定外部服务的ip、端口和协议
kube-proxy和service的关系:
kube-proxy---watch-->k8s-apiserver
kube-proxy监听着k8s-apiserver,一旦service资源发生变化(调k8s-api修改service信息),kube-proxy就会生成对应的负载调度的调整,这样就保证service的最新状态。
#service案例case2:
[root@k8s-master1 case2]#kubectl apply -f 1-deploy_node.yml
deployment.apps/nginx-deployment created
[root@k8s-master1 case2]#kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-5d76cf6966-nz9cn 1/1 Running 0 4s
[root@k8s-master1 case2]#kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 11d
#默认的ClusterIP类型:
[root@k8s-master1 case2]#vim 2-svc_service.yml
ports:
- name: http
port: 88
targetPort: 80
protocol: TCP
type: ClusterIP
[root@k8s-master1 case2]#kubectl apply -f 2-svc_service.yml
service/ng-deploy-80 created
[root@k8s-master1 case2]#kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 11d
ng-deploy-80 ClusterIP 10.100.229.10 <none> 88/TCP 2s
[root@k8s-master1 case2]#curl 10.100.229.10:88 #正常访问
#使用NodePort类型:
[root@k8s-master1 case2]#kubectl delete -f 2-svc_service.yml
[root@k8s-master1 case2]#vim 3-svc_NodePort.yml
ports:
- name: http
port: 90
targetPort: 80
nodePort: 30012
protocol: TCP
type: NodePort
[root@k8s-master1 case2]#kubectl apply -f 3-svc_NodePort.yml
service/ng-deploy-80 created
[root@k8s-master1 case2]#kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 11d
ng-deploy-80 NodePort 10.100.125.157 <none> 90:30012/TCP 6s
[root@k8s-master1 case2]#curl 10.100.125.157:90 #正常访问
#配置haproxy进行访问(不带端口访问,公网访问或域名访问)
[root@k8s-ha1 ~]#vim /etc/haproxy/haproxy.cfg
listen magedu-nginx-80
bind 192.168.150.189:80
mode tcp
server k8s1 192.168.150.151:30012 check inter 3s fall 3 rise 5
#server k8s2 192.168.150.152:30012 check inter 3s fall 3 rise 5
#server k8s3 192.168.150.153:30012 check inter 3s fall 3 rise 5
[root@k8s-ha1 ~]#systemctl restart haproxy
!!!重启报错!!!
4、Volume:
https://kubernetes.io/zh/docs/concepts/storage/volumes/ Why:数据和镜像解耦,以及容器间的数据共享 What: k8s抽象出的一个对象,用来保存数据,做存储用
常用的几种卷:
emptyDir:本地临时卷(放日志,一般不用)
hostPath:本地卷(不能被数据共享)
nfs等:共享卷
configmap:主要用于配置文件变更和定义环境变量
(1)emptyDir 当Pod被分配给节点时,首先创建 emptyDir卷,并且只要该Pod在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。 Pod中的容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除Pod时,emptyDir中的数据将被永久删除。
#宿主机临时路径:/var/lib/kubelet/pods/$ID/volumes/kubernetes.io~empty-dir/cache-volume/$FILE
case3案例:
[root@k8s-master1 case3]#vim deploy_empty.yml
volumeMounts:
- mountPath: /cache
name: cache-volume-n56 #把卷cache-volume-n56挂载到目录/cache
volumes: #先定义再调用
- name: cache-volume-n56
emptyDir: {
}
[root@k8s-master1 case3]#kubectl apply -f deploy_empty.yml
[root@k8s-master1 case3]#kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-7d4dcd7f7d-m96zz 1/1 Running 0 9m15s 10.200.36.77 192.168.150.161 <none> <none>
#测试
[root@k8s-master1 case3]#kubectl exec -it nginx-deployment-7d4dcd7f7d-m96zz bash
root@nginx-deployment-7d4dcd7f7d-m96zz:/# cd cache/
root@nginx-deployment-7d4dcd7f7d-m96zz:/cache# echo "123">> n56.txt
root@nginx-deployment-7d4dcd7f7d-m96zz:/cache# cat n56.txt
123
root@nginx-deployment-7d4dcd7f7d-m96zz:/cache# exit
[root@k8s-node1 ~]#cat /var/lib/kubelet/pods/84a807c9-55a8-4b8e-9502-bd033a146a7c/volumes/kubernetes.io~empty-dir/cache-volume-n56/n56.txt
123
[root@k8s-node1 ~]#echo "456">> /var/lib/kubelet/pods/84a807c9-55a8-4b8e-9502-bd033a146a7c/volumes/kubernetes.io~empty-dir/cache-volume-n56/n56.txt
[root@k8s-node1 ~]#cat /var/lib/kubelet/pods/84a807c9-55a8-4b8e-9502-bd033a146a7c/volumes/kubernetes.io~empty-dir/cache-volume-n56/n56.txt
123
456
[root@k8s-master1 case3]#kubectl exec -it nginx-deployment-7d4dcd7f7d-m96zz bash
root@nginx-deployment-7d4dcd7f7d-m96zz:/# cat /cache/n56.txt
123
456
#pod删除后宿主机数据也被删除,不做保留
root@nginx-deployment-7d4dcd7f7d-m96zz:/# rm -rf /cache/n56.txt
[root@k8s-node1 ~]#ls /var/lib/kubelet/pods/84a807c9-55a8-4b8e-9502-bd033a146a7c/volumes/kubernetes.io~empty-dir/cache-volume-n56/
[root@k8s-master1 case3]#kubectl delete -f deploy_empty.yml
deployment.apps "nginx-deployment" deleted
[root@k8s-node1 ~]#ls /var/lib/kubelet/pods/84a807c9-55a8-4b8e-9502-bd033a146a7c/volumes/kubernetes.io~empty-dir/cache-volume-n56/
ls: cannot access '/var/lib/kubelet/pods/84a807c9-55a8-4b8e-9502-bd033a146a7c/volumes/kubernetes.io~empty-dir/cache-volume-n56/': No such file or directory
(2)hostPath hostPath卷将主机节点的文件系统中的文件或目录挂载到集群中,pod删除的时候,卷不会被删除
hostPath:(不常用,因为再次运行该pod时,如果该pod绑定了其他node则数据需要迁移才会展示)
case4案例:
[root@k8s-master1 case4]#vim deploy_hostPath.yml
volumeMounts:
- mountPath: /data/n56
name: cache-n56-volume
volumes:
- name: cache-n56-volume
hostPath:
path: /opt/n56
[root@k8s-master1 case4]#kubectl apply -f deploy_hostPath.yml
deployment.apps/nginx-deployment created
[root@k8s-master1 case4]#kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-56b8bf9f66-xn4cr 1/1 Running 0 6s 10.200.36.81 192.168.150.161 <none> <none>
[root@k8s-master1 case4]#kubectl exec -it nginx-deployment-56b8bf9f66-xn4cr bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx-deployment-56b8bf9f66-xn4cr:/# echo "1111">>/data/n56/1.txt
root@nginx-deployment-56b8bf9f66-xn4cr:/# cat /data/n56/1.txt
1111
#宿主机验证
[root@k8s-node1 ~]#cat /opt/n56/1.txt
1111
#删除pod数据不丢失
[root@k8s-master1 case4]#kubectl delete -f deploy_hostPath.yml
deployment.apps "nginx-deployment" deleted
[root@k8s-node1 ~]#cat /opt/n56/1.txt
1111
(3)nfs等共享存储卷 nfs卷允许将现有的NFS(网络文件系统)共享挂载到您的容器中。不像emptyDir,当删除Pod时,nfs卷的内容被保留,卷仅仅是被卸载。这意味着NFS卷可以预填充数据,并且可以在pod之间“切换”数据。NFS可以被多个写入者同时挂载。 创建多个pod测试挂载同一个NFS 创建多个pod测试每个pod挂载多个NFS
case5案例:
#1、准备nfs(复用haproxy机器)
[root@k8s-ha1 ~]#apt install nfs-server
[root@k8s-ha1 ~]#mkdir /data/magedu/n56 -p
[root@k8s-ha1 ~]#mkdir /data/magedu/js
#将目录共享出去
[root@k8s-ha1 ~]#vim /etc/exports
/data/magedu *(rw,no_root_squash)
[root@k8s-ha1 ~]#systemctl restart nfs-server.service
[root@k8s-ha1 ~]#systemctl enable nfs-server.service
#测试挂载没问题
[root@k8s-master1 case5]#showmount -e 192.168.150.159
Export list for 192.168.150.159:
/data/magedu *
#2、配置挂载nfs共享存储
[root@k8s-master1 case5]#kubectl explain deployment.spec.template.spec.volumes.nfs
[root@k8s-master1 case5]#vim deploy_nfs.yml
volumeMounts:
- mountPath: /usr/share/nginx/html/mysite
name: my-nfs-volume
- mountPath: /usr/share/nginx/html/js
name: my-nfs-js
volumes:
- name: my-nfs-volume
nfs:
server: 192.168.150.159
path: /data/magedu/n56
- name: my-nfs-js
nfs:
server: 192.168.150.159
path: /data/magedu/js
[root@k8s-master1 case5]#kubectl apply -f deploy_nfs.yml
deployment.apps/nginx-deployment created
service/ng-deploy-80 created
[root@k8s-master1 case5]#kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-5d66576b45-q9brx 1/1 Running 0 24m 10.200.36.82 192.168.150.161 <none> <none>
[root@k8s-master1 case5]#kubectl exec -it nginx-deployment-5d66576b45-q9brx bash
root@nginx-deployment-5d66576b45-q9brx:/# df
192.168.150.159:/data/magedu/js 125764864 8582400 117182464 7% /usr/share/nginx/html/js
192.168.150.159:/data/magedu/n56 125764864 8582400 117182464 7% /usr/share/nginx/html/mysite
root@nginx-deployment-5d66576b45-q9brx:/# cd /usr/share/nginx/html/mysite/ #上传数据测试
root@nginx-deployment-5d66576b45-q9brx:/usr/share/nginx/html/mysite# ll
#或通过挂载本地上传数据
[root@k8s-master1 case5]#mount -t nfs 192.168.150.159:/data/magedu/n56 /mnt
[root@k8s-master1 case5]#cd /mnt/
[root@k8s-master1 mnt]#ls
ee87cf318f3ac192ce9399da8f5c39a.jpg
#验证访问网页
#验证nfs数据
[root@k8s-ha1 ~]#ls /data/magedu/n56/
ee87cf318f3ac192ce9399da8f5c39a.jpg
#重新启动新pod后数据不丢失,可直接使用
#3、宿主机挂载位置
[root@k8s-node1 ~]#df
192.168.150.159:/data/magedu/js 125764864 8590848 117174016 7% /var/lib/kubelet/pods/394719ff-6b9d-4941-87af-bfb04a03ff04/volumes/kubernetes.io~nfs/my-nfs-js
192.168.150.159:/data/magedu/n56 125764864 8590848 117174016 7% /var/lib/kubelet/pods/394719ff-6b9d-4941-87af-bfb04a03ff04/volumes/kubernetes.io~nfs/my-nfs-volume
(4)configmap Why:配置信息和镜像解耦 What:将配置信息放到configmap对象中,然后在pod的对象中导入configmap对象,实现导入配置的操作 How:声明一个ConfigMap的对象,作为Volume挂载到pod中 configmap配置文件详解: 声明容器(先声明再挂载) 修改配置文件,一个pod所有容器都将重建 tomcat和nginx的挂载点可以不同 示例: configmap环境变量示例:不常用 configmap环境变量示例:常用,直接指定 系统级环境变量,可直接使用
配置变更的几种方式
直接把服务的配置文件(nginx.conf)放到镜像
configmap:把配置和镜像解耦
配置中心:阿波罗(要求足够的性能和高可用)
定义环境变量的几种方法
(1)dockerfile
(2)configmap
(3)yaml
(4)配置文件
case6案例:
[root@k8s-master1 case6]#kubectl explain configmap #如何写configmap
[root@k8s-master1 case6]#vim deploy_configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
default: |
server {
listen 80;
server_name www.mysite.com;
index index.html;
location / {
root /data/nginx/html;
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
}
}
}
#1、修改为不挂载看效果
[root@k8s-master1 case6]#vim deploy_configmap.yml
# - name: nginx-config
# mountPath: /etc/nginx/conf.d
[root@k8s-master1 case6]#kubectl apply -f deploy_configmap.yml
configmap/nginx-config unchanged
deployment.apps/nginx-deployment configured
service/ng-deploy-80 unchanged
[root@k8s-master1 case6]#kubectl get pod
nginx-deployment-84b6d76b5-q66ph 2/2 Running 0 107s
#验证
root@nginx-deployment-84b6d76b5-q66ph:/# ls /etc/nginx/conf.d/
default.conf
#2、改回挂载后继续操作
[root@k8s-master1 case6]#vim deploy_configmap.yml
- name: nginx-config
mountPath: /etc/nginx/conf.d
[root@k8s-master1 case6]#kubectl apply -f deploy_configmap.yml
#(1)nginx验证
[root@k8s-master1 case6]#vim deploy_configmap.yml
kind: ConfigMap
server_name www.mysite.com;
kind: Deployment
- name: nginx-config
mountPath: /etc/nginx/conf.d
#登录dashboard验证
root@nginx-deployment-789d799b8c-nfn9z:/# ls /etc/nginx/conf.d/
mysite.conf
root@nginx-deployment-789d799b8c-nfn9z:/# cat /etc/nginx/conf.d/mysite.conf
server {
listen 80;
server_name www.mysite.com;
index index.html;
location / {
root /data/nginx/html;
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
}
}
}
#配置haproxy和vip
[root@k8s-ha1 ~]#vim /etc/keepalived/keepalived.conf
virtual_ipaddress {
192.168.150.189 dev eth0 label eth0:1
[root@k8s-ha1 ~]#vim /etc/haproxy/haproxy.cfg
listen magedu-nginx-80
bind 192.168.150.189:80
mode tcp
server k8s1 192.168.150.151:30019 check inter 3s fall 3 rise 5
#server k8s1 192.168.150.152:30019 check inter 3s fall 3 rise 5
#server k8s1 192.168.150.153:30019 check inter 3s fall 3 rise 5
[root@k8s-ha1 ~]#systemctl restart keepalived.service
[root@k8s-ha1 ~]#systemctl restart haproxy.service
#配置本地浏览器域名访问
C:\Windows\System32\drivers\etc\hosts
192.168.150.189 www.mysite.com
#dashboard登录后自定义页面展示信息
root@nginx-deployment-789d799b8c-j4bnv:/# cd /data/nginx/html/
root@nginx-deployment-789d799b8c-j4bnv:/data/nginx/html# ls
root@nginx-deployment-789d799b8c-j4bnv:/data/nginx/html# echo "my app"> index.html
#访问网址验证:http://www.mysite.com/
#(2)tomcat验证
[root@k8s-master1 case6]#vim deploy_configmap.yml
kind: Deployment
- name: ng-deploy-8080
image: tomcat
ports:
- containerPort: 8080
volumeMounts:
- name: nginx-config
mountPath: /data
#登录dashboard验证
root@nginx-deployment-789d799b8c-j4bnv:/usr/local/tomcat# cat /data/mysite.conf
server {
listen 80;
server_name www.mysite.com;
index index.html;
location / {
root /data/nginx/html;
if (!-e $request_filename) {
rewrite ^/(.*)