k3s/pkg/daemons/agent/agent.go

179 lines
4.9 KiB
Go
Raw Normal View History

2019-01-01 08:23:01 +00:00
package agent
import (
2019-01-22 21:14:58 +00:00
"bufio"
2019-01-01 08:23:01 +00:00
"context"
"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"
2019-01-09 16:54:15 +00:00
"github.com/rancher/k3s/pkg/daemons/config"
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-01-01 08:23:01 +00:00
app2 "k8s.io/kubernetes/cmd/kube-proxy/app"
"k8s.io/kubernetes/cmd/kubelet/app"
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
2019-03-08 22:47:44 +00:00
2019-01-01 08:23:01 +00:00
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
_ "k8s.io/kubernetes/pkg/version/prometheus" // for version metric registration
)
func Agent(config *config.Agent) error {
rand.Seed(time.Now().UTC().UnixNano())
kubelet(config)
kubeProxy(config)
return nil
}
func kubeProxy(cfg *config.Agent) {
argsMap := map[string]string{
"proxy-mode": "iptables",
"healthz-bind-address": "127.0.0.1",
"kubeconfig": cfg.KubeConfig,
"cluster-cidr": cfg.ClusterCIDR.String(),
}
args := config.GetArgsList(argsMap, cfg.ExtraKubeProxyArgs)
2019-01-01 08:23:01 +00:00
command := app2.NewProxyCommand()
command.SetArgs(args)
go func() {
err := command.Execute()
logrus.Fatalf("kube-proxy exited: %v", err)
}()
}
2019-01-09 16:54:15 +00:00
func kubelet(cfg *config.Agent) {
2019-01-01 08:23:01 +00:00
command := app.NewKubeletCommand(context.Background().Done())
logs.InitLogs()
defer logs.FlushLogs()
argsMap := map[string]string{
"healthz-bind-address": "127.0.0.1",
"read-only-port": "0",
"allow-privileged": "true",
2019-04-12 06:06:35 +00:00
"cluster-domain": cfg.ClusterDomain,
"kubeconfig": cfg.KubeConfig,
"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",
"authorization-mode": modes.ModeWebhook,
2019-01-01 08:23:01 +00:00
}
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
}
2019-01-09 16:54:15 +00:00
if len(cfg.ClusterDNS) > 0 {
argsMap["cluster-dns"] = cfg.ClusterDNS.String()
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["container-runtime-endpoint"] = cfg.RuntimeSocket
argsMap["serialize-image-pulls"] = "false"
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
}
if cfg.CACertPath != "" {
argsMap["anonymous-auth"] = "false"
argsMap["client-ca-file"] = cfg.CACertPath
2019-04-19 18:20:34 +00:00
}
if cfg.NodeCertFile != "" && cfg.NodeKeyFile != "" {
argsMap["tls-cert-file"] = cfg.NodeCertFile
argsMap["tls-private-key-file"] = cfg.NodeKeyFile
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
}
root, hasCFS, hasPIDs := 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 root != "" {
argsMap["runtime-cgroups"] = root
argsMap["kubelet-cgroups"] = root
}
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
2019-03-08 22:47:44 +00:00
args := config.GetArgsList(argsMap, cfg.ExtraKubeletArgs)
2019-01-01 08:23:01 +00:00
command.SetArgs(args)
go func() {
2019-01-09 16:54:15 +00:00
logrus.Infof("Running kubelet %s", config.ArgString(args))
2019-01-01 08:23:01 +00:00
logrus.Fatalf("kubelet exited: %v", command.Execute())
}()
}
2019-01-22 21:14:58 +00:00
func addFeatureGate(current, new string) string {
if current == "" {
return new
}
return current + "," + new
}
func checkCgroups() (root string, hasCFS bool, hasPIDs bool) {
2019-01-22 21:14:58 +00:00
f, err := os.Open("/proc/self/cgroup")
if err != nil {
return "", false, false
2019-01-22 21:14:58 +00:00
}
defer f.Close()
scan := bufio.NewScanner(f)
for scan.Scan() {
parts := strings.Split(scan.Text(), ":")
if len(parts) < 3 {
continue
}
systems := strings.Split(parts[1], ",")
for _, system := range systems {
if system == "pids" {
hasPIDs = true
} else if system == "cpu" {
2019-01-22 21:14:58 +00:00
p := filepath.Join("/sys/fs/cgroup", parts[1], parts[2], "cpu.cfs_period_us")
if _, err := os.Stat(p); err == nil {
hasCFS = true
}
} else if system == "name=systemd" {
last := parts[len(parts)-1]
i := strings.LastIndex(last, ".slice")
if i > 0 {
root = "/systemd" + last[:i+len(".slice")]
2019-01-22 21:14:58 +00:00
}
}
}
}
return root, hasCFS, hasPIDs
2019-01-22 21:14:58 +00:00
}