k8s资源清单描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ApiVersion:
资源的版本,官方对每个资源规定了不同的版本,我们需要根据资源的版本进行书写。
一般情况下,资源的版本很少变动,除非在升级过程中,随着功能的增强,版本可能也会微调。

kind:
资源的类型,K8S集群中一切皆资源。

metadata:
资源的元数据信息,包括但不限于:
- 资源的名称;(常用)
- 资源所属的名称空间;(常用)
- 资源的标签;(常用)
- 资源的注解;(早期版本常用)
- 资源的创建时间;
- ...

spec:
定义了用户对Pod的期望状态。用户可以做如下操作:
- 指定节点调度;
- 指定调度的亲和性或反亲和性;
- 资源的数据是否进行持久化;
- 资源的配置文件是否需要修改;
- 资源的容器使用具体的镜像;
- 资源的限制
- 资源的认证信息
- 资源的安全信息
- ...

status:
资源实际的状态,比如调度到哪个worker节点,实际分配的IP地址,运行周期,重启次数等。
该资源一般不需要人为定义,而是有K8S集群自身维护。

pod资源及资源清单

1.POD资源

kubernetes资源对象操作

资源对象
node kubectl delete node kubectl get nodes
namespace kubectl create ns [资源名] kubectl delete ns [资源名] kubectl edit ns [资源名] kubectl get ns
pod kubectl delete pod [资源名] kubectl edit pod[资源名] kubectl get pod

查看集群节点状态

1
2
3
4
5
6
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 4d13h v1.19.3
node01 Ready <none> 4d13h v1.19.3
node02 Ready <none> 4d13h v1.19.3
node03 Ready <none> 4d13h v1.19.3

查看名称空间

1
2
3
4
5
6
7
8
[root@master ~]# kubectl get ns
NAME STATUS AGE
default Active 4d13h
kube-flannel Active 4d12h
kube-node-lease Active 4d13h
kube-public Active 4d13h
kube-system Active 4d13h
luay Active 4h17m

查看pod (默认default名称空间)

1
2
3
4
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-565785f75c-tpjmj 1/1 Running 0 6h8m
nginx-pod 1/1 Running 0 5h43m

查看pod (指定名称空间)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@master ~]# kubectl get pods -n luay
NAME READY STATUS RESTARTS AGE
busybox-pod 2/2 Running 0 3m30s


[root@master ~]# kubectl get pod -n luay -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-pod 2/2 Running 0 4m14s 10.2.2.6 node03 <none> <none>

-n 指定命名空间
-o 指定输出方式
json:输出json格式
yaml:输出yaml格式
wide:输出详细信息

2.pod的资源清单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@master01 ~]# vim nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: default
spec:
containers:
- image: nginx:alpine
imagePullPolicy: IfNotPresent
name: nginx-containers

`注释`
apiVersion: v1 # K8S资源接口
kind: Pod # 资源类型
metadata: #资源的元数据
name: nginx-pod # POD名字
namespace: default # 指定资源启动在哪个名称空间,默认default
spec: #容器相关信息
containers: #容器信息
- image: nginx:alpine #指定容器镜像
imagePullPolicy: IfNotPresent #指定镜像拉取规则
name: nginx-containers #容器名字


Always:总是拉取镜像,不管当前机器上是否有该镜像都拉取 nginx:latest
Never:从不拉取镜像,需要提前docker pull
IfNotPresent:如果镜像不存在,则拉取

pod报错及可能原因

1.ImagePullBackOff
  问题原因:
      镜像拉取失败。
  可能原因:
      1.可能是网络问题导致,检查Pod所在节点是否能够正常访问网络;
      2.镜像名称写错,也可能会导致这个错误;
      3.镜像是私有仓库,镜像无权限拉取;

2.ContainerCreating
    问题分析:
        容器正在创建阶段,等待容器创建,该过程包含拉取镜像的时间。

3.Pending
    问题分析:
        任务已经被K8S集群接受,但是未调度到指定节点。

    可能原因:
        1.当前集群不正常工作,请检查集群状态,比如CNI组件未安装;
        2.指定的调度的节点不存在时也会出现这样的问题;
        3.端口冲突,无法完成调度;
        4.所有节点都被打上污点,且pod没有配置污点容忍也会导致该状态;

4.CrashLoopBackOff
    问题分析:
        处于该状态,说明Pod内至少有一个容器正在重启。
    可能原因:
        1.可能是容器的守护进程运行命令结束导致的;

5.Completed
    问题分析:
        容器正常退出,容器没有被强制中断。

6.Running
    问题分析:
        至少有一个容器处于正常运行状态。

7.Init:1/2 
    问题分析:
        当前的Pod处于初始化容器阶段,目前已经完成一个初始化容器,正在进行第二个容器初始化。

8.PodInitializing
    问题分析:
        Pod正处于初始化阶段。

9.ErrImageNeverPull 
    问题分析:
        将镜像下载策略设置为Never,且本地也没有缓存镜像,因此启动容器失败。

10.OutOfcpu
    问题分析:
        一般情况下是由于CPU资源不足导致的。

11.OutOfmemory
    问题分析:
        一般情况下是由于内存不足无法分配导致的。

12.NodePorts
    问题分析:
        当前的worker节点的端口可能存在冲突。

13.RunContainerError
    问题分析:
        运行容器时出错,可以通过kubectl describe pods <POD_NAME>查看详细的信息。

14.ErrImagePull
    问题分析:
        拉取镜像是失败。

    可能原因:
        1.镜像名称写错了;
        2.没有访问权限;

15.Terminating
    问题分析:
        Pod的容器正在删除,此过程可能需要等待一段时间,一般情况下不会超过30s。

16.CreateContainerConfigError
    问题分析:
        运行容器出错,一般情下,是配置出错。

17.ContainerStatusUnknown
    问题分析:
        容器重启策略为Nerver,且我们测试时将工作节点的容器直接删除啦。无法获取

资源清单编写案例

基于一个pod部署wordpress

1.编写资源清单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[root@master kubernetes]# cat wordpress.yaml 
apiVersion: v1
kind: Pod
metadata:
name: wordpress-pod
spec:
# 使用宿主机网络名称空间
hostNetwork: true
containers:
- name: db
image: mysql:8.0
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ALLOW_EMPTY_PASSWORD
value: "yes"
- name: MYSQL_DATABASE
value: wp
- name: MYSQL_USER
value: wp_usre
- name: MYSQL_PASSWORD
value: '123'
- name: wp
image: wordpress:latest
imagePullPolicy: IfNotPresent
env:
- name: WORDPRESS_DB_HOST
value: "127.0.0.1"
- name: WORDPRESS_DB_NAME
value: wp
- name: WORDPRESS_DB_USER
value: wp_usre
- name: WORDPRESS_DB_PASSWORD
value: '123'

2.根据资源清单创建pod

1
2
3
[root@master kubernetes]# kubectl apply -f wordpress.yaml

`因为使用的宿主机网络名称空间,需保证80端口不被占用`

3.查看pod节点信息

1
2
3
4
5
6
7
8
[root@master kubernetes]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-565785f75c-tpjmj 1/1 Running 0 8h 10.2.2.2 node03
nginx-pod 1/1 Running 0 8h 10.2.2.3 node03
wordpress-pod 2/2 Running 0 36m 10.0.0.203 node03

#创建节点node03 ip 10.0.0.203
浏览器访问10.0.0.203

基于一个pod起wordpress,做持久化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
[root@master kubernetes]# cat wordpress.yaml 
apiVersion: v1
kind: Pod
metadata:
name: wordpress-pod
namespace: default
labels:
app: mysql
run: mysql
spec:
#如果使用下面ports,这个可以不使用宿主机网络
hostNetwork: true
volumes:
- name: mysql-data
hostPath:
path: /data/mysql
containers:
- name: db
image: mysql:8.0
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ALLOW_EMPTY_PASSWORD
value: "yes"
- name: MYSQL_DATABASE
value: wp
- name: MYSQL_USER
value: wp_usre
- name: MYSQL_PASSWORD
value: '123'
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql

- name: wp
image: wordpress:latest
imagePullPolicy: IfNotPresent
#相当于暴露端口,直接使用节点的宿主机ip访问即可·
ports:
- containerPort: 80
hostPort: 80
env:
- name: WORDPRESS_DB_HOST
value: "127.0.0.1"
- name: WORDPRESS_DB_NAME
value: wp
- name: WORDPRESS_DB_USER
value: wp_usre
- name: WORDPRESS_DB_PASSWORD
value: '123'

连接pod

1
2
3
4
5
## 连接到POD
[root@master01 kubernetes]# kubectl exec -it nginx-pod -- /bin/sh

## 当一个POD中有多个容器时,使用-c指定容器名,连接到指定的容器
[root@master01 kubernetes]# kubectl exec -it nginx-busybox -c busybox-container -- /bin/sh

pod的网络共享

1
2
3
4
5
1.POD内的容器使用Container模式共享根容器的网络
2.容器看到的网络设备信息和根容器完全相同
3.POD内的多个容器可以使用localhost进行网络通讯
4.POD内的多个容器不能绑定相同的端口
5.POD的生命周期和根容器一样,如果根容器退出了,POD就退出了

pod的文件共享

image-20241002101149735

挂载方式hostPath

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[root@master01 kubernetes]# cat mysql.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql57-pod
namespace: default
labels:
app: mysql
run: mysql
spec:
volumes:
- name: mysql-data
#宿主机挂载的目录
hostPath:
path: /data/mysql
containers:
- name: mysql57-container
image: mysql:5.7
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: '123'
- name: MYSQL_DATABASE
value: 'wordpress'
- name: MYSQL_USER
value: 'wp_user'
- name: MYSQL_PASSWORD
value: '123'
#传递命令指定字符集
args:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumeMounts:
#name要和上面挂载目录的name一致,mountPath是容器内的要挂载的目录
- name: mysql-data
mountPath: /var/lib/mysql

hostPath的type类型

hostPath:
path: string
type : string

type 为空时为默认类型

官方:https://kubernetes.io/docs/concepts/storage/volumes/#hostpath

type类型 说明
“” 为空时 默认
DirectoryOrCreate 目录必须存在,权限必须是755
Directory 目录必须存在
FileOrCreate 文件必须存在,权限必须是644
File 文件必须存在
Socket 挂载socket文件
CharDevice 挂载字符设备文件(键盘,终端…)
BlockDevice 挂载快设备文件(磁盘,U盘,移动硬盘…)

挂载方式emptyDir

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
## 将pod内容器目录映射到宿主机上的一个临时目录中,如果POD结束,目录也会被删除
[root@master01 kubernetes]# cat mysql.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql57-pod
namespace: default
labels:
app: mysql
run: mysql
spec:
volumes:
- name: mysql-data
hostPath:
path: /data/mysql
- name: empty-data
emptyDir: {}
containers:
- name: mysql57-container
image: mysql:5.7
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: '123'
- name: MYSQL_DATABASE
value: 'wordpress'
- name: MYSQL_USER
value: 'wp_user'
- name: MYSQL_PASSWORD
value: '123'
args:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumeMounts:
- name: empty-data
mountPath: /var/lib/mysql


## 将一个POD内的两个容器共享目录
[root@master01 kubernetes]# cat busybox.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-busybox
namespace: default
spec:
volumes:
- name: empty-data
emptyDir: {}
containers:
- name: nginx-container
image: nginx:alpine
imagePullPolicy: IfNotPresent
volumeMounts:
- name: empty-data
mountPath: /usr/share/nginx/html
- name: c7-container
image: centos:7
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","tail -f /etc/hosts"]
volumeMounts:
- name: empty-data
mountPath: /opt/ html

标签的使用及设置

node节点打标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
kubectl get [资源] -n 名称空间 --show-labels
## 查看node标签
[root@master01 ~]# kubectl get nodes --show-labels

#给node打标签
[root@master01 ~]# kubectl label node node01 MEM=16g

#查看node角色标签role
[root@master kubernetes]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 5d15h v1.19.3
node01 Ready None 5d15h v1.19.3
node02 Ready None 5d15h v1.19.3
node03 Ready None 5d15h v1.19.3

#给node角色标签role
[root@master kubernetes]# kubectl label node node01 node-role.kubernetes.io/node=
[root@master kubernetes]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 5d15h v1.19.3
node01 Ready node 5d15h v1.19.3
node02 Ready None 5d15h v1.19.3
node03 Ready None 5d15h v1.19.3

kubectl label node node01 node-role.kubernetes.io/node=
节点名 调用接口 /roles标签名=

#删除node角色标签role
[root@master kubernetes]# kubectl label node node01 node-role.kubernetes.io/node-

给pod打标签

给pod打标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#查看pod标签
[root@master kubernetes]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-565785f75c-tpjmj 1/1 Running 2 33h app=nginx
nginx-pod 1/1 Running 2 33h <none>
wordpress-pod 2/2 Running 0 2m11s <none>

#打标签
kubectl label 资源类型 资源名 标签
[root@master kubernetes]# kubectl label pod nginx-pod name=nginx
'pod/nginx-pod labeled
[root@master kubernetes]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-565785f75c-tpjmj 1/1 Running 2 33h app=nginx
nginx-pod 1/1 Running 2 33h name=nginx

使用资源清单打标签

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
Kind: Pod
metadata:
name: nginx-pod
namespace: default
labels:
run: nginx
spec:
containers:
- name: nginx-container
image: nginx:alpine
imagePullPolicy: IfNotPresent

利用标签,启动pod在指定标签的node上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@master01 kubernetes]# cat nginx-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-v2
namespace: default
labels:
run: nginx
spec:
#这里是选择起在标签是MEM: 16g的node节点上,使用kubectl get nodes --show-labels 查看node标签
nodeSelector:
MEM: 16g
containers:
- name: nginx-container-v2
image: nginx:alpine
imagePullPolicy: IfNotPresent

删除pod标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
kubectl label [资源] [资源名] [标签名、标签key]-
#查看当前pod有的标签
[root@master kubernetes]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-565785f75c-tpjmj 1/1 Running 2 35h app=nginx,pod-template-hash=565785f75c
nginx-pod 1/1 Running 2 34h name=nginx
wordpress-pod 2/2 Running 0 39m <none>

#删除pod标签
[root@master kubernetes]# kubectl label pod nginx-pod name-
pod/nginx-pod labeled

#查看
[root@master kubernetes]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-565785f75c-tpjmj 1/1 Running 2 35h app=nginx,pod-template-hash=565785f75c
nginx-pod 1/1 Running 2 34h <none>
wordpress-pod 2/2 Running 0 39m <none>

根据标签查找pod

1
2
3
4
5
[root@master kubernetes]# kubectl get pod --show-labels -l app
NAME READY STATUS RESTARTS AGE LABELS
nginx-565785f75c-tpjmj 1/1 Running 2 35h app=nginx,pod-template-hash=565785f75c

#使用 `-l` 查找指定的pod

根据标签删除pod

1
[root@master kubernetes]# kubectl delete pod -l app=nginx

kubectl用于排错命令

describe

kubectl describe pod

查看相关 Pod 的详细信息,帮助我们了解 Pod 的状态、配置和运行状况。尤其是Events可以帮助我们做一些故障排查。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@master ~]# kubectl describe pod busybox-pod -n luay
#如果查看的pod的名称空间不是默认default,则需要指定 -n
···
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 18m default-scheduler Successfully assigned luay/busybox-pod to node03
Normal Pulled 18m kubelet Container image "busybox" already present on machine
Normal Created 18m kubelet Created container busybox-container
Normal Started 18m kubelet Started container busybox-container
Normal Pulled 18m kubelet Container image "nginx:alpine" already present on machine
Normal Created 18m kubelet Created container nginx-container
Normal Started 18m kubelet Started container nginx-container

#查看node节点信息
[root@master ~]# kubectl describe node master01

logs

kubectl logs 资源名 可以使用kubectl get pod 查看资源名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
'kubectl logs 资源名称'
[root@master ~]# kubectl logs mysql80

#实时查看日志
[root@master ~]# kubectl logs -f mysql80

#基于一个Pod内多个容器查看指的容器的日志 -c 指定容器名
[root@master ~]# kubectl logs -f multiple-wordpress -c db

'multiple-wordpress' pod名
-c 指定pod里的某一个容器名

#查看pod上一个容器的日志(前提是该容器存在,若移除了则看不到)
'这种情况存在于,杀掉了pod里某个容器,又被kubelet重新拉取了另一个新的容器,-p查看上个容器日志'
[root@master ~]# kubectl logs -f mysql80 -p
'mysql80' 容器名 ----待验证


#查看5分钟内的日志信息, 默认是查看所有日志,可以自定义指定时间,例如: 5s, 2m, or 3h.
[root@master ~]# kubectl logs -f mysql80 --since 5m

cp

将本地的文件拷贝到Pod的容器中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@master ~]# kubectl cp wordpress.yaml mysql80:/tmp

如何查看?
[root@master ~]# kubectl exec -it mysql80 --ls /tmp
类似于docker exec


#如果有多个容器,则需要使用-c指定
kubectl cp wordpress.yaml -c wp multiple-wordpress:/

'multiple-wordpress' #pod名 ---待验证
'wp' #容器名

如果有多个容器,则需要使用-c指定容器的名称,若不指定,则默认Pod连接第一个容器

explain

查看指定字段的帮助信息

1
2
3
4
[root@master ~]# kubectl explain pods.
[root@master ~]# kubectl explain pods.metadata
[root@master ~]# kubectl explain pods.metadata.name
[root@master ~]# kubectl explain pods.spec.containers

常见的资源类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<string>:
表示一个字符串。

<Object>:
表示有下级字段。

<[]Object>:
表示数组对象说可以有多个,每个对象的区分使用"-",同一个对象数组内的相关字段可以相互交换。

<boolean>:
只有truefalse两个有效值。

<integer>:
整型,表示的是一个整数。

-required-
表示该字段必须定义,不定义则会报错。