Skip to content

Commit 7d7ba8b

Browse files
author
Kubernetes Submit Queue
authored
Merge pull request kubernetes#39442 from deads2k/generic-08-client-go-01
Automatic merge from submit-queue switch webhook to clientgo Switches the delegating authentication and authorization webhooks to use client-go. The ripples go out aways, but I kept it as contained as I could. @sttts
2 parents 6f32006 + 1df5b65 commit 7d7ba8b

File tree

24 files changed

+314
-142
lines changed

24 files changed

+314
-142
lines changed

cmd/kubelet/app/BUILD

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,28 @@ load(
88
"go_test",
99
)
1010

11+
go_test(
12+
name = "go_default_test",
13+
srcs = [
14+
"bootstrap_test.go",
15+
"server_test.go",
16+
],
17+
library = ":go_default_library",
18+
tags = ["automanaged"],
19+
deps = [
20+
"//pkg/client/restclient:go_default_library",
21+
"//pkg/kubelet:go_default_library",
22+
"//pkg/util/config:go_default_library",
23+
"//pkg/util/diff:go_default_library",
24+
],
25+
)
26+
1127
go_library(
1228
name = "go_default_library",
1329
srcs = [
1430
"auth.go",
1531
"bootstrap.go",
32+
"clientgo.go",
1633
"plugins.go",
1734
"server.go",
1835
"server_linux.go",
@@ -28,8 +45,6 @@ go_library(
2845
"//pkg/capabilities:go_default_library",
2946
"//pkg/client/chaosclient:go_default_library",
3047
"//pkg/client/clientset_generated/clientset:go_default_library",
31-
"//pkg/client/clientset_generated/clientset/typed/authentication/v1beta1:go_default_library",
32-
"//pkg/client/clientset_generated/clientset/typed/authorization/v1beta1:go_default_library",
3348
"//pkg/client/clientset_generated/clientset/typed/certificates/v1alpha1:go_default_library",
3449
"//pkg/client/clientset_generated/clientset/typed/core/v1:go_default_library",
3550
"//pkg/client/record:go_default_library",
@@ -101,22 +116,13 @@ go_library(
101116
"//vendor:k8s.io/apiserver/pkg/authentication/authenticator",
102117
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
103118
"//vendor:k8s.io/apiserver/pkg/healthz",
104-
],
105-
)
106-
107-
go_test(
108-
name = "go_default_test",
109-
srcs = [
110-
"bootstrap_test.go",
111-
"server_test.go",
112-
],
113-
library = ":go_default_library",
114-
tags = ["automanaged"],
115-
deps = [
116-
"//pkg/client/restclient:go_default_library",
117-
"//pkg/kubelet:go_default_library",
118-
"//pkg/util/config:go_default_library",
119-
"//pkg/util/diff:go_default_library",
119+
"//vendor:k8s.io/client-go/kubernetes",
120+
"//vendor:k8s.io/client-go/kubernetes/typed/authentication/v1beta1",
121+
"//vendor:k8s.io/client-go/kubernetes/typed/authorization/v1beta1",
122+
"//vendor:k8s.io/client-go/rest",
123+
"//vendor:k8s.io/client-go/tools/auth",
124+
"//vendor:k8s.io/client-go/tools/clientcmd",
125+
"//vendor:k8s.io/client-go/tools/clientcmd/api",
120126
],
121127
)
122128

cmd/kubelet/app/auth.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ import (
2323

2424
"k8s.io/apiserver/pkg/authentication/authenticator"
2525
"k8s.io/apiserver/pkg/authorization/authorizer"
26+
clientset "k8s.io/client-go/kubernetes"
27+
authenticationclient "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
28+
authorizationclient "k8s.io/client-go/kubernetes/typed/authorization/v1beta1"
29+
2630
"k8s.io/kubernetes/pkg/apis/componentconfig"
27-
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
28-
authenticationclient "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/authentication/v1beta1"
29-
authorizationclient "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/authorization/v1beta1"
3031
apiserverauthenticator "k8s.io/kubernetes/pkg/genericapiserver/authenticator"
3132
alwaysallowauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer"
3233
apiserverauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer"

cmd/kubelet/app/clientgo.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
Copyright 2017 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+
// this file contains parallel methods for getting a client-go clientconfig
18+
// The types are not reasonably compatibly between the client-go and kubernetes restclient.Interface,
19+
// restclient.Config, or typed clients, so this is the simplest solution during the transition
20+
package app
21+
22+
import (
23+
"fmt"
24+
"net/http"
25+
26+
"github.com/golang/glog"
27+
28+
"k8s.io/client-go/rest"
29+
clientauth "k8s.io/client-go/tools/auth"
30+
"k8s.io/client-go/tools/clientcmd"
31+
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
32+
33+
"k8s.io/kubernetes/cmd/kubelet/app/options"
34+
"k8s.io/kubernetes/pkg/client/chaosclient"
35+
)
36+
37+
func kubeconfigClientGoConfig(s *options.KubeletServer) (*rest.Config, error) {
38+
if s.RequireKubeConfig {
39+
// Ignores the values of s.APIServerList
40+
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
41+
&clientcmd.ClientConfigLoadingRules{ExplicitPath: s.KubeConfig.Value()},
42+
&clientcmd.ConfigOverrides{},
43+
).ClientConfig()
44+
}
45+
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
46+
&clientcmd.ClientConfigLoadingRules{ExplicitPath: s.KubeConfig.Value()},
47+
&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: s.APIServerList[0]}},
48+
).ClientConfig()
49+
}
50+
51+
// createClientConfig creates a client configuration from the command line
52+
// arguments. If --kubeconfig is explicitly set, it will be used. If it is
53+
// not set, we attempt to load the default kubeconfig file, and if we cannot,
54+
// we fall back to the default client with no auth - this fallback does not, in
55+
// and of itself, constitute an error.
56+
func createClientGoConfig(s *options.KubeletServer) (*rest.Config, error) {
57+
if s.RequireKubeConfig {
58+
return kubeconfigClientGoConfig(s)
59+
}
60+
61+
// TODO: handle a new --standalone flag that bypasses kubeconfig loading and returns no error.
62+
// DEPRECATED: all subsequent code is deprecated
63+
if len(s.APIServerList) == 0 {
64+
return nil, fmt.Errorf("no api servers specified")
65+
}
66+
// TODO: adapt Kube client to support LB over several servers
67+
if len(s.APIServerList) > 1 {
68+
glog.Infof("Multiple api servers specified. Picking first one")
69+
}
70+
71+
if s.KubeConfig.Provided() {
72+
return kubeconfigClientGoConfig(s)
73+
}
74+
// If KubeConfig was not provided, try to load the default file, then fall back
75+
// to a default auth config.
76+
clientConfig, err := kubeconfigClientGoConfig(s)
77+
if err != nil {
78+
glog.Warningf("Could not load kubeconfig file %s: %v. Using default client config instead.", s.KubeConfig, err)
79+
80+
authInfo := &clientauth.Info{}
81+
authConfig, err := authInfo.MergeWithConfig(rest.Config{})
82+
if err != nil {
83+
return nil, err
84+
}
85+
authConfig.Host = s.APIServerList[0]
86+
clientConfig = &authConfig
87+
}
88+
return clientConfig, nil
89+
}
90+
91+
// createAPIServerClientGoConfig generates a client.Config from command line flags,
92+
// including api-server-list, via createClientConfig and then injects chaos into
93+
// the configuration via addChaosToClientConfig. This func is exported to support
94+
// integration with third party kubelet extensions (e.g. kubernetes-mesos).
95+
func createAPIServerClientGoConfig(s *options.KubeletServer) (*rest.Config, error) {
96+
clientConfig, err := createClientGoConfig(s)
97+
if err != nil {
98+
return nil, err
99+
}
100+
101+
clientConfig.ContentType = s.ContentType
102+
// Override kubeconfig qps/burst settings from flags
103+
clientConfig.QPS = float32(s.KubeAPIQPS)
104+
clientConfig.Burst = int(s.KubeAPIBurst)
105+
106+
addChaosToClientGoConfig(s, clientConfig)
107+
return clientConfig, nil
108+
}
109+
110+
// addChaosToClientConfig injects random errors into client connections if configured.
111+
func addChaosToClientGoConfig(s *options.KubeletServer, config *rest.Config) {
112+
if s.ChaosChance != 0.0 {
113+
config.WrapTransport = func(rt http.RoundTripper) http.RoundTripper {
114+
seed := chaosclient.NewSeed(1)
115+
// TODO: introduce a standard chaos package with more tunables - this is just a proof of concept
116+
// TODO: introduce random latency and stalls
117+
return chaosclient.NewChaosRoundTripper(rt, chaosclient.LogChaos, seed.P(s.ChaosChance, chaosclient.ErrSimulatedConnectionResetByPeer))
118+
}
119+
}
120+
}

cmd/kubelet/app/server.go

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ import (
3737
"github.com/spf13/pflag"
3838

3939
"k8s.io/apiserver/pkg/healthz"
40+
clientgoclientset "k8s.io/client-go/kubernetes"
41+
4042
"k8s.io/kubernetes/cmd/kubelet/app/options"
4143
"k8s.io/kubernetes/pkg/api"
4244
"k8s.io/kubernetes/pkg/api/v1"
@@ -137,19 +139,20 @@ func UnsecuredKubeletDeps(s *options.KubeletServer) (*kubelet.KubeletDeps, error
137139
}
138140

139141
return &kubelet.KubeletDeps{
140-
Auth: nil, // default does not enforce auth[nz]
141-
CAdvisorInterface: nil, // cadvisor.New launches background processes (bg http.ListenAndServe, and some bg cleaners), not set here
142-
Cloud: nil, // cloud provider might start background processes
143-
ContainerManager: nil,
144-
DockerClient: dockerClient,
145-
KubeClient: nil,
146-
Mounter: mounter,
147-
NetworkPlugins: ProbeNetworkPlugins(s.NetworkPluginDir, s.CNIConfDir, s.CNIBinDir),
148-
OOMAdjuster: oom.NewOOMAdjuster(),
149-
OSInterface: kubecontainer.RealOS{},
150-
Writer: writer,
151-
VolumePlugins: ProbeVolumePlugins(s.VolumePluginDir),
152-
TLSOptions: tlsOptions,
142+
Auth: nil, // default does not enforce auth[nz]
143+
CAdvisorInterface: nil, // cadvisor.New launches background processes (bg http.ListenAndServe, and some bg cleaners), not set here
144+
Cloud: nil, // cloud provider might start background processes
145+
ContainerManager: nil,
146+
DockerClient: dockerClient,
147+
KubeClient: nil,
148+
ExternalKubeClient: nil,
149+
Mounter: mounter,
150+
NetworkPlugins: ProbeNetworkPlugins(s.NetworkPluginDir, s.CNIConfDir, s.CNIBinDir),
151+
OOMAdjuster: oom.NewOOMAdjuster(),
152+
OSInterface: kubecontainer.RealOS{},
153+
Writer: writer,
154+
VolumePlugins: ProbeVolumePlugins(s.VolumePluginDir),
155+
TLSOptions: tlsOptions,
153156
}, nil
154157
}
155158

@@ -359,6 +362,7 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.KubeletDeps) (err error) {
359362

360363
if kubeDeps == nil {
361364
var kubeClient, eventClient *clientset.Clientset
365+
var externalKubeClient clientgoclientset.Interface
362366
var cloud cloudprovider.Interface
363367

364368
if s.CloudProvider != componentconfigv1alpha1.AutoDetectCloudProvider {
@@ -406,13 +410,35 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.KubeletDeps) (err error) {
406410
}
407411
}
408412

413+
// client-go and kuberenetes generated clients are incompatible because the runtime
414+
// and runtime/serializer types have been duplicated in client-go. This means that
415+
// you can't reasonably convert from one to the other and its impossible for a single
416+
// type to fulfill both interfaces. Because of that, we have to build the clients
417+
// up from scratch twice.
418+
// TODO eventually the kubelet should only use the client-go library
419+
clientGoConfig, err := createAPIServerClientGoConfig(s)
420+
if err == nil {
421+
externalKubeClient, err = clientgoclientset.NewForConfig(clientGoConfig)
422+
if err != nil {
423+
glog.Warningf("New kubeClient from clientConfig error: %v", err)
424+
}
425+
} else {
426+
if s.RequireKubeConfig {
427+
return fmt.Errorf("invalid kubeconfig: %v", err)
428+
}
429+
if standaloneMode {
430+
glog.Warningf("No API client: %v", err)
431+
}
432+
}
433+
409434
kubeDeps, err = UnsecuredKubeletDeps(s)
410435
if err != nil {
411436
return err
412437
}
413438

414439
kubeDeps.Cloud = cloud
415440
kubeDeps.KubeClient = kubeClient
441+
kubeDeps.ExternalKubeClient = externalKubeClient
416442
kubeDeps.EventClient = eventClient
417443
}
418444

@@ -421,7 +447,8 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.KubeletDeps) (err error) {
421447
if err != nil {
422448
return err
423449
}
424-
auth, err := buildAuth(nodeName, kubeDeps.KubeClient, s.KubeletConfiguration)
450+
451+
auth, err := buildAuth(nodeName, kubeDeps.ExternalKubeClient, s.KubeletConfiguration)
425452
if err != nil {
426453
return err
427454
}

0 commit comments

Comments
 (0)