Browse Source
Merge pull request #11530 from VannTen/ci/cleanup_with_k8s_gc
Merge pull request #11530 from VannTen/ci/cleanup_with_k8s_gc
[CI] Use Kubernetes GC to clean kubevirt VMs (packet-* jobs)pull/11714/head
Kubernetes Prow Robot
1 week ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 152 additions and 352 deletions
Unified View
Diff Options
-
7.gitlab-ci.yml
-
8.gitlab-ci/packet.yml
-
23tests/Makefile
-
8tests/cloud_playbooks/cleanup-packet.yml
-
3tests/cloud_playbooks/create-packet.yml
-
11tests/cloud_playbooks/delete-packet.yml
-
16tests/cloud_playbooks/roles/cleanup-packet-ci/tasks/main.yml
-
17tests/cloud_playbooks/roles/packet-ci/tasks/cleanup-old-vms.yml
-
50tests/cloud_playbooks/roles/packet-ci/tasks/create-vms.yml
-
30tests/cloud_playbooks/roles/packet-ci/tasks/delete-vms.yml
-
59tests/cloud_playbooks/roles/packet-ci/tasks/main.yml
-
98tests/cloud_playbooks/roles/packet-ci/templates/inventory.j2
-
97tests/cloud_playbooks/roles/packet-ci/templates/vm.yml.j2
-
44tests/cloud_playbooks/roles/packet-ci/vars/main.yml
-
5tests/common/_kubespray_test_settings.yml
-
10tests/common_vars.yml
-
2tests/scripts/testcases_cleanup.sh
-
16tests/scripts/testcases_run.sh
@ -1,8 +0,0 @@ |
|||||
--- |
|
||||
|
|
||||
- name: Cleanup packet vms |
|
||||
hosts: localhost |
|
||||
gather_facts: false |
|
||||
become: true |
|
||||
roles: |
|
||||
- { role: cleanup-packet-ci } |
|
@ -1,11 +0,0 @@ |
|||||
--- |
|
||||
|
|
||||
- name: Terminate Packet VMs |
|
||||
hosts: localhost |
|
||||
gather_facts: false |
|
||||
become: true |
|
||||
vars: |
|
||||
ci_job_name: "{{ lookup('env', 'CI_JOB_NAME') }}" |
|
||||
test_name: "{{ test_id | regex_replace('\\.', '-') }}" |
|
||||
roles: |
|
||||
- { role: packet-ci, vm_cleanup: true } |
|
@ -1,16 +0,0 @@ |
|||||
--- |
|
||||
|
|
||||
- name: Fetch a list of namespaces |
|
||||
kubernetes.core.k8s_info: |
|
||||
api_version: v1 |
|
||||
kind: Namespace |
|
||||
label_selectors: |
|
||||
- cijobs = true |
|
||||
register: namespaces |
|
||||
|
|
||||
- name: Delete stale namespaces for more than 2 hours |
|
||||
command: "kubectl delete namespace {{ item.metadata.name }}" |
|
||||
failed_when: false |
|
||||
loop: "{{ namespaces.resources }}" |
|
||||
when: |
|
||||
- (now() - (item.metadata.creationTimestamp | to_datetime("%Y-%m-%dT%H:%M:%SZ"))).total_seconds() >= 7200 |
|
@ -1,17 +0,0 @@ |
|||||
--- |
|
||||
|
|
||||
- name: Fetch a list of namespaces |
|
||||
kubernetes.core.k8s_info: |
|
||||
api_version: v1 |
|
||||
kind: Namespace |
|
||||
label_selectors: |
|
||||
- cijobs = true |
|
||||
- branch = {{ branch_name_sane }} |
|
||||
register: namespaces |
|
||||
|
|
||||
- name: Delete older namespaces |
|
||||
command: "kubectl delete namespace {{ item.metadata.name }}" |
|
||||
failed_when: false |
|
||||
loop: "{{ namespaces.resources }}" |
|
||||
when: |
|
||||
- (item.metadata.labels.pipeline_id | int) < (pipeline_id | int) |
|
@ -1,50 +0,0 @@ |
|||||
--- |
|
||||
|
|
||||
- name: "Create CI namespace {{ test_name }} for test vms" |
|
||||
shell: |- |
|
||||
kubectl create namespace {{ test_name }} && |
|
||||
kubectl label namespace {{ test_name }} cijobs=true branch="{{ branch_name_sane }}" pipeline_id="{{ pipeline_id }}" |
|
||||
changed_when: false |
|
||||
|
|
||||
- name: "Create temp dir /tmp/{{ test_name }} for CI files" |
|
||||
file: |
|
||||
path: "/tmp/{{ test_name }}" |
|
||||
state: directory |
|
||||
mode: "0755" |
|
||||
|
|
||||
- name: Template vm files for CI job |
|
||||
set_fact: |
|
||||
vms_files: "{{ vms_files + [lookup('ansible.builtin.template', 'vm.yml.j2') | from_yaml] }}" |
|
||||
vars: |
|
||||
vms_files: [] |
|
||||
loop: "{{ range(1, vm_count | int + 1, 1) | list }}" |
|
||||
loop_control: |
|
||||
index_var: vm_id |
|
||||
|
|
||||
- name: Start vms for CI job |
|
||||
kubernetes.core.k8s: |
|
||||
definition: "{{ item }}" |
|
||||
changed_when: false |
|
||||
loop: "{{ vms_files }}" |
|
||||
|
|
||||
- name: Wait for vms to have ipaddress assigned |
|
||||
shell: "set -o pipefail && kubectl get vmis -n {{ test_name }} instance-{{ vm_id }} -o json | jq '.status.interfaces[].ipAddress' | tr -d '\"'" |
|
||||
args: |
|
||||
executable: /bin/bash |
|
||||
changed_when: false |
|
||||
register: vm_ips |
|
||||
loop: "{{ range(1, vm_count | int + 1, 1) | list }}" |
|
||||
loop_control: |
|
||||
index_var: vm_id |
|
||||
retries: 20 |
|
||||
delay: 15 |
|
||||
until: |
|
||||
- vm_ips.stdout | ansible.utils.ipaddr |
|
||||
|
|
||||
- name: "Create inventory for CI test in file /tmp/{{ test_name }}/inventory" |
|
||||
template: |
|
||||
src: "inventory.j2" |
|
||||
dest: "{{ inventory_path }}" |
|
||||
mode: "0644" |
|
||||
vars: |
|
||||
vms: "{{ vm_ips }}" |
|
@ -1,30 +0,0 @@ |
|||||
--- |
|
||||
|
|
||||
- name: Check if temp directory for {{ test_name }} exists |
|
||||
stat: |
|
||||
path: "/tmp/{{ test_name }}" |
|
||||
get_attributes: false |
|
||||
get_checksum: false |
|
||||
get_mime: false |
|
||||
register: temp_dir_details |
|
||||
|
|
||||
- name: "Cleanup temp directory for {{ test_name }}" |
|
||||
file: |
|
||||
path: "/tmp/{{ test_name }}" |
|
||||
state: absent |
|
||||
|
|
||||
- name: "Cleanup namespace for {{ test_name }}" |
|
||||
command: "kubectl delete namespace {{ test_name }}" |
|
||||
changed_when: false |
|
||||
|
|
||||
- name: Wait for namespace {{ test_name }} to be fully deleted |
|
||||
command: kubectl get ns {{ test_name }} |
|
||||
register: delete_namespace |
|
||||
failed_when: |
|
||||
- delete_namespace.rc == 0 |
|
||||
changed_when: |
|
||||
- delete_namespace.rc == 0 |
|
||||
retries: 12 |
|
||||
delay: 10 |
|
||||
until: |
|
||||
- delete_namespace.rc != 0 |
|
@ -1,17 +1,52 @@ |
|||||
--- |
--- |
||||
|
|
||||
- name: "Include custom vars for ci job: {{ ci_job_name }}" |
|
||||
|
- name: Include custom vars for ci job |
||||
include_vars: "../files/{{ ci_job_name }}.yml" |
include_vars: "../files/{{ ci_job_name }}.yml" |
||||
|
|
||||
- name: Cleamup old VMs |
|
||||
import_tasks: cleanup-old-vms.yml |
|
||||
|
- name: Start vms for CI job |
||||
|
vars: |
||||
|
# Workaround for compatibility when testing upgrades with old == before e9d406ed088d4291ef1d9018c170a4deed2bf928 |
||||
|
# TODO: drop after 2.27.0 |
||||
|
legacy_groups: "{{ (['kube_control_plane', 'kube_node', 'calico_rr'] | intersect(item) | length > 0) | ternary(['k8s_cluster'], []) }}" |
||||
|
tvars: |
||||
|
kubespray_groups: "{{ item + legacy_groups }}" |
||||
|
kubernetes.core.k8s: |
||||
|
definition: "{{ lookup('template', 'vm.yml.j2', template_vars=tvars) }}" |
||||
|
loop: "{{ scenarios[mode | d('default')] }}" |
||||
|
|
||||
|
- name: Wait for vms to have IP addresses |
||||
|
kubernetes.core.k8s_info: |
||||
|
api_version: kubevirt.io/v1 |
||||
|
kind: VirtualMachineInstance |
||||
|
label_selectors: |
||||
|
- "ci_job_id={{ ci_job_id }}" |
||||
|
namespace: "{{ pod_namespace }}" |
||||
|
register: vmis |
||||
|
until: vmis.resources |
||||
|
| map(attribute='status.interfaces.0') |
||||
|
| rejectattr('ipAddress', 'defined') == [] |
||||
|
retries: 30 |
||||
|
delay: 10 |
||||
|
|
||||
- name: Create VMs |
|
||||
import_tasks: create-vms.yml |
|
||||
when: |
|
||||
- not vm_cleanup |
|
||||
|
- name: Massage VirtualMachineInstance data into an Ansible inventory structure |
||||
|
vars: |
||||
|
ips: "{{ vmis.resources | map(attribute='status.interfaces.0.ipAddress') }}" |
||||
|
names: "{{ vmis.resources | map(attribute='metadata.name') }}" |
||||
|
_groups: "{{ vmis.resources | map(attribute='metadata.annotations.ansible_groups') | map('split', ',') }}" |
||||
|
hosts: "{{ ips | zip(_groups, names) |
||||
|
| map('zip', ['ansible_host', 'ansible_groups', 'k8s_vmi_name']) |
||||
|
| map('map', 'reverse') | map('community.general.dict') }}" |
||||
|
loop: "{{ hosts | map(attribute='ansible_groups') | flatten | unique }}" |
||||
|
set_fact: |
||||
|
ci_inventory: "{{ ci_inventory|d({}) | combine({ |
||||
|
item: { |
||||
|
'hosts': hosts | selectattr('ansible_groups', 'contains', item) |
||||
|
| rekey_on_member('k8s_vmi_name') |
||||
|
} |
||||
|
}) |
||||
|
}}" |
||||
|
|
||||
- name: Delete VMs |
|
||||
import_tasks: delete-vms.yml |
|
||||
when: |
|
||||
- vm_cleanup | default(false) |
|
||||
|
- name: Create inventory for CI tests |
||||
|
copy: |
||||
|
content: "{{ ci_inventory | to_yaml }}" |
||||
|
dest: "{{ inventory_path }}/ci_inventory.yml" |
||||
|
mode: "0644" |
@ -1,98 +0,0 @@ |
|||||
[all] |
|
||||
{% for instance in vms.results %} |
|
||||
instance-{{ loop.index }} ansible_host={{instance.stdout}} |
|
||||
{% endfor %} |
|
||||
|
|
||||
{% if mode == "separate" %} |
|
||||
[kube_control_plane] |
|
||||
instance-1 |
|
||||
|
|
||||
[kube_node] |
|
||||
instance-2 |
|
||||
|
|
||||
[etcd] |
|
||||
instance-3 |
|
||||
{% elif mode == "ha" %} |
|
||||
[kube_control_plane] |
|
||||
instance-1 |
|
||||
instance-2 |
|
||||
|
|
||||
[kube_node] |
|
||||
instance-3 |
|
||||
|
|
||||
[etcd] |
|
||||
instance-1 |
|
||||
instance-2 |
|
||||
instance-3 |
|
||||
{% elif mode == "default" %} |
|
||||
[kube_control_plane] |
|
||||
instance-1 |
|
||||
|
|
||||
[kube_node] |
|
||||
instance-2 |
|
||||
|
|
||||
[etcd] |
|
||||
instance-1 |
|
||||
{% elif mode == "all-in-one" %} |
|
||||
[kube_control_plane] |
|
||||
instance-1 |
|
||||
|
|
||||
[kube_node] |
|
||||
instance-1 |
|
||||
|
|
||||
[etcd] |
|
||||
instance-1 |
|
||||
{% elif mode == "ha-recover" %} |
|
||||
[kube_control_plane] |
|
||||
instance-1 |
|
||||
instance-2 |
|
||||
|
|
||||
[kube_node] |
|
||||
instance-3 |
|
||||
|
|
||||
[etcd] |
|
||||
instance-3 |
|
||||
instance-1 |
|
||||
instance-2 |
|
||||
|
|
||||
[broken_kube_control_plane] |
|
||||
instance-2 |
|
||||
|
|
||||
[broken_etcd] |
|
||||
instance-2 etcd_member_name=etcd3 |
|
||||
{% elif mode == "ha-recover-noquorum" %} |
|
||||
[kube_control_plane] |
|
||||
instance-3 |
|
||||
instance-1 |
|
||||
instance-2 |
|
||||
|
|
||||
[kube_node] |
|
||||
instance-3 |
|
||||
|
|
||||
[etcd] |
|
||||
instance-3 |
|
||||
instance-1 |
|
||||
instance-2 |
|
||||
|
|
||||
[broken_kube_control_plane] |
|
||||
instance-1 |
|
||||
instance-2 |
|
||||
|
|
||||
[broken_etcd] |
|
||||
instance-1 etcd_member_name=etcd2 |
|
||||
instance-2 etcd_member_name=etcd3 |
|
||||
{% elif mode == "node-etcd-client" %} |
|
||||
[kube_control_plane] |
|
||||
instance-1 |
|
||||
|
|
||||
[etcd] |
|
||||
instance-1 |
|
||||
instance-2 |
|
||||
instance-3 |
|
||||
|
|
||||
[kube_node] |
|
||||
instance-1 |
|
||||
instance-2 |
|
||||
instance-3 |
|
||||
instance-4 |
|
||||
{% endif %} |
|
@ -1,54 +1,59 @@ |
|||||
--- |
--- |
||||
apiVersion: kubevirt.io/v1alpha3 |
|
||||
kind: VirtualMachine |
|
||||
|
apiVersion: kubevirt.io/v1 |
||||
|
kind: VirtualMachineInstance |
||||
metadata: |
metadata: |
||||
name: "instance-{{ vm_id }}" |
|
||||
namespace: "{{ test_name }}" |
|
||||
|
generateName: test-vm- |
||||
|
namespace: {{ pod_namespace }} |
||||
annotations: |
annotations: |
||||
kubespray.com/ci.template-path: "tests/cloud_playbooks/roles/packet-ci/templates/vm.yml.j2" |
kubespray.com/ci.template-path: "tests/cloud_playbooks/roles/packet-ci/templates/vm.yml.j2" |
||||
|
ansible_groups: "{{ kubespray_groups | join(',') }}" |
||||
|
# This does not use a dns prefix because dots are hard to escape with map(attribute=) in Jinja |
||||
labels: |
labels: |
||||
kubevirt.io/os: {{ cloud_image }} |
kubevirt.io/os: {{ cloud_image }} |
||||
|
kubevirt.io/size: small |
||||
|
kubevirt.io/domain: "{{ test_name }}" |
||||
|
ci_job_id: "{{ ci_job_id }}" |
||||
|
ci_job_name: "{{ ci_job_name }}" |
||||
|
# leverage the Kubernetes GC for resources cleanup |
||||
|
ownerReferences: |
||||
|
- apiVersion: v1 |
||||
|
kind: Pod |
||||
|
name: "{{ pod_name }}" |
||||
|
uid: "{{ pod_uid }}" |
||||
spec: |
spec: |
||||
running: true |
|
||||
template: |
|
||||
metadata: |
|
||||
labels: |
|
||||
kubevirt.io/size: small |
|
||||
kubevirt.io/domain: "{{ test_name }}" |
|
||||
spec: |
|
||||
domain: |
|
||||
devices: |
|
||||
blockMultiQueue: true |
|
||||
disks: |
|
||||
- disk: |
|
||||
bus: virtio |
|
||||
name: containervolume |
|
||||
cache: writethrough |
|
||||
- disk: |
|
||||
bus: virtio |
|
||||
name: cloudinitvolume |
|
||||
interfaces: |
|
||||
- name: default |
|
||||
bridge: {} |
|
||||
cpu: |
|
||||
cores: {{ vm_cpu_cores }} |
|
||||
sockets: {{ vm_cpu_sockets }} |
|
||||
threads: {{ vm_cpu_threads }} |
|
||||
resources: |
|
||||
requests: |
|
||||
memory: "{{ vm_memory * memory_allocation_ratio }}Mi" |
|
||||
cpu: {{ vm_cpu_cores * cpu_allocation_ratio }} |
|
||||
limits: |
|
||||
memory: "{{ vm_memory }}Mi" |
|
||||
cpu: {{ vm_cpu_cores }} |
|
||||
networks: |
|
||||
|
domain: |
||||
|
devices: |
||||
|
blockMultiQueue: true |
||||
|
disks: |
||||
|
- disk: |
||||
|
bus: virtio |
||||
|
name: containervolume |
||||
|
cache: writethrough |
||||
|
- disk: |
||||
|
bus: virtio |
||||
|
name: cloudinitvolume |
||||
|
interfaces: |
||||
- name: default |
- name: default |
||||
pod: {} |
|
||||
terminationGracePeriodSeconds: 0 |
|
||||
volumes: |
|
||||
- name: containervolume |
|
||||
containerDisk: |
|
||||
image: quay.io/kubespray/vm-{{ cloud_image }} |
|
||||
- name: cloudinitvolume |
|
||||
cloudInitNoCloud: |
|
||||
userDataBase64: {{ cloud_init[cloud_image] }} |
|
||||
|
bridge: {} |
||||
|
cpu: |
||||
|
cores: {{ vm_cpu_cores }} |
||||
|
sockets: {{ vm_cpu_sockets }} |
||||
|
threads: {{ vm_cpu_threads }} |
||||
|
resources: |
||||
|
requests: |
||||
|
memory: "{{ vm_memory * memory_allocation_ratio }}Mi" |
||||
|
cpu: {{ vm_cpu_cores * cpu_allocation_ratio }} |
||||
|
limits: |
||||
|
memory: "{{ vm_memory }}Mi" |
||||
|
cpu: {{ vm_cpu_cores }} |
||||
|
networks: |
||||
|
- name: default |
||||
|
pod: {} |
||||
|
terminationGracePeriodSeconds: 0 |
||||
|
volumes: |
||||
|
- name: containervolume |
||||
|
containerDisk: |
||||
|
image: quay.io/kubespray/vm-{{ cloud_image }} |
||||
|
- name: cloudinitvolume |
||||
|
cloudInitNoCloud: |
||||
|
userDataBase64: {{ cloud_init[cloud_image] }} |
@ -1,11 +1,37 @@ |
|||||
--- |
--- |
||||
_vm_count_dict: |
|
||||
separate: 3 |
|
||||
ha: 3 |
|
||||
ha-recover: 3 |
|
||||
ha-recover-noquorum: 3 |
|
||||
all-in-one: 1 |
|
||||
node-etcd-client: 4 |
|
||||
default: 2 |
|
||||
|
# This is a list of nodes with groups for each scenario/cluster layouts |
||||
|
scenarios: |
||||
|
separate: |
||||
|
- ['kube_control_plane'] |
||||
|
- ['kube_node'] |
||||
|
- ['etcd'] |
||||
|
ha: |
||||
|
- ['kube_control_plane', 'etcd'] |
||||
|
- ['kube_control_plane', 'etcd'] |
||||
|
- ['kube_node', 'etcd'] |
||||
|
default: |
||||
|
- ['kube_control_plane', 'etcd'] |
||||
|
- ['kube_node'] |
||||
|
all-in-one: |
||||
|
- ['kube_control_plane', 'etcd', 'kube_node'] |
||||
|
ha-recover: |
||||
|
- ['kube_control_plane', 'etcd'] |
||||
|
- ['kube_control_plane', 'etcd', 'broken_kube_control_plane', 'broken_etcd'] |
||||
|
- ['kube_node', 'etcd'] |
||||
|
ha-recover-noquorum: |
||||
|
- ['kube_control_plane', 'etcd', 'broken_kube_control_plane', 'broken_etcd'] |
||||
|
- ['kube_control_plane', 'etcd', 'broken_kube_control_plane', 'broken_etcd'] |
||||
|
- ['kube_node', 'etcd'] |
||||
|
node-etcd-client: |
||||
|
- ['kube_node', 'kube_control_plane', 'etcd'] |
||||
|
- ['kube_node', 'etcd'] |
||||
|
- ['kube_node', 'etcd'] |
||||
|
- ['kube_node'] |
||||
|
|
||||
vm_count: "{{ _vm_count_dict[mode | d('default')] }}" |
|
||||
|
# Get pod metadata / CI vars from environment |
||||
|
|
||||
|
ci_job_id: "{{ lookup('ansible.builtin.env', 'CI_JOB_ID', default=undefined) }}" |
||||
|
ci_job_name: "{{ lookup('ansible.builtin.env', 'CI_JOB_NAME', default=undefined) }}" |
||||
|
pod_name: "{{ lookup('ansible.builtin.env', 'POD_NAME', default=undefined) }}" |
||||
|
pod_uid: "{{ lookup('ansible.builtin.env', 'POD_UID', default=undefined) }}" |
||||
|
pod_namespace: "{{ lookup('ansible.builtin.env', 'POD_NAMESPACE', default=undefined) }}" |
@ -1,5 +0,0 @@ |
|||||
--- |
|
||||
# Kubespray settings for tests |
|
||||
deploy_netchecker: true |
|
||||
dns_min_replicas: 1 |
|
||||
unsafe_show_logs: true |
|
Write
Preview
Loading…
Cancel
Save