* Remove use of failing config proxy and retry proxy in loops
* Argument refactor to kubelets
... | ... |
@@ -8,7 +8,7 @@ import ( |
8 | 8 |
"os" |
9 | 9 |
"os/exec" |
10 | 10 |
"path/filepath" |
11 |
- "reflect" |
|
11 |
+ "strings" |
|
12 | 12 |
"time" |
13 | 13 |
|
14 | 14 |
kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" |
... | ... |
@@ -31,7 +31,6 @@ import ( |
31 | 31 |
cmdutil "github.com/openshift/origin/pkg/cmd/util" |
32 | 32 |
dockerutil "github.com/openshift/origin/pkg/cmd/util/docker" |
33 | 33 |
"github.com/openshift/origin/pkg/kubelet/app" |
34 |
- "github.com/openshift/origin/pkg/service" |
|
35 | 34 |
) |
36 | 35 |
|
37 | 36 |
type commandExecutor interface { |
... | ... |
@@ -220,6 +219,8 @@ func (c *NodeConfig) RunKubelet() { |
220 | 220 |
"docker", |
221 | 221 |
mount.New(), |
222 | 222 |
"", // docker daemon container |
223 |
+ false, |
|
224 |
+ 200, |
|
223 | 225 |
) |
224 | 226 |
if err != nil { |
225 | 227 |
glog.Fatalf("Couldn't run kubelet: %s", err) |
... | ... |
@@ -263,12 +264,6 @@ func (c *NodeConfig) RunProxy() { |
263 | 263 |
// initialize kube proxy |
264 | 264 |
serviceConfig := pconfig.NewServiceConfig() |
265 | 265 |
endpointsConfig := pconfig.NewEndpointsConfig() |
266 |
- pconfig.NewSourceAPI( |
|
267 |
- c.Client.Services(kapi.NamespaceAll), |
|
268 |
- c.Client.Endpoints(kapi.NamespaceAll), |
|
269 |
- 30*time.Second, |
|
270 |
- serviceConfig.Channel("api"), |
|
271 |
- endpointsConfig.Channel("api")) |
|
272 | 266 |
loadBalancer := proxy.NewLoadBalancerRR() |
273 | 267 |
endpointsConfig.RegisterHandler(loadBalancer) |
274 | 268 |
|
... | ... |
@@ -286,15 +281,39 @@ func (c *NodeConfig) RunProxy() { |
286 | 286 |
protocol = iptables.ProtocolIpv6 |
287 | 287 |
} |
288 | 288 |
|
289 |
- var proxier pconfig.ServiceConfigHandler |
|
290 |
- proxier = proxy.NewProxier(loadBalancer, ip, iptables.New(kexec.New(), protocol)) |
|
291 |
- if proxier == nil || reflect.ValueOf(proxier).IsNil() { // explicitly declared interfaces aren't plain nil, you must reflect inside to see if it's really nil or not |
|
292 |
- glog.Errorf("WARNING: Could not modify iptables. iptables must be mutable by this process to use services. Do you have root permissions?") |
|
293 |
- proxier = &service.FailingServiceConfigProxy{} |
|
294 |
- } |
|
295 |
- serviceConfig.RegisterHandler(proxier) |
|
289 |
+ go util.Forever(func() { |
|
290 |
+ proxier, err := proxy.NewProxier(loadBalancer, ip, iptables.New(kexec.New(), protocol)) |
|
291 |
+ if err != nil { |
|
292 |
+ switch { |
|
293 |
+ // conflicting use of iptables, retry |
|
294 |
+ case proxy.IsProxyLocked(err): |
|
295 |
+ glog.Errorf("Unable to start proxy, will retry: %v", err) |
|
296 |
+ return |
|
297 |
+ // on a system without iptables |
|
298 |
+ case strings.Contains(err.Error(), "executable file not found in path"): |
|
299 |
+ glog.V(4).Infof("kube-proxy initialization error: %v", err) |
|
300 |
+ glog.Warningf("WARNING: Could not find the iptables command. The service proxy requires iptables and will be disabled.") |
|
301 |
+ case err == proxy.ErrProxyOnLocalhost: |
|
302 |
+ glog.Warningf("WARNING: The service proxy cannot bind to localhost and will be disabled.") |
|
303 |
+ case strings.Contains(err.Error(), "you must be root"): |
|
304 |
+ glog.Warningf("WARNING: Could not modify iptables. You must run this process as root to use the service proxy.") |
|
305 |
+ default: |
|
306 |
+ glog.Warningf("WARNING: Could not modify iptables. You must run this process as root to use the service proxy: %v", err) |
|
307 |
+ } |
|
308 |
+ select {} |
|
309 |
+ } |
|
296 | 310 |
|
297 |
- glog.Infof("Started Kubernetes Proxy on %s", host) |
|
311 |
+ pconfig.NewSourceAPI( |
|
312 |
+ c.Client.Services(kapi.NamespaceAll), |
|
313 |
+ c.Client.Endpoints(kapi.NamespaceAll), |
|
314 |
+ 30*time.Second, |
|
315 |
+ serviceConfig.Channel("api"), |
|
316 |
+ endpointsConfig.Channel("api")) |
|
317 |
+ |
|
318 |
+ serviceConfig.RegisterHandler(proxier) |
|
319 |
+ glog.Infof("Started Kubernetes Proxy on %s", host) |
|
320 |
+ select {} |
|
321 |
+ }, 5*time.Second) |
|
298 | 322 |
} |
299 | 323 |
|
300 | 324 |
// TODO: more generic location |
... | ... |
@@ -218,7 +218,7 @@ func TestValidateImageStream(t *testing.T) { |
218 | 218 |
namespace: "!$", |
219 | 219 |
name: "foo", |
220 | 220 |
expected: fielderrors.ValidationErrorList{ |
221 |
- fielderrors.NewFieldInvalid("metadata.namespace", "!$", `must have at most 253 characters and match regex [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*`), |
|
221 |
+ fielderrors.NewFieldInvalid("metadata.namespace", "!$", `must be a DNS subdomain (at most 253 characters, matching regex [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*): e.g. "example.com"`), |
|
222 | 222 |
}, |
223 | 223 |
}, |
224 | 224 |
"invalid dockerImageRepository": { |
... | ... |
@@ -21,7 +21,7 @@ func (*UnknownObject) IsAnAPIObject() {} |
21 | 21 |
func TestIgnoreThatWhichCannotBeKnown(t *testing.T) { |
22 | 22 |
handler := &lifecycle{} |
23 | 23 |
unknown := &UnknownObject{} |
24 |
- err := handler.Admit(admission.NewAttributesRecord(unknown, "who-cares", "unknown", "what", "CREATE")) |
|
24 |
+ err := handler.Admit(admission.NewAttributesRecord(unknown, "who-cares", "unknown", "what", "CREATE", nil)) |
|
25 | 25 |
if err != nil { |
26 | 26 |
t.Errorf("Admission control should not error if it finds an object it knows nothing about %v", err) |
27 | 27 |
} |
... | ... |
@@ -54,7 +54,7 @@ func TestAdmissionExists(t *testing.T) { |
54 | 54 |
}, |
55 | 55 |
Status: buildapi.BuildStatusNew, |
56 | 56 |
} |
57 |
- err := handler.Admit(admission.NewAttributesRecord(build, "Build", "bogus-ns", "builds", "CREATE")) |
|
57 |
+ err := handler.Admit(admission.NewAttributesRecord(build, "Build", "bogus-ns", "builds", "CREATE", nil)) |
|
58 | 58 |
if err == nil { |
59 | 59 |
t.Errorf("Expected an error because namespace does not exist") |
60 | 60 |
} |
... | ... |
@@ -96,7 +96,7 @@ func TestAdmissionLifecycle(t *testing.T) { |
96 | 96 |
}, |
97 | 97 |
Status: buildapi.BuildStatusNew, |
98 | 98 |
} |
99 |
- err := handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "builds", "CREATE")) |
|
99 |
+ err := handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "builds", "CREATE", nil)) |
|
100 | 100 |
if err != nil { |
101 | 101 |
t.Errorf("Unexpected error returned from admission handler: %v", err) |
102 | 102 |
} |
... | ... |
@@ -106,19 +106,19 @@ func TestAdmissionLifecycle(t *testing.T) { |
106 | 106 |
store.Add(namespaceObj) |
107 | 107 |
|
108 | 108 |
// verify create operations in the namespace cause an error |
109 |
- err = handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "builds", "CREATE")) |
|
109 |
+ err = handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "builds", "CREATE", nil)) |
|
110 | 110 |
if err == nil { |
111 | 111 |
t.Errorf("Expected error rejecting creates in a namespace when it is terminating") |
112 | 112 |
} |
113 | 113 |
|
114 | 114 |
// verify update operations in the namespace can proceed |
115 |
- err = handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "builds", "UPDATE")) |
|
115 |
+ err = handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "builds", "UPDATE", nil)) |
|
116 | 116 |
if err != nil { |
117 | 117 |
t.Errorf("Unexpected error returned from admission handler: %v", err) |
118 | 118 |
} |
119 | 119 |
|
120 | 120 |
// verify delete operations in the namespace can proceed |
121 |
- err = handler.Admit(admission.NewAttributesRecord(nil, "Build", build.Namespace, "builds", "DELETE")) |
|
121 |
+ err = handler.Admit(admission.NewAttributesRecord(nil, "Build", build.Namespace, "builds", "DELETE", nil)) |
|
122 | 122 |
if err != nil { |
123 | 123 |
t.Errorf("Unexpected error returned from admission handler: %v", err) |
124 | 124 |
} |
... | ... |
@@ -99,7 +99,7 @@ func TestPodAdmission(t *testing.T) { |
99 | 99 |
project.ObjectMeta.Annotations = map[string]string{"openshift.io/node-selector": test.projectNodeSelector} |
100 | 100 |
pod.Spec = kapi.PodSpec{NodeSelector: test.podNodeSelector} |
101 | 101 |
|
102 |
- err := handler.Admit(admission.NewAttributesRecord(pod, "Pod", project.ObjectMeta.Name, "pods", "CREATE")) |
|
102 |
+ err := handler.Admit(admission.NewAttributesRecord(pod, "Pod", project.ObjectMeta.Name, "pods", "CREATE", nil)) |
|
103 | 103 |
if test.admit && err != nil { |
104 | 104 |
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) |
105 | 105 |
} else if !test.admit && err == nil { |
106 | 106 |
deleted file mode 100644 |
... | ... |
@@ -1,20 +0,0 @@ |
1 |
-package service |
|
2 |
- |
|
3 |
-import ( |
|
4 |
- "strings" |
|
5 |
- |
|
6 |
- "github.com/GoogleCloudPlatform/kubernetes/pkg/api" |
|
7 |
- "github.com/golang/glog" |
|
8 |
-) |
|
9 |
- |
|
10 |
-type FailingServiceConfigProxy struct { |
|
11 |
-} |
|
12 |
- |
|
13 |
-// OnUpdate implements method for kubernetes/pkg/proxy/config/ServiceConfigHandler |
|
14 |
-func (proxy *FailingServiceConfigProxy) OnUpdate(services []api.Service) { |
|
15 |
- names := []string{} |
|
16 |
- for i := range services { |
|
17 |
- names = append(names, services[i].Name) |
|
18 |
- } |
|
19 |
- glog.V(4).Infof("Failed to properly wire up services. This can happen if you forget to launch with permissions to iptables. Access to the following services will be impaired: %#v\n", strings.Join(names, ", ")) |
|
20 |
-} |