Every VCN has its own resolver. That works for one VCN. With a hub and many spokes plus an on-prem DNS, you need a deliberate design or names resolve in some places and not in others.
The building blocks
| Component | Role |
|---|---|
| Private zone | Records, e.g. app.internal.example.com |
| Private view | A container of private zones |
| VCN resolver | Answers queries from the VCN; has a default view plus attached views |
| Listening endpoint | IP in a subnet where outside resolvers (on-prem, other VCNs) send queries to this resolver |
| Forwarding endpoint | IP the resolver uses as the source when forwarding queries out |
| Resolver rules | "Forward corp.example.com to 192.168.10.53 via forwarding endpoint" |
Pattern: one shared view, attached everywhere
Create a view in a network compartment, put shared zones in it, and attach that view to every VCN resolver. Every VCN then resolves the same names without forwarding.
VIEW=$(oci dns view create --compartment-id $NET_COMP --display-name view-shared-internal --scope PRIVATE --query 'data.id' --raw-output)
oci dns zone create --compartment-id $NET_COMP --name internal.example.com \
--zone-type PRIMARY --scope PRIVATE --view-id $VIEW
RESOLVER=$(oci network vcn-dns-resolver-association get --vcn-id $SPOKE_VCN --query 'data."dns-resolver-id"' --raw-output)
oci dns resolver update --resolver-id $RESOLVER --scope PRIVATE \
--attached-views '[{"viewId":"'"$VIEW"'"}]'
--attached-views replaces the list; include any views already attached. Order matters: the first view that has a matching zone answers. The VCN's own default view is consulted first.
Add a record:
oci dns record rrset update --zone-name-or-id internal.example.com --domain api.internal.example.com --rtype A \
--scope PRIVATE --view-id $VIEW \
--items '[{"domain":"api.internal.example.com","rtype":"A","rdata":"10.1.2.15","ttl":300}]' --force
Hybrid: on-prem resolves OCI names
- Create a listening endpoint in the hub VCN:
oci dns resolver-endpoint create --resolver-id $HUB_RESOLVER --name listen_hub \
--is-listening true --is-forwarding false --subnet-id $HUB_DNS_SUBNET \
--listening-address 10.0.2.10 --scope PRIVATE
- On-prem DNS: conditional forwarder for
internal.example.comandoraclevcn.com(the default VCN domain) to10.0.2.10. - Security rules on the endpoint subnet allow UDP and TCP 53 from on-prem DNS servers.
Hybrid: OCI resolves on-prem names
- Create a forwarding endpoint in the hub VCN:
oci dns resolver-endpoint create --resolver-id $HUB_RESOLVER --name fwd_hub \
--is-listening false --is-forwarding true --subnet-id $HUB_DNS_SUBNET \
--forwarding-address 10.0.2.11 --scope PRIVATE
- Add a rule on the hub resolver:
oci dns resolver update --resolver-id $HUB_RESOLVER --scope PRIVATE --rules '[
{"action":"FORWARD","qnameCoverConditions":["corp.example.com"],
"destinationAddresses":["192.168.10.53","192.168.10.54"],"sourceEndpointName":"fwd_hub"}
]'
- Spokes: either repeat endpoints and rules per spoke, or (simpler) add a forwarding rule in each spoke resolver that sends
corp.example.comto the hub listening endpoint, which then applies the hub's rules. The spoke needs its own forwarding endpoint as the source.
Warning
Avoid forwarding loops: never let on-prem forward a zone to OCI while OCI forwards the same zone back to on-prem. Keep a written table of which side is authoritative for each zone.
Debugging from the right place
Always test from an instance inside the VCN in question; the VCN resolver is at 169.254.169.254.
dig +short api.internal.example.com @169.254.169.254
dig +short dc01.corp.example.com @169.254.169.254
dig +short api.internal.example.com @10.0.2.10 # from on-prem, via listening endpoint
| Symptom | Cause | Fix |
|---|---|---|
| Resolves in hub, NXDOMAIN in spoke | View not attached to spoke resolver | Attach the shared view |
| Resolves from OCI, timeout from on-prem | Listening endpoint subnet blocks 53, or no route back to on-prem | Security list/NSG, DRG routes |
| On-prem names time out in OCI | Forwarding endpoint cannot reach on-prem DNS | Routes from endpoint subnet via DRG; on-prem firewall allows the forwarding IP |
| Wrong answer for a name | Two attached views both have the zone; first match wins | Remove duplicate zone or reorder views |
| Changes not visible | TTL caching | Lower TTL before changes; wait it out |
Prevent it next time
- Shared zones live in one network compartment, managed by Terraform.
- New VCNs get the shared view attached in the same module that creates the VCN.
- Monitor endpoint health and keep two on-prem DNS targets in each forward rule.