From d0997a3d1fc30ea741916e078edb117ba48fee61 Mon Sep 17 00:00:00 2001 From: CJ Cullen Date: Fri, 18 Nov 2016 15:07:59 -0800 Subject: [PATCH 1/2] Generate a kubelet CA and kube-apiserver cert-pair for kubelet auth. Plumb through to kubelet/kube-apiserver on gci & cvm. --- cluster/common.sh | 22 +++++++++++- cluster/gce/configure-vm.sh | 35 +++++++++++++++++++ cluster/gce/debian/master-helper.sh | 2 +- cluster/gce/gci/configure-helper.sh | 20 +++++++++++ cluster/gce/gci/configure.sh | 19 ++++++++++ cluster/gce/gci/health-monitor.sh | 6 ++-- cluster/gce/gci/master-helper.sh | 2 +- .../kube-apiserver/kube-apiserver.manifest | 4 ++- cluster/saltbase/salt/kubelet/default | 7 +++- cluster/saltbase/salt/kubelet/init.sls | 13 +++++++ .../salt/supervisor/kubelet-checker.sh | 9 ++--- cmd/kube-apiserver/app/options/options.go | 6 +++- cmd/kube-apiserver/app/server.go | 7 ++-- pkg/kubelet/client/kubelet_client.go | 5 +-- 14 files changed, 137 insertions(+), 20 deletions(-) diff --git a/cluster/common.sh b/cluster/common.sh index d06e40eccd..7081bffc6a 100755 --- a/cluster/common.sh +++ b/cluster/common.sh @@ -555,6 +555,7 @@ function write-master-env { fi build-kube-env true "${KUBE_TEMP}/master-kube-env.yaml" + build-kube-master-certs "${KUBE_TEMP}/kube-master-certs.yaml" } function write-node-env { @@ -565,6 +566,15 @@ function write-node-env { build-kube-env false "${KUBE_TEMP}/node-kube-env.yaml" } +function build-kube-master-certs { + local file=$1 + rm -f ${file} + cat >$file <>$file <${cert_create_debug_output} || { + ./easyrsa build-client-full kubecfg nopass + cd ../kubelet + ./easyrsa init-pki + ./easyrsa --batch "--req-cn=kubelet@$(date +%s)" build-ca nopass + ./easyrsa build-client-full kube-apiserver nopass) &>${cert_create_debug_output} || { # If there was an error in the subshell, just die. # TODO(roberthbailey): add better error handling here cat "${cert_create_debug_output}" >&2 diff --git a/cluster/gce/configure-vm.sh b/cluster/gce/configure-vm.sh index 2e60c13046..26e3b802fe 100755 --- a/cluster/gce/configure-vm.sh +++ b/cluster/gce/configure-vm.sh @@ -142,6 +142,23 @@ for k,v in yaml.load(sys.stdin).iteritems(): ' < """${kube_env_yaml}""")" } +function set-kube-master-certs() { + local kube_master_certs_yaml="${INSTALL_DIR}/kube_master_certs.yaml" + + until curl-metadata kube-master-certs > "${kube_master_certs_yaml}"; do + echo 'Waiting for kube-master-certs...' + sleep 3 + done + + eval "$(python -c ' +import pipes,sys,yaml + +for k,v in yaml.load(sys.stdin).iteritems(): + print("""readonly {var}={value}""".format(var = k, value = pipes.quote(str(v)))) + print("""export {var}""".format(var = k)) + ' < """${kube_master_certs_yaml}""")" +} + function remove-docker-artifacts() { echo "== Deleting docker0 ==" apt-get-install bridge-utils @@ -613,6 +630,11 @@ EOF if [ -n "${SCHEDULING_ALGORITHM_PROVIDER:-}" ]; then cat <>/srv/salt-overlay/pillar/cluster-params.sls scheduling_algorithm_provider: '$(echo "${SCHEDULING_ALGORITHM_PROVIDER}" | sed -e "s/'/''/g")' +EOF + fi + if [ -n "${KUBELET_AUTH_CA_CERT:-}" ]; then + cat <>/srv/salt-overlay/pillar/cluster-params.sls +kubelet_auth_ca_cert: /var/lib/kubelet/kubelet_auth_ca.crt EOF fi } @@ -659,6 +681,13 @@ function create-salt-master-auth() { echo "${KUBECFG_KEY:-}" | base64 --decode > /srv/kubernetes/kubecfg.key) fi fi + if [ ! -e /srv/kubernetes/kubeapiserver.cert ]; then + if [[ ! -z "${KUBEAPISERVER_CERT:-}" ]] && [[ ! -z "${KUBEAPISERVER_KEY:-}" ]]; then + (umask 077; + echo "${KUBEAPISERVER_CERT}" | base64 --decode > /srv/kubernetes/kubeapiserver.cert; + echo "${KUBEAPISERVER_KEY}" | base64 --decode > /srv/kubernetes/kubeapiserver.key) + fi + fi if [ ! -e "${BASIC_AUTH_FILE}" ]; then mkdir -p /srv/salt-overlay/salt/kube-apiserver (umask 077; @@ -726,6 +755,11 @@ current-context: service-account-context EOF ) fi + local -r kubelet_auth_ca_file="/srv/salt-overlay/salt/kubelet/kubelet_auth_ca.crt" + if [ ! -e "${kubelet_auth_ca_file}" ] && [[ ! -z "${KUBELET_AUTH_CA_CERT:-}" ]]; then + (umask 077; + echo "${KUBELET_AUTH_CA_CERT}" | base64 --decode > "${kubelet_auth_ca_file}") + fi } # This should happen both on cluster initialization and node upgrades. @@ -1099,6 +1133,7 @@ if [[ -z "${is_push}" ]]; then [[ "${KUBERNETES_MASTER}" == "true" ]] && mount-master-pd create-salt-pillar if [[ "${KUBERNETES_MASTER}" == "true" ]]; then + set-kube-master-certs create-salt-master-auth create-salt-master-etcd-auth create-salt-master-kubelet-auth diff --git a/cluster/gce/debian/master-helper.sh b/cluster/gce/debian/master-helper.sh index 72097b9618..f4e3f40772 100755 --- a/cluster/gce/debian/master-helper.sh +++ b/cluster/gce/debian/master-helper.sh @@ -87,7 +87,7 @@ function create-master-instance-internal() { --scopes "storage-ro,compute-rw,monitoring,logging-write" \ --can-ip-forward \ --metadata-from-file \ - "startup-script=${KUBE_TEMP}/configure-vm.sh,kube-env=${KUBE_TEMP}/master-kube-env.yaml,cluster-name=${KUBE_TEMP}/cluster-name.txt" \ + "startup-script=${KUBE_TEMP}/configure-vm.sh,kube-env=${KUBE_TEMP}/master-kube-env.yaml,cluster-name=${KUBE_TEMP}/cluster-name.txt,kube-master-certs=${KUBE_TEMP}/kube-master-certs.yaml" \ --disk "name=${master_name}-pd,device-name=master-pd,mode=rw,boot=no,auto-delete=no" \ --boot-disk-size "${MASTER_ROOT_DISK_SIZE:-10}" \ ${preemptible_master} diff --git a/cluster/gce/gci/configure-helper.sh b/cluster/gce/gci/configure-helper.sh index aa4f54fefe..03dc61aa0b 100644 --- a/cluster/gce/gci/configure-helper.sh +++ b/cluster/gce/gci/configure-helper.sh @@ -201,6 +201,10 @@ function create-master-auth { echo "${MASTER_CERT}" | base64 --decode > "${auth_dir}/server.cert" echo "${MASTER_KEY}" | base64 --decode > "${auth_dir}/server.key" fi + if [ ! -e "${auth_dir}/kubeapiserver.cert" ] && [[ ! -z "${KUBEAPISERVER_CERT:-}" ]] && [[ ! -z "${KUBEAPISERVER_KEY:-}" ]]; then + echo "${KUBEAPISERVER_CERT}" | base64 --decode > "${auth_dir}/kubeapiserver.cert" + echo "${KUBEAPISERVER_KEY}" | base64 --decode > "${auth_dir}/kubeapiserver.key" + fi local -r basic_auth_csv="${auth_dir}/basic_auth.csv" if [[ ! -e "${basic_auth_csv}" && -n "${KUBE_PASSWORD:-}" && -n "${KUBE_USER:-}" ]]; then echo "${KUBE_PASSWORD},${KUBE_USER},admin" > "${basic_auth_csv}" @@ -344,6 +348,12 @@ current-context: service-account-context EOF } +function create-kubelet-auth-ca { + if [[ -n "${KUBELET_AUTH_CA_CERT:-}" ]]; then + echo "${KUBELET_AUTH_CA_CERT}" | base64 --decode > "/var/lib/kubelet/kubelet_auth_ca.crt" + fi +} + # Uses KUBELET_CA_CERT (falling back to CA_CERT), KUBELET_CERT, and KUBELET_KEY # to generate a kubeconfig file for the kubelet to securely connect to the apiserver. # Set REGISTER_MASTER_KUBELET to true if kubelet on the master node @@ -578,6 +588,9 @@ function start-kubelet { if [[ -n "${FEATURE_GATES:-}" ]]; then flags+=" --feature-gates=${FEATURE_GATES}" fi + if [ -n "${KUBELET_AUTH_CA_CERT:-}" ]; then + flags+=" --anonymous-auth=false --client-ca-file=/var/lib/kubelet/kubelet_auth_ca.crt" + fi local -r kubelet_env_file="/etc/default/kubelet" echo "KUBELET_OPTS=\"${flags}\"" > "${kubelet_env_file}" @@ -793,6 +806,8 @@ function start-kube-apiserver { params+=" --secure-port=443" params+=" --tls-cert-file=/etc/srv/kubernetes/server.cert" params+=" --tls-private-key-file=/etc/srv/kubernetes/server.key" + params+=" --kubelet-client-certificate=/etc/srv/kubernetes/kubeapiserver.cert" + params+=" --kubelet-client-key=/etc/srv/kubernetes/kubeapiserver.key" params+=" --token-auth-file=/etc/srv/kubernetes/known_tokens.csv" if [[ -n "${KUBE_PASSWORD:-}" && -n "${KUBE_USER:-}" ]]; then params+=" --basic-auth-file=/etc/srv/kubernetes/basic_auth.csv" @@ -1266,6 +1281,10 @@ fi source "${KUBE_HOME}/kube-env" +if [[ -e "${KUBE_HOME}/kube-master-certs" ]]; then + source "${KUBE_HOME}/kube-master-certs" +fi + if [[ -n "${KUBE_USER:-}" ]]; then if ! [[ "${KUBE_USER}" =~ ^[-._@a-zA-Z0-9]+$ ]]; then echo "Bad KUBE_USER format." @@ -1289,6 +1308,7 @@ if [[ "${KUBERNETES_MASTER:-}" == "true" ]]; then create-master-etcd-auth else create-kubelet-kubeconfig + create-kubelet-auth-ca create-kubeproxy-kubeconfig fi diff --git a/cluster/gce/gci/configure.sh b/cluster/gce/gci/configure.sh index 11fe6f08d6..5298535e2f 100644 --- a/cluster/gce/gci/configure.sh +++ b/cluster/gce/gci/configure.sh @@ -54,6 +54,22 @@ for k,v in yaml.load(sys.stdin).iteritems(): rm -f "${tmp_kube_env}" } +function download-kube-master-certs { + # Fetch kube-env from GCE metadata server. + local -r tmp_kube_master_certs="/tmp/kube-master-certs.yaml" + curl --fail --retry 5 --retry-delay 3 --silent --show-error \ + -H "X-Google-Metadata-Request: True" \ + -o "${tmp_kube_master_certs}" \ + http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-master-certs + # Convert the yaml format file into a shell-style file. + eval $(python -c ''' +import pipes,sys,yaml +for k,v in yaml.load(sys.stdin).iteritems(): + print("readonly {var}={value}".format(var = k, value = pipes.quote(str(v)))) +''' < "${tmp_kube_master_certs}" > "${KUBE_HOME}/kube-master-certs") + rm -f "${tmp_kube_master_certs}" +} + function validate-hash { local -r file="$1" local -r expected="$2" @@ -208,6 +224,9 @@ set-broken-motd KUBE_HOME="/home/kubernetes" download-kube-env source "${KUBE_HOME}/kube-env" +if [[ "${KUBERNETES_MASTER:-}" == "true" ]]; then + download-kube-master-certs +fi install-kube-binary-config echo "Done for installing kubernetes files" diff --git a/cluster/gce/gci/health-monitor.sh b/cluster/gce/gci/health-monitor.sh index 4d50e4ee8d..896bc05ea2 100644 --- a/cluster/gce/gci/health-monitor.sh +++ b/cluster/gce/gci/health-monitor.sh @@ -38,14 +38,14 @@ function docker_monitoring { } function kubelet_monitoring { - echo "Wait for 2 minutes for kubelet to be fuctional" + echo "Wait for 2 minutes for kubelet to be functional" # TODO(andyzheng0831): replace it with a more reliable method if possible. sleep 120 local -r max_seconds=10 while [ 1 ]; do - if ! curl --insecure -m "${max_seconds}" -f -s https://127.0.0.1:${KUBELET_PORT:-10250}/healthz > /dev/null; then + if ! curl -m "${max_seconds}" -f -s http://127.0.0.1:10255/healthz > /dev/null; then echo "Kubelet is unhealthy!" - curl --insecure https://127.0.0.1:${KUBELET_PORT:-10250}/healthz + curl http://127.0.0.1:10255/healthz pkill kubelet # Wait for a while, as we don't want to kill it again before it is really up. sleep 60 diff --git a/cluster/gce/gci/master-helper.sh b/cluster/gce/gci/master-helper.sh index db67224f84..35365a1f7f 100755 --- a/cluster/gce/gci/master-helper.sh +++ b/cluster/gce/gci/master-helper.sh @@ -89,7 +89,7 @@ function create-master-instance-internal() { --scopes "storage-ro,compute-rw,monitoring,logging-write" \ --can-ip-forward \ --metadata-from-file \ - "kube-env=${KUBE_TEMP}/master-kube-env.yaml,user-data=${KUBE_ROOT}/cluster/gce/gci/master.yaml,configure-sh=${KUBE_ROOT}/cluster/gce/gci/configure.sh,cluster-name=${KUBE_TEMP}/cluster-name.txt,gci-update-strategy=${KUBE_TEMP}/gci-update.txt,gci-ensure-gke-docker=${KUBE_TEMP}/gci-ensure-gke-docker.txt,gci-docker-version=${KUBE_TEMP}/gci-docker-version.txt" \ + "kube-env=${KUBE_TEMP}/master-kube-env.yaml,user-data=${KUBE_ROOT}/cluster/gce/gci/master.yaml,configure-sh=${KUBE_ROOT}/cluster/gce/gci/configure.sh,cluster-name=${KUBE_TEMP}/cluster-name.txt,gci-update-strategy=${KUBE_TEMP}/gci-update.txt,gci-ensure-gke-docker=${KUBE_TEMP}/gci-ensure-gke-docker.txt,gci-docker-version=${KUBE_TEMP}/gci-docker-version.txt,kube-master-certs=${KUBE_TEMP}/kube-master-certs.yaml" \ --disk "name=${master_name}-pd,device-name=master-pd,mode=rw,boot=no,auto-delete=no" \ --boot-disk-size "${MASTER_ROOT_DISK_SIZE:-10}" \ ${preemptible_master} diff --git a/cluster/saltbase/salt/kube-apiserver/kube-apiserver.manifest b/cluster/saltbase/salt/kube-apiserver/kube-apiserver.manifest index da89e827d0..de62d4dbaa 100644 --- a/cluster/saltbase/salt/kube-apiserver/kube-apiserver.manifest +++ b/cluster/saltbase/salt/kube-apiserver/kube-apiserver.manifest @@ -82,6 +82,8 @@ {% set cert_file = "--tls-cert-file=/srv/kubernetes/server.cert" -%} {% set key_file = "--tls-private-key-file=/srv/kubernetes/server.key" -%} +{% set kubelet_cert_file = "--kubelet-client-certificate=/srv/kubernetes/kubeapiserver.cert" -%} +{% set kubelet_key_file = "--kubelet-client-key=/srv/kubernetes/kubeapiserver.key" -%} {% set client_ca_file = "" -%} {% set secure_port = "6443" -%} @@ -169,7 +171,7 @@ {% endif -%} {% set params = address + " " + storage_backend + " " + etcd_servers + " " + etcd_servers_overrides + " " + cloud_provider + " " + cloud_config + " " + runtime_config + " " + feature_gates + " " + admission_control + " " + max_requests_inflight + " " + target_ram_mb + " " + service_cluster_ip_range + " " + client_ca_file + basic_auth_file + " " + min_request_timeout + " " + enable_garbage_collector + " " + etcd_quorum_read -%} -{% set params = params + " " + cert_file + " " + key_file + " --secure-port=" + secure_port + token_auth_file + " " + bind_address + " " + log_level + " " + advertise_address + " " + proxy_ssh_options + authz_mode + abac_policy_file + webhook_authentication_config + webhook_authorization_config + image_review_config -%} +{% set params = params + " " + cert_file + " " + key_file + " " + kubelet_cert_file + " " + kubelet_key_file + " --secure-port=" + secure_port + token_auth_file + " " + bind_address + " " + log_level + " " + advertise_address + " " + proxy_ssh_options + authz_mode + abac_policy_file + webhook_authentication_config + webhook_authorization_config + image_review_config -%} # test_args has to be kept at the end, so they'll overwrite any prior configuration {% if pillar['apiserver_test_args'] is defined -%} diff --git a/cluster/saltbase/salt/kubelet/default b/cluster/saltbase/salt/kubelet/default index 389ce64f04..8aa9c03901 100644 --- a/cluster/saltbase/salt/kubelet/default +++ b/cluster/saltbase/salt/kubelet/default @@ -188,5 +188,10 @@ {% set eviction_hard="--eviction-hard=" + pillar['eviction_hard'] %} {% endif -%} +{% set kubelet_auth_ca_cert = "" %} +{% if pillar['kubelet_auth_ca_cert'] is defined -%} + {% set kubelet_auth_ca_cert="--anonymous-auth=false --client-ca-file=" + pillar['kubelet_auth_ca_cert'] %} +{% endif -%} + # test_args has to be kept at the end, so they'll overwrite any prior configuration -DAEMON_ARGS="{{daemon_args}} {{api_servers_with_port}} {{debugging_handlers}} {{hostname_override}} {{cloud_provider}} {{cloud_config}} {{config}} {{manifest_url}} --allow-privileged={{pillar['allow_privileged']}} {{log_level}} {{cluster_dns}} {{cluster_domain}} {{docker_root}} {{kubelet_root}} {{non_masquerade_cidr}} {{cgroup_root}} {{system_container}} {{pod_cidr}} {{ master_kubelet_args }} {{cpu_cfs_quota}} {{network_plugin}} {{kubelet_port}} {{ hairpin_mode }} {{enable_custom_metrics}} {{runtime_container}} {{kubelet_container}} {{node_labels}} {{babysit_daemons}} {{eviction_hard}} {{feature_gates}} {{test_args}}" +DAEMON_ARGS="{{daemon_args}} {{api_servers_with_port}} {{debugging_handlers}} {{hostname_override}} {{cloud_provider}} {{cloud_config}} {{config}} {{manifest_url}} --allow-privileged={{pillar['allow_privileged']}} {{log_level}} {{cluster_dns}} {{cluster_domain}} {{docker_root}} {{kubelet_root}} {{non_masquerade_cidr}} {{cgroup_root}} {{system_container}} {{pod_cidr}} {{ master_kubelet_args }} {{cpu_cfs_quota}} {{network_plugin}} {{kubelet_port}} {{ hairpin_mode }} {{enable_custom_metrics}} {{runtime_container}} {{kubelet_container}} {{node_labels}} {{babysit_daemons}} {{eviction_hard}} {{kubelet_auth_ca_cert}} {{feature_gates}} {{test_args}}" diff --git a/cluster/saltbase/salt/kubelet/init.sls b/cluster/saltbase/salt/kubelet/init.sls index a03bf7a6cb..f5b3eee14d 100644 --- a/cluster/saltbase/salt/kubelet/init.sls +++ b/cluster/saltbase/salt/kubelet/init.sls @@ -31,6 +31,15 @@ - mode: 400 - makedirs: true +{% if pillar['kubelet_auth_ca_cert'] is defined %} +/var/lib/kubelet/kubelet_auth_ca.crt: + file.managed: + - source: salt://kubelet/kubelet_auth_ca.crt + - user: root + - group: root + - mode: 400 + - makedirs: true +{% endif %} {% if pillar.get('is_systemd') %} @@ -52,6 +61,7 @@ fix-service-kubelet: - file: {{ pillar.get('systemd_system_path') }}/kubelet.service - file: {{ environment_file }} - file: /var/lib/kubelet/kubeconfig + - file: /var/lib/kubelet/kubelet_auth_ca.crt {% else %} @@ -79,6 +89,9 @@ kubelet: {% endif %} - file: {{ environment_file }} - file: /var/lib/kubelet/kubeconfig +{% if pillar['kubelet_auth_ca_cert'] is defined %} + - file: /var/lib/kubelet/kubelet_auth_ca.crt +{% endif %} {% if pillar.get('is_systemd') %} - provider: - service: systemd diff --git a/cluster/saltbase/salt/supervisor/kubelet-checker.sh b/cluster/saltbase/salt/supervisor/kubelet-checker.sh index 7ee171f3eb..85b67f66d3 100755 --- a/cluster/saltbase/salt/supervisor/kubelet-checker.sh +++ b/cluster/saltbase/salt/supervisor/kubelet-checker.sh @@ -18,11 +18,6 @@ # it detects a failure. It then exits, and supervisord restarts it # which in turn restarts the kubelet. -{% set kubelet_port = "10250" -%} -{% if pillar['kubelet_port'] is defined -%} - {% set kubelet_port = pillar['kubelet_port'] -%} -{% endif -%} - /etc/init.d/kubelet stop /etc/init.d/kubelet start @@ -32,9 +27,9 @@ sleep 60 max_seconds=10 while true; do - if ! curl --insecure -m ${max_seconds} -f -s https://127.0.0.1:{{kubelet_port}}/healthz > /dev/null; then +if ! curl -m ${max_seconds} -f -s http://127.0.0.1:10255/healthz > /dev/null; then echo "kubelet failed!" - curl --insecure https://127.0.0.1:{{kubelet_port}}/healthz + curl http://127.0.0.1:10255/healthz exit 2 fi sleep 10 diff --git a/cmd/kube-apiserver/app/options/options.go b/cmd/kube-apiserver/app/options/options.go index df9b18281d..d45f7ad1eb 100644 --- a/cmd/kube-apiserver/app/options/options.go +++ b/cmd/kube-apiserver/app/options/options.go @@ -69,7 +69,8 @@ func NewServerRunOptions() *ServerRunOptions { EventTTL: 1 * time.Hour, MasterCount: 1, KubeletConfig: kubeletclient.KubeletClientConfig{ - Port: ports.KubeletPort, + Port: ports.KubeletPort, + ReadOnlyPort: ports.KubeletReadOnlyPort, PreferredAddressTypes: []string{ string(api.NodeHostName), string(api.NodeInternalIP), @@ -151,6 +152,9 @@ func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet) { "DEPRECATED: kubelet port.") fs.MarkDeprecated("kubelet-port", "kubelet-port is deprecated and will be removed.") + fs.UintVar(&s.KubeletConfig.ReadOnlyPort, "kubelet-read-only-port", s.KubeletConfig.ReadOnlyPort, + "DEPRECATED: kubelet port.") + fs.DurationVar(&s.KubeletConfig.HTTPTimeout, "kubelet-timeout", s.KubeletConfig.HTTPTimeout, "Timeout for kubelet operations.") diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index f52ec29cbc..fa6407ffcd 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -140,12 +140,15 @@ func Run(s *options.ServerRunOptions) error { if s.KubeletConfig.Port == 0 { return fmt.Errorf("must enable kubelet port if proxy ssh-tunneling is specified") } + if s.KubeletConfig.ReadOnlyPort == 0 { + return fmt.Errorf("Must enable kubelet readonly port if proxy ssh-tunneling is specified.") + } // Set up the tunneler // TODO(cjcullen): If we want this to handle per-kubelet ports or other // kubelet listen-addresses, we need to plumb through options. healthCheckPath := &url.URL{ - Scheme: "https", - Host: net.JoinHostPort("127.0.0.1", strconv.FormatUint(uint64(s.KubeletConfig.Port), 10)), + Scheme: "http", + Host: net.JoinHostPort("127.0.0.1", strconv.FormatUint(uint64(s.KubeletConfig.ReadOnlyPort), 10)), Path: "healthz", } tunneler = genericapiserver.NewSSHTunneler(s.SSHUser, s.SSHKeyfile, healthCheckPath, installSSH) diff --git a/pkg/kubelet/client/kubelet_client.go b/pkg/kubelet/client/kubelet_client.go index d67d0069d5..7638e4b020 100644 --- a/pkg/kubelet/client/kubelet_client.go +++ b/pkg/kubelet/client/kubelet_client.go @@ -32,8 +32,9 @@ import ( type KubeletClientConfig struct { // Default port - used if no information about Kubelet port can be found in Node.NodeStatus.DaemonEndpoints. - Port uint - EnableHttps bool + Port uint + ReadOnlyPort uint + EnableHttps bool // PreferredAddressTypes - used to select an address from Node.NodeStatus.Addresses PreferredAddressTypes []string From 3ab0e37cc6dc5fb18030a3329c6ede08e87d7201 Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Tue, 6 Dec 2016 16:08:39 -0800 Subject: [PATCH 2/2] implement upgrades --- cluster/common.sh | 1 + cluster/gce/gci/configure-helper.sh | 6 +++--- cluster/gce/upgrade.sh | 3 +++ cmd/kube-apiserver/app/server.go | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cluster/common.sh b/cluster/common.sh index 7081bffc6a..db23bc2331 100755 --- a/cluster/common.sh +++ b/cluster/common.sh @@ -572,6 +572,7 @@ function build-kube-master-certs { cat >$file < "${kubelet_env_file}" diff --git a/cluster/gce/upgrade.sh b/cluster/gce/upgrade.sh index a3c8e77bdd..83b8dadc1c 100755 --- a/cluster/gce/upgrade.sh +++ b/cluster/gce/upgrade.sh @@ -233,6 +233,9 @@ function prepare-node-upgrade() { KUBELET_CERT_BASE64=$(get-env-val "${node_env}" "KUBELET_CERT") KUBELET_KEY_BASE64=$(get-env-val "${node_env}" "KUBELET_KEY") + local master_env=$(get-master-env) + KUBELET_AUTH_CA_CERT_BASE64=$(get-env-val "${master_env}" "KUBELET_AUTH_CA_CERT") + # TODO(zmerlynn): How do we ensure kube-env is written in a ${version}- # compatible way? write-node-env diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index fa6407ffcd..65e1c11387 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -141,7 +141,7 @@ func Run(s *options.ServerRunOptions) error { return fmt.Errorf("must enable kubelet port if proxy ssh-tunneling is specified") } if s.KubeletConfig.ReadOnlyPort == 0 { - return fmt.Errorf("Must enable kubelet readonly port if proxy ssh-tunneling is specified.") + return fmt.Errorf("must enable kubelet readonly port if proxy ssh-tunneling is specified") } // Set up the tunneler // TODO(cjcullen): If we want this to handle per-kubelet ports or other