-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using bridge network for nodes #484
Changes from 13 commits
0a51a90
91d7f97
c01f04d
ad97d59
66e9e08
9ca5380
c6e557e
37afb9e
94d79ce
55b2ea5
22fc9aa
c27ee94
52e1c61
e9b32dc
48977ec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,7 @@ import ( | |
"sigs.k8s.io/kind/pkg/cluster/nodes" | ||
"sigs.k8s.io/kind/pkg/concurrent" | ||
"sigs.k8s.io/kind/pkg/container/cri" | ||
"sigs.k8s.io/kind/pkg/container/docker" | ||
logutil "sigs.k8s.io/kind/pkg/log" | ||
) | ||
|
||
|
@@ -80,6 +81,14 @@ func provisionNodes( | |
) error { | ||
defer status.End(false) | ||
|
||
// check if the network is exist. | ||
if !docker.IsNetworkExist(cfg.Networking.BridgeName) { | ||
// create bridge network for nodes. | ||
if err := createNetwork(status, cfg.Networking.BridgeName); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
if err := createNodeContainers(status, cfg, clusterName, clusterLabel); err != nil { | ||
return err | ||
} | ||
|
@@ -88,6 +97,18 @@ func provisionNodes( | |
return nil | ||
} | ||
|
||
func createNetwork(status *logutil.Status, clusterName string) error { | ||
defer status.End(false) | ||
|
||
status.Start("Creating bridge network 🌉") | ||
tao12345666333 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err := docker.CreateNetwork(clusterName); err != nil { | ||
tao12345666333 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return err | ||
} | ||
|
||
status.End(true) | ||
return nil | ||
} | ||
|
||
func createNodeContainers( | ||
status *logutil.Status, cfg *config.Cluster, clusterName, clusterLabel string, | ||
) error { | ||
|
@@ -103,7 +124,7 @@ func createNodeContainers( | |
desiredNode := desiredNode // capture loop variable | ||
fns = append(fns, func() error { | ||
// create the node into a container (~= docker run -d) | ||
_, err := desiredNode.Create(clusterLabel) | ||
_, err := desiredNode.Create(cfg.Networking.BridgeName, clusterLabel) | ||
return err | ||
}) | ||
} | ||
|
@@ -193,16 +214,16 @@ func nodesToCreate(cfg *config.Cluster, clusterName string) []nodeSpec { | |
} | ||
|
||
// TODO(bentheelder): remove network in favor of []cri.PortMapping when that is in | ||
func (d *nodeSpec) Create(clusterLabel string) (node *nodes.Node, err error) { | ||
func (d *nodeSpec) Create(networkName, clusterLabel string) (node *nodes.Node, err error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why isn't this in the nodeSpec? |
||
// create the node into a container (docker run, but it is paused, see createNode) | ||
// TODO(bentheelder): decouple from config objects further | ||
switch d.Role { | ||
case constants.ExternalLoadBalancerNodeRoleValue: | ||
node, err = nodes.CreateExternalLoadBalancerNode(d.Name, d.Image, clusterLabel, d.APIServerAddress, d.APIServerPort) | ||
node, err = nodes.CreateExternalLoadBalancerNode(d.Name, d.Image, networkName, clusterLabel, d.APIServerAddress, d.APIServerPort) | ||
case constants.ControlPlaneNodeRoleValue: | ||
node, err = nodes.CreateControlPlaneNode(d.Name, d.Image, clusterLabel, d.APIServerAddress, d.APIServerPort, d.ExtraMounts) | ||
node, err = nodes.CreateControlPlaneNode(d.Name, d.Image, networkName, clusterLabel, d.APIServerAddress, d.APIServerPort, d.ExtraMounts) | ||
case constants.WorkerNodeRoleValue: | ||
node, err = nodes.CreateWorkerNode(d.Name, d.Image, clusterLabel, d.ExtraMounts) | ||
node, err = nodes.CreateWorkerNode(d.Name, d.Image, networkName, clusterLabel, d.ExtraMounts) | ||
default: | ||
return nil, errors.Errorf("unknown node role: %s", d.Role) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -104,6 +104,7 @@ kubeletConfiguration: | |
nodefs.available: "0%" | ||
nodefs.inodesFree: "0%" | ||
imagefs.available: "0%" | ||
resolvConf: /kind/resolv.conf | ||
controllerManagerExtraArgs: | ||
enable-hostpath-provisioner: "true" | ||
nodeRegistration: | ||
|
@@ -181,6 +182,7 @@ evictionHard: | |
nodefs.available: "0%" | ||
nodefs.inodesFree: "0%" | ||
imagefs.available: "0%" | ||
resolvConf: /kind/resolv.conf | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is not being done for all api versions |
||
--- | ||
# no-op entry that exists solely so it can be patched | ||
apiVersion: kubeproxy.config.k8s.io/v1alpha1 | ||
|
@@ -245,6 +247,7 @@ evictionHard: | |
nodefs.available: "0%" | ||
nodefs.inodesFree: "0%" | ||
imagefs.available: "0%" | ||
resolvConf: /kind/resolv.conf | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really don't like the idea that containerd and debugging tools will have a different resolv conf than kubelet. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as you said
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After considering it, I think the current practice is relatively simple. If we do resolv.conf merge, we need a lot of testing. Why don't we put it later? 🤔 Keep this practice for a while, then change it after the verification is passed. I hope we can move forward. ❤️ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this means other components have an inconsistent resolv conf and we're not actually solving the issue. if we're going to use hostnames we need kubelet and everything else to have the same lookup. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. technically having a different resolv.conf doesn't mean that have a different lookup, just that the pods will not be able to resolv the nodes names, the other requests will use the same dns server, however I agree that reality is always different and we can be broken because docker changes on the DNS behaviour, that will not be surprising 😅
I agree with tao here, I think that we should left until last the DNS exercise There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 on merging the resolv.confs if feasable. |
||
--- | ||
# no-op entry that exists solely so it can be patched | ||
apiVersion: kubeproxy.config.k8s.io/v1alpha1 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,9 @@ package nodes | |
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"regexp" | ||
"runtime" | ||
|
||
"github.com/pkg/errors" | ||
"sigs.k8s.io/kind/pkg/cluster/internal/loadbalancer" | ||
|
@@ -44,3 +47,29 @@ func GetControlPlaneEndpoint(allNodes []Node) (string, error) { | |
|
||
return fmt.Sprintf("%s:%d", loadBalancerIP, loadbalancer.ControlPlanePort), nil | ||
} | ||
|
||
// to avoid the DNS crash we need copy host's /etc/resolv.conf to node | ||
// ref: https://github.com/kubernetes-sigs/kind/pull/484#issuecomment-489469044 | ||
func addResolve(node *Node) error { | ||
// TODO(Jintao Zhang): I can't accurately judge the behavior of windows, so I skipped it for now. | ||
// https://github.com/kubernetes-sigs/kind/pull/484#discussion_r284064671 | ||
if runtime.GOOS == "windows" { | ||
return nil | ||
} | ||
|
||
resolv, err := ioutil.ReadFile("/etc/resolv.conf") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. windows has no /etc/resolv.conf. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a blocker. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Then I will judge through the OS first, skip the behavior of windows. I can't accurately judge the behavior of windows. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just skip Windows. 🙊 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is the first time kind does not behave the same in all environments, not really a fan of that. also, I don't think we should be reading the host's resolv.conf at all |
||
if err != nil { | ||
return errors.Wrap(err, "failed to read /etc/resolv.conf") | ||
} | ||
|
||
// filter the loopback addresses | ||
re := regexp.MustCompile("(?m)[\r\n]+^.*((127.([0-9]{1,3}.){2}[0-9]{1,3})|(::1)).*$") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this shouldn't even be necessary in the hosts's resolv.conf ? |
||
content := re.ReplaceAllString(string(resolv), "") | ||
|
||
err = node.WriteFile("/kind/resolv.conf", content) | ||
tao12345666333 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil { | ||
return errors.Wrap(err, "failed to write /kind/resolv.conf to node") | ||
} | ||
|
||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
Copyright 2019 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 docker | ||
|
||
import ( | ||
"fmt" | ||
|
||
"sigs.k8s.io/kind/pkg/cluster/constants" | ||
"sigs.k8s.io/kind/pkg/exec" | ||
) | ||
|
||
// CreateNetwork create a bridge network | ||
func CreateNetwork(networkName string) error { | ||
cmd := exec.Command( | ||
"docker", "network", | ||
"create", | ||
"--driver=bridge", | ||
"--label="+fmt.Sprintf("%s=%s", constants.ClusterLabelKey, networkName), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this package should not be aware of the cluster label key. this package just implements docker functionality |
||
networkName, | ||
tao12345666333 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
return cmd.Run() | ||
} | ||
|
||
// DeleteNetwork delete the special network | ||
func DeleteNetwork(networkName string) error { | ||
cmd := exec.Command( | ||
"docker", "network", | ||
"rm", | ||
networkName, | ||
) | ||
return cmd.Run() | ||
} | ||
|
||
// IsNetworkExist check if the network exist | ||
func IsNetworkExist(networkName string) bool { | ||
cmd := exec.Command( | ||
"docker", "network", | ||
"inspect", | ||
networkName, | ||
) | ||
if err := cmd.Run(); err != nil { | ||
return false | ||
} | ||
|
||
return true | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#273 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(this config field name is not suitable, we need to separate docker specific functionality and make that clear)