metropolis/node/kubernetes: move worker services to KubernetesWorker nodes

This finalizes the Big Split. After this change, nodes will only run a
kubelet (and related services) if they have a KubernetesWorker role
attached.

The first node in a new cluster now starts out with KubernetesController
and ConsensusMember. All joined nodes start with no roles attached.

Change-Id: I25a059318450b7d2dd3c19f3653fc15367867693
Reviewed-on: https://review.monogon.dev/c/monogon/+/1380
Tested-by: Jenkins CI
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/metropolis/node/kubernetes/pki/kubernetes.go b/metropolis/node/kubernetes/pki/kubernetes.go
index dbebf73..ead8897 100644
--- a/metropolis/node/kubernetes/pki/kubernetes.go
+++ b/metropolis/node/kubernetes/pki/kubernetes.go
@@ -392,29 +392,25 @@
 	return client, nil
 }
 
-// VolatileKubelet returns a pair of server/client ceritficates for the Kubelet
-// to use. The certificates are ephemeral, meaning they are not stored in etcd,
-// and instead are regenerated any time this function is called.
-func (k *PKI) VolatileKubelet(ctx context.Context, name string) (server *opki.Certificate, client *opki.Certificate, err error) {
-	name = fmt.Sprintf("system:node:%s", name)
+// NetServices returns a certificate to be used by nfproxy and clusternet running
+// on a worker node.
+func (k *PKI) NetServices(ctx context.Context, name string, pubkey ed25519.PublicKey) (client *opki.Certificate, err error) {
+	name = fmt.Sprintf("metropolis:netservices:%s", name)
 	err = k.EnsureAll(ctx)
 	if err != nil {
-		return nil, nil, fmt.Errorf("could not ensure certificates exist: %w", err)
+		return nil, fmt.Errorf("could not ensure certificates exist: %w", err)
 	}
 	kubeCA := k.Certificates[IdCA]
-	server = &opki.Certificate{
-		Namespace: &k.namespace,
-		Issuer:    kubeCA,
-		Template:  opki.Server([]string{name}, nil),
-		Mode:      opki.CertificateEphemeral,
-	}
+	clientName := fmt.Sprintf("netservices-%s", name)
 	client = &opki.Certificate{
+		Name:      clientName,
 		Namespace: &k.namespace,
 		Issuer:    kubeCA,
-		Template:  opki.Client(name, []string{"system:nodes"}),
-		Mode:      opki.CertificateEphemeral,
+		Template:  opki.Client(name, []string{"metropolis:netservices"}),
+		Mode:      opki.CertificateExternal,
+		PublicKey: pubkey,
 	}
-	return server, client, nil
+	return client, nil
 }
 
 // VolatileClient returns a client certificate for Kubernetes clients to use.