Skip to content

Commit 9a5d164

Browse files
authored
Merge pull request #6939 from mikesplain/automated-cherry-pick-of-#6890-#6893-#6898-origin-release-1.14
Automated cherry pick of #6890: Fix machine types with klog #6893: /etc/hosts (gossip): Stronger logic #6898: Add i3en
2 parents 3cf570d + 1b3e2ab commit 9a5d164

File tree

6 files changed

+327
-11
lines changed

6 files changed

+327
-11
lines changed

hack/machine_types/machine_types.go

-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ func main() {
4141
flag.StringVar(&outputPath, "out", outputPath, "file to write")
4242

4343
flag.Parse()
44-
flag.Lookup("logtostderr").Value.Set("true")
4544

4645
if err := run(); err != nil {
4746
fmt.Fprintf(os.Stderr, "%v\n", err)

hack/machine_types/vpc_ip_resource_limit.go

+14
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ var InstanceENIsAvailable = map[string]int{
9898
"i3.8xlarge": 8,
9999
"i3.16xlarge": 15,
100100
"i3.metal": 15,
101+
"i3en.large": 3,
102+
"i3en.xlarge": 4,
103+
"i3en.2xlarge": 4,
104+
"i3en.3xlarge": 4,
105+
"i3en.6xlarge": 8,
106+
"i3en.12xlarge": 8,
107+
"i3en.24xlarge": 15,
101108
"m1.small": 2,
102109
"m1.medium": 2,
103110
"m1.large": 3,
@@ -296,6 +303,13 @@ var InstanceIPsAvailable = map[string]int64{
296303
"i3.8xlarge": 30,
297304
"i3.16xlarge": 50,
298305
"i3.metal": 50,
306+
"i3en.large": 10,
307+
"i3en.xlarge": 15,
308+
"i3en.2xlarge": 15,
309+
"i3en.3xlarge": 15,
310+
"i3en.6xlarge": 30,
311+
"i3en.12xlarge": 30,
312+
"i3en.24xlarge": 50,
299313
"m1.small": 4,
300314
"m1.medium": 6,
301315
"m1.large": 10,
+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
load("@io_bazel_rules_go//go:def.bzl", "go_library")
1+
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
22

33
go_library(
44
name = "go_default_library",
@@ -7,3 +7,10 @@ go_library(
77
visibility = ["//visibility:public"],
88
deps = ["//vendor/k8s.io/klog:go_default_library"],
99
)
10+
11+
go_test(
12+
name = "go_default_test",
13+
srcs = ["hosts_test.go"],
14+
embed = [":go_default_library"],
15+
deps = ["//pkg/diff:go_default_library"],
16+
)

protokube/pkg/gossip/dns/hosts/hosts.go

+75-9
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,30 @@ limitations under the License.
1717
package hosts
1818

1919
import (
20+
"bytes"
2021
"fmt"
2122
"io/ioutil"
23+
math_rand "math/rand"
2224
"os"
2325
"path/filepath"
2426
"sort"
2527
"strings"
28+
"sync"
29+
"time"
2630

2731
"k8s.io/klog"
2832
)
2933

3034
const GUARD_BEGIN = "# Begin host entries managed by kops - do not edit"
3135
const GUARD_END = "# End host entries managed by kops"
3236

37+
var hostsFileMutex sync.Mutex
38+
3339
func UpdateHostsFileWithRecords(p string, addrToHosts map[string][]string) error {
40+
// For safety / sanity, we avoid concurrent updates from one process
41+
hostsFileMutex.Lock()
42+
defer hostsFileMutex.Unlock()
43+
3444
stat, err := os.Stat(p)
3545
if err != nil {
3646
return fmt.Errorf("error getting file status of %q: %v", p, err)
@@ -42,19 +52,28 @@ func UpdateHostsFileWithRecords(p string, addrToHosts map[string][]string) error
4252
}
4353

4454
var out []string
45-
depth := 0
55+
inGuardBlock := false
4656
for _, line := range strings.Split(string(data), "\n") {
4757
k := strings.TrimSpace(line)
4858
if k == GUARD_BEGIN {
49-
depth++
59+
if inGuardBlock {
60+
klog.Warningf("/etc/hosts guard-block begin seen while in guard block; will ignore")
61+
}
62+
inGuardBlock = true
5063
}
5164

52-
if depth <= 0 {
65+
if !inGuardBlock {
5366
out = append(out, line)
5467
}
5568

5669
if k == GUARD_END {
57-
depth--
70+
if !inGuardBlock {
71+
klog.Warningf("/etc/hosts guard-block end seen before guard-block start; will ignore end")
72+
// Don't output the line
73+
out = out[:len(out)-1]
74+
}
75+
76+
inGuardBlock = false
5877
}
5978
}
6079

@@ -72,25 +91,72 @@ func UpdateHostsFileWithRecords(p string, addrToHosts map[string][]string) error
7291
}
7392
out = append(out, "")
7493

75-
out = append(out, GUARD_BEGIN)
94+
var block []string
7695
for addr, hosts := range addrToHosts {
7796
sort.Strings(hosts)
78-
out = append(out, addr+"\t"+strings.Join(hosts, " "))
97+
block = append(block, addr+"\t"+strings.Join(hosts, " "))
7998
}
99+
// Sort into a consistent order to minimize updates
100+
sort.Strings(block)
101+
102+
out = append(out, GUARD_BEGIN)
103+
out = append(out, block...)
80104
out = append(out, GUARD_END)
81105
out = append(out, "")
82106

107+
updated := []byte(strings.Join(out, "\n"))
108+
109+
if bytes.Equal(updated, data) {
110+
klog.V(2).Infof("skipping update of unchanged /etc/hosts")
111+
return nil
112+
}
113+
83114
// Note that because we are bind mounting /etc/hosts, we can't do a normal atomic file write
84115
// (where we write a temp file and rename it)
85-
// TODO: We should just hold the file open while we read & write it
86-
err = ioutil.WriteFile(p, []byte(strings.Join(out, "\n")), stat.Mode().Perm())
87-
if err != nil {
116+
if err := pseudoAtomicWrite(p, updated, stat.Mode()); err != nil {
88117
return fmt.Errorf("error writing file %q: %v", p, err)
89118
}
90119

91120
return nil
92121
}
93122

123+
// Because we are bind-mounting /etc/hosts, we can't do a normal
124+
// atomic file write (where we write a temp file and rename it);
125+
// instead we write the file, pause, re-read and see if anyone else
126+
// wrote in the meantime; if so we rewrite again. By pausing for a
127+
// random amount of time, eventually we'll win the write race and
128+
// exit. This doesn't guarantee fairness, but it should mean that the
129+
// end-result is not malformed (i.e. partial writes).
130+
func pseudoAtomicWrite(p string, b []byte, mode os.FileMode) error {
131+
attempt := 0
132+
for {
133+
attempt++
134+
if attempt > 10 {
135+
return fmt.Errorf("failed to consistently write file %q - too many retries", p)
136+
}
137+
138+
if err := ioutil.WriteFile(p, b, mode); err != nil {
139+
klog.Warningf("error writing file %q: %v", p, err)
140+
continue
141+
}
142+
143+
n := 1 + math_rand.Intn(20)
144+
time.Sleep(time.Duration(n) * time.Millisecond)
145+
146+
contents, err := ioutil.ReadFile(p)
147+
if err != nil {
148+
klog.Warningf("error re-reading file %q: %v", p, err)
149+
continue
150+
}
151+
152+
if bytes.Equal(contents, b) {
153+
return nil
154+
}
155+
156+
klog.Warningf("detected concurrent write to file %q, will retry", p)
157+
}
158+
}
159+
94160
func atomicWriteFile(filename string, data []byte, perm os.FileMode) error {
95161
dir := filepath.Dir(filename)
96162

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package hosts
18+
19+
import (
20+
"io/ioutil"
21+
"os"
22+
"path/filepath"
23+
"strings"
24+
"testing"
25+
26+
"k8s.io/kops/pkg/diff"
27+
)
28+
29+
func TestRemovesDuplicateGuardedBlocks(t *testing.T) {
30+
in := `
31+
foo 10.2.3.4
32+
33+
# Begin host entries managed by etcd-manager[etcd] - do not edit
34+
# End host entries managed by etcd-manager[etcd]
35+
# Begin host entries managed by etcd-manager[etcd] - do not edit
36+
# End host entries managed by etcd-manager[etcd]
37+
# Begin host entries managed by kops - do not edit
38+
# End host entries managed by kops
39+
# Begin host entries managed by kops - do not edit
40+
# End host entries managed by kops
41+
# Begin host entries managed by kops - do not edit
42+
# End host entries managed by kops
43+
# Begin host entries managed by kops - do not edit
44+
# End host entries managed by kops
45+
# Begin host entries managed by kops - do not edit
46+
# End host entries managed by kops
47+
# Begin host entries managed by kops - do not edit
48+
# End host entries managed by kops
49+
# Begin host entries managed by kops - do not edit
50+
# End host entries managed by kops
51+
# Begin host entries managed by kops - do not edit
52+
# End host entries managed by kops
53+
`
54+
55+
expected := `
56+
foo 10.2.3.4
57+
58+
# Begin host entries managed by etcd-manager[etcd] - do not edit
59+
# End host entries managed by etcd-manager[etcd]
60+
# Begin host entries managed by etcd-manager[etcd] - do not edit
61+
# End host entries managed by etcd-manager[etcd]
62+
63+
# Begin host entries managed by kops - do not edit
64+
a\t10.0.1.1 10.0.1.2
65+
b\t10.0.2.1
66+
c\t
67+
# End host entries managed by kops
68+
`
69+
70+
runTest(t, in, expected)
71+
}
72+
73+
func TestRecoversFromBadNesting(t *testing.T) {
74+
in := `
75+
foo 10.2.3.4
76+
77+
# End host entries managed by kops
78+
# Begin host entries managed by kops - do not edit
79+
# Begin host entries managed by kops - do not edit
80+
# End host entries managed by kops
81+
# End host entries managed by kops
82+
# End host entries managed by kops
83+
# Begin host entries managed by kops - do not edit
84+
# End host entries managed by kops
85+
# Begin host entries managed by kops - do not edit
86+
# End host entries managed by kops
87+
# Begin host entries managed by kops - do not edit
88+
# End host entries managed by kops
89+
# Begin host entries managed by kops - do not edit
90+
# Begin host entries managed by kops - do not edit
91+
# Begin host entries managed by kops - do not edit
92+
# Begin host entries managed by kops - do not edit
93+
# End host entries managed by kops
94+
# Begin host entries managed by kops - do not edit
95+
# End host entries managed by kops
96+
97+
bar 10.1.2.3
98+
`
99+
100+
expected := `
101+
foo 10.2.3.4
102+
103+
104+
bar 10.1.2.3
105+
106+
# Begin host entries managed by kops - do not edit
107+
a\t10.0.1.1 10.0.1.2
108+
b\t10.0.2.1
109+
c\t
110+
# End host entries managed by kops
111+
`
112+
113+
runTest(t, in, expected)
114+
}
115+
116+
func runTest(t *testing.T, in string, expected string) {
117+
expected = strings.Replace(expected, "\\t", "\t", -1)
118+
119+
dir, err := ioutil.TempDir("", "")
120+
if err != nil {
121+
t.Fatalf("error creating temp dir: %v", err)
122+
}
123+
defer func() {
124+
err := os.RemoveAll(dir)
125+
if err != nil {
126+
t.Errorf("failed to remove temp dir %q: %v", dir, err)
127+
}
128+
}()
129+
130+
p := filepath.Join(dir, "hosts")
131+
addrToHosts := map[string][]string{
132+
"a": {"10.0.1.2", "10.0.1.1"},
133+
"b": {"10.0.2.1"},
134+
"c": {},
135+
}
136+
137+
if err := ioutil.WriteFile(p, []byte(in), 0755); err != nil {
138+
t.Fatalf("error writing hosts file: %v", err)
139+
}
140+
141+
// We run it repeatedly to make sure we don't change it accidentally
142+
for i := 0; i < 100; i++ {
143+
if err := UpdateHostsFileWithRecords(p, addrToHosts); err != nil {
144+
t.Fatalf("error updating hosts file: %v", err)
145+
}
146+
147+
b, err := ioutil.ReadFile(p)
148+
if err != nil {
149+
t.Fatalf("error reading output file: %v", err)
150+
}
151+
152+
actual := string(b)
153+
if actual != expected {
154+
diffString := diff.FormatDiff(expected, actual)
155+
t.Logf("diff:\n%s\n", diffString)
156+
t.Errorf("unexpected output. expected=%q, actual=%q", expected, actual)
157+
}
158+
}
159+
}

0 commit comments

Comments
 (0)