From ca60f81cfd3839f2c8bda2c6723a37e11f898fa5 Mon Sep 17 00:00:00 2001
From: kaiyou <dev@kaiyou.fr>
Date: Sun, 23 Apr 2023 15:17:25 +0200
Subject: [PATCH] Improve documentation about the apiserver

---
 services/apiserver.go | 42 ++++++++++++++++++++++++------------------
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/services/apiserver.go b/services/apiserver.go
index bd5bfce..81afb46 100644
--- a/services/apiserver.go
+++ b/services/apiserver.go
@@ -9,7 +9,6 @@ import (
 	"time"
 
 	"github.com/google/uuid"
-	//	extensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
 	extensions "k8s.io/apiextensions-apiserver/pkg/apiserver"
 	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
@@ -214,11 +213,17 @@ var kubeApiserver = &Unit{
 		// Allow privileged pods
 		capabilities.Setup(true, 0)
 
-		// Configure etcd backend
+		// Configure the etcd backend, this is used by both the default and CRD apiservers
 		etcdConfig := storagebackend.NewDefaultConfig("/registry", nil)
 		etcdConfig.Transport.ServerList = []string{"http://[::1]:2379"}
 
 		// Servers are created in reverse orders for proper delegation
+		// First notFound is the default handler, that basically returns a 404,
+		// then the extensions serves CRD for unknown kinds, finally
+		// the default apiserver is first in the chain and serves all default kinds
+		// Note that no API aggregation is setup, which means that k8s API aggregation
+		// is not supported by hepto.
+
 		notFound := notfoundhandler.New(config.Serializer, apifilters.NoMuxAndDiscoveryIncompleteKey)
 
 		// Tweak the configuration and build the extension server
@@ -233,7 +238,6 @@ var kubeApiserver = &Unit{
 		extensionsConfig.GenericConfig.RESTOptionsGetter = &RestOptionsFactory{
 			StorageFactory: storage.NewDefaultStorageFactory(
 				*etcdConfig,
-				//*storagebackend.NewDefaultConfig("/registry", extensions.Codecs.LegacyCodec(extensionsv1.SchemeGroupVersion)),
 				runtime.ContentTypeJSON,
 				legacyscheme.Codecs,
 				storage.NewDefaultResourceEncodingConfig(extensions.Scheme),
@@ -256,7 +260,7 @@ var kubeApiserver = &Unit{
 			controlplane.DefaultAPIResourceConfigSource(),
 			kubeapiserver.SpecialDefaultResourcePrefixes,
 		)
-		signer, err := serviceaccount.JWTTokenGenerator("https://kubernetes.default.svc.cluster.local", c.masterCerts.APITokens.Key)
+		signer, err := serviceaccount.JWTTokenGenerator(audience, c.masterCerts.APITokens.Key)
 		if err != nil {
 			return fmt.Errorf("could not initilize service account signer: %w", err)
 		}
@@ -271,32 +275,30 @@ var kubeApiserver = &Unit{
 					ReadOnlyPort:          ports.KubeletReadOnlyPort,
 					PreferredAddressTypes: []string{string(core.NodeInternalIP), string(core.NodeExternalIP)},
 				},
-				ServiceIPRange:           *c.networking.ServiceNet,
-				APIServerServiceIP:       c.networking.APIAddress,
-				APIServerServicePort:     443,
-				ServiceNodePortRange:     options.DefaultServiceNodePortRange,
+				ServiceIPRange:       *c.networking.ServiceNet,
+				APIServerServiceIP:   c.networking.APIAddress,
+				APIServerServicePort: 443,
+				ServiceNodePortRange: options.DefaultServiceNodePortRange,
+				// This still triggers an error, stating that stale data was found and cleaned up,
+				// which is inevitable
 				EndpointReconcilerType:   reconcilers.NoneEndpointReconcilerType,
 				MasterCount:              1,
 				ServiceAccountIssuer:     signer,
-				ServiceAccountIssuerURL:  "https://kubernetes.default.svc.cluster.local",
-				ServiceAccountPublicKeys: nil, // TODO
+				ServiceAccountIssuerURL:  audience,
+				ServiceAccountPublicKeys: []interface{}{&c.masterCerts.APITokens.Key.PublicKey},
 				VersionedInformers:       clients.Informer,
 			},
 		}
 		apiConfig.GenericConfig.RESTOptionsGetter = &RestOptionsFactory{StorageFactory: storageFactory}
-		getOpenapi := openapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(generatedopenapi.GetOpenAPIDefinitions)
-		apiConfig.GenericConfig.OpenAPIConfig = server.DefaultOpenAPIConfig(getOpenapi, openapinamer.NewDefinitionNamer(legacyscheme.Scheme, extensions.Scheme))
-		apiConfig.GenericConfig.OpenAPIConfig = server.DefaultOpenAPIConfig(getOpenapi, openapinamer.NewDefinitionNamer(legacyscheme.Scheme, extensions.Scheme))
+		openapiFactory := openapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(generatedopenapi.GetOpenAPIDefinitions)
+		apiConfig.GenericConfig.OpenAPIConfig = server.DefaultOpenAPIConfig(openapiFactory, openapinamer.NewDefinitionNamer(legacyscheme.Scheme, extensions.Scheme))
+		apiConfig.GenericConfig.OpenAPIConfig = server.DefaultOpenAPIConfig(openapiFactory, openapinamer.NewDefinitionNamer(legacyscheme.Scheme, extensions.Scheme))
 		apiConfig.ExtraConfig.ClusterAuthenticationInfo.ClientCA = config.SecureServing.ClientCA
 		apiServer, err := apiConfig.Complete().New(extensionServer.GenericAPIServer)
 		if err != nil {
 			return fmt.Errorf("could not initialize generic apiserver: %w", err)
 		}
 
-		// TODO: no aggregation layer is setup
-
-		server := apiServer.GenericAPIServer.PrepareRun()
-
 		// Write a loopback config (different for every start)
 		name := "loopback"
 		clientConfig := api.Config{
@@ -324,12 +326,16 @@ var kubeApiserver = &Unit{
 			return fmt.Errorf("could not write privileged kubeconfig: %w", err)
 		}
 
+		// Finally start the apiserver
+		server := apiServer.GenericAPIServer.PrepareRun()
 		return server.Run(ctx.Done())
 	},
 	Ready: func(u *Unit, c *Cluster) bool {
 		u.Logger.Info("checking if apiserver is ready")
+		// Use the scheduler certificate for readiness test, which is more relevant than
+		// using the internal privileged API token
 		kc := &rest.Config{
-			Host: fmt.Sprintf("https://[%s]:6443", c.networking.NodeAddress.IP.String()),
+			Host: fmt.Sprintf("https://[%s]:%d", c.networking.NodeAddress.IP.String(), apiserverPort),
 			TLSClientConfig: rest.TLSClientConfig{
 				CAFile:   c.pki.TLS.CertPath(),
 				CertFile: c.masterCerts.SchedulerAPI.CertPath(),
-- 
GitLab