12 K8S Pod 合理管理容器


通过 Pod 合理管理容器

准备工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 容器准备 
[root@k8s-master2 src]# cat app.js

const http = require ('http');
const os = require ('os');
console.log("Kubia server starting...");

var handler = function(request,response){
console.log("Received request from" + request.connection.remoteAddress);
response.writeHead(200);
response.end("You've hit " + os.hostname() + "\n");
};

var www = http.createServer(handler);
www.listen(8080);
1
2
3
4
[root@k8s-master2 src]# cat Dockerfile 
FROM node:7
ADD app.js /app.js
ENTRYPOINT ["node","app.js"]
1
2
3
4
5
6
7
8
# 上传到镜像仓库
docker build -t kubia .
docker images
docker run --name kubia-container -p 8080:8080 -d kubia
docker login 172.31.228.68
docker tag kubia 172.31.228.68/project/kubia
docker images
docker push 172.31.228.68/project/kubia

kubectl run 命令创建资源

1
2
3
4
# run 命令 可以创建所有必要的组件 无需yaml文件 
[root@k8s-master1 ~]# kubectl run kubia --image=172.31.228.68/project/kubia --port=8080 --generator=run/v1
kubectl run --generator=run/v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
replicationcontroller/kubia created
1
2
3
4
5
6
7
8
9
10
11
# 查看 replicationcontroller 
[root@k8s-master1 ~]# kubectl get replicationcontrollers
NAME DESIRED CURRENT READY AGE
kubia 1 1 1 7m46s

[root@k8s-master1 ~]# kubectl get rc
NAME DESIRED CURRENT READY AGE
kubia 1 1 1 7m50s

DESIRED: 希望保持的pod副本数
CURRENT: 当前运行的pod副本数
1
2
3
4
5
6
7
# 增加期望的副本数 
[root@k8s-master1 ~]# kubectl scale rc kubia --replicas=3
replicationcontroller/kubia scaled

[root@k8s-master1 ~]# kubectl get rc
NAME DESIRED CURRENT READY AGE
kubia 3 3 3 11m
1
2
3
# 一步增加副本数
[root@k8s-master1 ~]# kubectl delete rc kubia
[root@k8s-master1 ~]# kubectl run kubia --image=172.31.228.68/project/kubia --port=8080 --generator=run/v1 --replicas=3

导出现有 pod 的 yaml 描述文件

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# 参考: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/ 
# 导出一个正在运行的Pod

[root@k8s-master1 demo]# kubectl get pod kubia-manual -o yaml
apiVersion: v1 # k8s api 版本
kind: Pod # k8s 对象 资源类型

# POD 元数据 (名称、标签、注解)
metadata:
creationTimestamp: "2020-03-10T23:59:10Z"
labels:
env: prod
team: A
name: kubia-manual
namespace: default
resourceVersion: "28257"
selfLink: /api/v1/namespaces/default/pods/kubia-manual
uid: f56b37e8-70d7-47c4-9299-a8841f574205

# POD 规格 | 内容 (POD的容器列表、volume等)
spec:
containers:
- image: 172.31.228.68/project/kubia
imagePullPolicy: Always
name: kubia
ports:
- containerPort: 8080
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-r29ch
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: k8s-master1
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: default-token-r29ch
secret:
defaultMode: 420
secretName: default-token-r29ch

# POD 内部容器的详细状态
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2020-03-10T23:59:10Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2020-03-10T23:59:12Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2020-03-10T23:59:12Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2020-03-10T23:59:10Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://b210eb2b042f79873db515d39c87081277fed8529754c0cae82cd69984ff51a9
image: 172.31.228.68/project/kubia:latest
imageID: docker-pullable://172.31.228.68/project/kubia@sha256:6b5f96aa6c2376e394301b83c57c551c84ae800415a53f668f6042bd1b76fcea
lastState: {}
name: kubia
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2020-03-10T23:59:11Z"
hostIP: 172.31.228.67
phase: Running
podIP: 10.244.2.11
podIPs:
- ip: 10.244.2.11
qosClass: BestEffort
startTime: "2020-03-10T23:59:10Z"

创建一个简单的yaml描述文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@k8s-master1 demo]# vim kubia-manual.yaml
# k8s api 版本
apiVersion: v1
# 资源对象
kind: Pod
# 元数据 pod名称
metadata:
name: kubia-manual
# POD 内容
spec:
containers
# 容器使用的镜像
- image: 172.31.228.68/project/kubia
# 容器名称
name: kubia
ports:
# 监听端口
- containerPort: 8080
protocol: TCP
1
2
3
# kubectl explain 查看支持的api对象
[root@k8s-master1 demo]# kubectl explain pod
[root@k8s-master1 demo]# kubectl explain pod.spec

使用 kubectl create 来创建 pod

1
2
3
4
5
# kubectl create -f 命令用于从YAML或者JSON文件创建任何资源(不只是POD)

[root@k8s-master1 demo]# kubectl create -f kubia-manual.yaml
pod/kubia-manual created
[root@k8s-master1 demo]# kubectl get pod -o wide
1
2
3
# kubectl logs 查看应用程序日志
[root@k8s-master1 demo]# kubectl logs kubia-manual
Kubia server starting...
1
2
# 获取多容器pod的日志 -c 指定容器名称
[root@k8s-master1 demo]# kubectl logs kubia-manual -c kubia

使用标签组织 pod

1
2
3
4
5
# 常用的标签
app: 指向应用
rel: 指向版本 stable beta canary(金丝雀)
team: 指向组 TeamA TeamB
env: 指向环境 test prod dev
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@k8s-master1 demo]# vim kubia-manual-with-labels.yaml

apiVersion: v1
kind: Pod
metadata:
name: kubia-manual-v2
labels:
team: A
env: prod
spec:
containers:
- image: 172.31.228.68/project/kubia
name: kubia
ports:
- containerPort: 8080
protocol: TCP

[root@k8s-master1 demo]# kubectl create -f kubia-manual-with-labels.yaml
1
2
3
4
5
# 查看 pod 并列出所有标签
[root@k8s-master1 demo]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
kubia-manual 1/1 Running 0 33m env=prod,team=A
kubia-manual-v2 1/1 Running 0 22m env=prod,team=A
1
2
3
4
5
# 根据标签名列出 pod 
[root@k8s-master1 demo]# kubectl get pod -L env
NAME READY STATUS RESTARTS AGE ENV
kubia-manual 1/1 Running 0 33m prod
kubia-manual-v2 1/1 Running 0 23m prod
1
2
3
4
5
6
7
8
# 修改pod的标签
[root@k8s-master1 demo]# kubectl label pod kubia-manual-v2 env=debug --overwrite
pod/kubia-manual-v2 labeled

[root@k8s-master1 demo]# kubectl get pod -L env
NAME READY STATUS RESTARTS AGE ENV
kubia-manual 1/1 Running 0 58m prod
kubia-manual-v2 1/1 Running 0 48m debug
1
2
3
4
5
6
7
8
9
10
11
12
13
# 给pod添加一个新标签
[root@k8s-master1 demo]# kubectl label pod kubia-manual app=os
pod/kubia-manual labeled

[root@k8s-master1 demo]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
kubia-manual 1/1 Running 0 60m app=os,env=prod,team=A
kubia-manual-v2 1/1 Running 0 49m env=debug,team=A

[root@k8s-master1 demo]# kubectl get pod -L app
NAME READY STATUS RESTARTS AGE APP
kubia-manual 1/1 Running 0 60m os
kubia-manual-v2 1/1 Running 0 50m

通过标签选择器列出pod子集

1
2
3
4
# 标签选择器条件:
1. 包含或不包含
2. 包含具有指定的键和值的标签
3. 包含具有指定键的标签,值不指定
1
2
3
4
5
# 列出所有Team=A组的标签的pod
[root@k8s-master1 demo]# kubectl get pod -l team=A
NAME READY STATUS RESTARTS AGE
kubia-manual 1/1 Running 0 64m
kubia-manual-v2 1/1 Running 0 53m
1
2
3
4
# 列出所有 有env 标签的app
[root@k8s-master1 demo]# kubectl get pod -l app
NAME READY STATUS RESTARTS AGE
kubia-manual 1/1 Running 0 65m
1
2
3
4
# 列出 没有app 标签的pod
[root@k8s-master1 demo]# kubectl get pod -l '!app'
NAME READY STATUS RESTARTS AGE
kubia-manual-v2 1/1 Running 0 55m

标签选择器匹配

1
2
3
4
5
6
7
8
9
10
11
# 反向条件选择 
[root@k8s-master1 demo]# kubectl label pod kubia-manual team=B --overwrite

[root@k8s-master1 demo]# kubectl get pod -L team
NAME READY STATUS RESTARTS AGE TEAM
kubia-manual 1/1 Running 0 70m B
kubia-manual-v2 1/1 Running 0 59m A

[root@k8s-master1 demo]# kubectl get pod -l 'team!=A'
NAME READY STATUS RESTARTS AGE
kubia-manual 1/1 Running 0 70m
1
2
3
4
5
6
7
8
9
10
# in 或
[root@k8s-master1 demo]# kubectl get pod -L env
NAME READY STATUS RESTARTS AGE ENV
kubia-manual 1/1 Running 0 72m prod
kubia-manual-v2 1/1 Running 0 61m debug

[root@k8s-master1 demo]# kubectl get pod -l 'env in (prod,debug)'
NAME READY STATUS RESTARTS AGE
kubia-manual 1/1 Running 0 71m
kubia-manual-v2 1/1 Running 0 61m
1
2
3
4
# not in 
[root@k8s-master1 demo]# kubectl get pod -l 'env notin (prod)' -L env
NAME READY STATUS RESTARTS AGE ENV
kubia-manual-v2 1/1 Running 0 63m debug

多条件标签选择器

1
2
3
4
# ,分割条件
[root@k8s-master1 demo]# kubectl get pod -l team=B,app=os
NAME READY STATUS RESTARTS AGE
kubia-manual 1/1 Running 0 79m

使用标签选择器来约束pod调度

1
2
3
4
# 解决pod随机调度到工作节点
# 根据基建基础,比如机械硬盘或者固态硬盘 将一组pod调度到ssd硬盘的工作节点
# 又或者是GPU节点
# 给node加上标签,然后在使用标签选择器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@k8s-master1 demo]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master1 Ready <none> 40h v1.16.0
k8s-node1 Ready <none> 40h v1.16.0
k8s-node2 Ready <none> 40h v1.16.0

# 比如node2 是 gpu计算节点
[root@k8s-master1 demo]# kubectl label node k8s-node2 gpu=true
node/k8s-node2 labeled

# 列出gpu node节点
[root@k8s-master1 demo]# kubectl get node -l gpu=true
NAME STATUS ROLES AGE VERSION
k8s-node2 Ready <none> 40h v1.16.0

[root@k8s-master1 demo]# kubectl get node -L gpu
NAME STATUS ROLES AGE VERSION GPU
k8s-master1 Ready <none> 40h v1.16.0
k8s-node1 Ready <none> 40h v1.16.0
k8s-node2 Ready <none> 40h v1.16.0 true

将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
# 在yaml文件中添加 节点选择器
# 节点选择器将pod部署到包含gpu=true的节点上
[root@k8s-master1 demo]# vim kubia-gpu.yaml

apiVersion: v1
kind: Pod
metadata:
name: kubia-gpu
spec:
nodeSelector:
gpu: "true"
containers:
- image: 172.31.228.68/project/kubia
name: kubia
ports:
- containerPort: 8080
protocol: TCP

[root@k8s-master1 demo]# kubectl create -f kubia-gpu.yaml

[root@k8s-master1 demo]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubia-gpu 1/1 Running 0 6s 10.244.1.13 k8s-node2 <none> <none>
kubia-manual 1/1 Running 0 101m 10.244.2.11 k8s-master1 <none> <none>
kubia-manual-v2 1/1 Running 0 90m 10.244.0.10 k8s-node1 <none> <none>

调度到一个特定节点

1
2
3
4
5
6
7
8
9
1. 每个机器都有一个通有标签 即主机名
2. 如果该node处于离线状态,会导致该pod不可调度
3. 不应该考虑单点调度

[root@k8s-master1 demo]# kubectl get node -L kubernetes.io/hostname
NAME STATUS ROLES AGE VERSION HOSTNAME
k8s-master1 Ready <none> 40h v1.16.0 k8s-master1
k8s-node1 Ready <none> 40h v1.16.0 k8s-node1
k8s-node2 Ready <none> 40h v1.16.0 k8s-node2

pod 的注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 指定创建pod对象的人员姓名
# 注解不能超过256KB

[root@k8s-master1 demo]# kubectl annotate pod kubia-gpu MAINTAINER="leo"
pod/kubia-gpu annotated

# 查看注解
[root@k8s-master1 demo]# kubectl describe pod kubia-gpu
Name: kubia-gpu
Namespace: default
Priority: 0
Node: k8s-node2/172.31.228.70
Start Time: Wed, 11 Mar 2020 09:40:37 +0800
Labels: <none>
Annotations: MAINTAINER: leo

使用命名空间对资源进行分组

1
2
3
4
5
6
7
8
9
10
# 列出集群中的所有命名空间
# 默认 default
[root@k8s-master1 demo]# kubectl get ns
NAME STATUS AGE
default Active 41h
ingress-nginx Active 40h
kube-node-lease Active 41h
kube-public Active 41h
kube-system Active 41h
kubernetes-dashboard Active 40h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 根据命名空间查找 pod
[root@k8s-master1 demo]# kubectl get pod --namespace kube-system
NAME READY STATUS RESTARTS AGE
coredns-6d8cfdd59d-6b75f 1/1 Running 3 41h
kube-flannel-ds-amd64-q29r8 1/1 Running 3 41h
kube-flannel-ds-amd64-xh7c4 1/1 Running 3 41h
kube-flannel-ds-amd64-xq7gq 1/1 Running 4 41h

[root@k8s-master1 demo]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-6d8cfdd59d-6b75f 1/1 Running 3 41h
kube-flannel-ds-amd64-q29r8 1/1 Running 3 41h
kube-flannel-ds-amd64-xh7c4 1/1 Running 3 41h
kube-flannel-ds-amd64-xq7gq 1/1 Running 4 41h
1
2
3
# 使用命名空间做k8s集群的用户隔离,多租户环境
# 允许某些用户访问指定资源
# 限制用户可用的计算资源数量

创建命名空间

1
2
3
4
5
6
7
8
9
# 从yaml文件创建 
[root@k8s-master1 demo]# vim leo-com-namespace.yaml
apiVersion: v1
kind: Namespace # 资源类型
metadata:
name: leo-com # 命名空间名称

[root@k8s-master1 demo]# kubectl create -f leo-com-namespace.yaml
namespace/leo-com created
1
2
3
4
5
6
7
8
9
# 使用命令创建
[root@k8s-master1 demo]# kubectl create namespace lex-com

# 命名空间不允许包含点号
[root@k8s-master1 demo]# kubectl get ns
NAME STATUS AGE
...
leo-com Active 101s
lex-com Active 26s

在命名空间中创建资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 在yaml文件中指定
[root@k8s-master1 demo]# vim kubia-manual.yaml

apiVersion: v1
kind: Pod
metadata:
name: kubia-manual
namespace: leo-com # 指定

[root@k8s-master1 demo]# kubectl get pods
NAME READY STATUS RESTARTS AGE
kubia-gpu 1/1 Running 0 42m
kubia-manual 1/1 Running 0 144m
kubia-manual-v2 1/1 Running 0 133m

[root@k8s-master1 demo]# kubectl get pods -n leo-com
NAME READY STATUS RESTARTS AGE
kubia-manual 1/1 Running 0 8s
1
2
3
4
5
6
7
8
# 创建资源的时候指定
# 如果yaml文件中有指定,创建的时候会报错,所以要统一
# 尽量在yaml中指定,强化api对象概念
# 如果不指定会以当前上下文默认的命名空间操作,kubectl config命名修改

[root@k8s-master1 demo]# kubectl create -f kubia-manual.yaml -n lex-com

[root@k8s-master1 demo]# kubectl get pods --all-namespaces

命名空间提供的隔离

1
2
3
4
1. 命名空间将对象分隔到不同的组
2. 命名空间不提供对象的任何隔离
3. 命名空间是否提供网络隔离取决于k8s的网络方案
4. 如果网络方案不提供命名空间的网络隔离,那么两个不同namespace中的两个pod之间是可以相互通信

停止和移除 pod

按 pod 名称删除

1
2
3
4
5
6
# k8s终止该pod中的所有容器
# k8s发送sigterm信号并等待一定的秒数(默认30秒),使其正常关闭
[root@k8s-master1 demo]# kubectl delete pod kubia-gpu

# 删除多个pod 用空格分割
[root@k8s-master1 demo]# kubectl delete pod kubia-gpu kubia-manual

使用标签选择器删除 pod

1
2
3
4
5
6
7
8
9
10
11
# 先找到他们共有的标签条件
# 可以一次性删除所有标签的pod,使用前需要确认

[root@k8s-master1 demo]# kubectl label pod kubia-manual env=debug --overwrite

[root@k8s-master1 demo]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
kubia-manual 1/1 Running 0 162m app=os,env=debug,team=B
kubia-manual-v2 1/1 Running 0 151m env=debug,team=A

[root@k8s-master1 demo]# kubectl delete pod -l env=debug

通过删除命名空间 来删除 pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1. 不需要命名空间下的pod
2. 不需要该命名空间
3. pod会伴随命名空间自动删除

[root@k8s-master1 demo]# kubectl get pod -n leo-com
NAME READY STATUS RESTARTS AGE
kubia-manual 1/1 Running 0 21m

[root@k8s-master1 demo]# kubectl delete ns leo-com

[root@k8s-master1 demo]# kubectl get ns

[root@k8s-master1 demo]# kubectl get pod -n leo-com
No resources found in leo-com namespace.

删除命名空间中的pod 保留命名空间

1
2
3
4
[root@k8s-master1 demo]# kubectl delete pod --all -n lex-com

[root@k8s-master1 demo]# kubectl get ns
lex-com Active 34m

注意 删除 pod 和 其他资源

1
2
3
# 如果我们通过run命令创建的rc,他不会直接创建pod,而是先创建一个rc,再由rc创建pod
# 如果我们删除rc创建的pod,他会立即创建自定个数的新pod
# 如果想要完整删除,还需要删除这个rc控制器,和deployment其他资源对象一样。

删除命名空间中的所有资源

1
2
3
4
5
6
7
# 可以删除rc和pod,也可以删除service
# all 指定删除所有的资源对象类型
# --all 删除所有资源实例
# 并不是真的完整删除素有内容,有一些会被保留,比如secret会包保留
# 这种命名不要不经考虑就使用
# 他会删除kubernetes的service,需要看看是否会自动创建
[root@k8s-master1 demo]# kubectl delete all --all