scripts/create_container: fix cockroachdb startup

After moving the build container to --net=host this broke building //...
(as sqlboiler touches a local crdb in order to generate SQL
boilerplate...). This moves cockroachdb to also run with --net=host, and
fixes the advertisement address in the same way as it's fixed in
run_ci.sh.

Test Plan: tested this locally :/

X-Origin-Diff: phab/D562
GitOrigin-RevId: 25aee769a555d34ae3c9f12560a8a29986601034
diff --git a/core/internal/kubernetes/BUILD.bazel b/core/internal/kubernetes/BUILD.bazel
index f3304cc..97387df 100644
--- a/core/internal/kubernetes/BUILD.bazel
+++ b/core/internal/kubernetes/BUILD.bazel
@@ -4,7 +4,6 @@
     name = "go_default_library",
     srcs = [
         "apiserver.go",
-        "auth.go",
         "controller-manager.go",
         "csi.go",
         "kubelet.go",
@@ -19,6 +18,7 @@
         "//core/internal/common:go_default_library",
         "//core/internal/common/supervisor:go_default_library",
         "//core/internal/consensus:go_default_library",
+        "//core/internal/kubernetes/pki:go_default_library",
         "//core/internal/kubernetes/reconciler:go_default_library",
         "//core/internal/storage:go_default_library",
         "//core/pkg/fileargs:go_default_library",
@@ -39,7 +39,6 @@
         "@io_k8s_client_go//kubernetes/typed/core/v1:go_default_library",
         "@io_k8s_client_go//tools/cache:go_default_library",
         "@io_k8s_client_go//tools/clientcmd:go_default_library",
-        "@io_k8s_client_go//tools/clientcmd/api:go_default_library",
         "@io_k8s_client_go//tools/record:go_default_library",
         "@io_k8s_client_go//tools/reference:go_default_library",
         "@io_k8s_client_go//util/workqueue:go_default_library",
diff --git a/core/internal/kubernetes/apiserver.go b/core/internal/kubernetes/apiserver.go
index 9bc32f3..b5bab3d 100644
--- a/core/internal/kubernetes/apiserver.go
+++ b/core/internal/kubernetes/apiserver.go
@@ -27,11 +27,11 @@
 	"path"
 
 	"git.monogon.dev/source/nexantic.git/core/internal/common"
+	"git.monogon.dev/source/nexantic.git/core/internal/common/supervisor"
+	"git.monogon.dev/source/nexantic.git/core/internal/kubernetes/pki"
+	"git.monogon.dev/source/nexantic.git/core/pkg/fileargs"
 
 	"go.etcd.io/etcd/clientv3"
-
-	"git.monogon.dev/source/nexantic.git/core/internal/common/supervisor"
-	"git.monogon.dev/source/nexantic.git/core/pkg/fileargs"
 )
 
 type apiserverConfig struct {
@@ -52,12 +52,12 @@
 func getPKIApiserverConfig(consensusKV clientv3.KV) (*apiserverConfig, error) {
 	var config apiserverConfig
 	var err error
-	config.idCA, _, err = getCert(consensusKV, "id-ca")
-	config.kubeletClientCert, config.kubeletClientKey, err = getCert(consensusKV, "kubelet-client")
-	config.aggregationCA, _, err = getCert(consensusKV, "aggregation-ca")
-	config.aggregationClientCert, config.aggregationClientKey, err = getCert(consensusKV, "front-proxy-client")
-	config.serverCert, config.serverKey, err = getCert(consensusKV, "apiserver")
-	saPrivkey, err := consensusKV.Get(context.Background(), path.Join(etcdPath, "service-account-privkey.der"))
+	config.idCA, _, err = pki.GetCert(consensusKV, "id-ca")
+	config.kubeletClientCert, config.kubeletClientKey, err = pki.GetCert(consensusKV, "kubelet-client")
+	config.aggregationCA, _, err = pki.GetCert(consensusKV, "aggregation-ca")
+	config.aggregationClientCert, config.aggregationClientKey, err = pki.GetCert(consensusKV, "front-proxy-client")
+	config.serverCert, config.serverKey, err = pki.GetCert(consensusKV, "apiserver")
+	saPrivkey, err := consensusKV.Get(context.Background(), path.Join(pki.EtcdPath, "service-account-privkey.der"))
 	if err != nil {
 		return nil, fmt.Errorf("failed to get serviceaccount privkey: %w", err)
 	}
diff --git a/core/internal/kubernetes/controller-manager.go b/core/internal/kubernetes/controller-manager.go
index 20d4605..a6b4b5d 100644
--- a/core/internal/kubernetes/controller-manager.go
+++ b/core/internal/kubernetes/controller-manager.go
@@ -27,6 +27,7 @@
 	"go.etcd.io/etcd/clientv3"
 
 	"git.monogon.dev/source/nexantic.git/core/internal/common/supervisor"
+	"git.monogon.dev/source/nexantic.git/core/internal/kubernetes/pki"
 	"git.monogon.dev/source/nexantic.git/core/pkg/fileargs"
 )
 
@@ -43,19 +44,19 @@
 func getPKIControllerManagerConfig(consensusKV clientv3.KV) (*controllerManagerConfig, error) {
 	var config controllerManagerConfig
 	var err error
-	config.rootCA, _, err = getCert(consensusKV, "id-ca")
+	config.rootCA, _, err = pki.GetCert(consensusKV, "id-ca")
 	if err != nil {
 		return nil, fmt.Errorf("failed to get ID root CA: %w", err)
 	}
-	config.serverCert, config.serverKey, err = getCert(consensusKV, "controller-manager")
+	config.serverCert, config.serverKey, err = pki.GetCert(consensusKV, "controller-manager")
 	if err != nil {
 		return nil, fmt.Errorf("failed to get controller-manager serving certificate: %w", err)
 	}
-	config.serviceAccountPrivKey, err = getSingle(consensusKV, "service-account-privkey.der")
+	config.serviceAccountPrivKey, err = pki.GetSingle(consensusKV, "service-account-privkey.der")
 	if err != nil {
 		return nil, fmt.Errorf("failed to get serviceaccount privkey: %w", err)
 	}
-	config.kubeConfig, err = getSingle(consensusKV, "controller-manager.kubeconfig")
+	config.kubeConfig, err = pki.GetSingle(consensusKV, "controller-manager.kubeconfig")
 	if err != nil {
 		return nil, fmt.Errorf("failed to get controller-manager kubeconfig: %w", err)
 	}
diff --git a/core/internal/kubernetes/kubelet.go b/core/internal/kubernetes/kubelet.go
index 3b0d966..e9d0332 100644
--- a/core/internal/kubernetes/kubelet.go
+++ b/core/internal/kubernetes/kubelet.go
@@ -18,21 +18,16 @@
 
 import (
 	"context"
-	"crypto/ed25519"
 	"encoding/json"
-	"encoding/pem"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net"
-	"os"
 	"os/exec"
 
 	"git.monogon.dev/source/nexantic.git/core/internal/common/supervisor"
 	"git.monogon.dev/source/nexantic.git/core/internal/kubernetes/reconciler"
 	"git.monogon.dev/source/nexantic.git/core/pkg/fileargs"
 
-	"go.etcd.io/etcd/clientv3"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	kubeletconfig "k8s.io/kubelet/config/v1beta1"
 )
@@ -41,44 +36,6 @@
 	clusterDNS []net.IP
 }
 
-func bootstrapLocalKubelet(consensusKV clientv3.KV, nodeName string) error {
-	idCA, idKeyRaw, err := getCert(consensusKV, "id-ca")
-	if err != nil {
-		return err
-	}
-	idKey := ed25519.PrivateKey(idKeyRaw)
-	cert, key, err := issueCertificate(clientCertTemplate("system:node:"+nodeName, []string{"system:nodes"}), idCA, idKey)
-	if err != nil {
-		return err
-	}
-	kubeconfig, err := makeLocalKubeconfig(idCA, cert, key)
-	if err != nil {
-		return err
-	}
-
-	serverCert, serverKey, err := issueCertificate(serverCertTemplate([]string{nodeName}, []net.IP{}), idCA, idKey)
-	if err != nil {
-		return err
-	}
-	if err := os.MkdirAll("/data/kubernetes", 0755); err != nil {
-		return err
-	}
-	if err := ioutil.WriteFile("/data/kubernetes/kubelet.kubeconfig", kubeconfig, 0400); err != nil {
-		return err
-	}
-	if err := ioutil.WriteFile("/data/kubernetes/ca.crt", pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: idCA}), 0400); err != nil {
-		return err
-	}
-	if err := ioutil.WriteFile("/data/kubernetes/kubelet.crt", pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: serverCert}), 0400); err != nil {
-		return err
-	}
-	if err := ioutil.WriteFile("/data/kubernetes/kubelet.key", pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: serverKey}), 0400); err != nil {
-		return err
-	}
-
-	return nil
-}
-
 func runKubelet(spec *KubeletSpec, output io.Writer) supervisor.Runnable {
 	return func(ctx context.Context) error {
 		fargs, err := fileargs.New()
diff --git a/core/internal/kubernetes/pki/BUILD.bazel b/core/internal/kubernetes/pki/BUILD.bazel
new file mode 100644
index 0000000..605ca64
--- /dev/null
+++ b/core/internal/kubernetes/pki/BUILD.bazel
@@ -0,0 +1,14 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_library")
+
+go_library(
+    name = "go_default_library",
+    srcs = ["auth.go"],
+    importpath = "git.monogon.dev/source/nexantic.git/core/internal/kubernetes/pki",
+    visibility = ["//core:__subpackages__"],
+    deps = [
+        "//core/internal/common:go_default_library",
+        "@io_etcd_go_etcd//clientv3:go_default_library",
+        "@io_k8s_client_go//tools/clientcmd:go_default_library",
+        "@io_k8s_client_go//tools/clientcmd/api:go_default_library",
+    ],
+)
diff --git a/core/internal/kubernetes/auth.go b/core/internal/kubernetes/pki/auth.go
similarity index 76%
rename from core/internal/kubernetes/auth.go
rename to core/internal/kubernetes/pki/auth.go
index fe2fe59..21d998c 100644
--- a/core/internal/kubernetes/auth.go
+++ b/core/internal/kubernetes/pki/auth.go
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package kubernetes
+package pki
 
 import (
 	"context"
@@ -28,6 +28,7 @@
 	"encoding/asn1"
 	"encoding/pem"
 	"fmt"
+	"io/ioutil"
 	"math/big"
 	"net"
 	"os"
@@ -42,7 +43,7 @@
 )
 
 const (
-	etcdPath = "/kube-pki/"
+	EtcdPath = "/kube-pki/"
 )
 
 var (
@@ -52,7 +53,7 @@
 
 // Directly derived from Kubernetes PKI requirements documented at
 // https://kubernetes.io/docs/setup/best-practices/certificates/#configure-certificates-manually
-func clientCertTemplate(identity string, groups []string) x509.Certificate {
+func ClientCertTemplate(identity string, groups []string) x509.Certificate {
 	return x509.Certificate{
 		Subject: pkix.Name{
 			CommonName:   identity,
@@ -62,7 +63,7 @@
 		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
 	}
 }
-func serverCertTemplate(dnsNames []string, ips []net.IP) x509.Certificate {
+func ServerCertTemplate(dnsNames []string, ips []net.IP) x509.Certificate {
 	return x509.Certificate{
 		Subject:     pkix.Name{},
 		KeyUsage:    x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
@@ -133,8 +134,8 @@
 }
 
 func storeCert(consensusKV clientv3.KV, name string, cert []byte, key []byte) error {
-	certPath := path.Join(etcdPath, fmt.Sprintf("%v-cert.der", name))
-	keyPath := path.Join(etcdPath, fmt.Sprintf("%v-key.der", name))
+	certPath := path.Join(EtcdPath, fmt.Sprintf("%v-cert.der", name))
+	keyPath := path.Join(EtcdPath, fmt.Sprintf("%v-key.der", name))
 	if _, err := consensusKV.Put(context.Background(), certPath, string(cert)); err != nil {
 		return fmt.Errorf("failed to store certificate: %w", err)
 	}
@@ -144,9 +145,9 @@
 	return nil
 }
 
-func getCert(consensusKV clientv3.KV, name string) (cert []byte, key []byte, err error) {
-	certPath := path.Join(etcdPath, fmt.Sprintf("%v-cert.der", name))
-	keyPath := path.Join(etcdPath, fmt.Sprintf("%v-key.der", name))
+func GetCert(consensusKV clientv3.KV, name string) (cert []byte, key []byte, err error) {
+	certPath := path.Join(EtcdPath, fmt.Sprintf("%v-cert.der", name))
+	keyPath := path.Join(EtcdPath, fmt.Sprintf("%v-key.der", name))
 	certRes, err := consensusKV.Get(context.Background(), certPath)
 	if err != nil {
 		err = fmt.Errorf("failed to get certificate: %w", err)
@@ -166,8 +167,8 @@
 	return
 }
 
-func getSingle(consensusKV clientv3.KV, name string) ([]byte, error) {
-	res, err := consensusKV.Get(context.Background(), path.Join(etcdPath, name))
+func GetSingle(consensusKV clientv3.KV, name string) ([]byte, error) {
+	res, err := consensusKV.Get(context.Background(), path.Join(EtcdPath, name))
 	if err != nil {
 		return []byte{}, fmt.Errorf("failed to get PKI item: %w", err)
 	}
@@ -182,7 +183,7 @@
 // the need for revocation and makes the logic much simpler. Thus PKI data can NEVER be stored
 // outside of etcd or other secure storage locations. All PKI data is stored in DER form and not
 // PEM encoded since that would require more logic to deal with it.
-func newCluster(consensusKV clientv3.KV) error {
+func NewCluster(consensusKV clientv3.KV) error {
 	// This whole issuance procedure is pretty repetitive, but abstracts badly because a lot of it
 	// is subtly different.
 	idCA, idKey, err := newCA("Smalltown Kubernetes ID CA")
@@ -209,14 +210,14 @@
 	if err != nil {
 		panic(err) // Always a programmer error
 	}
-	_, err = consensusKV.Put(context.Background(), path.Join(etcdPath, "service-account-privkey.der"),
+	_, err = consensusKV.Put(context.Background(), path.Join(EtcdPath, "service-account-privkey.der"),
 		string(serviceAccountPrivKey))
 	if err != nil {
 		return fmt.Errorf("failed to store service-account-privkey.der: %w", err)
 	}
 
-	apiserverCert, apiserverKey, err := issueCertificate(
-		serverCertTemplate([]string{
+	apiserverCert, apiserverKey, err := IssueCertificate(
+		ServerCertTemplate([]string{
 			"kubernetes",
 			"kubernetes.default",
 			"kubernetes.default.svc",
@@ -234,8 +235,8 @@
 		return err
 	}
 
-	kubeletClientCert, kubeletClientKey, err := issueCertificate(
-		clientCertTemplate("smalltown:apiserver-kubelet-client", []string{}),
+	kubeletClientCert, kubeletClientKey, err := IssueCertificate(
+		ClientCertTemplate("smalltown:apiserver-kubelet-client", []string{}),
 		idCA, idKey,
 	)
 	if err != nil {
@@ -245,8 +246,8 @@
 		return err
 	}
 
-	frontProxyClientCert, frontProxyClientKey, err := issueCertificate(
-		clientCertTemplate("front-proxy-client", []string{}),
+	frontProxyClientCert, frontProxyClientKey, err := IssueCertificate(
+		ClientCertTemplate("front-proxy-client", []string{}),
 		aggregationCA, aggregationKey,
 	)
 	if err != nil {
@@ -256,28 +257,28 @@
 		return err
 	}
 
-	controllerManagerClientCert, controllerManagerClientKey, err := issueCertificate(
-		clientCertTemplate("system:kube-controller-manager", []string{}),
+	controllerManagerClientCert, controllerManagerClientKey, err := IssueCertificate(
+		ClientCertTemplate("system:kube-controller-manager", []string{}),
 		idCA, idKey,
 	)
 	if err != nil {
 		return fmt.Errorf("failed to issue certificate for controller-manager client: %w", err)
 	}
 
-	controllerManagerKubeconfig, err := makeLocalKubeconfig(idCA, controllerManagerClientCert,
+	controllerManagerKubeconfig, err := MakeLocalKubeconfig(idCA, controllerManagerClientCert,
 		controllerManagerClientKey)
 	if err != nil {
 		return fmt.Errorf("failed to create kubeconfig for controller-manager: %w", err)
 	}
 
-	_, err = consensusKV.Put(context.Background(), path.Join(etcdPath, "controller-manager.kubeconfig"),
+	_, err = consensusKV.Put(context.Background(), path.Join(EtcdPath, "controller-manager.kubeconfig"),
 		string(controllerManagerKubeconfig))
 	if err != nil {
 		return fmt.Errorf("failed to store controller-manager kubeconfig: %w", err)
 	}
 
-	controllerManagerCert, controllerManagerKey, err := issueCertificate(
-		serverCertTemplate([]string{"kube-controller-manager.local"}, []net.IP{}),
+	controllerManagerCert, controllerManagerKey, err := IssueCertificate(
+		ServerCertTemplate([]string{"kube-controller-manager.local"}, []net.IP{}),
 		idCA, idKey,
 	)
 	if err != nil {
@@ -287,27 +288,27 @@
 		return err
 	}
 
-	schedulerClientCert, schedulerClientKey, err := issueCertificate(
-		clientCertTemplate("system:kube-scheduler", []string{}),
+	schedulerClientCert, schedulerClientKey, err := IssueCertificate(
+		ClientCertTemplate("system:kube-scheduler", []string{}),
 		idCA, idKey,
 	)
 	if err != nil {
 		return fmt.Errorf("failed to issue certificate for scheduler client: %w", err)
 	}
 
-	schedulerKubeconfig, err := makeLocalKubeconfig(idCA, schedulerClientCert, schedulerClientKey)
+	schedulerKubeconfig, err := MakeLocalKubeconfig(idCA, schedulerClientCert, schedulerClientKey)
 	if err != nil {
 		return fmt.Errorf("failed to create kubeconfig for scheduler: %w", err)
 	}
 
-	_, err = consensusKV.Put(context.Background(), path.Join(etcdPath, "scheduler.kubeconfig"),
+	_, err = consensusKV.Put(context.Background(), path.Join(EtcdPath, "scheduler.kubeconfig"),
 		string(schedulerKubeconfig))
 	if err != nil {
 		return fmt.Errorf("failed to store controller-manager kubeconfig: %w", err)
 	}
 
-	schedulerCert, schedulerKey, err := issueCertificate(
-		serverCertTemplate([]string{"kube-scheduler.local"}, []net.IP{}),
+	schedulerCert, schedulerKey, err := IssueCertificate(
+		ServerCertTemplate([]string{"kube-scheduler.local"}, []net.IP{}),
 		idCA, idKey,
 	)
 	if err != nil {
@@ -317,21 +318,21 @@
 		return err
 	}
 
-	masterClientCert, masterClientKey, err := issueCertificate(
-		clientCertTemplate("smalltown:master", []string{"system:masters"}),
+	masterClientCert, masterClientKey, err := IssueCertificate(
+		ClientCertTemplate("smalltown:master", []string{"system:masters"}),
 		idCA, idKey,
 	)
 	if err != nil {
 		return fmt.Errorf("failed to issue certificate for master client: %w", err)
 	}
 
-	masterClientKubeconfig, err := makeLocalKubeconfig(idCA, masterClientCert,
+	masterClientKubeconfig, err := MakeLocalKubeconfig(idCA, masterClientCert,
 		masterClientKey)
 	if err != nil {
 		return fmt.Errorf("failed to create kubeconfig for master client: %w", err)
 	}
 
-	_, err = consensusKV.Put(context.Background(), path.Join(etcdPath, "master.kubeconfig"),
+	_, err = consensusKV.Put(context.Background(), path.Join(EtcdPath, "master.kubeconfig"),
 		string(masterClientKubeconfig))
 	if err != nil {
 		return fmt.Errorf("failed to store master kubeconfig: %w", err)
@@ -348,7 +349,7 @@
 	return nil
 }
 
-func issueCertificate(template x509.Certificate, caCert []byte, privateKey interface{}) (cert []byte, privkey []byte, err error) {
+func IssueCertificate(template x509.Certificate, caCert []byte, privateKey interface{}) (cert []byte, privkey []byte, err error) {
 	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 127)
 	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
 	if err != nil {
@@ -380,7 +381,7 @@
 	return
 }
 
-func makeLocalKubeconfig(ca, cert, key []byte) ([]byte, error) {
+func MakeLocalKubeconfig(ca, cert, key []byte) ([]byte, error) {
 	kubeconfig := configapi.NewConfig()
 	cluster := configapi.NewCluster()
 	cluster.Server = fmt.Sprintf("https://127.0.0.1:%v", common.KubernetesAPIPort)
@@ -397,3 +398,41 @@
 	kubeconfig.CurrentContext = "default"
 	return clientcmd.Write(*kubeconfig)
 }
+
+func bootstrapLocalKubelet(consensusKV clientv3.KV, nodeName string) error {
+	idCA, idKeyRaw, err := GetCert(consensusKV, "id-ca")
+	if err != nil {
+		return err
+	}
+	idKey := ed25519.PrivateKey(idKeyRaw)
+	cert, key, err := IssueCertificate(ClientCertTemplate("system:node:"+nodeName, []string{"system:nodes"}), idCA, idKey)
+	if err != nil {
+		return err
+	}
+	kubeconfig, err := MakeLocalKubeconfig(idCA, cert, key)
+	if err != nil {
+		return err
+	}
+
+	serverCert, serverKey, err := IssueCertificate(ServerCertTemplate([]string{nodeName}, []net.IP{}), idCA, idKey)
+	if err != nil {
+		return err
+	}
+	if err := os.MkdirAll("/data/kubernetes", 0755); err != nil {
+		return err
+	}
+	if err := ioutil.WriteFile("/data/kubernetes/kubelet.kubeconfig", kubeconfig, 0400); err != nil {
+		return err
+	}
+	if err := ioutil.WriteFile("/data/kubernetes/ca.crt", pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: idCA}), 0400); err != nil {
+		return err
+	}
+	if err := ioutil.WriteFile("/data/kubernetes/kubelet.crt", pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: serverCert}), 0400); err != nil {
+		return err
+	}
+	if err := ioutil.WriteFile("/data/kubernetes/kubelet.key", pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: serverKey}), 0400); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/core/internal/kubernetes/scheduler.go b/core/internal/kubernetes/scheduler.go
index d3ee20b..e3be0a0 100644
--- a/core/internal/kubernetes/scheduler.go
+++ b/core/internal/kubernetes/scheduler.go
@@ -26,6 +26,7 @@
 	"go.etcd.io/etcd/clientv3"
 
 	"git.monogon.dev/source/nexantic.git/core/internal/common/supervisor"
+	"git.monogon.dev/source/nexantic.git/core/internal/kubernetes/pki"
 	"git.monogon.dev/source/nexantic.git/core/pkg/fileargs"
 )
 
@@ -38,11 +39,11 @@
 func getPKISchedulerConfig(consensusKV clientv3.KV) (*schedulerConfig, error) {
 	var config schedulerConfig
 	var err error
-	config.serverCert, config.serverKey, err = getCert(consensusKV, "scheduler")
+	config.serverCert, config.serverKey, err = pki.GetCert(consensusKV, "scheduler")
 	if err != nil {
 		return nil, fmt.Errorf("failed to get scheduler serving certificate: %w", err)
 	}
-	config.kubeConfig, err = getSingle(consensusKV, "scheduler.kubeconfig")
+	config.kubeConfig, err = pki.GetSingle(consensusKV, "scheduler.kubeconfig")
 	if err != nil {
 		return nil, fmt.Errorf("failed to get scheduler kubeconfig: %w", err)
 	}
diff --git a/core/internal/kubernetes/service.go b/core/internal/kubernetes/service.go
index b2d340e..b8c3cf8 100644
--- a/core/internal/kubernetes/service.go
+++ b/core/internal/kubernetes/service.go
@@ -35,6 +35,7 @@
 	schema "git.monogon.dev/source/nexantic.git/core/generated/api"
 	"git.monogon.dev/source/nexantic.git/core/internal/common/supervisor"
 	"git.monogon.dev/source/nexantic.git/core/internal/consensus"
+	"git.monogon.dev/source/nexantic.git/core/internal/kubernetes/pki"
 	"git.monogon.dev/source/nexantic.git/core/internal/kubernetes/reconciler"
 	"git.monogon.dev/source/nexantic.git/core/internal/storage"
 	"git.monogon.dev/source/nexantic.git/core/pkg/logbuffer"
@@ -74,7 +75,7 @@
 }
 
 func (s *Service) NewCluster() error {
-	return newCluster(s.getKV())
+	return pki.NewCluster(s.getKV())
 }
 
 // GetComponentLogs grabs logs from various Kubernetes binaries
@@ -98,16 +99,16 @@
 	if !s.consensusService.IsReady() {
 		return nil, status.Error(codes.Unavailable, "Consensus not ready yet")
 	}
-	idCA, idKeyRaw, err := getCert(s.getKV(), "id-ca")
+	idCA, idKeyRaw, err := pki.GetCert(s.getKV(), "id-ca")
 	idKey := ed25519.PrivateKey(idKeyRaw)
 	if err != nil {
 		return nil, status.Errorf(codes.Unavailable, "Failed to load ID CA: %v", err)
 	}
-	debugCert, debugKey, err := issueCertificate(clientCertTemplate(request.Id, request.Groups), idCA, idKey)
+	debugCert, debugKey, err := pki.IssueCertificate(pki.ClientCertTemplate(request.Id, request.Groups), idCA, idKey)
 	if err != nil {
 		return nil, status.Errorf(codes.Unavailable, "Failed to issue certs for kubeconfig: %v\n", err)
 	}
-	debugKubeconfig, err := makeLocalKubeconfig(idCA, debugCert, debugKey)
+	debugKubeconfig, err := pki.MakeLocalKubeconfig(idCA, debugCert, debugKey)
 	if err != nil {
 		return nil, status.Errorf(codes.Unavailable, "Failed to generate kubeconfig: %v", err)
 	}
@@ -151,7 +152,7 @@
 			return err
 		}
 
-		masterKubeconfig, err := getSingle(consensusKV, "master.kubeconfig")
+		masterKubeconfig, err := pki.GetSingle(consensusKV, "master.kubeconfig")
 		if err != nil {
 			return err
 		}
diff --git a/scripts/create_container.sh b/scripts/create_container.sh
index 486d758..3ecf877 100755
--- a/scripts/create_container.sh
+++ b/scripts/create_container.sh
@@ -60,4 +60,5 @@
     --pod nexantic \
     --ulimit nofile=262144:262144 \
     --name=nexantic-cockroach \
-    cockroachdb/cockroach:v19.1.5 start --insecure
+    --net=host \
+    cockroachdb/cockroach:v19.1.5 start --insecure  --advertise-addr localhost