听GPT 讲K8s源代码--pkg(四)

/pkg/controlplane、/pkg/credentialprovider、/pkg/kubeapiserver是Kubernetes中的三个核心包,它们分别实现了不同的功能。

/pkg/controlplane包

/pkg/controlplane是Kubernetes的一个包,它包含了控制平面组件的实现,例如API Server、Controller Manager、Scheduler等。这些组件是Kubernetes的核心部分,负责管理集群中的资源,调度容器,提供API服务等。控制平面组件的实现是Kubernetes中最复杂的部分之一,需要考虑到高可用性、数据一致性、安全性等方面的问题。控制平面组件的实现对于Kubernetes的正确运行至关重要,因为它们是集群的大脑,负责决策和协调集群中的所有操作。

/pkg/credentialprovider包

/pkg/credentialprovider是Kubernetes的另一个包,它实现了Kubernetes的凭证提供者接口,负责从外部获取认证和授权所需的凭证,例如TLS证书、Token、用户名和密码等。这些凭证用于访问Kubernetes集群中的API服务器或其它服务。在Kubernetes中,凭证提供者接口是一个插件化的接口,可以支持不同的认证和授权机制。/pkg/credentialprovider包实现了一些默认的凭证提供者,例如从Docker配置文件中获取认证信息、从Kubernetes Secret中获取TLS证书等。

/pkg/kubeapiserver包

/pkg/kubeapiserver是Kubernetes的另一个核心包,它实现了Kubernetes API Server,负责处理所有的API请求,并将它们路由到正确的控制平面组件中进行处理。Kubernetes API Server是Kubernetes集群的入口点,所有的Kubernetes操作都通过API Server进行。/pkg/kubeapiserver包实现了Kubernetes API Server的核心功能,包括API请求的认证、授权、路由、转发等。Kubernetes API Server还支持多版本的API,/pkg/kubeapiserver包也实现了这些API版本之间的转换和兼容性。

alt



File: pkg/controlplane/apiserver/apiextensions.go

pkg/controlplane/apiserver/apiextensions.go 是 Kubernetes 中扩展 API 的核心代码文件。扩展 API 是 Kubernetes 允许用户根据需要动态添加自定义 API 资源和 REST 操作的机制。

具体地说,这个文件提供了以下功能:

  1. 定义了 API 扩展组,用于将扩展 API 资源按照逻辑分组;
  2. 实现了自定义资源和 CRD(Custom Resource Definition)的注册和处理机制;
  3. 注册和启用了 Swagger 文档解析和展示功能;
  4. 支持 Kubernetes API 服务器自动生成 OpenAPI 规范;
  5. 定义了对 CRD 进行默认化和分析合并的功能。

其中,CreateAPIExtensionsConfig 函数是一个工厂函数,它根据传入的参数生成一个包含所有扩展 API 配置信息的 Config 结构体。

具体而言,CreateAPIExtensionsConfig 函数包括以下几个子函数:

  1. CreateCRDRESTStorage: 根据传入的 CRD 定义生成相应的 REST Storage,包括 create、get、list、watch、update 和 delete 操作;
  2. CreateCustomResourceStorage: 根据传入的自定义资源定义生成相应的 REST Storage; 3,AddAPIExtensionsConfig: 将传入的自定义资源定义或 CRD 定义添加到 API 扩展配置(Config)中;
  3. MakeSwaggerService: 根据传入的 API 扩展配置生成 Swagger API 文档。

总之,pkg/controlplane/apiserver/apiextensions.go 是 Kubernetes 扩展 API 的核心代码文件,定义了各种扩展 API 资源的注册、处理和配置机制,是 Kubernetes 可以灵活扩展和适应不同用户需求的重要工具。

File: pkg/credentialprovider/plugin/config.go

pkg/credentialprovider/plugin/config.go文件是Kubernetes的证书提供程序插件配置文件。该文件的作用是为Kubernetes集群中的不同资源(如Pod)提供可能需要的证书,例如Docker私有仓库的凭据。

readCredentialProviderConfigFile是一个函数,该函数的作用是读取一个配置文件,并返回读取结果,其中包含了所有的凭据提供者配置。

decode函数是一个函数,该函数的作用是将传入的数据解码成Config类型的结构。

validateCredentialProviderConfig函数是一个函数,该函数的作用是验证Config类型的结构中的数据是否有效和合法。例如,对于每一个provider,都需要验证其image,args和env等信息是否有效。

这三个函数一起构成了kubernetes的证书提供程序插件配置的基本流程,从读取配置文件到验证配置信息。这一过程最终会使得可以自动从存储和管理凭据的地方获取所需的凭据,并将其提供给相关的资源以进行后续操作。

File: pkg/controlplane/client_util.go

pkg/controlplane/client_util.go文件是Kubernetes项目中的一个客户端工具库,主要提供了一些常用的客户端操作函数,例如创建、删除资源、获取资源等操作。这个文件的作用是为了方便其它组件或特定需求在Kubernetes中创建和查询资源对象。

其中的createNamespaceIfNeeded是用来创建命名空间资源。在Kubernetes中,命名空间是一种可以用于隔离和管理部署和应用的资源的机制。这些资源也可以跨命名空间使用和共享,但是一般来说,Kubernetes中的资源会被划分到不同的命名空间中,以实现对资源的分离和控制。

createNamespaceIfNeeded函数的作用是检查是否存在一个指定的命名空间,如果没有,则会创建一个新的命名空间。这个函数需要传入一个clientset(即Kubernetes客户端),一个namespace名称和一个要被设置命名空间标签的标签结构体。函数首先会检查指定的命名空间是否已经存在,如果不存在,则它将使用指定的标识符创建新的命名空间。如果指定了标签,函数还会将这些标签附加到新创建的命名空间上。

总之,pkg/controlplane/client_util.go文件提供了一些常见的客户端操作函数和方法,这些函数和方法可以方便地创建、修改或删除Kubernetes中的资源。通过这些函数和方法,Kubernetes集群中的应用程序可以动态地创建和管理资源,而无需手动处理。这在Kubernetes的自动化部署和运维中非常有用。

File: pkg/controlplane/controller/clusterauthenticationtrust/cluster_authentication_trust_controller.go

pkg/controlplane/controller/clusterauthenticationtrust/cluster_authentication_trust_controller.go是Kubernetes中核心控制器(Cluster Controller)之一,可以为Kubernetes集群的访问控制提供额外的安全层保护。具体地说,此控制器通过观察Kubernetes ConfigMap、Namespace和证书过期情况来协助管理集群的安全认证信息(Cluster Authentication Info)。

在这个文件中,Controller结构体是负责启动和运行实际操作的最高层,与ClusterAuthenticationInfo结构体一起协调工作。ClusterAuthenticationInfo结构体保存有关集群的安全认证信息的数据结构。

NewClusterAuthenticationTrustController是控制器的构造函数,创建一个新的ClusterAuthenticationTrustController对象并返回引用。syncConfigMap函数用于同步Kubernetes ConfigMap内容和内存中的本地clusterAuthenticationInfo。createNamespaceIfNeeded函数用于创建可能不存在的Namespace,writeConfigMap函数用于将数据更新到ConfigMap中。

combinedClusterAuthenticationInfo函数的作用是根据默认值和ConfigMap的数据构建一个完整的ClusterAuthenticationInfo数据集。getConfigMapDataFor函数获取用于ClusterAuthenticationTrustController的ConfigMap数据。getClusterAuthenticationInfoFor函数根据提供的域名查找存储在ClusterAuthenticationTrustController中的证书列表。

jsonSerializeStringSlice和jsonDeserializeStringSlice函数分别用于将字符串切片序列化和反序列化。combineUniqueStringSlices函数通过将两个字符串切片组合为一个来组合唯一的字符串切片。combineCertLists函数用于组合唯一的证书列表。filterExpiredCerts函数用于过滤已过期的证书。

Enqueue函数用于将任务加入队列中,Run函数循环调用runWorker函数处理队列中的项目。runWorker函数获取下一个要处理的任务并调用processNextWorkItem函数来处理它。keyFn函数将提供的项目映射到它们独特的标识符,以便将它们加入队列中。

encodeCertificates函数将X.509证书编码为PEM格式的字符串。

File: pkg/controlplane/controller/crdregistration/crdregistration_controller.go

在 Kubernetes 项目中,pkg/controlplane/controller/crdregistration/crdregistration_controller.go 文件的作用是实现 Custom Resource Definition(简称 CRD)的自动注册。

这个文件中定义了两个重要的结构体:AutoAPIServiceRegistration 和 crdRegistrationController。其中 AutoAPIServiceRegistration 用于自动注册 Kubernetes API。当 Kubernetes 发现新的 API 资源时,它会尝试自动注册该 API,这样就可以通过 Kubernetes API Server 访问该资源。而 crdRegistrationController 是 Kubernetes 控制器库中的一个控制器,它负责在 Kubernetes 群集中安装自定义资源定义(CRD)并为其创建 API endpoints。

NewCRDRegistrationController 函数用于创建一个新的 CRD 注册控制器。这个函数会返回一个 crdRegistrationController 结构体指针。Run 函数用于启动 CRD 注册控制器,它会将注册的 CRD 作为任务加入到任务队列中,等待被处理。WaitForInitialSync 函数用于阻塞程序直到所有 CRD 注册都完成并且 API Server 上所有资源都已经同步。runWorker 函数是 CRD 注册控制器中的一个私有函数,它用于处理任务队列中的任务。processNextWorkItem 函数用于处理 CRD 注册任务,并将新的任务加入到任务队列中。enqueueCRD 函数用于将需要注册的 CRD 添加到注册任务队列中。handleVersionUpdate 函数用于处理 API 资源的版本更新,当版本更新时,它会将相应的资源更新到 API Server 的 endpoints 中。

总之,这个文件实现了 Custom Resource Definition 的自动注册功能,使得我们可以自定义 Kubernetes 的 API 资源,从而更好地管理 Kubernetes 群集中的应用。同时,它提供了一些工具函数和控制器,用于处理注册任务队列中的任务和更新 API endpoints。

File: pkg/controlplane/controller/systemnamespaces/system_namespaces_controller.go

pkg/controlplane/controller/systemnamespaces/system_namespaces_controller.go文件的作用是管理Kubernetes中的系统命名空间。这些命名空间是Kubernetes内部使用的,例如kube-system、kube-public和kube-node-lease。通过SystemNamespacesController,可以确保这些命名空间的创建、更新和删除是以正确的方式进行的。

文件中定义了以下Controller结构体:

  • SystemNamespacesController:这是控制器的核心结构体,用于管理系统命名空间。
  • SystemNamespace:表示要管理的系统命名空间的元数据。

NewController函数初始化了一个SystemNamespacesController结构体,用于创建、更新和删除系统命名空间。Run函数开始控制器的工作,它会遍历预定义的系统命名空间列表,并尝试在集群中创建它们。如果命名空间已经存在,它将更新该命名空间的元数据。如果操作失败,控制器将进行重试。

sync函数根据需要创建、更新或删除系统命名空间。如果在执行这些操作时遇到任何错误,控制器将进行重试。该函数还会确保系统命名空间包含正确的标签和注释。

createNamespaceIfNeeded函数是一个辅助函数,当需要创建系统命名空间时,它将调用apiClient创建命名空间。它还负责设置命名空间的标签和注释。

总结来说,该文件实现了SystemNamespacesController结构体,用于确保Kubernetes系统命名空间的正确创建、更新和删除。该控制器的实现依赖于apiClient进行与Kubernetes API的交互,确保系统命名空间的创建是稳定和正确的。

File: pkg/controlplane/import_known_versions.go

pkg/controlplane/import_known_versions.go是Kubernetes控制平面包的一部分,负责导入已知的版本信息和协议,包括API版本、API分组、API资源等。其主要作用包括:

  1. 支持Kubernetes API版本的升级:在Kubernetes项目的演化过程中,会不断引入新的API版本,为了实现版本的平滑升级,import_known_versions.go文件定义了已知的API版本、分组和资源,方便Kubernetes运行时环境检测到新的API版本并进行相应的处理。

  2. 维护API资源的映射关系:Kubernetes内部实现了一种机制,即CRD(Custom Resource Definitions),即开发者可以自定义API资源,但是需要在系统中注册和定义相应的映射关系。import_known_versions.go文件中定义了这些映射关系,同时支持开发者自定义添加新的资源映射关系。

  3. 简化控制平面的开发:import_known_versions.go文件为开发者提供了一个简化控制平面开发的接口,可以方便地使用Kubernetes内部定义的API版本和资源,降低开发成本和难度。

总之,pkg/controlplane/import_known_versions.go文件在Kubernetes控制平面包中具有很重要的作用,主要负责定义和实现已知的API版本和API资源,方便Kubernetes运行时环境的检测和升级,并为开发者提供一个方便的接口,可以快速地开发和集成自定义的API资源。

File: pkg/controlplane/instance.go

pkg/controlplane/instance.go是Kubernetes的一个重要文件,它定义了Kubernetes控制平面的实例。

其中IdentityLeaseGCPeriod是身份租赁垃圾回收周期,IdentityLeaseDurationSeconds是自动续订身份租赁的时间,IdentityLeaseRenewIntervalPeriod是自动续订身份租约的时间间隔,stableAPIGroupVersionsEnabledByDefault是是否默认启用稳定的API组版本,legacyBetaEnabledByDefaultResources是是否默认启用旧版beta资源,betaAPIGroupVersionsDisabledByDefault是默认情况下是否禁用beta API组版本,alphaAPIGroupVersionsDisabledByDefault是默认情况下是否禁用alpha API组版本。这些变量的作用是为控制平面提供配置选项。

ExtraConfig、Config、completedConfig、CompletedConfig、EndpointReconcilerConfig、Instance、RESTStorageProvider是结构体,它们分别定义了控制平面实例所需的配置信息、完成配置、Endpoint协调器的配置、实例、REST存储提供程序等。

createMasterCountReconciler、createNoneReconciler、createLeaseReconciler、createEndpointReconciler、Complete、New、labelAPIServerHeartbeatFunc、InstallLegacyAPI、InstallAPIs、DefaultAPIResourceConfigSource是一些函数,用于创建和初始化控制平面实例,以及配置API组版本和存储配置,并为控制平面提供一些其他的功能。

总之,pkg/controlplane/instance.go是Kubernetes控制平面功能的核心文件,对于深入理解Kubernetes控制平面的实现和原理非常重要。

File: pkg/controlplane/reconcilers/endpointsadapter.go

pkg/controlplane/reconcilers/endpointsadapter.go文件是Kubernetes项目中的一个重要文件,它主要负责处理和管理Endpoints资源。在Kubernetes中,Endpoints是用来暴露Service服务的IP和端口的资源。EndpointsAdapter这个结构体及其相关的函数都是用来管理Endpoints资源的。

EndpointsAdapter结构体有两个成员变量:client和assembler。其中,client负责与API Server交互,assembler负责创建EndpointSlice资源。

NewEndpointsAdapter函数用来创建EndpointsAdapter对象。

Get函数用来从API Server中获取指定名称的Endpoints资源。

Create函数用来创建一个Endpoints资源。

Update函数用来更新一个Endpoints资源。

EnsureEndpointSliceFromEndpoints函数用来创建或更新EndpointSlice资源。EndpointSlice是在Kubernetes 1.16版本中引入的,用来替代Endpoints资源。

endpointSliceFromEndpoints函数用来将Endpoints转换成EndpointSlice资源。

getEndpointsFromAddresses函数用来获取Endpoints资源中的所有IP地址。

endpointFromAddress函数用来创建一个Endpoint资源对象。

allAddressesIPv6函数用来判断一个IP地址是否为IPv6地址。

setSkipMirrorTrue函数用来设置跳过Mirror Pods,这是一种特殊的Pod。

总的来说,EndpointsAdapter这个结构体及其相关的函数在Kubernetes项目中扮演着非常重要的角色,其作用是管理Endpoints资源,保证Kubernetes集群中的Service服务正常运行。

File: pkg/controlplane/reconcilers/instancecount.go

pkg/controlplane/reconcilers/instancecount.go是 Kubernetes Control Plane 中用来控制 Master 和 Worker 节点的数量的一部分代码。

该文件中定义了一个 MasterCountEndpointReconciler 结构体以及一些用于操作它的函数。MasterCountEndpointReconciler 结构体主要是将实际的 Master 节点数量与期望的 Master 节点数量进行比较,并确保集群中的 Endpoint 对象反映出正确的 Master 节点数量。

NewMasterCountEndpointReconciler() 函数用于创建一个新的 MasterCountEndpointReconciler 实例。

ReconcileEndpoints() 函数用于检查当前的 Endpoints 对象是否与期望的 Master 数量匹配,并在有必要时更新 Endpoints。

RemoveEndpoints() 函数则是删除 Endpoints 对象。

StopReconciling() 函数用于停止与当前的 MasterCountEndpointReconciler 实例关联的协程的执行。

Destroy() 函数用于销毁 MasterCountEndpointReconciler 实例。

checkEndpointSubsetFormat() 函数则用于检查 endpoint 的子集格式是否正确。

总的来说,MasterCountEndpointReconciler 确保正确的 Master 节点数量在 Kubernetes 集群中注册,并为其他 Kubernetes 控制器提供可靠的节点数量信息。

File: pkg/controlplane/reconcilers/lease.go

pkg/controlplane/reconcilers/lease.go文件的作用是维护kubernetes集群中的租约机制,用于确保在某个节点上只有一个正在运行的控制器。

_这几个变量分别为占位符,用于占用未使用的变量或返回值。

Leases结构体用于管理租约信息,storageLeases结构体用于管理租约存储,leaseEndpointReconciler结构体用于协调租约和节点的信息。

ListLeases函数用于列出租约信息,UpdateLease函数用于更新租约信息,RemoveLease函数用于删除租约信息,Destroy函数用于销毁租约,NewLeases函数用于创建租约,NewLeaseEndpointReconciler函数用于创建租约和节点之间的协调器,ReconcileEndpoints函数用于协调租约和节点信息的更新,doReconcile函数用于执行协调节点和租约信息的逻辑,checkEndpointSubsetFormatWithLease函数用于检查EndpointSubset格式是否符合规定,RemoveEndpoints函数用于删除节点信息,StopReconciling函数用于停止协调节点和租约信息的更新。

综上所述,pkg/controlplane/reconcilers/lease.go文件的作用是确保在kubernetes集群中,某个节点只有一个正在运行的控制器,为了实现该机制,该文件中定义了多个结构体和函数,用于管理和协调租约、节点和信息的更新,并且通过上述函数和结构体来实现集群控制逻辑。

File: pkg/controlplane/reconcilers/none.go

在 Kubernetes 项目中,pkg/controlplane/reconcilers/none.go 文件主要实现了针对无执行器的 Endpoint 协调器,用于处理不存在执行器的 Endpoint 对象。

具体来说,noneEndpointReconciler 结构体用于表示无执行器的 Endpoint 协调器,用于处理 Endpoint 对象的创建、更新、删除等操作。NewNoneEndpointReconciler 方法用于新建一个 noneEndpointReconciler 对象,ReconcileEndpoints 方法用于协调处理 Endpoint 对象的创建或更新,RemoveEndpoints 方法用于协调处理 Endpoint 对象的删除,StopReconciling 方法用于停止协调 Endpoint 对象的创建和更新,Destroy 方法用于销毁 noneEndpointReconciler 对象。

noneEndpointReconciler 在处理 Endpoint 对象时,会触发相应的增加、修改、删除事件,然后根据事件类型决定具体如何处理相关的 Endpoint 对象。如果是添加事件,则会向 API server 发送创建 Endpoint 对象的请求;如果是修改事件,则会更新相关的 Endpoint 对象;如果是删除事件,则会删除对应的 Endpoint 对象。

总之,noneEndpointReconciler 用于管理没有执行器的 Endpoint 对象,主要负责 Endpoint 对象的创建、修改和删除工作,以确保 Kubernetes 集群中的服务正常运行。

File: pkg/controlplane/reconcilers/reconcilers.go

pkg/controlplane/reconcilers/reconcilers.go是kubernetes项目中的一个包,其作用是提供用于控制平面的各种reconciler,用于自动化容器编排的过程,确保系统在运行时的状态和所期望的状态一致。reconciler是一种用于协调系统状态的工具,其通过不断比较“期望状态”与“实际状态”,并采取一些措施来实现这两种状态的一致性。

AllTypes是一个包含所有资源类型的列表,包括了应该被reconciler处理的大部分的资源类型,它是一个字符串类型的数组

EndpointReconciler是一个结构体,代表着对endpoint对象的管理。Type是一个string类型的字段,表示此reconciler处理的资源类型。Types是一个字符串类型的数组,表示这个reconciler所支持的资源类型。

Names是一组function,用于将一个object的kind和name 组合成一个string类型的namespacedName。

在kubernetes系统中,Names的主要作用是将object的名称和类型组合生成一个字符串,这个字符串被用作map中的key进行查找和比对。同时,Names也可以将一个对象拼成一个标准的object reference用于打log和输出debug信息。

File: pkg/controlplane/storageversionhashdata/data.go

pkg/controlplane/storageversionhashdata/data.go文件用于定义存储版本的哈希值数据。在Kubernetes的控制平面中,数据对象的存储版本是非常重要的信息,因为这个版本将决定对象被存储在哪个存储介质上。该文件中定义了一些存储版本哈希值的常量,以便Kubernetes能够将不同版本的对象映射到正确的存储位置。

具体来说,该文件中定义了如下几个变量:

  1. NoStorageVersionHash:表示没有存储版本哈希值的常量。

  2. GVRToStorageVersionHash:表示将Group/Version/Resource(GVR)映射到其对应的存储版本哈希值的常量。这个映射关系是非常重要的,因为它可以帮助Kubernetes准确地定位对象的存储位置。例如,如果要存储一个Pod对象,Kubernetes需要知道该对象的GVR信息,然后通过GVRToStorageVersionHash变量中的映射关系确定该对象对应的存储版本哈希值。

在总体上,pkg/controlplane/storageversionhashdata/data.go文件定义了存储版本哈希值的信息,以便Kubernetes能够准确地将数据存储在正确的位置。这个文件对于Kubernetes的正常运行是非常重要的。




File: pkg/credentialprovider/azure/azure_acr_helper.go

pkg/credentialprovider/azure/azure_acr_helper.go 这个文件是Kubernetes中用于支持Azure容器注册表身份验证的帮助程序。

代码中的client变量用于表示 HTTP 客户端。其中,client 是通过 Azure ACR 服务发送请求和接收响应。client 包括请求标头、请求体、响应标头、响应体以及其他 HTTP 客户端所需的属性和指令。

authDirective 和 acrAuthResponse 分别表示从 Azure ACR 服务收到的授权指令和响应。authDirective 是用户身份验证提供程序的代码中用于存储从 Azure ACR 服务接收到的 HTTP 身份验证指令的结构体。acrAuthResponse 结构体则是用于将响应从 Azure ACR 服务解码的结构体。

receiveChallengeFromLoginServer 方法用于从認證服務器接收 HTTP 身份验证指令。performTokenExchange 方法用于执行令牌交换。它使用身份验证指令和用户凭据而不是用户名和密码来获取 OAuth2 令牌。parseAssignments 方法用于解析 Azure ACR 站点发送的指令。

nextOccurrence 和 nextNoneSpace 方法分别是帮助程序中的辅助函数。nextOccurrence 函数用于在字符串中返回后续字符的下一次出现,nextNoneSpace 则用于从字符串的当前位置开始查找其后的第一个非空白字符。

总的来说,pkg/credentialprovider/azure/azure_acr_helper.go 文件中包含了 Kubernetes 中用于支持 Azure 容器注册表身份验证所需的实用程序函数和结构体。通过编写和使用这些功能,Kubernetes 客户端可以连接到 Azure 容器注册表,进行身份验证并下载拉取镜像。

File: pkg/credentialprovider/azure/azure_credentials.go

pkg/credentialprovider/azure/azure_credentials.go是Kubernetes项目中的Azure凭证提供者模块。这个文件实现了Azure Container Registry (ACR)中的Docker Credential Helper规范,允许使用Azure Active Directory (AAD)提供者在Kubernetes集群中获取ACR中的镜像。

flagConfigFile用于指定配置文件的路径,containerRegistryUrls用于指定配置文件中需要解析的容器注册表URLs,acrRE用于解析ACR的Registry名称,warnOnce用于记录已发出的警告信息。

cacheEntry用于管理缓存的地址信息及过期时间,acrExpirationPolicy用于管理ACR的过期时间策略,RegistriesClient用于管理ACR API的调用,acrProvider是一个实现Docker Credential Helper规范的结构体。

init函数用于初始化配置文件,stringKeyFunc用于将镜像字符串转换为适合ACR API的键名,IsExpired函数用于检查缓存的地址信息是否过期,NewACRProvider函数用于创建acrProvider实例,parseConfig函数用于解析配置文件,loadConfig函数用于加载配置文件,Enabled函数用于检查ACR凭证提供者的启用状态,getFromCache函数用于从缓存中获取地址信息,getFromACR函数用于从ACR API获取地址信息,Provide函数用于提供凭证信息,getLoginServer函数用于获取ACR的登陆服务器地址,getACRDockerEntryFromARMToken用于从ARM Token中获取ACR的Docker Credential Helper规范信息,parseACRLoginServerFromImage用于从镜像名称中解析出ACR的登陆服务器地址。

综上所述,pkg/credentialprovider/azure/azure_credentials.go的主要作用是为Kubernetes集群提供获取Azure Container Registry中镜像的凭证信息。通过对该文件中变量和函数的了解,我们可以理解该模块如何管理缓存、获取地址信息、提供凭证信息等,从而更好地了解其工作原理。

File: pkg/credentialprovider/gcp/metadata.go

pkg/credentialprovider/gcp/metadata.go文件是Kubernetes项目中实现Google Cloud Platform(GCP)凭据提供者的文件之一。该文件实现了从GCP元数据服务(metadata service)获取和提供凭证的功能。GCP元数据服务是GCP中的一个服务,可以提供有关GCE虚拟机(VM)实例的信息,例如该实例拥有的服务帐户以及该帐户的访问令牌。

gceProductNameFile变量是一个字符串,它表示在GCE VM实例上运行时,元数据服务从中读取主机名和管理的实例组名称的文件的路径。metadataHeader变量是一个字符串,用于指定从元数据服务获取信息时使用的HTTP头。在这种情况下,HTTP头指定要获取的元数据的服务帐户令牌。warnOnce变量是用于控制在提供凭据时是否要警告的布尔值变量。

MetadataProvider结构体是一个实现了Provider接口的类型。它提供了获取GCP服务帐户令牌、GCP项目ID和服务帐户电子邮件地址的方法。DockerConfigKeyProvider结构体是另一种Provider接口类型,它提供了获取Docker配置文件的方法。DockerConfigURLKeyProvider和ContainerRegistryProvider结构体也实现了Provider接口,并提供了获取Docker配置文件和容器注册表凭证的方法。

init函数是在导入时运行的函数。它的作用是初始化各种变量,例如元数据服务的URL和提供凭证的默认实现。onGCEVM函数用于检查当前是否在GCE VM实例上运行。Enabled函数用于确定是否启用GCP凭证提供者。Provide函数负责提供GCP凭证,如GCP服务帐户令牌和项目ID。runWithBackoff函数负责获取GCP服务帐户令牌并在失败时进行重试。最后,registryToDocker函数将容器注册表URL转换为Docker URL(docker.io)。

File: pkg/credentialprovider/keyring.go

pkg/credentialprovider/keyring.go是Kubernetes项目中一个用于管理Docker镜像的Credential Provider接口实现的代码文件。Credential Provider是一种将安全凭据提供给容器运行时环境的插件,可以帮助容器进行身份验证和授权等操作。

在这个文件中,定义了多个结构体,其作用分别如下:

  1. DockerKeyring:用于管理Docker Hub的镜像凭据的结构体。
  2. BasicDockerKeyring:用于管理基本的Docker镜像凭据的结构体,包括上传镜像到私有仓库所需要的凭据。
  3. providersDockerKeyring:一个用于管理多个Docker凭据提供者的结构体。
  4. AuthConfig:一个用于存储Docker认证配置的结构体。
  5. FakeKeyring:一个用于测试的Docker凭据提供者的结构体。
  6. UnionDockerKeyring:将多个Docker凭据提供者集成在一起的结构体。

此外,这个文件中还定义了多个函数,其作用分别如下:

  1. Add:向Docker认证配置中添加一个凭据。
  2. isDefaultRegistryMatch:检查给定的URL是否匹配Docker Hub。
  3. ParseSchemelessURL:解析不带协议头的URL地址。
  4. SplitURL:分离URL的协议、主机名和路径。
  5. URLsMatchStr:检查两个URL是否匹配。
  6. URLsMatch:检查两个URL是否匹配。
  7. Lookup:在Docker凭据提供者中查找凭据。

这些函数和结构体相互协作,用于在Kubernetes中管理Docker镜像的凭据,确保容器在使用镜像时可以进行身份验证,保护镜像数据的安全性。

File: pkg/credentialprovider/plugin/plugin.go

pkg/credentialprovider/plugin/plugin.go这个文件是Kubernetes中用于提供认证插件的包。它提供了一个框架,可以让外部插件来实现不同的认证方式。

在该文件中,有三个全局变量:scheme,codecs和apiVersions。其中,scheme是用于识别插件的URL scheme,codecs是编解码器,apiVersions是支持的API版本。

此外,还有四个结构体:pluginProvider、cacheEntry、cacheExpirationPolicy和Plugin。pluginProvider中包含一个认证插件的列表,cacheEntry表示一个认证插件的缓存条目,cacheExpirationPolicy是缓存持续时间的策略,Plugin是一个认证插件的实例。

Kubernetes中的认证插件实现在特定的框架下运行,可以通过上述结构体中的字段获取和管理认证插件。每个插件可以通过实现接口方法来提供自己的身份验证功能。

init、RegisterCredentialProviderPlugins、newPluginProvider、cacheKeyFunc、IsExpired、Provide、Enabled、isImageAllowed、getCachedCredentials、ExecPlugin、runPlugin、encodeRequest、decodeResponse、parseRegistry和mergeEnvVars这些功能函数的作用如下:

  1. init:用于初始化认证插件。
  2. RegisterCredentialProviderPlugins:用于将认证插件注册到插件提供者的列表。
  3. newPluginProvider:用于创建新的插件提供者实例。
  4. cacheKeyFunc:用于创建对认证插件进行缓存的键。
  5. IsExpired:用于检查缓存是否过期。
  6. Provide:使用插件提供者查找和提供认证插件。
  7. Enabled:用于检查指定的插件是否启用。
  8. isImageAllowed:用于检查指定镜像是否允许使用插件提供的身份验证。
  9. getCachedCredentials:从缓存的插件中提取凭证。
  10. ExecPlugin:对插件进行执行调用。
  11. runPlugin:运行调用插件。
  12. encodeRequest:编码请求。
  13. decodeResponse:解码响应。
  14. parseRegistry:解析注册表名和镜像名。
  15. mergeEnvVars:合并环境变量。

File: pkg/credentialprovider/plugins.go

pkg/credentialprovider/plugins.go是Kubernetes项目中的一个文件,其主要作用是提供容器镜像凭证提供程序的插件系统。该文件中的代码实现了将不同的容器镜像仓库(如DockerHub、GCR等)的认证信息(如用户名、密码、令牌等)存储在安全的地方,以供Kubernetes使用。

其中,providersMutex和providers这两个变量用于维护以插件形式加载的凭证提供程序的列表。providersMutex是一个同步机制,用于保护providers列表的读写操作。而providers就是一个切片,存储所有已注册的凭证提供程序。

RegisterCredentialProvider函数用于将凭证提供程序注册到Kubernetes的插件系统中。这个函数接受一个凭证提供程序的结构体类型作为参数。调用这个函数将会把该凭证提供程序的实例注册到providers列表中。不同的凭证提供程序类型需要实现Provider接口中的方法。

AreLegacyCloudCredentialProvidersDisabled函数用于检查是否禁用了传统的云凭证提供程序。这些凭证提供程序包括AWS、GCP、Azure等。如果在Kubernetes节点上设置了相应的环境变量或者kubelet的启动参数,则会禁用这些凭证提供程序。

NewDockerKeyring函数用于创建Docker凭证提供程序的实例。Docker凭证提供程序可以用来存储DockerHub、Quay等镜像仓库的认证信息。这个函数会创建一个带有Docker认证信息的密钥环(keyring),用于在请求Docker镜像时提供身份验证信息。

总而言之,pkg/credentialprovider/plugins.go是Kubernetes中的一个核心文件,用于实现容器镜像凭证提供程序的插件系统。它定义了Kubernetes的插件接口,提供了凭证提供程序的注册、管理和调用接口,为Kubernetes的容器镜像使用提供了安全的身份验证机制。

File: pkg/credentialprovider/provider.go

pkg/credentialprovider/provider.go 这个文件是 Kubernetes 中用于管理 Image Pull Secrets 的代码文件。它为 Kubernetes 中用于拉取镜像的容器提供了身份验证所需的凭据,例如私有库的用户名和密码等。

在此文件中,有三个主要的结构体,它们分别是:DockerConfigProvider、defaultDockerConfigProvider和CachingDockerConfigProvider。

DockerConfigProvider 结构体是 Kubernetes 中对外提供的接口,代表了一个镜像凭据提供者,它的作用是提供给注入容器的环境变量,以使容器能够在需要时自动拉取需要的镜像。

defaultDockerConfigProvider 结构体是 DockerConfigProvider 接口的默认实现,它通过 $HOME/.docker/config.json 文件中的数据提供有关 Docker 镜像的凭据信息用于身份验证。

CachingDockerConfigProvider 结构体是一个缓存 Docker 镜像凭据的实现,它可以缓存凭据,避免每次拉取镜像都重新获取凭据信息。

此外,还有一些重要的函数,包括 init()、Enabled() 和 Provide()。

init() 函数是在 DockerConfigProvider 结构体被创建时运行的初始化函数,它在此阶段读取相关的配置文件并建立缓存机制。

Enabled() 函数返回一个布尔值,代表是否启用了 Image Pull Secrets,实现是检查 defaultDockerConfigProvider 是否的可用的(例如文件是否存在)。

Provide() 函数返回 DockerConfigProvider,它将根据情况选择默认的 DockerConfigProvider 或启用缓存 DockerConfigProvider,并返回一个 DockerConfigProvider 对象,以供 Kubernetes 使用。

File: pkg/credentialprovider/secrets/secrets.go

pkg/credentialprovider/secrets/secrets.go是Kubernetes的一个密钥提供者插件,在容器镜像中使用密钥进行身份验证。该文件提供了与不同的密钥存储系统进行交互的功能,使得Kubernetes能够支持各种类型的密钥存储系统,如Docker config、Azure key vault、Google cloud credentials等。

该文件中的MakeDockerKeyring函数是一个针对Docker认证密钥的工具函数,它主要用于配置docker的认证密钥环,确保容器可以使用这些密钥进行认证。其中,该函数使用了kubernetes的secret对象来管理密钥,根据不同情况返回相应的环境变量或docker配置文件。

具体而言,MakeDockerKeyring函数的作用如下:

  1. 创建一个docker认证密钥环(docker.ConfigFile)对象;
  2. 在密钥环中添加default密钥(默认为名为.dockerconfigjson的secret);
  3. 如果有额外的密钥,用相应的密钥覆盖default密钥;
  4. 根据密钥环中的内容,生成一个docker配置文件。

总之,MakeDockerKeyring函数的作用是为docker容器提供所需的认证密钥环,方便其进行身份验证。

除了MakeDockerKeyring之外,pkg/credentialprovider/secrets/secrets.go文件中还有其他一些函数,如GetSecrets、AddCredentialConfig等,它们都是与密钥存储系统进行交互的工具函数,提供了一些管理密钥的方法。这些函数的作用就是为了方便Kubernetes与不同的密钥存储系统进行交互,为容器提供所需的认证信息,确保容器的安全运行。




File: pkg/kubeapiserver/admission/initializer.go

在Kubernetes项目中,pkg/kubeapiserver/admission/initializer.go文件的作用是实现初始化插件的逻辑。该文件定义了初始化插件的结构体和函数,用于在Kubernetes API服务器启动时加载和初始化插件。

_这几个变量在代码中通常表示一个不需要具体赋值的占位符,用于忽略某个变量。

WantsCloudConfig结构体用于指定初始化插件所需的云提供商配置。它定义了一个名为"cloudprovider"的字段,用于保存云提供商的名称。该结构体可用于判断初始化插件是否需要云提供商的配置。

PluginInitializer结构体定义了一个名为"PluginInitializer"的接口。这个接口包含一个名为"SetCloudProvider"的方法,用于设置云提供商的配置,并返回是否执行了该方法。

NewPluginInitializer函数用于创建PluginInitializer接口的实例。它接收一个WantsCloudConfig结构体作为参数,并返回一个实现了PluginInitializer接口的对象。

Initialize函数是PluginInitializer接口的方法之一,用于初始化插件。它接收一个kubeutil包中的Config类型的参数,表示Kubernetes API服务器的配置,然后根据配置进行相应的初始化操作。该函数可能会返回一个错误,用于指示初始化是否成功。

综上所述,pkg/kubeapiserver/admission/initializer.go文件的作用是为Kubernetes API服务器提供初始化插件的功能。它通过定义一系列结构体和函数,用于判断插件是否需要云提供商的配置,创建插件初始化器实例,并在API服务器启动时执行插件的初始化操作。

File: pkg/kubeapiserver/authorizer/modes/modes.go

pkg/kubeapiserver/authorizer/modes/modes.go是Kubernetes项目中的一个文件,它的作用是定义和管理授权模式(Authorization Modes)。

在Kubernetes中,授权模式用于定义和管理对API资源的访问权限。modes.go文件中的AuthorizationModeChoices变量是一个授权模式选项的切片,每个选项表示一种授权模式。这些选项通常包括:AlwaysAllow、AlwaysDeny、ABAC、RBAC、Webhook等。

IsValidAuthorizationMode是modes.go文件中定义的一组函数,用于检查和验证给定的字符串是否是有效的授权模式。这些函数会遍历AuthorizationModeChoices切片,以确定给定的授权模式是否存在于选项中。如果授权模式是有效的,则返回true;否则返回false。

IsValidAuthorizationMode函数主要有以下几个作用:

  1. 验证给定的字符串是否是有效的授权模式。
  2. 确定授权模式是否存在于AuthorizationModeChoices切片中。
  3. 提供一种机制来检查Kubernetes API Server配置文件中的授权模式是否正确。

通过这些函数,Kubernetes项目能够有效地管理和验证授权模式,确保系统的安全性和可用性。

File: pkg/kubeapiserver/default_storage_factory_builder.go

pkg/kubeapiserver/default_storage_factory_builder.go文件的作用是构建默认的存储工厂(Storage Factory)配置。存储工厂是用于创建和管理API对象资源的组件。

SpecialDefaultResourcePrefixes变量是一个定义了一些特殊资源的前缀的字符串切片。这些特殊资源在创建默认的存储工厂时需要进行特殊处理。

StorageFactoryConfig结构体定义了存储工厂的配置信息,包括资源类型和存储版本的映射关系。

completedStorageFactoryConfig结构体是StorageFactoryConfig的补充结构体,它包含了补充的默认值,用于构建完整的存储工厂配置。

DefaultWatchCacheSizes是一个定义了默认的观察缓存大小的映射关系。

NewStorageFactoryConfig函数用于创建一个新的存储工厂配置实例。

Complete函数用于将StorageFactoryConfig配置实例补充完整,添加默认的值和处理特殊资源。

New函数用于创建一个新的存储工厂实例,将存储工厂配置传递给存储工厂构造函数。

以上是对pkg/kubeapiserver/default_storage_factory_builder.go文件和其中相关变量和函数的详细介绍。

File: pkg/kubeapiserver/options/admission.go

在kubernetes项目中,pkg/kubeapiserver/options/admission.go这个文件的作用是为kube-apiserver提供命令行选项和配置验证,以及为插件提供注册和管理。

AdmissionOptions中定义了一组选项,用于配置和控制Admission插件。这些选项包括:

  • Plugins:定义了启用的Admission插件列表。
  • PluginConfigFile:指定Admission插件的配置文件路径。
  • Enabled:指示是否启用Admission插件。
  • Initializers:定义了在请求流入之前要应用的初始化器。

接下来,让我们逐个介绍每个相关的函数:

  1. NewAdmissionOptions: 该函数用于创建一个新的Admission插件选项配置,并返回AdmissionOptions结构体的实例。

  2. AddFlags: 该函数用于将Admission插件选项的命令行标志添加到给定的FlagSet中。这样,用户在运行kube-apiserver时就可以使用这些标志进行配置。

  3. Validate: 该函数用于验证Admission插件选项的有效性。它检查选项是否符合一些基本的约束,例如插件列表中是否包含有效的插件名称。

  4. ApplyTo: 该函数用于将Admission插件的配置应用到给定的插件集。它遍历所有插件,将配置应用到每个插件。

  5. computePluginNames: 该函数用于从插件列表中解析插件名称。它先从插件列表中获取插件名称,然后根据指定的策略(例如ALLOW和DENY)来解析插件名称。

总之,pkg/kubeapiserver/options/admission.go文件定义了Admission插件选项的配置和管理,提供了用于创建、添加标志、验证配置、应用配置和解析插件名称等一系列函数。这些函数是为了方便用户对Admission插件进行配置和管理。

File: pkg/kubeapiserver/options/authentication.go

在kubernetes项目中,pkg/kubeapiserver/options/authentication.go文件包含了一些用于身份验证的选项和函数。具体来说,它定义了用于构建身份验证配置的结构体和函数。

  1. BuiltInAuthenticationOptions:表示内置身份验证选项,用于指定使用 Kubernetes 预定义的身份验证方式。

  2. AnonymousAuthenticationOptions:表示匿名身份验证选项,用于指定是否允许匿名用户访问 Kubernetes API。

  3. BootstrapTokenAuthenticationOptions:表示引导令牌身份验证选项,用于指定使用引导令牌进行身份验证的方式。

  4. OIDCAuthenticationOptions:表示 OpenID Connect(OIDC)身份验证选项,用于指定使用 OIDC 进行身份验证的方式。

  5. ServiceAccountAuthenticationOptions:表示服务帐户身份验证选项,用于指定使用服务帐户进行身份验证的方式。

  6. TokenFileAuthenticationOptions:表示令牌文件身份验证选项,用于指定使用令牌文件进行身份验证的方式。

  7. WebHookAuthenticationOptions:表示 WebHook 身份验证选项,用于指定使用 WebHook 进行身份验证的方式。

上述结构体提供了不同的身份验证方式,使用者可以根据需求选择适合的方式。

下面是一些重要的函数:

  1. NewBuiltInAuthenticationOptions:用于创建一个新的内置身份验证选项。

  2. WithAll、WithAnonymous、WithBootstrapToken、WithClientCert、WithOIDC、WithRequestHeader、WithServiceAccounts、WithTokenFile、WithWebHook:这些函数用于设置不同类型身份验证方式的相关选项。

  3. Validate:用于验证身份验证配置的有效性。

  4. AddFlags:用于添加命令行标志,使用户能够在命令行中设置身份验证的选项。

  5. ToAuthenticationConfig:将身份验证选项转换为身份验证配置。

  6. ApplyTo:将身份验证配置应用到 kube-apiserver 的配置中。

  7. ApplyAuthorization:将身份验证配置应用到授权配置中。

这些函数提供了配置和应用身份验证选项的功能,使用户能够自定义和管理身份验证方式。它们通过读取用户的配置和标志,并对配置进行验证和应用,确保身份验证的正确性和安全性。

File: pkg/kubeapiserver/options/authorization.go

在Kubernetes项目中,pkg/kubeapiserver/options/authorization.go文件的作用是定义了用于配置鉴权(authorization)的选项。该文件中包含了BuiltInAuthorizationOptions结构体和一些相关的函数。

BuiltInAuthorizationOptions是一个结构体,用于存储鉴权选项的配置信息。它包含了以下几个字段:

  1. AlwaysAllow: 一个布尔类型的字段,表示是否启用AlwaysAllow授权模式。如果设置为true,将允许对所有API请求执行任何操作。

  2. AlwaysDeny: 一个布尔类型的字段,表示是否启用AlwaysDeny授权模式。如果设置为true,将拒绝对所有API请求的任何操作。

  3. ABACOptions: ABAC(Attribute-Based Access Control)选项的配置信息。ABAC是一种鉴权模式,通过使用静态的策略文件进行授权。

  4. RBACOptions: RBAC(Role-Based Access Control)选项的配置信息。RBAC是一种基于角色的访问控制模型,通过使用角色和角色绑定来授权。

NewBuiltInAuthorizationOptions是一个函数,用于创建一个默认的BuiltInAuthorizationOptions对象。它为AlwaysAllow和AlwaysDeny字段设置了默认值,并返回创建的对象。

Validate是一个函数,用于验证BuiltInAuthorizationOptions对象的配置是否合法。它检查字段的值是否设置正确,并返回相应的错误信息。

AddFlags是一个函数,用于为BuiltInAuthorizationOptions对象添加命令行标志。当命令行启动kube-apiserver时,可以通过命令行参数设置鉴权选项的配置信息。

ToAuthorizationConfig是一个函数,用于将BuiltInAuthorizationOptions对象转换为kubernetes认证配置(authorization.Config)。kubernetes认证配置是一种用于描述鉴权选项的数据结构,它包含了上述提到的几种鉴权模式的配置信息。

总而言之,pkg/kubeapiserver/options/authorization.go文件中的结构体和函数提供了一种配置Kubernetes API服务器鉴权选项的方式。通过这些选项,可以选择不同的鉴权模式,并设置相应的配置信息,以满足具体的鉴权需求。

File: pkg/kubeapiserver/options/cloudprovider.go

pkg/kubeapiserver/options/cloudprovider.go文件的作用是定义了与云服务提供商相关的选项参数,包括CloudProviderOptions结构体、NewCloudProviderOptions函数、Validate函数和AddFlags函数。

CloudProviderOptions是一个结构体,用于存储与云服务提供商相关的选项参数。它包含了以下字段:

  • CloudProvider: 云服务提供商的名称,例如AWS、Azure等。
  • CloudConfigFile: 云服务提供商的配置文件路径。
  • ControllerAttachDetach: 是否启用云提供商的卷附加和分离功能。
  • RouteReconciliationPeriod: 路由调整周期,用于调整云提供商的路由表。

NewCloudProviderOptions函数用于创建一个CloudProviderOptions结构体的实例,并返回该实例的指针。它接收一个flagset参数,用于解析和设置命令行参数。

Validate函数用于验证CloudProviderOptions结构体的字段值是否合法。它检查CloudProvider字段是否有效,并根据特定的云服务提供商,进一步检查其他字段的合法性。

AddFlags函数用于向flagset添加与云服务提供商相关的命令行选项。它提供了CloudProviderOptions结构体中各个字段的选项参数,用于动态解析和设置命令行参数。

简而言之,pkg/kubeapiserver/options/cloudprovider.go文件定义了与云服务提供商相关的选项参数,提供了相关函数用于创建、验证和解析这些选项参数。这些选项参数可以用于配置Kubernetes集群与云服务提供商之间的集成和交互。

File: pkg/kubeapiserver/options/serving.go

在kubernetes项目中,pkg/kubeapiserver/options/serving.go文件的作用是定义和管理Kubernetes API服务器的安全服务选项。

该文件包含了NewSecureServingOptions函数,该函数的作用是创建并返回一个SecureServingOptions结构体,该结构体包含了一系列用于配置和管理安全服务的选项。SecureServingOptions结构体是Kubernetes API服务器中用于定义服务器安全配置的关键组件。

NewSecureServingOptions函数内部主要完成以下任务:

  1. 创建和配置 SecureServingOptions结构体的基本选项,例如获取要使用的监听地址、端口等。
  2. 调用 NewDynamicCertProvider函数创建并配置证书管理器,以便用于管理和自动获取服务器的TLS证书。
  3. 调用 setDefaultServerCertOptions函数设置与服务器证书相关的默认选项,例如默认证书的密钥类型、默认证书的CA证书等。
  4. 调用 applyServerCertOptionsFromConfig函数从配置文件中读取和应用服务器证书相关的选项。
  5. 调用 applyServerCertOptionsFromDynamicClient函数从动态客户端中读取和应用服务器证书相关的选项。

NewSecureServingOptions函数的返回值即为配置好的SecureServingOptions结构体,该结构体包含了用于配置和管理安全服务的选项,例如:

  • BindAddress:服务器监听地址。
  • BindPort:服务器监听端口。
  • CertDNSNames:证书中用于验证服务器身份的DNS名称。
  • CertIPs:证书中用于验证服务器身份的IP地址列表。
  • ClientCA:用于验证客户端证书的CA证书。
  • CertKeyFileCertFile:服务器TLS证书的私钥和证书文件路径。

这些配置选项可以通过Kubernetes配置文件或命令行参数进行配置,用于确保Kubernetes API服务器在进行安全通信时具备良好的配置和管理能力。




内容由chatgpt生成,仅供参考,不作为面试依据。

仓库地址:https://github.com/cuishuang/explain-source-code-by-chatgpt

本文由 mdnice 多平台发布

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值