diff --git a/.gitignore b/.gitignore
index 4629d0b27205cf910ed2005af1ea44e31a766c40..909a038d3d7288d5a93f565db8ee15c230788893 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@ ansible/*.retry
 # Ansible Galaxy roles
 ansible/roles/ahuffman.resolv/
 ansible/roles/jriguera.configdrive/
+ansible/roles/mrlesmithjr.manage-lvm/
 ansible/roles/MichaelRigart.interfaces/
 ansible/roles/resmo.ntp/
 ansible/roles/yatesr.timezone/
diff --git a/ansible/group_vars/all/seed b/ansible/group_vars/all/seed
new file mode 100644
index 0000000000000000000000000000000000000000..cec19f8f33c3b8b13c7fb230b7fc7896bcb29b90
--- /dev/null
+++ b/ansible/group_vars/all/seed
@@ -0,0 +1,39 @@
+---
+###############################################################################
+# Seed node configuration.
+
+# List of seed VM LVM volume groups. See mrlesmithjr.manage-lvm role for
+# format.
+seed_lvm_groups:
+  - "{{ seed_lvm_group_data }}"
+
+# Seed LVM volume group for data. See mrlesmithjr.manage-lvm role for format.
+seed_lvm_group_data:
+  vgname: data
+  disks: "{{ seed_lvm_group_data_disks | join(',') }}"
+  create: True
+  lvnames: "{{ seed_lvm_group_data_lvs }}"
+
+# List of disks for use by seed LVM data volume group. Default to an invalid
+# value to require configuration.
+seed_lvm_group_data_disks:
+  - changeme
+
+# List of LVM logical volumes for the data volume group.
+seed_lvm_group_data_lvs:
+  - "{{ seed_lvm_group_data_lv_docker_volumes }}"
+
+# Docker volumes LVM backing volume.
+seed_lvm_group_data_lv_docker_volumes:
+  lvname: docker-volumes
+  size: "{{ seed_lvm_group_data_lv_docker_volumes_size }}"
+  create: True
+  filesystem: "{{ seed_lvm_group_data_lv_docker_volumes_fs }}"
+  mount: True
+  mntp: /var/lib/docker/volumes
+
+# Size of docker volumes LVM backing volume.
+seed_lvm_group_data_lv_docker_volumes_size: 75%VG
+
+# Filesystem for docker volumes LVM backing volume. ext4 allows for shrinking.
+seed_lvm_group_data_lv_docker_volumes_fs: ext4
diff --git a/ansible/group_vars/controllers/lvm b/ansible/group_vars/controllers/lvm
new file mode 100644
index 0000000000000000000000000000000000000000..345f1379393bca75fddf95ae3d55379c00ca6a9a
--- /dev/null
+++ b/ansible/group_vars/controllers/lvm
@@ -0,0 +1,6 @@
+---
+###############################################################################
+# Controller node LVM configuration.
+
+# List of LVM volume groups.
+lvm_groups: []
diff --git a/ansible/group_vars/seed/lvm b/ansible/group_vars/seed/lvm
new file mode 100644
index 0000000000000000000000000000000000000000..9c75a27a9fe4bba6f7a94e4d521c99a07e624142
--- /dev/null
+++ b/ansible/group_vars/seed/lvm
@@ -0,0 +1,6 @@
+---
+###############################################################################
+# Seed node LVM configuration.
+
+# List of LVM volume groups.
+lvm_groups: "{{ seed_lvm_groups }}"
diff --git a/ansible/lvm.yml b/ansible/lvm.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7d1d3f0d8dbf02b091747cd5e43444af7b7eab9d
--- /dev/null
+++ b/ansible/lvm.yml
@@ -0,0 +1,10 @@
+---
+- name: Ensure LVM configuration is applied
+  hosts: seed:controllers
+  roles:
+    - role: mrlesmithjr.manage-lvm
+      manage_lvm: True
+      become: True
+      when:
+        - "{{ lvm_groups is defined}}"
+        - "{{ lvm_groups | length > 0 }}"
diff --git a/ansible/requirements.yml b/ansible/requirements.yml
index d5660ac10a7a121ef871da3b3ff9e69bdc0edde8..50b8fff951f578193e9d5824d42e9c6269abc094 100644
--- a/ansible/requirements.yml
+++ b/ansible/requirements.yml
@@ -2,5 +2,6 @@
 - src: ahuffman.resolv
 - src: jriguera.configdrive
 - src: MichaelRigart.interfaces
+- src: mrlesmithjr.manage-lvm
 - src: resmo.ntp
 - src: yatesr.timezone
diff --git a/etc/kayobe/seed.yml b/etc/kayobe/seed.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8d316443ba8482dc1f75bd0f5f1535a81d74103e
--- /dev/null
+++ b/etc/kayobe/seed.yml
@@ -0,0 +1,31 @@
+---
+# Seed node configuration.
+
+###############################################################################
+# LVM configuration.
+
+# List of seed VM LVM volume groups. See mrlesmithjr.manage-lvm role for
+# format.
+#seed_lvm_groups:
+
+# Seed LVM volume group for data. See mrlesmithjr.manage-lvm role for format.
+#seed_lvm_group_data:
+
+# List of disks for use by seed LVM data volume group.
+#seed_lvm_group_data_disks:
+
+# List of LVM logical volumes for the data volume group.
+#seed_lvm_group_data_lvs:
+
+# Docker volumes LVM backing volume.
+#seed_lvm_group_data_lv_docker_volumes:
+
+# Size of docker volumes LVM backing volume.
+#seed_lvm_group_data_lv_docker_volumes_size:
+
+# Filesystem for docker volumes LVM backing volume. ext4 allows for shrinking.
+#seed_lvm_group_data_lv_docker_volumes_fs:
+
+###############################################################################
+# Dummy variable to allow Ansible to accept this file.
+workaround_ansible_issue_8743: yes
diff --git a/kayobe/cli/commands.py b/kayobe/cli/commands.py
index 169a8dbbc568f3b5f9f49fcdc78e1b2101d37a00..fb9105df36f70fdb915fd911f450be073385f6ce 100644
--- a/kayobe/cli/commands.py
+++ b/kayobe/cli/commands.py
@@ -138,7 +138,7 @@ class SeedHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, Command):
                                            var_name="kayobe_ansible_user")
         playbooks = ["ansible/%s.yml" % playbook for playbook in
                      "ip-allocation", "ssh-known-host", "kayobe-ansible-user",
-                     "disable-selinux", "network", "ntp"]
+                     "disable-selinux", "network", "ntp", "lvm"]
         ansible.run_playbooks(parsed_args, playbooks, limit="seed")
         kolla_ansible.run_seed(parsed_args, "bootstrap-servers",
                                extra_vars={"ansible_user": ansible_user})
@@ -190,7 +190,7 @@ class OvercloudHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, Command):
                                            var_name="kayobe_ansible_user")
         playbooks = ["ansible/%s.yml" % playbook for playbook in
                      "ip-allocation", "ssh-known-host", "kayobe-ansible-user",
-                     "disable-selinux", "network", "ntp"]
+                     "disable-selinux", "network", "ntp", "lvm"]
         ansible.run_playbooks(parsed_args, playbooks, limit="controllers")
         kolla_ansible.run_overcloud(parsed_args, "bootstrap-servers",
                                     extra_vars={"ansible_user": ansible_user})
@@ -211,5 +211,5 @@ class OvercloudServiceDeploy(KollaAnsibleMixin, KayobeAnsibleMixin, Command):
             kolla_ansible.run_overcloud(parsed_args, command)
         # FIXME: Fudge to work around incorrect configuration path.
         extra_vars = {"node_config_directory": parsed_args.config_path}
-        kolla_ansible.run_overcloud(parsed_args, command,
+        kolla_ansible.run_overcloud(parsed_args, "post-deploy",
                                     extra_vars=extra_vars)