Pod & Container
Kubernetes 的最小调度单元是 Pod,在 Pod 中包含多个 Container。
Pod 基本操作
查看 Pod
pod 默认有 kube-default 和 kube-system 两个命名空间。
# 查询默认 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,该方式生产中一般不用。
# 创建 pod
kubectl run [podname] --image=nginx:1.24
常用的创建方式:yml 文件(必须),创建 nginx-pod.yml 文件加入以下内容:
# 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:
# 创建时如果 pod 已经存在则报错
kubectl create -f nginx-pod.yml
# 创建时如果 pod 已经存在则更新(推荐使用)
kubectl apply -f nginx-pod.yml
默认会部署 pod 到当前的命名空间,如果要部署应用到指定的命名空间:
kubectl apply -f filename.yml --namespace [namespace]
删除 Pod
# 直接删除 pod
kubectl delete pod [podname]
# 通过配置文件也可以删除已经存在的 pod(推荐使用)
kubectl delete -f [pod-yml]
Pod 其它操作
# 进入 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 个字符;必须以字母、数字、字符开头和结尾;包含破折号、下划线、点和字母数字;
操作
# 显示所有 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 为启动命令传递参数。
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 检查,如果端口打开,则诊断成功。如果远程系统在打开连接后立即将其关闭,这算作健康状态。
每种命令都有几个探针参数:
# 初始化时间
initialDelaySeconds: 5
# 检测间隔时间
periodSeconds: 4
# 默认检测超时时间 1 s
timeoutSeconds: 1
# 默认失败次数为 3 次,达到 3 次后重启 Pod
failureThreshold: 3
# 默认成功次数为 1 次,1 次监测成功代表成功
successThreshold: 1
举个例子: {% folding 举个例子 open:false color:green %} {% tabs %}
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
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
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次代表成功
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次代表成功
{% endtabs %} {% endfolding %}
资源限制
在 Kubernetes 中对于容器的资源限制主要分为两类:内存资源限制、CPU 资源限制。Kubernetes 可以定义容易运行占用的资源限制,超过最大资源容器会被 kill,并报 OOM Error。
{% folding 安装 metrics open:false %}
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
{% endfolding %}
安装之后可以使用
kubectl top pod [pod-name]命令查看当前占用的系统资源情况。
- 限制内存
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
# 查看容器当前内存使用情况
kubectl get pod [pod-name] -o yaml
-
内存请求和限制的目的 通过为集群中运行的容器配置内存请求和限制,可以有效利用集群节点上可用的内存资源。通过将 Pod 的内存请求保持在较低水平,你可以更好地安排 Pod 调度。通过让内存限制大于内存请求,你可以完成两件事:
- Pod 可以进行一些突发活动,从而更好的利用可用内存。
- Pod 在突发活动期间,可使用的内存被限制为合理的数量。
-
没有指定内存限制 如果你没有为一个容器指定内存限制,则自动遵循以下情况之一:
- 容器可无限制地使用内存。容器可以使用其所在节点所有的可用内存,进而可能导致该节点调用 OOM Killer。此外,如果发生 OOM KiLL,没有资源限制的容器将被杀掉的可行性更大。
- 运行的容器所在命名空间有默认的内存限制,那么该容器会被自动分配默认限制。
- 限制 CPU
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 )。
# 显示所有节点
kubectl get nodes
# 显示所有的节点及其标签
kubectl get nodes --show-labels;
# 添加标签
kubectl label node [node-name] [key=value]
-
节点标签调度 Pod
使用
nodeSelector时如果指定的 label 不存在,k8s 将不会运行 Pod。 -
节点名称调度 Pod
nodeName
Controller 控制器
一般不单独创建 Pod,而是通过 Controller 创建并管理,Controller 也是通过 label 来关联 Pod 并进行管理。
Deployment
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 伸缩
# 查询副本
kubectl get rs|replicaset
# 扩展 deployment
kubectl scale deployment [deployment-name] --replicas=num
deployment 回滚
#查看上线状态
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 的包管理器。
# 联网查找软件包
helm search hub [name]
# 查找本地包
helm search repo [name]
# 查看本地启动的列表
helm list
# 安装自定义 chart
helm create [chart-name]
# 校验编写的脚本
helm lint [chart-name]
# 打包
helm package path

说些什么吧!