Pod & Container

Kubernetes 的最小调度单元是 Pod,在 Pod 中包含多个 Container。

Pod 基本操作

查看 Pod

pod 默认有 kube-defaultkube-system 两个命名空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 查询默认 pod
kubectl get po|pod|pods

# 查询指定命名空间的所有 pod
kubectl get pods -n [namspace]

# 查询当前命名空间的所有 pod
kubectl get pods -A

# 查看指定命名空间下 pod 的详细信息
kubectl get pod -o wide -n [namspace]

# 查看所有命名空间下 pod 的详细信息
kubectl get pod -o wide -A

# 查看指定 pod 的详细信息(不能查看 pod 中的具体容器,pod 为最小管理单元)
kubectl describe pod [pod-name]

创建 Pod

先说一种不常用的方式,这种方式很 docker,该方式生产中一般不用。

1
2
# 创建 pod
kubectl run [podname] --image=nginx:1.24

常用的创建方式:yml 文件(必须),创建 nginx-pod.yml 文件加入以下内容:

nginx-pod.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# api 版本
apiVersion: v1
# 创建的分类
kind: Pod

# 标准的对象元数据(用户自定义信息,例如 pod 名称等)。更多信息: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
metadata:
name: nginx
# 标签
labels:
key: value
# 对 Pod 预期行为的规约。更多信息: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
spec:
containers:
- name: nginx
image: nginx:1.24
ports:
- containerPort: 80
restartPolicy: Always

IDEA 使用 Kubernetes 插件创建 yml 文件后输入 k 可以选择创建模板。

创建 pod:

1
2
3
4
5
# 创建时如果 pod 已经存在则报错
kubectl create -f nginx-pod.yml

# 创建时如果 pod 已经存在则更新(推荐使用)
kubectl apply -f nginx-pod.yml

默认会部署 pod 到当前的命名空间,如果要部署应用到指定的命名空间:kubectl apply -f filename.yml --namespace [namespace]

删除 Pod

1
2
3
4
5
# 直接删除 pod
kubectl delete pod [podname]

# 通过配置文件也可以删除已经存在的 pod(推荐使用)
kubectl delete -f [pod-yml]

Pod 其它操作

1
2
3
4
5
6
7
# 进入 pod 中的指定容器,-c 指定进入 pod 的容器名称
kubectl exec -it [podname] -c [containername] -- bash

# 查看 pod 所有容器的日志,使用 -f 可以查看实时日志
kubectl logs -f [podname]
# 查看 pod 指定容器的日志
kubectl logs -f [podname] -c [containername]

Pod 的 label 标签

标签是一组键值对组成,每个 key 对与给定对象必须是唯一的。

Pod Labels 必须小于 63 个字符;必须以字母、数字、字符开头和结尾;包含破折号、下划线、点和字母数字;

操作
1
2
3
4
5
6
7
8
9
10
11
12
# 显示所有 pods 的 labels
kubectl get pods --show-labels

# 为已经创建的 pod 添加 label
kubectl label pod [podname] [key=value]
# 修改 pod 的 label
kubectl label --overwrite pod [podname] [key=value]
# 删除 key 后面添加一个 - 即可删除
kubectl label pod [podname] [key-]

# 筛选指定标签的 pods
kubectl get pods -l [key/key=value]

Pod 的生命周期

Container 容器

容器重启策略

Pod 的 spec 包含一个 restartPolicy 字段,有三个可选值:Always(总是重启)、OnFailure(容器异常退出)、Never,默认为 Aways。

该值适用于 Pod 中的所有容器。

自定义容器的启动命令

推荐在 k8s 中使用 command 修改启动命令,使用 args 为启动命令传递参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Pod
metadata:
name: redis
# 标签
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7.0.14
command: ["redis-server"]
args: ["--appendonly yes"]
ports:
- containerPort: 6379
imagePullPolicy: IfNotPresent
restartPolicy: Always

容器探针

probe 是由 kubelet 对容器执行的定期诊断,可以看作一个诊断工具。探针检测后有三种状态:

Sucess:成功,容器通过诊断;
Failure:失败,容器未通过诊断;
Unknown:未知,诊断失败,不会采取任何行动。

三种探针类型

livenessProbe:检测容器是否正在运行。
readinessProbe:检测容器是否准备好为请求提供服务。
startupProbe(1.7+):检测容器中的应用是否已经启动。

每种类型的探针都有以下几个机制/命令:

  • exec:在容器内部执行命令,如果命令退出代码时返回 0,则诊断成功;
  • grpc:使用远程过程调用,如果响应的状态是 “Serving”,则诊断成功。gRPC 探针是一个 Alpha 特性,需要启用 GPRCContainerProbe 特性时才能使用;
  • httpGet:发送一个 GET 请求,如果响应码大于等于 200 且小于 400,则诊断成功;
  • tcpSocket:对容器的 IP 地址上的指定端口执行 TCP 检查,如果端口打开,则诊断成功。如果远程系统在打开连接后立即将其关闭,这算作健康状态。

每种命令都有几个探针参数:

1
2
3
4
5
6
7
8
9
10
# 初始化时间
initialDelaySeconds: 5
# 检测间隔时间
periodSeconds: 4
# 默认检测超时时间 1 s
timeoutSeconds: 1
# 默认失败次数为 3 次,达到 3 次后重启 Pod
failureThreshold: 3
# 默认成功次数为 1 次,1 次监测成功代表成功
successThreshold: 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
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
ports:
- containerPort: 80
args:
- /bin/sh
- -c
- sleep 7;nginx -g "daemon off;" #这一步会和初始化同时开始运行,也就是在初始化5s后和7秒之间,会检测出一次失败,7秒后启动后检测正常,所以pod不会重启
imagePuLLPoLicy: IfNotPresent
livenessProbe:
exec:
command:
- ls
- /var/run/nginx.pid
initialDelaySeconds: 5 #初始化时间5
speriodSeconds: 4 # 检测间隔时间4
timeoutSeconds: 1 # 默认检测超时时间为1s
failureThreshold: 3 #默认失败次数为3次、达到3次后重启
successThreshoLd: 1 #默认成功次数为1次,1次代表成功

参考官网:https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-grpc-liveness-probe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
name: etcd-with-grpc
spec:
containers:
- name: etcd
image: registry.k8s.io/etcd:3.5.1-0
command: [ "/usr/local/bin/etcd", "--data-dir", "/var/lib/etcd", "--listen-client-urls", "http://0.0.0.0:2379", "--advertise-client-urls", "http://127.0.0.1:2379", "--log-level", "debug"]
ports:
- containerPort: 2379
livenessProbe:
grpc:
port: 2379
initialDelaySeconds: 10
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
apiVersion: v1
kind: Pod
metadata:
name: Liveness-httpget
labels:
httpget: httpget
spec:
containers:
- name: nginx
image: nginx:1.19
ports:
- containerPort: 80
args:
- /bin/sh
- -c
- sleep 7;nginx -g "daemon off;" #这一步会和初始化同时开始运行,也就是在初始化5s后和7秒之间,会检测出一次失败,7秒后启动后检测正常,所以pod不会重启
imagePuLLPoLicy: IfNotPresent
livenessProbe:
httpGet: # httpget
port: 80 #访问的端口
path: /index.htmt #访问的路径
initialDelaySeconds: 5 #初始化时间5
speriodSeconds: 4 # 检测间隔时间4
timeoutSeconds: 1 # 默认检测超时时间为1s
failureThreshold: 3 #默认失败次数为3次、达到3次后重启
successThreshoLd: 1 #默认成功次数为1次,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
apiVersion: v1
kind: Pod
metadata:
name: liveness-tcp
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
ports:
- containerPort: 80
args:
- /bin/sh
- -c
- sleep 7;nginx -g "daemon off;" # 这一步会和初始化同时开始运行,也就是在初始化5s后和7秒之间,会检测出一次失败,7秒后启动后检测正常,所以pod不会重启
imagePuLLPoLicy: IfNotPresent
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 5 #初始化时间5
speriodSeconds: 4 # 检测间隔时间4
timeoutSeconds: 1 # 默认检测超时时间为1s
failureThreshold: 3 #默认失败次数为3次、达到3次后重启
successThreshoLd: 1 #默认成功次数为1次,1次代表成功

资源限制

在 Kubernetes 中对于容器的资源限制主要分为两类:内存资源限制、CPU 资源限制。Kubernetes 可以定义容易运行占用的资源限制,超过最大资源容器会被 kill,并报 OOM Error。

安装 metrics

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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
name: system:aggregated-metrics-reader
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- nodes/metrics
verbs:
- get
- apiGroups:
- ""
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
ports:
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: metrics-server
strategy:
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
k8s-app: metrics-server
spec:
containers:
- args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
image: registry.k8s.io/metrics-server/metrics-server:v0.6.4
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 4443
name: https
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /readyz
port: https
scheme: HTTPS
initialDelaySeconds: 20
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 200Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
volumeMounts:
- mountPath: /tmp
name: tmp-dir
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-cluster-critical
serviceAccountName: metrics-server
volumes:
- emptyDir: {}
name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
labels:
k8s-app: metrics-server
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
version: v1beta1
versionPriority: 100

安装之后可以使用 kubectl top pod [pod-name] 命令查看当前占用的系统资源情况。

  1. 限制内存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Pod
metadata:
name: liveness-tcp
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
imagePuLLPoLicy: IfNotPresent
# 设置该 container 的请求限制最小 100M,最大 200M
resources:
requests:
memory: 100M
limits:
memory: 200M
1
2
# 查看容器当前内存使用情况
kubectl get pod [pod-name] -o yaml
  • 内存请求和限制的目的
    通过为集群中运行的容器配置内存请求和限制,可以有效利用集群节点上可用的内存资源。通过将 Pod 的内存请求保持在较低水平,你可以更好地安排 Pod 调度。通过让内存限制大于内存请求,你可以完成两件事:

    • Pod 可以进行一些突发活动,从而更好的利用可用内存。
    • Pod 在突发活动期间,可使用的内存被限制为合理的数量。
  • 没有指定内存限制
    如果你没有为一个容器指定内存限制,则自动遵循以下情况之一:

    • 容器可无限制地使用内存。容器可以使用其所在节点所有的可用内存,进而可能导致该节点调用 OOM Killer。此外,如果发生 OOM KiLL,没有资源限制的容器将被杀掉的可行性更大。
    • 运行的容器所在命名空间有默认的内存限制,那么该容器会被自动分配默认限制。
  1. 限制 CPU
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Pod
metadata:
name: liveness-tcp
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
imagePuLLPoLicy: IfNotPresent
# 设置该 container 的请求限制最小 100M,最大 200M
resources:
requests:
cpu: 10m
limits:
cpu: 50m
  • CPU 请求和限制的初衷
    通过配置你的集群中运行的容器的ICPU请求和限制,你可以有效利用集群上可用的CPU资源。通过将Pod CPU 请求保持在较低水平,可以使 Pod 更有机会被调度。通过使 CPU 限制大于 CPU 请求,你可以完成两件事:
    • Pod 可能会有突发性的活动,它可以利用碰巧可用的 CPU 资源。
    • Pod 在突发负载期间可以使用的 CPU 资源数量仍被限制为合理的数量。
  • 如果不指定 CPU 限制
    如果你没有为容器指定 CPU 限制,则会发生以下情况之一:
    • 容器在可以使用的 CPU 资源上没有上限。因而可以使用所在节点上所有的可用 CPU 资源。
    • 容器在具有默认 CPU 限制的名称空间中运行,系统会自动为容器设置默认限制。
  • 如果你设置了 CPU 限制但未设置 CPU 请求,Kubernetes 会自动为其设置与 CPU 限制相同的 CPU 请求值。类似的,如果容器设置了内存限制值但未设置内存请求值,Kubernetes 也会为其设置与内存限制值相同的内存请求。

Pod 中的 Init 容器

Init 容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。每个 Pod 中可以包含多个容器,应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。

Init 容器与普通的容器非常像,除了如下两点:

  • 它们总是运行到完成。
  • 每个都必须在下一个启动之前成功完成。

如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。 然而,如果 Pod 对应的 restartPolicy 值为 “Never”,并且 Pod 的 Init 容器失败, 则 Kubernetes 会将整个 Pod 状态设置为失败。

Init 容器不支持 lifecycle、livenessProbe、readinessProbe 和 startupProbe, 因为它们必须在 Pod 就绪之前运行完成。

如果为一个 Pod 指定了多个 Init 容器,这些容器会按顺序逐个运行。 每个 Init 容器必须运行成功,下一个才能够运行。当所有的 Init 容器运行完成时, Kubernetes 才会为 Pod 初始化应用容器并像平常一样运行。

Pod 节点 label

作用:根据 label 确定 Pod 运行的节点(yaml 中使用 nodeSelector )。

1
2
3
4
5
6
# 显示所有节点
kubectl get nodes
# 显示所有的节点及其标签
kubectl get nodes --show-labels;
# 添加标签
kubectl label node [node-name] [key=value]

Controller 控制器

一般不单独创建 Pod,而是通过 Controller 创建并管理,Controller 也是通过 label 来关联 Pod 并进行管理。

Deployment

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
apiVersion: apps/v1
# Deployment 类型控制器
kind: Deployment
metadata:
name: nginx-deployment
# 控制器 label
labels:
app: nginx-deployment
spec:
# 一次创建 3 个副本:即启动 3 个 nginx
replicas: 3
# 表明控制器如何查找要管理的 Pod
selector:
matchLabels:
app: nginx
template:
metadata:
# 必须对应 selector: matchLabels:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80

deployment 的一些命令和 Pod 类似,把 pod 换为 deployment 即可。这里不再举例。

deployment 伸缩

1
2
3
4
# 查询副本
kubectl get rs|replicaset
# 扩展 deployment
kubectl scale deployment [deployment-name] --replicas=num

deployment 回滚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#查看上线状态
kubectl rollout status [deployment deployment-name| deployment/deployment-name]
# 查看版本历史
kubectl rollout history deployment [deployment-name]
#查看某个版本的详细信息
kubectl rollout history deployment/[deployment-name] --revision=version-num
#回到上个版本
kubectl rollout undo deployment [deployment-name]
#回到指定版本
kubectl rollout undo deployment [deployment-name] --to-revision=version-num
# 重启
kubectl rollout restart deployment [deployment-name]
#暂停运行,暂停后,对depLoyment的修改不会立刻生效,恢复后才应用设置
kubectl rollout pause deployment [deployment-name]
#恢复
kubectl rollout resume deployment [deployment-name]

StatefulSet

StatefulSet 和 Deplotment 差不多,但是可以为 Pod 提供持久存储和持久标识符。

删除或这扩缩 StatefulSet 的时候,不会删除的它关联的数据卷,以此保证数据的安全。

不推荐删除 StatefulSet 的 yml。

DaemonSet

Job

Service

Kubernetes 中 Service 是 将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法。

Helm

Helm 是一个 Kubernetes 的包管理器。

1
2
3
4
5
6
7
8
9
10
11
12
# 联网查找软件包
helm search hub [name]
# 查找本地包
helm search repo [name]
# 查看本地启动的列表
helm list
# 安装自定义 chart
helm create [chart-name]
# 校验编写的脚本
helm lint [chart-name]
# 打包
helm package path

本站由 江湖浪子 使用 Stellar 1.29.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。