The official K8s documentation states that it is necessary to include ResourceQuota in the --enable-admission-plugins of apiserver to enable resource quota. https://kubernetes.io/docs/concepts/policy/resource-quotas/#enabling-resource-quota
In a certain K8s 1.19 environment, I did not find the ResourceQuota configuration in --enable-admission-plugins. However, once resourcequota is set for each Namespace, this resourcequota will take effect. enter image description here
Additionally, by examining the source code of apiserver(release-1.28), the Register method in pkg/admission/plugin/resourcequota/admission.go is not referenced. In pkg/server/options/admission.go, the Validate method of AdmissionOptions will check whether the plugins in the configuration are registered. If not registered, it will return an error. This Validate method is called from the Validate method of RecommendedOptions, but NewRecommendedOptions is not called.
I'm confused.
I would appreciate any guidance from experts. Thank you.
I want to figure out how the ResourceQuota in K8s takes effect. I would like to find the basis from the source code.
I have find the answer to this question myself. The function "enablePluginNames" of AdmissionOptions in vendor/k8s.io/apiserver/pkg/server/options/admission.go is the answer.
// enabledPluginNames makes use of RecommendedPluginOrder, DefaultOffPlugins,
// EnablePlugins, DisablePlugins fields
// to prepare a list of ordered plugin names that are enabled.
func (a *AdmissionOptions) enabledPluginNames() []string {
allOffPlugins := append(a.DefaultOffPlugins.List(), a.DisablePlugins...)
disabledPlugins := sets.NewString(allOffPlugins...)
enabledPlugins := sets.NewString(a.EnablePlugins...)
disabledPlugins = disabledPlugins.Difference(enabledPlugins)
orderedPlugins := []string{}
for _, plugin := range a.RecommendedPluginOrder {
if !disabledPlugins.Has(plugin) {
orderedPlugins = append(orderedPlugins, plugin)
}
}
return orderedPlugins
}
The plugins in RecommendedPluginOrder will be enabled by default as long as they are not disabled.
RecommendedPlugionOrder is initialized in the NewAdmissionOptions method in pkg/kubeapiserver/options/admission.go.
// NewAdmissionOptions creates a new instance of AdmissionOptions
// Note:
//
// In addition it calls RegisterAllAdmissionPlugins to register
// all kube-apiserver admission plugins.
//
// Provides the list of RecommendedPluginOrder that holds sane values
// that can be used by servers that don't care about admission chain.
// Servers that do care can overwrite/append that field after creation.
func NewAdmissionOptions() *AdmissionOptions {
options := genericoptions.NewAdmissionOptions()
// register all admission plugins
RegisterAllAdmissionPlugins(options.Plugins)
// set RecommendedPluginOrder
options.RecommendedPluginOrder = AllOrderedPlugins
// set DefaultOffPlugins
options.DefaultOffPlugins = DefaultOffAdmissionPlugins()
return &AdmissionOptions{
GenericAdmission: options,
}
}
AllOrderedPlugins is declared like this:
// AllOrderedPlugins is the list of all the plugins in order.
var AllOrderedPlugins = []string{
admit.PluginName, // AlwaysAdmit
autoprovision.PluginName, // NamespaceAutoProvision
lifecycle.PluginName, // NamespaceLifecycle
exists.PluginName, // NamespaceExists
scdeny.PluginName, // SecurityContextDeny
antiaffinity.PluginName, // LimitPodHardAntiAffinityTopology
limitranger.PluginName, // LimitRanger
serviceaccount.PluginName, // ServiceAccount
noderestriction.PluginName, // NodeRestriction
nodetaint.PluginName, // TaintNodesByCondition
alwayspullimages.PluginName, // AlwaysPullImages
imagepolicy.PluginName, // ImagePolicyWebhook
podsecurity.PluginName, // PodSecurity
podnodeselector.PluginName, // PodNodeSelector
podpriority.PluginName, // Priority
defaulttolerationseconds.PluginName, // DefaultTolerationSeconds
podtolerationrestriction.PluginName, // PodTolerationRestriction
eventratelimit.PluginName, // EventRateLimit
extendedresourcetoleration.PluginName, // ExtendedResourceToleration
label.PluginName, // PersistentVolumeLabel
setdefault.PluginName, // DefaultStorageClass
storageobjectinuseprotection.PluginName, // StorageObjectInUseProtection
gc.PluginName, // OwnerReferencesPermissionEnforcement
resize.PluginName, // PersistentVolumeClaimResize
runtimeclass.PluginName, // RuntimeClass
certapproval.PluginName, // CertificateApproval
certsigning.PluginName, // CertificateSigning
ctbattest.PluginName, // ClusterTrustBundleAttest
certsubjectrestriction.PluginName, // CertificateSubjectRestriction
defaultingressclass.PluginName, // DefaultIngressClass
denyserviceexternalips.PluginName, // DenyServiceExternalIPs
// new admission plugins should generally be inserted above here
// webhook, resourcequota, and deny plugins must go at the end
mutatingwebhook.PluginName, // MutatingAdmissionWebhook
validatingadmissionpolicy.PluginName, // ValidatingAdmissionPolicy
validatingwebhook.PluginName, // ValidatingAdmissionWebhook
resourcequota.PluginName, // ResourceQuota
deny.PluginName, // AlwaysDeny
}
Therefore, the ResourceQuota plugin will be enabled by default, event without being declared in the --enable-admission-plugins parameter.