123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- /*
- Copyright 2018 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 kubelet
- import (
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
- "github.com/pkg/errors"
- "k8s.io/klog"
- kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
- "k8s.io/kubernetes/cmd/kubeadm/app/constants"
- "k8s.io/kubernetes/cmd/kubeadm/app/features"
- "k8s.io/kubernetes/cmd/kubeadm/app/images"
- kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
- "k8s.io/kubernetes/cmd/kubeadm/app/util/initsystem"
- utilsexec "k8s.io/utils/exec"
- )
- type kubeletFlagsOpts struct {
- nodeRegOpts *kubeadmapi.NodeRegistrationOptions
- featureGates map[string]bool
- pauseImage string
- registerTaintsUsingFlags bool
- execer utilsexec.Interface
- isServiceActiveFunc func(string) (bool, error)
- }
- // GetNodeNameAndHostname obtains the name for this Node using the following precedence
- // (from lower to higher):
- // - actual hostname
- // - NodeRegistrationOptions.Name (same as "--node-name" passed to "kubeadm init/join")
- // - "hostname-overide" flag in NodeRegistrationOptions.KubeletExtraArgs
- // It also returns the hostname or an error if getting the hostname failed.
- func GetNodeNameAndHostname(cfg *kubeadmapi.NodeRegistrationOptions) (string, string, error) {
- hostname, err := kubeadmutil.GetHostname("")
- nodeName := hostname
- if cfg.Name != "" {
- nodeName = cfg.Name
- }
- if name, ok := cfg.KubeletExtraArgs["hostname-override"]; ok {
- nodeName = name
- }
- return nodeName, hostname, err
- }
- // WriteKubeletDynamicEnvFile writes an environment file with dynamic flags to the kubelet.
- // Used at "kubeadm init" and "kubeadm join" time.
- func WriteKubeletDynamicEnvFile(cfg *kubeadmapi.ClusterConfiguration, nodeReg *kubeadmapi.NodeRegistrationOptions, registerTaintsUsingFlags bool, kubeletDir string) error {
- flagOpts := kubeletFlagsOpts{
- nodeRegOpts: nodeReg,
- featureGates: cfg.FeatureGates,
- pauseImage: images.GetPauseImage(cfg),
- registerTaintsUsingFlags: registerTaintsUsingFlags,
- execer: utilsexec.New(),
- isServiceActiveFunc: func(name string) (bool, error) {
- initSystem, err := initsystem.GetInitSystem()
- if err != nil {
- return false, err
- }
- return initSystem.ServiceIsActive(name), nil
- },
- }
- stringMap := buildKubeletArgMap(flagOpts)
- argList := kubeadmutil.BuildArgumentListFromMap(stringMap, nodeReg.KubeletExtraArgs)
- envFileContent := fmt.Sprintf("%s=%q\n", constants.KubeletEnvFileVariableName, strings.Join(argList, " "))
- return writeKubeletFlagBytesToDisk([]byte(envFileContent), kubeletDir)
- }
- // buildKubeletArgMap takes a kubeletFlagsOpts object and builds based on that a string-string map with flags
- // that should be given to the local kubelet daemon.
- func buildKubeletArgMap(opts kubeletFlagsOpts) map[string]string {
- kubeletFlags := map[string]string{}
- if opts.nodeRegOpts.CRISocket == constants.DefaultDockerCRISocket {
- // These flags should only be set when running docker
- kubeletFlags["network-plugin"] = "cni"
- driver, err := kubeadmutil.GetCgroupDriverDocker(opts.execer)
- if err != nil {
- klog.Warningf("cannot automatically assign a '--cgroup-driver' value when starting the Kubelet: %v\n", err)
- } else {
- kubeletFlags["cgroup-driver"] = driver
- }
- if opts.pauseImage != "" {
- kubeletFlags["pod-infra-container-image"] = opts.pauseImage
- }
- } else {
- kubeletFlags["container-runtime"] = "remote"
- kubeletFlags["container-runtime-endpoint"] = opts.nodeRegOpts.CRISocket
- }
- if opts.registerTaintsUsingFlags && opts.nodeRegOpts.Taints != nil && len(opts.nodeRegOpts.Taints) > 0 {
- taintStrs := []string{}
- for _, taint := range opts.nodeRegOpts.Taints {
- taintStrs = append(taintStrs, taint.ToString())
- }
- kubeletFlags["register-with-taints"] = strings.Join(taintStrs, ",")
- }
- ok, err := opts.isServiceActiveFunc("systemd-resolved")
- if err != nil {
- klog.Warningf("cannot determine if systemd-resolved is active: %v\n", err)
- }
- if ok {
- kubeletFlags["resolv-conf"] = "/run/systemd/resolve/resolv.conf"
- }
- // Pass the "--hostname-override" flag to the kubelet only if it's different from the hostname
- nodeName, hostname, err := GetNodeNameAndHostname(opts.nodeRegOpts)
- if err != nil {
- klog.Warning(err)
- }
- if nodeName != hostname {
- klog.V(1).Infof("setting kubelet hostname-override to %q", nodeName)
- kubeletFlags["hostname-override"] = nodeName
- }
- // TODO: Conditionally set `--cgroup-driver` to either `systemd` or `cgroupfs` for CRI other than Docker
- // TODO: The following code should be removed after dual-stack is GA.
- // Note: The user still retains the ability to explicitly set feature-gates and that value will overwrite this base value.
- if enabled, present := opts.featureGates[features.IPv6DualStack]; present {
- kubeletFlags["feature-gates"] = fmt.Sprintf("%s=%t", features.IPv6DualStack, enabled)
- }
- return kubeletFlags
- }
- // writeKubeletFlagBytesToDisk writes a byte slice down to disk at the specific location of the kubelet flag overrides file
- func writeKubeletFlagBytesToDisk(b []byte, kubeletDir string) error {
- kubeletEnvFilePath := filepath.Join(kubeletDir, constants.KubeletEnvFileName)
- fmt.Printf("[kubelet-start] Writing kubelet environment file with flags to file %q\n", kubeletEnvFilePath)
- // creates target folder if not already exists
- if err := os.MkdirAll(kubeletDir, 0700); err != nil {
- return errors.Wrapf(err, "failed to create directory %q", kubeletDir)
- }
- if err := ioutil.WriteFile(kubeletEnvFilePath, b, 0644); err != nil {
- return errors.Wrapf(err, "failed to write kubelet configuration to the file %q", kubeletEnvFilePath)
- }
- return nil
- }
|