文章目录
资源清单文件
资源清单文件
- 资源清单文件详解
- k8s对象是"目标性记录"
- k8s使用资源清单文件描述期望达到的状态
- 命名规范
- 当你与指定的API对象进行交互时,使用大写驼峰式命名法,也被称为帕斯卡拼写法
- 不要将API对象的名称切分成多个单词
- key使用小驼峰,第一个字母不大写,value使用大驼峰,首字母都大写
正确写法 | 错误写法 |
---|---|
type: NodePort | type: nodePort |
nodePort: 30001 | NodePort: 30001 |
- 键值对嵌套
- 数据格式:{"metadata":{"name" :"mypod"}}
- 数组嵌套
- 数据格式:
bash
{ "ports":
[ {"name":"xx","Port":80},{"name":"hh","Port":443}
}
静态Pod
- 什么是静态Pod
- 静态Pod是由kubelet守护进程直接管理的Pod,不需要API 服务器监管,与由监控面管理的Pod不同
- kubelet监视每个静态Pod(在它崩溃之后重新启动)
- 静态Pod永远都会绑定到一个指定节点上的Kubelet
- 静态Pod的spec不能引用其他API对象
- 静态Pod配置路径/var/lib/kubelet/config.yaml
staticPodPath: /etc/kubernetes/manifests
- 创建静态Pod
bash
[root@node-0003 ~] vim /etc/kubernetes/manifests/myweb.yaml #在节点编写资源清单文件
---
kind: Pod
apiVersion: v1
metabata:
name: myweb
spec:
containers:
- name: httpd
image: myos:httpd
#在master查看
[root@master ~] kubectl get pods -o wide
- 删除静态Pod
bash
[root@master ~] kubectl delete pod myweb-node-0003
pod "myweb-node-0003" deleted #虽然提示已删除,但是节点上会自动重建Pod
[root@master ~] kubectl get pods -o wide
[root@node-0003 ~] rm -rf /etc/kubernetes/manifests/myweb.yaml #删除清单文件才能彻底删除Pod
[root@master ~] kubectl get pods
模板与帮助信息
- 资源清单文件优势
- 方便管理、保存、追随历史
- 可以实现命令无法完成的高级功能
- 如何获取资源清单文件
- 资源清单文件需要用户根据具体需求编写
- 技巧1:使用命令创建模板
- 技巧2:使用AI编写资源清单文件
- 技巧3:查询官方手册
- 生成资源清单文件模板
- 除Pod外,其他资源对象模板使用create生成
- 生成模板命令:--dry-run=client -o yaml
bash
# 获取资源对象模板
[root@master ~] kubectl create namespace work --dry-run=client -o yaml
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: null
name: work
spec: {}
status: {}
- 资源文件参数如何查询?
- 使用"."分隔层数结构关系
bash
# kind: 一级,可以表示为.kind
kind: xxx
# apiVersion: 一级,可以表示为.apiVersion
apiVersion: xx
metadata:
# name: 二级,可以表示为.metadata.name
name: xx
spec:
# restartPolicy: 二级,可以表示为.spec.restartPolicy
restartPolicy: xx
containers:
# - name: 三级,可以表示为.spec.containers.name
- name: xx
# image: 三级,可以表示为.spec.containers.image
image: xx
# status: 一级,可以表示为.status
status: {}
- 如何获取帮助信息?
- 执行explain资源对象+层级关系
bash
# 查询帮助信息
[root@master ~] kubectl explain Pod.metadata
KIND: Pod
VERSION: v1
FIELD: metadata <ObjectMeta> ... ...
namespace <string>
Namespace defines the space within which each name must be unique. An empty
namespace is equivalent to the "default" namespace, but "default" is the
canonical representation. Not all objects are required to be scoped to a
namespace - the value of this field for those objects will be empty.
[root@master ~] kubectl explain Pod.metadata.namespace
KIND: Pod
VERSION: v1
FIELD: namespace <string>
DESCRIPTION:
Namespace defines the space within which each name must be unique. An empty
namespace is equivalent to the "default" namespace, but "default" is the
canonical representation. Not all objects are required to be scoped to a
namespace - the value of this field for those objects will be empty.
Must be a DNS_LABEL. Cannot be updated. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces
- 管理资源清单文件
bash
#创建多个资源清单文件
[root@master ~] mkdir app
[root@master ~] sed "s/myweb,web1," myweb.yml >app/web1.yml
[root@master ~] sed "s/myweb,web2," myweb.yml >app/web2.yml
[root@master ~] sed "s/myweb,web3," myweb.yml >app/web3.yml
[root@master ~] tree app/
app/
├── web1.yml
├── web2.yml
└── web3.yml
# 创建应用
[root@master ~] kubectl apply -f app/web1.yml -f app/web2.yml
pod/web1 created
pod/web2 created
# 执行目录下所有资源清单文件
[root@master ~] kubectl apply -f app/
pod/web1 unchanged
pod/web2 unchanged
pod/web3 created
- 合并资源清单文件
- 多个资源清单文件可以使用 --- 做为分隔符号,合并管理
bash
# 删除资源对象
[root@master ~] kubectl delete -f app/
pod "web1" deleted
pod "web2" deleted
pod "web3" deleted
# 合并管理资源清单文件
[root@master ~] cat app/* >app.yml
[root@master ~] kubectl apply -f app.yml
pod/web1 created
pod/web2 created
pod/web3 created
多容器Pod
- 多容器Pod
- Pod中文翻译就是豌豆荚,在计算机里Pod和豌豆荚一样,一个壳子包含着一个或多个容器(豌豆)
- Pod是一个服务的多个进程的聚合单位
- 同一个Pod共享主机名称、共享网络IP及权限、共享存储设备
- 创建多容器Pod
bash
[root@master ~] vim mynginx.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: mynginx
namespace: default
spec:
containers:
- name: nginx
image: myos:nginx
- name: php
image: myos:php-fpm
[root@master ~] kubectl apply -f mynginx.yaml
pod/mynginx created
[root@master ~] kubectl get pods
NAME READY STATUS RESTARTS AGE
mynginx 2/2 Running 0 3s
- 管理多容器Pod
受到多容器影响的命令:「"logs","exec","cp"」
bash
# 查看日志
[root@master ~] kubectl logs mynginx -c nginx
[root@master ~] kubectl logs mynginx -c php
[06-Mar-2024 12:56:18] NOTICE: [pool www] 'user' directive is ignored when FPM is not running as root
[06-Mar-2024 12:56:18] NOTICE: [pool www] 'group' directive is ignored when FPM is not running as root
# 执行命令
[root@master ~] kubectl exec -it mynginx -c nginx -- pstree -p
nginx(1)-+-nginx(7)
`-nginx(8)
[root@master ~] kubectl exec -it mynginx -c php -- pstree -p
php-fpm(1)
# 拷贝文件
[root@master ~] kubectl cp mynginx:/etc/php-fpm.conf /root/php.conf -c nginx
tar: Removing leading `/' from member names
tar: /etc/php-fpm.conf: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors
[root@master ~] kubectl cp mynginx:/etc/php-fpm.conf /root/php.conf -c php
tar: Removing leading `/' from member names
自定义任务
- Pod自定义命令
- 创建Pod时,可以为其设置启动时要执行的自定义命令,如果配置了自定义命令,那么镜像中自带的默认启动命令将被覆盖
- 自定义命令设置在command字段下,如果命令有参数,需要填写在args字段下
- Pod自定义命令样例
bash
root@master ~] vim mycmd.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: mycmd
spec:
containers:
- name: linux
image: myos:httpd
command: ["sleep"] # 配置自定义命令
args: # 设置命令参数
- "30"
[root@master ~] kubectl apply -f mycmd.yaml
pod/mycmd created
[root@master ~] kubectl get pods -w
NAME READY STATUS RESTARTS AGE
mycmd 1/1 Running 0 4s
mycmd 0/1 Completed 0 31s
mycmd 1/1 Running 1 (2s ago) 32s
- restartPolicy策略
- Pod会根据策略决定容器结束后是否重启
bash
[root@master ~] vim mycmd.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: mycmd
spec:
restartPolicy: OnFailure # 配置重启策略退出状态码不为0则自动重启
containers:
- name: linux
image: myos:httpd
command: ["sleep"]
args:
- "30"
[root@master ~] kubectl replace --force -f mycmd.yaml
pod "mycmd" deleted
pod/mycmd replaced
[root@master ~] kubectl get pods -w #-w实时查看Pod状态
NAME READY STATUS RESTARTS AGE
mycmd 1/1 Running 0 4s
mycmd 0/1 Completed 0 31s
- terminationGracePeriodSeconds策略
- 宽限期是为了避免服务突然中断,造成的事物不一致的问题,宽限期默认设置为30s
bash
[root@master ~] vim mycmd.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: mycmd
spec:
terminationGracePeriodSeconds: 0 # 设置宽限期
restartPolicy: OnFailure
containers:
- name: linux
image: myos:httpd
command: ["sleep"]
args:
- "30"
[root@master ~] kubectl delete pods mycmd
pod "mycmd" deleted
[root@master ~] kubectl apply -f mycmd.yaml
pod/mycmd created
[root@master ~] kubectl delete pods mycmd
pod "mycmd" deleted
- 如何执行复杂命令?
bash
[root@master ~] vim mycmd.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: mycmd
spec:
terminationGracePeriodSeconds: 0
restartPolicy: OnFailure
containers:
- name: linux
image: myos:8.5
command: ["sh"]
args:
- -c
- |
for i in {0..9};do
echo hello world.
sleep 3.3
done
exit 0
[root@master ~] kubectl replace --force -f mycmd.yaml
pod "mycmd" deleted
pod/mycmd replaced
[root@master ~] kubectl logs mycmd #通过logs查看脚本执行结果
hello world.
hello world.
hello world.
- 循环死锁
- 如果一个Pod的内部程序在运行的时候出现循环死锁,那么就会永远不停的重复执行,如何避免这种情况发生?
- acticveDeadlineSeconds策略
当为Pod设置了此参数后,从Pod启动开始计时,一旦达到这个时间限制:
- 首先,Kubernetes会向Pod内的主进程发送一个终止信号(通常是SIGTERM信号)
- 然后,Pod在默认的宽先期限(terminationGracePeriodSeconds参数)下处理正在完成的任务和保存数据等并进行优雅的关闭,如果在这个时间内没有处理完成那么kubernetes会强制关闭Pod,并设置其状态为Error
- 若是terminationGracePeriodSeconds参数设置为0那么Pod会在activeDeadlineSeconds参数设置的时间一到的瞬间关闭,也会设置其状态为Error
bash
[root@master ~] vim mycmd.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: mycmd
spec:
terminationGracePeriodSeconds: 0
activeDeadlineSeconds: 60 # 可以执行的最大时长
restartPolicy: OnFailure
containers:
- name: linux
image: myos:8.5
command: ["sh"]
args:
- -c
- |
for i in {0..9};do
echo hello world.
sleep 33
done
exit 0
[root@master ~] kubectl replace --force -f mycmd.yaml
pod "mycmd" deleted
pod/mycmd replaced
[root@master ~] kubectl get pods -w
mycmd 1/1 Running 0 1s
mycmd 1/1 Running 0 60s
mycmd 0/1 Error 0 62s
自定义Pod脚本
创建一个 Pod,完成以下功能
- 该 Pod 每隔 5 秒获取一次当前系统内存使用情况
- 如果内存使用量小于 1000Mi 就输出:INFO: running normally
- 如果内存使用量大于 1000Mi 就输出:WARN: high memory usage
bash
---
kind: Pod
apiVersion: v1
metadata:
name: mymem
spec:
restartPolicy: OnFailure
containers:
- name: linux
image: myos:8.5
command: ["sh"]
args:
- -c
- |
while sleep 5;do
use=$(free -m |awk '$1=="Mem:"{print $3}')
if (( ${use} < 1000 ));then
echo -e "\x1b[32mINFO:\x1b[39m running normally"
else
echo -e "\x1b[31mWARN:\x1b[39m high memory usage"
fi
done
Pod调度策略管理
Pod调度策略
调度策略概述
- 什么是调度分配?
- 在k8s中,调度是将Pod分配道合适的计算节点上,然后对应节点上的kubelet运行这些Pod
- kube-scheduler是默认调度器,是集群的核心组件
- 调度器是如何工作的?
- 调度器通过k8s的监测(Watch)机制来发现集群中尚未被调度到节点上的Pod。调度器依据调度原则将Pod分配道一个合适的节点上运行
调度流程概述
- 调度流程
- 调度器给一个Pod做调度选择包含两个步骤:过滤和打分
- 第一步过滤(筛选)
- 首先要筛选出满座Pod所有的资源请求节点,这里包含计算资源、内存、存储、网络、端口号等等,如果没有节点能满足Pod需求,Pod将一直停留在Pending状态,直到调度器能够找到合适的节点运行它
- 第二步打分(优选)
- 在打分阶段,调度器会根据打分规则,为每一个可调度节点进行打分。选出其中得分最高的节点来运行Pod。如果存在多个得分最高的节点,调度器会从中随机选取一个。
- 绑定
- 在确定了某一个节点运行Pod之后,调度器将这个调度决定通知给kube-apiserver,这个过程叫做绑定
定向调度
- 基于节点名称的调度
- 在创建Pod的过程中,我们可以配置相关的调度规则,从而让Pod运行在制定的节点上
- nodeName标签,让Pod运行在指定的节点上
- 测试验证
- 注意:如果标签指定的节点无法运行Pod,它不会迁移到其他节点,将会一直等待下去
bash
[root@master ~] vim myhttp.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: myhttp
spec:
nodeName: node-0001 # 基于节点名称进行调度
containers:
- name: apache
image: myos:httpd
[root@master ~] kubectl apply -f myhttp.yaml
pod/myhttp created
[root@master ~] kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
myhttp 1/1 Running 0 3s 10.244.1.6 node-0001
标签与Pod调度
标签管理
- 标签是什么?
- 标签(Labels)是附加到Kubernetes对象上的键值对
- 标签的用途
- k8s在创建、删除、修改资源对象的时候可以使用标签来确定要修改的资源对象。在Pod调度的任务中,使用标签可以更加灵活的完成调度任务
- 标签可以在创建时附加到对象,也可以在创建之后随时添加和修改。标签可以用于组织和选择对象的子集
- 管理标签的语法格式
- 设置标签
kubectl label 资源类型「资源名称」key=value - 删除标签
kubectl label 资源类型 「资源名称」key- - 查看标签
kubectl get 资源类型 「资源名称」-l key=value
- 使用label命令管理标签
bash
# 查看标签
[root@master ~] kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myhttp 1/1 Running 0 2m34s <none>
# 添加标签
[root@master ~] kubectl label pod myhttp app=apache
pod/myhttp labeled
[root@master ~] kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myhttp 1/1 Running 0 14m app=apache
# 删除标签
[root@master ~] kubectl label pod myhttp app-
pod/myhttp unlabeled
[root@master ~] kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myhttp 1/1 Running 0 14m <none>
# 资源清单文件配置标签
[root@master ~] vim myhttp.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: myhttp
labels:
app: apache
spec:
containers:
- name: apache
image: myos:httpd
[root@master ~] kubectl replace --force -f myhttp.yaml
pod "myhttp" deleted
pod/myhttp replaced
[root@master ~] kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myhttp 1/1 Running 0 7s app=apache
# 使用标签过滤资源对象
[root@master ~] kubectl get pods -l app=apache
NAME READY STATUS RESTARTS AGE
myhttp 1/1 Running 0 6m44s
[root@master ~] kubectl get nodes -l kubernetes.io/hostname=master
NAME STATUS ROLES AGE VERSION
master Ready control-plane 5d6h v1.29.2
[root@master ~] kubectl get namespaces -l kubernetes.io/metadata.name=default
NAME STATUS AGE
default Active 5d6h
Pod标签调度
- 标签选择运算符
- 与名称和UID不同,标签不支持唯一性。通常,我们希望许多对象携带相同的标签
- 通过标签选择运算符,客户端/用户可以识别一组对象
- 标签选择运算符可以由多个需求组成,在多个需求的情况下,必须满足所有要求,相当于逻辑与(&&)运算符
- 基于标签调度
bash
# 查询 node 节点上的标签
[root@master ~] kubectl get nodes --show-labels
NAME STATUS ROLES VERSION LABELS
master Ready control-plane v1.29.2 kubernetes.io/hostname=master
node-0001 Ready <none> v1.29.2 kubernetes.io/hostname=node-0001
node-0002 Ready <none> v1.29.2 kubernetes.io/hostname=node-0002
node-0003 Ready <none> v1.29.2 kubernetes.io/hostname=node-0003
node-0004 Ready <none> v1.29.2 kubernetes.io/hostname=node-0004
node-0005 Ready <none> v1.29.2 kubernetes.io/hostname=node-0005
# 使用 node 上的标签调度 Pod
[root@master ~] vim myhttp.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: myhttp
labels:
app: apache
spec:
nodeSelector:
kubernetes.io/hostname: node-0002
containers:
- name: apache
image: myos:httpd
[root@master ~] kubectl replace --force -f myhttp.yaml
pod "myhttp" deleted
pod/myhttp replaced
[root@master ~] kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
myhttp 1/1 Running 0 1s 10.244.2.11 node-0002
- 标签调度实验案例
- 已只节点中node-0002和node-0003使用的是ssd硬盘
- 把Pod调度到有ssd硬盘的节点上
- 做一个批量创建pod验证一下
bash
[root@master ~] kubectl label node node-0003 disk=ssd
node/node-0003 labeled
[root@master ~] kubectl label node node-0002 disk=ssd
node/node-0002 labeled
[root@master ~] vim mylabel.yml
---
kind: Pod
apiVersion: v1
metadata:
name: mynode
labels:
app: apache
spec:
nodeSelector:
disk: ssd
containers:
- name: node
image: myos:httpd
[root@master ~] for i in {1..9};do sed "s/mynode/mynode$i/" mylabel.yml | kubectl create -f -;done
pod/mynode1 created
pod/mynode2 created
pod/mynode3 created
pod/mynode4 created
pod/mynode5 created
pod/mynode6 created
pod/mynode7 created
pod/mynode8 created
pod/mynode9 created
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mynode 1/1 Running 0 14m 10.244.243.198 node-0003 <none> <none>
mynode1 1/1 Running 0 118s 10.244.147.4 node-0002 <none> <none>
mynode2 1/1 Running 0 118s 10.244.243.199 node-0003 <none> <none>
mynode3 1/1 Running 0 118s 10.244.147.5 node-0002 <none> <none>
mynode4 1/1 Running 0 118s 10.244.243.200 node-0003 <none> <none>
mynode5 1/1 Running 0 117s 10.244.147.6 node-0002 <none> <none>
mynode6 1/1 Running 0 117s 10.244.243.201 node-0003 <none> <none>
mynode7 1/1 Running 0 117s 10.244.147.7 node-0002 <none> <none>
mynode8 1/1 Running 0 117s 10.244.243.202 node-0003 <none> <none>
mynode9 1/1 Running 0 117s 10.244.147.8 node-0002 <none> <none>