Kubernetes学习笔记(三):namespace和pod
在部署实际应用程序时,k8s集群中会运行很多pod。随着pod数量的增加,管理pod也越来越困难。因此,我们需要一种可以有效组织这些pod的机制。通过标签,我们能够基于任意标准将pod组织成更小群体,从而能够有效地管理这些pod。标签不仅可以组织pod,也可以组织所有其他的Kubernetes资源。详细来讲,标签是可以附加到资源的任意键值对,用以选择具有该确切标签的资源(这是通过标签选择器完成的)
文章目录
namespace(命名空间)
为何需要namespace
-
namespace为k8s资源提供了一个作用域,可以对集群资源进行隔离划分。
-
namespace默认只隔离资源,不隔离网络。
-
不同的namespace可以包含同名的资源。
在实际中,我们可以通过namespace将一个复杂系统分为生产、开发和 QA 环境。每个namespace内包含一整套系统的组件资源。这些资源名称只需在namespace内保持唯一即可,两个不同的namespace的资源可以同名。如下图:
namespace的常用命令
常用命令
# 创建名为 hello 的命名空间
kubectl create ns hello
# 删除名为 hello 的命名空间
kubectl delete ns hello
创建命名空间的yaml文件(文件名:hello.yaml)
# 资源版本号
apiVersion: v1
# 资源类型
kind: Namespace
# 元数据
metadata:
# 资源名字
name: hello
# 通过如下命令调用yaml文件,创建资源
kubectl apply -f <文件名>
kubectl apply -f hello.yaml
# 删除通过yaml文件创建的资源
kubectl delete -f <文件名>
kubectl delete -f hello.yaml
# 查询所有的命名空间列表
kubectl get ns -A
# 查询 default 命名空间的详细信息
kubectl describe ns default
kubectl describe ns <命名空间名>
pod
为何需要pod?
- 为什么要有pod?为什么不直接管理容器?
- ==在k8s和docker中,每个容器只运行一个进程(除非进程本身产生子进程)。==如果在单个容器中运行多个不相关的进程,那么保持所有进程运行、管理它们的日志等将会是我们的责任。例如,我们需要包含一种在进程崩溃时能够自动重启的机制。同时这些进程都将记录到相同的标准输出中,而此时我们将很难确定每个进程分别记录了什么。
- ==由于不能将多个进程聚集在一个单独的容器中,我们需要另一种更高级的结构来将多个运行密切相关的进程的容器绑定在一起,并将它们作为一个单元进行管理,这个单元就是pod。==在包含多个容器的pod中,我们可以同时运行多个密切相关的进程,并为它们提供(几乎)相同的环境,此时这些进程就好像全部运行于单个容器中一样,同时又保持着一定的隔离。这样一来,我们便能全面地利用容器所提供的特性,同时对这些进程来说它们就像运行在一起一样,实现两全其美。
- pod特点:
- 一个pod可以包含一个或多个容器。
- 一个pod总是运行在同一个工作节点上,绝不会跨越多个工作节点。
了解pod
-
同一 pod 中的容器互相部分隔离
- 对于一个包含多容器的pod,其中的容器不是完全隔离的。同一个pod 内的所有容器共享相同的 Linux 命名空间。
-
同一个pod 内的所有容器共享相同的主机名、网络接口、IP地址和端口空间
- 所以同一pod中的多个容器在运行时需要注意不能绑定到相同的端口号,否则会导致端口冲突。但不同的pod有独立的端口空间,所以不同pod的容器不会遇到端口冲突。
-
每个pod都可以通过其他pod的IP地址来实现相互访问。
Kubemetes 集群中的所有 pod 都在同一个共享网络地址空间中,这意味着每个 pod 都可以通过其他 pod 的 IP 地址来实现相互访问。
通过pod合理管理容器
-
不应该将整个应用程序都放到单一pod中。在部署应用程序时,我们应该将应用程序部署到多个 pod 中, 而每个 pod 只包含紧密相关的组件或进程。
-
那如何判断两个组件是放入一个 pod 还是两个单独的 pod ?此时,我们需要问自己以下问题:
- 它们需要一起运行还是可以在不同的主机上运行?
- 它们代表的是一个整体还是相互独立的组件?
- 它们必须一起进行扩缩容还是可以分别进行?
pod常用命令
yaml描述文件结构
执行
kubectl get pods kubia -oyaml
得到如下yaml资源,yaml资源的主要组成部分如下:
- apiVersion:YAML中使用的Kubernetes API版本
- kind:YAML描述的资源类型
- metadata:包括名称、命名空间、标签和关于该容器的其他信息。
- spec:包含pod内容的实际说明,例如pod的容器、卷和其他数据。
- status:包含运行中的pod的当前信息,例如pod所处的条件、每个容器的描述和状态,以及内部P和其他基本信息。在创建新的pod时,不需要提供status部分。
# YAML描述文件所使用的Kubernetes API版本
apiVersion: v1
# Kubernetes对象资源类型
kind: Pod
# pod元数据(名称、标签和注解等)
metadata:
creationTimestamp: "2024-01-14T16:45:48Z"
labels:
run: kubia
name: kubia
namespace: default
resourceVersion: "81563"
uid: 1dbf17b8-b0ab-43c6-abeb-ec42d3aa9ae6
# pod规格/内容(pod的容器列表、volume等)
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/xylearn/kubia:v1
imagePullPolicy: IfNotPresent
name: kubia
ports:
- containerPort: 8080
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-jh68j
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: kind-worker
preemptionPolicy: PreemptLowerPriority
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: kube-api-access-jh68j
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
# pod及其内部容器的详细状态
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2024-01-14T16:45:49Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2024-01-15T06:40:20Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2024-01-15T06:40:20Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2024-01-14T16:45:49Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: containerd://fb82290958070d21fe5ae9b92ad11b3e186eed765d560293a5d4ddd233444ad5
image: registry.cn-hangzhou.aliyuncs.com/xylearn/kubia:v1
imageID: sha256:e56bbdd6fb8d3129e6902fcecbe8c8d90e17e4ce22c3d330a0e7f25b88a5ab9f
lastState:
terminated:
containerID: containerd://698c740db9ae644c80305efc2a292c99b2def88241f5fb15054aff01e798febd
exitCode: 255
finishedAt: "2024-01-15T06:39:38Z"
reason: Unknown
startedAt: "2024-01-14T20:13:48Z"
name: kubia
ready: true
restartCount: 2
started: true
state:
running:
startedAt: "2024-01-15T06:40:19Z"
hostIP: 172.18.0.3
phase: Running
podIP: 10.244.1.3
podIPs:
- ip: 10.244.1.3
qosClass: BestEffort
startTime: "2024-01-14T16:45:49Z"
通过yaml文件创建pod
创建yaml文件kubia-manual.yaml
apiVersion: v1
kind: Pod
metadata:
name: kubia-manual
namespace: hello
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/xylearn/kubia:v1
name: kubia
ports:
- containerPort: 9000
protocol: TCP
执行yaml文件
kubectl create -f kubia-manual.yaml
# 或者
kubectl apply -f kubia-manual.yaml
注:
可以用
kubectl explain
查看资源的api描述,描述资源各字段的含义kubectl explain pods
通过kubectl run来创建pod
# 创建名为 xypod1 的pod
kubectl run xypod1 --image=nginx
kubectl run <pod名> --image=<镜像>
查询pod
# 查看default名称空间的Pod
kubectl get pod
# 查看所有的Pod
kubectl get pod -A
# # 查看namespace hello中的Pod
kubectl get pod -n hello
# 每个Pod - k8s都会分配一个ip,查看default名称空间的Pod的ip
kubectl get pod -owide
# 查看pod的完整定义
kubectl get pod <Pod名字> -oyaml
kubectl get pod <Pod名字> -ojson
# 查看pod描述
kubectl describe pod <Pod名字>
# 查看pod中的容器列表
# 查看普通容器(不包括init容器)
kubectl get pods kubia-manual -o jsonpath={.spec.containers[*].name} -n default
# 查看init容器
kubectl get pods kubia-manual -o jsonpath={.spec.initContainers[*].name} -n default
# 查看所有容器
kubectl get pods kubia-manual -o jsonpath="{.spec['containers','initContainers'][*].name}" -n default
查看应用程序日志
# 查看Pod的运行日志
kubectl logs -f <Pod名字>
# 如果pod中有多个容器,可以查询指定容器的日志
kubectl logs -f <Pod名字> -c <容器名字>
kubectl logs -f kubia-manual -c kubia
停止和删除pod
# 按名字删除pod
kubectl delete pod kubia-gpu
# 按名字删除多个pod
kubectl delete pod kubia-gpu kubia
# 按标签选择器删除pod
kubectl delete pod -A -l xy.com/author=tt
# 删除namespace会删除其中的所有pod
kubectl delete ns xyns
# 删除当前namespace中的所有pod
kubectl delete pod --all -n xyns
# 删除几乎所有资源
kubectl delete all --all -n xyns
向pod发送请求
如果想要在不通过service的情况下与某个特定的pod进行通信(出于调试或其他原因),Kubernetes将允许我们配置端口转发到该pod。可以通过kubectl port-forward命令完成上述操作。
# 将机器的本地端口8888转发到kubia-manual pod的端口8080
kubectl port-forward kubia-manual 8888:8080
# 另开一个终端,可以访问8888端口
curl localhost:8888
标签
介绍标签
在部署实际应用程序时,k8s集群中会运行很多pod。随着pod数量的增加,管理pod也越来越困难。因此,我们需要一种可以有效组织这些pod的机制。通过标签,我们能够基于任意标准将pod组织成更小群体,从而能够有效地管理这些pod。
标签不仅可以组织pod,也可以组织所有其他的Kubernetes资源。详细来讲,标签是可以附加到资源的任意键值对,用以选择具有该确切标签的资源(这是通过标签选择器完成的)。
使用标签
- 通过yaml创建
apiVersion: v1
kind: Pod
metadata:
name: kubia-manual-v2
# 附加标签
labels:
xy.com/method: manual
xy.com/env: prod
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/xylearn/kubia:v1
name: kubia
ports:
- containerPort: 8080
protocol: TCP
- 标签常用命令如下:
# 查看pod标签
kubectl get pods -A --show-labels
# 查看指定标签信息
kubectl get pods -L xy.com/env,xy.com/method
kubectl get pods -L <标签1>,<标签2>
# 修改已有pod的标签
## 添加新标签
kubectl label pod kubia-manual-v2 xy.com/author=tt
## 修改已有标签的值
kubectl label pod kubia-manual-v2 xy.com/env=dev --overwrite
使用标签选择器查询pod
单个条件查询
标签选择器根据资源的以下条件来选择资源:
- 包含(或不包含)使用特定键的标签
- 包含具有特定键和值的标签
- 包含具有特定键的标签, 但其值不等于我们指定的值
# 查询指定标签的pod
kubectl get pods -A -l xy.com/author=tt
# 查询所有包含指定标签的pod
kubectl get pods -A -l k8s-app
# 查询所有不包含指定标签的pod,这里注意要用单引号
kubectl get pods -A -l '!k8s-app'
# 查询所有指定标签的值不等于指定值的pod,这里注意要用单引号
kubectl get pods -A -l 'k8s-app!=kube-dns'
# 范围查询
kubectl get pods -A -l 'xy.com/env in (prod,dev)'
# 反向范围查询,这里会把不包含xy.com/env标签的pod也查出来
kubectl get pods -A -l 'xy.com/env notin (prod,dev)'
# 反向范围查询,且排除不包含xy.com/env标签的pod
kubectl get pods -A -l 'xy.com/env notin (prod,dev)',xy.com/env
多个条件查询
在包含多个逗号分隔的情况下,可以在标签选择器中同时使用多个条件,此时资源需要全部匹配才算成功匹配了选择器。
使用标签和选择器来约束pod调度
在实际生产部署中,我们有时希望某类pod部署一些满足条件的node中,甚至是某一个node中。这里就可以用标签和选择器实现。
将pod调度到一类特定节点
例如,我们现在有个pod对服务器的gpu要求比较高,希望能部署到gpu性能好的节点。我们在集群中添加gpu性能好的节点后,修改它的标签。
kubectl label node gpu-kubia-node gpu=true
然后修改pod的yaml文件
apiVersion: v1
kind: Pod
metadata:
name: kubia-manual
namespace: hello
spec:
# 节点选择器要求k8s只将pod部署到包含标签gpu=true的节点上
nodeSelector:
gpu: "true"
containers:
- image: registry.cn-hangzhou.aliyuncs.com/xylearn/kubia:v1
name: kubia
ports:
- containerPort: 9000
protocol: TCP
将pod调度到一个特定节点
同样地,我们也可以将pod调度到某个确定的节点,由于每个节点都有一个唯一标签,其中键为kubernetes.io/hostname,值为该节点的实际主机名因此我们也可以将pod调度到某个确定的节点。
我们绝不应该考虑单个节点,而是应该通过标签选择器考虑符合特定标准的逻辑节点组。
注解
介绍注解
注解也是键值对,所以它们本质上与标签非常相似。但与标签不同,注解并不是为了保存标识信息而存在的,它们不能像标签一样用于对对象进行分组。当我们可以通过标签选择器选择对象时,就不存在注解选择器这样的东西。
==注解可以容纳更多的信息(总共不超过256KB),所以可以用注解为每个pod或其他API对象添加说明,以便每个使用该集群的人都可以快速查找有关每个单独对象的信息。==例如,指定创建对象的人员姓名的注解可以使在集群中工作的人员之间的协作更加便利。
常用命令
# 创建注解 mycompany.com/someannotation="foo bar"
kubectl annotate pod kubia-manual mycompany.com/someannotation="foo bar"
# 查看注解
kubectl describe pod kubia-manual
参考资料
-
《Kubernetes in Action》
更多推荐
所有评论(0)