API 资源组成
,SSA
和CSA
资源操作方式,以及资源类别
工作负载,服务,配置和存储,认证,鉴权,策略,扩展,集群 等简单描述整理这部分笔记,在找 K8s干扰预算
相关笔记的时候,突然看到那篇笔记末尾之前摘的一句话; "我曾以为总有一天,我能够改变一些什么,可当我看见她渐渐淹没在人海的时候,我才明白,我们这一生除了相遇大概注定一事无成了。 ——网易云" 。似水流年,却未曾三十而立...
官方文档位置:
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/
在 k8s 体系中,把涉及部署环境,自动化运维相关所有行为、实体抽象为 API 对象,用对应的 API 对象来表示相关的容器化应用部署行为,或者叫动作实体
。
比如抽象出Pod
API 来表示一组在共享网络(IP)、存储和计算资源的环境下运行的容器,这里实际上是抽象了多个容器化应用部署在一个逻辑主机
的环境中。
通过 抽象出Service
API 来表示一个高可用的服务,不同的Service
类型对应的不同的服务发布方式,。
通过抽象deploy
API 来描述一个 高可用集群环境的部署行为
,
通过 ReplicaSet
来表示一个任何时候都能保持副本数不变的集群的行为。
在 K8s中 一个常见的 API 对象由下面四部分构成:
ResourceKind、Version
: 这是关于 API 资源的类型和版本说明apiVersion: v1
kind: Pod
ResourceMeta
: 这是关于资源的元数据,名称、所属命名空间、注释和标签,从属关系等。metadata:
creationTimestamp: null
labels:
run: pod-static
name: pod-static
namespeace: default
ResourceSpec
: 这是由用户定义的,描述资源的期望状态。在创建或更新一个对象时填写这个。spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod-demo
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
......
ResourceStatus
: 这是由服务动态生成的,用于描述API对象当前状态。在大多数情况下,用户不需要改变这个。status:
phase: Running
conditions:
- type: Initialized
status: 'True'
lastProbeTime: null
lastTransitionTime: '2023-02-18T14:46:54Z'
- type: Ready
status: 'True'
lastProbeTime: null
lastTransitionTime: '2023-02-18T14:54:04Z'
- type: ContainersReady
status: 'True'
lastProbeTime: null
lastTransitionTime: '2023-02-18T14:54:04Z'
- type: PodScheduled
status: 'True'
lastProbeTime: null
lastTransitionTime: '2023-02-11T04:11:46Z'
hostIP: 192.168.26.105
podIP: 10.244.169.101
podIPs:
- ip: 10.244.169.101
startTime: '2023-02-11T04:11:46Z'
..................
通过上面的组成,可以很直观的体会到 K8s声明式的操作风格
,告诉系统我们需要什么,而不是告诉系统你需要做什么,使用kubectl apply
创建指定配置文件所定义的所有对象。通常,此配置文件采用yaml
进行描述。也就是我们上面的4部分。
声明式操作在分布式系统中的好处是稳定,不怕丢操作或运行多次。例如,设置副本数为3
的操作运行多次也还是一个结果,而通过kubectl
给副本数加1的操作就不是声明式的,指令或者命令式运行多次结果不一样。
API 资源对象的基本操作分为4
类,即传统的增删改查。
kubectl create -f deployment.yaml
。替换(Replace)
和修补(Patch)
。
需要用户提供完整的资源定义
。如果在读取和写入之间资源被修改,那么乐观锁定失败将会发生只有在满足一定更新要求之后才会被更新
。注意,ResourceStatus将被系统忽略,不会被更新。要更新状态,必须调用特定的状态更新操作。替换资源对象可能不会立即导致更改传播到下游对象。对上游资源(如ConfigMap
或Secret
)所做的更改可能不会立即反映到依赖于它们的下游对象(如Pods
)中.kubectl replace -f deployment.yaml
更改的合并方式是按字段定义的
。列表可以被替换或合并
。修补从不会导致乐观锁定失败
,后写入将胜出。当在更新之前没有读取完整状态,或者不希望在乐观锁定失败时失败的情况下,建议使用修补。乐观锁定
:乐观锁定是一种并发控制策略,它允许多个用户或进程同时修改资源,但在提交更改时会检查资源版本是否已被其他用户修改,当乐观锁定
失败时,Kubernetes 会阻止更新操作并返回错误。用户需要获取最新的资源版本并再次尝试更新操作,或者使用--force
或--force-conflicts
标志强制更新(谨慎使用)
获取(Get)
、列出(List)
和监视(Watch)
。
kubectl get pods productpage-v1-979d4d9fc-k88z7
。kubectl get pods
kubectl get pods -A
。kubectl get pods -w
。kubectl delete pods reviews-v1-569db879f5-hdx2h
,删除特定资源,服务器可能会或可能不会对子对象进行垃圾收集,比如删除一个Deployment
资源时,默认情况下,Kubernetes
会自动删除由该Deployment
创建的所有Pod
子对象。然而,在某些情况下,您可能希望保留这些子对象,而不是让它们被垃圾收集。在这种情况下,您可以使用--cascade=orphan
选项来删除 Deployment,同时保留其子对象kubectl rollout undo deployment/my-deployment
。kubectl get deployment my-deployment -o jsonpath='{.spec.replicas}'/ kubectl scale deployment my-deployment --replicas=5
kubectl get deployment my-deployment -o jsonpath='{.status.availableReplicas}'
这些操作允许用户灵活地控制资源的创建、更新、读取和删除。实际上通过命令行方式,我们用的最多的是apply ,即应用操作,一般直接指定 声明文件。
kubectl apply
用于创建或更新资源配置,具有更高的灵活性和并发处理能力;默认情况下,使用Client-Side Apply
的处理方式
可以创建新的资源,还可以更新现有的资源。当管理员或开发者对资源的配置进行修改后,可以使用此命令将更改应用到集群中。
kubectl apply
会根据提供的配置文件创建新的资源。补丁(patch)
,然后将补丁发送到 Kubernetes API 服务器以应用更改。这种特性使得kubectl apply
成为在Kubernetes中创建和更新资源的统一方法。
kubectl apply
还具有一种称为Server-Side Apply
的特性。当多个用户或进程同时修改同一资源
时,Kubernetes 会在服务器端处理并发更新,以确保资源的一致性。
要使用 Server-Side Apply,只需在kubectl apply
命令中添加--server-side
标志。例如:
kubectl apply -f deployment.yaml --server-side
通过kubectl apply -f rs.yaml
的方式,使用的是Client-Side Apply
的方式, 要使用Server-Side Apply
,需在kubectl apply
命令中添加--server-side
标志。例如:
kubectl apply -f deployment.yaml --server-side
Server-Side Apply
是Kubernetes 1.14
版本引入的新特性,并在后续版本中得到了改进。在使用 Server-Side Apply 时,请确保您的 Kubernetes 集群和 kubectl 客户端版本支持此特性。1.16
版本为 beta,到1.18
版本beta2
,在1.22V
升级为GA
。
如何区分资源操作是CSA
还是SSA
CSA
在使用kubectl apply
进行Client-Side Apply
时,kubectl
会自行填充元数据注解kubectl.kubernetes.io/last-applied-configuration
。
下面为通过kubectl
工具 直接kubectl apply -f vs.yaml
创建的VS,kubectl.kubernetes.io/last-applied-configuration
为 kubectl 客户端自行填充。
liruilong@liruilongdeMacBook-Air .kube % kubectl get vs -n defalut m-liruilong-online-vs -o yaml --show-managed-fields
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.istio.io/v1beta1","kind":"VirtualService","metadata":{"annotations":{},"name":"m-liruilong-online-vs","namespace":"defalut"},"spec":{"gateways":["istio-system/gw-any-liruilong-online"],"hosts":["m.liruilong.online"],"http":[{"match":[{"uri":{"prefix":"/"}}],"route":[{"destination":{"host":"share-web-svc.defalut.svc.cluster.local","port":{"number":8083}}}]}]}}
creationTimestamp: "2024-11-11T12:40:54Z"
generation: 3
managedFields:
- apiVersion: networking.istio.io/v1beta1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:kubectl.kubernetes.io/last-applied-configuration: {}
f:spec:
.: {}
f:gateways: {}
f:hosts: {}
f:http: {}
manager: kubectl-client-side-apply
operation: Update
time: "2024-11-11T17:49:04Z"
name: m-liruilong-online-vs
namespace: defalut
resourceVersion: "16170709"
uid: 1b772566-d540-459e-9b2d-3b42f5d7e088
spec:
........
liruilong@liruilongdeMacBook-Air .kube %
这个注解主要用于标识哪些字段是通过 kubectl apply 来管理的,kubectl
会将本次apply
的配置文件全量的记录在last-applied-configurationannotation
中。
前面我们有讲,当apply
一个对象,如果该对象不存在,则创建它(同时写入last-applied-configuration
)。如果对象已经存在,则kubectl
需要根据以下三个状态计算出patch
报文,通过patch
方式进行更新(patch 更新特定字段,避免乐观锁定)。
修改对象前先Get一次
)apply
的配置。apply
的配置。 (在last-applied-configuration
里)patch报文
的计算方法如下:
计算要删除的字段
,即在last-applied-configuration
中存在但在配置文件中不再存在的字段,同时对于本地对象配置文件中显式设置为空的字段,清除其在现时配置中的设置, 无论这些字段是否出现在last-applied-configuration
中计算要添加或设置的字段
,即在配置文件中存在但其取值与现时配置不同的字段。设置现时配置的值之后设置last-applied-configuration
注解的内容,使之与配置文件匹配。将前面步骤得出的结果合并,构成向 API 服务器发送的补丁(patch)
请求内容。
详细可以参考官方文档的Demo:
https://kubernetes.io/zh-cn/docs/tasks/manage-kubernetes-objects/declarative-config/
SSA
使用 kubectl 进行Server-Side Apply
操作,需要显示指定,
要使用Server-Side Apply
,只需在kubectl apply
命令中添加--server-side
标志。
kubectl apply -f deployment.yaml --server-side
同时会在元数据中添加managedFields
字段,。managedFields
的出现导致kubectl get xxx -oyaml | json
的输出变得非常冗长,难以阅读。 这个问题在v1.20
版本中得到优化,使用v1.20+
版本的kubectl
将默认不显示managedFields
下面的cm
即通过SSA
来 apply
的资源
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test-cm
namespace: default
labels:
test-label: test
managedFields:
- manager: kubectl
operation: Apply # 注意大写: “Apply” (或者 “Update”)
apiVersion: v1
time: "2010-10-10T0:00:00Z"
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels:
f:test-label: {}
f:data:
f:key: {}
data:
key: some value
根据以上输出的yaml
的metadata.managedFields
字段,我们不难得出它想表达的含义:该configmap
中data.key
字段都是由kubectl
来管理的。manager: kubectl
为 kubectl ,如果最后更改该字段的请求是服务器端应用的patch
操作,则operation
的值为 Apply;否则为 Update。
下面这个 deploy 是通过在阿里云上通过面板工具创建的,所以manager: okhttp
可以看到 通过 API 来操作资源也是使用过的Server-Side Apply
的方式, 并且管理的对象为整个资源对象
管理器(manager)
识别出正在修改对象的工作流程(在冲突时尤其有用), 并且可以作为修改请求的一部分,通过 manager 查询参数来指定。 当你Apply
某个资源时,需要指定manager
参数。 对于其他更新,API 服务器使用 “User-Agent:” HTTP 头(如果存在)推断字段管理器标识(为什么是 okhttp)。
字段管理(field management)
机制追踪对象字段的变化。 当一个字段值改变时,其所有权从当前管理器(manager)转移到施加变更的管理器。
当尝试将新配置应用到一个对象时,如果字段有不同的值,且由其他管理器管理, 将会引发冲突。冲突引发警告信号:此操作可能抹掉其他协作者的修改
。
冲突可以被刻意忽略
,这种情况下,值将会被改写,所有权也会发生转移
。
当你使用kubectl
工具执行服务器端应用操作时,kubectl
默认情况下会将管理器标识设置为kubectl
。下面的 yaml 中存在多个管理器的对象,
liruilong@liruilongdeMacBook-Air .kube % kubectl get deploy ams-hotel-cloudr-server -n defalut -o yaml --show-managed-fields
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "19"
creationTimestamp: "2024-11-08T07:32:43Z"
generation: 27
labels:
app: ams-hotel-cloudr-server
managedFields:
- apiVersion: apps/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations: {}
f:labels:
.: {}
f:app: {}
f:spec:
f:progressDeadlineSeconds: {}
f:replicas: {}
f:revisionHistoryLimit: {}
f:selector: {}
f:strategy:
f:rollingUpdate:
.: {}
f:maxSurge: {}
f:maxUnavailable: {}
f:type: {}
f:template:
f:metadata:
f:labels:
.: {}
f:app: {}
f:spec:
f:containers:
k:{"name":"ams-hotel-cloudr-server"}:
.: {}
f:env:
.: {}
k:{"name":"TZ"}:
.: {}
f:name: {}
f:value: {}
f:image: {}
f:imagePullPolicy: {}
f:name: {}
f:ports:
.: {}
k:{"containerPort":8080,"protocol":"TCP"}:
.: {}
f:containerPort: {}
f:protocol: {}
f:resources:
.: {}
f:requests:
.: {}
f:cpu: {}
f:memory: {}
f:terminationMessagePath: {}
f:terminationMessagePolicy: {}
f:dnsPolicy: {}
f:imagePullSecrets:
.: {}
k:{"name":"acck"}: {}
f:restartPolicy: {}
f:schedulerName: {}
f:securityContext: {}
f:terminationGracePeriodSeconds: {}
manager: okhttp
operation: Update
time: "2024-11-21T09:49:35Z"
- apiVersion: apps/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
f:deployment.kubernetes.io/revision: {}
f:status:
f:availableReplicas: {}
f:conditions:
.: {}
k:{"type":"Available"}:
.: {}
f:lastTransitionTime: {}
f:lastUpdateTime: {}
f:message: {}
f:reason: {}
f:status: {}
f:type: {}
k:{"type":"Progressing"}:
.: {}
f:lastTransitionTime: {}
f:lastUpdateTime: {}
f:message: {}
f:reason: {}
f:status: {}
f:type: {}
f:observedGeneration: {}
f:readyReplicas: {}
f:replicas: {}
f:updatedReplicas: {}
manager: kube-controller-manager
operation: Update
subresource: status
time: "2024-11-21T09:49:44Z"
name: ams-hotel-cloudr-server
namespace: defalut
resourceVersion: "21530560"
uid: c9fb0c9c-2129-4ffe-9675-96e01c396289
spec:
.....
liruilong@liruilongdeMacBook-Air .kube %
可以看到两个update
操作,一个由okhttp
管理器操作,主要进行基础资源的定义,第二个由kube-controller-manager
管理器操作,进行一些元数据添加,主要为status
字段的添加。两个管理器没有直接的冲突。
这部分更多信息小伙伴可以官网了解;
https://kubernetes.io/zh-cn/docs/reference/using-api/server-side-apply/
当apply
改变一个字段时,而恰巧该字段被其他用户声明了,此时会发生冲突。 这可以防止一个管理者不小心覆盖掉其他用户设置的值。
参考博客Demo:
https://juejin.cn/post/7173328614644006942
如果修改我们刚刚通过SSA创建的test-server-side-applyconfigmap
,并且手动设置管理者为test(通过--field-manager字段),此时kubectl会拒绝我们的提交,提示冲突:
$ kubectl apply --server-side=true --field-manager="test" -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: test-server-side-apply
data:
a: "a"
# 把b,改成c了。
b: "c"
EOF
error: Apply failed with 1 conflict: conflict with "kubectl": .data.b
Please review the fields above--they currently have other managers. Here
are the ways you can resolve this warning:
* If you intend to manage all of these fields, please re-run the apply
command with the `--force-conflicts` flag.
* If you do not intend to manage all of the fields, please edit your
manifest to remove references to the fields that should keep their
current managers.
* You may co-own fields by updating your manifest to match the existing
value; in this case, you'll become the manager if the other manager(s)
stop managing the field (remove it from their configuration).
See https://kubernetes.io/docs/reference/using-api/server-side-apply/#conflicts
从kubectl返回的提示,我们可以得知当冲突发生的时我们有三种选择:
覆盖前值
,成为当前字段的唯一管理者——通过增加--force-conflicts
flag不覆盖前值
,放弃管理权——在本次配置中,把修改的字段删掉(本例中是data.b
)不覆盖前值
,成为共享管理者——把冲突值改成和服务器对象一致工作负载资源负责管理和运行集群中的容器
。容器
是由控制器
通过Pod
创建的。Pods
运行容器并提供环境依赖,如共享网络环境,持久性存储卷和配置或注入容器密码数据。
Deployments
用于无状态的持久性应用(如HTTP服务器)
。它可以实现Pod
和ReplicaSets
的声明式更新。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
template
字段用于声明Pod 模版,selector
用于约束 Pod 的选择器,replicas
为副本数
StatefulSets
用于有状态的持久化应用(如数据库)。 为Pod
提供持久存储
和持久标识符
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
minReadySeconds: 10 # by default is 0
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: registry.k8s.io/nginx-slim:0.24
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "my-storage-class"
resources:
requests:
storage: 1Gi
在 StatefulSets中,serviceName
字段是必须的,它指定了一个Headless Service
的名称,该Service
为StatefulSet
中的每个Pod提供了一个稳定的DNS名称和网络身份
volumeClaimTemplates
字段也是必须的,允许你为Pod
定义PersistentVolumeClaims(PVC)
模板。这为每个Pod 提供了独立的持久化存储
HorizontalPodAutoscaler (HPA)
根据负载自动扩展工作负载的副本数量.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
根据需要自动调整 Pod 的数量,最少保持一个 Pod 在运行,最多可以扩展到 10 个 Pod,当平均 CPU 利用率
超过50%
时触发伸缩操作
ControllerRevision
保存特定控制器版本的状态信息。ControllerRevision
实现了状态数据的不可变快照。客户端负责序列化和反序列化对象,包含对象内部状态。 成功创建ControllerRevision
后,将无法对其进行更新。 API 服务器将无法成功验证所有尝试改变 data 字段的请求。 但是,可以删除ControllerRevisions
。 请注意,由于DaemonSet
和StatefulSet
控制器都使用它来进行更新和回滚,所以这个对象是Beta
版。
apiVersion: apps/v1
kind: ControllerRevision
metadata:
name: example-controllerrevision
namespace: default
labels:
app: example-app
spec:
revision: 2
selector:
matchLabels:
app: example-app
template:
metadata:
labels:
app: example-app
spec:
containers:
- name: example-container
image: nginx:1.16.1
ports:
- containerPort: 80
Jobs/CronJob
用于(周期)运行完成的应用程序的Job(如批处理Job),类似定时任务,只是线程变成了 Pod
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
周期性Job
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "* * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
restartPolicy
定义了当Pod
失败时应该如何处理
DaemonSet
用于节点守护应用
,确保全部(或者某些)节点上运行一个Pod
的副本。类似守护进程一样,当节点存在对应的Pod
就会存在
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: kube-system
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
tolerations:
# these tolerations are to have the daemonset runnable on control plane nodes
# remove them if your control plane nodes should not run pods
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
# it may be desirable to set a high priority class to ensure that a DaemonSet Pod
# preempts running Pods
# priorityClassName: important
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
一般会结合亲和性做一些配置,用于集群监控,收集每个节点的指标数据,或者网络代理等。
ReplicaSet
ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。 一般不会主动创建
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
# modify replicas according to your case
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: php-redis
image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5
ReplicationController
在k8s之前的版本用于无状态应用部署,现在推荐使用deployment
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
Pod
简单讲,Pod为一组容器,这组容器共享存储,网络,命名空间以及运行容器的一些声明,是在 K8s 中创建管理的最小的可部署的计算单元, Pod 所建模的是特定于应用的 “逻辑主机”。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Binding
Binding 将一个对象与另一个对象绑定在一起;例如,调度程序将一个 Pod 绑定到一个节点。1.7
版中已弃用
PodTemplate
定义Pod模板。
Container
单个容器,容器只能在Pod 中创建,通常通过 控制器来完成,单个 Pod 中的容器会在共同调度下,于同一位置运行在相同的节点上。
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
PodSchedulingContext
控制Pod调度相关的资源。PodSchedulingContext
对象包含使用 "WaitForFirstConsumer" 分配模式的ResourceClaims
来调度Pod
所需的信息。
关于动态资源
部分,当前1.31 版本中,需要显式启用,动态资源分配是一个用于在 Pod 之间和 Pod 内部容器之间请求和共享资源的 API
。我没怎么接触,这里不做整理,感兴趣小伙伴可以看看官网文档。
https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/dynamic-resource-allocation/
PriorityClass
定义Pod
优先级。在一个并非所有用户都是可信的集群中,恶意用户可能以最高优先级创建 Pod, 导致其他 Pod 被驱逐或者无法被调度。 管理员可以使用 ResourceQuota 来阻止用户创建高优先级的 Pod
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000 # 优先级值
globalDefault: false # 不是全局默认优先级
description: "此优先级类应仅用于 XYZ 服务 Pod。"
没有指定preemptionPolicy
,因此在默认情况下,如果集群资源不足,使用这个优先级类的 Pod 可能会抢占(驱逐)低优先级的 Pod 以获取所需的资源。
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority-nonpreempting
value: 1000000
preemptionPolicy: Never #使用这个优先级类的 Pod 永远不会抢占(驱逐)其他 Pod
globalDefault: false
description: "This priority class will not cause other pods to be preempted."
创建Pod
,并将其priorityClassName
设置为新增的PriorityClass
。
服务资源负责将你的工作负载
拼接成一个可访问的负载均衡服务
。默认情况下,工作负载只能在集群内访问,外部访问必须使用LoadBalancer
或NodePort
服务在外部公开。
Service
用于在多个工作负载副本中提供单一端点
负载平衡。并且提供相同的访问方式。在集群中通过DNS 访问
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
Ingress
简单讲,类似一个反向代理,可以理解为Haproxy
或者Nginx
,一个规则集合,对集群中服务的外部访问进行管理的 API 对象,允许入站连接到后端定义某个端点。提供一个https(s)
端点路由到一个或多个服务。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-ingress
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
元数据中的annotations
字段nginx.ingress.kubernetes.io/rewrite-target
用于指定路由跳转,所有匹配/testpath
前缀的请求在转发到后端服务时,其 URL 路径被重写为/
ingressClassName: 用于明确指定 Ingress 类,即提供能力的后端控制器,Kubernetes 1.18 及更高版本中引入的字段,在低版本中一般会在元数据的注解中声明kubernetes.io/ingress.class: "nginx"
用于指定 Ingress 控制器。
这里需要注意使用Ingress
进行负载分发时,Ingress Controller
基于Ingress
规则将客户端请求直接转发到Service
对应的后端Endpoint (Pod)
上,这样会跳过kube-proxy
的转发功能,kube-proxy
不再起作用。如果IngressController
提供的是对外服务,则实际上实现的是边缘路由器的功能。
其他资源类型:
Endpoints
是实现实际服务的后端Pod端点的集合。1.21 以及之后的版本,Endpoints
同时会生成EndpointSlicp
apiVersion: v1
kind: Endpoints
metadata:
creationTimestamp: "2024-11-11T02:14:27Z"
name: ams-hotel-xxl-job-svc
namespace: smart-campus
resourceVersion: "18254844"
uid: 4f5b5662-5c7a-48ad-a386-49a5ecfbde7c
subsets:
- addresses:
- ip: 172.27.99.11
nodeName: cn-huhehaote.10.1.20.40
targetRef:
kind: Pod
name: ams-hotel-xxl-job-74c66f67bd-fjz4x
namespace: smart-campus
uid: 8948324e-0289-4a04-8a2d-7174252b011c
ports:
- port: 8888
protocol: TCP
EndpointSlice
代表实现服务的后端Pod端点的一个子集。当Endpoints
超过100个,会形成新的 EndpointSlice
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: example-abc
labels:
kubernetes.io/service-name: example
addressType: IPv4
ports:
- name: http
protocol: TCP
port: 80
endpoints:
- addresses:
- "10.1.2.3"
conditions:
ready: true
hostname: pod-1
nodeName: node-1
zone: us-west2-a
Ingress controller
Ingress
资源的后端实现,集群必须有一个正在运行的 Ingress 控制器。可以理解为 Ingress 的后端,提供实际的负载能力,
以Ingress-nginx
为Demo,实际上就是一个集群中的的流量入口,本质是上一个 Nginx 无状态控制器 作反向代理,可以配置路由规则。
IngressClass
IngressClass 表示 Ingress 的类别,由 Ingress Spec 引用。指定实现的Ingress Controller
名称,建立Ingress 和 Ingress controller 之间的关系。
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx-ingress
labels:
app: nginx-ingress
spec:
controller: k8s.io/ingress-nginx
parameters:
apiGroup: k8s.io
kind: IngressParameters
name: default-backend-parameters
服务资源负责将你的工作负载
拼接,通过环境变量、命令行参数或文件注入
到应用程序中。
常见的资源类型:
ConfigMap
持有供pod
使用的配置数据。对应实际应用中的配置文件,它提供文本键值对
,通过环境变量
、命令行参数
或文件
注入到应用程序中。
apiVersion: v1
kind: ConfigMap
metadata:
name: game-demo
data:
# property-like keys; each key maps to a simple value
player_initial_lives: "3"
ui_properties_file_name: "user-interface.properties"
# file-like keys
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
Secrets
保存某种类型的秘密数据。它提供二进制数据,通过文件注入到应用程序中。对应实际应用中的密码,连接串等数据。
apiVersion: v1
kind: Secret
metadata:
name: dotfile-secret
data:
.secret-file: dmFsdWUtMg0KDQo=
---
apiVersion: v1
kind: Pod
metadata:
name: secret-dotfiles-pod
spec:
volumes:
- name: secret-volume
secret:
secretName: dotfile-secret
containers:
- name: dotfile-test-container
image: registry.k8s.io/busybox
command:
- ls
- "-l"
- "/etc/secret-volume"
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
Volumes
用于提供容器外部的文件系统
。可能在同一Pod
内的不同容器之间共享
,并具有超越容器或Pod的持久性。不作为一个单独的API 存在,有多种后端实现
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: test
image: busybox:1.28
command: ['sh', '-c', 'echo "The app is running!" && tail -f /dev/null']
volumeMounts:
- name: config-vol
mountPath: /etc/config
volumes:
- name: config-vol
configMap:
name: log-config
items:
- key: log_level
path: log_level
在Pod
中通过volumes
挂载上面的configMap
PersistentVolumeClaim(PVC)
PersistentVolumeClaim(PVC)
是一种声明式方式来请求存储资源。它允许用户以一种与特定存储后端无关
的方式请求存储空间,而不需要了解底层存储的具体实现细节,PV,PVC
和SC
和LVM
的思想有些类似,化零为整,动态分配
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
storageClassName: slow
selector:
matchLabels:
release: "stable"
matchExpressions:
- {key: environment, operator: In, values: [dev]}
PersistentVolume(PV)
是一个由管理员提供的存储资源。直接映射到每个Pod
,代表集群中的一块持久化存储空间。PV
可以由管理员预先创建,也可以由存储类(Storage Class)
动态创建。PV ,PVC 之类属于集群资源,不基于命名空间隔离
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0003
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp
server: 172.17.0.2
StorageClass
描述了一个可以动态配置PersistentVolumes
的存储类别的参数。用户可以通过指定 Storage Class 来选择不同的存储后端,如云提供商的存储服务、本地存储、网络存储等
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: example-vol-default
provisioner: vendor-name.example/magicstorage
parameters:
resturl: "http://192.168.10.100:8080"
restuser: ""
secretNamespace: ""
secretName: ""
allowVolumeExpansion: true
VolumeAttachment
VolumeAttachment
抓取将指定卷
挂接到指定节点
或从指定节点解除挂接指定卷
的意图,VolumeAttachment
对象未划分命名空间。
表示一个卷(通常是持久卷 Persistent Volume,PV)被绑定到某个节点的状态,确保卷在 Pod 需要时已挂载在指定节点,便于后续 CSI 驱动程序将其挂载到容器中,维护卷和节点的绑定关系,记录卷在哪些节点上可用
apiVersion: storage.k8s.io/v1
kind: VolumeAttachment
metadata:
annotations:
csi.alpha.kubernetes.io/node-id: test-vpc-k8s-worker06
# 注解中指定了 node-id,用来表明该 VolumeAttachment 所属的节点;这有助于 CSI 驱动定位挂载目标节点
finalizers:
- external-attacher/evs-csi-huawei-cn
# 这里 external-attacher/evs-csi-huawei-cn 表示该卷在删除前需要由 evs-csi-huawei-cn 驱动的 external-attacher 进行卸载操作
# 只有在 ControllerUnpublishVolume 成功完成并移除 finalizer 后,VolumeAttachment 才会真正被删除
name: csi-0dc8eaebe8d1f7dc6e035ec06be0dc926f17e7da71edda5fe7a0cdda34d774bc
# csi-0dc8eaebe8d1f7dc6e035ec06be0dc926f17e7da71edda5fe7a0cdda34d774bc VolumeAttachment 对象的名称;
# 通常由 CSI 驱动生成一个唯一的 ID,用于标识此挂载请求
spec:
attacher: evs-csi-huawei-cn
# 用于指定 CSI 驱动的名称,表明哪个驱动程序负责处理此挂载请求
nodeName: test-vpc-k8s-worker06
# 指定将卷挂载到的节点名称
source:
persistentVolumeName:pvc-19ea9ae8-8b42-45ad-9bcf-7ba216c1c87c
status:
# 表示挂载状态,通常由 CSI 驱动更新
attached: true
# 布尔值,表示卷是否已成功挂载
attachmentMetadata:
# 可选字段,包含 CSI 驱动在挂载过程中生成的元数据(例如设备路径)
evs-csi-huawei-cn/volume-name:pvc-19ea9ae8-8b42-45ad-9bcf-7ba216c1c87c
VolumeAttributesClass
存储类资源(StorageClass)
的补充,用来控制存储卷的行为,比如性能参数、备份策略等
apiVersion: storage.k8s.io/v1beta1
kind: VolumeAttributesClass
metadata:
name: silver
driverName: pd.csi.storage.gke.io
parameters:
provisioned-iops: "3000"
provisioned-throughput: "50"
------
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: example-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
volumeAttributesClassName: example-va-class
provisioned-iops
:指定预配置的IOPS(每秒输入/输出操作数)为3000
CSIDriver
捕获有关部署在集群上的容器存储接口(CSI)卷驱动器的信息。使用CSIDriver资源来注册和管理CSI驱动程序,确保驱动程序与Kubernetes API服务器正确交互。一般由存储厂商实现
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: my-csi-driver
spec:
attachRequired: true
podInfoOnMount: true
volumeLifecycleModes:
- Persistent
storageCapacity: true
topologyAware: true
StorageVersionMigration
StorageVersionMigration
表示存储的数据向最新存储版本的一次迁移。这里的版本是只apiVersion: v1
中的版本
kind: StorageVersionMigration
apiVersion: storagemigration.k8s.io/v1alpha1
metadata:
name: secrets-migration
spec:
resource:
group: ""
version: v1
resource: secrets
如果你想迁移secrets资源 到 V1 版本
下面API 资源用于身份认证
,
TokenRequest
TokenRequest 为给定的服务账号SA
请求一个令牌
apiVersion: authentication.k8s.io/v1
kind: TokenRequest
spec:
audiences:
- "https://example.com" # 这里应该填写你希望令牌有效的受众(audience),通常是 API 服务器的地址或某个特定的服务
boundObjectRef:
apiVersion: v1
kind: ServiceAccount
name: your-service-account-name # 替换为你的服务账户名称
namespace: your-namespace # 替换为你的命名空间
expirationSeconds: 86400 # 令牌的过期时间(秒),默认为1小时(3600秒),这里设置为24小时
令牌可以用于身份验证和授权,以便访问 Kubernetes API 或其他需要身份验证的资源。
TokenReview
TokenReview 尝试通过验证令牌来确认已知用户
。 注意:TokenReview 请求可能会被 kube-apiserver 中的 webhook 令牌验证器插件缓存。
apiVersion: authentication.k8s.io/v1
kind: TokenReview
spec:
token: <YOUR_TOKEN_HERE>
apply 之后填充的数据
{
"apiVersion": "authentication.k8s.io/v1",
"kind": "TokenReview",
"status": {
"authenticated": true,
"user": {
"username": "system:serviceaccount:<your-namespace>:<your-service-account>",
"uid": "<uid>",
"groups": [
"system:serviceaccounts",
"system:serviceaccounts:<your-namespace>",
"system:authenticated"
],
"extra": {
"kubernetes.io/serviceaccount/namespace": [
"<your-namespace>"
],
"kubernetes.io/serviceaccount/secret.name": [
"<your-secret-name>"
],
"kubernetes.io/serviceaccount/secret.uid": [
"<secret-uid>"
],
"kubernetes.io/serviceaccount/name": [
"<your-service-account>"
]
}
}
}
}
如果authenticated
字段为true
,则表示令牌是有效的,并且响应中的user
字段包含了与该令牌关联的用户信息。
ServiceAccount
服务账号,用于为 Pod 提供相对于集群管理的身份验证凭据,简单来讲,用于为 Pod 提供访问集群的能力,Pod 中访问 集群需要做认证和授权,sa 通过 token 认证,通过 绑定的角色,基于RBAC 授权。
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: metallb
name: controller
namespace: metallb-system
SelfSubjectReview
SelfSubjectReview
包含kube-apiserver
所拥有的与发出此请求的用户有关的用户信息。
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectReview
在官方文档中,SelfSubjectReview
资源被归纳到身份认证资源
,而不是鉴权资源
。
可以看到具体的用户信息,所属的组,以及角色和权限
apiVersion: authentication.k8s.io/v1alpha1
kind: SelfSubjectReview
status:
userInfo:
username: jane.doe
uid: b79dbf30-0c6a-11ed-861d-0242ac120002
groups:
- students
- teachers
- system:authenticated
extra:
skills:
- reading
- learning
subjects:
- math
- sports
CertificateSigningRequest
用于请求签名证书。要创建一个指定权限的kubeconfig
文件的话,我们需要一个私钥
,以及集群CA
授权颁发的证书
。不能直接用私钥生成公钥
,而必须是用私钥生成证书请求文件(申请书)
,然后根据证书请求文件
向CA(权威机构)申请证书(身份证)
,CA 审核通过之后会颁发证书。
上面讲的 申请证书 即为CertificateSigningRequest
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: liruilong
spec:
signerName: kubernetes.io/kube-apiserver-client
request: LS0tLS1CRUdJTiBDRVJUSUZJ...............
usages:
- client auth
之后需要通过批准证书
kubectl certificate approve liruilong
ClusterTrustBundle
用于管理集群中的信任证书。ClusterTrustBundle 是一个集群范围
的容器,用于存放X.509 信任锚(根证书)
。 当前为v1alpha1
版本.
可以被集群中的任何经过身份验证的用户读取
apiVersion: certificates.k8s.io/v1alpha1
kind: ClusterTrustBundle
metadata:
name: example-trust-bundle
spec:
trustBundle: |
-----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgIThAOxVoDEnEXQfankuXrJestQDzANBgkqhkiG9w0BAQsF
ADAVMRMwEQYDVQQDEwpleGFtcGxlLmNvbTAeFw0xNTEyMTYwMTI1MjZaFw0yMDEy
MTUwMTI1MjZaMBUxEzARBgNVBAMTCmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEA7bYaCSHxc91o4LRXzxxtVufus1OqV6dMJFEKTIE5
z23f6BbQoiX4kS/ALCaRj+BPJj+IxstD7M0iDCHVH0jW43yDK2qai0FvgZPuD9vY
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDAzCCAeugAwIBAgIQCHMGwmqMm8SQR/vdxwIrODANBgkqhkiG9w0BAQsFADAV
MRMwEQYDVQQDEwpleGFtcGxlLmNvbTAeFw0xNTEyMTYwMTI1MjZaFw0yMDEyMTUw
MTI1MjZaMBUxEzARBgNVBAMTCmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEA7bYaCSHxc91o4LRXzxxtVufus1OqV6dMJFEKTIE5z23f
6BbQoiX4kS/ALCaRj+BPJj+IxstD7M0iDCHVH0jW43yDK2qai0FvgZPuD9vYKKGs
-----END CERTIFICATE-----
signerName: example.com/my-signer
SelfSubjectAccessReview
鉴权这部分资源API文档地址
https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/authorization-resources/
SelfSubjectAccessReview(SSAR)
检查当前用户是否可以执行某操作。 不填写spec.namespace
表示 “在所有命名空间中”。Self
是一个特殊情况,因为用户应始终能够检查自己是否可以执行某操作。
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectAccessReview
metadata:
name: check-create-pods-in-namespace
spec:
resourceAttributes:
namespace: "default" # 替换为你要检查的命名空间
verb: "create"
resource: "pods"
LocalSubjectAccessReview
LocalSubjectAccessReview(LSAR)
和SubjectAccessReview(SAR)
都是K8s
中用于权限检查的API对象,关键的区别在于作用域
不同:
SubjectAccessReview(SAR)
:用于检查集群范围
内的权限。它可以检查特定用户
或用户组
在集群中的任何命名空间
下是否有权执行特定操作。LocalSubjectAccessReview(LSAR)
:用于检查特定命名空间
内的权限。它只能检查在指定命名空间
下,特定用户
或用户组
是否有权执行特定操作。LocalSubjectAccessReview
检查用户或组是否可以在给定的命名空间
内执行某操作。
LocalSubjectAccessReview
与上面SelfSubjectAccessReview
区别是SelfSubjectAccessReview
是用于评估当前用户自身的权限
,self
这个关键字小伙伴们应该不陌生
SelfSubjectAccessReview
不需要指定主体,因为它默认评估当前用户
。LocalSubjectAccessReview
需要指定要评估的用户或组,即下面配置文件中user
和group
部分。
apiVersion: authorization.k8s.io/v1
kind: LocalSubjectAccessReview
spec:
subjectAccessReviewSpec:
resourceAttributes:
namespace: default
verb: get
group: apps
resource: deployments
user: alice
group:
- team-a
- team-b
上面的 Demo,用于检查用户alice
和组team-a
和team-b
是否有 命名空间 中 无状态应用的 get 权限.
apply
上面的资源声明,可以在status
的allowed
字段下看到是否拥有权限
status:
allowed: true
SubjectAccessReview
SubjectAccessReview
:检查一个用户在整个集群中的权限,无论在哪个命名空间下,你应该使用SAR
。
对于SubjectAccessReview(SAR)
,这里没有命名空间资源,意味着作用在所有的命名空间
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
metadata:
name: check-pods-list-cluster-wide
spec:
user: "example-user"
resourceAttributes:
verb: "list"
resource: "pods"
SelfSubjectRulesReview
SelfSubjectRulesReview(SSRR)
枚举当前用户可以在某命名空间内执行的操作集合。返回的操作列表可能不完整
,具体取决于服务器的鉴权模式以及评估过程中遇到的任何错误。
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectRulesReview
spec:
namespace: default
apply
之后返回的结果大概是这个样子
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectRulesReview
status:
evaluationError: ""
incomplete: false
nonResourceRules:
- apiGroups: [""]
nonResourceURLs: ["/healthz", "/version", "/openapi/*"]
verbs: ["get"]
resourceRules:
- apiGroups: ["apps", ""]
resourceNames: []
resources: ["deployments", "replicasets", "pods"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
Role
用于定义命名空间范围内的角色
角色(Role
) 一个角色就是一组权限的集合。在
同一个命名空间中,可以用Role来定义一个角色,如果是集群级别的,就需要使用
ClusterRole了`。角色只能对命名空间内的资源进行授权
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app: metallb
name: controller
namespace: metallb-system
rules:
- apiGroups:
- ''
resources:
- secrets
verbs:
- create
- apiGroups:
- ''
resources:
- secrets
resourceNames:
- memberlist
verbs:
- list
- apiGroups:
- apps
resources:
- deployments
resourceNames:
- controller
verbs:
- get
RoleBinding
RoleBinding
用来把一个角色绑定到一个目标上,绑定目标可以是User (用户) 、Group (组)或者Service Account
。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app: metallb
name: controller
namespace: metallb-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: controller
subjects:
- kind: ServiceAccount
name: controller
这里绑定到了 controller 这个 sa 上
ClusterRole
用于定义集群范围内的角色。ClusterRole
集群角色,基于RBAC
的鉴权,角色申明方式为资源+动作