前言
kube-apiserver 不仅负责 RESTful API 路由的建立,也负责请求的认证,授权和准入。如下图所示:

本篇文章将介绍 kube-apiserver 的认证机制。
认证 Authentication
认证是对请求的认证,确认请求是否具有访问 Kubernetes 集群的权限。在 kube-apiserver 中,通过 handler 处理请求的认证,所有请求都将通过认证 handler 进行认证。可以把它理解成 Gin 框架的中间件。
认证 handler
首先,从认证 handler 的创建过程入手。
1# kubernetes/vendor/k8s.io/apiserver/pkg/server/config.go
2// 进入 GenericAPIServer 的创建函数 New
3func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*GenericAPIServer, error) {
4 handlerChainBuilder := func(handler http.Handler) http.Handler {
5 return c.BuildHandlerChainFunc(handler, c.Config)
6 }
7
8
9 apiServerHandler := NewAPIServerHandler(name, c.Serializer, handlerChainBuilder, delegationTarget.UnprotectedHandler())
10 ...
11}
12
13# kubernetes/vendor/k8s.io/apiserver/pkg/server/config.go
14func NewAPIServerHandler(name string, s runtime.NegotiatedSerializer, handlerChainBuilder HandlerChainBuilderFn, notFoundHandler http.Handler) *APIServerHandler {
15 ...
16
17 director := director{
18 name: name,
19 goRestfulContainer: gorestfulContainer,
20 nonGoRestfulMux: nonGoRestfulMux,
21 }
22
23 return &APIServerHandler{
24 // 创建 FullHandlerChain
25 FullHandlerChain: handlerChainBuilder(director),
26 GoRestfulContainer: gorestfulContainer,
27 NonGoRestfulMux: nonGoRestfulMux,
28 Director: director,
29 }
30}
这里 FullHandlerChain 内装有认证 handler。继续看哪里定义 handlerChainBuilder 函数的。
1# kubernetes/vendor/k8s.io/apiserver/pkg/server/config.go
2func NewConfig(codecs serializer.CodecFactory) *Config {
3 return &Config{
4 ...
5 BuildHandlerChainFunc: DefaultBuildHandlerChain,
6 }
7}
8
9# kubernetes/vendor/k8s.io/apiserver/pkg/server/config.go
10func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
11 handler = genericapifilters.WithAuthentication(handler, c.Authentication.Authenticator, failedHandler, c.Authentication.APIAudiences, c.Authentication.RequestHeaderConfig)
12 return handler
13}
14
15# kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/filters/authentication.go
16func WithAuthentication(handler http.Handler, auth authenticator.Request, failed http.Handler, apiAuds authenticator.Audiences, requestHeaderConfig *authenticatorfactory.RequestHeaderConfig) http.Handler {
17 return withAuthentication(handler, auth, failed, apiAuds, requestHeaderConfig, recordAuthenticationMetrics)
18}
在创建配置 Config 时,将 DefaultBuildHandlerChain 赋值给 BuildHandlerChainFunc。DefaultBuildHandlerChain 内的 genericapifilters.WithAuthentication 创建了认证 handler。
接着往下走,进入 genericapifilters.WithAuthentication。
1func withAuthentication(handler http.Handler, auth authenticator.Request, failed http.Handler, apiAuds authenticator.Audiences, requestHeaderConfig *authenticatorfactory.RequestHeaderConfig, metrics authenticationRecordMetricsFunc) http.Handler {
2 return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
3 resp, ok, err := auth.AuthenticateRequest(req)
4
5 // authorization header is not required anymore in case of a successful authentication.
6 req.Header.Del("Authorization")
7
8 req = req.WithContext(genericapirequest.WithUser(req.Context(), resp.User))
9 handler.ServeHTTP(w, req)
10 })
11}
12
13type Request interface {
14 AuthenticateRequest(req *http.Request) (*Response, bool, error)
15}
可以看到,认证 handler 中通过 auth.AuthenticateRequest(req) 对 RESTful API 请求进行认证。这里 auth 是一个实现 Request 接口的实例。
那么,auth 实例是在哪里创建的呢,调用的 AuthenticateRequest 方法具体做的是什么呢?带着这个问题我们看下一节认证实例。
认证实例
通过层层回溯找到调用点。
1handler = genericapifilters.WithAuthentication(handler, c.Authentication.Authenticator, failedHandler, c.Authentication.APIAudiences, c.Authentication.RequestHeaderConfig)
这里 c.Authentication.Authenticator 即为 auth 的实例。我们看 c.Authentication.Authenticator 是在哪里创建的。
1# kubernetes/pkg/controlplane/apiserver/config.go
2func BuildGenericConfig(
3 s controlplaneapiserver.CompletedOptions,
4 schemes []*runtime.Scheme,
5 getOpenAPIDefinitions func(ref openapicommon.ReferenceCallback) map[string]openapicommon.OpenAPIDefinition,
6) (
7 genericConfig *genericapiserver.Config,
8 versionedInformers clientgoinformers.SharedInformerFactory,
9 storageFactory *serverstorage.DefaultStorageFactory,
10
11 lastErr error,
12) {
13 // Authentication.ApplyTo requires already applied OpenAPIConfig and EgressSelector if present
14 if lastErr = s.Authentication.ApplyTo(&genericConfig.Authentication, genericConfig.SecureServing, genericConfig.EgressSelector, genericConfig.OpenAPIConfig, genericConfig.OpenAPIV3Config, clientgoExternalClient, versionedInformers); lastErr != nil {
15 return
16 }
17}
18
19# kubernetes/pkg/kubeapiserver/options/authentication.go
20func (o *BuiltInAuthenticationOptions) ApplyTo(authInfo *genericapiserver.AuthenticationInfo, secureServing *genericapiserver.SecureServingInfo, egressSelector *egressselector.EgressSelector, openAPIConfig *openapicommon.Config, openAPIV3Config *openapicommon.Config, extclient kubernetes.Interface, versionedInformer informers.SharedInformerFactory) error {
21 authenticatorConfig, err := o.ToAuthenticationConfig()
22 if err != nil {
23 return err
24 }
25
26 ...
27
28 authInfo.Authenticator, openAPIConfig.SecurityDefinitions, err = authenticatorConfig.New()
29}
c.Authentication.Authenticator 实际是 authenticatorConfig.New() 创建的 authInfo.Authenticator 认证器。进入 authenticatorConfig.New() 看创建认证器过程。
1# kubernetes/pkg/controlplane/apiserver/config.go
2func (config Config) New() (authenticator.Request, *spec.SecurityDefinitions, error) {
3 var authenticators []authenticator.Request
4 var tokenAuthenticators []authenticator.Token
5 securityDefinitions := spec.SecurityDefinitions{}
6
7 // front-proxy, BasicAuth methods, local first, then remote
8 // Add the front proxy authenticator if requested
9 if config.RequestHeaderConfig != nil {
10 requestHeaderAuthenticator := headerrequest.NewDynamicVerifyOptionsSecure(
11 config.RequestHeaderConfig.CAContentProvider.VerifyOptions,
12 config.RequestHeaderConfig.AllowedClientNames,
13 config.RequestHeaderConfig.UsernameHeaders,
14 config.RequestHeaderConfig.GroupHeaders,
15 config.RequestHeaderConfig.ExtraHeaderPrefixes,
16 )
17 authenticators = append(authenticators, authenticator.WrapAudienceAgnosticRequest(config.APIAudiences, requestHeaderAuthenticator))
18 }
19
20 // X509 methods
21 if config.ClientCAContentProvider != nil {
22 certAuth := x509.NewDynamic(config.ClientCAContentProvider.VerifyOptions, x509.CommonNameUserConversion)
23 authenticators = append(authenticators, certAuth)
24 }
25
26 ...
27
28 authenticator := union.New(authenticators...)
29 authenticator = group.NewAuthenticatedGroupAdder(authenticator)
30 return authenticator, &securityDefinitions, nil
31}
32
33# kubernetes/vendor/k8s.io/apiserver/pkg/authentication/request/union/union.go
34func New(authRequestHandlers ...authenticator.Request) authenticator.Request {
35 if len(authRequestHandlers) == 1 {
36 return authRequestHandlers[0]
37 }
38 return &unionAuthRequestHandler{Handlers: authRequestHandlers, FailOnError: false}
39}
40
41# kubernetes/vendor/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go
42func NewAuthenticatedGroupAdder(auth authenticator.Request) authenticator.Request {
43 return &AuthenticatedGroupAdder{auth}
44}
可以看到,认证器是一系列认证器的组合。每个认证器包括组合的认证器都实现了 authenticator.Request 接口的 AuthenticateRequest 方法。
回头看在 handler 中定义的 auth.AuthenticateRequest(req) 方法,实际执行的是 authenticator.AuthenticateRequest(req)。
1# kubernetes/vendor/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go
2func (g *AuthenticatedGroupAdder) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
3 r, ok, err := g.Authenticator.AuthenticateRequest(req)
4 if err != nil || !ok {
5 return nil, ok, err
6 }
7}
8
9# kubernetes/vendor/k8s.io/apiserver/pkg/authentication/request/union/union.go
10func (authHandler *unionAuthRequestHandler) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
11 var errlist []error
12 for _, currAuthRequestHandler := range authHandler.Handlers {
13 resp, ok, err := currAuthRequestHandler.AuthenticateRequest(req)
14 if err != nil {
15 if authHandler.FailOnError {
16 return resp, ok, err
17 }
18 errlist = append(errlist, err)
19 continue
20 }
21
22 if ok {
23 return resp, ok, err
24 }
25 }
26
27 return nil, false, utilerrors.NewAggregate(errlist)
28}
通过层层调用,最终执行到 unionAuthRequestHandler.AuthenticateRequest。该方法中循环执行各个认证器的 AuthenticateRequest 方法,直到认证成功。
各认证器的认证方式不同,这里就不过多介绍了,具体涉及到各种认证方式的时候可详细看相应认证器的 AuthenticateRequest 方法。
总结
通过本篇文章介绍了 kube-apiserver 中的 Authentication 认证流程,下一篇将继续介绍 kube-apiserver 的 Authorization 授权流程。