Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
6bbed9fe
Commit
6bbed9fe
authored
Jan 29, 2019
by
RA489
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kubeadm: graduate control plane join phase
parent
2de487c9
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
233 additions
and
95 deletions
+233
-95
BUILD
cmd/kubeadm/app/cmd/BUILD
+0
-2
join.go
cmd/kubeadm/app/cmd/join.go
+23
-92
BUILD
cmd/kubeadm/app/cmd/phases/join/BUILD
+4
-1
controlplanejoin.go
cmd/kubeadm/app/cmd/phases/join/controlplanejoin.go
+206
-0
controlplaneprepare.go
cmd/kubeadm/app/cmd/phases/join/controlplaneprepare.go
+0
-0
No files found.
cmd/kubeadm/app/cmd/BUILD
View file @
6bbed9fe
...
@@ -40,9 +40,7 @@ go_library(
...
@@ -40,9 +40,7 @@ go_library(
"//cmd/kubeadm/app/images:go_default_library",
"//cmd/kubeadm/app/images:go_default_library",
"//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library",
"//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library",
"//cmd/kubeadm/app/phases/certs:go_default_library",
"//cmd/kubeadm/app/phases/certs:go_default_library",
"//cmd/kubeadm/app/phases/etcd:go_default_library",
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
"//cmd/kubeadm/app/phases/markcontrolplane:go_default_library",
"//cmd/kubeadm/app/phases/uploadconfig:go_default_library",
"//cmd/kubeadm/app/phases/uploadconfig:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
"//cmd/kubeadm/app/util:go_default_library",
"//cmd/kubeadm/app/util:go_default_library",
...
...
cmd/kubeadm/app/cmd/join.go
View file @
6bbed9fe
...
@@ -20,7 +20,6 @@ import (
...
@@ -20,7 +20,6 @@ import (
"fmt"
"fmt"
"io"
"io"
"os"
"os"
"path/filepath"
"text/template"
"text/template"
"github.com/lithammer/dedent"
"github.com/lithammer/dedent"
...
@@ -41,9 +40,6 @@ import (
...
@@ -41,9 +40,6 @@ import (
cmdutil
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
cmdutil
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeadmconstants
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/discovery"
"k8s.io/kubernetes/cmd/kubeadm/app/discovery"
etcdphase
"k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
markcontrolplanephase
"k8s.io/kubernetes/cmd/kubeadm/app/phases/markcontrolplane"
uploadconfigphase
"k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
kubeadmutil
"k8s.io/kubernetes/cmd/kubeadm/app/util"
kubeadmutil
"k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil
"k8s.io/kubernetes/cmd/kubeadm/app/util/config"
configutil
"k8s.io/kubernetes/cmd/kubeadm/app/util/config"
kubeconfigutil
"k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
kubeconfigutil
"k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
...
@@ -137,6 +133,7 @@ type joinOptions struct {
...
@@ -137,6 +133,7 @@ type joinOptions struct {
// this data is shared across all the phases that are included in the workflow.
// this data is shared across all the phases that are included in the workflow.
type
joinData
struct
{
type
joinData
struct
{
cfg
*
kubeadmapi
.
JoinConfiguration
cfg
*
kubeadmapi
.
JoinConfiguration
skipTokenPrint
bool
initCfg
*
kubeadmapi
.
InitConfiguration
initCfg
*
kubeadmapi
.
InitConfiguration
tlsBootstrapCfg
*
clientcmdapi
.
Config
tlsBootstrapCfg
*
clientcmdapi
.
Config
clientSets
map
[
string
]
*
clientset
.
Clientset
clientSets
map
[
string
]
*
clientset
.
Clientset
...
@@ -162,14 +159,30 @@ func NewCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command {
...
@@ -162,14 +159,30 @@ func NewCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command {
c
,
err
:=
joinRunner
.
InitData
(
args
)
c
,
err
:=
joinRunner
.
InitData
(
args
)
kubeadmutil
.
CheckErr
(
err
)
kubeadmutil
.
CheckErr
(
err
)
data
:=
c
.
(
*
joinData
)
err
=
joinRunner
.
Run
(
args
)
err
=
joinRunner
.
Run
(
args
)
kubeadmutil
.
CheckErr
(
err
)
kubeadmutil
.
CheckErr
(
err
)
// TODO: remove this once we have all phases in place.
// if the node is hosting a new control plane instance
// the method joinData.Run() itself should be removed too.
if
data
.
cfg
.
ControlPlane
!=
nil
{
data
:=
c
.
(
*
joinData
)
// outputs the join control plane done message and exit
err
=
data
.
Run
()
etcdMessage
:=
""
kubeadmutil
.
CheckErr
(
err
)
if
data
.
initCfg
.
Etcd
.
External
==
nil
{
etcdMessage
=
"* A new etcd member was added to the local/stacked etcd cluster."
}
ctx
:=
map
[
string
]
string
{
"KubeConfigPath"
:
kubeadmconstants
.
GetAdminKubeConfigPath
(),
"etcdMessage"
:
etcdMessage
,
}
joinControPlaneDoneTemp
.
Execute
(
data
.
outputWriter
,
ctx
)
}
else
{
// otherwise, if the node joined as a worker node;
// outputs the join done message and exit
fmt
.
Fprintf
(
data
.
outputWriter
,
joinWorkerNodeDoneMsg
)
}
},
},
// We accept the control-plane location as an optional positional argument
// We accept the control-plane location as an optional positional argument
Args
:
cobra
.
MaximumNArgs
(
1
),
Args
:
cobra
.
MaximumNArgs
(
1
),
...
@@ -182,6 +195,7 @@ func NewCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command {
...
@@ -182,6 +195,7 @@ func NewCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command {
joinRunner
.
AppendPhase
(
phases
.
NewControlPlanePreparePhase
())
joinRunner
.
AppendPhase
(
phases
.
NewControlPlanePreparePhase
())
joinRunner
.
AppendPhase
(
phases
.
NewCheckEtcdPhase
())
joinRunner
.
AppendPhase
(
phases
.
NewCheckEtcdPhase
())
joinRunner
.
AppendPhase
(
phases
.
NewKubeletStartPhase
())
joinRunner
.
AppendPhase
(
phases
.
NewKubeletStartPhase
())
joinRunner
.
AppendPhase
(
phases
.
NewControlPlaneJoinPhase
())
// sets the data builder function, that will be used by the runner
// sets the data builder function, that will be used by the runner
// both when running the entire workflow or single phases
// both when running the entire workflow or single phases
...
@@ -413,89 +427,6 @@ func (j *joinData) OutputWriter() io.Writer {
...
@@ -413,89 +427,6 @@ func (j *joinData) OutputWriter() io.Writer {
return
j
.
outputWriter
return
j
.
outputWriter
}
}
// Run executes worker node provisioning and tries to join an existing cluster.
func
(
j
*
joinData
)
Run
()
error
{
// Fetch the init configuration based on the join configuration.
// TODO: individual phases should call these:
// - phases that need initCfg should call joinData.InitCfg().
// - phases that need tlsBootstrapCfg should call joinData.TLSBootstrapCfg().
initCfg
,
err
:=
j
.
InitCfg
()
if
err
!=
nil
{
return
err
}
// if the node is hosting a new control plane instance
if
j
.
cfg
.
ControlPlane
!=
nil
{
// Completes the control plane setup
if
err
:=
j
.
PostInstallControlPlane
(
initCfg
);
err
!=
nil
{
return
err
}
// outputs the join control plane done template and exits
etcdMessage
:=
""
// in case of local etcd
if
initCfg
.
Etcd
.
External
==
nil
{
etcdMessage
=
"* A new etcd member was added to the local/stacked etcd cluster."
}
ctx
:=
map
[
string
]
string
{
"KubeConfigPath"
:
kubeadmconstants
.
GetAdminKubeConfigPath
(),
"etcdMessage"
:
etcdMessage
,
}
joinControPlaneDoneTemp
.
Execute
(
j
.
outputWriter
,
ctx
)
return
nil
}
// otherwise, if the node joined as a worker node;
// outputs the join done message and exits
fmt
.
Fprintf
(
j
.
outputWriter
,
joinWorkerNodeDoneMsg
)
return
nil
}
// PostInstallControlPlane marks the new node as control-plane and update the cluster status with information about current node
func
(
j
*
joinData
)
PostInstallControlPlane
(
initConfiguration
*
kubeadmapi
.
InitConfiguration
)
error
{
kubeConfigFile
:=
filepath
.
Join
(
kubeadmconstants
.
KubernetesDir
,
kubeadmconstants
.
AdminKubeConfigFileName
)
client
,
err
:=
kubeconfigutil
.
ClientSetFromFile
(
kubeConfigFile
)
if
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"couldn't create Kubernetes client"
)
}
// in case of local etcd
if
initConfiguration
.
Etcd
.
External
==
nil
{
// creates target folder if doesn't exist already
if
err
:=
os
.
MkdirAll
(
initConfiguration
.
Etcd
.
Local
.
DataDir
,
0700
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"failed to create etcd directory %q"
,
initConfiguration
.
Etcd
.
Local
.
DataDir
)
}
// Adds a new etcd instance; in order to do this the new etcd instance should be "announced" to
// the existing etcd members before being created.
// This operation must be executed after kubelet is already started in order to minimize the time
// between the new etcd member is announced and the start of the static pod running the new etcd member, because during
// this time frame etcd gets temporary not available (only when moving from 1 to 2 members in the etcd cluster).
// From https://coreos.com/etcd/docs/latest/v2/runtime-configuration.html
// "If you add a new member to a 1-node cluster, the cluster cannot make progress before the new member starts
// because it needs two members as majority to agree on the consensus. You will only see this behavior between the time
// etcdctl member add informs the cluster about the new member and the new member successfully establishing a connection to the existing one."
klog
.
V
(
1
)
.
Info
(
"[join] adding etcd"
)
if
err
:=
etcdphase
.
CreateStackedEtcdStaticPodManifestFile
(
client
,
kubeadmconstants
.
GetStaticPodDirectory
(),
initConfiguration
.
NodeRegistration
.
Name
,
&
initConfiguration
.
ClusterConfiguration
,
&
initConfiguration
.
LocalAPIEndpoint
);
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"error creating local etcd static pod manifest file"
)
}
}
klog
.
V
(
1
)
.
Info
(
"[join] uploading currently used configuration to the cluster"
)
if
err
:=
uploadconfigphase
.
UploadConfiguration
(
initConfiguration
,
client
);
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"error uploading configuration"
)
}
klog
.
V
(
1
)
.
Info
(
"[join] marking the control-plane with right label"
)
if
err
=
markcontrolplanephase
.
MarkControlPlane
(
client
,
initConfiguration
.
NodeRegistration
.
Name
,
initConfiguration
.
NodeRegistration
.
Taints
);
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"error applying control-plane label and taints"
)
}
return
nil
}
// fetchInitConfigurationFromJoinConfiguration retrieves the init configuration from a join configuration, performing the discovery
// fetchInitConfigurationFromJoinConfiguration retrieves the init configuration from a join configuration, performing the discovery
func
fetchInitConfigurationFromJoinConfiguration
(
cfg
*
kubeadmapi
.
JoinConfiguration
,
tlsBootstrapCfg
*
clientcmdapi
.
Config
)
(
*
kubeadmapi
.
InitConfiguration
,
error
)
{
func
fetchInitConfigurationFromJoinConfiguration
(
cfg
*
kubeadmapi
.
JoinConfiguration
,
tlsBootstrapCfg
*
clientcmdapi
.
Config
)
(
*
kubeadmapi
.
InitConfiguration
,
error
)
{
// Retrieves the kubeadm configuration
// Retrieves the kubeadm configuration
...
...
cmd/kubeadm/app/cmd/phases/join/BUILD
View file @
6bbed9fe
...
@@ -4,7 +4,8 @@ go_library(
...
@@ -4,7 +4,8 @@ go_library(
name = "go_default_library",
name = "go_default_library",
srcs = [
srcs = [
"checketcd.go",
"checketcd.go",
"controlplane.go",
"controlplanejoin.go",
"controlplaneprepare.go",
"kubelet.go",
"kubelet.go",
"preflight.go",
"preflight.go",
],
],
...
@@ -21,7 +22,9 @@ go_library(
...
@@ -21,7 +22,9 @@ go_library(
"//cmd/kubeadm/app/phases/etcd:go_default_library",
"//cmd/kubeadm/app/phases/etcd:go_default_library",
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
"//cmd/kubeadm/app/phases/kubelet:go_default_library",
"//cmd/kubeadm/app/phases/kubelet:go_default_library",
"//cmd/kubeadm/app/phases/markcontrolplane:go_default_library",
"//cmd/kubeadm/app/phases/patchnode:go_default_library",
"//cmd/kubeadm/app/phases/patchnode:go_default_library",
"//cmd/kubeadm/app/phases/uploadconfig:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
"//cmd/kubeadm/app/util/apiclient:go_default_library",
"//cmd/kubeadm/app/util/apiclient:go_default_library",
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
...
...
cmd/kubeadm/app/cmd/phases/join/controlplanejoin.go
0 → 100644
View file @
6bbed9fe
/*
Copyright 2019 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
phases
import
(
"fmt"
"github.com/pkg/errors"
clientset
"k8s.io/client-go/kubernetes"
kubeadmapi
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
etcdphase
"k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
markcontrolplanephase
"k8s.io/kubernetes/cmd/kubeadm/app/phases/markcontrolplane"
uploadconfigphase
"k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var
(
controlPlaneJoinExample
=
normalizer
.
Examples
(
`
# Joins a machine as a control plane instance
kubeadm join phase control-plane-join all
`
)
)
type
controlPlaneJoinData
interface
{
Cfg
()
*
kubeadmapi
.
JoinConfiguration
ClientSetFromFile
(
string
)
(
*
clientset
.
Clientset
,
error
)
InitCfg
()
(
*
kubeadmapi
.
InitConfiguration
,
error
)
KubeConfigPath
()
string
}
func
getControlPlaneJoinPhaseFlags
()
[]
string
{
return
[]
string
{
options
.
APIServerAdvertiseAddress
,
options
.
APIServerBindPort
,
options
.
CfgPath
,
options
.
ControlPlane
,
options
.
NodeName
,
options
.
TokenDiscovery
,
options
.
TokenDiscoveryCAHash
,
options
.
TokenDiscoverySkipCAHash
,
options
.
KubeconfigPath
,
}
}
// NewControlPlaneJoinPhase creates a kubeadm workflow phase that implements joining a machine as a control plane instance
func
NewControlPlaneJoinPhase
()
workflow
.
Phase
{
return
workflow
.
Phase
{
Name
:
"control-plane-join"
,
Short
:
"Joins a machine as a control plane instance"
,
Long
:
cmdutil
.
MacroCommandLongDescription
,
Phases
:
[]
workflow
.
Phase
{
{
Name
:
"all"
,
Short
:
"Joins a machine as a control plane instance"
,
InheritFlags
:
getControlPlaneJoinPhaseFlags
(),
RunAllSiblings
:
true
,
},
newEtcdLocalSubphase
(),
newUploadConfigSubphase
(),
newMarkControlPlaneSubphase
(),
},
}
}
func
newEtcdLocalSubphase
()
workflow
.
Phase
{
return
workflow
.
Phase
{
Name
:
"etcd"
,
Short
:
"Generates the static Pod manifest file for a local etcd member"
,
Run
:
runEtcdPhase
,
InheritFlags
:
getControlPlaneJoinPhaseFlags
(),
}
}
func
newUploadConfigSubphase
()
workflow
.
Phase
{
return
workflow
.
Phase
{
Name
:
"upload-config"
,
Short
:
"Upload the currently used configuration to the cluster"
,
Run
:
runUploadConfigPhase
,
InheritFlags
:
getControlPlaneJoinPhaseFlags
(),
}
}
func
newMarkControlPlaneSubphase
()
workflow
.
Phase
{
return
workflow
.
Phase
{
Name
:
"mark-control-plane"
,
Short
:
"Mark a node as a control-plane"
,
Run
:
runMarkControlPlanePhase
,
InheritFlags
:
getControlPlaneJoinPhaseFlags
(),
}
}
func
runEtcdPhase
(
c
workflow
.
RunData
)
error
{
data
,
ok
:=
c
.
(
controlPlaneJoinData
)
if
!
ok
{
return
errors
.
New
(
"control-plane-join phase invoked with an invalid data struct"
)
}
if
data
.
Cfg
()
.
ControlPlane
==
nil
{
return
nil
}
kubeConfigFile
:=
data
.
KubeConfigPath
()
client
,
err
:=
data
.
ClientSetFromFile
(
kubeConfigFile
)
if
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"couldn't create Kubernetes client"
)
}
cfg
,
err
:=
data
.
InitCfg
()
if
err
!=
nil
{
return
err
}
// in case of local etcd
if
cfg
.
Etcd
.
External
!=
nil
{
fmt
.
Println
(
"[control-plane-join] using external etcd - no local stacked instance added"
)
return
nil
}
// Adds a new etcd instance; in order to do this the new etcd instance should be "announced" to
// the existing etcd members before being created.
// This operation must be executed after kubelet is already started in order to minimize the time
// between the new etcd member is announced and the start of the static pod running the new etcd member, because during
// this time frame etcd gets temporary not available (only when moving from 1 to 2 members in the etcd cluster).
// From https://coreos.com/etcd/docs/latest/v2/runtime-configuration.html
// "If you add a new member to a 1-node cluster, the cluster cannot make progress before the new member starts
// because it needs two members as majority to agree on the consensus. You will only see this behavior between the time
// etcdctl member add informs the cluster about the new member and the new member successfully establishing a connection to the // existing one."
if
err
:=
etcdphase
.
CreateStackedEtcdStaticPodManifestFile
(
client
,
kubeadmconstants
.
GetStaticPodDirectory
(),
cfg
.
NodeRegistration
.
Name
,
&
cfg
.
ClusterConfiguration
,
&
cfg
.
LocalAPIEndpoint
);
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"error creating local etcd static pod manifest file"
)
}
return
nil
}
func
runUploadConfigPhase
(
c
workflow
.
RunData
)
error
{
data
,
ok
:=
c
.
(
controlPlaneJoinData
)
if
!
ok
{
return
errors
.
New
(
"control-plane-join phase invoked with an invalid data struct"
)
}
if
data
.
Cfg
()
.
ControlPlane
==
nil
{
return
nil
}
kubeConfigFile
:=
data
.
KubeConfigPath
()
client
,
err
:=
data
.
ClientSetFromFile
(
kubeConfigFile
)
if
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"couldn't create Kubernetes client"
)
}
cfg
,
err
:=
data
.
InitCfg
()
if
err
!=
nil
{
return
err
}
if
err
:=
uploadconfigphase
.
UploadConfiguration
(
cfg
,
client
);
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"error uploading configuration"
)
}
return
nil
}
func
runMarkControlPlanePhase
(
c
workflow
.
RunData
)
error
{
data
,
ok
:=
c
.
(
controlPlaneJoinData
)
if
!
ok
{
return
errors
.
New
(
"control-plane-join phase invoked with an invalid data struct"
)
}
if
data
.
Cfg
()
.
ControlPlane
==
nil
{
return
nil
}
kubeConfigFile
:=
data
.
KubeConfigPath
()
client
,
err
:=
data
.
ClientSetFromFile
(
kubeConfigFile
)
if
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"couldn't create Kubernetes client"
)
}
cfg
,
err
:=
data
.
InitCfg
()
if
err
!=
nil
{
return
err
}
if
err
:=
markcontrolplanephase
.
MarkControlPlane
(
client
,
cfg
.
NodeRegistration
.
Name
,
cfg
.
NodeRegistration
.
Taints
);
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"error applying control-plane label and taints"
)
}
return
nil
}
cmd/kubeadm/app/cmd/phases/join/controlplane.go
→
cmd/kubeadm/app/cmd/phases/join/controlplane
prepare
.go
View file @
6bbed9fe
File moved
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment