mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 09:22:44 +00:00
Flannel handshakes with kubelet.
This commit is contained in:
parent
4cd1ee177b
commit
7aa8ebe30f
@ -4,16 +4,16 @@ flannel-tar:
|
|||||||
- user: root
|
- user: root
|
||||||
- name: /usr/local/src
|
- name: /usr/local/src
|
||||||
- makedirs: True
|
- makedirs: True
|
||||||
- source: https://github.com/coreos/flannel/releases/download/v0.5.3/flannel-0.5.3-linux-amd64.tar.gz
|
- source: https://github.com/coreos/flannel/releases/download/v0.5.5/flannel-0.5.5-linux-amd64.tar.gz
|
||||||
- tar_options: v
|
- tar_options: v
|
||||||
- source_hash: md5=2a82ed82a37d71c85586977f0e475b70
|
- source_hash: md5=972c717254775bef528f040af804f2cc
|
||||||
- archive_format: tar
|
- archive_format: tar
|
||||||
- if_missing: /usr/local/src/flannel/flannel-0.5.3/
|
- if_missing: /usr/local/src/flannel/flannel-0.5.5/
|
||||||
|
|
||||||
flannel-symlink:
|
flannel-symlink:
|
||||||
file.symlink:
|
file.symlink:
|
||||||
- name: /usr/local/bin/flanneld
|
- name: /usr/local/bin/flanneld
|
||||||
- target: /usr/local/src/flannel-0.5.3/flanneld
|
- target: /usr/local/src/flannel-0.5.5/flanneld
|
||||||
- force: true
|
- force: true
|
||||||
- watch:
|
- watch:
|
||||||
- archive: flannel-tar
|
- archive: flannel-tar
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
{% set root_ca_file = "--root-ca-file=/srv/kubernetes/ca.crt" -%}
|
{% set root_ca_file = "--root-ca-file=/srv/kubernetes/ca.crt" -%}
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
|
||||||
{% set params = "--master=127.0.0.1:8080" + " " + cluster_name + " " + cluster_cidr + " " + allocate_node_cidrs + " " + terminated_pod_gc + " " + cloud_provider + " " + cloud_config + service_account_key + pillar['log_level'] + " " + root_ca_file -%}
|
{% set params = "--master=127.0.0.1:8080" + " " + cluster_name + " " + cluster_cidr + " --allocate-node-cidrs=false" + " " + terminated_pod_gc + " " + cloud_provider + " " + cloud_config + service_account_key + pillar['log_level'] + " " + root_ca_file -%}
|
||||||
|
|
||||||
|
|
||||||
# test_args has to be kept at the end, so they'll overwrite any prior configuration
|
# test_args has to be kept at the end, so they'll overwrite any prior configuration
|
||||||
|
@ -67,7 +67,11 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultRootDir = "/var/lib/kubelet"
|
const (
|
||||||
|
defaultRootDir = "/var/lib/kubelet"
|
||||||
|
networkConfig = "/var/run/flannel/network.json"
|
||||||
|
useDefaultOverlay = true
|
||||||
|
)
|
||||||
|
|
||||||
// KubeletServer encapsulates all of the parameters necessary for starting up
|
// KubeletServer encapsulates all of the parameters necessary for starting up
|
||||||
// a kubelet. These can either be set via command line or directly.
|
// a kubelet. These can either be set via command line or directly.
|
||||||
@ -155,6 +159,10 @@ type KubeletServer struct {
|
|||||||
|
|
||||||
// Pull images one at a time.
|
// Pull images one at a time.
|
||||||
SerializeImagePulls bool
|
SerializeImagePulls bool
|
||||||
|
|
||||||
|
// Flannel config parameters
|
||||||
|
UseDefaultOverlay bool
|
||||||
|
NetworkConfig string
|
||||||
}
|
}
|
||||||
|
|
||||||
// bootstrapping interface for kubelet, targets the initialization protocol
|
// bootstrapping interface for kubelet, targets the initialization protocol
|
||||||
@ -227,6 +235,9 @@ func NewKubeletServer() *KubeletServer {
|
|||||||
ReconcileCIDR: true,
|
ReconcileCIDR: true,
|
||||||
KubeAPIQPS: 5.0,
|
KubeAPIQPS: 5.0,
|
||||||
KubeAPIBurst: 10,
|
KubeAPIBurst: 10,
|
||||||
|
// Flannel parameters
|
||||||
|
UseDefaultOverlay: useDefaultOverlay,
|
||||||
|
// NetworkConfig: networkConfig,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,6 +352,10 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) {
|
|||||||
fs.Float32Var(&s.KubeAPIQPS, "kube-api-qps", s.KubeAPIQPS, "QPS to use while talking with kubernetes apiserver")
|
fs.Float32Var(&s.KubeAPIQPS, "kube-api-qps", s.KubeAPIQPS, "QPS to use while talking with kubernetes apiserver")
|
||||||
fs.IntVar(&s.KubeAPIBurst, "kube-api-burst", s.KubeAPIBurst, "Burst to use while talking with kubernetes apiserver")
|
fs.IntVar(&s.KubeAPIBurst, "kube-api-burst", s.KubeAPIBurst, "Burst to use while talking with kubernetes apiserver")
|
||||||
fs.BoolVar(&s.SerializeImagePulls, "serialize-image-pulls", s.SerializeImagePulls, "Pull images one at a time. We recommend *not* changing the default value on nodes that run docker daemon with version < 1.9 or an Aufs storage backend. Issue #10959 has more details. [default=true]")
|
fs.BoolVar(&s.SerializeImagePulls, "serialize-image-pulls", s.SerializeImagePulls, "Pull images one at a time. We recommend *not* changing the default value on nodes that run docker daemon with version < 1.9 or an Aufs storage backend. Issue #10959 has more details. [default=true]")
|
||||||
|
|
||||||
|
// Flannel config parameters
|
||||||
|
fs.BoolVar(&s.UseDefaultOverlay, "use-default-overlay", s.UseDefaultOverlay, "Experimental support for starting the kubelet with the default overlay network (flannel). Assumes flanneld is already running in client mode. [default=false]")
|
||||||
|
fs.StringVar(&s.NetworkConfig, "network-config", s.NetworkConfig, "Absolute path to a network json file, as accepted by flannel.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnsecuredKubeletConfig returns a KubeletConfig suitable for being run, or an error if the server setup
|
// UnsecuredKubeletConfig returns a KubeletConfig suitable for being run, or an error if the server setup
|
||||||
@ -478,6 +493,10 @@ func (s *KubeletServer) UnsecuredKubeletConfig() (*KubeletConfig, error) {
|
|||||||
TLSOptions: tlsOptions,
|
TLSOptions: tlsOptions,
|
||||||
Writer: writer,
|
Writer: writer,
|
||||||
VolumePlugins: ProbeVolumePlugins(),
|
VolumePlugins: ProbeVolumePlugins(),
|
||||||
|
|
||||||
|
// Flannel options
|
||||||
|
UseDefaultOverlay: s.UseDefaultOverlay,
|
||||||
|
NetworkConfig: s.NetworkConfig,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -949,6 +968,10 @@ type KubeletConfig struct {
|
|||||||
TLSOptions *kubelet.TLSOptions
|
TLSOptions *kubelet.TLSOptions
|
||||||
Writer io.Writer
|
Writer io.Writer
|
||||||
VolumePlugins []volume.VolumePlugin
|
VolumePlugins []volume.VolumePlugin
|
||||||
|
|
||||||
|
// Flannel parameters
|
||||||
|
UseDefaultOverlay bool
|
||||||
|
NetworkConfig string
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.PodConfig, err error) {
|
func CreateAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.PodConfig, err error) {
|
||||||
@ -1031,6 +1054,9 @@ func CreateAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.Pod
|
|||||||
kc.OOMAdjuster,
|
kc.OOMAdjuster,
|
||||||
kc.SerializeImagePulls,
|
kc.SerializeImagePulls,
|
||||||
kc.ContainerManager,
|
kc.ContainerManager,
|
||||||
|
// Flannel parameters
|
||||||
|
kc.UseDefaultOverlay,
|
||||||
|
//kc.NetworkConfig,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
132
pkg/kubelet/flannel_server.go
Normal file
132
pkg/kubelet/flannel_server.go
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
package kubelet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
networkType = "vxlan"
|
||||||
|
dockerOptsFile = "/etc/default/docker"
|
||||||
|
flannelSubnetKey = "FLANNEL_SUBNET"
|
||||||
|
flannelNetworkKey = "FLANNEL_NETWORK"
|
||||||
|
flannelMtuKey = "FLANNEL_MTU"
|
||||||
|
dockerOptsKey = "DOCKER_OPTS"
|
||||||
|
flannelSubnetFile = "/var/run/flannel/subnet.env"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FlannelServer struct {
|
||||||
|
subnetFile string
|
||||||
|
// TODO: Manage subnet file.
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFlannelServer() *FlannelServer {
|
||||||
|
return &FlannelServer{flannelSubnetFile}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FlannelServer) Handshake() (podCIDR string, err error) {
|
||||||
|
// Flannel daemon will hang till the server comes up, kubelet will hang until
|
||||||
|
// flannel daemon has written subnet env variables. This is the kubelet handshake.
|
||||||
|
// To improve performance, we could defer just the configuration of the container
|
||||||
|
// bridge till after subnet.env is written. Keeping it local is clearer for now.
|
||||||
|
// TODO: Using a file to communicate is brittle
|
||||||
|
if _, err = os.Stat(f.subnetFile); err != nil {
|
||||||
|
return "", fmt.Errorf("Waiting for subnet file %v", f.subnetFile)
|
||||||
|
}
|
||||||
|
glog.Infof("(kubelet)Found flannel subnet file %v", f.subnetFile)
|
||||||
|
|
||||||
|
// TODO: Rest of this function is a hack.
|
||||||
|
config, err := parseKVConfig(f.subnetFile)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if err = writeDockerOptsFromFlannelConfig(config); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
podCIDR, ok := config[flannelSubnetKey]
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("No flannel subnet, config %+v", config)
|
||||||
|
}
|
||||||
|
kubeNetwork, ok := config[flannelNetworkKey]
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("No flannel network, config %+v", config)
|
||||||
|
}
|
||||||
|
if err := exec.Command("iptables",
|
||||||
|
"-t", "nat",
|
||||||
|
"-A", "POSTROUTING",
|
||||||
|
"!", "-d", kubeNetwork,
|
||||||
|
"-s", podCIDR,
|
||||||
|
"-j", "MASQUERADE").Run(); err != nil {
|
||||||
|
return "", fmt.Errorf("Unable to install iptables rule for flannel.")
|
||||||
|
}
|
||||||
|
return podCIDR, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take env variables from flannel subnet env and write to /etc/docker/defaults.
|
||||||
|
func writeDockerOptsFromFlannelConfig(flannelConfig map[string]string) error {
|
||||||
|
// TODO: Write dockeropts to unit file on systemd machines
|
||||||
|
// https://github.com/docker/docker/issues/9889
|
||||||
|
mtu, ok := flannelConfig[flannelMtuKey]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("No flannel mtu, flannel config %+v", flannelConfig)
|
||||||
|
}
|
||||||
|
dockerOpts, err := parseKVConfig(dockerOptsFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
opts, ok := dockerOpts[dockerOptsKey]
|
||||||
|
if !ok {
|
||||||
|
glog.Errorf("(kubelet)Did not find docker opts, writing them")
|
||||||
|
opts = fmt.Sprintf(
|
||||||
|
" --bridge=cbr0 --iptables=false --ip-masq=false")
|
||||||
|
} else {
|
||||||
|
opts, _ = strconv.Unquote(opts)
|
||||||
|
}
|
||||||
|
dockerOpts[dockerOptsKey] = fmt.Sprintf("\"%v --mtu=%v\"", opts, mtu)
|
||||||
|
if err = writeKVConfig(dockerOptsFile, dockerOpts); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseKVConfig takes a file with key-value env variables and returns a dictionary mapping the same.
|
||||||
|
func parseKVConfig(filename string) (map[string]string, error) {
|
||||||
|
config := map[string]string{}
|
||||||
|
if _, err := os.Stat(filename); err != nil {
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
buff, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
str := string(buff)
|
||||||
|
glog.Infof("(kubelet) Read kv options %+v from %v", str, filename)
|
||||||
|
for _, line := range strings.Split(str, "\n") {
|
||||||
|
kv := strings.Split(line, "=")
|
||||||
|
if len(kv) != 2 {
|
||||||
|
glog.Warningf("Ignoring non key-value pair %v", kv)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
config[string(kv[0])] = string(kv[1])
|
||||||
|
}
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeKVConfig writes a kv map as env variables into the given file.
|
||||||
|
func writeKVConfig(filename string, kv map[string]string) error {
|
||||||
|
if _, err := os.Stat(filename); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
content := ""
|
||||||
|
for k, v := range kv {
|
||||||
|
content += fmt.Sprintf("%v=%v\n", k, v)
|
||||||
|
}
|
||||||
|
glog.Warningf("(kubelet)Writing kv options %+v to %v", content, filename)
|
||||||
|
return ioutil.WriteFile(filename, []byte(content), 0644)
|
||||||
|
}
|
@ -217,6 +217,7 @@ func NewMainKubelet(
|
|||||||
oomAdjuster *oom.OOMAdjuster,
|
oomAdjuster *oom.OOMAdjuster,
|
||||||
serializeImagePulls bool,
|
serializeImagePulls bool,
|
||||||
containerManager cm.ContainerManager,
|
containerManager cm.ContainerManager,
|
||||||
|
useDefaultOverlay bool,
|
||||||
) (*Kubelet, error) {
|
) (*Kubelet, error) {
|
||||||
|
|
||||||
if rootDirectory == "" {
|
if rootDirectory == "" {
|
||||||
@ -327,8 +328,16 @@ func NewMainKubelet(
|
|||||||
cpuCFSQuota: cpuCFSQuota,
|
cpuCFSQuota: cpuCFSQuota,
|
||||||
daemonEndpoints: daemonEndpoints,
|
daemonEndpoints: daemonEndpoints,
|
||||||
containerManager: containerManager,
|
containerManager: containerManager,
|
||||||
}
|
|
||||||
|
|
||||||
|
// Flannel options
|
||||||
|
// TODO: This is currently a dummy server.
|
||||||
|
flannelServer: NewFlannelServer(),
|
||||||
|
useDefaultOverlay: useDefaultOverlay,
|
||||||
|
}
|
||||||
|
if klet.kubeClient == nil {
|
||||||
|
glog.Infof("Master not setting up flannel overlay")
|
||||||
|
klet.useDefaultOverlay = false
|
||||||
|
}
|
||||||
if plug, err := network.InitNetworkPlugin(networkPlugins, networkPluginName, &networkHost{klet}); err != nil {
|
if plug, err := network.InitNetworkPlugin(networkPlugins, networkPluginName, &networkHost{klet}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
@ -649,6 +658,10 @@ type Kubelet struct {
|
|||||||
|
|
||||||
// oneTimeInitializer is used to initialize modules that are dependent on the runtime to be up.
|
// oneTimeInitializer is used to initialize modules that are dependent on the runtime to be up.
|
||||||
oneTimeInitializer sync.Once
|
oneTimeInitializer sync.Once
|
||||||
|
|
||||||
|
// Flannel options.
|
||||||
|
useDefaultOverlay bool
|
||||||
|
flannelServer *FlannelServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kl *Kubelet) allSourcesReady() bool {
|
func (kl *Kubelet) allSourcesReady() bool {
|
||||||
@ -1116,6 +1129,7 @@ func (kl *Kubelet) syncNodeStatus() {
|
|||||||
}
|
}
|
||||||
if kl.registerNode {
|
if kl.registerNode {
|
||||||
// This will exit immediately if it doesn't need to do anything.
|
// This will exit immediately if it doesn't need to do anything.
|
||||||
|
glog.Infof("(kubelet) registering node with apiserver")
|
||||||
kl.registerWithApiserver()
|
kl.registerWithApiserver()
|
||||||
}
|
}
|
||||||
if err := kl.updateNodeStatus(); err != nil {
|
if err := kl.updateNodeStatus(); err != nil {
|
||||||
@ -2574,10 +2588,10 @@ func (kl *Kubelet) updateRuntimeUp() {
|
|||||||
|
|
||||||
func (kl *Kubelet) reconcileCBR0(podCIDR string) error {
|
func (kl *Kubelet) reconcileCBR0(podCIDR string) error {
|
||||||
if podCIDR == "" {
|
if podCIDR == "" {
|
||||||
glog.V(5).Info("PodCIDR not set. Will not configure cbr0.")
|
glog.V(1).Info("(kubelet) PodCIDR not set. Will not configure cbr0.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
glog.V(5).Infof("PodCIDR is set to %q", podCIDR)
|
glog.V(1).Infof("(kubelet) PodCIDR is set to %q", podCIDR)
|
||||||
_, cidr, err := net.ParseCIDR(podCIDR)
|
_, cidr, err := net.ParseCIDR(podCIDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -2619,6 +2633,17 @@ var oldNodeUnschedulable bool
|
|||||||
func (kl *Kubelet) syncNetworkStatus() {
|
func (kl *Kubelet) syncNetworkStatus() {
|
||||||
var err error
|
var err error
|
||||||
if kl.configureCBR0 {
|
if kl.configureCBR0 {
|
||||||
|
if kl.useDefaultOverlay {
|
||||||
|
glog.Infof("(kubelet) handshaking")
|
||||||
|
podCIDR, err := kl.flannelServer.Handshake()
|
||||||
|
if err != nil {
|
||||||
|
glog.Infof("Flannel server handshake failed %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
glog.Infof("(kubelet) setting cidr, currently: %v -> %v",
|
||||||
|
kl.runtimeState.podCIDR(), podCIDR)
|
||||||
|
kl.runtimeState.setPodCIDR(podCIDR)
|
||||||
|
}
|
||||||
if err := ensureIPTablesMasqRule(); err != nil {
|
if err := ensureIPTablesMasqRule(); err != nil {
|
||||||
err = fmt.Errorf("Error on adding ip table rules: %v", err)
|
err = fmt.Errorf("Error on adding ip table rules: %v", err)
|
||||||
glog.Error(err)
|
glog.Error(err)
|
||||||
@ -2884,9 +2909,13 @@ func (kl *Kubelet) tryUpdateNodeStatus() error {
|
|||||||
if node == nil {
|
if node == nil {
|
||||||
return fmt.Errorf("no node instance returned for %q", kl.nodeName)
|
return fmt.Errorf("no node instance returned for %q", kl.nodeName)
|
||||||
}
|
}
|
||||||
if kl.reconcileCIDR {
|
// TODO: Actually update the node spec with pod cidr, this is currently a no-op.
|
||||||
|
if kl.useDefaultOverlay {
|
||||||
|
node.Spec.PodCIDR = kl.runtimeState.podCIDR()
|
||||||
|
} else if kl.reconcileCIDR {
|
||||||
kl.runtimeState.setPodCIDR(node.Spec.PodCIDR)
|
kl.runtimeState.setPodCIDR(node.Spec.PodCIDR)
|
||||||
}
|
}
|
||||||
|
glog.Infof("(kubelet) updating node in apiserver with cidr %v", node.Spec.PodCIDR)
|
||||||
|
|
||||||
if err := kl.setNodeStatus(node); err != nil {
|
if err := kl.setNodeStatus(node); err != nil {
|
||||||
return err
|
return err
|
||||||
|
Loading…
Reference in New Issue
Block a user