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

Template the ingress controller #24391

Merged
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
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{% set kube_uid = "" -%}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andyzheng0831 This file is getting templated in preparation for running as a static pod on the master. FYI.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for heads-up. I am waiting for this PR to be merged, then I can test my change to gci support

{% if pillar['kube_uid'] is defined -%}
{% set kube_uid = pillar['kube_uid'] %}
{% endif -%}

apiVersion: v1
kind: ReplicationController
metadata:
Expand Down Expand Up @@ -65,4 +70,5 @@ spec:
memory: 50Mi
args:
- --default-backend-service=kube-system/default-http-backend
- --sync-period=300s
- --sync-period=60s
- --cluster-uid={{kube_uid}}
12 changes: 12 additions & 0 deletions cluster/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,16 @@ function gen-kube-bearertoken() {
KUBE_BEARER_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null)
}

# Generate uid
# This function only works on systems with python. It generates a time based
# UID instead of a UUID because GCE has a name length limit.
#
# Vars set:
# KUBE_UID
function gen-uid {
KUBE_UID=$(python -c 'import uuid; print uuid.uuid1().fields[0]')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe consider this? Your choice. I am okay with python.
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah i thought about urandom and in fact my previous commit had /proc/sys/kernel/random/uuid, but neither of those is cross platform. You could argue that python might not be installed, but I grepped our kube-up scripts and it showed that other places were using python so i figured it's the least evil choice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that @mikedanese is working on removing python for the on-host parts, but maybe it's ok to leave in here.

}


function load-or-gen-kube-basicauth() {
if [[ ! -z "${KUBE_CONTEXT:-}" ]]; then
Expand Down Expand Up @@ -456,6 +466,7 @@ function build-kube-env {
local file=$2

build-runtime-config
gen-uid

rm -f ${file}
cat >$file <<EOF
Expand Down Expand Up @@ -503,6 +514,7 @@ KUBE_DOCKER_REGISTRY: $(yaml-quote ${KUBE_DOCKER_REGISTRY:-})
KUBE_ADDON_REGISTRY: $(yaml-quote ${KUBE_ADDON_REGISTRY:-})
MULTIZONE: $(yaml-quote ${MULTIZONE:-})
NON_MASQUERADE_CIDR: $(yaml-quote ${NON_MASQUERADE_CIDR:-})
KUBE_UID: $(yaml-quote ${KUBE_UID:-})
EOF
if [ -n "${KUBELET_PORT:-}" ]; then
cat >>$file <<EOF
Expand Down
1 change: 1 addition & 0 deletions cluster/gce/configure-vm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ manifest_url: '$(echo "$MANIFEST_URL" | sed -e "s/'/''/g")'
manifest_url_header: '$(echo "$MANIFEST_URL_HEADER" | sed -e "s/'/''/g")'
num_nodes: $(echo "${NUM_NODES}" | sed -e "s/'/''/g")
e2e_storage_test_environment: '$(echo "$E2E_STORAGE_TEST_ENVIRONMENT" | sed -e "s/'/''/g")'
kube_uid: '$(echo "${KUBE_UID}" | sed -e "s/'/''/g")'
EOF
if [ -n "${KUBELET_PORT:-}" ]; then
cat <<EOF >>/srv/salt-overlay/pillar/cluster-params.sls
Expand Down
1 change: 1 addition & 0 deletions cluster/saltbase/salt/kube-addons/init.sls
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ addon-dir-create:
file.recurse:
- source: salt://kube-addons/cluster-loadbalancing/glbc
- include_pat: E@(^.+\.yaml$|^.+\.json$)
- template: jinja
- user: root
- group: root
- dir_mode: 755
Expand Down
114 changes: 36 additions & 78 deletions test/e2e/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,76 +253,49 @@ func kubectlLogLBController(c *client.Client, ns string) {
}

type IngressController struct {
ns string
rcPath string
defaultSvcPath string
UID string
Project string
rc *api.ReplicationController
svc *api.Service
c *client.Client
ns string
rcPath string
UID string
Project string
rc *api.ReplicationController
svc *api.Service
c *client.Client
}

func (cont *IngressController) create() {

// TODO: This cop out is because it would be *more* brittle to duplicate all
// the name construction logic from the controller cross-repo. We will not
// need to be so paranoid about leaked resources once we figure out a solution
// for issues like #16337. Currently, all names should fall within 63 chars.
testName := fmt.Sprintf("k8s-fw-foo-app-X-%v--%v", cont.ns, cont.UID)
if len(testName) > nameLenLimit {
framework.Failf("Cannot reliably test the given namespace(%v)/uid(%v), too close to GCE limit of %v",
cont.ns, cont.UID, nameLenLimit)
}

if cont.defaultSvcPath != "" {
svc := svcFromManifest(cont.defaultSvcPath)
svc.Namespace = cont.ns
svc.Labels = controllerLabels
svc.Spec.Selector = controllerLabels
cont.svc = svc
_, err := cont.c.Services(cont.ns).Create(cont.svc)
Expect(err).NotTo(HaveOccurred())
}
rc := rcFromManifest(cont.rcPath)

func (cont *IngressController) getL7AddonUID() (string, error) {
listOpts := api.ListOptions{LabelSelector: labels.SelectorFromSet(labels.Set(clusterAddonLBLabels))}
existingRCs, err := cont.c.ReplicationControllers(api.NamespaceSystem).List(listOpts)
Expect(err).NotTo(HaveOccurred())
if len(existingRCs.Items) != 1 {
framework.Failf("Unexpected number of lb cluster addons %v with label %v in kube-system namespace", len(existingRCs.Items), clusterAddonLBLabels)
if err != nil {
return "", err
}

// Merge the existing spec and new spec. The modifications should not
// manifest as functional changes to the controller. Most importantly, the
// podTemplate shouldn't change (but for the additional test cmd line flags)
// to ensure we test actual cluster functionality across upgrades.
rc.Spec = existingRCs.Items[0].Spec
rc.Name = "glbc"
rc.Namespace = cont.ns
rc.Labels = controllerLabels
rc.Spec.Selector = controllerLabels
rc.Spec.Template.Labels = controllerLabels
rc.Spec.Replicas = 1

// These command line params are only recognized by v0.51 and above.
testArgs := []string{
// Pass namespace uid so the controller will tag resources with it.
fmt.Sprintf("--cluster-uid=%v", cont.UID),
// Tell the controller to delete all resources as it quits.
fmt.Sprintf("--delete-all-on-quit=true"),
// Don't use the default Service from kube-system.
fmt.Sprintf("--default-backend-service=%v/%v", cont.svc.Namespace, cont.svc.Name),
if len(existingRCs.Items) != 1 {
return "", fmt.Errorf("Unexpected number of lb cluster addons %v with label %v in kube-system namespace", len(existingRCs.Items), clusterAddonLBLabels)
}
rc := existingRCs.Items[0]
commandPrefix := "--cluster-uid="
for i, c := range rc.Spec.Template.Spec.Containers {
if c.Name == lbContainerName {
rc.Spec.Template.Spec.Containers[i].Args = append(c.Args, testArgs...)
for _, arg := range rc.Spec.Template.Spec.Containers[i].Args {
if strings.HasPrefix(arg, commandPrefix) {
return strings.Replace(arg, commandPrefix, "", -1), nil
}
}
}
}
cont.rc = rc
_, err = cont.c.ReplicationControllers(cont.ns).Create(cont.rc)
return "", fmt.Errorf("Could not find cluster UID for L7 addon pod")
}

func (cont *IngressController) init() {
uid, err := cont.getL7AddonUID()
Expect(err).NotTo(HaveOccurred())
Expect(framework.WaitForRCPodsRunning(cont.c, cont.ns, cont.rc.Name)).NotTo(HaveOccurred())
cont.UID = uid
// There's a name limit imposed by GCE. The controller will truncate.
testName := fmt.Sprintf("k8s-fw-foo-app-X-%v--%v", cont.ns, cont.UID)
if len(testName) > nameLenLimit {
framework.Logf("WARNING: test name including cluster UID: %v is over the GCE limit of %v", testName, nameLenLimit)
} else {
framework.Logf("Deteced cluster UID %v", cont.UID)
}
}

func (cont *IngressController) Cleanup(del bool) error {
Expand Down Expand Up @@ -457,24 +430,14 @@ var _ = framework.KubeDescribe("GCE L7 LoadBalancer Controller [Feature:Ingress]
f.BeforeEach()
client = f.Client
ns = f.Namespace.Name
// Scaled down the existing Ingress controller so it doesn't interfere with the test.
Expect(framework.ScaleRCByLabels(client, api.NamespaceSystem, clusterAddonLBLabels, 0)).NotTo(HaveOccurred())
addonDir = filepath.Join(
framework.TestContext.RepoRoot, "cluster", "addons", "cluster-loadbalancing", "glbc")

nsParts := strings.Split(ns, "-")
ingController = &IngressController{
ns: ns,
// The UID in the namespace was generated by the master, so it's
// global to the cluster.
UID: nsParts[len(nsParts)-1],
Project: framework.TestContext.CloudConfig.ProjectID,
rcPath: filepath.Join(addonDir, "glbc-controller.yaml"),
defaultSvcPath: filepath.Join(addonDir, "default-svc.yaml"),
c: client,
ns: ns,
Project: framework.TestContext.CloudConfig.ProjectID,
c: client,
}
ingController.create()
framework.Logf("Finished creating ingress controller")
ingController.init()
// If we somehow get the same namespace uid as someone else in this
// gce project, just back off.
Expect(ingController.Cleanup(false)).NotTo(HaveOccurred())
Expand Down Expand Up @@ -509,9 +472,6 @@ var _ = framework.KubeDescribe("GCE L7 LoadBalancer Controller [Feature:Ingress]
}
return true, nil
})
// TODO: Remove this once issue #17802 is fixed
Expect(framework.ScaleRCByLabels(client, ingController.rc.Namespace, ingController.rc.Labels, 0)).NotTo(HaveOccurred())

// If the controller failed to cleanup the test will fail, but we want to cleanup
// resources before that.
if pollErr != nil {
Expand All @@ -520,8 +480,6 @@ var _ = framework.KubeDescribe("GCE L7 LoadBalancer Controller [Feature:Ingress]
}
framework.Failf("Failed to cleanup GCE L7 resources.")
}
// Restore the cluster Addon.
Expect(framework.ScaleRCByLabels(client, api.NamespaceSystem, clusterAddonLBLabels, 1)).NotTo(HaveOccurred())
f.AfterEach()
framework.Logf("Successfully verified GCE L7 loadbalancer via Ingress.")
})
Expand Down