Skip to content

Commit

Permalink
Implement workaround for kubernetes/kubeadm#857
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Lipovetsky committed Jul 29, 2018
1 parent 5e0c90b commit 761b689
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 0 deletions.
7 changes: 7 additions & 0 deletions apis/defaults.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package apis

import (
"log"

"github.com/platform9/nodeadm/constants"
kubeadmv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
)
Expand All @@ -15,6 +17,11 @@ func SetInitDefaults(config *InitConfiguration) {
kubeadmv1alpha1.SetDefaults_MasterConfiguration(&config.MasterConfiguration)
config.MasterConfiguration.KubernetesVersion = constants.KUBERNETES_VERSION
config.MasterConfiguration.NoTaintMaster = true
nodeName, err := constants.GetHostnameOverride()
if err != nil {
log.Fatalf("Failed to dervice hostname override: %v", err)
}
config.MasterConfiguration.NodeName = nodeName
config.MasterConfiguration.APIServerExtraArgs = map[string]string{
"service-node-port-range": constants.ServiceNodePortRange,
}
Expand Down
8 changes: 8 additions & 0 deletions cmd/nodeinit.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (
"path/filepath"

"github.com/ghodss/yaml"

"github.com/platform9/nodeadm/workarounds"

"github.com/platform9/nodeadm/apis"
"github.com/platform9/nodeadm/constants"
"github.com/platform9/nodeadm/deprecated"
Expand Down Expand Up @@ -55,6 +58,11 @@ var nodeCmdInit = &cobra.Command{

kubeadmInit(constants.KUBEADM_CONFIG)

log.Println("Applying workaround for https://github.com/kubernetes/kubeadm/issues/857")
if err := workarounds.EnsureKubeProxyRespectsHostoverride(); err != nil {
log.Fatalf("Failed to apply workaround: %v", err)
}

networkInit(config)
},
}
Expand Down
139 changes: 139 additions & 0 deletions workarounds/kubeadm_issue_857.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package workarounds

import (
"bytes"
"context"
"fmt"
"log"
"os/exec"
"path/filepath"
"strings"
"time"

"github.com/platform9/nodeadm/constants"
)

const (
// Patch hard-codes docker image "k8s.gcr.io/kube-proxy-amd64:v1.10.4"
patch = `[
{
"op": "add",
"path": "/spec/template/spec/volumes/-",
"value": {
"name": "shared-data",
"mountPath": "/shared-data"
}
},
{
"op": "add",
"path": "/spec/template/spec/containers/0/volumeMounts/-",
"value": {
"name": "shared-data",
"mountPath": "/shared-data"
}
},
{
"op": "replace",
"path": "/spec/template/spec/containers/0/command/1",
"value": "--config=/shared-data/config.conf"
},
{
"op": "add",
"path": "/spec/template/spec/initContainers",
"value": [
{
"command": [
"sh",
"-c",
"/bin/sed \"s/hostnameOverride: \\\"\\\"/hostnameOverride: $(NODE_NAME)/\" /var/lib/kube-proxy/config.conf > /shared-data/config.conf"
],
"env": [
{
"name": "NODE_NAME",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "spec.nodeName"
}
}
}
],
"image": "k8s.gcr.io/kube-proxy-amd64:v1.10.4",
"imagePullPolicy": "IfNotPresent",
"name": "update-config-file",
"volumeMounts": [
{
"mountPath": "/var/lib/kube-proxy",
"name": "kube-proxy"
},
{
"mountPath": "/shared-data",
"name": "shared-data"
}
]
}
]
}
]`

resultIfPatched = "--config=/shared-data/config.conf"
)

// EnsureKubeProxyRespectsHostoverride patches the kube-proxy daemonset so that
// kube-proxy respects the hostnameOverride setting. The function is idempotent.
// See: https://github.com/kubernetes/kubeadm/issues/857
func EnsureKubeProxyRespectsHostoverride() error {
log.Println("[workarounds] Checking whether kube-proxy daemonset is patched")
patched, err := isPatchedKubeProxyDaemonSet()
if err != nil {
return fmt.Errorf("unable to check if kube-proxy daemonset is patched: %v", err)
}
if patched {
log.Println("[workarounds] Kube-proxy daemonset already patched. Continuing. ")
return nil
}
log.Println("[workarounds] Patching kube-proxy daemonset")
err = patchKubeProxyDaemonSet()
if err != nil {
return fmt.Errorf("unable to patch kube-proxy daemonset: %v", err)
}
log.Println("[workarounds] Patched kube-proxy daemonset")
return nil
}

func isPatchedKubeProxyDaemonSet() (bool, error) {
name := "/bin/sh"
arg := fmt.Sprintf("%s --kubeconfig=%s --namespace=kube-system get daemonset kube-proxy -ojsonpath='{.spec.template.spec.containers[0].command[1]}'", filepath.Join(constants.BASE_INSTALL_DIR, constants.KubectlFilename), constants.AdminKubeconfigFile)

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
var stdout, stderr bytes.Buffer
cmd := exec.CommandContext(ctx, name, "-c", arg)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return false, fmt.Errorf("error running %q: %v (stdout: %s) (stderr: %s)", strings.Join(cmd.Args, " "), err, string(stdout.Bytes()), string(stderr.Bytes()))
}

if strings.Compare(string(stdout.Bytes()), resultIfPatched) == 0 {
return true, nil
}
return false, nil
}

func patchKubeProxyDaemonSet() error {
name := "/bin/sh"
arg := fmt.Sprintf("%s --kubeconfig=%s --namespace=kube-system patch --type=json daemonset kube-proxy --patch='%s'", filepath.Join(constants.BASE_INSTALL_DIR, constants.KubectlFilename), constants.AdminKubeconfigFile, patch)

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
var stdout, stderr bytes.Buffer
cmd := exec.CommandContext(ctx, name, "-c", arg)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("error running %q: %v (stdout: %s) (stderr: %s)", strings.Join(cmd.Args, " "), err, string(stdout.Bytes()), string(stderr.Bytes()))
}

return nil
}

0 comments on commit 761b689

Please sign in to comment.