[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L33TYpAW-1576315971384)(E:\OneDrive\笔记\markdown\picture\image-20191118220148390.png)]
pod能有多个容器,应用运行在容器里面,但是他也有可能有一个或多个先于容器启动的Init容器。
init容器与普通容器非常像,除了以下两点:
如果pod的init容器启动失败,kubernetes会不断重启该pod,直到init容器成功为止。然而,如果pod对应的restartPolicy为Never,他不会重新启动
Pod能够具有多个容器,应用运行在容器里面,但是他也有一个或多个先于应用容器启动的Init容器。
Init容器与普通容器非常像,除了以下两点:
如果Pod的Init容器容器失败,Kubernetes会不断重启该Pod,直到Init容器启动成功为止。然而,如果Pod对应的restartPolicy为Never,他不会重新启动。
因为Init容器具有与应用程序容器分离的单独镜像,所以他们的启动相关代码具有如下优势:
特殊说明:
init模板:
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh','-c','echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox
command: ['sh','-c','until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox
command: ['sh','-c','until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 1111
---
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 1112
探针是由kubelet对容器执行的定期诊断。要执行诊断,kubelet调用由容器实现的Handler。
有三种类型的处理程序:
ExecAction:在容器内执行指定命令。如果命令退出时返回码为0,则认为诊断成功。
TCPSocketAction:对指定端口上的容器的IP地址进行TCP检查。如果端口打开,则诊断被认为是成功的
HTTPGetAction:对指定的端口和路径上的容器的IP地址执行HTTP Get请求。如果(200<=状态码<400),则诊断被认为是成功的
HTTP probe中可以给httpGet设置以下配置项:
host
: 连接的主机名,默认连接到pod的ipscheme
: 支持的协议,http、https,默认httppath
:访问的HTTP server的pathhttpHeaders
:自定义请求的headerport
:访问的容器的端口名字或者端口号,端口号必须介于1和65525之间每次探测都将获得以下三种结果之一:
???Probe中的精切配置,可以更精确的配置liveness和readiness检测:
periodSeconds: 3
每3秒执行一次探测。执行探测的频率,默认是10秒,最小1秒initialDelaySeconds: 3
容器初始化完成后延迟3秒执行探测timeoutSeconds
:探测超时时间,默认1秒,最小1秒successThreshold
:探测失败后,最少连续探测成功多少次才被认定为成功。默认1,最小值是1。对于liveness必须是1failureThreshold
:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3,最小值是1探测方式
livenessProbe
存活探针:指示容器是否正在运行。如果存活探测失败,则kubelet会杀死容器,并且容器会受其重启策略的影响。如果容器不提供存活探针,则默认状态为SuccessreadinessProbe
就绪探针:指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与Pod匹配的所有Service的端点中删除该Pod的IP地址。初始延迟之前的就绪状态默认为Failure。如果容器不提供就绪探针,则默认状态为SuccessreadinessProbe-httpget
apiVersion: v1
kind: Pod
metadata:
name: readiness-httpget-pod
namespace: default
spec:
containers:
- name: readiness-httpget-container
image: tomcat:v1 #镜像名称
imagePullPolicy: Never #镜像拉去策略,IfNotPresent:本地docker没有时从仓库拉取
readinessProbe:
httpGet: #httpget方式的探针诊断类型
port: 8080 #访问的端口
path: /docs/index.html #httpget请求的路径
initialDelaySeconds: 1 #容器初始化完成后延时几秒再探测
periodSeconds: 3 #每3秒检测一次
如果不符合存活条件就销毁pod再创建新的pod,与上面的就绪检测有一定差别
livenessProbe-exec
说明:以下容器启动时会先创建一个live文件,然后过60秒再删除这个文件。存活检测每三秒检测一次这个文件是否存在,如果不存在会直接销毁容器,重新创建。最后的现象就是pod会隔段时间不断重启
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec-pod
namespace: default
spec:
containers:
- name: liveness-exec-container
image: busybox #不写镜像tag默认是latest
imagePullPolicy: IfNotPresent #镜像拉去策略,IfNotPresent:本地docker没有时从仓库拉取
command: ["bin/sh","-c","touch /tmp/live;sleep 60;rm -rf /tmp/live;sleep 60"] #容器创建完后先创建一个live文件,睡60秒,删除文件再睡60秒
livenessProbe:
exec:
command: ["test","-e","/tmp/live"] #测试文件是否存在,不存在就重启
initialDelaySeconds: 1 #容器初始化完成后延时几秒再探测
periodSeconds: 3 #每3秒检测一次
livenessProbe-httpget
说明:启动是正常的,进到容器内删除tomcat中的webapps/docs/index.html后,就会探活失败,pod会重启。
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget-pod
namespace: default
spec:
containers:
- name: liveness-httpget-container
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- name: haha
containerPort: 8080 #pod暴露的端口,此端口仅是额外的信息,对端口是否被暴露没有影响,不太理解
livenessProbe:
httpGet:
port: haha #试探时发现要与上面的ports中的haha相对应才行,否则要直接写一个具体的端口号。
path: /docs/index.html #访问的HTTP server的path
initialDelaySeconds: 1 #容器初始化完成后延时几秒再探测
periodSeconds: 3 #每3秒检测一次
timeoutSeconds: 10 #超时时间
livenessProbe-tcp
说明:tcp探活探测端口9090是否有监听,本处是没有的,探测9090端口时没返回,而且超时时间设置为1秒,直接超时导致认为pod是挂的,会不断重启pod
apiVersion: v1
kind: Pod
metadata:
name: liveness-tcp-pod
namespace: default
spec:
containers:
- name: liveness-tcp-container
image: tomcat
imagePullPolicy: IfNotPresent
livenessProbe:
initialDelaySeconds: 5 #容器初始化完成后延时几秒再探测
periodSeconds: 3 #每3秒检测一次
timeoutSeconds: 1 #超时时间
tcpSocket: #tcp探测端口是否开启,如果没有监听则认为容器是挂的,就会重启pod
port: 9090
也即当容器启动时要做的事情,与容器停止时要做的事情。
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-pod #pod名称
namespace: default
spec:
containers:
- name: lifecycle-demo-container #容器名称
image: tomcat
lifecycle:
postStart: #启动容器后的操作
exec:
command: ["/bin/sh","-c","echo Hello postStart handler > /home/msg.txt"]
preStop: #停止容器前的操作
exec:
command: ["/bin/sh","-c","echo bye~ postStop handler > /home/msg.txt"]
Kubernetes 中内建了很多 controller(控制器),这些相当于一个状态机,用来控制 Pod 的具体状态和行为
ReplicationController(RC)用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来替代;而如果异常多出来的容器也会自动回收;
在新版本的 Kubernetes 中建议使用 ReplicaSet 来取代 ReplicationController 。ReplicaSet 跟ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector;RC已经被逐渐废弃!
Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义 (declarative) 方法,用来替代以前的ReplicationController 来方便的管理应用。典型的应用场景包括;
DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod
使用 DaemonSet 的一些典型用法:
glusterd
、ceph
fluentd
、logstash
gmond
Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束
Cron Job 管理基于时间的 Job,即:
使用前提条件:
当前使用的 Kubernetes 集群,版本 >= 1.8(对 CronJob)。对于先前版本的集群,版本 <1.8,启动 API Server时,通过传递选项--runtime-config=batch/v2alpha1=true
可以开启 batch/v2alpha1API
典型的用法如下所示:
StatefulSet 作为 Controller 为 Pod 提供唯一的标识。它可以保证部署和 scale 的顺序
StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括:
应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让service中的Pod个数自动调整呢?这就有赖于Horizontal Pod Autoscaling了,顾名思义,使Pod水平自动缩放
RC (ReplicationController )主要的作用就是用来确保容器应用的副本数始终保持在用户定义的副本数 。即如果有容器异常退出,会自动创建新的Pod来替代;而如果异常多出来的容器也会自动回收
Kubernetes 官方建议使用 RS(ReplicaSet ) 替代 RC (ReplicationController ) 进行部署,RS 跟 RC 没有本质的不同,只是名字不一样,并且 RS 支持集合式的 selector
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: replicaset-demo #注意名字不能有大写字母
spec:
replicas: 3
selector:
matchLabels: #标签选择器
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
containers:
- name: my-tomcat
image: tomcat
env:
- name: yc #环境变量key
value: yangche #环境变量value
ports:
- containerPort: 80 #容器暴露的端口
Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController 来方便的管理应用。典型的应用场景包括:
Ⅰ、部署一个简单的 Nginx 应用
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml --record
## --record参数可以记录命令,我们可以很方便的查看每次 revision 的变化
Ⅱ、扩容
kubectl scale deployment nginx-deployment --replicas 10
Ⅲ、如果集群支持 horizontal pod autoscaling 的话,还可以为Deployment设置自动扩展
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
Ⅳ、更新镜像也比较简单
#更新镜像版本,在deployment下有个名称为nginx-deployment的deployment
#为nginx的更改镜像为nginx:1.9.1
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
Ⅴ、回滚
kubectl rollout undo deployment/nginx-deployment
假如我们现在想要让 nginx pod 使用nginx:1.9.1
的镜像来代替原来的nginx:1.7.9
的镜像
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment "nginx-deployment" image updated
可以使用edit
命令来编辑 Deployment
$ kubectl edit deployment/nginx-deployment
deployment "nginx-deployment" edited
查看 rollout 的状态
$ kubectl rollout status deployment/nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out
查看历史 RS
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 3 3 0 6s
nginx-deployment-2035384211 0 0 0 36s
Deployment 可以保证在升级时只有一定数量的 Pod 是 down 的。默认的,它会确保至少有比期望的Pod数量少一个是up状态(最多一个不可用)
Deployment 同时也可以确保只创建出超过期望数量的一定数量的 Pod。默认的,它会确保最多比期望的Pod数量多一个的 Pod 是 up 的(最多1个 surge )
未来的 Kuberentes 版本中,将从1-1变成25%-25%
$ kubectl describe deployments
假如您创建了一个有5个niginx:1.7.9
replica的 Deployment,但是当还只有3个nginx:1.7.9
的 replica 创建出来的时候您就开始更新含有5个nginx:1.9.1
replica 的 Deployment。在这种情况下,Deployment 会立即杀掉已创建的3个nginx:1.7.9
的 Pod,并开始创建nginx:1.9.1
的 Pod。它不会等到所有的5个nginx:1.7.9
的Pod 都创建完成后才开始改变航道
kubectl set image deployment/nginx-deployment nginx=nginx:1.91
kubectl rollout status deployments nginx-deployment
kubectl get pods
kubectl rollout history deployment/nginx-deployment
kubectl rollout undo deployment/nginx-deployment
kubectl rollout undo deployment/nginx-deployment --to-revision=2 ## 可以使用 --revision参数指定
某个历史版本
kubectl rollout pause deployment/nginx-deployment ## 暂停 deployment 的更新
您可以用kubectl rollout status
命令查看 Deployment 是否完成。如果 rollout 成功完成, kubectl rollout status
将返回一个0值的 Exit Code
$ kubectl rollout status deploy/nginx
Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx" successfully rolled out
$ echo $?
0
您可以通过设置.spec.revisonHistoryLimit
项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的 revision;如果将该项设置为0,Deployment 就不允许回退了
DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
一般主节点不会创建,有一个污点的概念,存在污点的不会创建,具体请看解释。
glusterd
、ceph
fluentd
、logstash
collectd
、Datadog 代理、New Relic 代理,或 Ganglia gmond
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: deamonset-example
labels:
app: daemonset
spec:
selector:
matchLabels:
name: deamonset-example #此处特别注意,必须和上面的标签对应
template:
metadata:
labels:
name: deamonset-example
spec:
containers:
- name: daemonset-example
image: tomcat
Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束
.spec.completions
标志Job结束需要成功运行的Pod个数,默认为1.spec.parallelism
标志并行运行的Pod的个数,默认为1.spec.activeDeadlineSeconds
标志失败Pod的重试最大时间,超过这个时间不会继续重试Example:查看日志可以查看答应的π小数点后2000位
查看日志的命令kubectl logs [pod名称] -n [namespace]
apiVersion: batch/v1
kind: Job
metadata:
name: job-demo
spec:
template:
metadata:
name: job-demo
spec:
containers:
- name: pi
image: perl #通过这个镜像,运行下列命令,得到圆周率小数点后2000位
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
Cron Job 管理基于时间的 Job,即:
使用条件
当前使用的 Kubernetes 集群,版本 >= 1.8(对 CronJob)
CrondJob 本身的一些限制
创建 Job 操作应该是 幂等的
典型的用法
CronJob Spec
.spec.schedule
:调度,必需字段,指定任务运行周期,格式同 Cron
.spec.jobTemplate
:Job 模板,必需字段,指定需要运行的任务,格式同 Job
.spec.startingDeadlineSeconds
:启动 Job 的期限(秒级别),该字段是可选的。如果因为任何原因而错过了被调度的时间,那么错过执行时间的 Job 将被认为是失败的。如果没有指定,则没有期限
.spec.concurrencyPolicy
:并发策略,该字段也是可选的。它指定了如何处理被 Cron Job 创建的 Job 的并发执行。只允许指定下面策略中的一种:
Allow
(默认):允许并发运行 JobForbid
:禁止并发运行,如果前一个还没有完成,则直接跳过下一个Replace
:取消当前正在运行的 Job,用一个新的来替换注意,当前策略只能应用于同一个 Cron Job 创建的 Job。如果存在多个 Cron Job,它们创建的 Job 之间总是允许并发运行。
.spec.suspend
:挂起,该字段也是可选的。如果设置为 true
,后续所有执行都会被挂起。它对已经开始执行的 Job 不起作用。默认值为 false
。
.spec.successfulJobsHistoryLimit
和 .spec.failedJobsHistoryLimit
:历史限制,是可选的字段。它们指定了可以保留多少完成和失败的 Job。默认情况下,它们分别设置为 3
和 1
。设置限制的值为 0
,相关类型的 Job 完成后将不会被保留。
Example
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: cronjob-hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: cronjob-hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
$ kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST-SCHEDULE
hello */1 * * * * False 0 <none>
$ kubectl get jobs
NAME DESIRED SUCCESSFUL AGE
hello-1202039034 1 1 49s
$ pods=$(kubectl get pods --selector=job-name=hello-1202039034 --output=jsonpath={.items..metadata.name})
$ kubectl logs $pods
Mon Aug 29 21:34:09 UTC 2016
Hello from the Kubernetes cluster
# 注意,删除 cronjob 的时候不会自动删除 job,这些 job 可以用 kubectl delete job 来删除
$ kubectl delete cronjob hello
cronjob "hello" deleted
Kubernetes Service
定义了这样一种抽象:一个 Pod
的逻辑分组,一种可以访问它们的策略 —— 通常称为微服务。 这一组 Pod
能够被 Service
访问到,通常是通过 Label Selector
Service 在 K8s 中有以下四种类型
ClusterIp
:默认类型,自动分配一个仅 Cluster 内部可以访问的虚拟 IPNodePort
:在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过 : NodePort 来访问该服务LoadBalancer
:在 NodePort 的基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到: NodePortExternalName
:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有 kubernetes 1.7 或更高版本的 kube-dns 才支持[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RlDeWVCk-1576315971388)(E:\OneDrive\笔记\markdown\picture\image-20191201113413524.png)]
在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy
进程。 kube-proxy
负责为 Service
实现了一种VIP(虚拟 IP)的形式,而不是 ExternalName
的形式。 在 Kubernetes v1.0 版本,代理完全在 userspace。在Kubernetes v1.1 版本,新增了 iptables 代理,但并不是默认的运行模式。 从 Kubernetes v1.2 起,默认就是iptables 代理。 在 Kubernetes v1.8.0-beta.0 中,添加了 ipvs 代理
在 Kubernetes 1.14 版本开始默认使用 ipvs 代理
在 Kubernetes v1.0 版本, Service
是 “4层”(TCP/UDP over IP)概念。 在 Kubernetes v1.1 版本,新增了Ingress
API(beta 版),用来表示 “7层”(HTTP)服务
!为何不使用 round-robin DNS?:因为大部分客户端会对dns进行缓存,而不能自动清除缓存。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gOC1ABB4-1576315971389)(E:\OneDrive\笔记\markdown\picture\image-20191201114510393.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QTuSrNPG-1576315971390)(E:\OneDrive\笔记\markdown\picture\image-20191201114449014.png)]
这种模式,kube-proxy 会监视 Kubernetes Service
对象和 Endpoints
,调用 netlink
接口以相应地创建ipvs 规则并定期与 Kubernetes Service
对象和 Endpoints 对象同步 ipvs 规则,以确保 ipvs 状态与期望一致。访问服务时,流量将被重定向到其中一个后端 Pod
与 iptables 类似,ipvs 于 netfilter 的 hook 功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着 ipvs 可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs 为负载均衡算法提供了更多选项,例如:
rr
:轮询调度lc
:最小连接数dh :目标哈希sh
:源哈希sed
:最短期望延迟nq : 不排队调度[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o3q9wgmn-1576315971391)(E:\OneDrive\笔记\markdown\picture\image-20191201114349614.png)]
clusterIP 主要在每个 node 节点使用 iptables,将发向 clusterIP 对应端口的数据,转发到 kube-proxy 中。然后 kube-proxy 自己内部实现有负载均衡的方法,并可以查询到这个 service 下对应 pod 的地址和端口,进而把数据转发给对应的 pod 的地址和端口
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fmWOlGQa-1576315971392)(E:\OneDrive\笔记\markdown\picture\image-20191201114635338.png)]
为了实现图上的功能,主要需要以下几个组件的协同工作:
Example
创建 myapp-deploy.yaml 文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: myapp
release: stabel
template:
metadata:
labels:
app: myapp
release: stabel
env: test
spec:
containers:
- name: myapp
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
创建 Service 信息
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
type: ClusterIP
selector:
app: myapp
release: stabel
ports:
- name: http
port: 80 #集群端口
targetPort: 8080 #后端服务真实代理的是哪些端口
查询svc代理的ip端口命令:ipvsadm -Ln
,必须是ipvs才行
有时不需要或不想要负载均衡,以及单独的 Service IP 。遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP) 的值为 “None” 来创建 Headless Service 。这类 Service 并不会分配 Cluster IP, kubeproxy不会处理它们,而且平台也不会为它们进行负载均衡和路由
apiVersion: v1
kind: Service
metadata:
name: myapp-headless
namespace: default
spec:
selector:
app: myapp
clusterIP: "None"
ports:
- port: 80
targetPort: 8080
别名会被写入core dns,他也是一个pod可以通过kubectl get pod -n kube-system
查看,通过这个coredns可以解析myapp-headless.default.svc.cluster.local
dig -t A myapp-headless.default.svc.cluster.local. @10.96.0.10
对外提供服务,service和pod是多对多的关系,是通过标签选择器代理到对应的pod。
nodePort 的原理在于在 node 上开了一个端口,将向该端口的流量导入到 kube-proxy,然后由 kube-proxy 进一步到给对应的 pod
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
type: NodePort
selector:
app: myapp
release: stabel
ports:
- name: http
port: 80
nodePort: 9000 #开启对外服务的端口,如果不写,会随机分配一个端口,端口范围在30000-32762
targetPort: 8080
查询流程
iptables -t nat -nvL KUBE-NODEPORTS
ipvsadm -Ln
声明:此种方式收费,看看就好
loadBalancer 和 nodePort 其实是同一种方式。区别在于 loadBalancer 比 nodePort 多了一步,就是可以调用cloud provider 去创建 LB 来向节点导流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qeVHQVNo-1576315971393)(E:\OneDrive\笔记\markdown\picture\image-20191201162024625.png)]
这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容( 例如:hub.atguigu.com )。ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务
apiVersion: v1
kind: Service
metadata:
name: service-external
namespace: default
spec:
type: ExternalName
externalName: www.baidu.com
当查询主机 my-service.defalut.svc.cluster.local ( SVC_NAME
.NAMESPACE
.svc.cluster.local
)时,集群的DNS 服务将返回一个值 my.database.example.com 的 CNAME 记录。访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发
如果没有dig命令可以用命令安装一个: yum install bind-utils
通过kubectl get pod -n kube-system
可以查看core dns,通过corn
查询服务,注意@前有一个空格
dig -t A service-external.default.svc.cluster.local. @10.244.0.14
查询结果
;; ANSWER SECTION:
service-external.default.svc.cluster.local. 5 IN CNAME www.baidu.com.
www.baidu.com. 5 IN CNAME www.a.shifen.com.
www.a.shifen.com. 5 IN A 61.135.169.121
www.a.shifen.com. 5 IN A 61.135.169.125
Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginx
Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qqZXvXL5-1576315971395)(E:\OneDrive\笔记\markdown\picture\image-20191208105917049.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3PhgWUTj-1576315971396)(E:\OneDrive\笔记\markdown\picture\image-20191208105931937.png)]
kubectl apply -f mandatory.yaml
kubectl apply -f service-nodeport.yaml
deployment、Service、Ingress Yaml 文件
kind: Deployment
metadata:
name: nginx-dm
spec:
replicas: 2
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: wangyanglinux/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-test
spec:
rules:
- host: www1.atguigu.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
创建证书,以及 cert 存储方式
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
deployment、Service、Ingress Yaml 文件
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-test
spec:
tls:
- hosts:
- foo.bar.com
secretName: tls-secret
rules:
- host: foo.bar.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
yum -y install httpd
htpasswd -c auth foo
kubectl create secret generic basic-auth --from-file=auth
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-with-auth
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
spec:
rules:
- host: foo2.bar.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
名称 | 描述 | 值 |
---|---|---|
nginx.ingress.kubernetes.io/rewrite-target | 必须重定向流量的目标URI | 串 |
nginx.ingress.kubernetes.io/ssl-redirect | 指示位置部分是否仅可访问SSL(当Ingress包含证书时默认为True) | 布尔 |
nginx.ingress.kubernetes.io/force-ssl-redirect | 即使Ingress未启用TLS,也强制重定向到HTTPS | 布尔 |
nginx.ingress.kubernetes.io/app-root | 定义Controller必须重定向的应用程序根,如果它在’/'上下文中 | 串 |
nginx.ingress.kubernetes.io/use-regex | 指示Ingress上定义的路径是否使用正则表达式 | 布尔 |
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: http://foo.bar.com:31795/hostname.html
spec:
rules:
- host: foo10.bar.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者 JSON 二进制大对象
$ ls docs/user-guide/configmap/kubectl/
game.properties
ui.properties
$ cat docs/user-guide/configmap/kubectl/game.properties
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
$ cat docs/user-guide/configmap/kubectl/ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
$ kubectl create configmap game-config --from-file=docs/user-guide/configmap/kubectl
--from-file
指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容
只要指定为一个文件就可以从单个文件中创建 ConfigMap
$ kubectl create configmap game-config-2 --from-file=docs/user-
guide/configmap/kubectl/game.properties
$ kubectl get configmaps game-config-2 -o yaml
--from-file
这个参数可以使用多次,你可以使用两次分别指定上个实例中的那两个配置文件,效果就跟指定整个目录是一样的
使用文字值创建,利用 --from-literal
参数传递配置信息,该参数可以使用多次,格式如下
$ kubectl create configmap special-config --from-literal=special.how=very --from-
literal=special.type=charm
$ kubectl get configmaps special-config -o yaml
事先写好标准的configMap的yaml文件,然后kubectl apply -f xxx.yaml
创建
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
#如果key: |,类似这样有个竖杠,则后面的内容会作为一个文件
special.how: very
special.type: charm
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: hub.atguigu.com/library/myapp:v1
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY #环境变量的key
valueFrom: #环境变量的值来源
configMapKeyRef: #指向configmap
name: special-config #configmap的名称
key: special.how #configmap中data中的key值
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
envFrom:
- configMapRef:
#这种方式会将所有configmap中data中的key作为环境变量的key
#,value做为pod中环境变量的value
name: env-config
restartPolicy: Never
注意:envFrom
这种方式引用的环境变量的key值都来自configmap中的key值,如果key值设置为mysql.config
时,进到容器内打印环境变量echo $mysql.config
时会提示“bad substitution”,将configmap中的mysql.config改成mysql_config,再打印就能正常显示,所以,用此种方式引用环境变量时,必须注意变量的命名规范
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: hub.atguigu.com/library/myapp:v1
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
restartPolicy: Never
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
在数据卷里面使用这个 ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: hub.atguigu.com/library/myapp:v1
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
以下都是通过volume使用configmap,重要
创建一个configmap,基本涵盖所有方式,接下来的volume都用到此configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: configmap-demo
namespace: default
data:
config1: yangche
config2:
username:yangche
sex:man
iphone:18713161789
user.config: |
nimeide,
nidayede,
╭(╯^╰)╮
以上configmap生成后的json格式如下
[root@k8s-master01 configmap]# kubectl get cm configmap-demo -o json
{
"apiVersion": "v1",
"data": {
"config1": "yangche",
"config2": "username:yangche sex:man iphone:18713161789",
"user.config": "nimeide,\nnidayede,\n╭(╯^╰)╮\n"
},
"kind": "ConfigMap",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"data\":{\"config1\":\"yangche\",\"config2\":\"username:yangche sex:man iphone:18713161789\",\"user.config\":\"nimeide,\\nnidayede,\\n╭(╯^╰)╮\\n\"},\"kind\":\"ConfigMap\",\"metadata\":{\"annotations\":{},\"name\":\"configmap-demo\",\"namespace\":\"default\"}}\n"
},
"creationTimestamp": "2019-12-13T07:13:08Z",
"name": "configmap-demo",
"namespace": "default",
"resourceVersion": "696614",
"selfLink": "/api/v1/namespaces/default/configmaps/configmap-demo",
"uid": "04a34b9a-665c-48d6-8f2a-32a7f0c9a355"
}
}
config1
:这种方式后面没有“|”,文件生成后没有回车符,username左面虽然有两个空格,但是最终是顶格,username:yangche与sex:man之间没有回车符,有两个空格间距,最终是个字符串user.config: |
:这种方式后面都是字符串,最前面顶格,并且每一行都有回车符apiVersion: v1
kind: Pod
metadata:
name: pod-configmap-demo1
spec:
containers:
- name: pod-configmap-demo
image: tomcat
imagePullPolicy: IfNotPresent
volumeMounts:
- name: config-volume
mountPath: /temp/config
volumes:
- name: config-volume
configMap:
name: configmap-demo
查看容器中的所有内容,进入到/temp/config目录中可以看到,config文件夹下,以每一个key为文件名,value为值创建了多个文件,如下所示:
root@pod-configmap-demo1:/temp/config# ls -lrt
total 0
lrwxrwxrwx 1 root root 18 Dec 13 07:30 user.config -> ..data/user.config
lrwxrwxrwx 1 root root 14 Dec 13 07:30 config2 -> ..data/config2
lrwxrwxrwx 1 root root 14 Dec 13 07:30 config1 -> ..data/config1
root@pod-configmap-demo1:/temp/config# cat user.config
nimeide,
nidayede,
╭(╯^╰)╮
root@pod-configmap-demo1:/temp/config# cat config2
username:yangche sex:man iphone:18713161789root@pod-configmap-demo1:/temp/config# cat config1
yangcheroot
如果不想以key名作为配置文件名,可以引入items
字段。在其中逐个指定要用相对路径path替换的key。
apiVersion: v1
kind: Pod
metadata:
name: pod-configmap-demo2
spec:
containers:
- name: pod-configmap-demo
image: tomcat
imagePullPolicy: IfNotPresent
volumeMounts:
- name: config-volume
mountPath: /temp/config
volumes:
- name: config-volume
configMap:
name: configmap-demo
items:
- key: config1
path: config1abc
- key: user.config
path: userconfigabc
以下结果可以看到,进入/temp/config后会有两个文件,且文件名是以上yaml文件中定义的path作为文件名。上面只引用了两个文件,所以此处只生成了两个文件
root@pod-configmap-demo2:/temp/config# ls -lrt
total 0
lrwxrwxrwx 1 root root 20 Dec 13 07:46 userconfigabc -> ..data/userconfigabc
lrwxrwxrwx 1 root root 17 Dec 13 07:46 config1abc -> ..data/config1abc
root@pod-configmap-demo2:/temp/config# cat userconfigabc
nimeide,
nidayede,
╭(╯^╰)╮
root@pod-configmap-demo2:/temp/config# cat config1abc
yangche
一个configmap中有三个文件,挂载的时候想分别挂载到不同的目录,且自定义文件的名称可以通过subPath
完成
apiVersion: v1
kind: Pod
metadata:
name: pod-configmap-demo3
spec:
containers:
- name: pod-configmap-demo
image: tomcat
imagePullPolicy: IfNotPresent
volumeMounts:
- name: config-volume #与volumes中的name相对应
mountPath: /temp/config1/a.config #最后a.config是最终生成的文件名
subPath: config1 #指向configmap的key
- name: config-volume
mountPath: /temp/config1/b.config
subPath: config2
- name: config-volume
mountPath: /temp/config2/c.config
subPath: user.config
volumes:
- name: config-volume
configMap:
name: configmap-demo
在容器中生成的目录与文件如下结构,需要注意的是:Ⅲ这种方式,最终生成的是具体的文件,Ⅰ、Ⅱ形成的是个链接,链接到..data/
# 目录与文件结构如下
/temp
/config1
a.config #文件
b.config #文件
/config2
c.config #文件
mountPath: /temp/config/abc_confg
注意一下几种情况
apiVersion: v1
kind: ConfigMap
metadata:
name: log-config
namespace: default
data:
log_level: INFO
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: hub.atguigu.com/library/myapp:v1
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: log-config
$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` cat
/etc/config/log_level
INFO
修改 ConfigMap
$ kubectl edit configmap log-config
修改 log_level
的值为 DEBUG
等待大概 10 秒钟时间,再次查看环境变量的值
$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` cat /tmp/log_level
DEBUG
ConfigMap 更新后滚动更新 Pod
更新 ConfigMap 目前并不会触发相关 Pod 的滚动更新,可以通过修改 pod annotations 的方式强制触发滚动更新
$ kubectl patch deployment my-nginx --patch '{"spec": {"template": {"metadata": {"annotations":
{"version/config": "20190411" }}}}}'
这个例子里我们在 .spec.template.metadata.annotations
中添加 version/config
,每次通过修改
version/config
来触发滚动更新
!!! 更新 ConfigMap 后:
Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec中。Secret 可以以 Volume 或者环境变量的方式使用
Secret 有三种类型:
/run/secrets/kubernetes.io/serviceaccount
目录中Service Account 用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod的/run/secrets/kubernetes.io/serviceaccount
目录中,了解即可。
$ kubectl run nginx --image nginx
deployment "nginx" created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-3137573019-md1u2 1/1 Running 0 13s
$ kubectl exec nginx-3137573019-md1u2 ls /run/secrets/kubernetes.io/serviceaccount
ca.crt
namespace
token
Opaque 类型的数据是一个 map 类型,要求 value 是 base64 编码格式:
$ echo -n "admin" | base64
YWRtaW4=
$ echo -n "12345" | base64
MTIzNDUK
secrets.yml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: MTIzNDUK
username: YWRtaW4=
1、将 Secret 挂载到 Volume 中
apiVersion: v1
kind: Pod
metadata:
labels:
name: seret-test
name: seret-test
spec:
volumes:
- name: secrets
secret:
secretName: mysecret
containers:
- image: hub.atguigu.com/library/myapp:v1
name: db
volumeMounts:
- name: secrets
mountPath: "
readOnly: true
2、将 Secret 导出到环境变量中
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: pod-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: pod-deployment
spec:
containers:
- name: pod-1
image: hub.atguigu.com/library/myapp:v1
ports:
- containerPort: 80
env:
- name: TEST_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: TEST_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
使用 Kuberctl 创建 docker registry 认证的 secret
$ kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --
docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
secret "myregistrykey" created.
在创建 Pod 的时候,通过 imagePullSecrets
来引用刚创建的 myregistrykey
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: foo
image: roc/awangyang:v1
imagePullSecrets:
- name: myregistrykey
容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)重新启动。其次,在Pod 中同时运行多个容器时,这些容器之间通常需要共享文件。Kubernetes 中的 Volume 抽象就很好的解决了这些问题
Kubernetes 中的卷有明确的寿命 —— 与封装它的 Pod 相同。所f以,卷的生命比 Pod 中的所有容器都长,当这
个容器重启时数据仍然得以保存。当然,当 Pod 不再存在时,卷也将不复存在。也许更重要的是,Kubernetes
支持多种类型的卷,Pod 可以同时使用任意数量的卷
Kubernetes 支持以下类型的卷:
awsElasticBlockStore
azureDisk
azureFile
cephfs
csi
downwardAPI
emptyDir
fc
flocker
gcePersistentDisk
gitRepo
glusterfs
hostPath
iscsi
local
nfs
persistentVolumeClaim
projected
portworxVolume
quobyte
rbd
scaleIO
secret
storageos
vsphereVolume
当一个pod中有多个容器时,这几个pod可以共享此卷
当 Pod 被分配给节点时,首先创建 emptyDir
卷,并且只要该 Pod 在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod 中的容器可以读取和写入 emptyDir 卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除 Pod 时, emptyDir 中的数据将被永久删除
emptyDir
的用法有:
apiVersion: v1
kind: Pod
metadata:
name: empty-dir-volume-pod
spec:
containers:
- image: tomcat
name: container-1
volumeMounts:
- mountPath: /one
name: cache-volume
- image: nginx
name: container-2
volumeMounts:
- mountPath: /two
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
**说明:**以上创建之后container-1的/one目录和container-2的/two目录是相互共享的,也就是在container-1中如果在/one目录放数据会在container-2的/two目录中看到。
如果一个pod中有多个容器,那么这多个容器的镜像不能相同,我试验时如果拉取的镜像相同第二个会报错CrashLoopBackOff
hostPath
卷将主机节点的文件系统中的文件或目录挂载到集群中
hostPath
的用途如下:
/var/lib/docker
的 hostPath
/dev/cgroups
的 hostPath
除了所需的 path
属性之外,用户还可以为 hostPath
卷指定 type
,如下所示:
值 | 行为 |
---|---|
空字符串(默认)用于向后兼容,这意味着在挂载hostPath卷之前,不会执行任何检查。 | |
DirectoryOrCreate |
如果在给定的路径上没有任何东西存在,那么将根据需要在那里创建一个空目录,权限设置为 0755,与 Kubelet 具有相同的组和所有权。 |
Directory |
给定的路径下必须存在目录 |
FileOrCreate |
如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为 0644,与 Kubelet 具有相同的组和所有权。 |
File |
给定的路径下必须存在文件 |
Socket |
给定的路径下必须存在 UNIX 套接字 |
CharDevice |
给定的路径下必须存在字符设备 |
BlockDevice |
给定的路径下必须存在块设备 |
使用这种卷类型时请注意,因为:
hostPath
卷yaml示例:
apiVersion: v1
kind: Pod
metadata:
name: hostpath-pod-demo
spec:
containers:
- image: nginx
name: test-container
volumeMounts:
- mountPath: /demo
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory
PersistentVolume
(PV)
是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。 PV 是Volume 之类的卷插件,但具有独立于使用 PV 的 Pod 的生命周期。此 API 对象包含存储实现的细节,即 NFS、iSCSI 或特定于云供应商的存储系统
PersistentVolumeClaim
(PVC)
是用户存储的请求。它与 Pod 相似。Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存)。声明可以请求特定的大小和访问模式(例如,可以以读/写一次或 只读多次模式挂载)
静态 pv
集群管理员创建一些 PV。它们带有可供群集用户使用的实际存储的细节。它们存在于 Kubernetes API 中,可用于消费
动态pv
当管理员创建的静态 PV 都不匹配用户的 PersistentVolumeClaim
时,集群可能会尝试动态地为 PVC 创建卷。此配置基于 StorageClasses
:PVC 必须请求 [存储类],并且管理员必须创建并配置该类才能进行动态创建。声明该类为 ""
可以有效地禁用其动态配置
要启用基于存储级别的动态存储配置,集群管理员需要启用 API server 上的 DefaultStorageClass
[准入控制器]。例如,通过确保 DefaultStorageClass
位于 API server 组件的 --admission-control
标志,使用逗号分隔的有序值列表中,可以完成此操作
持久化卷声明的保护
PVC 保护的目的是确保由 pod 正在使用的 PVC 不会从系统中移除,因为如果被移除的话可能会导致数据丢失
当启用PVC 保护 alpha 功能时,如果用户删除了一个 pod 正在使用的 PVC,则该 PVC 不会被立即删除。PVC 的
删除将被推迟,直到 PVC 不再被任何 pod 使用
持久化卷类型
PersistentVolume
类型以插件形式实现。Kubernetes
目前支持以下插件类型:
持久卷演示yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0003
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp
server: 172.17.0.2
PersistentVolume 可以以资源提供者支持的任何方式挂载到主机上。如下表所示,供应商具有不同的功能,每个PV 的访问模式都将被设置为该卷支持的特定模式。例如,NFS 可以支持多个读/写客户端,但特定的 NFS PV 可能以只读方式导出到服务器上。每个 PV 都有一套自己的,用来描述特定功能的访问模式
在命令行中,访问模式缩写为:
不同的volume类型支持的访问模式也不相同:
Volume 插件 | ReadWriteOnce | ReadOnlyMany | ReadWriteMany |
---|---|---|---|
AWSElasticBlockStoreAWSElasticBlockStore | ✓ | - | - |
AzureFile | ✓ | ✓ | ✓ |
AzureDisk | ✓ | - | - |
CephFS | ✓ | ✓ | ✓ |
Cinder | ✓ | - | - |
FC | ✓ | ✓ | - |
FlexVolume | ✓ | ✓ | - |
Flocker | ✓ | - | - |
GCEPersistentDisk | ✓ | ✓ | - |
Glusterfs | ✓ | ✓ | ✓ |
HostPath | ✓ | - | - |
iSCSI | ✓ | ✓ | - |
PhotonPersistentDisk | ✓ | - | - |
Quobyte | ✓ | ✓ | ✓ |
NFS | ✓ | ✓ | ✓ |
RBD | ✓ | ✓ | - |
VsphereVolume | ✓ | - | -(当 pod 并列时有效) |
PortworxVolume | ✓ | - | ✓ |
ScaleIO | ✓ | ✓ | - |
StorageOS | ✓ | - | - |
rm -rf /thevolume/*
)当前,只有 NFS 和 HostPath 支持回收策略。AWS EBS、GCE PD、Azure Disk 和 Cinder 卷支持删除策略
卷可以处于以下的某种状态:
命令行会显示绑定到 PV 的 PVC 的名称
yum install -y nfs-common nfs-utils rpcbind
mkdir /nfsdata
chmod 666 /nfsdata
chown nfsnobody /nfsdata
cat /etc/exports
/nfsdata *(rw,no_root_squash,no_all_squash,sync)
systemctl start rpcbind
systemctl start nfs
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfspv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /data/nfs
server: 10.66.66.10
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "nfs"
resources:
requests:
storage: 1Gi
Statefulset的启停顺序:
StatefulSet使用场景:
kubectl explain [资源名称]
查看资源的完整模板信息,如果想查看资源的子资源,可以用点的方式查看
kubectl get pod --show-labels
查看pod时展示pod的标签
DTR全称是Docker Trusted Registry。为Docker自带的
The connection to the server 192.168.73.200:6443 was refused - did you specify the right host or port?
运行 systemctl status kubelet
查看kubelet状态,果然kubelet服务失败,也就是并不是API Server出错导致查不到Pod,而不是kubelet出错无法向API Server注册节点
*运行journalctl -xefu kubelet
查看systemd日志发现真正的错误原因是 :kubelet cgroup driver: "systemd" is different from docker cgroup driver: "cgroupfs"
此处有两种修改方式,可以修改docker也可以修改kubelet,我本处修改的docker,因为我知道以前我动过我的docker的配置文件。vim /etc/docker/daemon.json
,最初的docker的内容为:
{ "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "registry-mirrors": ["https://d3b5ib7d.mirror.aliyuncs.com"] }
最后的registry-mirrors是我的阿里云的快速通道配置。每个人不同
设置完毕后我们重新加载配置文件,并重启docker。
systemctl daemon-reload
systemctl restart docker
会被飘移到其它 Node 上,Pod IP 会发生变化,但是 Pod 域名不会有变化
Statefulset的启停顺序:
StatefulSet使用场景:
kubectl explain [资源名称]
查看资源的完整模板信息,如果想查看资源的子资源,可以用点的方式查看
kubectl get pod --show-labels
查看pod时展示pod的标签
DTR全称是Docker Trusted Registry。为Docker自带的
The connection to the server 192.168.73.200:6443 was refused - did you specify the right host or port?
运行 systemctl status kubelet
查看kubelet状态,果然kubelet服务失败,也就是并不是API Server出错导致查不到Pod,而不是kubelet出错无法向API Server注册节点
*运行journalctl -xefu kubelet
查看systemd日志发现真正的错误原因是 :kubelet cgroup driver: "systemd" is different from docker cgroup driver: "cgroupfs"
此处有两种修改方式,可以修改docker也可以修改kubelet,我本处修改的docker,因为我知道以前我动过我的docker的配置文件。vim /etc/docker/daemon.json
,最初的docker的内容为:
{ "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "registry-mirrors": ["https://d3b5ib7d.mirror.aliyuncs.com"] }
最后的registry-mirrors是我的阿里云的快速通道配置。每个人不同
设置完毕后我们重新加载配置文件,并重启docker。
systemctl daemon-reload
systemctl restart docker