Unverified Commit c79743d4 authored by Erik Wilson's avatar Erik Wilson Committed by GitHub

Merge pull request #1013 from erikwilson/node-cleanup

Node password cleanup
parents c736888e 55c05ac5
...@@ -82,7 +82,7 @@ func getNodeNamedCrt(nodeName, nodePasswordFile string) HTTPRequester { ...@@ -82,7 +82,7 @@ func getNodeNamedCrt(nodeName, nodePasswordFile string) HTTPRequester {
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode == http.StatusForbidden { if resp.StatusCode == http.StatusForbidden {
return nil, fmt.Errorf("Node password rejected, contents of '%s' may not match server passwd entry", nodePasswordFile) return nil, fmt.Errorf("Node password rejected, duplicate hostname or contents of '%s' may not match server node-passwd entry, try enabling a unique node name with the --with-node-id flag", nodePasswordFile)
} }
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
...@@ -93,6 +93,20 @@ func getNodeNamedCrt(nodeName, nodePasswordFile string) HTTPRequester { ...@@ -93,6 +93,20 @@ func getNodeNamedCrt(nodeName, nodePasswordFile string) HTTPRequester {
} }
} }
func ensureNodeID(nodeIDFile string) (string, error) {
if _, err := os.Stat(nodeIDFile); err == nil {
id, err := ioutil.ReadFile(nodeIDFile)
return strings.TrimSpace(string(id)), err
}
id := make([]byte, 4, 4)
_, err := cryptorand.Read(id)
if err != nil {
return "", err
}
nodeID := hex.EncodeToString(id)
return nodeID, ioutil.WriteFile(nodeIDFile, []byte(nodeID+"\n"), 0644)
}
func ensureNodePassword(nodePasswordFile string) (string, error) { func ensureNodePassword(nodePasswordFile string) (string, error) {
if _, err := os.Stat(nodePasswordFile); err == nil { if _, err := os.Stat(nodePasswordFile); err == nil {
password, err := ioutil.ReadFile(nodePasswordFile) password, err := ioutil.ReadFile(nodePasswordFile)
...@@ -107,6 +121,21 @@ func ensureNodePassword(nodePasswordFile string) (string, error) { ...@@ -107,6 +121,21 @@ func ensureNodePassword(nodePasswordFile string) (string, error) {
return nodePassword, ioutil.WriteFile(nodePasswordFile, []byte(nodePassword+"\n"), 0600) return nodePassword, ioutil.WriteFile(nodePasswordFile, []byte(nodePassword+"\n"), 0600)
} }
func upgradeOldNodePasswordPath(oldNodePasswordFile, newNodePasswordFile string) {
password, err := ioutil.ReadFile(oldNodePasswordFile)
if err != nil {
return
}
if err := ioutil.WriteFile(newNodePasswordFile, password, 0600); err != nil {
logrus.Warnf("Unable to write password file: %v", err)
return
}
if err := os.Remove(oldNodePasswordFile); err != nil {
logrus.Warnf("Unable to remove old password file: %v", err)
return
}
}
func getServingCert(nodeName, servingCertFile, servingKeyFile, nodePasswordFile string, info *clientaccess.Info) (*tls.Certificate, error) { func getServingCert(nodeName, servingCertFile, servingKeyFile, nodePasswordFile string, info *clientaccess.Info) (*tls.Certificate, error) {
servingCert, err := Request("/v1-k3s/serving-kubelet.crt", info, getNodeNamedCrt(nodeName, nodePasswordFile)) servingCert, err := Request("/v1-k3s/serving-kubelet.crt", info, getNodeNamedCrt(nodeName, nodePasswordFile))
if err != nil { if err != nil {
...@@ -244,11 +273,6 @@ func get(envInfo *cmds.Agent) (*config.Node, error) { ...@@ -244,11 +273,6 @@ func get(envInfo *cmds.Agent) (*config.Node, error) {
return nil, err return nil, err
} }
nodeName, nodeIP, err := getHostnameAndIP(*envInfo)
if err != nil {
return nil, err
}
hostLocal, err := exec.LookPath("host-local") hostLocal, err := exec.LookPath("host-local")
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to find host-local") return nil, errors.Wrapf(err, "failed to find host-local")
...@@ -274,14 +298,40 @@ func get(envInfo *cmds.Agent) (*config.Node, error) { ...@@ -274,14 +298,40 @@ func get(envInfo *cmds.Agent) (*config.Node, error) {
servingKubeletCert := filepath.Join(envInfo.DataDir, "serving-kubelet.crt") servingKubeletCert := filepath.Join(envInfo.DataDir, "serving-kubelet.crt")
servingKubeletKey := filepath.Join(envInfo.DataDir, "serving-kubelet.key") servingKubeletKey := filepath.Join(envInfo.DataDir, "serving-kubelet.key")
nodePasswordFile := filepath.Join(envInfo.DataDir, "node-password.txt")
servingCert, err := getServingCert(nodeName, servingKubeletCert, servingKubeletKey, nodePasswordFile, info) nodePasswordRoot := "/"
if envInfo.Rootless {
nodePasswordRoot = envInfo.DataDir
}
nodeConfigPath := filepath.Join(nodePasswordRoot, "etc", "rancher", "node")
if err := os.MkdirAll(nodeConfigPath, 0755); err != nil {
return nil, err
}
oldNodePasswordFile := filepath.Join(envInfo.DataDir, "node-password.txt")
newNodePasswordFile := filepath.Join(nodeConfigPath, "password")
upgradeOldNodePasswordPath(oldNodePasswordFile, newNodePasswordFile)
nodeName, nodeIP, err := getHostnameAndIP(*envInfo)
if err != nil {
return nil, err
}
if envInfo.WithNodeID {
nodeID, err := ensureNodeID(filepath.Join(nodeConfigPath, "id"))
if err != nil {
return nil, err
}
nodeName += "-" + nodeID
}
servingCert, err := getServingCert(nodeName, servingKubeletCert, servingKubeletKey, newNodePasswordFile, info)
if err != nil { if err != nil {
return nil, err return nil, err
} }
clientKubeletCert := filepath.Join(envInfo.DataDir, "client-kubelet.crt") clientKubeletCert := filepath.Join(envInfo.DataDir, "client-kubelet.crt")
if err := getNodeNamedHostFile(clientKubeletCert, nodeName, nodePasswordFile, info); err != nil { if err := getNodeNamedHostFile(clientKubeletCert, nodeName, newNodePasswordFile, info); err != nil {
return nil, err return nil, err
} }
...@@ -334,6 +384,7 @@ func get(envInfo *cmds.Agent) (*config.Node, error) { ...@@ -334,6 +384,7 @@ func get(envInfo *cmds.Agent) (*config.Node, error) {
nodeConfig.Images = filepath.Join(envInfo.DataDir, "images") nodeConfig.Images = filepath.Join(envInfo.DataDir, "images")
nodeConfig.AgentConfig.NodeIP = nodeIP nodeConfig.AgentConfig.NodeIP = nodeIP
nodeConfig.AgentConfig.NodeName = nodeName nodeConfig.AgentConfig.NodeName = nodeName
nodeConfig.AgentConfig.NodeConfigPath = nodeConfigPath
nodeConfig.AgentConfig.NodeExternalIP = envInfo.NodeExternalIP nodeConfig.AgentConfig.NodeExternalIP = envInfo.NodeExternalIP
nodeConfig.AgentConfig.ServingKubeletCert = servingKubeletCert nodeConfig.AgentConfig.ServingKubeletCert = servingKubeletCert
nodeConfig.AgentConfig.ServingKubeletKey = servingKubeletKey nodeConfig.AgentConfig.ServingKubeletKey = servingKubeletKey
......
...@@ -26,6 +26,7 @@ type Agent struct { ...@@ -26,6 +26,7 @@ type Agent struct {
Debug bool Debug bool
Rootless bool Rootless bool
RootlessAlreadyUnshared bool RootlessAlreadyUnshared bool
WithNodeID bool
AgentShared AgentShared
ExtraKubeletArgs cli.StringSlice ExtraKubeletArgs cli.StringSlice
ExtraKubeProxyArgs cli.StringSlice ExtraKubeProxyArgs cli.StringSlice
...@@ -57,6 +58,11 @@ var ( ...@@ -57,6 +58,11 @@ var (
EnvVar: "K3S_NODE_NAME", EnvVar: "K3S_NODE_NAME",
Destination: &AgentConfig.NodeName, Destination: &AgentConfig.NodeName,
} }
WithNodeIDFlag = cli.BoolFlag{
Name: "with-node-id",
Usage: "(agent/node) Append id to node name",
Destination: &AgentConfig.WithNodeID,
}
DockerFlag = cli.BoolFlag{ DockerFlag = cli.BoolFlag{
Name: "docker", Name: "docker",
Usage: "(agent/runtime) Use docker instead of containerd", Usage: "(agent/runtime) Use docker instead of containerd",
......
...@@ -210,6 +210,7 @@ func NewServerCommand(action func(*cli.Context) error) cli.Command { ...@@ -210,6 +210,7 @@ func NewServerCommand(action func(*cli.Context) error) cli.Command {
Destination: &ServerConfig.DisableNPC, Destination: &ServerConfig.DisableNPC,
}, },
NodeNameFlag, NodeNameFlag,
WithNodeIDFlag,
NodeLabels, NodeLabels,
NodeTaints, NodeTaints,
DockerFlag, DockerFlag,
......
...@@ -14,8 +14,8 @@ import ( ...@@ -14,8 +14,8 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/net"
"k8s.io/component-base/logs" "k8s.io/component-base/logs"
app2 "k8s.io/kubernetes/cmd/kube-proxy/app" proxy "k8s.io/kubernetes/cmd/kube-proxy/app"
"k8s.io/kubernetes/cmd/kubelet/app" kubelet "k8s.io/kubernetes/cmd/kubelet/app"
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration _ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
...@@ -25,34 +25,37 @@ import ( ...@@ -25,34 +25,37 @@ import (
func Agent(config *config.Agent) error { func Agent(config *config.Agent) error {
rand.Seed(time.Now().UTC().UnixNano()) rand.Seed(time.Now().UTC().UnixNano())
kubelet(config) logs.InitLogs()
kubeProxy(config) defer logs.FlushLogs()
startKubelet(config)
startKubeProxy(config)
return nil return nil
} }
func kubeProxy(cfg *config.Agent) { func startKubeProxy(cfg *config.Agent) {
argsMap := map[string]string{ argsMap := map[string]string{
"proxy-mode": "iptables", "proxy-mode": "iptables",
"healthz-bind-address": "127.0.0.1", "healthz-bind-address": "127.0.0.1",
"kubeconfig": cfg.KubeConfigKubeProxy, "kubeconfig": cfg.KubeConfigKubeProxy,
"cluster-cidr": cfg.ClusterCIDR.String(), "cluster-cidr": cfg.ClusterCIDR.String(),
} }
args := config.GetArgsList(argsMap, cfg.ExtraKubeProxyArgs) if cfg.NodeName != "" {
argsMap["hostname-override"] = cfg.NodeName
}
command := app2.NewProxyCommand() args := config.GetArgsList(argsMap, cfg.ExtraKubeProxyArgs)
command := proxy.NewProxyCommand()
command.SetArgs(args) command.SetArgs(args)
go func() { go func() {
err := command.Execute() logrus.Infof("Running kube-proxy %s", config.ArgString(args))
logrus.Fatalf("kube-proxy exited: %v", err) logrus.Fatalf("kube-proxy exited: %v", command.Execute())
}() }()
} }
func kubelet(cfg *config.Agent) { func startKubelet(cfg *config.Agent) {
command := app.NewKubeletCommand(context.Background().Done())
logs.InitLogs()
defer logs.FlushLogs()
argsMap := map[string]string{ argsMap := map[string]string{
"healthz-bind-address": "127.0.0.1", "healthz-bind-address": "127.0.0.1",
"read-only-port": "0", "read-only-port": "0",
...@@ -146,6 +149,7 @@ func kubelet(cfg *config.Agent) { ...@@ -146,6 +149,7 @@ func kubelet(cfg *config.Agent) {
} }
args := config.GetArgsList(argsMap, cfg.ExtraKubeletArgs) args := config.GetArgsList(argsMap, cfg.ExtraKubeletArgs)
command := kubelet.NewKubeletCommand(context.Background().Done())
command.SetArgs(args) command.SetArgs(args)
go func() { go func() {
......
...@@ -48,6 +48,7 @@ type Containerd struct { ...@@ -48,6 +48,7 @@ type Containerd struct {
type Agent struct { type Agent struct {
NodeName string NodeName string
NodeConfigPath string
ServingKubeletCert string ServingKubeletCert string
ServingKubeletKey string ServingKubeletKey string
ClusterCIDR net.IPNet ClusterCIDR net.IPNet
......
...@@ -44,8 +44,8 @@ func Read(file string) (*Passwd, error) { ...@@ -44,8 +44,8 @@ func Read(file string) (*Passwd, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(record) < 3 { if len(record) < 2 {
return nil, fmt.Errorf("password file '%s' must have at least 3 columns (password, user name, user uid), found %d", file, len(record)) return nil, fmt.Errorf("password file '%s' must have at least 2 columns (password, name), found %d", file, len(record))
} }
e := entry{ e := entry{
pass: record[0], pass: record[0],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment