diff --git a/ansible/group_vars/all/bifrost b/ansible/group_vars/all/bifrost
index c9c529e626477252c7d67c73a7add5471341728e..f22e252d7e37181c8e57a59bff025cea0ee26b86 100644
--- a/ansible/group_vars/all/bifrost
+++ b/ansible/group_vars/all/bifrost
@@ -86,7 +86,7 @@ kolla_bifrost_inspector_ipmi_password: "{{ ipmi_password }}"
 kolla_bifrost_inspector_lldp_switch_port_interface: "{{ inspector_lldp_switch_port_interface_default }}"
 
 # Ironic inspector deployment kernel location.
-kolla_bifrost_inspector_deploy_kernel: "http://{{ provision_oc_net_name | net_ip }}:8080/ipa.vmlinuz"
+kolla_bifrost_inspector_deploy_kernel: "http://{{ provision_oc_net_name | net_ip }}:8080/ipa.kernel"
 
 # Ironic inspector deployment ramdisk location.
 kolla_bifrost_inspector_deploy_ramdisk: "http://{{ provision_oc_net_name | net_ip }}:8080/ipa.initramfs"
diff --git a/ansible/group_vars/all/ipa b/ansible/group_vars/all/ipa
index c9970fb746112783730bdabb31fea799f7bb07fa..66861dd256bdbf1261692ef6cfa85b8a02c06fd5 100644
--- a/ansible/group_vars/all/ipa
+++ b/ansible/group_vars/all/ipa
@@ -13,19 +13,27 @@ ipa_build_source_url: "https://opendev.org/openstack/ironic-python-agent"
 # Version of IPA source repository. Default is {{ openstack_branch }}.
 ipa_build_source_version: "{{ openstack_branch }}"
 
-# TODO(mgoddard): Use CentOS 8.
+# URL of IPA builder source repository.
+ipa_builder_source_url: "https://opendev.org/openstack/ironic-python-agent-builder"
+
+# Version of IPA builder source repository. Default is master.
+ipa_builder_source_version: master
+
 # List of default Diskimage Builder (DIB) elements to use when building IPA
-# images.
+# images. Default is ["centos", "enable-serial-console",
+# "ironic-python-agent-ramdisk"].
 ipa_build_dib_elements_default:
-  - centos7
+  - centos
   - enable-serial-console
-  - ironic-agent
+  - ironic-python-agent-ramdisk
 
 # List of additional Diskimage Builder (DIB) elements to use when building IPA
-# images.
+# images. Default is none.
 ipa_build_dib_elements_extra: []
 
 # List of Diskimage Builder (DIB) elements to use when building IPA images.
+# Default is combination of ipa_build_dib_elements_default and
+# ipa_build_dib_elements_extra.
 ipa_build_dib_elements: >
   {{ ipa_build_dib_elements_default +
      ipa_build_dib_elements_extra }}
@@ -46,9 +54,23 @@ ipa_build_dib_env: >
   {{ ipa_build_dib_env_default |
      combine(ipa_build_dib_env_extra) }}
 
+# List of default git repositories containing Diskimage Builder (DIB) elements.
+# See stackhpc.os-images role for usage. Default is one item for IPA builder.
+ipa_build_dib_git_elements_default:
+  - repo: "{{ ipa_builder_source_url }}"
+    local: "{{ source_checkout_path }}/ironic-python-agent-builder"
+    version: "{{ ipa_builder_source_version }}"
+    elements_path: "dib"
+
+# List of additional git repositories containing Diskimage Builder (DIB)
+# elements. See stackhpc.os-images role for usage. Default is empty.
+ipa_build_dib_git_elements_extra: []
+
 # List of git repositories containing Diskimage Builder (DIB) elements. See
-# stackhpc.os-images role for usage.
-ipa_build_dib_git_elements: []
+# stackhpc.os-images role for usage. Default is a combination of
+# ipa_build_dib_git_elements_default and ipa_build_dib_git_elements_extra.
+ipa_build_dib_git_elements: >-
+  {{ ipa_build_dib_git_elements_default + ipa_build_dib_git_elements_extra }}
 
 # List of DIB packages to install. Default is none.
 ipa_build_dib_packages: []
@@ -61,10 +83,10 @@ ipa_build_dib_packages: []
 ipa_images_upstream_url_suffix: "-{{ openstack_branch | replace('/', '-') }}"
 
 # Name of Ironic deployment kernel image to register in Glance.
-ipa_images_kernel_name: "ipa.vmlinuz"
+ipa_images_kernel_name: "ipa.kernel"
 
 # URL of Ironic deployment kernel image to download.
-ipa_kernel_upstream_url: "https://tarballs.openstack.org/ironic-python-agent/dib/files/ipa-centos7{{ ipa_images_upstream_url_suffix }}.kernel"
+ipa_kernel_upstream_url: "https://tarballs.openstack.org/ironic-python-agent/dib/files/ipa-centos8{{ ipa_images_upstream_url_suffix }}.kernel"
 
 # URL of checksum of Ironic deployment kernel image.
 ipa_kernel_checksum_url: "{{ ipa_kernel_upstream_url }}.{{ ipa_kernel_checksum_algorithm }}"
@@ -76,7 +98,7 @@ ipa_kernel_checksum_algorithm: "sha256"
 ipa_images_ramdisk_name: "ipa.initramfs"
 
 # URL of Ironic deployment ramdisk image to download.
-ipa_ramdisk_upstream_url: "https://tarballs.openstack.org/ironic-python-agent/dib/files/ipa-centos7{{ ipa_images_upstream_url_suffix }}.initramfs"
+ipa_ramdisk_upstream_url: "https://tarballs.openstack.org/ironic-python-agent/dib/files/ipa-centos8{{ ipa_images_upstream_url_suffix }}.initramfs"
 
 # URL of checksum of Ironic deployment ramdisk image.
 ipa_ramdisk_checksum_url: "{{ ipa_ramdisk_upstream_url }}.{{ ipa_ramdisk_checksum_algorithm }}"
diff --git a/ansible/kolla-openstack.yml b/ansible/kolla-openstack.yml
index 4d2671217e22eac4da929dc7e2a95aa0e6e7c584..99e31a01d98a79c05ee028be24de697e4b842a7d 100644
--- a/ansible/kolla-openstack.yml
+++ b/ansible/kolla-openstack.yml
@@ -20,7 +20,7 @@
     # These are the filenames generated by overcloud-ipa-build.yml.
     ipa_image_name: "ipa"
     ipa_images:
-      - "{{ ipa_image_name }}.vmlinuz"
+      - "{{ ipa_image_name }}.kernel"
       - "{{ ipa_image_name }}.initramfs"
   tasks:
     - block:
diff --git a/ansible/overcloud-ipa-images.yml b/ansible/overcloud-ipa-images.yml
index e3568e408485faecd4b9d895db588e225133e0f2..483a4685df865f111c74754b690a2960c6d50edc 100644
--- a/ansible/overcloud-ipa-images.yml
+++ b/ansible/overcloud-ipa-images.yml
@@ -17,7 +17,7 @@
     # These are the filenames generated by overcloud-ipa-build.yml.
     ipa_image_name: "ipa"
     ipa_images:
-      - "{{ ipa_image_name }}.vmlinuz"
+      - "{{ ipa_image_name }}.kernel"
       - "{{ ipa_image_name }}.initramfs"
   pre_tasks:
     - name: Validate OpenStack password authentication parameters
diff --git a/ansible/roles/kolla-bifrost/templates/bifrost.yml.j2 b/ansible/roles/kolla-bifrost/templates/bifrost.yml.j2
index ab9d640d4173172c699df4d250f9646e99a32310..eb5cf82a2da47195ad8b477e84ee699322bfe558 100644
--- a/ansible/roles/kolla-bifrost/templates/bifrost.yml.j2
+++ b/ansible/roles/kolla-bifrost/templates/bifrost.yml.j2
@@ -46,21 +46,6 @@ ipa_kernel_upstream_url: "{{ kolla_bifrost_ipa_kernel_upstream_url }}"
 # URL of checksum of Ironic Python Agent (IPA) kernel image.
 ipa_kernel_upstream_checksum_url: "{{ kolla_bifrost_ipa_kernel_checksum_url }}"
 
-# NOTE(mgoddard): In bifrost 7.1.0, the default for ipa_kernel and
-# ipa_kernel_url was changed from .vmlinuz to .kernel. This broke our inspector
-# rule which uses .vmlinuz when setting driver_info.deploy_kernel. It will also
-# break existing nodes if the IPA kernel is updated e.g. following an upgrade.
-# Use the old value of .vmlinuz here.
-# TODO(mgoddard): Remove these when we use IPA builder.
-{# Using double jinja escaping here since this will be templated by kayobe #}
-{# and kolla ansible, then interpreted as Ansible variables by Bifrost. #}
-{{ '{% raw %}' }}
-{% raw %}
-ipa_kernel: "{{http_boot_folder}}/ipa.vmlinuz"
-ipa_kernel_url: "{{ ipa_file_protocol }}://{{ hostvars[inventory_hostname]['ansible_' + ans_network_interface]['ipv4']['address'] }}:{{file_url_port}}/ipa.vmlinuz"
-{% endraw %}
-{{ '{% endraw %}' }}
-
 # Algorithm of checksum of Ironic Python Agent (IPA) kernel image.
 ipa_kernel_upstream_checksum_algo: "{{ kolla_bifrost_ipa_kernel_checksum_algorithm }}"
 
diff --git a/ansible/seed-ipa-build.yml b/ansible/seed-ipa-build.yml
index 1e2e0e413838daa5e4e21d28b71c9c75a981f40b..6f4bdc6f736c8e165c206d5c35bb3f37e45348bb 100644
--- a/ansible/seed-ipa-build.yml
+++ b/ansible/seed-ipa-build.yml
@@ -9,7 +9,7 @@
   vars:
     ipa_image_name: "ipa"
     ipa_images:
-      - "{{ ipa_image_name }}.vmlinuz"
+      - "{{ ipa_image_name }}.kernel"
       - "{{ ipa_image_name }}.initramfs"
     ipa_image_force_rebuild: false
   tasks:
diff --git a/ansible/seed-service-upgrade-prep.yml b/ansible/seed-service-upgrade-prep.yml
index ce7001e941f63a9ece29594eaea016b8acee450d..213750726a9f53a8c89394f61587a440aa579120 100644
--- a/ansible/seed-service-upgrade-prep.yml
+++ b/ansible/seed-service-upgrade-prep.yml
@@ -13,8 +13,8 @@
               # images.
               - ipa.initramfs
               - ipa.initramfs.sha256
-              - ipa.vmlinuz
-              - ipa.vmlinuz.sha256
+              - ipa.kernel
+              - ipa.kernel.sha256
           register: find_result
           become: true
 
diff --git a/dev/tenks-deploy-config-compute.yml b/dev/tenks-deploy-config-compute.yml
index fa84b1c4cfbdfb08fb0bc6538060f68d6dbe9b71..2ff60889fc240d77b5b799ec0be3d5789571f610 100644
--- a/dev/tenks-deploy-config-compute.yml
+++ b/dev/tenks-deploy-config-compute.yml
@@ -31,7 +31,7 @@ nova_flavors:
 physnet_mappings:
   physnet1: breth1
 
-deploy_kernel: ipa.vmlinuz
+deploy_kernel: ipa.kernel
 deploy_ramdisk: ipa.initramfs
 
 # Use a custom socket path to avoid a conflict with the nova_libvirt kolla
diff --git a/doc/source/configuration/bifrost.rst b/doc/source/configuration/bifrost.rst
index 67db4df8b17814b24fda69c8de0dbb33a21d57b1..98c5cc7f4e95d9f6b40521cc22ae8b628584ddaf 100644
--- a/doc/source/configuration/bifrost.rst
+++ b/doc/source/configuration/bifrost.rst
@@ -223,7 +223,7 @@ The following options configure the Ironic Inspector service in the
     ``${KAYOBE_CONFIG_PATH}/inspector.yml``.
 ``kolla_bifrost_inspector_deploy_kernel``
     Ironic inspector deployment kernel location. Default is ``http://{{
-    provision_oc_net_name | net_ip }}:8080/ipa.vmlinuz``.
+    provision_oc_net_name | net_ip }}:8080/ipa.kernel``.
 ``kolla_bifrost_inspector_deploy_ramdisk``
     Ironic inspector deployment ramdisk location. Default is ``http://{{
     provision_oc_net_name | net_ip }}:8080/ipa.initramfs``.
diff --git a/doc/source/configuration/ironic-python-agent.rst b/doc/source/configuration/ironic-python-agent.rst
index 43ae6bd0faf2a3b1f7f2544aa292769ee689a6c5..ab5c125c9fcdfa95a6fbd6b29fe1afcbb8b60146 100644
--- a/doc/source/configuration/ironic-python-agent.rst
+++ b/doc/source/configuration/ironic-python-agent.rst
@@ -39,10 +39,15 @@ image build``.
     https://opendev.org/openstack/ironic-python-agent
 ``ipa_build_source_version``
     Version of IPA source repository. Default is ``{{ openstack_branch }}``.
+``ipa_builder_source_url``
+    URL of IPA builder source repository. Default is
+    https://opendev.org/openstack/ironic-python-agent-builder
+``ipa_builder_source_version``
+    Version of IPA builder source repository. Default is ``master``.
 ``ipa_build_dib_elements_default``
     List of default Diskimage Builder (DIB) elements to use when building IPA
-    images. Default is ``["centos7", "enable-serial-console",
-    "ironic-agent"]``.
+    images. Default is ``["centos", "enable-serial-console",
+    "ironic-python-agent-ramdisk"]``.
 ``ipa_build_dib_elements_extra``
     List of additional Diskimage Builder (DIB) elements to use when building IPA
     images. Default is empty.
@@ -62,10 +67,21 @@ image build``.
     Dictionary of environment variables to provide to Diskimage Builder (DIB)
     during IPA image build. Default is a combination of
     ``ipa_build_dib_env_default`` and ``ipa_build_dib_env_extra``.
+``ipa_build_dib_git_elements_default``
+    List of default git repositories containing Diskimage Builder (DIB)
+    elements. See `stackhpc.os-images
+    <https://galaxy.ansible.com/stackhpc/os-images>`__ role for usage. Default
+    is one item for IPA builder.
+``ipa_build_dib_git_elements_extra``
+    List of additional git repositories containing Diskimage Builder (DIB)
+    elements. See `stackhpc.os-images
+    <https://galaxy.ansible.com/stackhpc/os-images>`__ role for usage. Default
+    is none.
 ``ipa_build_dib_git_elements``
     List of git repositories containing Diskimage Builder (DIB) elements. See
     `stackhpc.os-images <https://galaxy.ansible.com/stackhpc/os-images>`__ role
-    for usage. Default is none.
+    for usage. Default is combination of ``ipa_build_dib_git_elements_default``
+    and ``ipa_build_dib_git_elements_extra``.
 ``ipa_build_dib_packages``
     List of DIB packages to install. Default is none.
 
@@ -189,10 +205,10 @@ Agent documentation <>` for full details.
     ``{{ openstack_branch }}``.
 ``ipa_images_kernel_name``
     Name of Ironic deployment kernel image to register in Glance. Default is
-    ``ipa.vmlinuz``.
+    ``ipa.kernel``.
 ``ipa_kernel_upstream_url``
     URL of Ironic deployment kernel image to download. Default is
-    ``https://tarballs.openstack.org/ironic-python-agent/dib/files/ipa-centos7{{
+    ``https://tarballs.openstack.org/ironic-python-agent/dib/files/ipa-centos8{{
     ipa_images_upstream_url_suffix }}.kernel``.
 ``ipa_kernel_checksum_url``
     URL of checksum of Ironic deployment kernel image. Default is ``{{
@@ -205,7 +221,7 @@ Agent documentation <>` for full details.
     ``ipa.initramfs``.
 ``ipa_ramdisk_upstream_url``
     URL of Ironic deployment ramdisk image to download. Default is
-    ``https://tarballs.openstack.org/ironic-python-agent/dib/files/ipa-centos7{{
+    ``https://tarballs.openstack.org/ironic-python-agent/dib/files/ipa-centos8{{
     ipa_images_upstream_url_suffix }}.initramfs``.
 ``ipa_ramdisk_checksum_url``
     URL of checksum of Ironic deployment ramdisk image. Default is ``{{
diff --git a/etc/kayobe/ipa.yml b/etc/kayobe/ipa.yml
index 2928e27e19562d64f52212ab619952b131ba8097..bcacbef48f7d73387b7d7cca62b16191a713049f 100644
--- a/etc/kayobe/ipa.yml
+++ b/etc/kayobe/ipa.yml
@@ -13,15 +13,24 @@
 # Version of IPA source repository. Default is {{ openstack_branch }}.
 #ipa_build_source_version:
 
+# URL of IPA builder source repository.
+#ipa_builder_source_url:
+
+# Version of IPA builder source repository. Default is master.
+#ipa_build_source_version:
+
 # List of default Diskimage Builder (DIB) elements to use when building IPA
-# images.
+# images. Default is ["centos", "enable-serial-console",
+# "ironic-python-agent-ramdisk"].
 #ipa_build_dib_elements_default:
 
 # List of additional Diskimage Builder (DIB) elements to use when building IPA
-# images.
+# images. Default is none.
 #ipa_build_dib_elements_extra:
 
 # List of Diskimage Builder (DIB) elements to use when building IPA images.
+# Default is combination of ipa_build_dib_elements_default and
+# ipa_build_dib_elements_extra.
 #ipa_build_dib_elements:
 
 # Dictionary of default environment variables to provide to Diskimage Builder
@@ -36,8 +45,17 @@
 # during IPA image build.
 #ipa_build_dib_env:
 
+# List of default git repositories containing Diskimage Builder (DIB) elements.
+# See stackhpc.os-images role for usage. Default is one item for IPA builder.
+#ipa_build_dib_git_elements_default:
+
+# List of additional git repositories containing Diskimage Builder (DIB)
+# elements. See stackhpc.os-images role for usage. Default is empty.
+#ipa_build_dib_git_elements_extra:
+
 # List of git repositories containing Diskimage Builder (DIB) elements. See
-# stackhpc.os-images role for usage.
+# stackhpc.os-images role for usage. Default is a combination of
+# ipa_build_dib_git_elements_default and ipa_build_dib_git_elements_extra.
 #ipa_build_dib_git_elements:
 
 # List of DIB packages to install. Default is none.
diff --git a/playbooks/kayobe-overcloud-upgrade-base/run.yml b/playbooks/kayobe-overcloud-upgrade-base/run.yml
index 7ba6272451518f608485b2ca397e1f392b40ff53..288a4fd1595dad83bbc6b9a23ba30716eada0b5f 100644
--- a/playbooks/kayobe-overcloud-upgrade-base/run.yml
+++ b/playbooks/kayobe-overcloud-upgrade-base/run.yml
@@ -27,10 +27,9 @@
         - name: Ensure test Tenks cluster is deployed
           shell:
             # Pass absolute source directory, since otherwise the `chdir` will
-            # cause this to fail. Don't use previous_kayobe_source_dir as
-            # tenks-deploy-compute.sh does not exist there.
+            # cause this to fail.
             cmd: dev/tenks-deploy-compute.sh '{{ tenks_src_dir }}' &> {{ logs_dir }}/ansible/tenks-deploy
-            chdir: "{{ kayobe_src_dir }}"
+            chdir: "{{ previous_kayobe_src_dir }}"
 
       environment:
         KAYOBE_CONFIG_SOURCE_PATH: "{{ previous_kayobe_config_src_dir }}"
diff --git a/releasenotes/notes/ipa-builder-ea6308b6691ae71e.yaml b/releasenotes/notes/ipa-builder-ea6308b6691ae71e.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f9a658d1be0965cda486b4370ff86f8d6de6ff61
--- /dev/null
+++ b/releasenotes/notes/ipa-builder-ea6308b6691ae71e.yaml
@@ -0,0 +1,24 @@
+---
+upgrade:
+  - |
+    Changes Ironic Python Agent (IPA) image builds to use `IPA builder
+    <https://docs.openstack.org/ironic-python-agent-builder/latest/>`__.
+    The following variables have been added to configure the IPA builder source
+    location: ``ipa_builder_source_url``, ``ipa_builder_source_version``. See
+    `story 2007070 <https://storyboard.openstack.org/#!/story/2007070>`__ for
+    details.
+  - |
+    Adds new variables to allow extension of the list of Disk Image Builder
+    (DIB) git repositories available when building Ironic Python Agent (IPA)
+    images: ``ipa_build_dib_git_elements_default`` and
+    ``ipa_build_dib_git_elements_extra``. The existing
+    ``ipa_build_dib_git_elements`` variable is a concatenation of these.
+    By default there is now one git repository configured for IPA builder, and
+    use of ``ipa_build_dib_git_elements`` should typically be replaced with
+    ``ipa_build_dib_git_elements_extra`` to avoid losing this default.
+  - |
+    The file extension used for the Ironic Python Agent (IPA) kernel image has
+    changed from ``vmlinuz`` to ``kernel``, in line with upstream changes in
+    Ironic. This affects both Bifrost running on the seed and Ironic running in
+    the overcloud for bare metal compute. If building images locally, this
+    should be done prior to upgrading services.