目录
一、基础操作
1、简化别名设置
2、查看kubernetes的资源对象
3、创建、查看namespace
4、Pod 增删改查
二、YAML文件创建Pod
1、标签部分作用
1.生成yaml文件
2.修改yaml中的标签名
2、imagePullPolicy
1.增加镜像拉取策略
2.yaml批量创建pod
3.通过label查询
3、restartPolicy 作用
1.修改重启策略
2.停止容器内的服务
3.常用退出码表:
4、dnsPolicy的作用
1.修改策略
2.查看Pod的DNS配置
5、容器对外暴露端口设置
1.修改yaml文件端口部分
2.修改后重新创建nginx3,测试是否能访问服务
3.若在master和非Pod工作节点 访问pod需要如下修改
①若集群外需要访问以service为例(还可以通过ingress)
②修改nginx3的yaml文件
③测试
6、容器执行的命令及参数设置
1. 编辑yaml文件
1.删除所有yaml文件
2.编写nginx1.yaml文件
3.编写nginx2.yaml文件
4.编写nginx3.yaml文件
5.创建三个Pod
6.查看运行日志
7.使用Dockerfile创建image验证
1.编写Dockerfile
2.使用dockerfile创建镜像
3.将制作的image制作成tar归档文件
4.将tar归档文件传送给工作节点(默认做过ssh免密)
5.加载镜像
6. 编写nginx4yaml文件
7.启动Pod
8.查看详细信息
7、容器中环境变量设置
1.修改nginx3.yaml文件
2.创建Pod
3.查看Pod日志
4.知识点
5.通过kubectl打印指定字段中的变量
8、容器资源限制
1.修改nginx3.yaml文件
2.创建Pod
3.验证结果-已达到最大限额
1.使用kubectl进入容器查询
2.在Node节点使用Docker查询
9、相同Pod中运行多个容器
1.修改yaml文件
2.创建Pod
3.查看状态
4.思考问题
1.两个容器是否有启动顺序?
2.如果其中一个容器没有顺利启动,是否会影响另外一个容器的启动?
1.修改其中一个镜像为不存在
2.应用
3.验证
3.如果要登入某个容器,该如何执行命令?(将镜像改为正常镜像并应用不在赘述)
10、初始化容器
1.initContainers优势
2.修改yaml文件
3.创建Pod
4.查看容器初始化信息
5.模拟问题
1.修改yaml文件,将访问地址改为一个无法访问的
2.刷新Pod
3.查看pod
4.结论
11、Pod健康检查
1.容器探针介绍
2.修改yaml文件
3.创建Pod
4.kubelet 驱逐时 Pod 的选择
5.问题
12、PV和PVC
1.介绍
2.实验准备工作
1.k8s01中安装nfs-server
2.工作节点 - 安装nfs客户端
3.配置nfs规则及启动服务
4.测试服务
3.编写YAML文件
1.编写PV的yaml文件
2.编写PVC的yaml文件
4.部署PV与PVC
5.使用PV和PVC
1.修改nginx3.yaml文件
2.部署Pod
5.测试
1.通过url访问测试
2.通过容器内部查询
一、基础操作
1、简化别名设置
[root@k8s01 ~]# alias k=kubectl #方便使用,官方考试默认使用k替代kubectl
标准关系运算符
2、查看kubernetes的资源对象
[root@k8s01 ~]# k api-resources
NAME SHORTNAMES APIGROUP NAMESPACED KIND
bindings true Binding
componentstatuses cs false ComponentStatus
configmaps cm true ConfigMap
endpoints ep true Endpoints
events ev true Event
limitranges limits true LimitRange
namespaces ns false Namespace
nodes no false Node
persistentvolumeclaims pvc true PersistentVolumeClaim
persistentvolumes pv false PersistentVolume
pods po true Pod
....
3、创建、查看namespace
[root@k8s01 ~]# k create namespace myname
namespace/myname created
[root@k8s01 ~]# k get namespaces
NAME STATUS AGE
default Active 9h
kube-node-lease Active 9h
kube-public Active 9h
kube-system Active 9h
myname Active 16s
4、Pod 增删改查
若不指定命名空间,默认在default命名空间
[root@k8s01 ~]# kubectl run nginx --image=nginx:1.21 #创建Pod
pod/nginx created
[root@k8s01 ~]# k get pods #查询default命名空间中的所有pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 9m34s[root@k8s01 ~]# k describe pod #列出Pod的详细信息
Name: nginx
Namespace: default
Priority: 0
Node: k8s03/192.168.248.22
Start Time: Mon, 14 Aug 2023 22:00:47 -0400
...
以YAML格式查看pod的详情
[root@k8s01 ~]# k get pods nginx -o yaml
apiVersion: v1
kind: Pod
metadata:annotations:cni.projectcalico.org/containerID: 49cd8e984a01a8f1cb2edb7820e1fe646bc4c9eb6711701aa6b0505b6911ab36cni.projectcalico.org/podIP: 10.244.235.130/32cni.projectcalico.org/podIPs: 10.244.235.130/32creationTimestamp: "2023-08-15T02:00:47Z"labels:run: nginx
...
可以使用YAML文件进行Pod的创建,可以使用“--dry-run”仅打印向kubernetes发送的内容,而不真正执行,同时使用“-o”可以指定输出的格式:
[root@k8s01 ~]# k run nginx --image=nginx:1.21 --dry-run=client -o yaml
apiVersion: v1
kind: Pod
metadata:creationTimestamp: nulllabels:run: nginxname: nginx
spec:containers:- image: nginx:1.21name: nginxresources: {}dnsPolicy: ClusterFirstrestartPolicy: Always
status: {}#当使用--dry-run=client选项时,kubectl会在本地客户端执行该命令,并根据命令的参数和选项生成一个
#模拟的资源配置文件。这个文件可以通过输出或重定向进行获取。这种方式不会将任何更改提交到服务器端,
#仅用于验证命令的有效性和观察其预期行为。#相反,当使用--dry-run=server选项时,kubectl会将模拟的请求发送到服务器端进行处理。
#服务器将根据请求中的信息模拟执行相应的操作,并返回模拟结果给客户端。
#这种方式可以验证命令在服务器端的行为,并获得更准确的模拟结果。
或者直接输出到yaml文件
[root@k8s01 ~]# k run nginx -o yaml --image=nginx:1.21 --dry-run=client > nginx.yaml
#借助生成的yaml文件,创建一个新的Pod;
[root@k8s01 ~]# cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:creationTimestamp: nulllabels:run: nginxname: nginx
spec:containers:- image: nginx:1.21name: nginxresources: {}dnsPolicy: ClusterFirstrestartPolicy: Always
status: {}[root@k8s01 ~]# k create -f nginx.yaml
Error from server (AlreadyExists): error when creating "nginx.yaml": pods "nginx" already exists
#提示nginx已存在
[root@k8s01 ~]# sed -i '0,/name: nginx/s/nginx/nginx-yaml/' nginx.yaml #改变容器标签,因为标签是唯一的所以无法创建
#或者可以修改命名空间,每个命名空间相对隔离
[root@k8s01 ~]# k create -f nginx.yaml
pod/nginx-yaml created
登录到容器内部
[root@k8s01 ~]# k exec -it nginx -- /bin/bash
删除容器
[root@k8s01 ~]# k delete pods nginx
pod "nginx" deleted
#可以把容器名换为 --all 代表删除所有容器
#加 --force 代表强制删除
#--grace-period
#非负值: --grace-period 参数只能接受非负整数值,即大于等于零的整数。
#删除流程: 当你执行删除操作时(例如 kubectl delete 命令),Kubernetes 会尝试触发资源的优雅终止。
#优雅终止期: --grace-period 设置了资源的优雅终止期,即在这个时间段内,Kubernetes 将等待资源进行清理操作。
#超时处理: 如果在优雅终止期内资源没有终止,Kubernetes 将强制删除该资源,以确保资源的删除不会无限期地阻塞。
#立即删除: 如果你希望立即删除资源,可以将 --grace-period 设置为 0,这将绕过优雅终止期,立即删除资源。
#--force: 如果在删除操作中同时使用了 --force 参数,--grace-period 的设置会被忽略,资源将会被立即强制删除
二、YAML文件创建Pod
1、标签部分作用
1.生成yaml文件
[root@k8s01 ~]# k run nginx -o yaml --image=nginx:1.21 --dry-run=client > nginx1.yaml
[root@k8s01 ~]# k run nginx -o yaml --image=nginx:1.21 --dry-run=client > nginx2.yaml
[root@k8s01 ~]# k run nginx -o yaml --image=nginx:1.21 --dry-run=client > nginx3.yaml
2.修改yaml中的标签名
[root@k8s01 ~]# sed -i '0,/name: nginx/s/nginx/nginx1/' nginx1.yaml
[root@k8s01 ~]# sed -i '0,/name: nginx/s/nginx/nginx2/' nginx2.yaml
[root@k8s01 ~]# sed -i '0,/name: nginx/s/nginx/nginx3/' nginx3.yaml
2、imagePullPolicy
1.增加镜像拉取策略
拉取策略说明
[root@k8s01 ~]# for i in {1..3}; do sed -i '/resources/ a \ \ \ \ imagePullPolicy: IfNotPresent' nginx$i.yaml; done
#IfNotPresent: 只有当镜像在本地不存在时才会拉取,默认策略
#Always: 每当 kubelet 启动一个容器时,kubelet 会查询容器的镜像仓库, 将名称解析为一个镜像摘要。 如果 kubelet 有一个容器镜像,并且对应的摘要已在本地缓存,kubelet 就会使用其缓存的镜像; 否则,kubelet 就会使用解析后的摘要拉取镜像,并使用该镜像来启动容器。
#Never: Kubelet 不会尝试获取镜像。如果镜像已经以某种方式存在本地, kubelet 会尝试启动容器;否则,会启动失败。
2.yaml批量创建pod
[root@k8s01 ~]# for i in {1..3}; do k create -f nginx${i}.yaml; done
pod/nginx1 created
pod/nginx2 created
pod/nginx3 created
3.通过label查询
[root@k8s01 ~]# kubectl get pods -l run
NAME READY STATUS RESTARTS AGE
nginx1 1/1 Running 0 6m54s
nginx2 1/1 Running 0 6m54s
nginx3 1/1 Running 0 6m54s
[root@k8s01 ~]# k get pods -l run!=nginx1 #通过排除标签名显示
NAME READY STATUS RESTARTS AGE
nginx2 1/1 Running 0 8m28s
nginx3 1/1 Running 0 8m28s
[root@k8s01 ~]# k get pods -l run=nginx1 #显示匹配的标签名显示
NAME READY STATUS RESTARTS AGE
nginx1 1/1 Running 0 8m36s
3、restartPolicy 作用
1.修改重启策略
#修改2,3yaml文件的重启策略
[root@k8s01 ~]# sed -i "/restartPolicy/ s/Always/OnFailure/" nginx2.yaml
[root@k8s01 ~]# sed -i "/restartPolicy/ s/Always/Never/" nginx3.yaml
#删除pod
[root@k8s01 ~]# k delete pods --all #删除default空间内的所有pod
#重新创建Pod
[root@k8s01 ~]# for i in {1..3}; do k create -f nginx${i}.yaml; done
pod/nginx1 created
pod/nginx2 created
pod/nginx3 created
2.停止容器内的服务
#停止所有pod
[root@k8s01 ~]# for i in {1..3}; do k exec -it nginx${i} -- nginx -s stop; done
2023/08/15 06:22:56 [notice] 32#32: signal process started
2023/08/15 06:22:56 [notice] 32#32: signal process started
2023/08/15 06:22:56 [notice] 32#32: signal process started
#查看pod状态,发现2/3处理完成状态
[root@k8s01 ~]# k get pods
NAME READY STATUS RESTARTS AGE
nginx1 1/1 Running 1 8m4s
nginx2 0/1 Completed 0 8m4s
nginx3 0/1 Completed 0 8m4s
#查看容器退出码
[root@k8s01 ~]# for i in {1..3}; do kubectl describe pods nginx${i} | grep "Exit Code"; doneExit Code: 0Exit Code: 0Exit Code: 0
#均为正常退出
结论:器是为任务而生的,因此,停止nginx服务后,容器也会随之停止
Always: 始终重启(默认值)
OnFailure:仅在失败时重启
Never: 永不重启
Pod 的生命周期
3.常用退出码表:
退出码 0:成功(Success) 容器正常退出且没有错误。通常情况下,0 表示一切正常。
非零退出码:错误(Errors) 任何非零的退出码都表示容器执行过程中遇到了问题。具体的非零值可能有不同的含义,这取决于容器内部的应用程序和操作。通常,开发者会在文档中记录他们的应用程序使用的退出码含义。
1:通用错误(Generic Error) 1 经常被用来表示通用的错误情况,没有具体的细节可以提供。
2:错误的 shell 命令语法(Misuse of shell builtins) 这个退出码通常表示 shell 命令语法错误,可能是命令拼写错误、错误的选项或参数等。
126:无法执行命令(Cannot execute command) 这个退出码表示无法执行指定的命令,可能是由于权限问题、找不到命令等原因。
127:找不到命令(Command not found) 这个退出码表示指定的命令未找到,可能是因为没有正确设置 PATH 或者命令不存在。
128:无效的退出码(Invalid argument to exit) 这个退出码表示容器内部的程序在调用
exit
函数时传递了一个无效的退出码,例如一个超出范围的值。130:中断信号(Terminated by Ctrl+C) 当用户在容器内部按下 Ctrl+C 组合键时,容器会被发送中断信号,退出码为 130。
137:OOM(Out of Memory) 当容器因为内存不足而被强制终止时,通常会返回退出码 137。这表示容器发生了内存溢出。
139:段错误(Segmentation Fault) 当容器内部的程序访问了无效的内存地址时,可能会导致段错误,返回退出码 139。
4、dnsPolicy的作用
1.修改策略
[root@k8s01 ~]# k delete pods --all #删除之前的Pod#nginx1改为None,加入2行:使用指定的 DNS 服务器来解析域名
[root@k8s01 ~]# sed -i "/dnsPolicy/ s/ClusterFirst/None/" nginx1.yaml
[root@k8s01 ~]# sed -i '/dnsPolicy/ a \ dnsConfig:\n nameservers: ["192.168.1.1","192.168.1.2"]' nginx1.yaml#nginx2改为Default
[root@k8s01 ~]# sed -i "/dnsPolicy/ s/ClusterFirst/Default/" nginx2.yaml #nginx3不变,保持ClusterFirst
2.查看Pod的DNS配置
[root@k8s01 ~]# for i in {1..3}; do k exec -it nginx${i} -- cat /etc/resolv.conf; done
nameserver 192.168.1.1
nameserver 192.168.1.2
nameserver 114.114.114.114
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
[root@k8s01 ~]# k get service -A | grep "10.96.0.10"
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 15h
Service 与 Pod 的 DNS | Kubernetes
结论:ClusterFirst配置的DNS是集群IP,该服务用于 DNS 解析和监控
5、容器对外暴露端口设置
1.修改yaml文件端口部分
[root@k8s01 ~]# k delete pods --all #删除之前创建的Pod
#修改nginx3.yaml文件,增加端口部分信息
[root@k8s01 ~]# sed -i '/imagePullP/ a\ ports:\n - name: nginx\n protocol: TCP\n containerPort: 80\n hostPort: 30001' nginx3.yaml
2.修改后重新创建nginx3,测试是否能访问服务
[root@k8s01 ~]# k apply -f nginx3.yaml
[root@k8s01 ~]# k get pods -o wide | awk 'NR==2 {print $6}' #查看Pod的IP地址
10.244.236.137
[root@k8s01 ~]# curl -s 10.244.236.136 | awk '/h1/ {print $0}' #可以正常访问
<h1>Welcome to nginx!</h1>[root@k8s01 ~]# k describe pods nginx3 | grep "Host Port" #查看暴露端口Host Port: 30001/TCP
[root@k8s01 ~]# k get pods -o wide | awk 'NR==2 {print $7}' #查看pod所处工作节点
k8s02
# 访问测试Pod的工作节点
[root@k8s01 ~]# curl -s 192.168.248.21:30001 | awk '/h1/ {print $0}'
<h1>Welcome to nginx!</h1>
3.若在master和非Pod工作节点 访问pod需要如下修改
Kubernetes 网络解决四方面的问题:
- 一个 Pod 中的容器之间通过本地回路(loopback)通信。
- 集群网络在不同 Pod 之间提供通信。
- Service API 允许你向外暴露 Pod 中运行的应用, 以支持来自于集群外部的访问。
- Ingress 提供专门用于暴露 HTTP 应用程序、网站和 API 的额外功能。
- 你也可以使用 Service 来发布仅供集群内部使用的服务。
每个 Service 创建时,会被分配一个唯一的 IP 地址(也称为 clusterIP)。 这个 IP 地址与 Service 的生命周期绑定在一起,只要 Service 存在,它就不会改变。 可以配置 Pod 使它与 Service 进行通信,Pod 知道与 Service 通信将被自动地负载均衡到该 Service 中的某些 Pod 上
使用 Service 连接到应用
①若集群外需要访问以service为例(还可以通过ingress)
集群中创建一个 Service,并且会分配一个随机的 NodePort,可以让你通过
curl <NodeIP>:<NodePort>
访问到该 Pod。请确保替换<NodeIP>
为实际的节点 IP 地址
#创建service文件
[root@k8s01 ~]# cat >> nginx1-service.yaml << EOF
apiVersion: v1
kind: Service
metadata:name: nginx-service
spec:type: NodePortports:- name: nginxprotocol: TCPport: 80targetPort: 80selector:run: nginx3
EOF
[root@k8s01 ~]# k apply -f nginx-service.yaml #启动服务
②修改nginx3的yaml文件
[root@k8s01 ~]# cat nginx3.yaml
apiVersion: v1
kind: Pod
metadata:creationTimestamp: nulllabels:run: nginx3name: nginx3
spec:containers:- image: nginx:1.21name: nginxresources: {}imagePullPolicy: IfNotPresentports:- name: nginxprotocol: TCPcontainerPort: 30001hostPort: 30001dnsPolicy: ClusterFirstWithHostNetrestartPolicy: NeverhostNetwork: true
status: {}
#集群中创建一个 Service,并且会分配一个随机的 NodePort,可以让你通过
#curl <NodeIP>:<NodePort> 访问到该 Pod。请确保替换 <NodeIP> 为实际的节点 IP 地址[root@k8s01 ~]# k replace -f nginx3.yaml --force
pod "nginx3" deleted
pod/nginx3 replaced
③测试
[root@k8s01 ~]# k get service nginx-service #查看暴露端口
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service NodePort 10.97.117.100 <none> 80:32656/TCP 15m
[root@k8s01 ~]# curl -s 192.168.248.20:32656|awk '/h1/ {print $0}' #访问正常
<h1>Welcome to nginx!</h1>
Service 与 Pod 的 DNS
"
ClusterFirstWithHostNet
": 对于以 hostNetwork 方式运行的 Pod,应将其 DNS 策略显式设置为 "ClusterFirstWithHostNet
"。否则,以 hostNetwork 方式和"ClusterFirst"
策略运行的 Pod 将会做出回退至"Default"
策略的行为
6、容器执行的命令及参数设置
#删除pod和service
[root@k8s01 ~]# k delete pods nginx3 --force
[root@k8s01 ~]# k delete service nginx-service
1. 编辑yaml文件
1.删除所有yaml文件
[root@k8s01 ~]# for i in {1..3}; do rm -rf nginx${i}.yaml; done
2.编写nginx1.yaml文件
更改了镜像、及内部命令
[root@k8s01 ~]# cat >> nginx1.yaml << EOF
apiVersion: v1
kind: Pod
metadata:labels:app: nginx1name: nginx1
spec:containers:- image: busyboximagePullPolicy: IfNotPresentname: nginxcommand: ["ping","www.baidu.com","-c","10"]resources: {}dnsPolicy: ClusterFirstrestartPolicy: Always
EOF
3.编写nginx2.yaml文件
更改了镜像、及内部命令
[root@k8s01 ~]# cat >> nginx2.yaml << EOF
apiVersion: v1
kind: Pod
metadata:labels:app: nginx2name: nginx2
spec:containers:- image: busyboximagePullPolicy: IfNotPresentname: nginxcommand:- ping- www.baidu.com- -c- "10"resources: {}dnsPolicy: DefaultrestartPolicy: OnFailure
EOF
4.编写nginx3.yaml文件
更改了镜像、及内部命令
[root@k8s01 ~]# cat >> nginx3.yaml << EOF
apiVersion: v1
kind: Pod
metadata:labels:app: nginx3name: nginx3
spec:containers:- image: busyboximagePullPolicy: IfNotPresentname: nginxcommand: ["ping"]args: ["www.baidu.com","-c","10"]resources: {}dnsPolicy: ClusterFirstrestartPolicy: Never
EOF
5.创建三个Pod
[root@k8s01 ~]# for i in {1..3}; do k apply -f nginx${i}.yaml; done
pod/nginx1 created
pod/nginx2 created
pod/nginx3 created
6.查看运行日志
[root@k8s01 ~]# k logs nginx1
PING www.baidu.com (110.242.68.3): 56 data bytes
64 bytes from 110.242.68.3: seq=0 ttl=127 time=12.853 ms
64 bytes from 110.242.68.3: seq=1 ttl=127 time=13.670 ms
64 bytes from 110.242.68.3: seq=2 ttl=127 time=13.384 ms
64 bytes from 110.242.68.3: seq=3 ttl=127 time=13.487 ms
64 bytes from 110.242.68.3: seq=4 ttl=127 time=13.523 ms
64 bytes from 110.242.68.3: seq=5 ttl=127 time=13.780 ms
64 bytes from 110.242.68.3: seq=6 ttl=127 time=14.470 ms
64 bytes from 110.242.68.3: seq=7 ttl=127 time=14.060 ms
64 bytes from 110.242.68.3: seq=8 ttl=127 time=12.710 ms
64 bytes from 110.242.68.3: seq=9 ttl=127 time=14.310 ms--- www.baidu.com ping statistics ---
10 packets transmitted, 10 packets received, 0% packet loss
round-trip min/avg/max = 12.710/13.624/14.470 ms
[root@k8s01 ~]# k logs nginx2
PING www.baidu.com (110.242.68.4): 56 data bytes
64 bytes from 110.242.68.4: seq=0 ttl=127 time=13.175 ms
64 bytes from 110.242.68.4: seq=1 ttl=127 time=13.465 ms
64 bytes from 110.242.68.4: seq=2 ttl=127 time=14.807 ms
64 bytes from 110.242.68.4: seq=3 ttl=127 time=13.442 ms
64 bytes from 110.242.68.4: seq=4 ttl=127 time=14.531 ms
64 bytes from 110.242.68.4: seq=5 ttl=127 time=13.285 ms
64 bytes from 110.242.68.4: seq=6 ttl=127 time=13.944 ms
64 bytes from 110.242.68.4: seq=7 ttl=127 time=12.497 ms
64 bytes from 110.242.68.4: seq=8 ttl=127 time=13.932 ms
64 bytes from 110.242.68.4: seq=9 ttl=127 time=14.161 ms--- www.baidu.com ping statistics ---
10 packets transmitted, 10 packets received, 0% packet loss
round-trip min/avg/max = 12.497/13.723/14.807 ms
[root@k8s01 ~]# k logs nginx3
PING www.baidu.com (110.242.68.4): 56 data bytes
64 bytes from 110.242.68.4: seq=0 ttl=127 time=13.705 ms
64 bytes from 110.242.68.4: seq=1 ttl=127 time=13.956 ms
64 bytes from 110.242.68.4: seq=2 ttl=127 time=14.217 ms
64 bytes from 110.242.68.4: seq=3 ttl=127 time=13.594 ms
64 bytes from 110.242.68.4: seq=4 ttl=127 time=14.257 ms
64 bytes from 110.242.68.4: seq=5 ttl=127 time=13.735 ms
64 bytes from 110.242.68.4: seq=6 ttl=127 time=14.431 ms
64 bytes from 110.242.68.4: seq=7 ttl=127 time=13.181 ms
64 bytes from 110.242.68.4: seq=8 ttl=127 time=13.301 ms
64 bytes from 110.242.68.4: seq=9 ttl=127 time=13.492 ms--- www.baidu.com ping statistics ---
10 packets transmitted, 10 packets received, 0% packet loss
round-trip min/avg/max = 13.181/13.786/14.431 ms
根据输出,可以看到三个Pod都执行了“ping www.baidu.com -c 10”的命令
7.使用Dockerfile创建image验证
1.编写Dockerfile
[root@k8s01 ~]# cat >> Dockerfile << EOF
FROM nginx:1.21
LABEL label='My_image'ENTRYPOINT ["nginx","-g","daemon off;"]
EOF
2.使用dockerfile创建镜像
[root@k8s01 ~]# docker build -t nginx4:1.21 .
Sending build context to Docker daemon 4.024MB
Step 1/3 : FROM nginx:1.21---> 605c77e624dd
Step 2/3 : LABEL label='For HCIE_v3.0'---> Running in df10dcec8d7b
Removing intermediate container df10dcec8d7b---> 5d29e7b24699
Step 3/3 : ENTRYPOINT ["nginx","-g","daemon off;"]---> Running in a8821fda2b20
Removing intermediate container a8821fda2b20---> 868e92f29793
Successfully built 868e92f29793
Successfully tagged nginx4:1.21
3.将制作的image制作成tar归档文件
[root@k8s01 ~]# docker save nginx_4.tar nginx_4:1.21
4.将tar归档文件传送给工作节点(默认做过ssh免密)
[root@k8s01 ~]# for i in 192.168.248.2{1..2}; do scp nginx_4.tar root@$i:/root; done
5.加载镜像
[root@k8s01 ~]# for i in 192.168.248.2{1..2}; do ssh root@$i "docker load -i /root/nginx_4.tar"; done
Loaded image: nginx4:1.21
Loaded image: nginx4:1.21
6. 编写nginx4yaml文件
[root@k8s01 ~]# cat >> nginx4.yaml << EOF
apiVersion: v1
kind: Pod
metadata:labels:app: nginx4name: nginx4
spec:containers:- image: nginx4:1.21imagePullPolicy: IfNotPresentname: nginxcommand: ["ping"]args: ["www.baidu.com","-c","10"]resources: {}dnsPolicy: ClusterFirstrestartPolicy: Never
EOF
7.启动Pod
[root@k8s01 ~]# k apply -f nginx4.yaml
pod/nginx4 created
[root@k8s01 ~]# k get pods nginx4
NAME READY STATUS RESTARTS AGE
nginx4 0/1 ContainerCannotRun 0 4s
8.查看详细信息
[root@k8s01 ~]# k describe pods nginx4|tail -1Warning Failed 41m kubelet Error: failed to start container "nginx": Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"ping\": executable file not found in $PATH": unknown
提示容器的 $PATH 环境变量中找不到可执行文件 “ping”
容器镜像本身并不包含此命令,所以无法执行
7、容器中环境变量设置
删除所有Pod
[root@k8s01 ~]# k delete pods --all --force
1.修改nginx3.yaml文件
将yaml文件中命令及参数部分删除
[root@k8s01 ~]# sed -i "/command/,+1d" nginx3.yaml将yaml文件中的镜像源修改为nginx:1.21
[root@k8s01 ~]# sed -i '/- image/ s/busybox/nginx:1.21/' nginx3.yaml再yaml中添加环境变量及运行env
[root@k8s01 ~]# sed -i '/name: nginx$/ a\ env:\n - name: WELCOME\n value: "this is a test page"\n - name: WRONG\n value: "try again"\n command: ["env"]' nginx3.yaml
修改后的文件
[root@k8s01 ~]# cat nginx3.yaml
apiVersion: v1
kind: Pod
metadata:labels:app: nginx3name: nginx3
spec:containers:- image: nginx:1.21imagePullPolicy: IfNotPresentname: nginxenv:- name: WELCOMEvalue: "this is a test page"- name: WRONGvalue: "try again"command: ["env"]resources: {}dnsPolicy: ClusterFirstrestartPolicy: Never
2.创建Pod
[root@k8s01 ~]# k apply -f nginx3.yaml
3.查看Pod日志
[root@k8s01 ~]# k logs nginx3
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=nginx3
WELCOME=this is a test page
WRONG=try again
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
HOME=/root
发现增加的变量已经在容器内部环境变量中
4.知识点
kubectl exec -it nginx3 -- echo $WELCOME”是否能够打印出对应的变量值?
不能,因为此时打印的是当前解释器中的变量
等同于如下 k exec -it nginx3 -- sh -c 'echo $WELCOME'
如果使用“kubectl exec -it nginx3 -- /bin/bash”登入容器后,再使用命令“echo $WELCOME”是否可以打印出对应的变量值?
[root@k8s01 ~]# k exec -it nginx3 -- env error: cannot exec into a container in a completed pod; current phase is Succeeded [root@k8s01 ~]# k exec -it nginx3 -- /bin/bash error: cannot exec into a container in a completed pod; current phase is Succeeded
结论:
①Pod中的容器定义中指定了
command
字段时,Kubernetes会根据指定的命令在容器内部运行,而不是默认情况下运行容器中的应用程序②意味着容器将运行
env
命令并显示容器的环境变量。当容器运行指定的命令完成后,它会退出,然后Pod会进入Completed
状态③Pod的主要任务是运行容器内的进程,而当容器的主进程(或者在这种情况下,指定的命令)完成后,Pod的使命也就完成了; 所以无法再进入Pod
5.通过kubectl打印指定字段中的变量
[root@k8s01 ~]# k get pods nginx3 -o custom-columns=NODE:.spec.nodeName
NODE
k8s02NODE字段可自行命名,如果只想打印出变量的值需要额外处理,
-o custom-columns选项时,它只是输出了您定义的自定义列,但是在自定义列之前还会包含一列名称。这就是为什么在输出中会出现"NODE",然后才是实际的节点名称
示例如下:
[root@k8s01 ~]# kubectl get pods nginx3 -o custom-columns=NODE:.spec.nodeName --no-headers | awk '{print $1}'
k8s02
具体字段可参照kubectl explain <type>.<fieldName>[.<fieldName>]
[root@k8s01 ~]# k explain pods.spec
...nodeName <string>NodeName is a request to schedule this pod onto a specific node. If it isnon-empty, the scheduler simply schedules this pod onto that node, assumingthat it fits resource requirements.
...
8、容器资源限制
删除所有Pod
[root@k8s01 ~]# k delete pods --all --force
1.修改nginx3.yaml文件
[root@k8s01 ~]# cat > nginx3.yaml << EOF
apiVersion: v1
kind: Pod
metadata:labels:app: nginx3name: nginx3
spec:containers:- image: progrium/stressimagePullPolicy: IfNotPresentname: nginxargs:- -c- "1"resources:requests:cpu: 0.1limits:cpu: 0.3dnsPolicy: ClusterFirstrestartPolicy: Never
EOF
K8S-资源配额 — 指导手册
2.创建Pod
[root@k8s01 ~]# k apply -f nginx3.yaml
3.验证结果-已达到最大限额
1.使用kubectl进入容器查询
[root@k8s01 ~]# k exec -it nginx3 -- /bin/bash -c "ps -aux | grep stress"
root 1 0.0 0.0 7304 428 ? Ss 04:22 0:00 /usr/bin/stress --verbose -c 1
root 6 29.9 0.0 7304 100 ? R 04:22 3:24 /usr/bin/stress --verbose -c 1
root 32 0.0 0.0 17952 1400 pts/0 Ss+ 04:34 0:00 /bin/bash -c ps -aux | grep stress
root 38 0.0 0.0 8860 644 pts/0 S+ 04:34 0:00 grep stress
2.在Node节点使用Docker查询
[root@k8s02 ~]# docker exec -it 2a3c /bin/bash -c "ps -aux | grep stress"
root 1 0.0 0.0 7304 428 ? Ss 04:22 0:00 /usr/bin/stress --verbose -c 1
root 6 29.9 0.0 7304 100 ? R 04:22 6:40 /usr/bin/stress --verbose -c 1
root 46 0.0 0.0 17952 1400 pts/0 Ss+ 04:45 0:00 /bin/bash -c ps -aux | grep stress
root 52 0.0 0.0 8860 648 pts/0 S+ 04:45 0:00 grep stress
9、相同Pod中运行多个容器
删除所有Pod
[root@k8s01 ~]# k delete pods --all --force
1.修改yaml文件
[root@k8s01 ~]# cat > nginx3.yaml << EOF
apiVersion: v1
kind: Pod
metadata:labels:app: nginx3name: nginx3
spec:containers:- image: nginx:1.21imagePullPolicy: IfNotPresentname: nginxresources:requests:cpu: 0.1limits:cpu: 0.3- image: busyboxname: busyboxcommand:- sleep- "3600"dnsPolicy: ClusterFirstrestartPolicy: Never
EOF
2.创建Pod
[root@k8s01 ~]# k apply -f nginx3.yaml
3.查看状态
[root@k8s01 ~]# k get pods
NAME READY STATUS RESTARTS AGE
nginx3 2/2 Running 0 109s
4.思考问题
1.两个容器是否有启动顺序?
Pod中有多个容器时,这些容器是同时启动的,它们之间没有固定的启动顺序。Kubernetes 不会强制执行容器的启动顺序,因此它们可以并行启动。这允许Pod内的多个容器之间可以进行协同工作或共享资源
2.如果其中一个容器没有顺利启动,是否会影响另外一个容器的启动?
1.修改其中一个镜像为不存在
[root@k8s01 ~]# sed -i '/image: b/ s/busybox/oxxxxxx-321/' nginx3.yaml
2.应用
[root@k8s01 ~]# k get pods
NAME READY STATUS RESTARTS AGE
nginx3 1/2 ImagePullBackOff 0 5m25s
3.验证
[root@k8s01 ~]# k get pods -o wide | awk 'NR==2 {print $6}' #确认Pod访问地址
10.244.236.150[root@k8s01 ~]# curl -s 10.244.236.150 | grep "h1" #可以正常访问web服务
<h1>Welcome to nginx!</h1>
一个容器在Pod中没有成功启动,通常情况下不会直接影响其他容器的启动。每个容器都有自己的运行环境和资源,它们的启动和运行是独立的。然而,这并不意味着一个容器无法影响另一个容器,因为它们可能共享一些资源,如共享的卷(volumes)或网络命名空间
3.如果要登入某个容器,该如何执行命令?(将镜像改为正常镜像并应用不在赘述)
[root@k8s01 ~]# k exec -it nginx3 -c nginx -- /bin/bash
root@nginx3:/# exit
exit
[root@k8s01 ~]# k exec -it nginx3 -c busybox -- /bin/sh
/ # exit
10、初始化容器
删除所有Pod
[root@k8s01 ~]# k delete pods --all --force
1.initContainers优势
Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。 例如,没有必要仅为了在安装过程中使用类似
sed
、awk
、python
或dig
这样的工具而去FROM
一个镜像来生成一个新的镜像。应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
与同一 Pod 中的多个应用容器相比,Init 容器能以不同的文件系统视图运行。因此,Init 容器可以被赋予访问应用容器不能访问的 Secret 的权限。
由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。 一旦前置条件满足,Pod 内的所有的应用容器会并行启动。
Init 容器可以安全地运行实用程序或自定义代码,而在其他方式下运行这些实用程序或自定义代码可能会降低应用容器镜像的安全性。 通过将不必要的工具分开,你可以限制应用容器镜像的被攻击范围。
初始化容器
2.修改yaml文件
初始化容器
[root@k8s01 ~]# cat > nginx3.yaml << EOF
apiVersion: v1
kind: Pod
metadata:labels:app: nginx3name: nginx3
spec:initContainers:- image: busyboxname: busyboxcommand:- ping- www.baidu.com- -c- "5"containers:- image: nginx:1.21imagePullPolicy: IfNotPresentname: nginxresources:requests:cpu: 0.1limits:cpu: 0.3dnsPolicy: ClusterFirstrestartPolicy: Never
EOF
3.创建Pod
[root@k8s01 ~]# k apply -f nginx3.yaml
4.查看容器初始化信息
[root@k8s01 ~]# k logs nginx3 -c busybox
PING www.baidu.com (110.242.68.4): 56 data bytes
64 bytes from 110.242.68.4: seq=0 ttl=127 time=34.744 ms
64 bytes from 110.242.68.4: seq=1 ttl=127 time=28.026 ms
64 bytes from 110.242.68.4: seq=2 ttl=127 time=53.680 ms
64 bytes from 110.242.68.4: seq=3 ttl=127 time=29.150 ms
64 bytes from 110.242.68.4: seq=4 ttl=127 time=26.672 ms--- www.baidu.com ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
5.模拟问题
1.修改yaml文件,将访问地址改为一个无法访问的
[root@k8s01 ~]# sed -i '/www/ s/www.baidu.com/abc.abc.abc/' nginx3.yaml
2.刷新Pod
[root@k8s01 ~]# k replace -f nginx3.yaml --force
pod "nginx3" deleted
pod/nginx3 replaced
3.查看pod
[root@k8s01 ~]# k get pods
NAME READY STATUS RESTARTS AGE
nginx3 0/1 Init:Error 0 114s
[root@k8s01 ~]# k logs nginx3 -c busybox
ping: bad address 'abc.abc.abc'
[root@k8s01 ~]# k logs nginx3 -c nginx
Error from server (BadRequest): container "nginx" in pod "nginx3" is waiting to start: PodInitializing
因为是无效的域名,导致InitContainers失败,由于配置的Never最终导致Pod启动失败
4.结论
Init 容器与普通的容器非常像,除了如下两点:
- 它们总是运行到完成。
- 每个都必须在下一个启动之前成功完成。
如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。 然而,如果 Pod 对应的
restartPolicy
值为 "Never",并且 Pod 的 Init 容器失败, 则 Kubernetes 会将整个 Pod 状态设置为失败
11、Pod健康检查
删除所有Pod
[root@k8s01 ~]# k delete pods --all --force
1.容器探针介绍
种类:存活(Liveness)、就绪(Readiness)和启动(Startup)探针
手册 — 配置存活、就绪和启动探针
kubernetes -- Pod健康检查*_花非人陌_*的博客-CSDN博客
2.修改yaml文件
[root@k8s01 ~]# cat > nginx3.yaml << EOF
apiVersion: v1
kind: Pod
metadata:labels:app: nginx3name: nginx3
spec:containers:- image: nginx:1.21imagePullPolicy: IfNotPresentname: nginxresources:requests:cpu: 0.1limits:cpu: 0.3startupProbe:tcpSocket:port: 80failureThreshold: 15successThreshold: 1periodSeconds: 10timeoutSeconds: 1livenessProbe:tcpSocket:port: 80failureThreshold: 3successThreshold: 1periodSeconds: 5timeoutSeconds: 1 dnsPolicy: ClusterFirstrestartPolicy: Never
EOF
failureThreshold: 探测次数,若超过次数说明失败
successThreshold: 连续成功的探测次数,达到目标才会被认定为成功
periodSeconds: 探测间隔时间
timeoutSeconds: 单个探测的最大持续时间,即允许多长时间来等待探测的响应在 Kubernetes 1.20 版本之前,
exec
探针会忽略timeoutSeconds
: 探针会无限期地持续运行,甚至可能超过所配置的限期,直到返回结果为止initialDelaySeconds:字段告诉 kubelet 在执行第一次探测前应该等待多少秒
3.创建Pod
[root@k8s01 ~]# k apply -f nginx3.yaml
4.kubelet 驱逐时 Pod 的选择
kubelet 使用以下参数来确定 Pod 驱逐顺序:
- Pod 的资源使用是否超过其请求
- Pod 优先级
- Pod 相对于请求的资源使用情况
5.问题
就绪探针只是首次执行成功,才会到达存活探针?
那么就绪探针成功以后,再存活探针工作时间就绪探针还会工作吗
① 就绪探针用于判断容器是否已经准备好接收流量。当就绪探针首次成功后,Kubernetes 认为容器已经准备好,并开始将流量引导到该容器。然后,就绪探针会继续以指定的间隔进行探测,但其状态不会影响流量的路由。如果就绪探针失败,Kubernetes 将停止将流量引导到该容器,直到就绪探针再次成功。
② 存活探针用于判断容器是否在运行时处于健康状态。存活探针的结果会影响 Kubernetes 管理器决定是否重新启动容器。如果存活探针失败,Kubernetes 将重新启动容器。
③ 这两种探针的工作方式独立运行,就绪探针的成功与否不会直接影响存活探针的工作。存活探针的工作取决于
initialDelaySeconds
和periodSeconds
参数,与就绪探针的成功无关
12、PV和PVC
1.介绍
临时卷类型的生命周期与 Pod 相同, 但持久卷可以比 Pod 的存活期长。 当 Pod 不再存在时,Kubernetes 也会销毁临时卷;不过 Kubernetes 不会销毁持久卷
Kubernetes 存储_*_花非人陌_*的博客-CSDN博客
卷 | Kubernetes
2.实验准备工作
1.k8s01中安装nfs-server
yum install -y nfs-utils rpcbind
2.工作节点 - 安装nfs客户端
安装服务
[root@k8s01 ~]# for i in 192.168.248.2{1..2}; do ssh root@${i} "yum -y install nfs-utils"; done
设置当前启动并且下次开机时自动启动
[root@k8s01 ~]# for i in 192.168.248.2{1..2}; do ssh root@${i} "systemctl enable --now nfs-utils"; done
3.配置nfs规则及启动服务
[root@k8s01 ~]# echo "/nfsData *(rw,no_root_squash)" > /etc/exports
#NFS 服务器将 /nfsData 目录共享给所有客户端,并允许以读写(rw)方式访问,同时禁用了对 root 用户的权限缩小[root@k8s01 ~]# systemctl enable --now rpcbind
[root@k8s01 ~]# systemctl enable --now nfs
[root@k8s01 ~]# mkdir /nfsData #创建文件夹
4.测试服务
[root@k8s01 ~]# showmount -e
Export list for k8s01:
/nfsData *
3.编写YAML文件
1.编写PV的yaml文件
[root@k8s01 ~]# ls /nfsDate
ls: cannot access /nfsDate: No such file or directory
[root@k8s01 ~]# cat >> pv.yaml << EOF
apiVersion: v1
kind: PersistentVolume
metadata:name: pv01
spec:capacity:storage: 1GivolumeMode: FilesystemaccessModes:- ReadWriteManypersistentVolumeReclaimPolicy: RecyclemountOptions:- hard- nfsvers=4.1nfs:path: /nfsDataserver: 192.168.248.20
EOF
2.编写PVC的yaml文件
[root@k8s01 ~]# cat >> pvc.yaml << EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: myclaim
spec:accessModes:- ReadWriteManyvolumeMode: FilesystemvolumeName: pv01resources:requests:storage: 1Gi
EOF
查看状态pv与pvc已经绑定
[root@k8s01 ~]# k get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv01 1Gi RWX Recycle Bound default/myclaim 12m
[root@k8s01 ~]# k get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myclaim Bound pv01 1Gi RWX 12m
4.部署PV与PVC
[root@k8s01 ~]# k apply -f pv.yaml
persistentvolume/pv01 created
[root@k8s01 ~]# k apply -f pvc.yaml
persistentvolumeclaim/myclaim created
5.使用PV和PVC
1.修改nginx3.yaml文件
增加PVC内容
[root@k8s01 ~]# cat > nginx3.yaml << EOF
apiVersion: v1
kind: Pod
metadata:labels:app: nginx3name: nginx3
spec:volumes:- name: datapersistentVolumeClaim:claimName: myclaimcontainers:- image: nginx:1.21imagePullPolicy: IfNotPresentname: nginxvolumeMounts:- name: datamountPath: /usr/share/nginx/html/dnsPolicy: ClusterFirstrestartPolicy: Never
EOF
2.部署Pod
[root@k8s01 ~]# k apply -f nginx3.yaml
5.测试
1.通过url访问测试
经过验证可以正常访问之前宿主机写的内容
[root@k8s01 ~]# echo Hello_World > /nfsData/index.html
[root@k8s01 ~]# curl 10.244.235.147
Hello_World
2.通过容器内部查询
[root@k8s01 ~]# k exec -it nginx3 -- /bin/bash -c "cat /usr/share/nginx/html/index.html"
Hello_World
当将nfsData目录中内容删除时,容器内部文件也随之消失