Skip to main content
Redhat Developers  Logo
  • Products

    Platforms

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat AI
      Red Hat AI
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • View All Red Hat Products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat Developer Hub
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat OpenShift Local
    • Red Hat Developer Sandbox

      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Secure Development & Architectures

      • Security
      • Secure coding
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • Product Documentation
    • API Catalog
    • Legacy Documentation
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

Declaratively assigning DNS records to virtual machines

September 11, 2025
Raffaele Spazzoli
Related topics:
KubernetesVirtualization
Related products:
Red Hat OpenShift Virtualization

Share:

    Virtual machines often use friendly names rather than just IP addresses, which requires the creation of a DNS record. This is primarily because many virtual machines are treated as "pets" rather than "cattle," which requires that a unique identity, including a network identity, be assigned.

    Organizations operating a fleet of virtual machines (VMs) often establish a naming convention for virtual machines along with a process for assigning DNS records to new instances. These actions are typically one component of a broader VM lifecycle automation, encompassing both provisioning and decommissioning.

    Red Hat OpenShift Virtualization lets you manage virtual machines declaratively, often through GitOps. This article explores methods for declaratively assigning DNS records to these virtual machines.

    Requirements

    To manage DNS records that are associated with VMs in a declarative fashion, there are several items you must consider. These virtual machines are typically exposed to the network on VLANs. Aside from VLANs, externally addressable user defined networks (UDNs), which use BGP to announce routes, are another option for providing virtual machines access to the network. 

    The IPs that these virtual machines receive might or might not be known in advance, but this solution should work with either approach. 

    Finally, virtual machines can be exposed on multiple networks, and therefore be available at multiple IPs and consequently require multiple DNS records.

    So, in summary:

    • Virtual machines can be exposed on multiple networks.
    • IPs can be assigned statically or dynamically.
    • Some of the assigned IPs to a virtual machine might need to have associated DNS records.

    Design

    We want the user experience to be as simple as possible. Ideally, adding labels and annotations on the VirtualMachine custom resource should be enough to declaratively create DNS records. The following is an approach from the user experience point of view that can be applied to achieve the envisioned goal:

    A label, such as vm.redhat-cop.dns-name: "true", can be used to declare that DNS records should be assigned to the VM.

    Annotations can then be added to specify FQDNs that should be associated with this virtual machine. The annotations will take this form:

    vm.redhat-cop.dns-name/<interface-name>: <FQDN>

    In this case, interface-name is the name of the network interface whose IP needs to be associated with the specified FQDN. This combination allows for assigning distinct FQDNs to multiple network interfaces.

    Now that the user experience side of the design is defined, let’s focus on how the system will actually work. The diagram in Figure 1 depicts the steps and components involved.

    A flowchart shows how OpenShift Virtualization cluster components interact to create and update an Enterprise DNS endpoint.
    Figure 1: The workflow for updating an Enterprise DNS record using a policy controller within an OpenShift Virtualization cluster.

    First, a VirtualMachine with the previously described labels and annotations is created in the spec.template section of the custom resource. The instantiation of a VirtualMachine generates a VirtualMachineInstance custom resource with the same labels and annotations.

    Given the way the virtual machine API works, the actual values of the IPs configured on the network interfaces are known only at runtime within the status of the VirtualMachineInstance. This also requires the qemu-guest-agent to be correctly installed in the virtual machine OS.

    A policy controller monitors VirtualMachineInstance for certain attributes. When there is a match between the IP record on the status and the value of the annotation a DNSEndpoint Custom Resource is created.

    The DNSEnpoint itself is monitored by the ExternalDNS controller, which, if correctly configured (out of scope for this article), will update the DNS server with the desired DNS records.

    As an example, let’s suppose we have a VirtualMachine with this snippet:

    spec:
      template:
       metadata:
         annotations:
           vm.redhat-cop.dns-name/enp1s0: vm.example.com
         labels:
           vm.redhat-cop.dn-name: "true"

    Assuming that at runtime the VirtualMachineInstance receives an IP, this should generate the following DSNEndpoint:

    apiVersion: externaldns.k8s.io/v1alpha1
    kind: DNSEndpoint
    metadata:
     name: fedora-moccasin-tahr-60-enp1s0
     namespace: test-vm
    spec:
     endpoints:
     - dnsName: vm.example.com
       recordTTL: 180
       recordType: A
       targets:
       - 10.136.0.178

    The final decision left unanswered to this point is the specific policy controller that will be used. Two frameworks will be shown: Kyverno and Red Hat Advanced Cluster Management for Kubernetes, which in the end, will achieve the same result.

    Kyverno-based approach

    Kyverno is a cloud-native policy management framework that has been donated to the Cloud Native Computing Foundation (CNCF). It is lightweight and relatively easy to use. However, as of the time of this article, Kyverno is not supported by Red Hat.

    Our policy will need to react based on the existence of certain conditions (i.e., VirtualMachineInstance with certain labels and annotations) and when this situation occurs, one or more objects will be created in response (i.e., DNSEndpoints for this use case). Such a policy can be written similar to the following:

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
     name: create-vm-dns-endpoints
     annotations:
       policies.kyverno.io/title: DNS Entries for Virtual Machines
       policies.kyverno.io/category: external-dns, virtual-machines, dns
       policies.kyverno.io/subject: DNSEndpoints, VirtualMachinesInstance
       policies.kyverno.io/minversion: 1.6.0
       policies.kyverno.io/description: >-

    This policy creates DNSEndpoints for external-dns to manage DNS entries for virtual machines.

    spec:
     rules:
     - name: generate-dns-endpoints
       match:
         any:
         - resources:
             kinds:
             - kubevirt.io/v1/VirtualMachineInstance
             selector:
               matchLabels:
                 vm.redhat-cop.dns-name: "true"
       generate:
         generateExisting: true
         synchronize: true
         orphanDownstreamOnPolicyDelete: true
         foreach:
           - list: request.object.status.interfaces
             preconditions:
               any:
               - key: '{{ request.object.metadata.annotations."vm.redhat-cop.dns-name/{{ element.name }}" || "" }}'
                 operator: NotEquals
                 value: ""
             apiVersion: externaldns.k8s.io/v1alpha1
             kind: DNSEndpoint
             name: '{{request.object.metadata.name}}-{{element.name}}'
             namespace: "{{request.object.metadata.namespace}}"                   
             data:
               spec:
                 endpoints:
                 - dnsName: '{{ request.object.metadata.annotations."vm.redhat-cop.dns-name/{{ element.name }}" }}'
                   recordTTL: 180
                   recordType: A
                   targets:
                   - '{{element.ipAddress}}'

    This policy will generate a DNSEndpoint for each interface for which a DNS address has been requested.

    Red Hat Advanced Cluster Management policies-based approach

    Red Hat Advanced Cluster Management for Kubernetes is OpenShift's fleet management tool. It operates in a hub-and-spoke architecture, so it requires that a hub cluster be established in order to enforce policies on managed clusters. Advanced Cluster Management for Kubernetes contains a very expressive policy definition language primarily based on Golang templates.

    An Advanced Cluster Management policy to satisfy our use case is shown here (this is a raw policy; the full policy definition, Placement, and Placement bindings have been omitted for brevity):

    object-templates-raw: |-
     {{ range (lookup "kubevirt.io/v1" "VirtualMachineInstance" "" "" "vm.redhat-cop.dns-name=true").items }}
     {{ $vm := . -}}
     - complianceType: mustonlyhave
       objectDefinition:
         apiVersion: externaldns.k8s.io/v1alpha1
         kind: DNSEndpoint
         metadata:
           name: "{{ .metadata.name }}"
           namespace: "{{ .metadata.namespace }}"
         spec:
         {{- if $vm.status.interfaces }}
           endpoints:
           {{- range $vm.status.interfaces -}}
           {{ $annotationName := printf "%v%v" "vm.redhat-cop.dns-name/" .name  -}}
           {{ if get $vm.metadata.annotations $annotationName -}}
           - dnsName: "{{ get $vm.metadata.annotations $annotationName }}"
             recordTTL: 180
             recordType: A
             targets:
             - "{{.ipAddress}}"
           {{ end }}
           {{ end }}
         {{ else }}
           endpoints: []
         {{ end }}
     {{ end }}

    Conclusion

    This article explored several methods for how to declaratively assign FQDNs to virtual machine running in OpenShift Virtualization by using a combination of policy controllers and operators.

    We started off by providing details related to how many organizations apply naming conventions (FQDNs) to virtual machines. We have not implemented this logic in our solution, but you can easily write more policies to allow only virtual machines with well-formed FQDNs. Admission  policies are relatively easy to write. This exercise is left to the reader. 

    Related Posts

    • Automatic certificate provisioning with cert-manager and DNS challenge

    • Live migrating VMs with OpenShift Virtualization

    • Use Vagrant Landrush to add DNS features to your OpenShift CDK Machine

    • How OpenShift Virtualization supports VM live migration

    • How to back up and restore virtual machines with OpenShift

    • Why I switched from VMware to OpenShift Virtualization

    Recent Posts

    • Profiling vLLM Inference Server with GPU acceleration on RHEL

    • Network performance in distributed training: Maximizing GPU utilization on OpenShift

    • Clang bytecode interpreter update

    • How Red Hat has redefined continuous performance testing

    • Simplify OpenShift installation in air-gapped environments

    What’s up next?

    Download the OpenShift Virtualization for VMware admins cheat sheet for a quick guide to managing virtual machines within the powerful OpenShift environment.

    Get the cheat sheet
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2025 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue