diff --git a/test-infra/image-builder/Makefile b/test-infra/image-builder/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..82dba642889f4ef9bcda3aaa047cf245bf78d303
--- /dev/null
+++ b/test-infra/image-builder/Makefile
@@ -0,0 +1,2 @@
+deploy:
+	ansible-playbook -i hosts.ini -e docker_password=$(docker_password) cluster.yml
diff --git a/test-infra/image-builder/cluster.yml b/test-infra/image-builder/cluster.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1601bddd8210374925bb3391581aea20d2c63497
--- /dev/null
+++ b/test-infra/image-builder/cluster.yml
@@ -0,0 +1,5 @@
+- hosts: image-builder
+  tasks:
+    - name: kubevirt-images
+      include_role:
+        name: kubevirt-images
diff --git a/test-infra/image-builder/hosts.ini b/test-infra/image-builder/hosts.ini
new file mode 100644
index 0000000000000000000000000000000000000000..f939dda73c2c9e40656233f4e549d0720e1a2a5b
--- /dev/null
+++ b/test-infra/image-builder/hosts.ini
@@ -0,0 +1,4 @@
+image-builder-1 ansible_ssh_host=147.75.100.185 ansible_ssh_user=root
+
+[image-builder]
+image-builder-1
diff --git a/test-infra/image-builder/roles/kubevirt-images/defaults/main.yml b/test-infra/image-builder/roles/kubevirt-images/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..717fa605c8759ebcb6b95e0b3d5925aacbc87910
--- /dev/null
+++ b/test-infra/image-builder/roles/kubevirt-images/defaults/main.yml
@@ -0,0 +1,36 @@
+images_dir: /images/base
+
+docker_user: kubespray+buildvmimages
+docker_host: quay.io
+registry: quay.io/kubespray
+
+images:
+    ubuntu-1604:
+      filename: xenial-server-cloudimg-amd64-disk1.img
+      url: https://storage.googleapis.com/kubespray-images/ubuntu/xenial-server-cloudimg-amd64-disk1.img
+      checksum: sha256:c0d099383cd064390b568e20d1c39a9c68ba864764404b70f754a7b1b2f808f7
+      converted: false
+
+    ubuntu-1804:
+      filename: bionic-server-cloudimg-amd64.img
+      url: https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img
+      checksum: sha256:c3d0e03f4245ffaabd7647e6dabf346b944a62b9934d0a89f3a04b4236386af2
+      converted: false
+
+    fedora-28:
+      filename: Fedora-Cloud-Base-28-1.1.x86_64.qcow2
+      url: https://mirror.netsite.dk/fedora/linux/releases/28/Cloud/x86_64/images/Fedora-Cloud-Base-28-1.1.x86_64.qcow2
+      checksum: sha256:d987209719fadaf81b8bff85c5d3590a1d3dac6357e4838fde8357086c49b5b4
+      converted: true
+
+    centos-7:
+      filename: CentOS-7-x86_64-GenericCloud-1809.qcow2
+      url: http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1809.qcow2
+      checksum: sha256:42c062df8a8c36991ec0282009dd52ac488461a3f7ee114fc21a765bfc2671c2
+      converted: true
+
+    debian-9:
+      filename: debian-9-openstack-amd64.qcow2
+      url: https://cdimage.debian.org/cdimage/openstack/current-9/debian-9-openstack-amd64.qcow2
+      checksum: sha256:01d9345ba7a6523d214d2eaabe07fe7b4b69b28e63d7a6b322521e99e5768719
+      converted: true
diff --git a/test-infra/image-builder/roles/kubevirt-images/tasks/main.yml b/test-infra/image-builder/roles/kubevirt-images/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..aa0ff34108fd2c03bb15c255841eb6e4affa79f6
--- /dev/null
+++ b/test-infra/image-builder/roles/kubevirt-images/tasks/main.yml
@@ -0,0 +1,53 @@
+---
+
+- name: Create image directory
+  file:
+    state: directory
+    path: " {{ images_dir }}"
+
+- name: Download images files
+  get_url:
+    url: "{{ item.value.url }}"
+    dest: "{{ images_dir }}/{{ item.value.filename }}"
+    checksum: "{{ item.value.checksum }}"
+  with_dict:
+    - "{{ images }}"
+
+- name: Convert images which is not in qcow2 format
+  command: qemu-img convert -O qcow2 {{ images_dir }}/{{ item.value.filename }} {{ images_dir }}/{{ item.key }}.qcow2
+  with_dict:
+    - "{{ images }}"
+  when:
+    - item.value.converted|bool != true
+  register: converted
+
+- name: Make sure all images are ending with qcow2
+  command: cp {{ images_dir }}/{{ item.value.filename }} {{ images_dir }}/{{ item.key }}.qcow2
+  with_dict:
+    - "{{ images }}"
+  when:
+    - item.value.converted|bool == true
+
+- name: Resize images
+  command: qemu-img resize {{ images_dir }}/{{ item.key }}.qcow2 +8G
+  with_dict:
+    - "{{ images }}"
+
+# STEP 2: Include the images inside a container
+- name: Template default Dockerfile
+  template:
+    src: Dockerfile
+    dest: "{{ images_dir }}/Dockerfile"
+
+- name: Create docker images for each OS
+  command: docker build -t {{registry}}/vm-{{ item.key }} --build-arg cloud_image="{{ item.key }}.qcow2" {{ images_dir }}
+  with_dict:
+    - "{{ images }}"
+
+- name: docker login
+  command: docker login -u="{{ docker_user }}" -p="{{ docker_password }}" "{{ docker_host }}"
+
+- name: docker push image
+  command: docker push {{ registry }}/vm-{{ item.key }}:latest
+  with_dict:
+    - "{{ images }}"
diff --git a/test-infra/image-builder/roles/kubevirt-images/templates/Dockerfile b/test-infra/image-builder/roles/kubevirt-images/templates/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..f776cbf65bb566da30e8a0dbcb2d5138271bc013
--- /dev/null
+++ b/test-infra/image-builder/roles/kubevirt-images/templates/Dockerfile
@@ -0,0 +1,6 @@
+FROM kubevirt/registry-disk-v1alpha
+
+ARG cloud_image
+MAINTAINER "The Kubespray Project" <kubespray@googlegroups.com>
+
+COPY $cloud_image /disk