diff --git a/.travis.yml b/.travis.yml
index 3bbb46d1ce5f49296e7a824348e3f3bca9ecee5d..e2a9f9f07c4d7fea08086907c83d8276c338b485 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -103,11 +103,11 @@ env:
 
 before_install:
   # Install Ansible.
-  - pip install --user boto -U
   - pip install --user ansible
   - pip install --user netaddr
   # W/A https://github.com/ansible/ansible-modules-core/issues/5196#issuecomment-253766186
   - pip install --user apache-libcloud==0.20.1
+  - pip install --user boto==2.9.0 -U
 
 cache:
   - directories:
@@ -149,16 +149,19 @@ script:
   - $HOME/.local/bin/ansible-playbook -i inventory/inventory.ini -u $SSH_USER -e ansible_ssh_user=$SSH_USER $SSH_ARGS -b --become-user=root tests/testcases/030_check-network.yml $LOG_LEVEL
 
 after_failure:
-  - $HOME/.local/bin/ansible-playbook -i inventory/inventory.ini -u $SSH_USER -e ansible_ssh_user=$SSH_USER $SSH_ARGS -b --become-user=root scripts/collect-info.yaml
+  - >
+    $HOME/.local/bin/ansible-playbook -i inventory/inventory.ini -u $SSH_USER
+    -e ansible_ssh_user=$SSH_USER $SSH_ARGS -b --become-user=root -e dir=$HOME
+    scripts/collect-info.yaml
   - >
     $HOME/.local/bin/ansible-playbook tests/cloud_playbooks/upload-logs-gcs.yml -i "localhost," -c local
-    -e test_id=${TEST_ID}
     -e kube_network_plugin=${KUBE_NETWORK_PLUGIN}
+    -e gce_project_id=${GCE_PROJECT_ID}
     -e gs_key=${GS_ACCESS_KEY_ID}
     -e gs_skey=${GS_SECRET_ACCESS_KEY}
     -e ostype=${CLOUD_IMAGE}
     -e commit=${TRAVIS_COMMIT}
-    -e pr=${TRAVIS_PULL_REQUEST}
+    -e dir=${HOME}
 
 after_script:
   - >
diff --git a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2 b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
index 4100e8a3414c00bde7ec61d5a55e53b9762ccb2d..a6718f9e5e14c0df096da10d7b0c53e03ea5f7d6 100644
--- a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
@@ -3,6 +3,8 @@ kind: Pod
 metadata:
   name: kube-apiserver
   namespace: kube-system
+  labels:
+    k8s-app: kube-apiserver
 spec:
   hostNetwork: true
   containers:
diff --git a/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2 b/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
index 3a9e1ef1b2e0d1475924ea65ba38f49931c1e6a3..a528f361e22975d170a43712c8a833652370d816 100644
--- a/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
@@ -3,6 +3,8 @@ kind: Pod
 metadata:
   name: kube-controller-manager
   namespace: kube-system
+  labels:
+    k8s-app: kube-controller
 spec:
   hostNetwork: true
   containers:
diff --git a/roles/kubernetes/master/templates/manifests/kube-scheduler.manifest.j2 b/roles/kubernetes/master/templates/manifests/kube-scheduler.manifest.j2
index 024ddbfaacc6e7e407b961a209e18b12b73028c7..15a705937fbee2caefd98f305e2c2fc69ff4c199 100644
--- a/roles/kubernetes/master/templates/manifests/kube-scheduler.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-scheduler.manifest.j2
@@ -3,6 +3,8 @@ kind: Pod
 metadata:
   name: kube-scheduler
   namespace: kube-system
+  labels:
+    k8s-app: kube-scheduler
 spec:
   hostNetwork: true
   containers:
diff --git a/roles/kubernetes/node/templates/manifests/kube-proxy.manifest.j2 b/roles/kubernetes/node/templates/manifests/kube-proxy.manifest.j2
index 7abffe053526d3f11386402a46d626bc9266841d..86d1e6f9e93e619d2fd95ba382eb30252f6b375d 100644
--- a/roles/kubernetes/node/templates/manifests/kube-proxy.manifest.j2
+++ b/roles/kubernetes/node/templates/manifests/kube-proxy.manifest.j2
@@ -3,6 +3,8 @@ kind: Pod
 metadata:
   name: kube-proxy
   namespace: kube-system
+  labels:
+    k8s-app: kube-proxy
 spec:
   hostNetwork: true
   containers:
diff --git a/roles/kubernetes/node/templates/manifests/nginx-proxy.manifest.j2 b/roles/kubernetes/node/templates/manifests/nginx-proxy.manifest.j2
index 50e054268088fe3b8213b141fde0244a1e0ef331..8e5dfcc116d94722c06b694d124736524b0d1c76 100644
--- a/roles/kubernetes/node/templates/manifests/nginx-proxy.manifest.j2
+++ b/roles/kubernetes/node/templates/manifests/nginx-proxy.manifest.j2
@@ -3,6 +3,8 @@ kind: Pod
 metadata:
   name: nginx-proxy
   namespace: kube-system
+  labels:
+    k8s-app: kube-nginx
 spec:
   hostNetwork: true
   containers:
diff --git a/scripts/collect-info.yaml b/scripts/collect-info.yaml
index 685b8b78710ce3bff27628422a997b9e487848c7..0ba47866e07b12dcb880d3cc5579020ae686e357 100644
--- a/scripts/collect-info.yaml
+++ b/scripts/collect-info.yaml
@@ -1,10 +1,9 @@
 ---
 - hosts: all
-  become: true
+  become: false
   gather_facts: no
 
   vars:
-    debug: false
     commands:
       - name: timedate_info
         cmd: timedatectl status
@@ -26,6 +25,37 @@
         cmd: journalctl -p err --utc --no-pager
       - name: etcd_info
         cmd: etcdctl --debug cluster-health
+      - name: weave_info
+        cmd: weave report | jq "."
+      - name: weave_logs
+        cmd: docker logs weave > weave.log
+      - name: kubedns_logs
+        cmd: sh -c "for i in `kubectl get pods --all-namespaces -l k8s-app=kubedns -o name`;
+          do kubectl logs $i --namespace kube-system kubedns > kubedns.log; done"
+      - name: apiserver_logs
+        cmd: sh -c "for i in `kubectl get pods --all-namespaces -l k8s-app=kube-apiserver -o name`;
+          do kubectl logs $i --namespace kube-system > kube-apiserver.log; done"
+      - name: controller_logs
+        cmd: sh -c "for i in `kubectl get pods --all-namespaces -l k8s-app=kube-controller -o name`;
+          do kubectl logs $i --namespace kube-system > kube-controller.log; done"
+      - name: scheduler_logs
+        cmd: sh -c "for i in `kubectl get pods --all-namespaces -l k8s-app=kube-scheduler -o name`;
+          do kubectl logs $i --namespace kube-system > kube-scheduler.log; done"
+      - name: proxy_logs
+        cmd: sh -c "for i in `kubectl get pods --all-namespaces -l k8s-app=kube-proxy -o name`;
+          do kubectl logs $i --namespace kube-system > kube-proxy.log; done"
+      - name: nginx_logs
+        cmd: sh -c "for i in `kubectl get pods --all-namespaces -l k8s-app=kube-nginx -o name`;
+          do kubectl logs $i --namespace kube-system > kube-nginx.log; done"
+      - name: flannel_logs
+        cmd: sh -c "for i in `kubectl get pods --all-namespaces -l app=flannel -o name`;
+          do kubectl logs $i --namespace kube-system flannel-container > flannel.log; done"
+      - name: canal_logs
+        cmd: sh -c "for i in `kubectl get pods --all-namespaces -l k8s-app=canal-node -o name`;
+          do kubectl logs $i --namespace kube-system flannel > flannel.log; done"
+      - name: calico_policy_logs
+        cmd: sh -c "for i in `kubectl get pods --all-namespaces -l k8s-app=calico-policy -o name`;
+          do kubectl logs $i --namespace kube-system calico-policy-controller > calico-policy-controller.log; done"
 
     logs:
       - /var/log/syslog
@@ -38,6 +68,15 @@
       - /var/log/calico/bird6/current
       - /var/log/calico/felix/current
       - /var/log/calico/confd/current
+      - weave.log
+      - kubedns.log
+      - kube-apiserver.log
+      - kube-controller.log
+      - kube-scheduler.log
+      - kube-proxy.log
+      - kube-nginx.log
+      - flannel.log
+      - calico-policy-controller.log
 
   tasks:
     - name: Storing commands output
@@ -47,10 +86,6 @@
       with_items: "{{commands}}"
       no_log: True
 
-    - debug: var=item
-      with_items: "{{output.results}}"
-      when: debug
-
     - name: Fetch results
       fetch: src={{ item.name }} dest=/tmp/collect-info/commands
       with_items: "{{commands}}"
@@ -60,7 +95,7 @@
       with_items: "{{logs}}"
 
     - name: Pack results and logs
-      local_action: shell GZIP=-9 tar --remove-files -cvzf logs.tar.gz -C /tmp collect-info
+      local_action: shell GZIP=-9 tar --remove-files -cvzf {{dir|default(".")}}/logs.tar.gz -C /tmp collect-info
       run_once: true
 
     - name: Clean up collected command outputs
diff --git a/tests/cloud_playbooks/templates/boto.j2 b/tests/cloud_playbooks/templates/boto.j2
new file mode 100644
index 0000000000000000000000000000000000000000..660f1a0a30f544a65fa7e7579867d0b3d282b02c
--- /dev/null
+++ b/tests/cloud_playbooks/templates/boto.j2
@@ -0,0 +1,11 @@
+[Credentials]
+gs_access_key_id = {{ gs_key }}
+gs_secret_access_key = {{ gs_skey }}
+[Boto]
+https_validate_certificates = True
+[GoogleCompute]
+[GSUtil]
+default_project_id = {{ gce_project_id }}
+content_language = en
+default_api_version = 2
+[OAuth2]
diff --git a/tests/cloud_playbooks/files/gcs_life.json b/tests/cloud_playbooks/templates/gcs_life.json.j2
similarity index 59%
rename from tests/cloud_playbooks/files/gcs_life.json
rename to tests/cloud_playbooks/templates/gcs_life.json.j2
index eaab30b4fa55d31ec33521f045b39213ff2078f7..a666c8feffd1668ece36ba95a24ed6c4043dd3d8 100644
--- a/tests/cloud_playbooks/files/gcs_life.json
+++ b/tests/cloud_playbooks/templates/gcs_life.json.j2
@@ -3,7 +3,7 @@
 	[
 		{
 			"action": {"type": "Delete"},
-			"condition": {"age": 2}
+			"condition": {"age": {{expire_days}}}
 		}
 	]
 }
diff --git a/tests/cloud_playbooks/upload-logs-gcs.yml b/tests/cloud_playbooks/upload-logs-gcs.yml
index 12013798dad348f018a9937f2ffbb3fa66eaea06..80d651ba440670b74323dc2a98efeeec5a81c85b 100644
--- a/tests/cloud_playbooks/upload-logs-gcs.yml
+++ b/tests/cloud_playbooks/upload-logs-gcs.yml
@@ -3,65 +3,73 @@
   become: false
   gather_facts: no
 
+  vars:
+    expire_days: 2
+
   tasks:
     - name: Generate uniq bucket name prefix
-      shell: date +%s | sha256sum | base64 | head -c 32
+      shell: date +%Y%m%d
       register: out
 
     - name: replace_test_id
       set_fact:
-        test_name: "kargo-{{ commit }}-{{ pr }}-{{ out.stdout|lower }}-{{ test_id | regex_replace('\\.', '-') }}"
+        test_name: "kargo-ci-{{ out.stdout }}"
+
+    - set_fact:
+        file_name: "{{ostype}}-{{kube_network_plugin}}-{{commit}}-logs.tar.gz"
 
     - name: Create a bucket
       gc_storage:
         bucket: "{{ test_name }}"
         mode: create
-        permission: private
+        permission: public-read
         gs_access_key: "{{ gs_key }}"
         gs_secret_key: "{{ gs_skey }}"
       no_log: True
 
+    - name: Create a lifecycle template for the bucket
+      template:
+        src: gcs_life.json.j2
+        dest: "{{dir}}/gcs_life.json"
+
+    - name: Create a boto config to access GCS
+      template:
+        src: boto.j2
+        dest: "{{dir}}/.boto"
+      no_log: True
+
     - name: Download gsutil cp installer
       get_url:
         url: https://dl.google.com/dl/cloudsdk/channels/rapid/install_google_cloud_sdk.bash
-        dest: /tmp/gcp-installer.sh
+        dest: "{{dir}}/gcp-installer.sh"
 
     - name: Get gsutil tool
-      script: /tmp/gcp-installer.sh
+      script: "{{dir}}/gcp-installer.sh"
       environment:
         CLOUDSDK_CORE_DISABLE_PROMPTS: 1
+        CLOUDSDK_INSTALL_DIR: "{{dir}}"
       no_log: True
-
-    - name: Create a lifecycle template for the bucket
-      file: src=gcs_life.json path=/tmp/gcs_life.json
-
-    - name: Hack the boto config for GCS access keys
-      lineinfile:
-        dest: .boto
-        line: "gs_access_key_id = {{ gs_key }}"
-        regexp: "^#gs_access_key_id = .*$"
-      no_log: True
-
-    - name: Hack the boto config for GCS secret access keys
-      lineinfile:
-        dest: .boto
-        line: "gs_secret_access_key = {{ gs_skey }}"
-        regexp: "^#gs_secret_access_key = .*$"
-      no_log: True
+      ignore_errors: true
 
     - name: Apply the lifecycle rules
-      shell: bash google-cloud-sdk/bin/gsutil lifecycle set /tmp/gcs_life.json gs://{{ test_name }}
+      command: "{{dir}}/google-cloud-sdk/bin/gsutil lifecycle set {{dir}}/gcs_life.json gs://{{test_name}}"
       environment:
-        BOTO_CONFIG: .boto
+        BOTO_CONFIG: "{{dir}}/.boto"
+      no_log: True
 
     - name: Upload collected diagnostic info
       gc_storage:
         bucket: "{{ test_name }}"
         mode: put
-        permission: private
-        object: "build-{{ ostype }}-{{ kube_network_plugin }}-logs.tar.gz"
-        src: logs.tar.gz
+        permission: public-read
+        object: "{{ file_name }}"
+        src: "{{dir}}/logs.tar.gz"
         headers: '{"Content-Encoding": "x-gzip"}'
         gs_access_key: "{{ gs_key }}"
         gs_secret_key: "{{ gs_skey }}"
+        expiration: "{{expire_days * 36000|int}}"
       ignore_errors: true
+      no_log: True
+
+    - debug:
+        msg: "A public url https://storage.googleapis.com/{{test_name}}/{{file_name}}"