mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 20:24:09 +00:00
Merge pull request #39846 from andrewrynhard/add_authorization_mode
Automatic merge from submit-queue Add authorization mode to kubeadm This PR adds an option in `kubeadm` to allow a user to specify an [authorization plugin](https://kubernetes.io/docs/admin/authorization/). It defaults to RBAC.
This commit is contained in:
commit
f90bb1772b
@ -36,6 +36,7 @@ filegroup(
|
|||||||
"//cmd/kubeadm/app/images:all-srcs",
|
"//cmd/kubeadm/app/images:all-srcs",
|
||||||
"//cmd/kubeadm/app/master:all-srcs",
|
"//cmd/kubeadm/app/master:all-srcs",
|
||||||
"//cmd/kubeadm/app/node:all-srcs",
|
"//cmd/kubeadm/app/node:all-srcs",
|
||||||
|
"//cmd/kubeadm/app/phases/apiconfig:all-srcs",
|
||||||
"//cmd/kubeadm/app/phases/certs:all-srcs",
|
"//cmd/kubeadm/app/phases/certs:all-srcs",
|
||||||
"//cmd/kubeadm/app/phases/kubeconfig:all-srcs",
|
"//cmd/kubeadm/app/phases/kubeconfig:all-srcs",
|
||||||
"//cmd/kubeadm/app/preflight:all-srcs",
|
"//cmd/kubeadm/app/preflight:all-srcs",
|
||||||
|
@ -39,6 +39,7 @@ type MasterConfiguration struct {
|
|||||||
Networking Networking
|
Networking Networking
|
||||||
KubernetesVersion string
|
KubernetesVersion string
|
||||||
CloudProvider string
|
CloudProvider string
|
||||||
|
AuthorizationMode string
|
||||||
}
|
}
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
|
@ -19,6 +19,7 @@ go_library(
|
|||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/v1:go_default_library",
|
"//pkg/api/v1:go_default_library",
|
||||||
|
"//pkg/kubeapiserver/authorizer:go_default_library",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||||
|
@ -18,6 +18,7 @@ package v1alpha1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -27,6 +28,7 @@ const (
|
|||||||
DefaultKubernetesFallbackVersion = "v1.5.0"
|
DefaultKubernetesFallbackVersion = "v1.5.0"
|
||||||
DefaultAPIBindPort = 6443
|
DefaultAPIBindPort = 6443
|
||||||
DefaultDiscoveryBindPort = 9898
|
DefaultDiscoveryBindPort = 9898
|
||||||
|
DefaultAuthorizationMode = authorizer.ModeRBAC
|
||||||
)
|
)
|
||||||
|
|
||||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||||
@ -56,4 +58,8 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
|
|||||||
if obj.Discovery.Token == nil && obj.Discovery.File == nil && obj.Discovery.HTTPS == nil {
|
if obj.Discovery.Token == nil && obj.Discovery.File == nil && obj.Discovery.HTTPS == nil {
|
||||||
obj.Discovery.Token = &TokenDiscovery{}
|
obj.Discovery.Token = &TokenDiscovery{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if obj.AuthorizationMode == "" {
|
||||||
|
obj.AuthorizationMode = DefaultAuthorizationMode
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ type MasterConfiguration struct {
|
|||||||
Networking Networking `json:"networking"`
|
Networking Networking `json:"networking"`
|
||||||
KubernetesVersion string `json:"kubernetesVersion"`
|
KubernetesVersion string `json:"kubernetesVersion"`
|
||||||
CloudProvider string `json:"cloudProvider"`
|
CloudProvider string `json:"cloudProvider"`
|
||||||
|
AuthorizationMode string `json:"authorizationMode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
|
@ -27,6 +27,7 @@ go_library(
|
|||||||
"//cmd/kubeadm/app/discovery:go_default_library",
|
"//cmd/kubeadm/app/discovery:go_default_library",
|
||||||
"//cmd/kubeadm/app/master:go_default_library",
|
"//cmd/kubeadm/app/master:go_default_library",
|
||||||
"//cmd/kubeadm/app/node:go_default_library",
|
"//cmd/kubeadm/app/node:go_default_library",
|
||||||
|
"//cmd/kubeadm/app/phases/apiconfig:go_default_library",
|
||||||
"//cmd/kubeadm/app/phases/certs:go_default_library",
|
"//cmd/kubeadm/app/phases/certs:go_default_library",
|
||||||
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
||||||
"//cmd/kubeadm/app/preflight:go_default_library",
|
"//cmd/kubeadm/app/preflight:go_default_library",
|
||||||
@ -34,6 +35,7 @@ go_library(
|
|||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/api/v1:go_default_library",
|
"//pkg/api/v1:go_default_library",
|
||||||
"//pkg/fields:go_default_library",
|
"//pkg/fields:go_default_library",
|
||||||
|
"//pkg/kubeapiserver/authorizer:go_default_library",
|
||||||
"//pkg/kubectl:go_default_library",
|
"//pkg/kubectl:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
"//pkg/util/flag:go_default_library",
|
"//pkg/util/flag:go_default_library",
|
||||||
@ -54,7 +56,10 @@ go_test(
|
|||||||
],
|
],
|
||||||
library = ":go_default_library",
|
library = ":go_default_library",
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = ["//cmd/kubeadm/app/preflight:go_default_library"],
|
deps = [
|
||||||
|
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
||||||
|
"//cmd/kubeadm/app/preflight:go_default_library",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
|
@ -32,6 +32,7 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/flags"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/flags"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery"
|
"k8s.io/kubernetes/cmd/kubeadm/app/discovery"
|
||||||
kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master"
|
kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/apiconfig"
|
||||||
|
|
||||||
certphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
certphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||||
@ -41,6 +42,7 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||||
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"
|
||||||
|
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -183,6 +185,7 @@ func NewInit(cfgPath string, cfg *kubeadmapi.MasterConfiguration, skipPreFlight
|
|||||||
}
|
}
|
||||||
cfg.KubernetesVersion = ver
|
cfg.KubernetesVersion = ver
|
||||||
fmt.Println("[init] Using Kubernetes version:", ver)
|
fmt.Println("[init] Using Kubernetes version:", ver)
|
||||||
|
fmt.Println("[init] Using Authorization mode:", cfg.AuthorizationMode)
|
||||||
|
|
||||||
// Warn about the limitations with the current cloudprovider solution.
|
// Warn about the limitations with the current cloudprovider solution.
|
||||||
if cfg.CloudProvider != "" {
|
if cfg.CloudProvider != "" {
|
||||||
@ -255,6 +258,24 @@ func (i *Init) Run(out io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if i.cfg.AuthorizationMode == authorizer.ModeRBAC {
|
||||||
|
err = apiconfig.CreateBootstrapRBACClusterRole(client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = apiconfig.CreateKubeDNSRBACClusterRole(client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove this when https://github.com/kubernetes/kubeadm/issues/114 is fixed
|
||||||
|
err = apiconfig.CreateKubeProxyClusterRoleBinding(client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := kubemaster.UpdateMasterRoleLabelsAndTaints(client, false); err != nil {
|
if err := kubemaster.UpdateMasterRoleLabelsAndTaints(client, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
"k8s.io/kubernetes/pkg/util/initsystem"
|
"k8s.io/kubernetes/pkg/util/initsystem"
|
||||||
@ -150,7 +151,7 @@ func drainAndRemoveNode(removeNode bool) error {
|
|||||||
hostname = strings.ToLower(hostname)
|
hostname = strings.ToLower(hostname)
|
||||||
|
|
||||||
// TODO: Use the "native" k8s client for this once we're confident the versioned is working
|
// TODO: Use the "native" k8s client for this once we're confident the versioned is working
|
||||||
kubeConfigPath := path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "kubelet.conf")
|
kubeConfigPath := path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfig.KubeletKubeConfigFileName)
|
||||||
|
|
||||||
getNodesCmd := fmt.Sprintf("kubectl --kubeconfig %s get nodes | grep %s", kubeConfigPath, hostname)
|
getNodesCmd := fmt.Sprintf("kubectl --kubeconfig %s get nodes | grep %s", kubeConfigPath, hostname)
|
||||||
output, err := exec.Command("sh", "-c", getNodesCmd).Output()
|
output, err := exec.Command("sh", "-c", getNodesCmd).Output()
|
||||||
@ -219,8 +220,8 @@ func resetConfigDir(configPathDir, pkiPathDir string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
filesToClean := []string{
|
filesToClean := []string{
|
||||||
path.Join(configPathDir, "admin.conf"),
|
path.Join(configPathDir, kubeconfig.AdminKubeConfigFileName),
|
||||||
path.Join(configPathDir, "kubelet.conf"),
|
path.Join(configPathDir, kubeconfig.KubeletKubeConfigFileName),
|
||||||
}
|
}
|
||||||
fmt.Printf("[reset] Deleting files: %v\n", filesToClean)
|
fmt.Printf("[reset] Deleting files: %v\n", filesToClean)
|
||||||
for _, path := range filesToClean {
|
for _, path := range filesToClean {
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -63,8 +64,8 @@ func TestConfigDirCleaner(t *testing.T) {
|
|||||||
"manifests/etcd.json",
|
"manifests/etcd.json",
|
||||||
"manifests/kube-apiserver.json",
|
"manifests/kube-apiserver.json",
|
||||||
"pki/ca.pem",
|
"pki/ca.pem",
|
||||||
"admin.conf",
|
kubeconfig.AdminKubeConfigFileName,
|
||||||
"kubelet.conf",
|
kubeconfig.KubeletKubeConfigFileName,
|
||||||
},
|
},
|
||||||
verifyExists: []string{
|
verifyExists: []string{
|
||||||
"manifests",
|
"manifests",
|
||||||
@ -77,7 +78,7 @@ func TestConfigDirCleaner(t *testing.T) {
|
|||||||
},
|
},
|
||||||
setupFiles: []string{
|
setupFiles: []string{
|
||||||
"pki/ca.pem",
|
"pki/ca.pem",
|
||||||
"kubelet.conf",
|
kubeconfig.KubeletKubeConfigFileName,
|
||||||
},
|
},
|
||||||
verifyExists: []string{
|
verifyExists: []string{
|
||||||
"pki",
|
"pki",
|
||||||
@ -95,8 +96,8 @@ func TestConfigDirCleaner(t *testing.T) {
|
|||||||
"manifests/etcd.json",
|
"manifests/etcd.json",
|
||||||
"manifests/kube-apiserver.json",
|
"manifests/kube-apiserver.json",
|
||||||
"pki/ca.pem",
|
"pki/ca.pem",
|
||||||
"admin.conf",
|
kubeconfig.AdminKubeConfigFileName,
|
||||||
"kubelet.conf",
|
kubeconfig.KubeletKubeConfigFileName,
|
||||||
"cloud-config",
|
"cloud-config",
|
||||||
},
|
},
|
||||||
verifyExists: []string{
|
verifyExists: []string{
|
||||||
@ -115,8 +116,8 @@ func TestConfigDirCleaner(t *testing.T) {
|
|||||||
"manifests/etcd.json",
|
"manifests/etcd.json",
|
||||||
"manifests/kube-apiserver.json",
|
"manifests/kube-apiserver.json",
|
||||||
"pki/ca.pem",
|
"pki/ca.pem",
|
||||||
"admin.conf",
|
kubeconfig.AdminKubeConfigFileName,
|
||||||
"kubelet.conf",
|
kubeconfig.KubeletKubeConfigFileName,
|
||||||
".cloud-config",
|
".cloud-config",
|
||||||
".mydir/.myfile",
|
".mydir/.myfile",
|
||||||
},
|
},
|
||||||
@ -166,8 +167,8 @@ func TestConfigDirCleaner(t *testing.T) {
|
|||||||
|
|
||||||
// Verify the files we cleanup implicitly in every test:
|
// Verify the files we cleanup implicitly in every test:
|
||||||
assertExists(t, tmpDir)
|
assertExists(t, tmpDir)
|
||||||
assertNotExists(t, filepath.Join(tmpDir, "admin.conf"))
|
assertNotExists(t, filepath.Join(tmpDir, kubeconfig.AdminKubeConfigFileName))
|
||||||
assertNotExists(t, filepath.Join(tmpDir, "kubelet.conf"))
|
assertNotExists(t, filepath.Join(tmpDir, kubeconfig.KubeletKubeConfigFileName))
|
||||||
assertDirEmpty(t, filepath.Join(tmpDir, "manifests"))
|
assertDirEmpty(t, filepath.Join(tmpDir, "manifests"))
|
||||||
assertDirEmpty(t, filepath.Join(tmpDir, "pki"))
|
assertDirEmpty(t, filepath.Join(tmpDir, "pki"))
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master"
|
kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||||
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"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
@ -123,7 +124,7 @@ func NewCmdTokenGenerate(out io.Writer) *cobra.Command {
|
|||||||
|
|
||||||
// RunCreateToken generates a new bootstrap token and stores it as a secret on the server.
|
// RunCreateToken generates a new bootstrap token and stores it as a secret on the server.
|
||||||
func RunCreateToken(out io.Writer, cmd *cobra.Command, tokenDuration time.Duration, token string) error {
|
func RunCreateToken(out io.Writer, cmd *cobra.Command, tokenDuration time.Duration, token string) error {
|
||||||
client, err := kubemaster.CreateClientFromFile(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "admin.conf"))
|
client, err := kubemaster.CreateClientFromFile(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfig.AdminKubeConfigFileName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -156,7 +157,7 @@ func RunGenerateToken(out io.Writer) error {
|
|||||||
|
|
||||||
// RunListTokens lists details on all existing bootstrap tokens on the server.
|
// RunListTokens lists details on all existing bootstrap tokens on the server.
|
||||||
func RunListTokens(out io.Writer, errW io.Writer, cmd *cobra.Command) error {
|
func RunListTokens(out io.Writer, errW io.Writer, cmd *cobra.Command) error {
|
||||||
client, err := kubemaster.CreateClientFromFile(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "admin.conf"))
|
client, err := kubemaster.CreateClientFromFile(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfig.AdminKubeConfigFileName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -215,7 +216,7 @@ func RunDeleteToken(out io.Writer, cmd *cobra.Command, tokenId string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := kubemaster.CreateClientFromFile(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "admin.conf"))
|
client, err := kubemaster.CreateClientFromFile(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfig.AdminKubeConfigFileName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ go_library(
|
|||||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||||
"//cmd/kubeadm/app/images:go_default_library",
|
"//cmd/kubeadm/app/images:go_default_library",
|
||||||
|
"//cmd/kubeadm/app/phases/kubeconfig: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",
|
||||||
"//pkg/api/resource:go_default_library",
|
"//pkg/api/resource:go_default_library",
|
||||||
@ -30,6 +31,7 @@ go_library(
|
|||||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||||
"//pkg/client/unversioned/clientcmd:go_default_library",
|
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||||
"//pkg/client/unversioned/clientcmd/api:go_default_library",
|
"//pkg/client/unversioned/clientcmd/api:go_default_library",
|
||||||
|
"//pkg/kubeapiserver/authorizer:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
"//pkg/registry/core/service/ipallocator:go_default_library",
|
"//pkg/registry/core/service/ipallocator:go_default_library",
|
||||||
"//pkg/util/cert:go_default_library",
|
"//pkg/util/cert:go_default_library",
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/resource"
|
"k8s.io/kubernetes/pkg/api/resource"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
@ -31,6 +32,8 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/util/intstr"
|
"k8s.io/kubernetes/pkg/util/intstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const KubeDNS = "kube-dns"
|
||||||
|
|
||||||
func createKubeProxyPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.PodSpec {
|
func createKubeProxyPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.PodSpec {
|
||||||
privilegedTrue := true
|
privilegedTrue := true
|
||||||
return v1.PodSpec{
|
return v1.PodSpec{
|
||||||
@ -68,7 +71,7 @@ func createKubeProxyPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.PodSpec {
|
|||||||
{
|
{
|
||||||
Name: "kubeconfig",
|
Name: "kubeconfig",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
HostPath: &v1.HostPathVolumeSource{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "kubelet.conf")},
|
HostPath: &v1.HostPathVolumeSource{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfig.KubeletKubeConfigFileName)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -86,6 +89,7 @@ func createKubeDNSPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.PodSpec {
|
|||||||
dnsmasqPort := int32(53)
|
dnsmasqPort := int32(53)
|
||||||
|
|
||||||
return v1.PodSpec{
|
return v1.PodSpec{
|
||||||
|
ServiceAccountName: KubeDNS,
|
||||||
Containers: []v1.Container{
|
Containers: []v1.Container{
|
||||||
// DNS server
|
// DNS server
|
||||||
{
|
{
|
||||||
@ -250,7 +254,7 @@ func createKubeDNSServiceSpec(cfg *kubeadmapi.MasterConfiguration) (*v1.ServiceS
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &v1.ServiceSpec{
|
return &v1.ServiceSpec{
|
||||||
Selector: map[string]string{"name": "kube-dns"},
|
Selector: map[string]string{"name": KubeDNS},
|
||||||
Ports: []v1.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{Name: "dns", Port: 53, Protocol: v1.ProtocolUDP},
|
{Name: "dns", Port: 53, Protocol: v1.ProtocolUDP},
|
||||||
{Name: "dns-tcp", Port: 53, Protocol: v1.ProtocolTCP},
|
{Name: "dns-tcp", Port: 53, Protocol: v1.ProtocolTCP},
|
||||||
@ -270,10 +274,14 @@ func CreateEssentialAddons(cfg *kubeadmapi.MasterConfiguration, client *clientse
|
|||||||
|
|
||||||
fmt.Println("[addons] Created essential addon: kube-proxy")
|
fmt.Println("[addons] Created essential addon: kube-proxy")
|
||||||
|
|
||||||
kubeDNSDeployment := NewDeployment("kube-dns", 1, createKubeDNSPodSpec(cfg))
|
kubeDNSDeployment := NewDeployment(KubeDNS, 1, createKubeDNSPodSpec(cfg))
|
||||||
SetMasterTaintTolerations(&kubeDNSDeployment.Spec.Template.ObjectMeta)
|
SetMasterTaintTolerations(&kubeDNSDeployment.Spec.Template.ObjectMeta)
|
||||||
SetNodeAffinity(&kubeDNSDeployment.Spec.Template.ObjectMeta, NativeArchitectureNodeAffinity())
|
SetNodeAffinity(&kubeDNSDeployment.Spec.Template.ObjectMeta, NativeArchitectureNodeAffinity())
|
||||||
|
kubeDNSServiceAccount := &v1.ServiceAccount{}
|
||||||
|
kubeDNSServiceAccount.ObjectMeta.Name = KubeDNS
|
||||||
|
if _, err := client.ServiceAccounts(api.NamespaceSystem).Create(kubeDNSServiceAccount); err != nil {
|
||||||
|
return fmt.Errorf("failed creating kube-dns service account [%v]", err)
|
||||||
|
}
|
||||||
if _, err := client.Extensions().Deployments(api.NamespaceSystem).Create(kubeDNSDeployment); err != nil {
|
if _, err := client.Extensions().Deployments(api.NamespaceSystem).Create(kubeDNSDeployment); err != nil {
|
||||||
return fmt.Errorf("failed creating essential kube-dns addon [%v]", err)
|
return fmt.Errorf("failed creating essential kube-dns addon [%v]", err)
|
||||||
}
|
}
|
||||||
@ -283,7 +291,7 @@ func CreateEssentialAddons(cfg *kubeadmapi.MasterConfiguration, client *clientse
|
|||||||
return fmt.Errorf("failed creating essential kube-dns addon [%v]", err)
|
return fmt.Errorf("failed creating essential kube-dns addon [%v]", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
kubeDNSService := NewService("kube-dns", *kubeDNSServiceSpec)
|
kubeDNSService := NewService(KubeDNS, *kubeDNSServiceSpec)
|
||||||
kubeDNSService.ObjectMeta.Labels["kubernetes.io/name"] = "KubeDNS"
|
kubeDNSService.ObjectMeta.Labels["kubernetes.io/name"] = "KubeDNS"
|
||||||
if _, err := client.Services(api.NamespaceSystem).Create(kubeDNSService); err != nil {
|
if _, err := client.Services(api.NamespaceSystem).Create(kubeDNSService); err != nil {
|
||||||
return fmt.Errorf("failed creating essential kube-dns addon [%v]", err)
|
return fmt.Errorf("failed creating essential kube-dns addon [%v]", err)
|
||||||
|
@ -69,10 +69,15 @@ func CreateClientAndWaitForAPI(file string) (*clientset.Clientset, error) {
|
|||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
wait.PollInfinite(apiCallRetryInterval, func() (bool, error) {
|
wait.PollInfinite(apiCallRetryInterval, func() (bool, error) {
|
||||||
|
// TODO: use /healthz API instead of this
|
||||||
cs, err := client.ComponentStatuses().List(v1.ListOptions{})
|
cs, err := client.ComponentStatuses().List(v1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if apierrs.IsForbidden(err) {
|
||||||
|
fmt.Print("\r[apiclient] Waiting for the API server to create RBAC policies")
|
||||||
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
fmt.Println("\n[apiclient] RBAC policies created")
|
||||||
// TODO(phase2) must revisit this when we implement HA
|
// TODO(phase2) must revisit this when we implement HA
|
||||||
if len(cs.Items) < 3 {
|
if len(cs.Items) < 3 {
|
||||||
fmt.Println("[apiclient] Not all control plane components are ready yet")
|
fmt.Println("[apiclient] Not all control plane components are ready yet")
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||||
"k8s.io/kubernetes/pkg/api/resource"
|
"k8s.io/kubernetes/pkg/api/resource"
|
||||||
api "k8s.io/kubernetes/pkg/api/v1"
|
api "k8s.io/kubernetes/pkg/api/v1"
|
||||||
|
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"k8s.io/kubernetes/pkg/util/intstr"
|
"k8s.io/kubernetes/pkg/util/intstr"
|
||||||
|
|
||||||
@ -40,15 +41,17 @@ const (
|
|||||||
DefaultClusterName = "kubernetes"
|
DefaultClusterName = "kubernetes"
|
||||||
DefaultCloudConfigPath = "/etc/kubernetes/cloud-config"
|
DefaultCloudConfigPath = "/etc/kubernetes/cloud-config"
|
||||||
|
|
||||||
etcd = "etcd"
|
etcd = "etcd"
|
||||||
apiServer = "apiserver"
|
apiServer = "apiserver"
|
||||||
controllerManager = "controller-manager"
|
controllerManager = "controller-manager"
|
||||||
scheduler = "scheduler"
|
scheduler = "scheduler"
|
||||||
proxy = "proxy"
|
proxy = "proxy"
|
||||||
kubeAPIServer = "kube-apiserver"
|
kubeAPIServer = "kube-apiserver"
|
||||||
kubeControllerManager = "kube-controller-manager"
|
kubeControllerManager = "kube-controller-manager"
|
||||||
kubeScheduler = "kube-scheduler"
|
kubeScheduler = "kube-scheduler"
|
||||||
kubeProxy = "kube-proxy"
|
kubeProxy = "kube-proxy"
|
||||||
|
authorizationPolicyFile = "abac_policy.json"
|
||||||
|
authorizationWebhookConfigFile = "webhook_authz.conf"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -296,6 +299,16 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string {
|
|||||||
"--allow-privileged",
|
"--allow-privileged",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if cfg.AuthorizationMode != "" {
|
||||||
|
command = append(command, "--authorization-mode="+cfg.AuthorizationMode)
|
||||||
|
switch cfg.AuthorizationMode {
|
||||||
|
case authorizer.ModeABAC:
|
||||||
|
command = append(command, "--authorization-policy-file="+path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, authorizationPolicyFile))
|
||||||
|
case authorizer.ModeWebhook:
|
||||||
|
command = append(command, "--authorization-webhook-config-file="+path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, authorizationWebhookConfigFile))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Use first address we are given
|
// Use first address we are given
|
||||||
if len(cfg.API.AdvertiseAddresses) > 0 {
|
if len(cfg.API.AdvertiseAddresses) > 0 {
|
||||||
command = append(command, fmt.Sprintf("--advertise-address=%s", cfg.API.AdvertiseAddresses[0]))
|
command = append(command, fmt.Sprintf("--advertise-address=%s", cfg.API.AdvertiseAddresses[0]))
|
||||||
@ -357,7 +370,7 @@ func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration) []string {
|
|||||||
"--service-account-private-key-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/apiserver-key.pem",
|
"--service-account-private-key-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/apiserver-key.pem",
|
||||||
"--cluster-signing-cert-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/ca.pem",
|
"--cluster-signing-cert-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/ca.pem",
|
||||||
"--cluster-signing-key-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/ca-key.pem",
|
"--cluster-signing-key-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/ca-key.pem",
|
||||||
"--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap",
|
"--insecure-experimental-approve-all-kubelet-csrs-for-group=kubeadm:kubelet-bootstrap",
|
||||||
)
|
)
|
||||||
|
|
||||||
if cfg.CloudProvider != "" {
|
if cfg.CloudProvider != "" {
|
||||||
|
@ -484,7 +484,7 @@ func TestGetControllerManagerCommand(t *testing.T) {
|
|||||||
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||||
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||||
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca-key.pem",
|
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca-key.pem",
|
||||||
"--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap",
|
"--insecure-experimental-approve-all-kubelet-csrs-for-group=kubeadm:kubelet-bootstrap",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -499,7 +499,7 @@ func TestGetControllerManagerCommand(t *testing.T) {
|
|||||||
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||||
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||||
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca-key.pem",
|
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca-key.pem",
|
||||||
"--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap",
|
"--insecure-experimental-approve-all-kubelet-csrs-for-group=kubeadm:kubelet-bootstrap",
|
||||||
"--cloud-provider=foo",
|
"--cloud-provider=foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -515,7 +515,7 @@ func TestGetControllerManagerCommand(t *testing.T) {
|
|||||||
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||||
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||||
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca-key.pem",
|
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca-key.pem",
|
||||||
"--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap",
|
"--insecure-experimental-approve-all-kubelet-csrs-for-group=kubeadm:kubelet-bootstrap",
|
||||||
"--allocate-node-cidrs=true",
|
"--allocate-node-cidrs=true",
|
||||||
"--cluster-cidr=bar",
|
"--cluster-cidr=bar",
|
||||||
},
|
},
|
||||||
|
@ -32,7 +32,7 @@ func CreateTokenAuthFile(bt string) error {
|
|||||||
if err := os.MkdirAll(kubeadmapi.GlobalEnvParams.HostPKIPath, 0700); err != nil {
|
if err := os.MkdirAll(kubeadmapi.GlobalEnvParams.HostPKIPath, 0700); err != nil {
|
||||||
return fmt.Errorf("failed to create directory %q [%v]", kubeadmapi.GlobalEnvParams.HostPKIPath, err)
|
return fmt.Errorf("failed to create directory %q [%v]", kubeadmapi.GlobalEnvParams.HostPKIPath, err)
|
||||||
}
|
}
|
||||||
serialized := []byte(fmt.Sprintf("%s,kubeadm-node-csr,%s,system:kubelet-bootstrap\n", bt, uuid.NewUUID()))
|
serialized := []byte(fmt.Sprintf("%s,kubeadm-node-csr,%s,kubeadm:kubelet-bootstrap\n", bt, uuid.NewUUID()))
|
||||||
// DumpReaderToFile create a file with mode 0600
|
// DumpReaderToFile create a file with mode 0600
|
||||||
if err := cmdutil.DumpReaderToFile(bytes.NewReader(serialized), tokenAuthFilePath); err != nil {
|
if err := cmdutil.DumpReaderToFile(bytes.NewReader(serialized), tokenAuthFilePath); err != nil {
|
||||||
return fmt.Errorf("failed to save token auth file (%q) [%v]", tokenAuthFilePath, err)
|
return fmt.Errorf("failed to save token auth file (%q) [%v]", tokenAuthFilePath, err)
|
||||||
|
@ -20,7 +20,6 @@ go_library(
|
|||||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||||
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
||||||
"//cmd/kubeadm/app/util:go_default_library",
|
"//cmd/kubeadm/app/util:go_default_library",
|
||||||
"//pkg/api/v1:go_default_library",
|
|
||||||
"//pkg/apis/certificates:go_default_library",
|
"//pkg/apis/certificates:go_default_library",
|
||||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||||
"//pkg/client/unversioned/clientcmd:go_default_library",
|
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||||
@ -28,6 +27,8 @@ go_library(
|
|||||||
"//pkg/kubelet/util/csr:go_default_library",
|
"//pkg/kubelet/util/csr:go_default_library",
|
||||||
"//pkg/util/cert:go_default_library",
|
"//pkg/util/cert:go_default_library",
|
||||||
"//vendor:github.com/square/go-jose",
|
"//vendor:github.com/square/go-jose",
|
||||||
|
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||||
|
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||||
],
|
],
|
||||||
|
@ -22,12 +22,13 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
apierrs "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||||
@ -128,14 +129,9 @@ func checkForNodeNameDuplicates(clientSet *clientset.Clientset) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to get node hostname [%v]", err)
|
return fmt.Errorf("Failed to get node hostname [%v]", err)
|
||||||
}
|
}
|
||||||
nodeList, err := clientSet.Nodes().List(v1.ListOptions{})
|
_, err = clientSet.Nodes().Get(hostName, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil && !apierrs.IsNotFound(err) {
|
||||||
return fmt.Errorf("Failed to list the nodes in the cluster: [%v]\n", err)
|
return err
|
||||||
}
|
|
||||||
for _, node := range nodeList.Items {
|
|
||||||
if hostName == node.Name {
|
|
||||||
return fmt.Errorf("Node with name [%q] already exists.", node.Name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
34
cmd/kubeadm/app/phases/apiconfig/BUILD
Normal file
34
cmd/kubeadm/app/phases/apiconfig/BUILD
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@io_bazel_rules_go//go:def.bzl",
|
||||||
|
"go_library",
|
||||||
|
)
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["clusterroles.go"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
deps = [
|
||||||
|
"//cmd/kubeadm/app/master:go_default_library",
|
||||||
|
"//pkg/api:go_default_library",
|
||||||
|
"//pkg/apis/rbac/v1beta1:go_default_library",
|
||||||
|
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||||
|
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
136
cmd/kubeadm/app/phases/apiconfig/clusterroles.go
Normal file
136
cmd/kubeadm/app/phases/apiconfig/clusterroles.go
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
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 apiconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/master"
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
rbac "k8s.io/kubernetes/pkg/apis/rbac/v1beta1"
|
||||||
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateBootstrapRBACClusterRole creates the necessary ClusterRole for bootstrapping
|
||||||
|
func CreateBootstrapRBACClusterRole(clientset *clientset.Clientset) error {
|
||||||
|
clusterRole := rbac.ClusterRole{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "kubeadm:kubelet-bootstrap"},
|
||||||
|
Rules: []rbac.PolicyRule{
|
||||||
|
rbac.NewRule("get").Groups("").Resources("nodes").RuleOrDie(),
|
||||||
|
rbac.NewRule("create", "watch").Groups("certificates.k8s.io").Resources("certificatesigningrequests").RuleOrDie(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if _, err := clientset.Rbac().ClusterRoles().Create(&clusterRole); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
subject := rbac.Subject{
|
||||||
|
Kind: "Group",
|
||||||
|
Name: "kubeadm:kubelet-bootstrap",
|
||||||
|
}
|
||||||
|
|
||||||
|
clusterRoleBinding := rbac.ClusterRoleBinding{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "kubeadm:kubelet-bootstrap",
|
||||||
|
},
|
||||||
|
RoleRef: rbac.RoleRef{
|
||||||
|
APIGroup: "rbac.authorization.k8s.io",
|
||||||
|
Kind: "ClusterRole",
|
||||||
|
Name: "kubeadm:kubelet-bootstrap",
|
||||||
|
},
|
||||||
|
Subjects: []rbac.Subject{subject},
|
||||||
|
}
|
||||||
|
if _, err := clientset.Rbac().ClusterRoleBindings().Create(&clusterRoleBinding); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("[apiconfig] Created kubelet-bootstrap RBAC rules")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateKubeDNSRBACClusterRole creates the necessary ClusterRole for kube-dns
|
||||||
|
func CreateKubeDNSRBACClusterRole(clientset *clientset.Clientset) error {
|
||||||
|
clusterRole := rbac.ClusterRole{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "kubeadm:" + master.KubeDNS},
|
||||||
|
Rules: []rbac.PolicyRule{
|
||||||
|
rbac.NewRule("list", "watch").Groups("").Resources("endpoints", "services").RuleOrDie(),
|
||||||
|
// TODO: remove watch rule when https://github.com/kubernetes/kubernetes/pull/38816 gets merged
|
||||||
|
rbac.NewRule("get", "list", "watch").Groups("").Resources("configmaps").RuleOrDie(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if _, err := clientset.Rbac().ClusterRoles().Create(&clusterRole); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
subject := rbac.Subject{
|
||||||
|
Kind: "ServiceAccount",
|
||||||
|
Name: master.KubeDNS,
|
||||||
|
Namespace: api.NamespaceSystem,
|
||||||
|
}
|
||||||
|
|
||||||
|
clusterRoleBinding := rbac.ClusterRoleBinding{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "kubeadm:" + master.KubeDNS,
|
||||||
|
},
|
||||||
|
RoleRef: rbac.RoleRef{
|
||||||
|
APIGroup: "rbac.authorization.k8s.io",
|
||||||
|
Kind: "ClusterRole",
|
||||||
|
Name: "kubeadm:" + master.KubeDNS,
|
||||||
|
},
|
||||||
|
Subjects: []rbac.Subject{subject},
|
||||||
|
}
|
||||||
|
if _, err := clientset.Rbac().ClusterRoleBindings().Create(&clusterRoleBinding); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("[apiconfig] Created kube-dns RBAC rules")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateKubeProxyClusterRoleBinding creates the necessary ClusterRole for kube-dns
|
||||||
|
func CreateKubeProxyClusterRoleBinding(clientset *clientset.Clientset) error {
|
||||||
|
systemKubeProxySubject := rbac.Subject{
|
||||||
|
Kind: "User",
|
||||||
|
Name: "system:kube-proxy",
|
||||||
|
Namespace: api.NamespaceSystem,
|
||||||
|
}
|
||||||
|
|
||||||
|
systemNodesSubject := rbac.Subject{
|
||||||
|
Kind: "Group",
|
||||||
|
Name: "system:nodes",
|
||||||
|
Namespace: api.NamespaceSystem,
|
||||||
|
}
|
||||||
|
|
||||||
|
clusterRoleBinding := rbac.ClusterRoleBinding{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "system:node-proxier",
|
||||||
|
},
|
||||||
|
RoleRef: rbac.RoleRef{
|
||||||
|
APIGroup: "rbac.authorization.k8s.io",
|
||||||
|
Kind: "ClusterRole",
|
||||||
|
Name: "system:node-proxier",
|
||||||
|
},
|
||||||
|
Subjects: []rbac.Subject{systemKubeProxySubject, systemNodesSubject},
|
||||||
|
}
|
||||||
|
if _, err := clientset.Rbac().ClusterRoleBindings().Update(&clusterRoleBinding); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("[apiconfig] Created kube-proxy RBAC rules")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -34,7 +34,6 @@ func newCertificateAuthority() (*rsa.PrivateKey, *x509.Certificate, error) {
|
|||||||
config := certutil.Config{
|
config := certutil.Config{
|
||||||
CommonName: "kubernetes",
|
CommonName: "kubernetes",
|
||||||
}
|
}
|
||||||
|
|
||||||
cert, err := certutil.NewSelfSignedCACert(config, key)
|
cert, err := certutil.NewSelfSignedCACert(config, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to create self-signed certificate [%v]", err)
|
return nil, nil, fmt.Errorf("unable to create self-signed certificate [%v]", err)
|
||||||
@ -61,16 +60,13 @@ func newServerKeyAndCert(caCert *x509.Certificate, caKey *rsa.PrivateKey, altNam
|
|||||||
return key, cert, nil
|
return key, cert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientKeyAndCert(caCert *x509.Certificate, caKey *rsa.PrivateKey) (*rsa.PrivateKey, *x509.Certificate, error) {
|
func NewClientKeyAndCert(config *certutil.Config, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*rsa.PrivateKey, *x509.Certificate, error) {
|
||||||
key, err := certutil.NewPrivateKey()
|
key, err := certutil.NewPrivateKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to create private key [%v]", err)
|
return nil, nil, fmt.Errorf("unable to create private key [%v]", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config := certutil.Config{
|
cert, err := certutil.NewSignedCert(*config, key, caCert, caKey)
|
||||||
CommonName: "kubernetes-client",
|
|
||||||
}
|
|
||||||
cert, err := certutil.NewSignedCert(config, key, caCert, caKey)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to sign certificate [%v]", err)
|
return nil, nil, fmt.Errorf("unable to sign certificate [%v]", err)
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,11 @@ func TestNewClientKeyAndCert(t *testing.T) {
|
|||||||
t.Fatalf("Couldn't create rsa Private Key")
|
t.Fatalf("Couldn't create rsa Private Key")
|
||||||
}
|
}
|
||||||
caCert := &x509.Certificate{}
|
caCert := &x509.Certificate{}
|
||||||
_, _, actual := NewClientKeyAndCert(caCert, caKey)
|
config := &certutil.Config{
|
||||||
|
CommonName: "test",
|
||||||
|
Organization: []string{"test"},
|
||||||
|
}
|
||||||
|
_, _, actual := NewClientKeyAndCert(config, caCert, caKey)
|
||||||
if (actual == nil) != rt.expected {
|
if (actual == nil) != rt.expected {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"failed NewClientKeyAndCert:\n\texpected: %t\n\t actual: %t",
|
"failed NewClientKeyAndCert:\n\texpected: %t\n\t actual: %t",
|
||||||
|
@ -31,9 +31,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
KubernetesDirPermissions = 0700
|
KubernetesDirPermissions = 0700
|
||||||
AdminKubeConfigFileName = "admin.conf"
|
AdminKubeConfigFileName = "admin.conf"
|
||||||
KubeletKubeConfigFileName = "kubelet.conf"
|
AdminKubeConfigClientName = "kubernetes-admin"
|
||||||
|
KubeletKubeConfigFileName = "kubelet.conf"
|
||||||
|
KubeletKubeConfigClientName = "kubelet"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This function is called from the main init and does the work for the default phase behaviour
|
// This function is called from the main init and does the work for the default phase behaviour
|
||||||
@ -68,36 +70,47 @@ func CreateAdminAndKubeletKubeConfig(masterEndpoint, pkiDir, outDir string) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// User admin should have full access to the cluster
|
// User admin should have full access to the cluster
|
||||||
if err := createKubeConfigFileForClient(masterEndpoint, "admin", outDir, caCert, caKey); err != nil {
|
adminCertConfig := &certutil.Config{
|
||||||
return fmt.Errorf("couldn't create a kubeconfig file for admin: %v", err)
|
CommonName: AdminKubeConfigClientName,
|
||||||
|
Organization: []string{"system:masters"},
|
||||||
|
}
|
||||||
|
adminKubeConfigFilePath := path.Join(outDir, AdminKubeConfigFileName)
|
||||||
|
if err := createKubeConfigFileForClient(masterEndpoint, adminKubeConfigFilePath, adminCertConfig, caCert, caKey); err != nil {
|
||||||
|
return fmt.Errorf("couldn't create config for %s: %v", AdminKubeConfigClientName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: The kubelet should have limited access to the cluster
|
// The kubelet should have limited access to the cluster
|
||||||
if err := createKubeConfigFileForClient(masterEndpoint, "kubelet", outDir, caCert, caKey); err != nil {
|
kubeletCertConfig := &certutil.Config{
|
||||||
return fmt.Errorf("couldn't create a kubeconfig file for kubelet: %v", err)
|
CommonName: KubeletKubeConfigClientName,
|
||||||
|
Organization: []string{"system:nodes"},
|
||||||
}
|
}
|
||||||
|
kubeletKubeConfigFilePath := path.Join(outDir, KubeletKubeConfigFileName)
|
||||||
|
if err := createKubeConfigFileForClient(masterEndpoint, kubeletKubeConfigFilePath, kubeletCertConfig, caCert, caKey); err != nil {
|
||||||
|
return fmt.Errorf("couldn't create config for %s: %v", KubeletKubeConfigClientName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO make credentials for the controller manager and kube proxy
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createKubeConfigFileForClient(masterEndpoint, client, outDir string, caCert *x509.Certificate, caKey *rsa.PrivateKey) error {
|
func createKubeConfigFileForClient(masterEndpoint, kubeConfigFilePath string, config *certutil.Config, caCert *x509.Certificate, caKey *rsa.PrivateKey) error {
|
||||||
key, cert, err := certphase.NewClientKeyAndCert(caCert, caKey)
|
key, cert, err := certphase.NewClientKeyAndCert(config, caCert, caKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failure while creating %s client certificate [%v]", client, err)
|
return fmt.Errorf("failure while creating %s client certificate [%v]", config.CommonName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config := MakeClientConfigWithCerts(
|
kubeConfig := MakeClientConfigWithCerts(
|
||||||
masterEndpoint,
|
masterEndpoint,
|
||||||
"kubernetes",
|
"kubernetes",
|
||||||
client,
|
config.CommonName,
|
||||||
certutil.EncodeCertPEM(caCert),
|
certutil.EncodeCertPEM(caCert),
|
||||||
certutil.EncodePrivateKeyPEM(key),
|
certutil.EncodePrivateKeyPEM(key),
|
||||||
certutil.EncodeCertPEM(cert),
|
certutil.EncodeCertPEM(cert),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Write it now to a file
|
// Write it now to a file
|
||||||
filepath := path.Join(outDir, fmt.Sprintf("%s.conf", client))
|
return WriteKubeconfigToDisk(kubeConfigFilePath, kubeConfig)
|
||||||
return WriteKubeconfigToDisk(filepath, config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteKubeconfigToDisk(filepath string, kubeconfig *clientcmdapi.Config) error {
|
func WriteKubeconfigToDisk(filepath string, kubeconfig *clientcmdapi.Config) error {
|
||||||
|
@ -14,6 +14,7 @@ go_library(
|
|||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||||
|
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
||||||
"//pkg/api/validation:go_default_library",
|
"//pkg/api/validation:go_default_library",
|
||||||
"//pkg/util/initsystem:go_default_library",
|
"//pkg/util/initsystem:go_default_library",
|
||||||
"//pkg/util/node:go_default_library",
|
"//pkg/util/node:go_default_library",
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
|
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||||
"k8s.io/kubernetes/pkg/api/validation"
|
"k8s.io/kubernetes/pkg/api/validation"
|
||||||
"k8s.io/kubernetes/pkg/util/initsystem"
|
"k8s.io/kubernetes/pkg/util/initsystem"
|
||||||
"k8s.io/kubernetes/pkg/util/node"
|
"k8s.io/kubernetes/pkg/util/node"
|
||||||
@ -320,8 +321,8 @@ func RunInitMasterChecks(cfg *kubeadmapi.MasterConfiguration) error {
|
|||||||
DirAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests")},
|
DirAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests")},
|
||||||
DirAvailableCheck{Path: kubeadmapi.GlobalEnvParams.HostPKIPath},
|
DirAvailableCheck{Path: kubeadmapi.GlobalEnvParams.HostPKIPath},
|
||||||
DirAvailableCheck{Path: "/var/lib/kubelet"},
|
DirAvailableCheck{Path: "/var/lib/kubelet"},
|
||||||
FileAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "admin.conf")},
|
FileAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfig.AdminKubeConfigFileName)},
|
||||||
FileAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "kubelet.conf")},
|
FileAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfig.KubeletKubeConfigFileName)},
|
||||||
FileContentCheck{Path: bridgenf, Content: []byte{'1'}},
|
FileContentCheck{Path: bridgenf, Content: []byte{'1'}},
|
||||||
InPathCheck{executable: "ip", mandatory: true},
|
InPathCheck{executable: "ip", mandatory: true},
|
||||||
InPathCheck{executable: "iptables", mandatory: true},
|
InPathCheck{executable: "iptables", mandatory: true},
|
||||||
@ -355,7 +356,7 @@ func RunJoinNodeChecks(cfg *kubeadmapi.NodeConfiguration) error {
|
|||||||
PortOpenCheck{port: 10250},
|
PortOpenCheck{port: 10250},
|
||||||
DirAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests")},
|
DirAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests")},
|
||||||
DirAvailableCheck{Path: "/var/lib/kubelet"},
|
DirAvailableCheck{Path: "/var/lib/kubelet"},
|
||||||
FileAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "kubelet.conf")},
|
FileAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfig.KubeletKubeConfigFileName)},
|
||||||
FileContentCheck{Path: bridgenf, Content: []byte{'1'}},
|
FileContentCheck{Path: bridgenf, Content: []byte{'1'}},
|
||||||
InPathCheck{executable: "ip", mandatory: true},
|
InPathCheck{executable: "ip", mandatory: true},
|
||||||
InPathCheck{executable: "iptables", mandatory: true},
|
InPathCheck{executable: "iptables", mandatory: true},
|
||||||
|
@ -27,6 +27,7 @@ cmd/kube-proxy
|
|||||||
cmd/kubeadm
|
cmd/kubeadm
|
||||||
cmd/kubeadm
|
cmd/kubeadm
|
||||||
cmd/kubeadm/app/apis/kubeadm/install
|
cmd/kubeadm/app/apis/kubeadm/install
|
||||||
|
cmd/kubeadm/app/phases/apiconfig
|
||||||
cmd/kubectl
|
cmd/kubectl
|
||||||
cmd/kubelet
|
cmd/kubelet
|
||||||
cmd/libs/go2idl/client-gen
|
cmd/libs/go2idl/client-gen
|
||||||
|
@ -562,6 +562,7 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
|
|||||||
obj.API.Port = 20
|
obj.API.Port = 20
|
||||||
obj.Networking.ServiceSubnet = "foo"
|
obj.Networking.ServiceSubnet = "foo"
|
||||||
obj.Networking.DNSDomain = "foo"
|
obj.Networking.DNSDomain = "foo"
|
||||||
|
obj.AuthorizationMode = "foo"
|
||||||
obj.Discovery.Token = &kubeadm.TokenDiscovery{}
|
obj.Discovery.Token = &kubeadm.TokenDiscovery{}
|
||||||
},
|
},
|
||||||
func(s *policy.PodDisruptionBudgetStatus, c fuzz.Continue) {
|
func(s *policy.PodDisruptionBudgetStatus, c fuzz.Continue) {
|
||||||
|
@ -90,7 +90,7 @@ func NewSignedCert(cfg Config, key *rsa.PrivateKey, caCert *x509.Certificate, ca
|
|||||||
certTmpl := x509.Certificate{
|
certTmpl := x509.Certificate{
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
CommonName: cfg.CommonName,
|
CommonName: cfg.CommonName,
|
||||||
Organization: caCert.Subject.Organization,
|
Organization: cfg.Organization,
|
||||||
},
|
},
|
||||||
DNSNames: cfg.AltNames.DNSNames,
|
DNSNames: cfg.AltNames.DNSNames,
|
||||||
IPAddresses: cfg.AltNames.IPs,
|
IPAddresses: cfg.AltNames.IPs,
|
||||||
|
Loading…
Reference in New Issue
Block a user