mirror of https://github.com/k3s-io/k3s
Merge pull request #42548 from andrewrynhard/use_secrets
Automatic merge from submit-queue (batch tested with PRs 48374, 48524, 48519, 42548, 48615) Use Secrets for files that self-hosted pods depend on **What this PR does / why we need it**: See https://github.com/kubernetes/kubeadm/issues/194 **Release note**: ```release-note NONE ``` ``` bash-4.2# kubectl --kubeconfig /etc/kubernetes/admin.conf get pods -n kube-system NAME READY STATUS RESTARTS AGE dummy-1628042694-6ghbq 1/1 Running 0 42m kube-dns-1853130399-4nzx4 3/3 Running 0 9m kube-flannel-ds-mnq10 2/2 Running 2 12m kube-flannel-ds-n3tl8 2/2 Running 0 42m kube-proxy-lqpcb 1/1 Running 0 42m kube-proxy-pw0pw 1/1 Running 0 12m self-hosted-kube-apiserver-fkkwd 1/1 Running 1 42m self-hosted-kube-controller-manager-1387498942-mzg41 1/1 Running 1 42m self-hosted-kube-scheduler-2588609441-cwhqb 1/1 Running 1 42m ``` ### API Server ``` bash-4.2# kubectl --kubeconfig /etc/kubernetes/admin.conf exec self-hosted-kube-apiserver-fkkwd -n kube-system -- ls /etc/pki ca-trust java nssdb rpm-gpg tls bash-4.2# kubectl --kubeconfig /etc/kubernetes/admin.conf exec self-hosted-kube-apiserver-fkkwd -n kube-system -- ls /etc/ssl certs bash-4.2# kubectl --kubeconfig /etc/kubernetes/admin.conf exec self-hosted-kube-apiserver-fkkwd -n kube-system -- ls /etc/kubernetes/ pki bash-4.2# kubectl --kubeconfig /etc/kubernetes/admin.conf exec self-hosted-kube-apiserver-fkkwd -n kube-system -- ls /etc/kubernetes/pki/ apiserver-kubelet-client.crt apiserver-kubelet-client.key apiserver.crt apiserver.key ca.crt front-proxy-ca.crt sa.pub ``` ### Scheduler ``` bash-4.2# kubectl --kubeconfig /etc/kubernetes/admin.conf exec self-hosted-kube-scheduler-2588609441-cwhqb -n kube-system -- ls /etc/kubernetes/ scheduler.conf ``` ### Controller Manager ``` bash-4.2# kubectl --kubeconfig /etc/kubernetes/admin.conf exec self-hosted-kube-controller-manager-1387498942-mzg41 -n kube-system -- ls /etc/ssl certs bash-4.2# kubectl --kubeconfig /etc/kubernetes/admin.conf exec self-hosted-kube-controller-manager-1387498942-mzg41 -n kube-system -- ls /etc/pki ca-trust java nssdb rpm-gpg tls bash-4.2# kubectl --kubeconfig /etc/kubernetes/admin.conf exec self-hosted-kube-controller-manager-1387498942-mzg41 -n kube-system -- ls /etc/kubernetes/ controller-manager.conf pki bash-4.2# kubectl --kubeconfig /etc/kubernetes/admin.conf exec self-hosted-kube-controller-manager-1387498942-mzg41 -n kube-system -- ls /etc/kubernetes/pki/ ca.crt ca.key sa.key ``` /cc @luxas @liggitt @pires @timothyscpull/6/head
commit
89136f64b9
|
@ -271,7 +271,7 @@ func (i *Init) Run(out io.Writer) error {
|
||||||
// Temporary control plane is up, now we create our self hosted control
|
// Temporary control plane is up, now we create our self hosted control
|
||||||
// plane components and remove the static manifests:
|
// plane components and remove the static manifests:
|
||||||
fmt.Println("[self-hosted] Creating self-hosted control plane...")
|
fmt.Println("[self-hosted] Creating self-hosted control plane...")
|
||||||
if err := selfhostingphase.CreateSelfHostedControlPlane(client); err != nil {
|
if err := selfhostingphase.CreateSelfHostedControlPlane(i.cfg, client); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,23 +19,30 @@ package phases
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting"
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewCmdSelfhosting returns the self-hosting Cobra command
|
// NewCmdSelfhosting returns the self-hosting Cobra command
|
||||||
func NewCmdSelfhosting() *cobra.Command {
|
func NewCmdSelfhosting() *cobra.Command {
|
||||||
var kubeConfigFile string
|
var kubeConfigFile string
|
||||||
|
cfg := &kubeadmapiext.MasterConfiguration{}
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "selfhosting",
|
Use: "selfhosting",
|
||||||
Aliases: []string{"selfhosted"},
|
Aliases: []string{"selfhosted"},
|
||||||
Short: "Make a kubeadm cluster self-hosted.",
|
Short: "Make a kubeadm cluster self-hosted.",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
api.Scheme.Default(cfg)
|
||||||
|
internalcfg := &kubeadmapi.MasterConfiguration{}
|
||||||
|
api.Scheme.Convert(cfg, internalcfg, nil)
|
||||||
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
|
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
|
||||||
kubeadmutil.CheckErr(err)
|
kubeadmutil.CheckErr(err)
|
||||||
|
|
||||||
err = selfhosting.CreateSelfHostedControlPlane(client)
|
err = selfhosting.CreateSelfHostedControlPlane(internalcfg, client)
|
||||||
kubeadmutil.CheckErr(err)
|
kubeadmutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,12 @@ go_test(
|
||||||
srcs = [
|
srcs = [
|
||||||
"podspec_mutation_test.go",
|
"podspec_mutation_test.go",
|
||||||
"selfhosting_test.go",
|
"selfhosting_test.go",
|
||||||
|
"selfhosting_volumes_test.go",
|
||||||
],
|
],
|
||||||
library = ":go_default_library",
|
library = ":go_default_library",
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||||
"//cmd/kubeadm/app/constants:go_default_library",
|
"//cmd/kubeadm/app/constants:go_default_library",
|
||||||
"//vendor/github.com/ghodss/yaml:go_default_library",
|
"//vendor/github.com/ghodss/yaml:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
|
@ -28,9 +30,11 @@ go_library(
|
||||||
srcs = [
|
srcs = [
|
||||||
"podspec_mutation.go",
|
"podspec_mutation.go",
|
||||||
"selfhosting.go",
|
"selfhosting.go",
|
||||||
|
"selfhosting_volumes.go",
|
||||||
],
|
],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||||
"//cmd/kubeadm/app/constants:go_default_library",
|
"//cmd/kubeadm/app/constants:go_default_library",
|
||||||
"//cmd/kubeadm/app/util:go_default_library",
|
"//cmd/kubeadm/app/util:go_default_library",
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
|
|
|
@ -18,38 +18,42 @@ package selfhosting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
// mutatePodSpec makes a Static Pod-hosted PodSpec suitable for self-hosting
|
// mutatePodSpec makes a Static Pod-hosted PodSpec suitable for self-hosting
|
||||||
func mutatePodSpec(name string, podSpec *v1.PodSpec) {
|
func mutatePodSpec(cfg *kubeadmapi.MasterConfiguration, name string, podSpec *v1.PodSpec) {
|
||||||
mutators := map[string][]func(*v1.PodSpec){
|
mutators := map[string][]func(*kubeadmapi.MasterConfiguration, *v1.PodSpec){
|
||||||
kubeAPIServer: {
|
kubeAPIServer: {
|
||||||
addNodeSelectorToPodSpec,
|
addNodeSelectorToPodSpec,
|
||||||
setMasterTolerationOnPodSpec,
|
setMasterTolerationOnPodSpec,
|
||||||
setRightDNSPolicyOnPodSpec,
|
setRightDNSPolicyOnPodSpec,
|
||||||
|
setVolumesOnKubeAPIServerPodSpec,
|
||||||
},
|
},
|
||||||
kubeControllerManager: {
|
kubeControllerManager: {
|
||||||
addNodeSelectorToPodSpec,
|
addNodeSelectorToPodSpec,
|
||||||
setMasterTolerationOnPodSpec,
|
setMasterTolerationOnPodSpec,
|
||||||
setRightDNSPolicyOnPodSpec,
|
setRightDNSPolicyOnPodSpec,
|
||||||
|
setVolumesOnKubeControllerManagerPodSpec,
|
||||||
},
|
},
|
||||||
kubeScheduler: {
|
kubeScheduler: {
|
||||||
addNodeSelectorToPodSpec,
|
addNodeSelectorToPodSpec,
|
||||||
setMasterTolerationOnPodSpec,
|
setMasterTolerationOnPodSpec,
|
||||||
setRightDNSPolicyOnPodSpec,
|
setRightDNSPolicyOnPodSpec,
|
||||||
|
setVolumesOnKubeSchedulerPodSpec,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the mutator functions for the component in question, then loop through and execute them
|
// Get the mutator functions for the component in question, then loop through and execute them
|
||||||
mutatorsForComponent := mutators[name]
|
mutatorsForComponent := mutators[name]
|
||||||
for _, mutateFunc := range mutatorsForComponent {
|
for _, mutateFunc := range mutatorsForComponent {
|
||||||
mutateFunc(podSpec)
|
mutateFunc(cfg, podSpec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// addNodeSelectorToPodSpec makes Pod require to be scheduled on a node marked with the master label
|
// addNodeSelectorToPodSpec makes Pod require to be scheduled on a node marked with the master label
|
||||||
func addNodeSelectorToPodSpec(podSpec *v1.PodSpec) {
|
func addNodeSelectorToPodSpec(cfg *kubeadmapi.MasterConfiguration, podSpec *v1.PodSpec) {
|
||||||
if podSpec.NodeSelector == nil {
|
if podSpec.NodeSelector == nil {
|
||||||
podSpec.NodeSelector = map[string]string{kubeadmconstants.LabelNodeRoleMaster: ""}
|
podSpec.NodeSelector = map[string]string{kubeadmconstants.LabelNodeRoleMaster: ""}
|
||||||
return
|
return
|
||||||
|
@ -59,7 +63,7 @@ func addNodeSelectorToPodSpec(podSpec *v1.PodSpec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setMasterTolerationOnPodSpec makes the Pod tolerate the master taint
|
// setMasterTolerationOnPodSpec makes the Pod tolerate the master taint
|
||||||
func setMasterTolerationOnPodSpec(podSpec *v1.PodSpec) {
|
func setMasterTolerationOnPodSpec(cfg *kubeadmapi.MasterConfiguration, podSpec *v1.PodSpec) {
|
||||||
if podSpec.Tolerations == nil {
|
if podSpec.Tolerations == nil {
|
||||||
podSpec.Tolerations = []v1.Toleration{kubeadmconstants.MasterToleration}
|
podSpec.Tolerations = []v1.Toleration{kubeadmconstants.MasterToleration}
|
||||||
return
|
return
|
||||||
|
@ -69,6 +73,38 @@ func setMasterTolerationOnPodSpec(podSpec *v1.PodSpec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setRightDNSPolicyOnPodSpec makes sure the self-hosted components can look up things via kube-dns if necessary
|
// setRightDNSPolicyOnPodSpec makes sure the self-hosted components can look up things via kube-dns if necessary
|
||||||
func setRightDNSPolicyOnPodSpec(podSpec *v1.PodSpec) {
|
func setRightDNSPolicyOnPodSpec(cfg *kubeadmapi.MasterConfiguration, podSpec *v1.PodSpec) {
|
||||||
podSpec.DNSPolicy = v1.DNSClusterFirstWithHostNet
|
podSpec.DNSPolicy = v1.DNSClusterFirstWithHostNet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setVolumesOnKubeAPIServerPodSpec makes sure the self-hosted api server has the required files
|
||||||
|
func setVolumesOnKubeAPIServerPodSpec(cfg *kubeadmapi.MasterConfiguration, podSpec *v1.PodSpec) {
|
||||||
|
setK8sVolume(apiServerProjectedVolume, cfg, podSpec)
|
||||||
|
for _, c := range podSpec.Containers {
|
||||||
|
c.VolumeMounts = append(c.VolumeMounts, k8sSelfHostedVolumeMount())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setVolumesOnKubeControllerManagerPodSpec makes sure the self-hosted controller manager has the required files
|
||||||
|
func setVolumesOnKubeControllerManagerPodSpec(cfg *kubeadmapi.MasterConfiguration, podSpec *v1.PodSpec) {
|
||||||
|
setK8sVolume(controllerManagerProjectedVolume, cfg, podSpec)
|
||||||
|
for _, c := range podSpec.Containers {
|
||||||
|
c.VolumeMounts = append(c.VolumeMounts, k8sSelfHostedVolumeMount())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setVolumesOnKubeSchedulerPodSpec makes sure the self-hosted scheduler has the required files
|
||||||
|
func setVolumesOnKubeSchedulerPodSpec(cfg *kubeadmapi.MasterConfiguration, podSpec *v1.PodSpec) {
|
||||||
|
setK8sVolume(schedulerProjectedVolume, cfg, podSpec)
|
||||||
|
for _, c := range podSpec.Containers {
|
||||||
|
c.VolumeMounts = append(c.VolumeMounts, k8sSelfHostedVolumeMount())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setK8sVolume(cb func(cfg *kubeadmapi.MasterConfiguration) v1.Volume, cfg *kubeadmapi.MasterConfiguration, podSpec *v1.PodSpec) {
|
||||||
|
for i, v := range podSpec.Volumes {
|
||||||
|
if v.Name == "k8s" {
|
||||||
|
podSpec.Volumes[i] = cb(cfg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -71,8 +72,9 @@ func TestMutatePodSpec(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg := &kubeadmapi.MasterConfiguration{}
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
mutatePodSpec(rt.component, rt.podSpec)
|
mutatePodSpec(cfg, rt.component, rt.podSpec)
|
||||||
|
|
||||||
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
||||||
t.Errorf("failed mutatePodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
t.Errorf("failed mutatePodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
||||||
|
@ -108,8 +110,9 @@ func TestAddNodeSelectorToPodSpec(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg := &kubeadmapi.MasterConfiguration{}
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
addNodeSelectorToPodSpec(rt.podSpec)
|
addNodeSelectorToPodSpec(cfg, rt.podSpec)
|
||||||
|
|
||||||
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
||||||
t.Errorf("failed addNodeSelectorToPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
t.Errorf("failed addNodeSelectorToPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
||||||
|
@ -145,8 +148,9 @@ func TestSetMasterTolerationOnPodSpec(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg := &kubeadmapi.MasterConfiguration{}
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
setMasterTolerationOnPodSpec(rt.podSpec)
|
setMasterTolerationOnPodSpec(cfg, rt.podSpec)
|
||||||
|
|
||||||
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
||||||
t.Errorf("failed setMasterTolerationOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
t.Errorf("failed setMasterTolerationOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
||||||
|
@ -175,8 +179,9 @@ func TestSetRightDNSPolicyOnPodSpec(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg := &kubeadmapi.MasterConfiguration{}
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
setRightDNSPolicyOnPodSpec(rt.podSpec)
|
setRightDNSPolicyOnPodSpec(cfg, rt.podSpec)
|
||||||
|
|
||||||
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
||||||
t.Errorf("failed setRightDNSPolicyOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
t.Errorf("failed setRightDNSPolicyOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
||||||
|
|
|
@ -29,6 +29,7 @@ import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
kuberuntime "k8s.io/apimachinery/pkg/runtime"
|
kuberuntime "k8s.io/apimachinery/pkg/runtime"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
@ -53,7 +54,15 @@ const (
|
||||||
// 7. The self-hosted containers should now step up and take over.
|
// 7. The self-hosted containers should now step up and take over.
|
||||||
// 8. In order to avoid race conditions, we're still making sure the API /healthz endpoint is healthy
|
// 8. In order to avoid race conditions, we're still making sure the API /healthz endpoint is healthy
|
||||||
// 9. Do that for the kube-apiserver, kube-controller-manager and kube-scheduler in a loop
|
// 9. Do that for the kube-apiserver, kube-controller-manager and kube-scheduler in a loop
|
||||||
func CreateSelfHostedControlPlane(client *clientset.Clientset) error {
|
func CreateSelfHostedControlPlane(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset) error {
|
||||||
|
|
||||||
|
if err := createTLSSecrets(cfg, client); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := createOpaqueSecrets(cfg, client); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// The sequence here isn't set in stone, but seems to work well to start with the API server
|
// The sequence here isn't set in stone, but seems to work well to start with the API server
|
||||||
components := []string{kubeAPIServer, kubeControllerManager, kubeScheduler}
|
components := []string{kubeAPIServer, kubeControllerManager, kubeScheduler}
|
||||||
|
@ -69,7 +78,7 @@ func CreateSelfHostedControlPlane(client *clientset.Clientset) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a DaemonSet object from the loaded PodSpec
|
// Build a DaemonSet object from the loaded PodSpec
|
||||||
ds := buildDaemonSet(componentName, podSpec)
|
ds := buildDaemonSet(cfg, componentName, podSpec)
|
||||||
|
|
||||||
// Create the DaemonSet in the API Server
|
// Create the DaemonSet in the API Server
|
||||||
if _, err := client.ExtensionsV1beta1().DaemonSets(metav1.NamespaceSystem).Create(ds); err != nil {
|
if _, err := client.ExtensionsV1beta1().DaemonSets(metav1.NamespaceSystem).Create(ds); err != nil {
|
||||||
|
@ -100,9 +109,9 @@ func CreateSelfHostedControlPlane(client *clientset.Clientset) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildDaemonSet is responsible for mutating the PodSpec and return a DaemonSet which is suitable for the self-hosting purporse
|
// buildDaemonSet is responsible for mutating the PodSpec and return a DaemonSet which is suitable for the self-hosting purporse
|
||||||
func buildDaemonSet(name string, podSpec *v1.PodSpec) *extensions.DaemonSet {
|
func buildDaemonSet(cfg *kubeadmapi.MasterConfiguration, name string, podSpec *v1.PodSpec) *extensions.DaemonSet {
|
||||||
// Mutate the PodSpec so it's suitable for self-hosting
|
// Mutate the PodSpec so it's suitable for self-hosting
|
||||||
mutatePodSpec(name, podSpec)
|
mutatePodSpec(cfg, name, podSpec)
|
||||||
|
|
||||||
// Return a DaemonSet based on that Spec
|
// Return a DaemonSet based on that Spec
|
||||||
return &extensions.DaemonSet{
|
return &extensions.DaemonSet{
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -90,9 +91,49 @@ spec:
|
||||||
name: pki
|
name: pki
|
||||||
hostNetwork: true
|
hostNetwork: true
|
||||||
volumes:
|
volumes:
|
||||||
- hostPath:
|
- name: k8s
|
||||||
path: /etc/kubernetes
|
projected:
|
||||||
name: k8s
|
sources:
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: ca.crt
|
||||||
|
- key: tls.key
|
||||||
|
path: ca.key
|
||||||
|
name: ca
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: apiserver.crt
|
||||||
|
- key: tls.key
|
||||||
|
path: apiserver.key
|
||||||
|
name: apiserver
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: apiserver-kubelet-client.crt
|
||||||
|
- key: tls.key
|
||||||
|
path: apiserver-kubelet-client.key
|
||||||
|
name: apiserver-kubelet-client
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: sa.pub
|
||||||
|
- key: tls.key
|
||||||
|
path: sa.key
|
||||||
|
name: sa
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: front-proxy-ca.crt
|
||||||
|
name: front-proxy-ca
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: front-proxy-client.crt
|
||||||
|
- key: tls.key
|
||||||
|
path: front-proxy-client.key
|
||||||
|
name: front-proxy-client
|
||||||
- hostPath:
|
- hostPath:
|
||||||
path: /etc/ssl/certs
|
path: /etc/ssl/certs
|
||||||
name: certs
|
name: certs
|
||||||
|
@ -171,9 +212,49 @@ spec:
|
||||||
- effect: NoSchedule
|
- effect: NoSchedule
|
||||||
key: node-role.kubernetes.io/master
|
key: node-role.kubernetes.io/master
|
||||||
volumes:
|
volumes:
|
||||||
- hostPath:
|
- name: k8s
|
||||||
path: /etc/kubernetes
|
projected:
|
||||||
name: k8s
|
sources:
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: ca.crt
|
||||||
|
- key: tls.key
|
||||||
|
path: ca.key
|
||||||
|
name: ca
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: apiserver.crt
|
||||||
|
- key: tls.key
|
||||||
|
path: apiserver.key
|
||||||
|
name: apiserver
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: apiserver-kubelet-client.crt
|
||||||
|
- key: tls.key
|
||||||
|
path: apiserver-kubelet-client.key
|
||||||
|
name: apiserver-kubelet-client
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: sa.pub
|
||||||
|
- key: tls.key
|
||||||
|
path: sa.key
|
||||||
|
name: sa
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: front-proxy-ca.crt
|
||||||
|
name: front-proxy-ca
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: front-proxy-client.crt
|
||||||
|
- key: tls.key
|
||||||
|
path: front-proxy-client.key
|
||||||
|
name: front-proxy-client
|
||||||
- hostPath:
|
- hostPath:
|
||||||
path: /etc/ssl/certs
|
path: /etc/ssl/certs
|
||||||
name: certs
|
name: certs
|
||||||
|
@ -237,9 +318,23 @@ spec:
|
||||||
name: pki
|
name: pki
|
||||||
hostNetwork: true
|
hostNetwork: true
|
||||||
volumes:
|
volumes:
|
||||||
- hostPath:
|
- name: k8s
|
||||||
path: /etc/kubernetes
|
projected:
|
||||||
name: k8s
|
sources:
|
||||||
|
- secret:
|
||||||
|
name: controller-manager.conf
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: ca.crt
|
||||||
|
- key: tls.key
|
||||||
|
path: ca.key
|
||||||
|
name: ca
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.key
|
||||||
|
path: sa.key
|
||||||
|
name: sa
|
||||||
- hostPath:
|
- hostPath:
|
||||||
path: /etc/ssl/certs
|
path: /etc/ssl/certs
|
||||||
name: certs
|
name: certs
|
||||||
|
@ -304,9 +399,23 @@ spec:
|
||||||
- effect: NoSchedule
|
- effect: NoSchedule
|
||||||
key: node-role.kubernetes.io/master
|
key: node-role.kubernetes.io/master
|
||||||
volumes:
|
volumes:
|
||||||
- hostPath:
|
- name: k8s
|
||||||
path: /etc/kubernetes
|
projected:
|
||||||
name: k8s
|
sources:
|
||||||
|
- secret:
|
||||||
|
name: controller-manager.conf
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.crt
|
||||||
|
path: ca.crt
|
||||||
|
- key: tls.key
|
||||||
|
path: ca.key
|
||||||
|
name: ca
|
||||||
|
- secret:
|
||||||
|
items:
|
||||||
|
- key: tls.key
|
||||||
|
path: sa.key
|
||||||
|
name: sa
|
||||||
- hostPath:
|
- hostPath:
|
||||||
path: /etc/ssl/certs
|
path: /etc/ssl/certs
|
||||||
name: certs
|
name: certs
|
||||||
|
@ -360,9 +469,11 @@ spec:
|
||||||
readOnly: true
|
readOnly: true
|
||||||
hostNetwork: true
|
hostNetwork: true
|
||||||
volumes:
|
volumes:
|
||||||
- hostPath:
|
- name: k8s
|
||||||
path: /etc/kubernetes
|
projected:
|
||||||
name: k8s
|
sources:
|
||||||
|
- secret:
|
||||||
|
name: scheduler.conf
|
||||||
status: {}
|
status: {}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -411,9 +522,11 @@ spec:
|
||||||
- effect: NoSchedule
|
- effect: NoSchedule
|
||||||
key: node-role.kubernetes.io/master
|
key: node-role.kubernetes.io/master
|
||||||
volumes:
|
volumes:
|
||||||
- hostPath:
|
- name: k8s
|
||||||
path: /etc/kubernetes
|
projected:
|
||||||
name: k8s
|
sources:
|
||||||
|
- secret:
|
||||||
|
name: scheduler.conf
|
||||||
updateStrategy: {}
|
updateStrategy: {}
|
||||||
status:
|
status:
|
||||||
currentNumberScheduled: 0
|
currentNumberScheduled: 0
|
||||||
|
@ -455,7 +568,8 @@ func TestBuildDaemonSet(t *testing.T) {
|
||||||
t.Fatalf("couldn't load the specified Pod")
|
t.Fatalf("couldn't load the specified Pod")
|
||||||
}
|
}
|
||||||
|
|
||||||
ds := buildDaemonSet(rt.component, podSpec)
|
cfg := &kubeadmapi.MasterConfiguration{}
|
||||||
|
ds := buildDaemonSet(cfg, rt.component, podSpec)
|
||||||
dsBytes, err := yaml.Marshal(ds)
|
dsBytes, err := yaml.Marshal(ds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to marshal daemonset to YAML: %v", err)
|
t.Fatalf("failed to marshal daemonset to YAML: %v", err)
|
||||||
|
|
|
@ -0,0 +1,340 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package selfhosting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tlsKeyPair struct {
|
||||||
|
name string
|
||||||
|
cert string
|
||||||
|
key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func k8sSelfHostedVolumeMount() v1.VolumeMount {
|
||||||
|
return v1.VolumeMount{
|
||||||
|
Name: "k8s",
|
||||||
|
MountPath: kubeadmapi.GlobalEnvParams.KubernetesDir,
|
||||||
|
ReadOnly: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func apiServerProjectedVolume(cfg *kubeadmapi.MasterConfiguration) v1.Volume {
|
||||||
|
return v1.Volume{
|
||||||
|
Name: "k8s",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
Projected: &v1.ProjectedVolumeSource{
|
||||||
|
Sources: []v1.VolumeProjection{
|
||||||
|
{
|
||||||
|
Secret: &v1.SecretProjection{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: kubeadmconstants.CACertAndKeyBaseName,
|
||||||
|
},
|
||||||
|
Items: []v1.KeyToPath{
|
||||||
|
{
|
||||||
|
Key: v1.TLSCertKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.CACertName),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: v1.TLSPrivateKeyKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.CAKeyName),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Secret: &v1.SecretProjection{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: kubeadmconstants.APIServerCertAndKeyBaseName,
|
||||||
|
},
|
||||||
|
Items: []v1.KeyToPath{
|
||||||
|
{
|
||||||
|
Key: v1.TLSCertKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.APIServerCertName),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: v1.TLSPrivateKeyKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.APIServerKeyName),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Secret: &v1.SecretProjection{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName,
|
||||||
|
},
|
||||||
|
Items: []v1.KeyToPath{
|
||||||
|
{
|
||||||
|
Key: v1.TLSCertKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.APIServerKubeletClientCertName),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: v1.TLSPrivateKeyKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.APIServerKubeletClientKeyName),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Secret: &v1.SecretProjection{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: kubeadmconstants.ServiceAccountKeyBaseName,
|
||||||
|
},
|
||||||
|
Items: []v1.KeyToPath{
|
||||||
|
{
|
||||||
|
Key: v1.TLSCertKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.ServiceAccountPublicKeyName),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: v1.TLSPrivateKeyKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.ServiceAccountPrivateKeyName),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Secret: &v1.SecretProjection{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: kubeadmconstants.FrontProxyCACertAndKeyBaseName,
|
||||||
|
},
|
||||||
|
Items: []v1.KeyToPath{
|
||||||
|
{
|
||||||
|
Key: v1.TLSCertKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.FrontProxyCACertName),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Secret: &v1.SecretProjection{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: kubeadmconstants.FrontProxyClientCertAndKeyBaseName,
|
||||||
|
},
|
||||||
|
Items: []v1.KeyToPath{
|
||||||
|
{
|
||||||
|
Key: v1.TLSCertKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.FrontProxyClientCertName),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: v1.TLSPrivateKeyKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.FrontProxyClientKeyName),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func schedulerProjectedVolume(cfg *kubeadmapi.MasterConfiguration) v1.Volume {
|
||||||
|
return v1.Volume{
|
||||||
|
Name: "k8s",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
Projected: &v1.ProjectedVolumeSource{
|
||||||
|
Sources: []v1.VolumeProjection{
|
||||||
|
{
|
||||||
|
Secret: &v1.SecretProjection{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: kubeadmconstants.SchedulerKubeConfigFileName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func controllerManagerProjectedVolume(cfg *kubeadmapi.MasterConfiguration) v1.Volume {
|
||||||
|
return v1.Volume{
|
||||||
|
Name: "k8s",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
Projected: &v1.ProjectedVolumeSource{
|
||||||
|
Sources: []v1.VolumeProjection{
|
||||||
|
{
|
||||||
|
Secret: &v1.SecretProjection{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: kubeadmconstants.ControllerManagerKubeConfigFileName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Secret: &v1.SecretProjection{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: kubeadmconstants.CACertAndKeyBaseName,
|
||||||
|
},
|
||||||
|
Items: []v1.KeyToPath{
|
||||||
|
{
|
||||||
|
Key: v1.TLSCertKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.CACertName),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: v1.TLSPrivateKeyKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.CAKeyName),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Secret: &v1.SecretProjection{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: kubeadmconstants.ServiceAccountKeyBaseName,
|
||||||
|
},
|
||||||
|
Items: []v1.KeyToPath{
|
||||||
|
{
|
||||||
|
Key: v1.TLSPrivateKeyKey,
|
||||||
|
Path: path.Join(path.Base(cfg.CertificatesDir), kubeadmconstants.ServiceAccountPrivateKeyName),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTLSSecrets(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset) error {
|
||||||
|
for _, tlsKeyPair := range getTLSKeyPairs() {
|
||||||
|
secret, err := createTLSSecretFromFiles(
|
||||||
|
tlsKeyPair.name,
|
||||||
|
path.Join(cfg.CertificatesDir, tlsKeyPair.cert),
|
||||||
|
path.Join(cfg.CertificatesDir, tlsKeyPair.key),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := client.CoreV1().Secrets(metav1.NamespaceSystem).Create(secret); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("[self-hosted] Created TLS secret %q from %s and %s\n", tlsKeyPair.name, tlsKeyPair.cert, tlsKeyPair.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createOpaqueSecrets(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset) error {
|
||||||
|
files := []string{
|
||||||
|
kubeadmconstants.SchedulerKubeConfigFileName,
|
||||||
|
kubeadmconstants.ControllerManagerKubeConfigFileName,
|
||||||
|
}
|
||||||
|
for _, file := range files {
|
||||||
|
secret, err := createOpaqueSecretFromFile(
|
||||||
|
file,
|
||||||
|
path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, file),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := client.CoreV1().Secrets(metav1.NamespaceSystem).Create(secret); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("[self-hosted] Created secret %q\n", file)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTLSSecretFromFiles(secretName, crt, key string) (*v1.Secret, error) {
|
||||||
|
crtBytes, err := ioutil.ReadFile(crt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
keyBytes, err := ioutil.ReadFile(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: secretName,
|
||||||
|
Namespace: metav1.NamespaceSystem,
|
||||||
|
},
|
||||||
|
Type: v1.SecretTypeTLS,
|
||||||
|
Data: map[string][]byte{
|
||||||
|
v1.TLSCertKey: crtBytes,
|
||||||
|
v1.TLSPrivateKeyKey: keyBytes,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createOpaqueSecretFromFile(secretName, file string) (*v1.Secret, error) {
|
||||||
|
fileBytes, err := ioutil.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: secretName,
|
||||||
|
Namespace: metav1.NamespaceSystem,
|
||||||
|
},
|
||||||
|
Type: v1.SecretTypeOpaque,
|
||||||
|
Data: map[string][]byte{
|
||||||
|
path.Base(file): fileBytes,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTLSKeyPairs() []*tlsKeyPair {
|
||||||
|
return []*tlsKeyPair{
|
||||||
|
{
|
||||||
|
name: kubeadmconstants.CACertAndKeyBaseName,
|
||||||
|
cert: kubeadmconstants.CACertName,
|
||||||
|
key: kubeadmconstants.CAKeyName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: kubeadmconstants.APIServerCertAndKeyBaseName,
|
||||||
|
cert: kubeadmconstants.APIServerCertName,
|
||||||
|
key: kubeadmconstants.APIServerKeyName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName,
|
||||||
|
cert: kubeadmconstants.APIServerKubeletClientCertName,
|
||||||
|
key: kubeadmconstants.APIServerKubeletClientKeyName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: kubeadmconstants.ServiceAccountKeyBaseName,
|
||||||
|
cert: kubeadmconstants.ServiceAccountPublicKeyName,
|
||||||
|
key: kubeadmconstants.ServiceAccountPrivateKeyName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: kubeadmconstants.FrontProxyCACertAndKeyBaseName,
|
||||||
|
cert: kubeadmconstants.FrontProxyCACertName,
|
||||||
|
key: kubeadmconstants.FrontProxyCAKeyName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: kubeadmconstants.FrontProxyClientCertAndKeyBaseName,
|
||||||
|
cert: kubeadmconstants.FrontProxyClientCertName,
|
||||||
|
key: kubeadmconstants.FrontProxyClientKeyName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package selfhosting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createTemporaryFile(name string) *os.File {
|
||||||
|
content := []byte("foo")
|
||||||
|
tmpfile, err := ioutil.TempFile("", name)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := tmpfile.Write(content); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmpfile
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateTLSSecretFromFile(t *testing.T) {
|
||||||
|
tmpCert := createTemporaryFile("foo.crt")
|
||||||
|
defer os.Remove(tmpCert.Name())
|
||||||
|
tmpKey := createTemporaryFile("foo.key")
|
||||||
|
defer os.Remove(tmpKey.Name())
|
||||||
|
|
||||||
|
_, err := createTLSSecretFromFiles("foo", tmpCert.Name(), tmpKey.Name())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tmpCert.Close(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tmpKey.Close(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateOpaqueSecretFromFile(t *testing.T) {
|
||||||
|
tmpFile := createTemporaryFile("foo")
|
||||||
|
defer os.Remove(tmpFile.Name())
|
||||||
|
|
||||||
|
_, err := createOpaqueSecretFromFile("foo", tmpFile.Name())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tmpFile.Close(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue