k3s/pkg/daemons/agent/agent.go

201 lines
6.4 KiB
Go
Raw Normal View History

2019-01-01 08:23:01 +00:00
package agent
import (
"math/rand"
2019-01-22 21:14:58 +00:00
"os"
2019-01-09 16:54:15 +00:00
"path/filepath"
2019-01-22 21:14:58 +00:00
"strings"
2019-01-01 08:23:01 +00:00
"time"
2019-03-08 22:47:44 +00:00
"github.com/opencontainers/runc/libcontainer/system"
"github.com/rancher/k3s/pkg/cgroups"
2019-01-09 16:54:15 +00:00
"github.com/rancher/k3s/pkg/daemons/config"
"github.com/rancher/k3s/pkg/daemons/executor"
"github.com/rancher/k3s/pkg/util"
2019-01-01 08:23:01 +00:00
"github.com/sirupsen/logrus"
2019-01-22 21:14:58 +00:00
"k8s.io/apimachinery/pkg/util/net"
2019-04-08 17:53:52 +00:00
"k8s.io/component-base/logs"
2019-12-12 01:23:55 +00:00
_ "k8s.io/component-base/metrics/prometheus/restclient" // for client metric registration
_ "k8s.io/component-base/metrics/prometheus/version" // for version metric registration
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
2019-01-01 08:23:01 +00:00
)
const unixPrefix = "unix://"
2019-01-01 08:23:01 +00:00
func Agent(config *config.Agent) error {
rand.Seed(time.Now().UTC().UnixNano())
2019-11-05 09:45:07 +00:00
logs.InitLogs()
defer logs.FlushLogs()
if err := startKubelet(config); err != nil {
return err
}
2020-04-27 16:31:25 +00:00
if !config.DisableKubeProxy {
return startKubeProxy(config)
}
2019-01-01 08:23:01 +00:00
return nil
}
2020-04-27 16:31:25 +00:00
func startKubeProxy(cfg *config.Agent) error {
argsMap := map[string]string{
"proxy-mode": "iptables",
"healthz-bind-address": "127.0.0.1",
"kubeconfig": cfg.KubeConfigKubeProxy,
"cluster-cidr": util.JoinIPNets(cfg.ClusterCIDRs),
"conntrack-max-per-core": "0",
"conntrack-tcp-timeout-established": "0s",
"conntrack-tcp-timeout-close-wait": "0s",
}
2019-11-05 09:45:07 +00:00
if cfg.NodeName != "" {
argsMap["hostname-override"] = cfg.NodeName
}
2019-01-01 08:23:01 +00:00
2019-11-05 09:45:07 +00:00
args := config.GetArgsList(argsMap, cfg.ExtraKubeProxyArgs)
logrus.Infof("Running kube-proxy %s", config.ArgString(args))
return executor.KubeProxy(args)
2019-01-01 08:23:01 +00:00
}
func startKubelet(cfg *config.Agent) error {
argsMap := map[string]string{
"healthz-bind-address": "127.0.0.1",
"read-only-port": "0",
2019-04-12 06:06:35 +00:00
"cluster-domain": cfg.ClusterDomain,
2019-05-29 18:53:51 +00:00
"kubeconfig": cfg.KubeConfigKubelet,
"eviction-hard": "imagefs.available<5%,nodefs.available<5%",
"eviction-minimum-reclaim": "imagefs.available=10%,nodefs.available=10%",
"fail-swap-on": "false",
//"cgroup-root": "/k3s",
"cgroup-driver": "cgroupfs",
"authentication-token-webhook": "true",
"anonymous-auth": "false",
"authorization-mode": modes.ModeWebhook,
2019-01-01 08:23:01 +00:00
}
if cfg.PodManifests != "" && argsMap["pod-manifest-path"] == "" {
argsMap["pod-manifest-path"] = cfg.PodManifests
}
if err := os.MkdirAll(argsMap["pod-manifest-path"], 0755); err != nil {
logrus.Errorf("Failed to mkdir %s: %v", argsMap["pod-manifest-path"], err)
}
2019-01-09 16:54:15 +00:00
if cfg.RootDir != "" {
argsMap["root-dir"] = cfg.RootDir
argsMap["cert-dir"] = filepath.Join(cfg.RootDir, "pki")
argsMap["seccomp-profile-root"] = filepath.Join(cfg.RootDir, "seccomp")
2019-01-01 08:23:01 +00:00
}
2019-01-09 16:54:15 +00:00
if cfg.CNIConfDir != "" {
argsMap["cni-conf-dir"] = cfg.CNIConfDir
2019-01-01 08:23:01 +00:00
}
2019-01-09 16:54:15 +00:00
if cfg.CNIBinDir != "" {
argsMap["cni-bin-dir"] = cfg.CNIBinDir
2019-01-01 08:23:01 +00:00
}
if cfg.CNIPlugin {
argsMap["network-plugin"] = "cni"
}
2019-01-09 16:54:15 +00:00
if len(cfg.ClusterDNS) > 0 {
argsMap["cluster-dns"] = util.JoinIPs(cfg.ClusterDNSs)
2019-01-01 08:23:01 +00:00
}
if cfg.ResolvConf != "" {
argsMap["resolv-conf"] = cfg.ResolvConf
}
2019-01-09 16:54:15 +00:00
if cfg.RuntimeSocket != "" {
argsMap["container-runtime"] = "remote"
argsMap["containerd"] = cfg.RuntimeSocket
argsMap["serialize-image-pulls"] = "false"
if strings.HasPrefix(argsMap["container-runtime-endpoint"], unixPrefix) {
argsMap["container-runtime-endpoint"] = cfg.RuntimeSocket
} else {
argsMap["container-runtime-endpoint"] = unixPrefix + cfg.RuntimeSocket
}
} else if cfg.PauseImage != "" {
argsMap["pod-infra-container-image"] = cfg.PauseImage
2019-01-01 08:23:01 +00:00
}
2019-01-09 16:54:15 +00:00
if cfg.ListenAddress != "" {
argsMap["address"] = cfg.ListenAddress
2019-01-09 16:54:15 +00:00
}
2019-05-29 18:53:51 +00:00
if cfg.ClientCA != "" {
argsMap["anonymous-auth"] = "false"
2019-05-29 18:53:51 +00:00
argsMap["client-ca-file"] = cfg.ClientCA
2019-04-19 18:20:34 +00:00
}
2019-05-29 18:53:51 +00:00
if cfg.ServingKubeletCert != "" && cfg.ServingKubeletKey != "" {
argsMap["tls-cert-file"] = cfg.ServingKubeletCert
argsMap["tls-private-key-file"] = cfg.ServingKubeletKey
2019-01-09 16:54:15 +00:00
}
if cfg.NodeName != "" {
argsMap["hostname-override"] = cfg.NodeName
2019-01-09 16:54:15 +00:00
}
defaultIP, err := net.ChooseHostInterface()
if err != nil || defaultIP.String() != cfg.NodeIP {
argsMap["node-ip"] = cfg.NodeIP
2019-01-09 16:54:15 +00:00
}
kubeletRoot, runtimeRoot, hasCFS, hasPIDs := cgroups.CheckCgroups()
if !hasCFS {
2019-01-22 21:14:58 +00:00
logrus.Warn("Disabling CPU quotas due to missing cpu.cfs_period_us")
argsMap["cpu-cfs-quota"] = "false"
2019-01-22 21:14:58 +00:00
}
if !hasPIDs {
logrus.Warn("Disabling pod PIDs limit feature due to missing cgroup pids support")
argsMap["cgroups-per-qos"] = "false"
argsMap["enforce-node-allocatable"] = ""
argsMap["feature-gates"] = addFeatureGate(argsMap["feature-gates"], "SupportPodPidsLimit=false")
}
if kubeletRoot != "" {
argsMap["kubelet-cgroups"] = kubeletRoot
}
if runtimeRoot != "" {
argsMap["runtime-cgroups"] = runtimeRoot
}
2019-03-08 22:47:44 +00:00
if system.RunningInUserNS() {
argsMap["feature-gates"] = addFeatureGate(argsMap["feature-gates"], "DevicePlugins=false")
2019-03-08 22:47:44 +00:00
}
2019-01-01 08:23:01 +00:00
argsMap["node-labels"] = strings.Join(cfg.NodeLabels, ",")
if len(cfg.NodeTaints) > 0 {
argsMap["register-with-taints"] = strings.Join(cfg.NodeTaints, ",")
}
2019-10-15 21:17:26 +00:00
if !cfg.DisableCCM {
argsMap["cloud-provider"] = "external"
}
if ImageCredProvAvailable(cfg) {
logrus.Infof("Kubelet image credential provider bin dir and configuration file found.")
argsMap["feature-gates"] = addFeatureGate(argsMap["feature-gates"], "KubeletCredentialProviders=true")
argsMap["image-credential-provider-bin-dir"] = cfg.ImageCredProvBinDir
argsMap["image-credential-provider-config"] = cfg.ImageCredProvConfig
}
if cfg.Rootless {
createRootlessConfig(argsMap, hasCFS, hasCFS)
}
if cfg.ProtectKernelDefaults {
argsMap["protect-kernel-defaults"] = "true"
}
2019-03-08 22:47:44 +00:00
args := config.GetArgsList(argsMap, cfg.ExtraKubeletArgs)
logrus.Infof("Running kubelet %s", config.ArgString(args))
2019-01-01 08:23:01 +00:00
return executor.Kubelet(args)
2019-01-01 08:23:01 +00:00
}
2019-01-22 21:14:58 +00:00
func addFeatureGate(current, new string) string {
if current == "" {
return new
}
return current + "," + new
}
// ImageCredProvAvailable checks to see if the kubelet image credential provider bin dir and config
// files exist and are of the correct types. This is exported so that it may be used by downstream projects.
func ImageCredProvAvailable(cfg *config.Agent) bool {
if info, err := os.Stat(cfg.ImageCredProvBinDir); err != nil || !info.IsDir() {
logrus.Debugf("Kubelet image credential provider bin directory check failed: %v", err)
return false
}
if info, err := os.Stat(cfg.ImageCredProvConfig); err != nil || info.IsDir() {
logrus.Debugf("Kubelet image credential provider config file check failed: %v", err)
return false
}
return true
}