文章目录
官方阅读文档:https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/kubernetes-objects/
k8s 对象
-
k8s 里面操作的资源实体,就是 k8s 的对象
- 可以使用
yaml
来声明 - 可以直接使用
kubectl
命令来创建 - 比如 pod、service、deploy、node…
- 可以使用
-
操作 k8s 对象,无论是什么操作(创建、修改、删除),都是需要使用
kubetnetes API
kubectl
也是调用的必要的kubernetes API
- 也可以在程序中使用客户端库来直接调用
kubernetes API
-
在 Kubernetes 系统中,Kubernetes 对象 是持久化的实体。 Kubernetes 使用这些实体去表示整个集群的状态。 比较特别地是,它们描述了如下信息:
- 哪些容器化应用正在运行(以及在哪些节点上运行)
- 可以被应用使用的资源
- 关于应用运行时表现的策略,比如重启策略、升级策略以及容错策略
-
Kubernetes 对象是“目标性记录” —— 一旦创建该对象,Kubernetes 系统将不断工作以确保该对象存在。 通过创建对象,你就是在告知 Kubernetes 系统,你想要的集群工作负载状态看起来应是什么样子的, 这就是 Kubernetes 集群所谓的 期望状态(Desired State)
对象规约(Spec)与状态(Status)
每一个 k8s 对象几乎都包含了2个嵌套的对象字段,他们负责管理对象的配置
- 对象
spec
(规约):必须在创建对象时设置其内容,描述你所希望对象的期望状态
#比如你要运行一个pod,通过kubectl run 来操作的
#这个时候对于 nginx-demo 这个pod来说,你的期望状态就是运行一个pod,利用镜像nginx
kubectl run nginx-demo --image=nginx:1.21-alpine
- 对象
status
(状态):描述了当前对象的当前状态,是由系统组件设置并随时更新的,在任何时刻,k8s 的控制平面都会一直积极地管理着对象的实际状态,并让它达到期望状态(spec) kubelet
就是做一件事情:对象的spec
和status
最终一致性
描述 k8s 对象
创建 Kubernetes 对象时,必须提供对象的
spec
,用来描述该对象的期望状态, 以及关于对象的一些基本信息(例如名称)等
- 推荐使用
yaml
文件来描述 k8s 对象 - kubectl 在发起 API 请求时,会将文件信息转换成 JSON 格式
获取具体对象的yaml文件
如何获取已存在的 k8s 对象的 yaml
描述文件呢?从下面这个例子能看到
- spec: 当前
pod
对象的期望状态 - status: 当前
pod
对象的当前状态
[root@k8s-01 ~]# kubectl get pod -oyaml nginx-demo
apiVersion: v1
kind: Pod
metadata:
annotations:
cni.projectcalico.org/podIP: 192.168.0.31/32
cni.projectcalico.org/podIPs: 192.168.0.31/32
creationTimestamp: "2023-02-20T04:29:18Z"
labels:
run: nginx-demo
name: nginx-demo
namespace: default
resourceVersion: "77219"
uid: 94ffbebd-0ac1-40bf-a890-ce08e827d024
spec:
containers:
- image: nginx:1.21-alpine
imagePullPolicy: IfNotPresent
name: nginx-demo
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-b48j8
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: k8s-03
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-b48j8
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
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2023-02-20T04:29:18Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2023-02-20T04:29:20Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2023-02-20T04:29:20Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2023-02-20T04:29:18Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://feaa5652cb9a820627fc37b182345e08bc5f0b0224ec5393b715c9fcba6aa2ae
image: nginx:1.21-alpine
imageID: docker-pullable://nginx@sha256:eb05700fe7baa6890b74278e39b66b2ed1326831f9ec3ed4bdc6361a4ac2f333
lastState: {}
name: nginx-demo
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2023-02-20T04:29:19Z"
hostIP: 192.168.204.55
phase: Running
podIP: 192.168.0.31
podIPs:
- ip: 192.168.0.31
qosClass: BestEffort
startTime: "2023-02-20T04:29:18Z"
一个 k8s 对象示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # 告知 Deployment 运行 2 个与该模板匹配的 Pod
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2 # 镜像的标签信息
ports:
- containerPort: 80
如何使用yaml文件
kubectl apply -f test.yaml
kubectl delete -f test.yaml
描述对象文件的必要字段信息
apiVersion
- 创建该对象所使用的 Kubernetes API 的版本kind
- 想要创建的对象的类别metadata
- 帮助唯一标识对象的一些数据,包括一个name
字符串、UID
和可选的namespace
spec
- 你所期望的该对象的状态
如何编写任意资源的 yaml 文件?
通过任意存在的对 象资源反向推理yaml文件
- 比如我通过
kubectl run
创建了一个 pod 资源
##这个操作就会最终启动一个pod
kubectl run tomcat --image=tomcat
- 随便在集群里面找一个 pod,将
yaml
输出出来,只需要除了status
状态的内容,比如我将上面的pod通过yaml
输出出来
###将集群中的任意一个pod通过yaml输出
kubectl get pod tomcat -o yaml
###得到内容
apiVersion: v1
kind: Pod
metadata:
annotations:
cni.projectcalico.org/podIP: 192.168.0.33/32
cni.projectcalico.org/podIPs: 192.168.0.33/32
creationTimestamp: "2023-02-20T05:07:04Z"
labels:
run: tomcat
name: tomcat
namespace: default
resourceVersion: "80605"
uid: eceea838-23c9-4cd8-b175-834f5ca034ec
spec:
containers:
- image: tomcat
imagePullPolicy: Always
name: tomcat
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-xfngv
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: k8s-03
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-xfngv
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
- 将上面输出出来的yaml修改一下镜像和说明信息,就可以直接拿来用了,
###将上面输出的yaml文件稍微修改一下
apiVersion: v1
kind: Pod
metadata:
annotations:
cni.projectcalico.org/podIP: 192.168.0.33/32
cni.projectcalico.org/podIPs: 192.168.0.33/32
creationTimestamp: "2023-02-20T05:07:04Z"
labels:
run: nginx
name: nginx
namespace: default
resourceVersion: "80605"
uid: 3808fb74-f56e-4969-b74c-52a8ceb6ea9d
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-xfngv
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: k8s-03
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-xfngv
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
## 尝试一下行不行
kubectl apply -f test.yaml
##这种方法是可行的,但是不知道其他字段信息与其他资源有重复,会不会有问题,这个后面深究一下
干跑一遍对象资源输出为yaml文件
- 不会实际产生k8s资源对象
##比如我要deploy一次
kubectl create deploy my-nginx --image=nginx --dry-run -oyaml
##然后形成了yaml文件
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: my-nginx
name: my-nginx
spec:
replicas: 1
selector:
matchLabels:
app: my-nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: my-nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
##k8s集群环境中也不会正式生成该资源对象信息
##这个方法挺靠谱一点
- 尝试修改一下上面的
yaml
文件
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: tomcat
name: tomcat
spec:
replicas: 1
selector:
matchLabels:
app: tomcat
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: tomcat
spec:
containers:
- image: tomcat
name: tomcat
resources: {}
##部署一下
kubectl apply -f test.yaml
能够描述的资源类型
kubectl api-resources
的KIND
字段
apiVersion: apps/v1 ## 同一资源多个版本(kubectl api-resources 中的APIVERSION字段)
kind: Deployment ## 资源类型 kubectl api-resources
metadata: ## 每一个资源定义一些元数据信息
creationTimestamp: null
labels:
app: tomcat
name: tomcat
spec: ## 资源的规约(期望状态:自定义):镜像名称、版本、环境变量等
replicas: 1
selector:
matchLabels:
app: tomcat
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: tomcat
spec:
containers:
- image: tomcat
name: tomcat
resources: {}
k8s 对象 yaml 的构成
typeMeta
- 对于 kind,通过
kubectl api-resources
字段中的KIND
字段,要写什么?比如pod
kubectl api-resources | grep -E 'pod|KIND'
- 所以对于
pod
来说,我们自己写的话,前段部分的内容就可以写成
kind: Pod
apiVersion: v1
metadata
元数据信息,这个地方到底能写一些什么元数据信息呢?
##比如给这次pod写上一个名字
metadata:
name: nginx-demo-pod
spec
容器的期望状态
spec: # 指定期望状态
containers: # 指定要启动一个什么样的容器
- image: nginx # 指定镜像
name: nginx-demo-pod # 指定容器名称
status
这段信息是 k8s 集群自己实时更新的信息,不需要我们来指定,只要资源变化,kubelet 会请求 api-server 保存最新的资源状态信息。
最简单的一个描述文件
kind: Pod
apiVersion: v1
metadata:
name: nginx-demo-pod
spec: # 指定期望状态
containers: # 指定要启动一个什么样的容器
- image: nginx # 指定镜像
name: nginx-demo-pod # 指定容器名称
管理 k8s 对象
管理技术 | 作用于 | 建议的环境 | 支持的写者 | 学习难度 |
---|---|---|---|---|
指令式命令 | 活跃对象(kubectl 命令系列 ) | 开发项目 | 1+ | 最低 |
指令式对象配置 | 单个文件(单个yaml 文件) | 生产项目 | 1 | 中等 |
声明式对象配置 | 文件目录(多个yaml 文件的多个目录kustomize ) | 生产项目 | 1+ | 最高 |
- 同一个资源对象应该只使用一种方式管理,否则可能会出现不可预期的结果
指令式命令
使用指令式命令时,用户可以在集群中的活动对象上进行操作。用户将操作传给
kubectl
命令作为参数或标志。
- 例如
kubectl create deployment nginx --image nginx
与对象配置相比的优点:
- 命令用单个动词表示。
- 命令仅需一步即可对集群进行更改。
与对象配置相比的缺点:
- 命令不与变更审查流程集成。
- 命令不提供与更改关联的审核跟踪。
- 除了实时内容外,命令不提供记录源。
- 命令不提供用于创建新对象的模板。
指令式对象配置
在指令式对象配置中,kubectl 命令指定操作(创建,替换等),可选标志和至少一个文件名。指定的文件必须包含 YAML 或 JSON 格式的对象的完整定义。
- 例如
kubectl create -f nginx.yaml
kubectl delete -f nginx.yaml -f redis.yaml
kubectl replace -f nginx.yaml
与指令式命令相比的优点:
- 对象配置可以存储在源控制系统中,比如 Git。
- 对象配置可以与流程集成,例如在推送和审计之前检查更新。
- 对象配置提供了用于创建新对象的模板。
与指令式命令相比的缺点:
- 对象配置需要对对象架构有基本的了解。
- 对象配置需要额外的步骤来编写 YAML 文件。
与声明式对象配置相比的优点:
- 指令式对象配置行为更加简单易懂。
- 从 Kubernetes 1.5 版本开始,指令对象配置更加成熟。
与声明式对象配置相比的缺点:
- 指令式对象配置更适合文件,而非目录。
- 对活动对象的更新必须反映在配置文件中,否则会在下一次替换时丢失。
声明式对象配置
使用声明式对象配置时,用户对本地存储的对象配置文件进行操作,但是用户未定义要对该文件执行的操作。
kubectl
会自动检测每个文件的创建、更新和删除操作。 这使得配置可以在目录上工作,根据目录中配置文件对不同的对象执行不同的操作。
- 例如
kubectl diff -f configs/
kubectl apply -f configs/
kubectl diff -R -f configs/
kubectl apply -R -f configs/
-
与指令式对象配置相比的优点:
- 对活动对象所做的更改即使未合并到配置文件中,也会被保留下来。
- 声明性对象配置更好地支持对目录进行操作并自动检测每个文件的操作类型(创建,修补,删除)。
-
与指令式对象配置相比的缺点:
- 声明式对象配置难于调试并且出现异常时结果难以理解。
- 使用 diff 产生的部分更新会创建复杂的合并和补丁操作。
对象名称
-
集群中的每一个对象都有一个名称来标识在同类资源中的唯一性
-
每个 Kubernetes 对象也有一个 UID 来标识在整个集群中的唯一性
-
在同一个名称空间 中只能有一个名为 myapp-1234 的 Pod,但是可以命名一个 Pod 和一个 Deployment 同为 myapp-1234
-
对于用户提供的非唯一性的属性,Kubernetes 提供了标签(Label)和 注解(Annotation)机制
名称规则
-
依据命名规则,Kubernetes对象的名字应该:
-
最长不超过 253个字符
-
必须由小写字母、数字、减号 - 、小数点 . 组成
-
某些资源类型有更具体的要求
UID
UID 是由 Kubernetes 系统生成的,唯一标识某个 Kubernetes 对象的字符串。Kubernetes集群中,每创建一个对象,都有一个唯一的 UID。用于区分多次创建的同名对象(如前所述,按照名字删除对象后,重新再创建同名对象时,两次创建的对象 name 相同,但是 UID 不同。)
名称空间
在 Kubernetes 中,名称空间(Namespace) 提供一种机制,将同一集群中的资源划分为相互隔离的组。 同一名称空间内的资源名称要唯一,但跨名称空间时没有这个要求。 名称空间作用域仅针对带有名称空间的对象,例如 Deployment、Service 等, 这种作用域对集群访问的对象不适用,例如 StorageClass、Node、PersistentVolume 等。
默认的名称空间
[root@k8s-01 ~]# kubectl get namespace
NAME STATUS AGE
default Active 8d
kube-node-lease Active 8d
kube-public Active 8d
kube-system Active 8d
kubernetes-dashboard Active 4d21h
[root@k8s-01 ~]#
- default :默认名称空间,如果 Kubernetes 对象中不定义 metadata.namespace 字段,该对象将放
在此名称空间下 - kube-system :Kubernetes系统创建的对象放在此名称空间下
- kube-public :此名称空间自动在安装集群是自动创建,并且所有用户都是可以读取的(即使是那些
未登录的用户)。主要是为集群预留的,例如,某些情况下,某些Kubernetes对象应该被所有集群
用户看到。
如何使用名称空间
-
基于环境的隔离,(开发环境?测试环境?生产环境?)
-
基于产品线的名称空间隔离,(安卓?ios?)
-
基于团队的隔离
如何创建?
老办法了
-
kubectl create namespace test1 --dry-run=client -oyaml
-
得到输出内容
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: null
name: test1
spec: {}
- 根据内容创建2个名称空间
##第一个
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: null
name: test1
spec: {}
##第二个
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: null
name: test2
spec: {}
##创建
kubectl apply -f test1.yaml
kubectl apply -f test2.yaml
- 分别在这2个名称空间部署一次
## test1
kind: Pod
apiVersion: v1
metadata:
name: nginx-demo-pod
namespace: test1 #不写就是default
spec: # 指定期望状态
containers: # 指定要启动一个什么样的容器
- image: nginx # 指定镜像
name: nginx-demo-pod # 指定容器名称
## test2
kind: Pod
apiVersion: v1
metadata:
name: nginx-demo-pod
namespace: test2 #不写就是default
spec: # 指定期望状态
containers: # 指定要启动一个什么样的容器
- image: nginx # 指定镜像
name: nginx-demo-pod # 指定容器名称
##分别部署
kubectl apply -f test1.yaml
kubectl apply -f test2.yaml
测试不同名称空间的网络互通情况
- pod 之间应该是可以互通的
查询k8s 资源是否存在名称空间
# 存在名称空间的资源输出
kubectl api-resources --namespaced=true
# 不存在名称空间的资源输出
kubectl api-resources --namespaced=false
- 其实就是
kubectl api-resources
的【NAMESPACED】字段为:true/false