Skip to content
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

Automated cherry pick of #14889 #15224 #17127

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 28 additions & 9 deletions cmd/kube-apiserver/app/server.go
Expand Up @@ -387,6 +387,30 @@ func (s *APIServer) Run(_ []string) error {
glog.Fatalf("Cloud provider could not be initialized: %v", err)
}

// Setup tunneler if needed
var tunneler master.Tunneler
var proxyDialerFn apiserver.ProxyDialerFunc
if len(s.SSHUser) > 0 {
// Get ssh key distribution func, if supported
var installSSH master.InstallSSHKey
if cloud != nil {
if instances, supported := cloud.Instances(); supported {
installSSH = instances.AddSSHKeyToAllInstances
}
}

// Set up the tunneler
tunneler = master.NewSSHTunneler(s.SSHUser, s.SSHKeyfile, installSSH)

// Use the tunneler's dialer to connect to the kubelet
s.KubeletConfig.Dial = tunneler.Dial
// Use the tunneler's dialer when proxying to pods, services, and nodes
proxyDialerFn = tunneler.Dial
}

// Proxying to pods and services is IP-based... don't expect to be able to verify the hostname
proxyTLSClientConfig := &tls.Config{InsecureSkipVerify: true}

kubeletClient, err := client.NewKubeletClient(&s.KubeletConfig)
if err != nil {
glog.Fatalf("Failure to start kubelet client: %v", err)
Expand Down Expand Up @@ -500,12 +524,7 @@ func (s *APIServer) Run(_ []string) error {
}
}
}
var installSSH master.InstallSSHKey
if cloud != nil {
if instances, supported := cloud.Instances(); supported {
installSSH = instances.AddSSHKeyToAllInstances
}
}

config := &master.Config{
StorageDestinations: storageDestinations,
StorageVersions: storageVersions,
Expand Down Expand Up @@ -533,9 +552,9 @@ func (s *APIServer) Run(_ []string) error {
ClusterName: s.ClusterName,
ExternalHost: s.ExternalHost,
MinRequestTimeout: s.MinRequestTimeout,
SSHUser: s.SSHUser,
SSHKeyfile: s.SSHKeyfile,
InstallSSHKey: installSSH,
ProxyDialer: proxyDialerFn,
ProxyTLSClientConfig: proxyTLSClientConfig,
Tunneler: tunneler,
ServiceNodePortRange: s.ServiceNodePortRange,
}
m := master.New(config)
Expand Down
3 changes: 1 addition & 2 deletions pkg/apiserver/api_installer.go
Expand Up @@ -42,7 +42,6 @@ type APIInstaller struct {
info *APIRequestInfoResolver
prefix string // Path prefix where API resources are to be registered.
minRequestTimeout time.Duration
proxyDialerFn ProxyDialerFunc
}

// Struct capturing information about an action ("GET", "POST", "WATCH", PROXY", etc).
Expand All @@ -65,7 +64,7 @@ var errEmptyName = errors.NewBadRequest("name must be provided")
func (a *APIInstaller) Install(ws *restful.WebService) (apiResources []unversioned.APIResource, errors []error) {
errors = make([]error, 0)

proxyHandler := (&ProxyHandler{a.prefix + "/proxy/", a.group.Storage, a.group.Codec, a.group.Context, a.info, a.proxyDialerFn})
proxyHandler := (&ProxyHandler{a.prefix + "/proxy/", a.group.Storage, a.group.Codec, a.group.Context, a.info})

// Register the paths in a deterministic (sorted) order to get a deterministic swagger spec.
paths := make([]string, len(a.group.Storage))
Expand Down
2 changes: 0 additions & 2 deletions pkg/apiserver/apiserver.go
Expand Up @@ -102,7 +102,6 @@ type APIGroupVersion struct {
Admit admission.Interface
Context api.RequestContextMapper

ProxyDialerFn ProxyDialerFunc
MinRequestTimeout time.Duration
}

Expand Down Expand Up @@ -163,7 +162,6 @@ func (g *APIGroupVersion) newInstaller() *APIInstaller {
info: info,
prefix: prefix,
minRequestTimeout: g.MinRequestTimeout,
proxyDialerFn: g.ProxyDialerFn,
}
return installer
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/apiserver/apiserver_test.go
Expand Up @@ -326,6 +326,7 @@ type SimpleRESTStorage struct {
// The id requested, and location to return for ResourceLocation
requestedResourceLocationID string
resourceLocation *url.URL
resourceLocationTransport http.RoundTripper
expectedResourceNamespace string

// If non-nil, called inside the WorkFunc when answering update, delete, create.
Expand Down Expand Up @@ -471,7 +472,7 @@ func (storage *SimpleRESTStorage) ResourceLocation(ctx api.Context, id string) (
}
// Make a copy so the internal URL never gets mutated
locationCopy := *storage.resourceLocation
return &locationCopy, nil, nil
return &locationCopy, storage.resourceLocationTransport, nil
}

// Implement Connecter
Expand Down
50 changes: 3 additions & 47 deletions pkg/apiserver/proxy.go
Expand Up @@ -17,11 +17,8 @@ limitations under the License.
package apiserver

import (
"crypto/tls"
"fmt"
"io"
"math/rand"
"net"
"net/http"
"net/http/httputil"
"net/url"
Expand All @@ -40,7 +37,6 @@ import (
proxyutil "k8s.io/kubernetes/pkg/util/proxy"

"github.com/golang/glog"
"k8s.io/kubernetes/third_party/golang/netutil"
)

// ProxyHandler provides a http.Handler which will proxy traffic to locations
Expand All @@ -51,8 +47,6 @@ type ProxyHandler struct {
codec runtime.Codec
context api.RequestContextMapper
apiRequestInfoResolver *APIRequestInfoResolver

dial func(network, addr string) (net.Conn, error)
}

func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
Expand Down Expand Up @@ -125,11 +119,8 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
httpCode = http.StatusNotFound
return
}
// If we have a custom dialer, and no pre-existing transport, initialize it to use the dialer.
if roundTripper == nil && r.dial != nil {
glog.V(5).Infof("[%x: %v] making a dial-only transport...", proxyHandlerTraceID, req.URL)
roundTripper = &http.Transport{Dial: r.dial}
} else if roundTripper != nil {

if roundTripper != nil {
glog.V(5).Infof("[%x: %v] using transport %T...", proxyHandlerTraceID, req.URL, roundTripper)
}

Expand Down Expand Up @@ -217,7 +208,7 @@ func (r *ProxyHandler) tryUpgrade(w http.ResponseWriter, req, newReq *http.Reque
if !httpstream.IsUpgradeRequest(req) {
return false
}
backendConn, err := dialURL(location, transport)
backendConn, err := proxyutil.DialURL(location, transport)
if err != nil {
status := errToAPIStatus(err)
writeJSON(status.Code, r.codec, status, w, true)
Expand Down Expand Up @@ -264,41 +255,6 @@ func (r *ProxyHandler) tryUpgrade(w http.ResponseWriter, req, newReq *http.Reque
return true
}

func dialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) {
dialAddr := netutil.CanonicalAddr(url)

switch url.Scheme {
case "http":
return net.Dial("tcp", dialAddr)
case "https":
// Get the tls config from the transport if we recognize it
var tlsConfig *tls.Config
if transport != nil {
httpTransport, ok := transport.(*http.Transport)
if ok {
tlsConfig = httpTransport.TLSClientConfig
}
}

// Dial
tlsConn, err := tls.Dial("tcp", dialAddr, tlsConfig)
if err != nil {
return nil, err
}

// Verify
host, _, _ := net.SplitHostPort(dialAddr)
if err := tlsConn.VerifyHostname(host); err != nil {
tlsConn.Close()
return nil, err
}

return tlsConn, nil
default:
return nil, fmt.Errorf("Unknown scheme: %s", url.Scheme)
}
}

// borrowed from net/http/httputil/reverseproxy.go
func singleJoiningSlash(a, b string) string {
aslash := strings.HasSuffix(a, "/")
Expand Down