diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 32d024af0119bc29bb8e929c35c8a34aac13089f..8a145aa4024ce051f8a18144aab59b52cecb5ee8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -80,3 +80,4 @@ include:
   - .gitlab-ci/terraform.yml
   - .gitlab-ci/packet.yml
   - .gitlab-ci/vagrant.yml
+  - .gitlab-ci/molecule.yml
diff --git a/.gitlab-ci/molecule.yml b/.gitlab-ci/molecule.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5f8e02e4c753bf6a39986057957fec5f8a7ee39c
--- /dev/null
+++ b/.gitlab-ci/molecule.yml
@@ -0,0 +1,93 @@
+---
+
+.molecule:
+  tags: [c3.small.x86]
+  only: [/^pr-.*$/]
+  except: ['triggers']
+  image: quay.io/kubespray/vagrant:$KUBESPRAY_VERSION
+  services: []
+  stage: deploy-part1
+  before_script:
+    - tests/scripts/rebase.sh
+    - apt-get update && apt-get install -y python3-pip
+    - update-alternatives --install /usr/bin/python python /usr/bin/python3 10
+    - python -m pip uninstall -y ansible ansible-base ansible-core
+    - python -m pip install -r tests/requirements.txt
+    - ./tests/scripts/vagrant_clean.sh
+  script:
+    - ./tests/scripts/molecule_run.sh
+  after_script:
+    - chronic ./tests/scripts/molecule_logs.sh
+  artifacts:
+    when: always
+    paths:
+      - molecule_logs/
+
+# CI template for periodic CI jobs
+# Enabled when PERIODIC_CI_ENABLED var is set
+.molecule_periodic:
+  only:
+    variables:
+      - $PERIODIC_CI_ENABLED
+  allow_failure: true
+  extends: .molecule
+
+molecule_full:
+  extends: .molecule_periodic
+
+molecule_no_container_engines:
+  extends: .molecule
+  script:
+    - ./tests/scripts/molecule_run.sh -e container-engine
+  when: on_success
+
+molecule_docker:
+  extends: .molecule
+  script:
+    - ./tests/scripts/molecule_run.sh -i container-engine/docker
+  when: on_success
+
+molecule_containerd:
+  extends: .molecule
+  script:
+    - ./tests/scripts/molecule_run.sh -i container-engine/containerd
+  when: on_success
+
+molecule_cri-o:
+  extends: .molecule
+  stage: deploy-part2
+  script:
+    - ./tests/scripts/molecule_run.sh -i container-engine/cri-o
+  when: on_success
+
+molecule_cri-dockerd:
+  extends: .molecule
+  stage: deploy-part2
+  script:
+    - ./tests/scripts/molecule_run.sh -i container-engine/cri-dockerd
+  when: on_success
+
+# Stage 3 container engines don't get as much attention so allow them to fail
+molecule_kata:
+  extends: .molecule
+  stage: deploy-part3
+  allow_failure: true
+  script:
+    - ./tests/scripts/molecule_run.sh -i container-engine/kata-containers
+  when: on_success
+
+molecule_gvisor:
+  extends: .molecule
+  stage: deploy-part3
+  allow_failure: true
+  script:
+    - ./tests/scripts/molecule_run.sh -i container-engine/gvisor
+  when: on_success
+
+molecule_youki:
+  extends: .molecule
+  stage: deploy-part3
+  allow_failure: true
+  script:
+    - ./tests/scripts/molecule_run.sh -i container-engine/youki
+  when: on_success
diff --git a/.gitlab-ci/vagrant.yml b/.gitlab-ci/vagrant.yml
index a13028ddaf0bd4a1e93d2f0bf39190efcc849132..8c0f4a21d03845d69d845342f367de88ff3e5df9 100644
--- a/.gitlab-ci/vagrant.yml
+++ b/.gitlab-ci/vagrant.yml
@@ -1,28 +1,5 @@
 ---
 
-molecule_tests:
-  tags: [c3.small.x86]
-  only: [/^pr-.*$/]
-  except: ['triggers']
-  image: quay.io/kubespray/vagrant:$KUBESPRAY_VERSION
-  services: []
-  stage: deploy-part1
-  before_script:
-    - tests/scripts/rebase.sh
-    - apt-get update && apt-get install -y python3-pip
-    - update-alternatives --install /usr/bin/python python /usr/bin/python3 10
-    - python -m pip uninstall -y ansible ansible-base ansible-core
-    - python -m pip install -r tests/requirements.txt
-    - ./tests/scripts/vagrant_clean.sh
-  script:
-    - ./tests/scripts/molecule_run.sh
-  after_script:
-    - chronic ./tests/scripts/molecule_logs.sh
-  artifacts:
-    when: always
-    paths:
-      - molecule_logs/
-
 .vagrant:
   extends: .testcases
   variables:
diff --git a/tests/scripts/molecule_run.sh b/tests/scripts/molecule_run.sh
index ff2966fd0276fd7df73fda3e64b7628a9bc1940a..9604238e13b21ca8b5333916264307d539cf274a 100755
--- a/tests/scripts/molecule_run.sh
+++ b/tests/scripts/molecule_run.sh
@@ -1,10 +1,32 @@
 #!/bin/bash
-set -euxo pipefail
+set -euxo pipefail -o noglob
 
 export LC_ALL=C.UTF-8
 export LANG=C.UTF-8
 
-for d in $(find roles -name molecule -type d)
+_PATH='roles'
+_EXCLUDE=""
+
+while [[ $# -gt 0 ]] ; do
+    case $1 in
+        -e|--exclude)
+            _EXCLUDE="${_EXCLUDE} -not -path ${_PATH}/$2/*"
+            shift
+            shift
+            ;;
+        -i|--include)
+            _PATH="${_PATH}/$2"
+            shift
+            shift
+            ;;
+        -h|--help)
+            echo "Usage: molecule_run.sh [-h|--help] [-e|--exclude] [-i|--include]"
+            exit 0
+            ;;
+    esac
+done
+
+for d in $(find ${_PATH} ${_EXCLUDE} -name molecule -type d)
 do
     pushd $(dirname $d)
     molecule test --all