k8s笔记2----pod详解
参考1.pod容器1.一个Pod中运行一个容器。"每个pod中一个容器"的模式是最常见的用法2.在一个Pod中同时运行多个容器。一个Pod中也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。这些在同一个Pod中的容器可以互相协作成为一个service单位。2.pause容器k8s解决同一个pod的所有容器共享资源问题一个Pod下的容器必须运行于同一节点上。现代容器技术建议一个容器只运
参考
1.pod容器
1.一个Pod中运行一个容器。"每个pod中一个容器"的模式是最常见的用法
2.在一个Pod中同时运行多个容器。一个Pod中也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。这些在同一个Pod中的容器可以互相协作成为一个service单位。
pod容器的好处:
Pod做为一个可以独立运行的服务单元,简化了应用部署的难度,以更高的抽象层次为应用部署管提供了极大的方便。
Pod中的容器共享相同的数据和网络地址空间,Pod之间也进行了统一的资源管理与分配
intc容器写在资源清单的init-Container,探针(liveness,readness)写在LivenessProbe,ReadnessProbe,stop&start写在资源清单的lifecycle
main容器包括下面的pause容器和应用程序容器
2.pause容器
k8s解决同一个pod的所有容器共享资源问题
一个Pod下的容器必须运行于同一节点上。现代容器技术建议一个容器只运行一个进程,该进程在容器中PID命令空间中的进程号为1,可直接接收并处理信号,进程终止时容器生命周期也就结束了。若想在容器内运行多个进程,需要有一个类似Linux操作系统init进程的管控类进程,以树状结构完成多进程的生命周期管理。运行于各自容器内的进程无法直接完成网络通信,这是由于容器间的隔离机制导致,k8s中的Pod资源抽象正是解决此类问题,Pod对象是一组容器的集合,这些容器共享Network、UTS及IPC命令空间,因此具有相同的域名、主机名和网络接口,并可通过IPC直接通信。
Pod资源中针对各容器提供网络命令空间等共享机制的是底层基础容器pause,基础容器(也可称为父容器) pause就是为了管理Pod容器间的共享操作,这个父容器需要能够准确地知道如何去创建共享运行环境的容器,还能管理这些容器的生命周期。为了实现这个父容器的构想,kubernetes中,用pause容器来作为一个Pod中所有容器的父容器。
这个pause容器有两个核心的功能:
一是它提供整个Pod的Linux命名空间的基础。
二来启用PID命名空间,它在每个Pod中都作为PID为1进程(init进程),并回收僵尸进程
2.1:网络
每个Pod都会被分配一个唯一的IP地址。Pod中的所有容器共享网络空间,包括IP地址和端口。Pod内部的容器可以使用localhost互相通信。
Pod中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。
2.2存储
Pod可以指定多个共享的volume。Pod中的所有容器都可以访问共享的volume。Volume也可以用来持久化Pod中的存储资源,以防容器重启后文件丢失。
pause功能:
① PID命名空间:Pod中的不同应用程序可以看到其他应用程序的进程ID。
② 网络命名空间:Pod中的多个容器能够访问同一个IP和端口范围。
③ IPC命名空间:Pod中的多个容器能够使用SystemV IPC或POSIX消息队列进行通信。
④ UTS命名空间:Pod中的多个容器共享一个主机名;Volumes(共享存储卷):
⑤ Pod中的各个容器可以访问在Pod级别定义的Volumes。
3.pod的三个探针
livenessProbe(存活探针)、readinessProbe(就绪探针)startupProbe(启动探针)三个探针,也是写在pod的资源清单里面的,写好了他的探测机制以及命令,写资源清单的时候没写过
实践参考
初始化容器实践
apiVersion: v1 #指定k8s的官方接口版本,目前就只有v1,这个是这个yaml文档使用服务接口
kind: Pod #指定这个yaml文件是一个Pod数据类型
metadata:
name: lqh-initpod1 #这个pod的名字
labels: #给这个pod贴标签
app: pod01-label
version: v2 #给这个pod定义一个版本
namespace: space02 #声明一个新的命名空间
spec: #详细定义这个yaml资源的内容specific具体的单词缩写
initContainers: #容器执行完就退出了
- name: redis011 #容器名
image: redis #镜像名字
imagePullPolicy: IfNotPresent # 指定拉取镜像的策略,默认是Always,每次尝试拉去新的, IfNotPresent表示每本的的再去拉
command: ["echo", "Hello第一个初始化容器redis01!"]
- name: nginx011 #容器名
image: nginx #镜像名字
imagePullPolicy: IfNotPresent # 指定拉取镜像的策略,默认是Always,每次尝试拉去新的, IfNotPresent表示每本的的再去拉
command: ["echo", "Hello 第二个初始化容器Nginx01!"]
containers: #指定这个pod的容器 下面的中横杠是表示yaml格式的数组
- name: redis01 #容器名
image: redis #镜像名字
imagePullPolicy: IfNotPresent # 指定拉取镜像的策略,默认是Always,每次尝试拉去新的, IfNotPresent表示每本的的再去拉
ports:
- containerPort: 6379
hostPort: 6355
- containerPort: 8080
hostPort: 8089
- name: nginx01 #容器名
image: nginx #镜像名字
imagePullPolicy: IfNotPresent # 指定拉取镜像的策略,默认是Always,每次尝试拉去新的, IfNotPresent表示每本的的再去拉```
4.pod的的start和stop
pod的启动和退出需要做哪一些操作写在1资源清单的lifecycle的postStart和preStop字段里,这就是start和stop.
参考
5.pod的相位
pod的状态就是相位,说的高大上而已。
由pod的分类知道什么是控制器
Pod 的分类
自主式 Pod:Pod 退出了,此类型的 Pod 不会被创建
控制器管理的 Pod:在控制器的生命周期里,始终要维持 Pod 的副本数目
1.replicaController:能保证pod的一定的副本数,pod异常退出会自动创建新的来代替
2.replicaSet:在replicaController基础上支持集合式的selector;可以使用打标签的方式进行指定集合
3.deployment(部署):这个控制器是通过创建replicaSet来进行管理,支持回滚,升级pod(灰度上线)
4.daemonset(守护set):确保k8s集群的每一个node都有这个控制器下pod的副本,当有一个Node加入了就增加一个pod的副本,删除了一个node就相对得去掉一个pod副本
5.statefulSet**:状态控制器**,相对replicaSet和deployment是没状态设计的控制器,例如部署存储的pod.
6.job:一次性执行任务,其中cron job 管理基于时间的定时job
apply 和create的区别
1.kubectl create命令可创建新资源。 因此,如果再次运行该命令,则会抛出错误,因为资源名称在名称空间中应该是唯一的。
2.apply 重复创建一个pod不报错,报pod/lqhpod1 unchanged;资源清单不在在kubectl apply命令中,我们指定系统的目标状态,并且不指定特定操作,因此声明性 。 我们让系统决定采取什么行动。 如果资源不在那里,它将创建它,如果资源在那里,那么它将配置应用于现有资源。
实践ReplicaSet
k8s的污点:
什么是污点容忍度:
taints:污点,定义在节点上,是键值数据
tolerations:容忍度,定义在pod上,可以定义能容忍哪些污点
使节点能够排斥一类特定的 pod。Taint 和 toleration 相互配合,可以用来避免pod 被分配到不合适的节点上。
apply生成rs报错:1 node(s) had taints that the pod didn’t tolerate
解决办法:删除node的污点
污点参考
replicaset的资源清单(新建一个名称为lqhrs2的rs)
apiVersion: extensions/v1beta1 #指定k8s的官方接口版本,目前就只有v1,这个是这个yaml文档使用服务接口
kind: ReplicaSet
metadata:
name: lqhrs2
namespace: space01 #声明一个新的命名空间
spec:
replicas: 3
selector:
matchLabels:
tier: lqhlabel1
template: # pod薪资嵌套在这个控制器的template里面
metadata:
labels:
tier: lqhlabel1 #绑定selector的label
spec:
nodeName: k8s-master01 #指定了node那么他所有的pod都在这个节点运行
containers: #指定这个pod的容器 下面的中横杠是表示yaml格式的数组
- name: redis01 #容器名
image: redis #镜像名字
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6379
hostPort: 6355
- containerPort: 8080
hostPort: 8089
- name: nginx01 #容器名
image: nginx #镜像名字
imagePullPolicy: IfNotPresent
遇到上面bug后看新建结果
实践rs拉起被删除的pod(控制器自动新建一个来代替
控制器rs是通过label来控制pod的(注意pod的label是通过键值对来标识的,资源清单的tie也是开发者随意起的名字)
lqhrs2的pod(lqhrs2-vpdvs)更改label之前
更改之后lqhlabel2
lqhrs2会新建一个pod维持自己的副本3,lqhrs2-vpdvs这个pod不受lqhrs2这个控制器管了
## 实践deployment
deployment资源清单(新建一个lqhdm1的deployment)
```yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: lqhdm1
namespace: space01 #声明一个新的命名空间
spec:
replicas: 3
selector:
matchLabels:
dmlab: lqhdmlab
template: # pod薪资嵌套在这个控制器的template里面
metadata:
labels:
dmlab: lqhdmlab #绑定selector的label
spec:
containers: #指定这个pod的容器 下面的中横杠是表示yaml格式的数组
- name: redis01 #容器名
image: redis #镜像名字
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6379
# hostPort: 6355
- containerPort: 8080
# hostPort: 8089
- name: nginx01 #容器名
image: nginx #镜像名字
imagePullPolicy: IfNotPresent
scale扩容新建pod是一个逐渐的过程
更新deployment下的容器的镜像
外部docker制作另外一个nginx镜像nginxv2
更新镜像不成功应该是不是使用本地的nginxv2 新建起来的,新建的rs(lqhdm1-6c64c5d7dd)下的pod没起来,还是使用原来的rs(lqhdm1-5ddc7f777b)
查找pod更新镜像失败没起来原因:其他两个node本地没有nginxv2这个镜像,在其他两个节点重复上面操作制作镜像nginxv2之后成功了,dmlqh1这个deployment的下的rs变成了lqhdm1-6c64c5d7dd
回滚版本
deployment的其他指令:
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 的更新
daemonSet实践
daemon资源清单里面指定replicas会报错 ValidationError(DaemonSet.spec): unknown field “replicas”
原因: daemonSet控制器会保证每一node有一个副本,不用指定
资源清单
apiVersion: apps/v1 #和rs,deployment又不一样
kind: DaemonSet
metadata:
name: lqhds1
namespace: space01 #声明一个新的命名空间
spec:
# replicas: 2 #daemonset是没有这个字段的
selector:
matchLabels:
dslab: lqhdslab
template: # pod薪资嵌套在这个控制器的template里面
metadata:
labels:
dslab: lqhdslab #绑定selector的label
spec:
containers: #指定这个pod的容器 下面的中横杠是表示yaml格式的数组
- name: redis01 #容器名
image: redis #镜像名字
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6379
# hostPort: 6355
- containerPort: 8080
#hostPort: 8089
- name: nginx01 #容器名
image: nginx #镜像名字
imagePullPolicy: IfNotPresent
看效果,daemonset不会像deployment新建一个rs来实现
删除一个master上的一个pod,为了维持每一个node上有一个pod副本会立即生成一个新的pod
job实践
资源和其他控制器有区别不用selector
apiVersion: batch/v1 #和rs,deployment又不一样
kind: Job
metadata:
name: lqhjob1
namespace: space01 #声明一个新的命名空间
spec:
template: # pod薪资嵌套在这个控制器的template里面
metadata:
spec:
containers: #指定这个pod的容器 下面的中横杠是表示yaml格式的数组
- name: redis01 #容器名
image: redis #镜像名字
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6379
- containerPort: 8080
command: ["echo", "Hello 作业帮牛的!"]
- name: nginx01 #容器名
image: nginx #镜像名字
imagePullPolicy: IfNotPresent
command: ["echo", "Hello 作业帮牛的!"]
restartPolicy: Never #容器永不重启
看效果
cronJob实践
资源清单,job的模板是嵌套在jobTemplate下面的,k8s变量名不能大写
起两个容器的每一分钟的第一秒执行的定时任务
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: lqhCronJob1
namespace: space01 #声明一个新的命名空间
spec:
schedule: "*/1 * * * *" #必写字段,仅支持5位,第一位表示每一分钟的第一秒执行,
jobTemplate: #job模板,必填,和job的格式一样
spec:
template: #是嵌套在jobTemplate下面的
metadata:
spec:
containers: #指定这个pod的容器 下面的中横杠是表示yaml格式的数组
- name: redis01 #容器名
image: redis #镜像名字
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6379
- containerPort: 8080
command: ["echo", "这是一个定时任务哦"]
- name: nginx01 #容器名
image: nginx #镜像名字
imagePullPolicy: IfNotPresent
command: ["echo", "这是一个定时任务哦!"]
restartPolicy: OnFailure #容器异常重启
.spec.concurrencyPolicy:并发策略,该字段也是可选的。它指定了如何处理被 Cron Job 创建的 Job 的并发执行。只允许指定下面策略中的一种:
Allow(默认):允许并发运行 Job
Forbid:禁止并发运行,如果前一个还没有完成,则直接跳过下一个
Replace:取消当前正在运行的 Job,用一个新的来替换
看效果
这个定时任务不删除,会每一分钟新建一个pod,但查询只保留了三个,会定期删除complete的pod
statefulSet实践
statefulSet有状态服务,之前一直理解错了并不是因为他是能存储数据,其实deployment也可以通过pvc,volume技术挂载的,但deployment是解决不了pod之间主从关系、主备关系等,pod之间是完全对等的关系。statefulset能有稳定的网络标识(通过没有headless service实现),pod之前的启动删除扩展是有顺序的,这个才是为什么他叫有状态服务的原因。
statefulset的资源清单必须有serviceName这个字段的
headless无头服务资源清单
apiVersion: v1
kind: Service
metadata:
name: lqh-statefulset-svc
namespace: space02
spec:
type: ClusterIP
selector:
svc-lab: svc-lab-Value #绑定ClusterIp的label
clusterIP: None #没有ip的服务svc
ports:
- name: redis01p1
port: 6378 #访问svc暴露的port
targetPort: 6379 #svc访问pod使用port
- name: redis01p2
port: 8090
targetPort: 8080
- name: nginx01
port: 81
targetPort: 80
statefulset资源清单:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: lqh-svc-statefulset
namespace: space02 #声明一个新的命名空间
spec:
serviceName: lqh-statefulset-svc
replicas: 3
selector:
matchLabels:
stateful-lab: stateful-lab-value
template: # pod薪资嵌套在这个控制器的template里面
metadata:
labels:
svc-lab: svc-lab-Value
stateful-lab: stateful-lab-value #
spec:
containers: #指定这个pod的容器 下面的中横杠是表示yaml格式的数组
- name: redis01 #容器名
image: redis #镜像名字
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6379
- containerPort: 8080
- name: nginx01 #容器名
image: nginx #镜像名字
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
看效果
statefulset下的pod的名字不会变的。
1.StatefulSet 为每个 Pod 副本创建了一个 DNS 域名,这个域名的格式为:
(
p
o
d
n
a
m
e
)
.
(
h
e
a
d
l
e
s
s
s
e
r
v
e
r
n
a
m
e
)
,也就意味着
∗
∗
服务间是通过
P
o
d
域名来通信而非
P
o
d
I
P
∗
∗
(
n
o
d
e
节点通过这个
p
o
d
名字是行不通的),因为当
P
o
d
所在
N
o
d
e
发生故障时,
P
o
d
会被飘移到其它
N
o
d
e
上,
P
o
d
I
P
会发生变化,但是
P
o
d
域名不会有变化
2.
S
t
a
t
e
f
u
l
S
e
t
使用
H
e
a
d
l
e
s
s
服务来控制
P
o
d
的域名,这个域名的
F
Q
D
N
为:
(podname).(headless server name),也就意味着**服务间是通过Pod域名来通信而非 Pod IP**(node节点通过这个pod名字是行不通的),因为当Pod所在Node发生故障时, Pod 会 被飘移到其它 Node 上,Pod IP 会发生变化,但是 Pod 域名不会有变化 2.StatefulSet 使用 Headless 服务来控制 Pod 的域名,这个域名的 FQDN 为:
(podname).(headlessservername),也就意味着∗∗服务间是通过Pod域名来通信而非PodIP∗∗(node节点通过这个pod名字是行不通的),因为当Pod所在Node发生故障时,Pod会被飘移到其它Node上,PodIP会发生变化,但是Pod域名不会有变化2.StatefulSet使用Headless服务来控制Pod的域名,这个域名的FQDN为:(servicename).$(namespace).svc.cluster.local,其中,“cluster.local” 指的是集群的域名
进入statefulset的容器里面根据pod名可以访问另外一个pod,这里由无头服务的DNS完成
k8s是给无头服务(没指定的虚拟ip的clusterIp类型的svc)提供了域名解析服务,可以借助dig指令来解析一下(servicename).$(namespace).svc.cluster.local这个空间下服务的ip映射。k8s域名服务器是在kube-system空间下dnspod。dig指令使用教程
看效果:
进入到无头服务以外的pod容器内ping无头服务的svc域名lqh-statefulset-svc.space02.svc.cluster.local(或lqh-statefulset-svc.space02),每次打到的ip不一样,一般是轮询,这相当于集群内部服务之间的调用,例如sch调用schui,
注意:在本节点node去ping这个SVC域名是通不了的,因为域名服务只提供给内部服务pod用
进入到无头服务以外的pod容器内ping无头服务的某一台pod域名也可以不svc.cluster.local
更多推荐
所有评论(0)