mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 10:20:51 +00:00
Configure the master to connect to the kubelet using HTTPS.
This commit is contained in:
parent
d0f48b68d8
commit
58bc792e68
@ -99,7 +99,7 @@ func NewAPIServer() *APIServer {
|
|||||||
RuntimeConfig: make(util.ConfigurationMap),
|
RuntimeConfig: make(util.ConfigurationMap),
|
||||||
KubeletConfig: client.KubeletConfig{
|
KubeletConfig: client.KubeletConfig{
|
||||||
Port: 10250,
|
Port: 10250,
|
||||||
EnableHttps: false,
|
EnableHttps: true,
|
||||||
HTTPTimeout: time.Duration(5) * time.Second,
|
HTTPTimeout: time.Duration(5) * time.Second,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ func NewCMServer() *CMServer {
|
|||||||
SyncNodeStatus: false,
|
SyncNodeStatus: false,
|
||||||
KubeletConfig: client.KubeletConfig{
|
KubeletConfig: client.KubeletConfig{
|
||||||
Port: ports.KubeletPort,
|
Port: ports.KubeletPort,
|
||||||
EnableHttps: false,
|
EnableHttps: true,
|
||||||
HTTPTimeout: time.Duration(5) * time.Second,
|
HTTPTimeout: time.Duration(5) * time.Second,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -139,14 +139,7 @@ func (g *APIGroupVersion) InstallREST(container *restful.Container) error {
|
|||||||
|
|
||||||
// TODO: Convert to go-restful
|
// TODO: Convert to go-restful
|
||||||
func InstallValidator(mux Mux, servers func() map[string]Server) {
|
func InstallValidator(mux Mux, servers func() map[string]Server) {
|
||||||
validator, err := NewValidator(servers)
|
mux.Handle("/validate", NewValidator(servers))
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("failed to set up validator: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if validator != nil {
|
|
||||||
mux.Handle("/validate", validator)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: document all handlers
|
// TODO: document all handlers
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package apiserver
|
package apiserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -34,21 +35,26 @@ type httpGet interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
Addr string
|
Addr string
|
||||||
Port int
|
Port int
|
||||||
Path string
|
Path string
|
||||||
|
EnableHTTPS bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// validator is responsible for validating the cluster and serving
|
// validator is responsible for validating the cluster and serving
|
||||||
type validator struct {
|
type validator struct {
|
||||||
// a list of servers to health check
|
// a list of servers to health check
|
||||||
servers func() map[string]Server
|
servers func() map[string]Server
|
||||||
client httpGet
|
rt http.RoundTripper
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: can this use pkg/probe/http
|
// TODO: can this use pkg/probe/http
|
||||||
func (s *Server) check(client httpGet) (probe.Result, string, error) {
|
func (s *Server) check(client httpGet) (probe.Result, string, error) {
|
||||||
resp, err := client.Get("http://" + net.JoinHostPort(s.Addr, strconv.Itoa(s.Port)) + s.Path)
|
scheme := "http://"
|
||||||
|
if s.EnableHTTPS {
|
||||||
|
scheme = "https://"
|
||||||
|
}
|
||||||
|
resp, err := client.Get(scheme + net.JoinHostPort(s.Addr, strconv.Itoa(s.Port)) + s.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return probe.Unknown, "", err
|
return probe.Unknown, "", err
|
||||||
}
|
}
|
||||||
@ -81,7 +87,22 @@ func (v *validator) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
reply := []ServerStatus{}
|
reply := []ServerStatus{}
|
||||||
for name, server := range v.servers() {
|
for name, server := range v.servers() {
|
||||||
status, msg, err := server.check(v.client)
|
transport := v.rt
|
||||||
|
if server.EnableHTTPS {
|
||||||
|
// TODO(roberthbailey): The servers that use HTTPS are currently the
|
||||||
|
// kubelets, and we should be using a standard kubelet client library
|
||||||
|
// to talk to them rather than a separate http client.
|
||||||
|
transport = &http.Transport{
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
Dial: (&net.Dialer{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
}).Dial,
|
||||||
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status, msg, err := server.check(&http.Client{Transport: transport})
|
||||||
var errorMsg string
|
var errorMsg string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorMsg = err.Error()
|
errorMsg = err.Error()
|
||||||
@ -103,30 +124,6 @@ func (v *validator) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewValidator creates a validator for a set of servers.
|
// NewValidator creates a validator for a set of servers.
|
||||||
func NewValidator(servers func() map[string]Server) (http.Handler, error) {
|
func NewValidator(servers func() map[string]Server) http.Handler {
|
||||||
return &validator{
|
return &validator{servers: servers, rt: http.DefaultTransport}
|
||||||
servers: servers,
|
|
||||||
client: &http.Client{},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeTestValidator(servers map[string]string, get httpGet) (http.Handler, error) {
|
|
||||||
result := map[string]Server{}
|
|
||||||
for name, value := range servers {
|
|
||||||
host, port, err := net.SplitHostPort(value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid server spec: %s (%v)", value, err)
|
|
||||||
}
|
|
||||||
val, err := strconv.Atoi(port)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid server spec: %s (%v)", port, err)
|
|
||||||
}
|
|
||||||
result[name] = Server{Addr: host, Port: val, Path: "/healthz"}
|
|
||||||
}
|
|
||||||
|
|
||||||
v, e := NewValidator(func() map[string]Server { return result })
|
|
||||||
if e == nil {
|
|
||||||
v.(*validator).client = get
|
|
||||||
}
|
|
||||||
return v, e
|
|
||||||
}
|
}
|
||||||
|
@ -21,35 +21,27 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/probe"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/probe"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fakeHttpGet struct {
|
type fakeRoundTripper struct {
|
||||||
err error
|
err error
|
||||||
resp *http.Response
|
resp *http.Response
|
||||||
url string
|
url string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *fakeHttpGet) Get(url string) (*http.Response, error) {
|
func (f *fakeRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
f.url = url
|
f.url = req.URL.String()
|
||||||
return f.resp, f.err
|
return f.resp, f.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeFake(data string, statusCode int, err error) *fakeHttpGet {
|
|
||||||
return &fakeHttpGet{
|
|
||||||
err: err,
|
|
||||||
resp: &http.Response{
|
|
||||||
Body: ioutil.NopCloser(bytes.NewBufferString(data)),
|
|
||||||
StatusCode: statusCode,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidate(t *testing.T) {
|
func TestValidate(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
err error
|
err error
|
||||||
@ -66,11 +58,18 @@ func TestValidate(t *testing.T) {
|
|||||||
s := Server{Addr: "foo.com", Port: 8080, Path: "/healthz"}
|
s := Server{Addr: "foo.com", Port: 8080, Path: "/healthz"}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
fake := makeFake(test.data, test.code, test.err)
|
fakeRT := &fakeRoundTripper{
|
||||||
|
err: test.err,
|
||||||
|
resp: &http.Response{
|
||||||
|
Body: ioutil.NopCloser(bytes.NewBufferString(test.data)),
|
||||||
|
StatusCode: test.code,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fake := &http.Client{Transport: fakeRT}
|
||||||
status, data, err := s.check(fake)
|
status, data, err := s.check(fake)
|
||||||
expect := fmt.Sprintf("http://%s:%d/healthz", s.Addr, s.Port)
|
expect := fmt.Sprintf("http://%s:%d/healthz", s.Addr, s.Port)
|
||||||
if fake.url != expect {
|
if fakeRT.url != expect {
|
||||||
t.Errorf("expected %s, got %s", expect, fake.url)
|
t.Errorf("expected %s, got %s", expect, fakeRT.url)
|
||||||
}
|
}
|
||||||
if test.expectErr && err == nil {
|
if test.expectErr && err == nil {
|
||||||
t.Errorf("unexpected non-error")
|
t.Errorf("unexpected non-error")
|
||||||
@ -87,8 +86,30 @@ func TestValidate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeTestValidator(servers map[string]string, rt http.RoundTripper) (http.Handler, error) {
|
||||||
|
result := map[string]Server{}
|
||||||
|
for name, value := range servers {
|
||||||
|
host, port, err := net.SplitHostPort(value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid server spec: %s (%v)", value, err)
|
||||||
|
}
|
||||||
|
val, err := strconv.Atoi(port)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid server spec: %s (%v)", port, err)
|
||||||
|
}
|
||||||
|
result[name] = Server{Addr: host, Port: val, Path: "/healthz"}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &validator{servers: func() map[string]Server { return result }, rt: rt}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestValidator(t *testing.T) {
|
func TestValidator(t *testing.T) {
|
||||||
fake := makeFake("foo", 200, nil)
|
fake := &fakeRoundTripper{
|
||||||
|
resp: &http.Response{
|
||||||
|
Body: ioutil.NopCloser(bytes.NewBufferString("foo")),
|
||||||
|
StatusCode: 200,
|
||||||
|
},
|
||||||
|
}
|
||||||
validator, err := makeTestValidator(map[string]string{
|
validator, err := makeTestValidator(map[string]string{
|
||||||
"foo": "foo.com:80",
|
"foo": "foo.com:80",
|
||||||
"bar": "bar.com:8080",
|
"bar": "bar.com:8080",
|
||||||
@ -101,7 +122,6 @@ func TestValidator(t *testing.T) {
|
|||||||
defer testServer.Close()
|
defer testServer.Close()
|
||||||
|
|
||||||
resp, err := http.Get(testServer.URL + "/validatez")
|
resp, err := http.Get(testServer.URL + "/validatez")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -113,13 +133,15 @@ func TestValidator(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
status := []ServerStatus{}
|
var status []ServerStatus
|
||||||
err = json.Unmarshal(data, &status)
|
if err := json.Unmarshal(data, &status); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
components := util.StringSet{}
|
components := util.StringSet{}
|
||||||
for _, s := range status {
|
for _, s := range status {
|
||||||
|
if s.Err != "nil" {
|
||||||
|
t.Errorf("Component %v is unhealthy: %v", s.Component, s.Err)
|
||||||
|
}
|
||||||
components.Insert(s.Component)
|
components.Insert(s.Component)
|
||||||
}
|
}
|
||||||
if len(status) != 2 || !components.Has("foo") || !components.Has("bar") {
|
if len(status) != 2 || !components.Has("foo") || !components.Has("bar") {
|
||||||
|
@ -75,9 +75,14 @@ type HTTPKubeletClient struct {
|
|||||||
func NewKubeletClient(config *KubeletConfig) (KubeletClient, error) {
|
func NewKubeletClient(config *KubeletConfig) (KubeletClient, error) {
|
||||||
transport := http.DefaultTransport
|
transport := http.DefaultTransport
|
||||||
|
|
||||||
tlsConfig, err := TLSConfigFor(&Config{
|
cfg := &Config{TLSClientConfig: config.TLSClientConfig}
|
||||||
TLSClientConfig: config.TLSClientConfig,
|
if config.EnableHttps {
|
||||||
})
|
hasCA := len(config.CAFile) > 0 || len(config.CAData) > 0
|
||||||
|
if !hasCA {
|
||||||
|
cfg.Insecure = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tlsConfig, err := TLSConfigFor(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -561,7 +561,7 @@ func (m *Master) getServersToValidate(c *Config) map[string]apiserver.Server {
|
|||||||
glog.Errorf("Failed to list minions: %v", err)
|
glog.Errorf("Failed to list minions: %v", err)
|
||||||
}
|
}
|
||||||
for ix, node := range nodes.Items {
|
for ix, node := range nodes.Items {
|
||||||
serversToValidate[fmt.Sprintf("node-%d", ix)] = apiserver.Server{Addr: node.Name, Port: ports.KubeletPort, Path: "/healthz"}
|
serversToValidate[fmt.Sprintf("node-%d", ix)] = apiserver.Server{Addr: node.Name, Port: ports.KubeletPort, Path: "/healthz", EnableHTTPS: true}
|
||||||
}
|
}
|
||||||
return serversToValidate
|
return serversToValidate
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user