学习理解 Kubernetes 代码实现
源码
- 1: 概述
- 2: 组件视角
- 2.1: API Server
- 2.2: Kube Scheduler
- 2.3: Kube Controller Manager
- 2.4: Kube Proxy
- 3: 仓库视角
- 3.1: api 仓库
- 3.1.1: 概述
- 3.1.2: admission
- 3.1.2.1: 概述
- 3.1.2.2: types.go
- 3.1.2.3: register.go
- 3.1.3: admissionregistration
- 3.1.3.1: 概述
- 3.1.3.2: types.go
- 3.1.3.3: register.go
- 3.1.4: apidiscovery
- 3.1.4.1: 概述
- 3.1.4.2: types.go
- 3.1.4.3: register.go
- 3.1.5: apiserverinternal
- 3.1.5.1: 概述
- 3.1.5.2: types.go
- 3.1.5.3: register.go
- 3.1.6: apps
- 3.1.6.1: 概述
- 3.1.6.2: types.go
- 3.1.6.3: register.go
- 3.1.7: authentication
- 3.1.7.1: 概述
- 3.1.7.2: types.go
- 3.1.7.3: register.go
- 3.1.8: authorization
- 3.1.8.1: 概述
- 3.1.8.2: types.go
- 3.1.8.3: register.go
- 4: API视角
- 4.1: pod
- 4.1.1: 概述
- 4.1.2: pod的定义
- 4.1.3: pkg\api\pod\util.go
- 4.1.3.1: ContainerType
- 4.1.3.2: ContainerVisitor
- 4.1.3.3: Visitor
- 4.1.3.4: PodCondition
- 4.1.3.5: ValidationOptions
- 4.1.3.6: Drop
- 4.1.4: pkg\api\pod\warnings.go
1 - 概述
1.1 - 组件
有哪些组件?
如何得知 k8s 有哪些组件?
看 k8s 进程
在 k8s 的 master 上,用 ps 命令查看 k8s 相关的进程:
ps -ef | grep -v kworker | grep -v nfs | grep -v nginx | grep -v pause | grep -v containerd | grep -v smbd | grep -v cpuhd | grep -v sshd | grep -v /usr/bin | grep -v /usr/sbin | grep -v scsi | grep -v /sbin
排除和k8s无关的进程,能看到:
root 1388 1299 0 May13 ? 00:04:25 kube-scheduler --authentication-kubeconfig=/etc/kubernetes/scheduler.conf --authorization-kubeconfig=/etc/kubernetes/scheduler.conf --bind-address=127.0.0.1 --kubeconfig=/etc/kubernetes/scheduler.conf --leader-elect=true
root 1398 1297 0 May13 ? 00:17:47 kube-apiserver --advertise-address=192.168.3.112 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/etc/kubernetes/pki/ca.crt --enable-admission-plugins=NodeRestriction --enable-bootstrap-token-auth=true --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --secure-port=6443 --service-account-issuer=https://kubernetes.default.svc.cluster.local --service-account-key-file=/etc/kubernetes/pki/sa.pub --service-account-signing-key-file=/etc/kubernetes/pki/sa.key --service-cluster-ip-range=10.96.0.0/12 --tls-cert-file=/etc/kubernetes/pki/apiserver.crt --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
root 1399 1295 0 May13 ? 00:08:55 etcd --advertise-client-urls=https://192.168.3.112:2379 --cert-file=/etc/kubernetes/pki/etcd/server.crt --client-cert-auth=true --data-dir=/var/lib/etcd --experimental-initial-corrupt-check=true --experimental-watch-progress-notify-interval=5s --initial-advertise-peer-urls=https://192.168.3.112:2380 --initial-cluster=k8s112=https://192.168.3.112:2380 --key-file=/etc/kubernetes/pki/etcd/server.key --listen-client-urls=https://127.0.0.1:2379,https://192.168.3.112:2379 --listen-metrics-urls=http://127.0.0.1:2381 --listen-peer-urls=https://192.168.3.112:2380 --name=k8s112 --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt --peer-client-cert-auth=true --peer-key-file=/etc/kubernetes/pki/etcd/peer.key --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt --snapshot-count=10000 --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
root 1401 1293 0 May13 ? 00:05:33 kube-controller-manager --allocate-node-cidrs=true --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf --bind-address=127.0.0.1 --client-ca-file=/etc/kubernetes/pki/ca.crt --cluster-cidr=10.244.0.0/16 --cluster-name=kubernetes --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt --cluster-signing-key-file=/etc/kubernetes/pki/ca.key --controllers=*,bootstrapsigner,tokencleaner --kubeconfig=/etc/kubernetes/controller-manager.conf --leader-elect=true --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt --root-ca-file=/etc/kubernetes/pki/ca.crt --service-account-private-key-file=/etc/kubernetes/pki/sa.key --service-cluster-ip-range=10.96.0.0/12 --use-service-account-credentials=true
root 3114 2988 0 May13 ? 00:00:07 /usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/config.conf --hostname-override=k8s112
root 5283 5118 0 May13 ? 00:00:39 /opt/bin/flanneld --ip-masq --kube-subnet-mgr
1001 8052 7828 0 May13 ? 00:00:06 /dashboard-auth
65532 8054 7829 0 May13 ? 00:00:51 /coredns -conf /etc/coredns/Corefile
1001 8069 7948 0 May13 ? 00:00:06 /dashboard-api --insecure-bind-address=0.0.0.0 --bind-address=0.0.0.0 --namespace=kubernetes-dashboard --metrics-scraper-service-name=kubernetes-dashboard-metrics-scraper
1001 8070 7940 0 May13 ? 00:00:05 /dashboard-metrics-scraper
sky 8072 7968 0 May13 ? 00:01:29 /metrics-server --cert-dir=/tmp --secure-port=10250 --kubelet-preferred-address-types=InternalIP --kubelet-insecure-tls --kubelet-use-node-status-port --metric-resolution=15s
1001 8073 7860 0 May13 ? 00:00:05 /dashboard-web --insecure-bind-address=0.0.0.0 --bind-address=0.0.0.0 --namespace=kubernetes-dashboard --settings-config-map-name=kubernetes-dashboard-web-settings
65532 8083 7937 0 May13 ? 00:00:53 /coredns -conf /etc/coredns/Corefile
这里面直接和k8s相关的进程有:
- coredns
- etcd
- kube-controller-manager
- kube-proxy
- kube-apiserver
- kube-scheduler
k8s 扩展之一的 dashboard:
- dashboard-api
- dashboard-metrics-scraper
- dashboard-web
- dashboard-auth
k8s 扩展之一的 metrics-server:
- metrics-server
看 k8s build 的产物
clone k8s 的源码:
https://github.com/kubernetes/kubernetes/
然后 build 一下:
git clone https://github.com/kubernetes/kubernetes
cd kubernetes
make
可以看到构建的日志:
+++ [0514 21:34:35] Building go targets for linux/amd64
github.com/onsi/ginkgo/v2/ginkgo (non-static)
k8s.io/apiextensions-apiserver (static)
k8s.io/component-base/logs/kube-log-runner (static)
k8s.io/kube-aggregator (static)
k8s.io/kubernetes/cluster/gce/gci/mounter (static)
k8s.io/kubernetes/cmd/kubeadm (static)
k8s.io/kubernetes/cmd/kube-apiserver (static)
k8s.io/kubernetes/cmd/kube-controller-manager (static)
k8s.io/kubernetes/cmd/kubectl (static)
k8s.io/kubernetes/cmd/kubectl-convert (static)
k8s.io/kubernetes/cmd/kubelet (non-static)
k8s.io/kubernetes/cmd/kubemark (static)
k8s.io/kubernetes/cmd/kube-proxy (static)
k8s.io/kubernetes/cmd/kube-scheduler (static)
k8s.io/kubernetes/test/conformance/image/go-runner (non-static)
k8s.io/kubernetes/test/e2e/e2e.test (test)
k8s.io/kubernetes/test/e2e_node/e2e_node.test (test)
构建的产物在 _output/bin 目录下,可以看到:
$ pwd
/home/sky/work/code/kubernetes/kubernetes/_output/bin
$ ls -la
total 1069404
drwxrwxr-x 2 sky sky 4096 May 14 21:34 .
drwxrwxr-x 3 sky sky 4096 May 14 20:50 ..
-rwxr-xr-x 1 sky sky 75759800 May 14 21:34 apiextensions-apiserver
-rwxr-xr-x 1 sky sky 117823416 May 14 21:34 e2e_node.test
-rwxr-xr-x 1 sky sky 126209360 May 14 21:34 e2e.test
-rwxr-xr-x 1 sky sky 10580260 May 14 21:34 ginkgo
-rwxr-xr-x 1 sky sky 2056484 May 14 21:34 go-runner
-rwxr-xr-x 1 sky sky 74133688 May 14 21:34 kubeadm
-rwxr-xr-x 1 sky sky 73158840 May 14 21:34 kube-aggregator
-rwxr-xr-x 1 sky sky 98341048 May 14 21:34 kube-apiserver
-rwxr-xr-x 1 sky sky 91111608 May 14 21:34 kube-controller-manager
-rwxr-xr-x 1 sky sky 59900088 May 14 21:34 kubectl
-rwxr-xr-x 1 sky sky 58917048 May 14 21:34 kubectl-convert
-rwxr-xr-x 1 sky sky 82080036 May 14 21:34 kubelet
-rwxr-xr-x 1 sky sky 1839288 May 14 21:34 kube-log-runner
-rwxr-xr-x 1 sky sky 80322744 May 14 21:34 kubemark
-rwxr-xr-x 1 sky sky 70992056 May 14 21:34 kube-proxy
-rwxr-xr-x 1 sky sky 70004920 May 14 21:34 kube-scheduler
-rwxr-xr-x 1 sky sky 1757368 May 14 21:34 mounter
可以看到,k8s 的组件有:
- apiextensions-apiserver
- kubeadm
- kube-aggregator
- kube-apiserver
- kube-controller-manager
- kubectl
- kubectl-convert
- kubelet
- kube-log-runner
- kubemark
- kube-proxy
- kube-scheduler
1.2 - 代码仓库
kubernetes/kubernetes
https://github.com/kubernetes/kubernetes
从它的 go.mod 文件可以看到,它依赖了大量的 k8s 的组件:
k8s.io/api v0.0.0
k8s.io/apiextensions-apiserver v0.0.0
k8s.io/apimachinery v0.0.0
k8s.io/apiserver v0.0.0
k8s.io/cli-runtime v0.0.0
k8s.io/client-go v0.0.0
k8s.io/cloud-provider v0.0.0
k8s.io/cluster-bootstrap v0.0.0
k8s.io/code-generator v0.0.0
k8s.io/component-base v0.0.0
k8s.io/component-helpers v0.0.0
k8s.io/controller-manager v0.0.0
k8s.io/cri-api v0.0.0
k8s.io/cri-client v0.0.0
k8s.io/csi-translation-lib v0.0.0
k8s.io/dynamic-resource-allocation v0.0.0
k8s.io/endpointslice v0.0.0
k8s.io/externaljwt v0.0.0
k8s.io/klog/v2 v2.130.1
k8s.io/kms v0.0.0
k8s.io/kube-aggregator v0.0.0
k8s.io/kube-controller-manager v0.0.0
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
k8s.io/kube-proxy v0.0.0
k8s.io/kube-scheduler v0.0.0
k8s.io/kubectl v0.0.0
k8s.io/kubelet v0.0.0
k8s.io/metrics v0.0.0
k8s.io/mount-utils v0.0.0
k8s.io/pod-security-admission v0.0.0
k8s.io/sample-apiserver v0.0.0
k8s.io/system-validators v1.9.1
k8s.io/utils v0.0.0-20250502105355-0f33e8f1c979
而这些又被 replace 到本地的 ./staging/src/k8s.io/ 目录下:
replace (
k8s.io/api => ./staging/src/k8s.io/api
k8s.io/apiextensions-apiserver => ./staging/src/k8s.io/apiextensions-apiserver
k8s.io/apimachinery => ./staging/src/k8s.io/apimachinery
k8s.io/apiserver => ./staging/src/k8s.io/apiserver
k8s.io/cli-runtime => ./staging/src/k8s.io/cli-runtime
k8s.io/client-go => ./staging/src/k8s.io/client-go
k8s.io/cloud-provider => ./staging/src/k8s.io/cloud-provider
k8s.io/cluster-bootstrap => ./staging/src/k8s.io/cluster-bootstrap
k8s.io/code-generator => ./staging/src/k8s.io/code-generator
k8s.io/component-base => ./staging/src/k8s.io/component-base
k8s.io/component-helpers => ./staging/src/k8s.io/component-helpers
k8s.io/controller-manager => ./staging/src/k8s.io/controller-manager
k8s.io/cri-api => ./staging/src/k8s.io/cri-api
k8s.io/cri-client => ./staging/src/k8s.io/cri-client
k8s.io/csi-translation-lib => ./staging/src/k8s.io/csi-translation-lib
k8s.io/dynamic-resource-allocation => ./staging/src/k8s.io/dynamic-resource-allocation
k8s.io/endpointslice => ./staging/src/k8s.io/endpointslice
k8s.io/externaljwt => ./staging/src/k8s.io/externaljwt
k8s.io/kms => ./staging/src/k8s.io/kms
k8s.io/kube-aggregator => ./staging/src/k8s.io/kube-aggregator
k8s.io/kube-controller-manager => ./staging/src/k8s.io/kube-controller-manager
k8s.io/kube-proxy => ./staging/src/k8s.io/kube-proxy
k8s.io/kube-scheduler => ./staging/src/k8s.io/kube-scheduler
k8s.io/kubectl => ./staging/src/k8s.io/kubectl
k8s.io/kubelet => ./staging/src/k8s.io/kubelet
k8s.io/metrics => ./staging/src/k8s.io/metrics
k8s.io/mount-utils => ./staging/src/k8s.io/mount-utils
k8s.io/pod-security-admission => ./staging/src/k8s.io/pod-security-admission
)
1.3 - API
k8s 的 API:
- pod
- replicationset
- service
- deployment
- job
- cronjob
- statefulset
- daemonset
- cronjob
2 - 组件视角
2.1 - API Server
2.2 - Kube Scheduler
2.3 - Kube Controller Manager
2.4 - Kube Proxy
3 - 仓库视角
staging 仓库
根目录下的 staging 目录是外部版本库暂存区,这些软件包已被拆分到各自的版本库中。这里的内容将定期发布到各自的顶级 k8s.io 仓库。
- k8s.io/api
- k8s.io/apiextensions-apiserver
- k8s.io/apimachinery
- k8s.io/apiserver
- k8s.io/cli-runtime
- k8s.io/client-go
- k8s.io/cloud-provider
- k8s.io/cluster-bootstrap
- k8s.io/code-generator
- k8s.io/component-base
- k8s.io/component-helpers
- k8s.io/controller-manager
- k8s.io/cri-api
- k8s.io/cri-client
- k8s.io/csi-translation-lib
- k8s.io/dynamic-resource-allocation
- k8s.io/endpointslice
- k8s.io/externaljwt
- k8s.io/kms
- k8s.io/kube-aggregator
- k8s.io/kube-controller-manager
- k8s.io/kube-proxy
- k8s.io/kube-scheduler
- k8s.io/kubectl
- k8s.io/kubelet
- k8s.io/metrics
- k8s.io/mount-utils
- k8s.io/pod-security-admission
3.1 - api 仓库
3.1.1 - 概述
api 信息
api 列表
- admission
- admissionregistration
- apidiscovery
- apiserverinternal
- apps
- authentication
- authorization
- autoscaling
- batch
- certificates
- coordination
- core
- discovery
- doc.go
- events
- extensions
- flowcontrol
- imagepolicy
- networking
- node
- policy
- rbac
- resource
- scheduling
- storage
- storagemigration
API 版本
大部分 api 都有多个版本,如:
- v1
- v1alpha1
- v1beta1
代码学习中,我们以 v1 版本为主。
api 代码结构
基本上每个 api 文件夹都有如下的文件列表:
- doc.go
- generated.pb.go
- register.go
- types.go
- types_swagger_doc_generated.go
- zz_generated.deepcopy.go
- zz_generated.prerelease-lifecycle.go
doc.go
这是包的文档文件,包含包的用途说明和基本的文档注释
通常会包含 +k8s:openapi-gen=true 这样的代码生成标记
定义了包的帮助文档和代码生成器的元数据。
打开看源码,发现除了 license 之外,只定义了 package 名字和该 package 相关的注解,如:
// +k8s:deepcopy-gen=package
// +k8s:protobuf-gen=package
// +k8s:openapi-gen=false
// +k8s:prerelease-lifecycle-gen=true
// +groupName=admission.k8s.io
package v1
generated.pb.go
generated.pb.go 是 Protocol Buffers 的生成文件(由 generated.proto 生成),包含了 AdmissionReview 等类型的 Protocol Buffers 序列化相关代码,用于 Kubernetes API 的 gRPC 通信和存储序列化。
代码都是从 generated.proto 文件生成的,没啥好看的,直接看 generated.proto 文件好了。
generated.proto
generated.proto 是Protocol Buffers 的定义文件,定义了当前 API 类型的 protobuf 消息格式。
generated.proto 文件会被 protoc 编译器用来生成 generated.pb.go
register.go
register.go 包含 API 类型的注册逻辑,将 API 中的类型注册到 Kubernetes API 的 Scheme 中。
register.go 定义了如何将 Go 类型与 API 版本/组进行映射,包含 AddToScheme 函数,其他组件可以调用它来注册这些类型。
types.go
最重要的文件,包含核心 API 类型的 Go 定义,定义了 API 相关的各种结构体,包含字段定义、标签注释和验证逻辑,有详细的字段注释说明每个字段的用途
types_swagger_doc_generated.go
自动生成的 Swagger 文档,包含 API 类型的详细文档,用于生成 Kubernetes API 参考文档。
这些注释会被 Kubernetes API 文档工具使用。
zz_generated.deepcopy.go
自动生成的 DeepCopy 方法实现,包含 api 类型的深拷贝方法,由 deepcopy-gen 工具根据 types.go 中的标记生成。
Kubernetes 运行时需要这些方法来安全地复制对象。
zz_generated.prerelease-lifecycle.go
自动生成的 API 生命周期相关代码,包含 API 版本的弃用和移除策略,由 prerelease-lifecycle-gen 工具生成。
用于管理 API 版本的生命周期(alpha/beta/stable 状态转换)。
3.1.2 - admission
3.1.2.1 - 概述
介绍
Admission API 主要用于 动态准入控制(Dynamic Admission Control),即在 Kubernetes API 请求被处理之前或之后,对其进行 拦截、验证或修改。它的主要功能包括:
- 验证(Validation):检查资源的合法性(如 Pod 的镜像是否符合安全策略)。
- 变更(Mutation):修改请求的内容(如自动注入 Sidecar 容器)。
- 审计(Auditing):记录 API 请求的详细信息,用于安全审计。
Admission API 通常与 Admission Webhooks 配合使用,允许用户自定义准入逻辑(如通过 Webhook 调用外部服务)。
核心类型
Admission API 主要定义在 types.go 中,核心结构体包括:
-
AdmissionReview
-
用于封装 准入请求(Request) 和 准入响应(Response)。
-
是 Webhook 和 API Server 之间的通信格式。
-
-
AdmissionRequest
表示一个 准入请求,包含所有需要验证或修改的资源信息。
-
AdmissionResponse
表示 准入控制的结果,决定是否允许该请求,并可以返回修改内容。
HTTP 方法
Admission API 本身不直接提供 REST API,而是 由 API Server 调用 Webhook 时使用。其交互流程如下:
- API Server 收到请求(如
kubectl create -f pod.yaml)。 - API Server 构造
AdmissionReview,发送给配置的 Webhook。 - Webhook 处理请求,返回
AdmissionReview{ Response: ... }。 - API Server 根据响应决定是否继续处理。
使用场景
Admission API 通常用于:
- 强制安全策略(如禁止特权容器)。
- 资源默认值注入(如自动设置
requests/limits)。 - Sidecar 注入(如 Istio 自动注入
istio-proxy)。 - 自定义验证逻辑(如检查 Ingress 域名是否合法)。
3.1.2.2 - types.go
AdmissionReview
AdmissionReview 描述了准入审查请求/应答。
// AdmissionReview describes an admission review request/response.
type AdmissionReview struct {
metav1.TypeMeta `json:",inline"`
// Request describes the attributes for the admission request.
// +optional
Request *AdmissionRequest `json:"request,omitempty" protobuf:"bytes,1,opt,name=request"`
// Response describes the attributes for the admission response.
// +optional
Response *AdmissionResponse `json:"response,omitempty" protobuf:"bytes,2,opt,name=response"`
}
AdmissionRequest
dmissionRequest 描述了准入请求的准入属性
type AdmissionRequest struct {
// UID 是单个请求/响应的唯一标识符。它允许我们区分其他方面相同的请求实例
//(并行请求、先前请求未修改时的请求等)
// UID 用于跟踪 KAS 和 WebHook 之间的往返(请求/响应),而不是用户请求
// 它适合在 webhook 和 apiserver 之间关联日志条目,用于审计或调试
UID types.UID `json:"uid" protobuf:"bytes,1,opt,name=uid"`
// Kind 是被提交对象的完全限定类型(例如 v1.Pod 或 autoscaling.v1.Scale)
Kind metav1.GroupVersionKind `json:"kind" protobuf:"bytes,2,opt,name=kind"`
// Resource 是被请求的完全限定资源(例如 v1.pods)
Resource metav1.GroupVersionResource `json:"resource" protobuf:"bytes,3,opt,name=resource"`
// SubResource 是被请求的子资源(如果有)(例如 "status" 或 "scale")
// +optional
SubResource string `json:"subResource,omitempty" protobuf:"bytes,4,opt,name=subResource"`
// RequestKind 是原始 API 请求的完全限定类型(例如 v1.Pod 或 autoscaling.v1.Scale)
// 如果指定且与 "kind" 中的值不同,则表示执行了等效匹配和转换
//
// 例如,如果 deployments 可以通过 apps/v1 和 apps/v1beta1 修改,并且 webhook 注册了规则
// `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]` 和 `matchPolicy: Equivalent`,
// 那么发送到 apps/v1beta1 deployments 的 API 请求会被转换并发送到 webhook,
// 其中 `kind: {group:"apps", version:"v1", kind:"Deployment"}`(匹配 webhook 注册的规则),
// 而 `requestKind: {group:"apps", version:"v1beta1", kind:"Deployment"}`(表示原始 API 请求的类型)
//
// 更多详情请参阅 webhook 配置类型中 "matchPolicy" 字段的文档
// +optional
RequestKind *metav1.GroupVersionKind `json:"requestKind,omitempty" protobuf:"bytes,13,opt,name=requestKind"`
// RequestResource 是原始 API 请求的完全限定资源(例如 v1.pods)
// 如果指定且与 "resource" 中的值不同,则表示执行了等效匹配和转换
//
// 例如,如果 deployments 可以通过 apps/v1 和 apps/v1beta1 修改,并且 webhook 注册了规则
// `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]` 和 `matchPolicy: Equivalent`,
// 那么发送到 apps/v1beta1 deployments 的 API 请求会被转换并发送到 webhook,
// 其中 `resource: {group:"apps", version:"v1", resource:"deployments"}`(匹配 webhook 注册的资源),
// 而 `requestResource: {group:"apps", version:"v1beta1", resource:"deployments"}`(表示原始 API 请求的资源)
//
// 更多详情请参阅 webhook 配置类型中 "matchPolicy" 字段的文档
// +optional
RequestResource *metav1.GroupVersionResource `json:"requestResource,omitempty" protobuf:"bytes,14,opt,name=requestResource"`
// RequestSubResource 是原始 API 请求的子资源名称(如果有)(例如 "status" 或 "scale")
// 如果指定且与 "subResource" 中的值不同,则表示执行了等效匹配和转换
// 更多详情请参阅 webhook 配置类型中 "matchPolicy" 字段的文档
// +optional
RequestSubResource string `json:"requestSubResource,omitempty" protobuf:"bytes,15,opt,name=requestSubResource"`
// Name 是请求中呈现的对象名称。在 CREATE 操作中,客户端可以省略名称,
// 依赖服务器生成名称。如果是这种情况,此字段将包含空字符串
// +optional
Name string `json:"name,omitempty" protobuf:"bytes,5,opt,name=name"`
// Namespace 是与请求关联的命名空间(如果有)
// +optional
Namespace string `json:"namespace,omitempty" protobuf:"bytes,6,opt,name=namespace"`
// Operation 是正在执行的操作。这可能与请求的操作不同
// 例如,一个 patch 可能导致 CREATE 或 UPDATE 操作
Operation Operation `json:"operation" protobuf:"bytes,7,opt,name=operation"`
// UserInfo 是关于请求用户的信息
UserInfo authenticationv1.UserInfo `json:"userInfo" protobuf:"bytes,8,opt,name=userInfo"`
// Object 是来自传入请求的对象
// +optional
Object runtime.RawExtension `json:"object,omitempty" protobuf:"bytes,9,opt,name=object"`
// OldObject 是现有对象。仅对 DELETE 和 UPDATE 请求填充
// +optional
OldObject runtime.RawExtension `json:"oldObject,omitempty" protobuf:"bytes,10,opt,name=oldObject"`
// DryRun 表示此请求的修改肯定不会持久化
// 默认为 false
// +optional
DryRun *bool `json:"dryRun,omitempty" protobuf:"varint,11,opt,name=dryRun"`
// Options 是正在执行的操作的操作选项结构
// 例如 `meta.k8s.io/v1.DeleteOptions` 或 `meta.k8s.io/v1.CreateOptions`。这可能与
// 调用者提供的选项不同。例如,对于 patch 请求,执行的操作可能是 CREATE,
// 在这种情况下,Options 将是 `meta.k8s.io/v1.CreateOptions`,即使调用者提供了 `meta.k8s.io/v1.PatchOptions`
// +optional
Options runtime.RawExtension `json:"options,omitempty" protobuf:"bytes,12,opt,name=options"`
}
AdmissionResponse
// AdmissionResponse 描述了一个准入响应
type AdmissionResponse struct {
// UID 是单个请求/响应的标识符
// 必须从对应的 AdmissionRequest 中复制过来
UID types.UID `json:"uid" protobuf:"bytes,1,opt,name=uid"`
// Allowed 表示是否允许该准入请求
Allowed bool `json:"allowed" protobuf:"varint,2,opt,name=allowed"`
// Result 包含关于为什么拒绝准入请求的额外细节
// 如果 "Allowed" 为 "true",则不会参考此字段
// +optional
Result *metav1.Status `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
// patch 内容体。目前我们只支持实现了 RFC 6902 的 "JSONPatch"
// +optional
Patch []byte `json:"patch,omitempty" protobuf:"bytes,4,opt,name=patch"`
// patch 类型。目前我们只允许 "JSONPatch"
// +optional
PatchType *PatchType `json:"patchType,omitempty" protobuf:"bytes,5,opt,name=patchType"`
// AuditAnnotations 是由远程准入控制器设置的非结构化键值映射(例如 error=image-blacklisted)
// MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 准入控制器会在键前加上
// 准入 webhook 名称(例如 imagepolicy.example.com/error=image-blacklisted)
// 准入 webhook 提供 AuditAnnotations 来为此请求的审计日志添加上下文
// +optional
AuditAnnotations map[string]string `json:"auditAnnotations,omitempty" protobuf:"bytes,6,opt,name=auditAnnotations"`
// warnings 是要返回给请求 API 客户端的警告消息列表
// 警告消息描述了 API 请求客户端应该纠正或注意的问题
// 尽可能将警告限制在 120 个字符以内
// 超过 256 个字符的警告和大量警告可能会被截断
// +optional
Warnings []string `json:"warnings,omitempty" protobuf:"bytes,7,rep,name=warnings"`
}
// PatchType is the type of patch being used to represent the mutated object
type PatchType string
// PatchType constants.
const (
PatchTypeJSONPatch PatchType = "JSONPatch"
)
3.1.2.3 - register.go
就注册了一个类型 AdmissionReview:
// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&AdmissionReview{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
3.1.3 - admissionregistration
3.1.3.1 - 概述
介绍
AdmissionRegistration API 核心功能:用于注册和管理 Kubernetes 的 动态准入控制 Webhook,允许用户在不修改 API Server 代码的情况下扩展准入控制逻辑。
主要分为两类:
- MutatingAdmissionWebhook
- 用于 修改 API 请求对象(如自动注入 Sidecar 容器)
- ValidatingAdmissionWebhook
- 用于 验证 API 请求对象(如检查资源是否符合安全策略)
核心类型
在 admissionregistration.k8s.io/v1 中定义了以下关键资源:
- MutatingWebhookConfiguration
- 用于注册多个 修改型 Webhook。
- 每个 Webhook 指定:
- 触发规则(匹配哪些 API 请求)
- 调用的 Webhook 服务地址
- 失败策略(如拒绝请求或忽略错误)
- ValidatingWebhookConfiguration
- 用于注册多个 验证型 Webhook。
- 结构与
MutatingWebhookConfiguration类似,但 Webhook 不能修改对象。
核心 API 方法
AdmissionRegistration API 通过标准的 Kubernetes REST 接口提供以下操作:
| HTTP 方法 | 路径 | 功能 |
|---|---|---|
GET |
/apis/admissionregistration.k8s.io/v1/mutatingwebhookconfigurations |
列出所有 MutatingWebhookConfiguration |
POST |
同上 | 创建新的 MutatingWebhookConfiguration |
PUT |
/apis/admissionregistration.k8s.io/v1/mutatingwebhookconfigurations/{name} |
更新指定配置 |
DELETE |
同上 | 删除配置 |
GET |
/apis/admissionregistration.k8s.io/v1/validatingwebhookconfigurations |
列出所有 ValidatingWebhookConfiguration |
POST |
同上 | 创建新的 ValidatingWebhookConfiguration |
关键字段解析
(1) WebhookClientConfig
type WebhookClientConfig struct {
URL *string `json:"url,omitempty"` // Webhook 服务 URL(直接调用)
Service *ServiceReference `json:"service,omitempty"` // 通过 Service 调用
CABundle []byte `json:"caBundle,omitempty"` // CA 证书(用于 TLS 验证)
}
- 支持两种调用方式:
- 直接指定 URL(如
https://webhook.example.com:443/admit) - 通过 Kubernetes Service 调用(推荐)
- 直接指定 URL(如
(2) RuleWithOperations
type RuleWithOperations struct {
Operations []OperationType `json:"operations"` // 操作类型:CREATE, UPDATE, DELETE, *
Rule Rule `json:"rule"` // 资源匹配规则
}
-
示例:匹配所有 Pod 的 CREATE/UPDATE 操作:
rules: - operations: ["CREATE", "UPDATE"] apiGroups: [""] apiVersions: ["v1"] resources: ["pods"]
(3) FailurePolicy
type FailurePolicyType string
const (
Ignore FailurePolicyType = "Ignore" // 失败时忽略(继续请求)
Fail FailurePolicyType = "Fail" // 失败时拒绝请求
)
工作原理
- API Server 接收请求(如创建 Pod)
- 检查匹配的 Webhook 规则
- 通过
rules字段过滤
- 通过
- 调用 Webhook 服务
- 发送
AdmissionReview请求
- 发送
- 处理响应
- 根据
allowed和patch字段决定是否允许请求
- 根据
3.1.3.2 - types.go
WebhookClientConfig
AdmissionReview 描述了准入审查请求/应答。
// WebhookClientConfig contains the information to make a TLS
// connection with the webhook
type WebhookClientConfig struct {
// `url` gives the location of the webhook, in standard URL form
// (`scheme://host:port/path`). Exactly one of `url` or `service`
// must be specified.
//
// The `host` should not refer to a service running in the cluster; use
// the `service` field instead. The host might be resolved via external
// DNS in some apiservers (e.g., `kube-apiserver` cannot resolve
// in-cluster DNS as that would be a layering violation). `host` may
// also be an IP address.
//
// Please note that using `localhost` or `127.0.0.1` as a `host` is
// risky unless you take great care to run this webhook on all hosts
// which run an apiserver which might need to make calls to this
// webhook. Such installs are likely to be non-portable, i.e., not easy
// to turn up in a new cluster.
//
// The scheme must be "https"; the URL must begin with "https://".
//
// A path is optional, and if present may be any string permissible in
// a URL. You may use the path to pass an arbitrary string to the
// webhook, for example, a cluster identifier.
//
// Attempting to use a user or basic auth e.g. "user:password@" is not
// allowed. Fragments ("#...") and query parameters ("?...") are not
// allowed, either.
//
// +optional
URL *string `json:"url,omitempty" protobuf:"bytes,3,opt,name=url"`
// `service` is a reference to the service for this webhook. Either
// `service` or `url` must be specified.
//
// If the webhook is running within the cluster, then you should use `service`.
//
// +optional
Service *ServiceReference `json:"service,omitempty" protobuf:"bytes,1,opt,name=service"`
// `caBundle` is a PEM encoded CA bundle which will be used to validate the webhook's server certificate.
// If unspecified, system trust roots on the apiserver are used.
// +optional
CABundle []byte `json:"caBundle,omitempty" protobuf:"bytes,2,opt,name=caBundle"`
}
RuleWithOperations
// RuleWithOperations is a tuple of Operations and Resources. It is recommended to make
// sure that all the tuple expansions are valid.
type RuleWithOperations struct {
// Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or *
// for all of those operations and any future admission operations that are added.
// If '*' is present, the length of the slice must be one.
// Required.
// +listType=atomic
Operations []OperationType `json:"operations,omitempty" protobuf:"bytes,1,rep,name=operations,casttype=OperationType"`
// Rule is embedded, it describes other criteria of the rule, like
// APIGroups, APIVersions, Resources, etc.
Rule `json:",inline" protobuf:"bytes,2,opt,name=rule"`
}
OperationType
// OperationType specifies an operation for a request.
// +enum
type OperationType string
// The constants should be kept in sync with those defined in k8s.io/kubernetes/pkg/admission/interface.go.
const (
OperationAll OperationType = "*"
Create OperationType = "CREATE"
Update OperationType = "UPDATE"
Delete OperationType = "DELETE"
Connect OperationType = "CONNECT"
)
FailurePolicyType
// FailurePolicyType specifies a failure policy that defines how unrecognized errors from the admission endpoint are handled.
// +enum
type FailurePolicyType string
const (
// Ignore means that an error calling the webhook is ignored.
Ignore FailurePolicyType = "Ignore"
// Fail means that an error calling the webhook causes the admission to fail.
Fail FailurePolicyType = "Fail"
)
3.1.3.3 - register.go
注册类型
// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&ValidatingWebhookConfiguration{},
&ValidatingWebhookConfigurationList{},
&MutatingWebhookConfiguration{},
&MutatingWebhookConfigurationList{},
&ValidatingAdmissionPolicy{},
&ValidatingAdmissionPolicyList{},
&ValidatingAdmissionPolicyBinding{},
&ValidatingAdmissionPolicyBindingList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
3.1.4 - apidiscovery
3.1.4.1 - 概述
介绍
APIDiscovery API 的核心功能是提供 Kubernetes API 的 动态发现机制,使客户端能够自动发现集群支持的 API 资源及其详细信息。
主要解决以下问题:
- API 资源发现:客户端无需硬编码即可知道集群支持哪些 API(如 pods、deployments 等)
- 版本兼容性:发现不同 API 版本(如 v1、v1beta1)及其差异
- API 聚合支持:支持自定义 API Server(Aggregated API Server)的自动注册和发现
- 高效缓存:客户端可以缓存发现信息,减少不必要的 API 调用
核心 API 资源类型
在 apidiscovery.k8s.io/v2(最新版本)中定义了以下关键结构:
(1) APIGroupDiscovery
// 描述一个 API 组的所有可用版本和资源
type APIGroupDiscovery struct {
metav1.TypeMeta `json:",inline"`
metav1.GroupVersion `json:",inline"` // 例如 "apps/v1"
Versions []APIVersionDiscovery `json:"versions"` // 该组下的所有版本
}
(2) APIVersionDiscovery
// 描述一个 API 版本下的所有资源
type APIVersionDiscovery struct {
Version string `json:"version"` // 例如 "v1"
Resources []APIResourceDiscovery `json:"resources"` // 该版本下的资源列表
Freshness metav1.ConditionStatus `json:"freshness"` // 表示数据是否最新
}
(3) APIResourceDiscovery
// 描述单个 API 资源的详细信息
type APIResourceDiscovery struct {
Resource string `json:"resource"` // 例如 "pods"
ResponseKind *metav1.GroupVersionKind `json:"responseKind"` // 返回的 Kind
Scope ScopeType `json:"scope"` // 作用域(Namespaced/Cluster)
SingularResource string `json:"singularResource"` // 单数形式(如 "pod")
Verbs []string `json:"verbs"` // 支持的动词(get/list/watch 等)
ShortNames []string `json:"shortNames"` // 缩写(如 "po")
Categories []string `json:"categories"` // 所属分类(如 "all")
Subresources []APISubresourceDiscovery `json:"subresources"` // 子资源
}
核心 API 方法
APIDiscovery API 通过以下标准 HTTP 端点提供服务:
| HTTP 方法 | 路径 | 功能 |
|---|---|---|
GET |
/apis/apidiscovery.k8s.io/v2 |
获取 APIDiscovery API 自身的描述 |
GET |
/apis/apidiscovery.k8s.io/v2/apigroups |
获取所有 API 组的发现信息 |
GET |
/apis/apidiscovery.k8s.io/v2/apigroups/{group} |
获取特定 API 组的发现信息 |
工作原理
-
客户端首次查询
kubectl get --raw /apis/apidiscovery.k8s.io/v2beta1/apigroups -
解析响应
- 获取所有 API 组、版本、资源及其能力
-
建立本地缓存
- 客户端缓存发现结果,后续只检查
Freshness
- 客户端缓存发现结果,后续只检查
-
处理 API 变更
- 当 API 扩展(如 CRD 注册)时,APIServer 自动更新发现信息
实际应用场景
(1) kubectl 自动补全
# kubectl 依赖发现 API 实现自动补全
kubectl get <TAB> # 显示所有可用资源类型
(2) 客户端库初始化
// client-go 使用发现 API 初始化动态客户端
discoveryClient := clientset.Discovery()
resources, err := discoveryClient.ServerResources()
(3) 自定义控制器开发
// 动态发现新的 CRD
discoveryClient.Discovery().ServerPreferredResources()
源码学习路径
- 类型定义:
staging/src/k8s.io/api/apidiscovery/v2/types.go - 服务端实现:
pkg/controlplane/apiserver/discovery/ - 客户端缓存逻辑:
staging/src/k8s.io/client-go/discovery/
3.1.4.2 - types.go
APIGroupDiscoveryList
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:prerelease-lifecycle-gen:introduced=1.30
// APIGroupDiscoveryList is a resource containing a list of APIGroupDiscovery.
// This is one of the types able to be returned from the /api and /apis endpoint and contains an aggregated
// list of API resources (built-ins, Custom Resource Definitions, resources from aggregated servers)
// that a cluster supports.
type APIGroupDiscoveryList struct {
v1.TypeMeta `json:",inline"`
// ResourceVersion will not be set, because this does not have a replayable ordering among multiple apiservers.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
v1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// items is the list of groups for discovery. The groups are listed in priority order.
Items []APIGroupDiscovery `json:"items" protobuf:"bytes,2,rep,name=items"`
}
APIGroupDiscovery
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:prerelease-lifecycle-gen:introduced=1.30
// APIGroupDiscovery holds information about which resources are being served for all version of the API Group.
// It contains a list of APIVersionDiscovery that holds a list of APIResourceDiscovery types served for a version.
// Versions are in descending order of preference, with the first version being the preferred entry.
type APIGroupDiscovery struct {
v1.TypeMeta `json:",inline"`
// Standard object's metadata.
// The only field completed will be name. For instance, resourceVersion will be empty.
// name is the name of the API group whose discovery information is presented here.
// name is allowed to be "" to represent the legacy, ungroupified resources.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
v1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// versions are the versions supported in this group. They are sorted in descending order of preference,
// with the preferred version being the first entry.
// +listType=map
// +listMapKey=version
Versions []APIVersionDiscovery `json:"versions,omitempty" protobuf:"bytes,2,rep,name=versions"`
}
3.1.4.3 - register.go
注册类型 APIGroupDiscoveryList 和 APIGroupDiscovery:
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&APIGroupDiscoveryList{},
&APIGroupDiscovery{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
3.1.5 - apiserverinternal
3.1.5.1 - 概述
介绍
apiserverinternal API 的核心功能是提供 API Server 的 内部状态管理和协调机制,主要服务于以下场景:
- 存储版本管理
- 跟踪资源对象在 etcd 中的存储版本(Storage Version)
- 确保多版本 API 的兼容性转换
- API Server 实例协调
- 在多个 API Server 实例间同步状态信息
- 支持高可用部署模式下的协调
- 内部状态监控
- 暴露 API Server 的内部健康状态和性能指标
核心 API 资源类型
在 apiserverinternal.k8s.io/v1alpha1 中定义了以下关键资源:
- StorageVersion
- StorageVersionStatus
- ServerStorageVersion
关键工作流程
(1) 存储版本协商
- 当资源存在多版本(如
v1和v1beta1)时:- 所有 API Server 实例通过
StorageVersion资源协商出一个统一的存储版本 - 写入 etcd 时统一转换为该版本
- 所有 API Server 实例通过
- 客户端请求时按需转换回目标版本
(2) 状态同步示例
# 示例:Deployment 资源的存储版本状态
apiVersion: apiserverinternal.k8s.io/v1alpha1
kind: StorageVersion
metadata:
name: deployments.apps
status:
storageVersions:
- apiServerID: "kube-apiserver-xyz"
encodingVersion: "apps/v1"
decodableVersions: ["apps/v1", "apps/v1beta1"]
commonEncodingVersion: "apps/v1"
实际应用场景
(1) 版本升级监控
# 查看当前存储版本协商状态
kubectl get storageversions.apiserverinternal.k8s.io
(2) 多版本兼容性保障
- 确保旧版本客户端(如使用
apps/v1beta1)仍能读写数据 - API Server 自动处理版本转换
(3) API Server 运维
- 检测集群中不同 API Server 实例的版本一致性
- 灰度升级时监控版本迁移状态
源码学习路径
- 类型定义:
staging/src/k8s.io/api/apiserverinternal/v1alpha1/types.go - 控制器逻辑:
pkg/controlplane/storageversiongc/(存储版本垃圾回收)pkg/apiserver/storageversion/(版本协调主逻辑) - 客户端交互:
staging/src/k8s.io/client-go/applyconfigurations/apiserverinternal/
调试技巧
# 查看所有资源的存储版本
kubectl get storageversions.apiserverinternal.k8s.io -o yaml
# 检查特定资源(如 Deployment)
kubectl get storageversions deployments.apps -o yaml
设计意义
- 解耦存储与 API 版本:允许 etcd 存储格式独立于对外暴露的 API 版本
- 平滑升级:支持多版本共存期间的无缝转换
- 分布式协调:解决多 API Server 实例的状态一致性问题
3.1.5.2 - types.go
StorageVersion
// Storage version of a specific resource.
type StorageVersion struct {
metav1.TypeMeta `json:",inline"`
// The name is <group>.<resource>.
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec is an empty spec. It is here to comply with Kubernetes API style.
Spec StorageVersionSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
// API server instances report the version they can decode and the version they
// encode objects to when persisting objects in the backend.
Status StorageVersionStatus `json:"status" protobuf:"bytes,3,opt,name=status"`
}
StorageVersionList
// A list of StorageVersions.
type StorageVersionList struct {
metav1.TypeMeta `json:",inline"`
// Standard list metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Items holds a list of StorageVersion
Items []StorageVersion `json:"items" protobuf:"bytes,2,rep,name=items"`
}
3.1.5.3 - register.go
注册类型 APIGroupDiscoveryList 和 APIGroupDiscovery:
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&StorageVersion{},
&StorageVersionList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
3.1.6 - apps
3.1.6.1 - 概述
介绍
apps API 的核心功能是提供对 应用层工作负载 的声明式管理,主要包括:
- 部署管理:滚动更新、回滚、扩缩容
- 状态维护:确保应用实例数与声明的一致
- 版本控制:管理应用更新时的版本切换
- 与底层资源(Pod)的协调
主要管理的资源类型:
- 无状态应用(Deployment)
- 有状态应用(StatefulSet)
- 守护进程(DaemonSet)
- 一次性任务(ReplicaSet,通常由 Deployment 自动管理)
核心 API 资源类型
在 apps/v1 中定义了以下关键资源(所有资源均为 namespace-scoped):
- Deployment
- DaemonSet
- StatefulSet
- ReplicaSet
源码学习路径
类型定义:
- staging/src/k8s.io/api/apps/v1/types.go
控制器实现:
- Deployment: pkg/controller/deployment/
- StatefulSet: pkg/controller/statefulset/
- DaemonSet: pkg/controller/daemon/
客户端操作:
- staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/
设计意义
- 抽象与自动化:将 Pod 管理从手动操作转为声明式管理
- 版本化运维:支持灰度发布、金丝雀发布等高级部署模式
- 状态分离:区分应用定义(Spec)和运行时状态(Status)
3.1.6.2 - types.go
StatefulSet
// StatefulSet represents a set of pods with consistent identities.
// Identities are defined as:
// - Network: A single stable DNS and hostname.
// - Storage: As many VolumeClaims as requested.
//
// The StatefulSet guarantees that a given network identity will always
// map to the same storage identity.
type StatefulSet struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec defines the desired identities of pods in this set.
// +optional
Spec StatefulSetSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// Status is the current status of Pods in this StatefulSet. This data
// may be out of date by some window of time.
// +optional
Status StatefulSetStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
Deployment
// Deployment enables declarative updates for Pods and ReplicaSets.
type Deployment struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Specification of the desired behavior of the Deployment.
// +optional
Spec DeploymentSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// Most recently observed status of the Deployment.
// +optional
Status DeploymentStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
DaemonSet
// DaemonSet represents the configuration of a daemon set.
type DaemonSet struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// The desired behavior of this daemon set.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
// +optional
Spec DaemonSetSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// The current status of this daemon set. This data may be
// out of date by some window of time.
// Populated by the system.
// Read-only.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
// +optional
Status DaemonSetStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
ReplicaSet
// ReplicaSet ensures that a specified number of pod replicas are running at any given time.
type ReplicaSet struct {
metav1.TypeMeta `json:",inline"`
// If the Labels of a ReplicaSet are empty, they are defaulted to
// be the same as the Pod(s) that the ReplicaSet manages.
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec defines the specification of the desired behavior of the ReplicaSet.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
// +optional
Spec ReplicaSetSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// Status is the most recently observed status of the ReplicaSet.
// This data may be out of date by some window of time.
// Populated by the system.
// Read-only.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
// +optional
Status ReplicaSetStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
ControllerRevision
// ControllerRevision implements an immutable snapshot of state data. Clients
// are responsible for serializing and deserializing the objects that contain
// their internal state.
// Once a ControllerRevision has been successfully created, it can not be updated.
// The API Server will fail validation of all requests that attempt to mutate
// the Data field. ControllerRevisions may, however, be deleted. Note that, due to its use by both
// the DaemonSet and StatefulSet controllers for update and rollback, this object is beta. However,
// it may be subject to name and representation changes in future releases, and clients should not
// depend on its stability. It is primarily for internal use by controllers.
type ControllerRevision struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Data is the serialized representation of the state.
Data runtime.RawExtension `json:"data,omitempty" protobuf:"bytes,2,opt,name=data"`
// Revision indicates the revision of the state represented by Data.
Revision int64 `json:"revision" protobuf:"varint,3,opt,name=revision"`
}
3.1.6.3 - register.go
注册类型:
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Deployment{},
&DeploymentList{},
&StatefulSet{},
&StatefulSetList{},
&DaemonSet{},
&DaemonSetList{},
&ReplicaSet{},
&ReplicaSetList{},
&ControllerRevision{},
&ControllerRevisionList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
3.1.7 - authentication
3.1.7.1 - 概述
介绍
authentication API 的核心功能是处理 Kubernetes 集群的 身份认证,确保请求来源的合法性。
主要职责包括:
- 验证请求者身份:
- 确认用户、ServiceAccount 或外部系统的身份凭证
- 支持多种认证机制:
- X.509 客户端证书
- Bearer Token(如 ServiceAccount Token)
- 身份代理(OIDC、LDAP 等)
- 提供认证配置管理:
- 管理 TLS 证书配置
- 管理 ServiceAccount 的 Token 签发
核心 API 资源类型
在 authentication.k8s.io/v1 和核心 API 组中定义了以下关键资源:
(1) TokenReview
// 用于验证 Bearer Token 的有效性
type TokenReview struct {
metav1.TypeMeta `json:",inline"`
Spec TokenReviewSpec `json:"spec"`
Status TokenReviewStatus `json:"status,omitempty"`
}
关键字段:
spec.token:待验证的 Token 字符串status.authenticated:验证结果(true/false)status.user:认证通过后的用户信息(用户名、组等)
(2) CertificateSigningRequest (CSR)
// 在 certificates.k8s.io/v1 中定义,但用于认证流程
type CertificateSigningRequest struct {
metav1.TypeMeta `json:",inline"`
Spec CertificateSigningRequestSpec `json:"spec"`
}
关键字段:
spec.request:PEM 编码的证书签名请求spec.signerName:指定签名用途(如kubernetes.io/kube-apiserver-client)
(3) ServiceAccount
// 在核心 v1 API 中定义,用于 Pod 身份认证
type ServiceAccount struct {
metav1.TypeMeta `json:",inline"`
Secrets []ObjectReference `json:"secrets,omitempty"` // 关联的 Token Secret
}
3.1.7.2 - types.go
TokenReview
type TokenReview struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec holds information about the request being evaluated
Spec TokenReviewSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
// Status is filled in by the server and indicates whether the request can be authenticated.
// +optional
Status TokenReviewStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
TokenRequest
// TokenRequest requests a token for a given service account.
type TokenRequest struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec holds information about the request being evaluated
Spec TokenRequestSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
// Status is filled in by the server and indicates whether the token can be authenticated.
// +optional
Status TokenRequestStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
SelfSubjectReview
// SelfSubjectReview contains the user information that the kube-apiserver has about the user making this request.
// When using impersonation, users will receive the user info of the user being impersonated. If impersonation or
// request header authentication is used, any extra keys will have their case ignored and returned as lowercase.
type SelfSubjectReview struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Status is filled in by the server with the user attributes.
Status SelfSubjectReviewStatus `json:"status,omitempty" protobuf:"bytes,2,opt,name=status"`
}
3.1.7.3 - register.go
注册类型:
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&TokenReview{},
&TokenRequest{},
&SelfSubjectReview{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
3.1.8 - authorization
3.1.8.1 - 概述
介绍
authorization API 的核心功能:决定是否允许某个主体(用户/ServiceAccount/组)执行特定操作。
3.1.8.2 - types.go
TokenReview
TokenRequest
// TokenRequest requests a token for a given service account.
type TokenRequest struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec holds information about the request being evaluated
Spec TokenRequestSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
// Status is filled in by the server and indicates whether the token can be authenticated.
// +optional
Status TokenRequestStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
SelfSubjectReview
// SelfSubjectReview contains the user information that the kube-apiserver has about the user making this request.
// When using impersonation, users will receive the user info of the user being impersonated. If impersonation or
// request header authentication is used, any extra keys will have their case ignored and returned as lowercase.
type SelfSubjectReview struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Status is filled in by the server with the user attributes.
Status SelfSubjectReviewStatus `json:"status,omitempty" protobuf:"bytes,2,opt,name=status"`
}
3.1.8.3 - register.go
注册类型:
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&TokenReview{},
&TokenRequest{},
&SelfSubjectReview{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
4 - API视角
4.1 - pod
4.1.1 - 概述
相关代码文件
搜索条件:
- “files to include”:
*\pod\*.go - “files to exclude”:
*_test.go,docs.go,doc.go,test\**\*.go
找到的相关代码文件为:

文件列表具体为:
- pkg\api\pod\util.go
- pkg\api\pod\warnings.go
- pkg\api\v1\pod\util.go
- pkg\kubelet\pod\mirror_client.go
- pkg\kubelet\pod\pod_manager.go
- pkg\registry\core\pod\strategy.go
- pkg\util\pod\pod.go
4.1.2 - pod的定义
概述
pod的结构体定义和属性,来自 cursor 的提示,感谢 cursor 的强大。
Pod 是 Kubernetes 中最小的可部署单元,它的定义位于 staging/src/k8s.io/api/core/v1/types.go 文件中。一个 Pod 包含以下主要部分:
- 基本结构:
type Pod struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Spec PodSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
Status PodStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
- 主要组件:
-
metadata: 包含 Pod 的元数据信息,如名称、命名空间、标签等 -
spec: Pod 的规格定义,包含以下重要字段:containers: Pod 中的容器列表(至少需要一个容器)initContainers: 初始化容器列表volumes: 可挂载的存储卷列表restartPolicy: 重启策略(Always、OnFailure、Never)nodeSelector: 节点选择器serviceAccountName: 服务账号名称securityContext: 安全上下文imagePullSecrets: 镜像拉取密钥affinity: 亲和性设置tolerations: 容忍设置- 等等…
-
status: Pod 的当前状态信息,包含:phase: Pod 的生命周期阶段(Pending、Running、Succeeded、Failed、Unknown)conditions: Pod 的条件状态message: 状态描述信息reason: 状态原因hostIP: 主机 IPpodIP: Pod IPcontainerStatuses: 容器状态列表initContainerStatuses: 初始化容器状态列表qosClass: 服务质量等级(Guaranteed、Burstable、BestEffort)
- 生命周期: Pod 有五个主要阶段:
Pending: Pod 已被系统接受,但容器镜像尚未创建Running: Pod 已绑定到节点,所有容器已启动Succeeded: 所有容器已成功终止Failed: 所有容器已终止,至少有一个容器失败Unknown: 无法获取 Pod 状态
- 条件状态: Pod 可以有以下条件状态:
ContainersReady: 所有容器是否就绪PodInitialized: 所有初始化容器是否成功启动PodReady: Pod 是否可以服务请求PodScheduled: Pod 的调度状态DisruptionTarget: Pod 是否即将被终止PodReadyToStartContainers: Pod 沙箱是否配置成功PodResizePending: Pod 是否正在调整大小PodResizeInProgress: Pod 大小调整是否正在进行
这就是 Kubernetes 中 Pod 的基本定义和结构。Pod 是 Kubernetes 中最小的可部署单元,它可以包含一个或多个容器,这些容器共享网络命名空间和存储卷。
pod 结构体
pod的结构体定义在 staging/src/k8s.io/api/core/v1/pod.go 文件中:
type Pod struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Specification of the desired behavior of the pod.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
// +optional
Spec PodSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// Most recently observed status of the pod.
// This data may not be up to date.
// Populated by the system.
// Read-only.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
// +optional
Status PodStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
备注:
staging/src/k8s.io/api的代码会被同步到仓库 https://github.com/kubernetes/api 中
PodSpec 结构体
PodSpec 的定义在同一个文件中:
// PodSpec is a description of a pod.
type PodSpec struct {
// List of volumes that can be mounted by containers belonging to the pod.
// More info: https://kubernetes.io/docs/concepts/storage/volumes
// +optional
// +patchMergeKey=name
// +patchStrategy=merge,retainKeys
// +listType=map
// +listMapKey=name
Volumes []Volume `json:"volumes,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name" protobuf:"bytes,1,rep,name=volumes"`
// List of initialization containers belonging to the pod.
// Init containers are executed in order prior to containers being started. If any
// init container fails, the pod is considered to have failed and is handled according
// to its restartPolicy. The name for an init container or normal container must be
// unique among all containers.
// Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes.
// The resourceRequirements of an init container are taken into account during scheduling
// by finding the highest request/limit for each resource type, and then using the max of
// that value or the sum of the normal containers. Limits are applied to init containers
// in a similar fashion.
// Init containers cannot currently be added or removed.
// Cannot be updated.
// More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/
// +patchMergeKey=name
// +patchStrategy=merge
// +listType=map
// +listMapKey=name
InitContainers []Container `json:"initContainers,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,20,rep,name=initContainers"`
// List of containers belonging to the pod.
// Containers cannot currently be added or removed.
// There must be at least one container in a Pod.
// Cannot be updated.
// +patchMergeKey=name
// +patchStrategy=merge
// +listType=map
// +listMapKey=name
Containers []Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=containers"`
// List of ephemeral containers run in this pod. Ephemeral containers may be run in an existing
// pod to perform user-initiated actions such as debugging. This list cannot be specified when
// creating a pod, and it cannot be modified by updating the pod spec. In order to add an
// ephemeral container to an existing pod, use the pod's ephemeralcontainers subresource.
// +optional
// +patchMergeKey=name
// +patchStrategy=merge
// +listType=map
// +listMapKey=name
EphemeralContainers []EphemeralContainer `json:"ephemeralContainers,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,34,rep,name=ephemeralContainers"`
// Restart policy for all containers within the pod.
// One of Always, OnFailure, Never. In some contexts, only a subset of those values may be permitted.
// Default to Always.
// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy
// +optional
RestartPolicy RestartPolicy `json:"restartPolicy,omitempty" protobuf:"bytes,3,opt,name=restartPolicy,casttype=RestartPolicy"`
// Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request.
// Value must be non-negative integer. The value zero indicates stop immediately via
// the kill signal (no opportunity to shut down).
// If this value is nil, the default grace period will be used instead.
// The grace period is the duration in seconds after the processes running in the pod are sent
// a termination signal and the time when the processes are forcibly halted with a kill signal.
// Set this value longer than the expected cleanup time for your process.
// Defaults to 30 seconds.
// +optional
TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"`
// Optional duration in seconds the pod may be active on the node relative to
// StartTime before the system will actively try to mark it failed and kill associated containers.
// Value must be a positive integer.
// +optional
ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty" protobuf:"varint,5,opt,name=activeDeadlineSeconds"`
// Set DNS policy for the pod.
// Defaults to "ClusterFirst".
// Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'.
// DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy.
// To have DNS options set along with hostNetwork, you have to specify DNS policy
// explicitly to 'ClusterFirstWithHostNet'.
// +optional
DNSPolicy DNSPolicy `json:"dnsPolicy,omitempty" protobuf:"bytes,6,opt,name=dnsPolicy,casttype=DNSPolicy"`
// NodeSelector is a selector which must be true for the pod to fit on a node.
// Selector which must match a node's labels for the pod to be scheduled on that node.
// More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
// +optional
// +mapType=atomic
NodeSelector map[string]string `json:"nodeSelector,omitempty" protobuf:"bytes,7,rep,name=nodeSelector"`
// ServiceAccountName is the name of the ServiceAccount to use to run this pod.
// More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
// +optional
ServiceAccountName string `json:"serviceAccountName,omitempty" protobuf:"bytes,8,opt,name=serviceAccountName"`
// DeprecatedServiceAccount is a deprecated alias for ServiceAccountName.
// Deprecated: Use serviceAccountName instead.
// +k8s:conversion-gen=false
// +optional
DeprecatedServiceAccount string `json:"serviceAccount,omitempty" protobuf:"bytes,9,opt,name=serviceAccount"`
// AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.
// +optional
AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty" protobuf:"varint,21,opt,name=automountServiceAccountToken"`
// NodeName indicates in which node this pod is scheduled.
// If empty, this pod is a candidate for scheduling by the scheduler defined in schedulerName.
// Once this field is set, the kubelet for this node becomes responsible for the lifecycle of this pod.
// This field should not be used to express a desire for the pod to be scheduled on a specific node.
// https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodename
// +optional
NodeName string `json:"nodeName,omitempty" protobuf:"bytes,10,opt,name=nodeName"`
// Host networking requested for this pod. Use the host's network namespace.
// If this option is set, the ports that will be used must be specified.
// Default to false.
// +k8s:conversion-gen=false
// +optional
HostNetwork bool `json:"hostNetwork,omitempty" protobuf:"varint,11,opt,name=hostNetwork"`
// Use the host's pid namespace.
// Optional: Default to false.
// +k8s:conversion-gen=false
// +optional
HostPID bool `json:"hostPID,omitempty" protobuf:"varint,12,opt,name=hostPID"`
// Use the host's ipc namespace.
// Optional: Default to false.
// +k8s:conversion-gen=false
// +optional
HostIPC bool `json:"hostIPC,omitempty" protobuf:"varint,13,opt,name=hostIPC"`
// Share a single process namespace between all of the containers in a pod.
// When this is set containers will be able to view and signal processes from other containers
// in the same pod, and the first process in each container will not be assigned PID 1.
// HostPID and ShareProcessNamespace cannot both be set.
// Optional: Default to false.
// +k8s:conversion-gen=false
// +optional
ShareProcessNamespace *bool `json:"shareProcessNamespace,omitempty" protobuf:"varint,27,opt,name=shareProcessNamespace"`
// SecurityContext holds pod-level security attributes and common container settings.
// Optional: Defaults to empty. See type description for default values of each field.
// +optional
SecurityContext *PodSecurityContext `json:"securityContext,omitempty" protobuf:"bytes,14,opt,name=securityContext"`
// ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec.
// If specified, these secrets will be passed to individual puller implementations for them to use.
// More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod
// +optional
// +patchMergeKey=name
// +patchStrategy=merge
// +listType=map
// +listMapKey=name
ImagePullSecrets []LocalObjectReference `json:"imagePullSecrets,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,15,rep,name=imagePullSecrets"`
// Specifies the hostname of the Pod
// If not specified, the pod's hostname will be set to a system-defined value.
// +optional
Hostname string `json:"hostname,omitempty" protobuf:"bytes,16,opt,name=hostname"`
// If specified, the fully qualified Pod hostname will be "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>".
// If not specified, the pod will not have a domainname at all.
// +optional
Subdomain string `json:"subdomain,omitempty" protobuf:"bytes,17,opt,name=subdomain"`
// If specified, the pod's scheduling constraints
// +optional
Affinity *Affinity `json:"affinity,omitempty" protobuf:"bytes,18,opt,name=affinity"`
// If specified, the pod will be dispatched by specified scheduler.
// If not specified, the pod will be dispatched by default scheduler.
// +optional
SchedulerName string `json:"schedulerName,omitempty" protobuf:"bytes,19,opt,name=schedulerName"`
// If specified, the pod's tolerations.
// +optional
// +listType=atomic
Tolerations []Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"`
// HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts
// file if specified.
// +optional
// +patchMergeKey=ip
// +patchStrategy=merge
// +listType=map
// +listMapKey=ip
HostAliases []HostAlias `json:"hostAliases,omitempty" patchStrategy:"merge" patchMergeKey:"ip" protobuf:"bytes,23,rep,name=hostAliases"`
// If specified, indicates the pod's priority. "system-node-critical" and
// "system-cluster-critical" are two special keywords which indicate the
// highest priorities with the former being the highest priority. Any other
// name must be defined by creating a PriorityClass object with that name.
// If not specified, the pod priority will be default or zero if there is no
// default.
// +optional
PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,24,opt,name=priorityClassName"`
// The priority value. Various system components use this field to find the
// priority of the pod. When Priority Admission Controller is enabled, it
// prevents users from setting this field. The admission controller populates
// this field from PriorityClassName.
// The higher the value, the higher the priority.
// +optional
Priority *int32 `json:"priority,omitempty" protobuf:"bytes,25,opt,name=priority"`
// Specifies the DNS parameters of a pod.
// Parameters specified here will be merged to the generated DNS
// configuration based on DNSPolicy.
// +optional
DNSConfig *PodDNSConfig `json:"dnsConfig,omitempty" protobuf:"bytes,26,opt,name=dnsConfig"`
// If specified, all readiness gates will be evaluated for pod readiness.
// A pod is ready when all its containers are ready AND
// all conditions specified in the readiness gates have status equal to "True"
// More info: https://git.k8s.io/enhancements/keps/sig-network/580-pod-readiness-gates
// +optional
// +listType=atomic
ReadinessGates []PodReadinessGate `json:"readinessGates,omitempty" protobuf:"bytes,28,opt,name=readinessGates"`
// RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used
// to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run.
// If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an
// empty definition that uses the default runtime handler.
// More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class
// +optional
RuntimeClassName *string `json:"runtimeClassName,omitempty" protobuf:"bytes,29,opt,name=runtimeClassName"`
// EnableServiceLinks indicates whether information about services should be injected into pod's
// environment variables, matching the syntax of Docker links.
// Optional: Defaults to true.
// +optional
EnableServiceLinks *bool `json:"enableServiceLinks,omitempty" protobuf:"varint,30,opt,name=enableServiceLinks"`
// PreemptionPolicy is the Policy for preempting pods with lower priority.
// One of Never, PreemptLowerPriority.
// Defaults to PreemptLowerPriority if unset.
// +optional
PreemptionPolicy *PreemptionPolicy `json:"preemptionPolicy,omitempty" protobuf:"bytes,31,opt,name=preemptionPolicy"`
// Overhead represents the resource overhead associated with running a pod for a given RuntimeClass.
// This field will be autopopulated at admission time by the RuntimeClass admission controller. If
// the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests.
// The RuntimeClass admission controller will reject Pod create requests which have the overhead already
// set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value
// defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero.
// More info: https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md
// +optional
Overhead ResourceList `json:"overhead,omitempty" protobuf:"bytes,32,opt,name=overhead"`
// TopologySpreadConstraints describes how a group of pods ought to spread across topology
// domains. Scheduler will schedule pods in a way which abides by the constraints.
// All topologySpreadConstraints are ANDed.
// +optional
// +patchMergeKey=topologyKey
// +patchStrategy=merge
// +listType=map
// +listMapKey=topologyKey
// +listMapKey=whenUnsatisfiable
TopologySpreadConstraints []TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty" patchStrategy:"merge" patchMergeKey:"topologyKey" protobuf:"bytes,33,opt,name=topologySpreadConstraints"`
// If true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default).
// In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname).
// In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters to FQDN.
// If a pod does not have FQDN, this has no effect.
// Default to false.
// +optional
SetHostnameAsFQDN *bool `json:"setHostnameAsFQDN,omitempty" protobuf:"varint,35,opt,name=setHostnameAsFQDN"`
// Specifies the OS of the containers in the pod.
// Some pod and container fields are restricted if this is set.
//
// If the OS field is set to linux, the following fields must be unset:
// -securityContext.windowsOptions
//
// If the OS field is set to windows, following fields must be unset:
// - spec.hostPID
// - spec.hostIPC
// - spec.hostUsers
// - spec.securityContext.appArmorProfile
// - spec.securityContext.seLinuxOptions
// - spec.securityContext.seccompProfile
// - spec.securityContext.fsGroup
// - spec.securityContext.fsGroupChangePolicy
// - spec.securityContext.sysctls
// - spec.shareProcessNamespace
// - spec.securityContext.runAsUser
// - spec.securityContext.runAsGroup
// - spec.securityContext.supplementalGroups
// - spec.securityContext.supplementalGroupsPolicy
// - spec.containers[*].securityContext.appArmorProfile
// - spec.containers[*].securityContext.seLinuxOptions
// - spec.containers[*].securityContext.seccompProfile
// - spec.containers[*].securityContext.capabilities
// - spec.containers[*].securityContext.readOnlyRootFilesystem
// - spec.containers[*].securityContext.privileged
// - spec.containers[*].securityContext.allowPrivilegeEscalation
// - spec.containers[*].securityContext.procMount
// - spec.containers[*].securityContext.runAsUser
// - spec.containers[*].securityContext.runAsGroup
// +optional
OS *PodOS `json:"os,omitempty" protobuf:"bytes,36,opt,name=os"`
// Use the host's user namespace.
// Optional: Default to true.
// If set to true or not present, the pod will be run in the host user namespace, useful
// for when the pod needs a feature only available to the host user namespace, such as
// loading a kernel module with CAP_SYS_MODULE.
// When set to false, a new userns is created for the pod. Setting false is useful for
// mitigating container breakout vulnerabilities even allowing users to run their
// containers as root without actually having root privileges on the host.
// This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature.
// +k8s:conversion-gen=false
// +optional
HostUsers *bool `json:"hostUsers,omitempty" protobuf:"bytes,37,opt,name=hostUsers"`
// SchedulingGates is an opaque list of values that if specified will block scheduling the pod.
// If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the
// scheduler will not attempt to schedule the pod.
//
// SchedulingGates can only be set at pod creation time, and be removed only afterwards.
//
// +patchMergeKey=name
// +patchStrategy=merge
// +listType=map
// +listMapKey=name
// +optional
SchedulingGates []PodSchedulingGate `json:"schedulingGates,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,38,opt,name=schedulingGates"`
// ResourceClaims defines which ResourceClaims must be allocated
// and reserved before the Pod is allowed to start. The resources
// will be made available to those containers which consume them
// by name.
//
// This is an alpha field and requires enabling the
// DynamicResourceAllocation feature gate.
//
// This field is immutable.
//
// +patchMergeKey=name
// +patchStrategy=merge,retainKeys
// +listType=map
// +listMapKey=name
// +featureGate=DynamicResourceAllocation
// +optional
ResourceClaims []PodResourceClaim `json:"resourceClaims,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name" protobuf:"bytes,39,rep,name=resourceClaims"`
// Resources is the total amount of CPU and Memory resources required by all
// containers in the pod. It supports specifying Requests and Limits for
// "cpu" and "memory" resource names only. ResourceClaims are not supported.
//
// This field enables fine-grained control over resource allocation for the
// entire pod, allowing resource sharing among containers in a pod.
// TODO: For beta graduation, expand this comment with a detailed explanation.
//
// This is an alpha field and requires enabling the PodLevelResources feature
// gate.
//
// +featureGate=PodLevelResources
// +optional
Resources *ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,40,opt,name=resources"`
}
PodStatus 结构体
PodStatus 的定义在同一个文件中:
// PodStatus represents information about the status of a pod. Status may trail the actual
// state of a system, especially if the node that hosts the pod cannot contact the control
// plane.
type PodStatus struct {
// If set, this represents the .metadata.generation that the pod status was set based upon.
// This is an alpha field. Enable PodObservedGenerationTracking to be able to use this field.
// +featureGate=PodObservedGenerationTracking
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty" protobuf:"varint,17,opt,name=observedGeneration"`
// The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle.
// The conditions array, the reason and message fields, and the individual container status
// arrays contain more detail about the pod's status.
// There are five possible phase values:
//
// Pending: The pod has been accepted by the Kubernetes system, but one or more of the
// container images has not been created. This includes time before being scheduled as
// well as time spent downloading images over the network, which could take a while.
// Running: The pod has been bound to a node, and all of the containers have been created.
// At least one container is still running, or is in the process of starting or restarting.
// Succeeded: All containers in the pod have terminated in success, and will not be restarted.
// Failed: All containers in the pod have terminated, and at least one container has
// terminated in failure. The container either exited with non-zero status or was terminated
// by the system.
// Unknown: For some reason the state of the pod could not be obtained, typically due to an
// error in communicating with the host of the pod.
//
// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase
// +optional
Phase PodPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase,casttype=PodPhase"`
// Current service state of pod.
// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions
// +optional
// +patchMergeKey=type
// +patchStrategy=merge
// +listType=map
// +listMapKey=type
Conditions []PodCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,2,rep,name=conditions"`
// A human readable message indicating details about why the pod is in this condition.
// +optional
Message string `json:"message,omitempty" protobuf:"bytes,3,opt,name=message"`
// A brief CamelCase message indicating details about why the pod is in this state.
// e.g. 'Evicted'
// +optional
Reason string `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"`
// nominatedNodeName is set only when this pod preempts other pods on the node, but it cannot be
// scheduled right away as preemption victims receive their graceful termination periods.
// This field does not guarantee that the pod will be scheduled on this node. Scheduler may decide
// to place the pod elsewhere if other nodes become available sooner. Scheduler may also decide to
// give the resources on this node to a higher priority pod that is created after preemption.
// As a result, this field may be different than PodSpec.nodeName when the pod is
// scheduled.
// +optional
NominatedNodeName string `json:"nominatedNodeName,omitempty" protobuf:"bytes,11,opt,name=nominatedNodeName"`
// hostIP holds the IP address of the host to which the pod is assigned. Empty if the pod has not started yet.
// A pod can be assigned to a node that has a problem in kubelet which in turns mean that HostIP will
// not be updated even if there is a node is assigned to pod
// +optional
HostIP string `json:"hostIP,omitempty" protobuf:"bytes,5,opt,name=hostIP"`
// hostIPs holds the IP addresses allocated to the host. If this field is specified, the first entry must
// match the hostIP field. This list is empty if the pod has not started yet.
// A pod can be assigned to a node that has a problem in kubelet which in turns means that HostIPs will
// not be updated even if there is a node is assigned to this pod.
// +optional
// +patchStrategy=merge
// +patchMergeKey=ip
// +listType=atomic
HostIPs []HostIP `json:"hostIPs,omitempty" protobuf:"bytes,16,rep,name=hostIPs" patchStrategy:"merge" patchMergeKey:"ip"`
// podIP address allocated to the pod. Routable at least within the cluster.
// Empty if not yet allocated.
// +optional
PodIP string `json:"podIP,omitempty" protobuf:"bytes,6,opt,name=podIP"`
// podIPs holds the IP addresses allocated to the pod. If this field is specified, the 0th entry must
// match the podIP field. Pods may be allocated at most 1 value for each of IPv4 and IPv6. This list
// is empty if no IPs have been allocated yet.
// +optional
// +patchStrategy=merge
// +patchMergeKey=ip
// +listType=map
// +listMapKey=ip
PodIPs []PodIP `json:"podIPs,omitempty" protobuf:"bytes,12,rep,name=podIPs" patchStrategy:"merge" patchMergeKey:"ip"`
// RFC 3339 date and time at which the object was acknowledged by the Kubelet.
// This is before the Kubelet pulled the container image(s) for the pod.
// +optional
StartTime *metav1.Time `json:"startTime,omitempty" protobuf:"bytes,7,opt,name=startTime"`
// Statuses of init containers in this pod. The most recent successful non-restartable
// init container will have ready = true, the most recently started container will have
// startTime set.
// Each init container in the pod should have at most one status in this list,
// and all statuses should be for containers in the pod.
// However this is not enforced.
// If a status for a non-existent container is present in the list, or the list has duplicate names,
// the behavior of various Kubernetes components is not defined and those statuses might be
// ignored.
// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-and-container-status
// +listType=atomic
InitContainerStatuses []ContainerStatus `json:"initContainerStatuses,omitempty" protobuf:"bytes,10,rep,name=initContainerStatuses"`
// Statuses of containers in this pod.
// Each container in the pod should have at most one status in this list,
// and all statuses should be for containers in the pod.
// However this is not enforced.
// If a status for a non-existent container is present in the list, or the list has duplicate names,
// the behavior of various Kubernetes components is not defined and those statuses might be
// ignored.
// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status
// +optional
// +listType=atomic
ContainerStatuses []ContainerStatus `json:"containerStatuses,omitempty" protobuf:"bytes,8,rep,name=containerStatuses"`
// The Quality of Service (QOS) classification assigned to the pod based on resource requirements
// See PodQOSClass type for available QOS classes
// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-qos/#quality-of-service-classes
// +optional
QOSClass PodQOSClass `json:"qosClass,omitempty" protobuf:"bytes,9,rep,name=qosClass"`
// Statuses for any ephemeral containers that have run in this pod.
// Each ephemeral container in the pod should have at most one status in this list,
// and all statuses should be for containers in the pod.
// However this is not enforced.
// If a status for a non-existent container is present in the list, or the list has duplicate names,
// the behavior of various Kubernetes components is not defined and those statuses might be
// ignored.
// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status
// +optional
// +listType=atomic
EphemeralContainerStatuses []ContainerStatus `json:"ephemeralContainerStatuses,omitempty" protobuf:"bytes,13,rep,name=ephemeralContainerStatuses"`
// Status of resources resize desired for pod's containers.
// It is empty if no resources resize is pending.
// Any changes to container resources will automatically set this to "Proposed"
// Deprecated: Resize status is moved to two pod conditions PodResizePending and PodResizeInProgress.
// PodResizePending will track states where the spec has been resized, but the Kubelet has not yet allocated the resources.
// PodResizeInProgress will track in-progress resizes, and should be present whenever allocated resources != acknowledged resources.
// +featureGate=InPlacePodVerticalScaling
// +optional
Resize PodResizeStatus `json:"resize,omitempty" protobuf:"bytes,14,opt,name=resize,casttype=PodResizeStatus"`
// Status of resource claims.
// +patchMergeKey=name
// +patchStrategy=merge,retainKeys
// +listType=map
// +listMapKey=name
// +featureGate=DynamicResourceAllocation
// +optional
ResourceClaimStatuses []PodResourceClaimStatus `json:"resourceClaimStatuses,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name" protobuf:"bytes,15,rep,name=resourceClaimStatuses"`
}
reference 文档
pod 的 reference 文档:
https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/workload-resources/pod-v1/
4.1.3 - pkg\api\pod\util.go
文件列表具体为:
- pkg\api\pod\util.go
4.1.3.1 - ContainerType
ContainerType 定义
ContainerType 类型定义,有3个类型:
// ContainerType signifies container type
type ContainerType int
const (
// Containers is for normal containers
Containers ContainerType = 1 << iota
// InitContainers is for init containers
InitContainers
// EphemeralContainers is for ephemeral containers
EphemeralContainers
)
// AllContainers specifies that all containers be visited
const AllContainers ContainerType = (InitContainers | Containers | EphemeralContainers)
AllFeatureEnabledContainers() 方法
AllFeatureEnabledContainers() 方法 返回一个 ContainerType mask,其中包括所有容器类型,但受 feature gate 保护的容器类型除外。
// AllContainers specifies that all containers be visited
const AllContainers ContainerType = (InitContainers | Containers | EphemeralContainers)
// AllFeatureEnabledContainers returns a ContainerType mask which includes all container
// types except for the ones guarded by feature gate.
func AllFeatureEnabledContainers() ContainerType {
return AllContainers
}
备注: 没有什么 feature gate 啊
4.1.3.2 - ContainerVisitor
ContainerType 定义
ContainerVisitor 类型定义:
// ContainerVisitor is called with each container spec, and returns true
// if visiting should continue.
type ContainerVisitor func(container *api.Container, containerType ContainerType) (shouldContinue bool)
每个容器规格都会调用 ContainerVisitor,如果应该继续访问,则返回 true 。
VisitContainers() 方法
VisitContainers() 方法使用指向给定 pod spec 中每个容器规格的指针调用访问者函数,容器规格的类型在掩码中设置。
如果 visitor 返回 false,则表示访问短路。如果访问完成,VisitContainers 返回 true;如果访问短路,则返回 false。
// VisitContainers invokes the visitor function with a pointer to every container
// spec in the given pod spec with type set in mask. If visitor returns false,
// visiting is short-circuited. VisitContainers returns true if visiting completes,
// false if visiting was short-circuited.
func VisitContainers(podSpec *api.PodSpec, mask ContainerType, visitor ContainerVisitor) bool {
// 如果 ContainerType 是 InitContainers
if mask&InitContainers != 0 {
// 对于每个 InitContainer
for i := range podSpec.InitContainers {
//调用 visitor() 方法
if !visitor(&podSpec.InitContainers[i], InitContainers) {
// 只要任何一个返回 false,则中断并返回 false
return false
}
}
}
// 如果 ContainerType 是普通 Containers
if mask&Containers != 0 {
// 对于每个 普通 Container
for i := range podSpec.Containers {
if !visitor(&podSpec.Containers[i], Containers) {
return false
}
}
}
// 如果 ContainerType 是普通 EphemeralContainers
if mask&EphemeralContainers != 0 {
// 对于每个 EphemeralContainers
for i := range podSpec.EphemeralContainers {
if !visitor((*api.Container)(&podSpec.EphemeralContainers[i].EphemeralContainerCommon), EphemeralContainers) {
return false
}
}
}
return true
}
4.1.3.3 - Visitor
Visitor() 方法定义
Visitor() 方法会被每个对象名称调用,如果要继续访问,则返回 true
// Visitor is called with each object name, and returns true if visiting should continue
type Visitor func(name string) (shouldContinue bool)
skipEmptyNames() 方法
skipEmptyNames 检查 name 是否为空,如果是,则跳过 visitor() 方法的调用,直接返回 true。
func skipEmptyNames(visitor Visitor) Visitor {
return func(name string) bool {
if len(name) == 0 {
// continue visiting
// 相当于如果 name 为空,则跳过 visitor() 方法直接返回 true
return true
}
// delegate to visitor
return visitor(name)
}
}
VisitPodSecretNames() 方法
VisitPodSecretNames() 方法 会调用 visit() 函数,并输入 pod spec 引用的每个 secret 的名称。
如果 visitor 返回 false,则访问将被短路。
不会访问传递引用(例如 pod -> pvc -> pv -> secret)。
如果访问完成,则返回 true;如果访问短路,则返回 false。
// VisitPodSecretNames invokes the visitor function with the name of every secret
// referenced by the pod spec. If visitor returns false, visiting is short-circuited.
// Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
// Returns true if visiting completed, false if visiting was short-circuited.
func VisitPodSecretNames(pod *api.Pod, visitor Visitor, containerType ContainerType) bool {
// 跳过空名称
visitor = skipEmptyNames(visitor)
// 对于每个 ImagePullSecrets
for _, reference := range pod.Spec.ImagePullSecrets {
if !visitor(reference.Name) {
return false
}
}
// 调用 VisitContainers() 方法,检查 container 的 secret
// 传入 ContainerVisitor 方法实现为调用 visitContainerSecretNames() 方法
VisitContainers(&pod.Spec, containerType, func(c *api.Container, containerType ContainerType) bool {
return visitContainerSecretNames(c, visitor)
})
// 对于每个 Volume,检查 Volume 的 secret
var source *api.VolumeSource
for i := range pod.Spec.Volumes {
source = &pod.Spec.Volumes[i].VolumeSource
switch {
case source.AzureFile != nil:
if len(source.AzureFile.SecretName) > 0 && !visitor(source.AzureFile.SecretName) {
return false
}
case source.CephFS != nil:
if source.CephFS.SecretRef != nil && !visitor(source.CephFS.SecretRef.Name) {
return false
}
case source.Cinder != nil:
if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Name) {
return false
}
case source.FlexVolume != nil:
if source.FlexVolume.SecretRef != nil && !visitor(source.FlexVolume.SecretRef.Name) {
return false
}
case source.Projected != nil:
for j := range source.Projected.Sources {
if source.Projected.Sources[j].Secret != nil {
if !visitor(source.Projected.Sources[j].Secret.Name) {
return false
}
}
}
case source.RBD != nil:
if source.RBD.SecretRef != nil && !visitor(source.RBD.SecretRef.Name) {
return false
}
case source.Secret != nil:
if !visitor(source.Secret.SecretName) {
return false
}
case source.ScaleIO != nil:
if source.ScaleIO.SecretRef != nil && !visitor(source.ScaleIO.SecretRef.Name) {
return false
}
case source.ISCSI != nil:
if source.ISCSI.SecretRef != nil && !visitor(source.ISCSI.SecretRef.Name) {
return false
}
case source.StorageOS != nil:
if source.StorageOS.SecretRef != nil && !visitor(source.StorageOS.SecretRef.Name) {
return false
}
case source.CSI != nil:
if source.CSI.NodePublishSecretRef != nil && !visitor(source.CSI.NodePublishSecretRef.Name) {
return false
}
}
}
return true
}
visitContainerSecretNames() 方法游历 container.EnvFrom 和 container.Env,检查 SecretRef 和 SecretKeyRef 的 name:
func visitContainerSecretNames(container *api.Container, visitor Visitor) bool {
for _, env := range container.EnvFrom {
if env.SecretRef != nil {
if !visitor(env.SecretRef.Name) {
return false
}
}
}
for _, envVar := range container.Env {
if envVar.ValueFrom != nil && envVar.ValueFrom.SecretKeyRef != nil {
if !visitor(envVar.ValueFrom.SecretKeyRef.Name) {
return false
}
}
}
return true
}
VisitPodConfigmapNames() 方法
VisitPodConfigMapNames() 方法 会调用 visitor 函数,并输入 pod spec 引用的每个 config map 的名称。
如果 visitor 返回 false,则访问将被短路。
不会访问传递引用(例如 pod -> pvc -> pv -> secret)。
如果访问完成,则返回 true;如果访问短路,则返回 false。
func VisitPodConfigmapNames(pod *api.Pod, visitor Visitor, containerType ContainerType) bool {
visitor = skipEmptyNames(visitor)
VisitContainers(&pod.Spec, containerType, func(c *api.Container, containerType ContainerType) bool {
return visitContainerConfigmapNames(c, visitor)
})
var source *api.VolumeSource
for i := range pod.Spec.Volumes {
source = &pod.Spec.Volumes[i].VolumeSource
switch {
case source.Projected != nil:
for j := range source.Projected.Sources {
if source.Projected.Sources[j].ConfigMap != nil {
if !visitor(source.Projected.Sources[j].ConfigMap.Name) {
return false
}
}
}
case source.ConfigMap != nil:
if !visitor(source.ConfigMap.Name) {
return false
}
}
}
return true
}
visitContainerConfigmapNames() 方法游历 container.EnvFrom 和 container.Env,检查 ConfigMapRef 和 ConfigMapKeyRef 的 name:
func visitContainerConfigmapNames(container *api.Container, visitor Visitor) bool {
for _, env := range container.EnvFrom {
if env.ConfigMapRef != nil {
if !visitor(env.ConfigMapRef.Name) {
return false
}
}
}
for _, envVar := range container.Env {
if envVar.ValueFrom != nil && envVar.ValueFrom.ConfigMapKeyRef != nil {
if !visitor(envVar.ValueFrom.ConfigMapKeyRef.Name) {
return false
}
}
}
return true
}
4.1.3.4 - PodCondition
IsPodReady() 方法
如果 pod ready 则返回 true
// IsPodReady returns true if a pod is ready; false otherwise.
func IsPodReady(pod *api.Pod) bool {
return IsPodReadyConditionTrue(pod.Status)
}
IsPodReadyConditionTrue() 方法
IsPodReadyConditionTrue 检查 pod 的 PodStatus, 如果为 ConditionTrue 则返回 true:
// IsPodReadyConditionTrue returns true if a pod is ready; false otherwise.
func IsPodReadyConditionTrue(status api.PodStatus) bool {
condition := GetPodReadyCondition(status)
return condition != nil && condition.Status == api.ConditionTrue
}
GetPodReadyCondition() 方法
GetPodReadyCondition() 方法 从给定状态中提取 pod 就绪条件并返回。如果条件不存在,则返回 nil。
// GetPodReadyCondition extracts the pod ready condition from the given status and returns that.
// Returns nil if the condition is not present.
func GetPodReadyCondition(status api.PodStatus) *api.PodCondition {
_, condition := GetPodCondition(&status, api.PodReady)
return condition
}
GetPodCondition() 方法
GetPodCondition() 方法从给定的状态中提取所提供的 condition 并返回。
如果 condition 不存在,则返回 nil 和-1,
如果 condition 存在,则返回所定位 condition 的索引。
// GetPodCondition extracts the provided condition from the given status and returns that.
// Returns nil and -1 if the condition is not present, and the index of the located condition.
func GetPodCondition(status *api.PodStatus, conditionType api.PodConditionType) (int, *api.PodCondition) {
if status == nil {
// 如果 pod 的 status 为空
return -1, nil
}
// 游历 status.Conditions
for i := range status.Conditions {
// 如果等于指定的 conditionType
if status.Conditions[i].Type == conditionType {
// 返回 index 和 对应 conditionType 的 condition
// 这里只会找到的第一个符合 conditionType 要求的 condition
return i, &status.Conditions[i]
}
}
return -1, nil
}
UpdatePodCondition() 方法
UpdatePodCondition 更新现有 pod condition 或创建新的 pod condition。
如果状态已更改,则将 LastTransitionTime 设置为 now。
如果 pod condition 已更改或已添加,则返回 true。
// UpdatePodCondition updates existing pod condition or creates a new one. Sets LastTransitionTime to now if the
// status has changed.
// Returns true if pod condition has changed or has been added.
func UpdatePodCondition(status *api.PodStatus, condition *api.PodCondition) bool {
// 设置 LastTransitionTime 为当前时间
condition.LastTransitionTime = metav1.Now()
// Try to find this pod condition.
conditionIndex, oldCondition := GetPodCondition(status, condition.Type)
//如果没有找到,说明之前没有设置这个类型的 condition
if oldCondition == nil {
// We are adding new pod condition.
status.Conditions = append(status.Conditions, *condition)
return true
}
// We are updating an existing condition, so we need to check if it has changed.
if condition.Status == oldCondition.Status {
// 如果 condition 的 status 和 oldCondition 的 status 相同,则将 LastTransitionTime 设置为 oldCondition 的 LastTransitionTime
condition.LastTransitionTime = oldCondition.LastTransitionTime
}
// 检查传入的 condition 和现有的 conditon 是否完全等同
isEqual := condition.Status == oldCondition.Status &&
condition.Reason == oldCondition.Reason &&
condition.Message == oldCondition.Message &&
condition.LastProbeTime.Equal(&oldCondition.LastProbeTime) &&
condition.LastTransitionTime.Equal(&oldCondition.LastTransitionTime)
// 更新 condition
status.Conditions[conditionIndex] = *condition
// Return true if one of the fields have changed.
return !isEqual
}
4.1.3.5 - ValidationOptions
预备方法
检查 Huge Pages 的 usesIndivisibleHugePagesValues() 方法
如果其中一个容器使用非整数倍的 huge page 单位大小,则 usesIndivisibleHugePagesValues() 方法 返回 true
// usesIndivisibleHugePagesValues returns true if the one of the containers uses non-integer multiple
// of huge page unit size
func usesIndivisibleHugePagesValues(podSpec *api.PodSpec) bool {
// 初始化一个布尔变量,用于记录是否找到非整数倍的 huge page 单位大小
foundIndivisibleHugePagesValue := false
// 遍历 podSpec 中的所有容器
VisitContainers(podSpec, AllContainers, func(c *api.Container, containerType ContainerType) bool {
// 检查容器是否使用非整数倍的 huge page 单位大小
if checkContainerUseIndivisibleHugePagesValues(*c) {
// 如果找到,则将 foundIndivisibleHugePagesValue 设置为 true
foundIndivisibleHugePagesValue = true
}
// 如果还没有找到非整数倍的 huge page 单位大小,则继续遍历
return !foundIndivisibleHugePagesValue // continue visiting if we haven't seen an invalid value yet
})
// 如果找到非整数倍的 huge page 单位大小,则返回 true
if foundIndivisibleHugePagesValue {
return true
}
// 游历检查 pod spec 中的 Overhead
for resourceName, quantity := range podSpec.Overhead {
if helper.IsHugePageResourceName(resourceName) {
if !helper.IsHugePageResourceValueDivisible(resourceName, quantity) {
return true
}
}
}
return false
}
checkContainerUseIndivisibleHugePagesValues() 方法
func checkContainerUseIndivisibleHugePagesValues(container api.Container) bool {
for resourceName, quantity := range container.Resources.Limits {
if helper.IsHugePageResourceName(resourceName) {
if !helper.IsHugePageResourceValueDivisible(resourceName, quantity) {
return true
}
}
}
for resourceName, quantity := range container.Resources.Requests {
if helper.IsHugePageResourceName(resourceName) {
if !helper.IsHugePageResourceValueDivisible(resourceName, quantity) {
return true
}
}
}
return false
}
检查 Topology Spread Constraints 的 hasInvalidTopologySpreadConstraintLabelSelector() 方法
hasInvalidTopologySpreadConstraintLabelSelector 如果 spec.TopologySpreadConstraints 有任何标签选择器无效的条目,则返回 true
// hasInvalidTopologySpreadConstraintLabelSelector return true if spec.TopologySpreadConstraints have any entry with invalid labelSelector
func hasInvalidTopologySpreadConstraintLabelSelector(spec *api.PodSpec) bool {
for _, constraint := range spec.TopologySpreadConstraints {
errs := metavalidation.ValidateLabelSelector(constraint.LabelSelector, metavalidation.LabelSelectorValidationOptions{AllowInvalidLabelValueInSelector: false}, nil)
if len(errs) != 0 {
return true
}
}
return false
}
TopologySpreadConstraints = 拓扑扩展限制
检查 Volumes 的 hasNonLocalProjectedTokenPath() 方法
hasNonLocalProjectedTokenPath 如果 spec.Volumes 有任何条目具有非本地投影标记路径(non-local projected token path),则返回 true
// hasNonLocalProjectedTokenPath return true if spec.Volumes have any entry with non-local projected token path
func hasNonLocalProjectedTokenPath(spec *api.PodSpec) bool {
for _, volume := range spec.Volumes {
if volume.Projected != nil {
for _, source := range volume.Projected.Sources {
if source.ServiceAccountToken == nil {
continue
}
errs := apivalidation.ValidateLocalNonReservedPath(source.ServiceAccountToken.Path, nil)
if len(errs) != 0 {
return true
}
}
}
}
return false
}
GetValidationOptionsFromPodSpecAndMeta() 方法
GetValidationOptionsFromPodSpecAndMeta() 方法 根据 pod spec和元数据返回验证选项:
// GetValidationOptionsFromPodSpecAndMeta returns validation options based on pod specs and metadata
func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, podMeta, oldPodMeta *metav1.ObjectMeta) apivalidation.PodValidationOptions {
// 默认的 pod 验证选项基于 feature gate
opts := apivalidation.PodValidationOptions{
AllowInvalidPodDeletionCost: !utilfeature.DefaultFeatureGate.Enabled(features.PodDeletionCost),
// Do not allow pod spec to use non-integer multiple of huge page unit size default
AllowIndivisibleHugePagesValues: false,
AllowInvalidLabelValueInSelector: false,
AllowInvalidTopologySpreadConstraintLabelSelector: false,
AllowNamespacedSysctlsForHostNetAndHostIPC: false,
AllowNonLocalProjectedTokenPath: false,
AllowPodLifecycleSleepActionZeroValue: utilfeature.DefaultFeatureGate.Enabled(features.PodLifecycleSleepActionAllowZero),
PodLevelResourcesEnabled: utilfeature.DefaultFeatureGate.Enabled(features.PodLevelResources),
AllowInvalidLabelValueInRequiredNodeAffinity: false,
AllowSidecarResizePolicy: utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling),
}
// 如果旧的 spec 使用宽松的验证或启用了 RelaxedEnvironmentVariableValidation feature gate,
// 我们必须允许它
opts.AllowRelaxedEnvironmentVariableValidation = useRelaxedEnvironmentVariableValidation(podSpec, oldPodSpec)
opts.AllowRelaxedDNSSearchValidation = useRelaxedDNSSearchValidation(oldPodSpec)
opts.AllowOnlyRecursiveSELinuxChangePolicy = useOnlyRecursiveSELinuxChangePolicy(oldPodSpec)
if oldPodSpec != nil {
// 如果旧的 spec 使用非整数倍的 huge page 单位大小,我们必须允许它
opts.AllowIndivisibleHugePagesValues = usesIndivisibleHugePagesValues(oldPodSpec)
opts.AllowInvalidLabelValueInSelector = hasInvalidLabelValueInAffinitySelector(oldPodSpec)
opts.AllowInvalidLabelValueInRequiredNodeAffinity = hasInvalidLabelValueInRequiredNodeAffinity(oldPodSpec)
// 如果旧的 spec 有无效的标签选择器在 topologySpreadConstraint,我们必须允许它
opts.AllowInvalidTopologySpreadConstraintLabelSelector = hasInvalidTopologySpreadConstraintLabelSelector(oldPodSpec)
// 如果旧的 spec 有无效的投影标记卷路径,我们必须允许它
opts.AllowNonLocalProjectedTokenPath = hasNonLocalProjectedTokenPath(oldPodSpec)
// 如果旧的 spec 有无效的 sysctl 与 hostNet 或 hostIPC,我们必须允许它在更新时
if oldPodSpec.SecurityContext != nil && len(oldPodSpec.SecurityContext.Sysctls) != 0 {
for _, s := range oldPodSpec.SecurityContext.Sysctls {
err := apivalidation.ValidateHostSysctl(s.Name, oldPodSpec.SecurityContext, nil)
if err != nil {
opts.AllowNamespacedSysctlsForHostNetAndHostIPC = true
break
}
}
}
opts.AllowPodLifecycleSleepActionZeroValue = opts.AllowPodLifecycleSleepActionZeroValue || podLifecycleSleepActionZeroValueInUse(oldPodSpec)
// 如果旧的 pod 有在可重启的 init 容器上设置的 resize 策略,我们必须允许它
opts.AllowSidecarResizePolicy = opts.AllowSidecarResizePolicy || hasRestartableInitContainerResizePolicy(oldPodSpec)
}
if oldPodMeta != nil && !opts.AllowInvalidPodDeletionCost {
// 这是一个更新,所以只验证现有的对象是否有效
_, err := helper.GetDeletionCostFromPodAnnotations(oldPodMeta.Annotations)
opts.AllowInvalidPodDeletionCost = err != nil
}
return opts
}
useRelaxedEnvironmentVariableValidation() 方法, 如果旧的 spec 使用宽松的验证或启用了 RelaxedEnvironmentVariableValidation feature gate,则返回 true
func useRelaxedEnvironmentVariableValidation(podSpec, oldPodSpec *api.PodSpec) bool {
if utilfeature.DefaultFeatureGate.Enabled(features.RelaxedEnvironmentVariableValidation) {
return true
}
var oldPodEnvVarNames, podEnvVarNames sets.Set[string]
if oldPodSpec != nil {
oldPodEnvVarNames = gatherPodEnvVarNames(oldPodSpec)
}
if podSpec != nil {
podEnvVarNames = gatherPodEnvVarNames(podSpec)
}
for env := range podEnvVarNames {
if relaxedEnvVarUsed(env, oldPodEnvVarNames) {
return true
}
}
return false
}
useRelaxedDNSSearchValidation() 方法, 如果旧的 spec 使用宽松的验证或启用了 RelaxedDNSSearchValidation feature gate,则返回 true
func useRelaxedDNSSearchValidation(oldPodSpec *api.PodSpec) bool {
// Return true early if feature gate is enabled
if utilfeature.DefaultFeatureGate.Enabled(features.RelaxedDNSSearchValidation) {
return true
}
// Return false early if there is no DNSConfig or Searches.
if oldPodSpec == nil || oldPodSpec.DNSConfig == nil || oldPodSpec.DNSConfig.Searches == nil {
return false
}
return hasDotOrUnderscore(oldPodSpec.DNSConfig.Searches)
}
hasDotOrUnderscore() 方法检查是否存在点或下划线:
// Helper function to check if any domain is a dot or contains an underscore.
func hasDotOrUnderscore(searches []string) bool {
for _, domain := range searches {
if domain == "." || strings.Contains(domain, "_") {
return true
}
}
return false
}
gatherPodEnvVarNames() 方法收集 pod 环境变量名称:
func gatherPodEnvVarNames(podSpec *api.PodSpec) sets.Set[string] {
podEnvVarNames := sets.Set[string]{}
for _, c := range podSpec.Containers {
for _, env := range c.Env {
podEnvVarNames.Insert(env.Name)
}
for _, env := range c.EnvFrom {
podEnvVarNames.Insert(env.Prefix)
}
}
for _, c := range podSpec.InitContainers {
for _, env := range c.Env {
podEnvVarNames.Insert(env.Name)
}
for _, env := range c.EnvFrom {
podEnvVarNames.Insert(env.Prefix)
}
}
for _, c := range podSpec.EphemeralContainers {
for _, env := range c.Env {
podEnvVarNames.Insert(env.Name)
}
for _, env := range c.EnvFrom {
podEnvVarNames.Insert(env.Prefix)
}
}
return podEnvVarNames
}
relaxedEnvVarUsed() 检查是否使用宽松的环境变量名称:
func relaxedEnvVarUsed(name string, oldPodEnvVarNames sets.Set[string]) bool {
// A length of 0 means this is not an update request,
// or the old pod does not exist in the env.
// We will let the feature gate decide whether to use relaxed rules.
if oldPodEnvVarNames.Len() == 0 {
return false
}
if len(validation.IsEnvVarName(name)) == 0 || len(validation.IsRelaxedEnvVarName(name)) != 0 {
// It's either a valid name by strict rules or an invalid name under relaxed rules.
// Either way, we'll use strict rules to validate.
return false
}
// The name in question failed strict rules but passed relaxed rules.
if oldPodEnvVarNames.Has(name) {
// This relaxed-rules name was already in use.
return true
}
return false
}
GetValidationOptionsFromPodTemplate() 方法
GetValidationOptionsFromPodTemplate() 方法 将返回指定模板的 pod 验证选项。
// GetValidationOptionsFromPodTemplate will return pod validation options for specified template.
func GetValidationOptionsFromPodTemplate(podTemplate, oldPodTemplate *api.PodTemplateSpec) apivalidation.PodValidationOptions {
var newPodSpec, oldPodSpec *api.PodSpec
var newPodMeta, oldPodMeta *metav1.ObjectMeta
// 我们必须小心这里关于 nil 指针的问题
// 特别是 replication controller 容易传递 nil
if podTemplate != nil {
newPodSpec = &podTemplate.Spec
newPodMeta = &podTemplate.ObjectMeta
}
if oldPodTemplate != nil {
oldPodSpec = &oldPodTemplate.Spec
oldPodMeta = &oldPodTemplate.ObjectMeta
}
return GetValidationOptionsFromPodSpecAndMeta(newPodSpec, oldPodSpec, newPodMeta, oldPodMeta)
}
4.1.3.6 - Drop
DropDisabledTemplateFields() 方法
DropDisabledTemplateFields() 方法 删除 pod 模板元数据和规范中禁用的字段。
对于包含 PodTemplateSpec 的所有资源,应在 PrepareForCreate/PrepareForUpdate 中调用此功能。
// DropDisabledTemplateFields removes disabled fields from the pod template metadata and spec.
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a PodTemplateSpec
func DropDisabledTemplateFields(podTemplate, oldPodTemplate *api.PodTemplateSpec) {
var (
podSpec *api.PodSpec
podAnnotations map[string]string
oldPodSpec *api.PodSpec
oldPodAnnotations map[string]string
)
if podTemplate != nil {
podSpec = &podTemplate.Spec
podAnnotations = podTemplate.Annotations
}
if oldPodTemplate != nil {
oldPodSpec = &oldPodTemplate.Spec
oldPodAnnotations = oldPodTemplate.Annotations
}
dropDisabledFields(podSpec, podAnnotations, oldPodSpec, oldPodAnnotations)
}
dropDisabledFields() 方法
dropDisabledFields() 方法 会删除 pod 元数据和规范中禁用的字段。
// dropDisabledFields removes disabled fields from the pod metadata and spec.
func dropDisabledFields(
podSpec *api.PodSpec, podAnnotations map[string]string,
oldPodSpec *api.PodSpec, oldPodAnnotations map[string]string,
) {
// the new spec must always be non-nil
if podSpec == nil {
podSpec = &api.PodSpec{}
}
// 如果 feature 被禁用且未在 use,则删除 hostUsers 字段。
if !utilfeature.DefaultFeatureGate.Enabled(features.UserNamespacesSupport) && !hostUsersInUse(oldPodSpec) {
// 仅在 SecurityContext 不为 nil 时删除 podSpec 中的字段。
// 如果为 nil,则不需要设置 hostUsers=nil(它也将为 nil)。
if podSpec.SecurityContext != nil {
podSpec.SecurityContext.HostUsers = nil
}
}
// 如果 feature 被禁用且未在 use,则删除 SupplementalGroupsPolicy 字段。
if !utilfeature.DefaultFeatureGate.Enabled(features.SupplementalGroupsPolicy) && !supplementalGroupsPolicyInUse(oldPodSpec) {
// 仅在 SecurityContext 不为 nil 时删除 podSpec 中的字段。
// 如果为 nil,则不需要设置 supplementalGroupsPolicy=nil(它也将为 nil)。
if podSpec.SecurityContext != nil {
podSpec.SecurityContext.SupplementalGroupsPolicy = nil
}
}
dropDisabledPodLevelResources(podSpec, oldPodSpec)
dropDisabledProcMountField(podSpec, oldPodSpec)
dropDisabledNodeInclusionPolicyFields(podSpec, oldPodSpec)
dropDisabledMatchLabelKeysFieldInTopologySpread(podSpec, oldPodSpec)
dropDisabledMatchLabelKeysFieldInPodAffinity(podSpec, oldPodSpec)
dropDisabledDynamicResourceAllocationFields(podSpec, oldPodSpec)
dropDisabledClusterTrustBundleProjection(podSpec, oldPodSpec)
if !utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) && !inPlacePodVerticalScalingInUse(oldPodSpec) {
// Drop ResizePolicy fields. Don't drop updates to Resources field as template.spec.resources
// field is mutable for certain controllers. Let ValidatePodUpdate handle it.
for i := range podSpec.Containers {
podSpec.Containers[i].ResizePolicy = nil
}
for i := range podSpec.InitContainers {
podSpec.InitContainers[i].ResizePolicy = nil
}
for i := range podSpec.EphemeralContainers {
podSpec.EphemeralContainers[i].ResizePolicy = nil
}
}
if !utilfeature.DefaultFeatureGate.Enabled(features.SidecarContainers) && !restartableInitContainersInUse(oldPodSpec) {
// Drop the RestartPolicy field of init containers.
for i := range podSpec.InitContainers {
podSpec.InitContainers[i].RestartPolicy = nil
}
// For other types of containers, validateContainers will handle them.
}
if !utilfeature.DefaultFeatureGate.Enabled(features.RecursiveReadOnlyMounts) && !rroInUse(oldPodSpec) {
for i := range podSpec.Containers {
for j := range podSpec.Containers[i].VolumeMounts {
podSpec.Containers[i].VolumeMounts[j].RecursiveReadOnly = nil
}
}
for i := range podSpec.InitContainers {
for j := range podSpec.InitContainers[i].VolumeMounts {
podSpec.InitContainers[i].VolumeMounts[j].RecursiveReadOnly = nil
}
}
for i := range podSpec.EphemeralContainers {
for j := range podSpec.EphemeralContainers[i].VolumeMounts {
podSpec.EphemeralContainers[i].VolumeMounts[j].RecursiveReadOnly = nil
}
}
}
dropPodLifecycleSleepAction(podSpec, oldPodSpec)
dropImageVolumes(podSpec, oldPodSpec)
dropSELinuxChangePolicy(podSpec, oldPodSpec)
dropContainerStopSignals(podSpec, oldPodSpec)
}
DropDisabledPodFields() 方法
DropDisabledPodFields 删除 Pod 元数据和规范中禁用的字段。
对于包含 Pod 的所有资源,应在 PrepareForCreate/PrepareForUpdate 中调用此功能。
// DropDisabledPodFields removes disabled fields from the pod metadata and spec.
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a Pod
func DropDisabledPodFields(pod, oldPod *api.Pod) {
var (
podSpec *api.PodSpec
podStatus *api.PodStatus
podAnnotations map[string]string
oldPodSpec *api.PodSpec
oldPodStatus *api.PodStatus
oldPodAnnotations map[string]string
)
if pod != nil {
podSpec = &pod.Spec
podStatus = &pod.Status
podAnnotations = pod.Annotations
}
if oldPod != nil {
oldPodSpec = &oldPod.Spec
oldPodStatus = &oldPod.Status
oldPodAnnotations = oldPod.Annotations
}
dropDisabledFields(podSpec, podAnnotations, oldPodSpec, oldPodAnnotations)
dropDisabledPodStatusFields(podStatus, oldPodStatus, podSpec, oldPodSpec)
}
dropDisabledPodStatusFields() 方法
dropDisabledPodStatusFields() 方法 删除 pod 状态中已禁用的字段
// dropDisabledPodStatusFields removes disabled fields from the pod status
func dropDisabledPodStatusFields(podStatus, oldPodStatus *api.PodStatus, podSpec, oldPodSpec *api.PodSpec) {
// 新的状态总是非 nil
if podStatus == nil {
podStatus = &api.PodStatus{}
}
if !utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) && !inPlacePodVerticalScalingInUse(oldPodSpec) {
// 删除 Resources 字段
dropResourcesField := func(csl []api.ContainerStatus) {
for i := range csl {
csl[i].Resources = nil
}
}
dropResourcesField(podStatus.ContainerStatuses)
dropResourcesField(podStatus.InitContainerStatuses)
dropResourcesField(podStatus.EphemeralContainerStatuses)
// 删除 AllocatedResources 字段
dropAllocatedResourcesField := func(csl []api.ContainerStatus) {
for i := range csl {
csl[i].AllocatedResources = nil
}
}
dropAllocatedResourcesField(podStatus.ContainerStatuses)
dropAllocatedResourcesField(podStatus.InitContainerStatuses)
dropAllocatedResourcesField(podStatus.EphemeralContainerStatuses)
}
if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) && !dynamicResourceAllocationInUse(oldPodSpec) {
podStatus.ResourceClaimStatuses = nil
}
if !utilfeature.DefaultFeatureGate.Enabled(features.RecursiveReadOnlyMounts) && !rroInUse(oldPodSpec) {
for i := range podStatus.ContainerStatuses {
podStatus.ContainerStatuses[i].VolumeMounts = nil
}
for i := range podStatus.InitContainerStatuses {
podStatus.InitContainerStatuses[i].VolumeMounts = nil
}
for i := range podStatus.EphemeralContainerStatuses {
podStatus.EphemeralContainerStatuses[i].VolumeMounts = nil
}
}
if !utilfeature.DefaultFeatureGate.Enabled(features.ResourceHealthStatus) {
setAllocatedResourcesStatusToNil := func(csl []api.ContainerStatus) {
for i := range csl {
csl[i].AllocatedResourcesStatus = nil
}
}
setAllocatedResourcesStatusToNil(podStatus.ContainerStatuses)
setAllocatedResourcesStatusToNil(podStatus.InitContainerStatuses)
setAllocatedResourcesStatusToNil(podStatus.EphemeralContainerStatuses)
}
// drop ContainerStatus.User field to empty (disable SupplementalGroupsPolicy)
if !utilfeature.DefaultFeatureGate.Enabled(features.SupplementalGroupsPolicy) && !supplementalGroupsPolicyInUse(oldPodSpec) {
dropUserField := func(csl []api.ContainerStatus) {
for i := range csl {
csl[i].User = nil
}
}
dropUserField(podStatus.InitContainerStatuses)
dropUserField(podStatus.ContainerStatuses)
dropUserField(podStatus.EphemeralContainerStatuses)
}
if !utilfeature.DefaultFeatureGate.Enabled(features.PodObservedGenerationTracking) && !podObservedGenerationTrackingInUse(oldPodStatus) {
podStatus.ObservedGeneration = 0
for i := range podStatus.Conditions {
podStatus.Conditions[i].ObservedGeneration = 0
}
}
}
4.1.4 - pkg\api\pod\warnings.go
文件列表具体为:
- pkg\api\pod\warnings.go