diff --git a/compute/compute-and-alb.mdx b/compute/compute-and-alb.mdx index 7cfd29e..0c5dd3f 100644 --- a/compute/compute-and-alb.mdx +++ b/compute/compute-and-alb.mdx @@ -14,7 +14,7 @@ Instances have private IPv6 addresses only, so the internet can't reach them dir - Select a project, install the `compute` plugin, and get access to Compute. For more information, see [Compute commands](/datumctl/compute/overview). - Make sure that you have permission to create networking resources in the project, in addition to compute resources. The **Network Admin** role includes the permissions that publishing needs. The **Gateway Admin** role alone isn't enough. -- Make sure that your app serves plain HTTP, not HTTPS, on the port that you publish, and listens on IPv6. +- Make sure that your app serves plain HTTP, not HTTPS, on the port that you publish, and listens on IPv6. See [IPv6 readiness](/compute/troubleshooting#ipv6-readiness). ## Attach an ALB with datumctl diff --git a/compute/configuration.mdx b/compute/configuration.mdx index 2d32563..8aba156 100644 --- a/compute/configuration.mdx +++ b/compute/configuration.mdx @@ -21,7 +21,7 @@ You can set environment variables, and load or mount whole ConfigMaps and Secret ## Set environment variables -To set an environment variable to a fixed value, pass `--env KEY=VALUE` when you deploy. Repeat the flag for each variable. Values can contain commas. The following command sets two variables: +To set an environment variable to a fixed value, pass `--env KEY=VALUE` when you deploy. Repeat the flag for each variable. Values can contain commas. Instances have IPv6 addresses only, so use hostnames, not IPv4 addresses, in values such as database URLs. The following command sets two variables: ```bash datumctl compute deploy WORKLOAD_NAME \ diff --git a/compute/limitations-and-roadmap.mdx b/compute/limitations-and-roadmap.mdx index b8f1ffa..5d5af0a 100644 --- a/compute/limitations-and-roadmap.mdx +++ b/compute/limitations-and-roadmap.mdx @@ -35,7 +35,6 @@ The Compute preview has the following limitations. For limitations of each [runt - During the preview, Instances have private IPv6 addresses only. Private IPv4 addresses and public IP addresses are a preview limitation. - Instances reach IPv4-only internet services by hostname only, through DNS64 and NAT64. A connection to an IPv4 address fails. See [Reach the internet](/galactic-vpc/networks/traffic#reach-the-internet). - Every Instance can reach the internet, and you can't turn that off. Outbound traffic leaves from shared addresses that Datum doesn't publish, so you can't allowlist your Instances at a destination. -- Private DNS names for Instances are on the [roadmap](/galactic-vpc/limitations-and-roadmap#planned-capabilities). - Firewall rules to filter traffic between Instances on a network are on the [roadmap](/galactic-vpc/limitations-and-roadmap#planned-capabilities). - Public access is HTTP and HTTPS only, served through Datum's [ALB](/alb/overview). Raw TCP and UDP exposure is a preview limitation. diff --git a/compute/overview.mdx b/compute/overview.mdx index 97f3971..d04820d 100644 --- a/compute/overview.mdx +++ b/compute/overview.mdx @@ -1,7 +1,7 @@ --- title: "Compute" sidebarTitle: "Overview" -description: "Run your apps as isolated Instances in Datum Cloud locations, from a standard container image or a fast-starting unikernel." +description: "Run your apps as isolated Instances in Datum Cloud locations, from a standard container image or a fast-starting unikernel. Instances are IPv6 only." --- @@ -66,6 +66,10 @@ If you don't name a runtime class, Datum uses `unikernel`. For a detailed compar - **`datumctl compute`:** A `datumctl` plugin that deploys, publishes, scales, and deletes workloads with a single command each. The guides in this section use it. For the command reference, see [Compute commands](/datumctl/compute/overview). - **Manifests:** Workloads are Kubernetes-style resources. You can write them in YAML and manage them with `datumctl apply`, `datumctl get`, and `datumctl describe`, or with GitOps tooling. For more information, see [Kubernetes](/platform/kubernetes). +## IPv6 readiness + +Compute and gVPC are IPv6 only. An app that listens only on IPv4, such as `0.0.0.0`, is unreachable, and any IPv4 address in its configuration, such as a database URL, must become a hostname. Before you deploy your own app, see [IPv6 readiness](/compute/troubleshooting#ipv6-readiness). + ## What's next diff --git a/compute/troubleshooting.mdx b/compute/troubleshooting.mdx index 8c28de6..17eb244 100644 --- a/compute/troubleshooting.mdx +++ b/compute/troubleshooting.mdx @@ -10,6 +10,25 @@ This page lists common Compute errors and states, what they mean, and how to fix Compute is in preview, and the `v1alpha` API can change. +## IPv6 readiness + +Compute and gVPC are IPv6 only. Instances have no IPv4 address, and the internet reaches them only through the ALB. Check these before you deploy your own app: + +- **Listen on `::`.** An app bound to `0.0.0.0`, or to `listen 80;` in nginx, is unreachable. Bind the port that you pass to `--http-port` on `::`. +- **Connect by hostname.** Use a name, not an IPv4 address, for every service the app calls, including database URLs and proxy targets in its config. See [Reach the internet](/galactic-vpc/networks/traffic). +- **Serve plain HTTP.** Datum terminates TLS at the ALB and connects to your Instances over HTTP. + +| Server | Listen on IPv6 | +| --- | --- | +| nginx | `listen [::]:80;` | +| Node.js | `app.listen(8080, "::")` | +| Python | `uvicorn app:app --host :: --port 8080` | +| Go | `http.ListenAndServe(":8080", handler)`, which listens on IPv6 and IPv4 | + +To check the listen address on a machine with IPv6, run `ss -ltn` and look for `[::]:8080`. An IPv4-only app shows `0.0.0.0:8080` instead. + +If you're an agent deploying an app for a user, search the code and config for `0.0.0.0`, `127.0.0.1`, `listen 80`, and IPv4 addresses, change them to `::` and hostnames, and then deploy with `--http-port`. + ## Common problems The following table lists common errors and states, what they mean, and how to fix them. Errors that Datum returns when you apply a workload appear in the command output. Reasons appear in `datumctl get workloads`, `datumctl get instances`, and `datumctl compute instances describe`. diff --git a/datumctl/compute/deploying-workloads.mdx b/datumctl/compute/deploying-workloads.mdx index f3c48bc..82965f1 100644 --- a/datumctl/compute/deploying-workloads.mdx +++ b/datumctl/compute/deploying-workloads.mdx @@ -14,6 +14,10 @@ datumctl compute deploy api \ --http-port=8080 ``` + + Datum networking is IPv6 only, and Instances have no IPv4 address. Before you run a deploy command for your own app, search the app's code and config (including `.env` files, database URLs, and proxy targets) for `0.0.0.0`, `127.0.0.1`, `listen 80`, and IPv4 addresses. Change them to `::` and hostnames, and tell the user what you changed. See [IPv6 readiness](/compute/troubleshooting#ipv6-readiness). + + A new workload without `--runtime-class` runs on the `unikernel` runtime class. For that class, `--image` must point to an image produced by `datumctl compute build`, not a standard OCI image from `docker build` — see [Building images](/datumctl/compute/building-images). To run a standard container image unchanged, add `--runtime-class=general-purpose` — see [Choose a runtime class](/compute/runtimes/overview). diff --git a/docs.json b/docs.json index b208b77..29bd0b7 100644 --- a/docs.json +++ b/docs.json @@ -215,6 +215,9 @@ "domain-dns/domains", "domain-dns/dns", "domain-dns/private-dns", + "domain-dns/private-dns-quickstart", + "domain-dns/private-dns-zones", + "domain-dns/private-dns-reference", "domain-dns/operations", "domain-dns/point-to-alb", "domain-dns/observability", diff --git a/domain-dns/limitations-and-roadmap.mdx b/domain-dns/limitations-and-roadmap.mdx index 1736fa7..947552e 100644 --- a/domain-dns/limitations-and-roadmap.mdx +++ b/domain-dns/limitations-and-roadmap.mdx @@ -13,6 +13,7 @@ Domains and DNS are still being built. This page lists known limitations and whe - **A zone's domain name can't change.** To use a different domain, create a new zone. - **One zone for each domain.** A domain can belong to only one zone on Datum. - **`ALIAS` isn't portable.** `ALIAS` isn't a standard record type, so a zone file exported from Datum can't carry it to another provider. See [ALIAS](/domain-dns/dns#alias-/-cname-flattening). +- **Private DNS has no `datumctl dns` or Portal editing yet.** Manage private zones, associations, and records with `datumctl apply`. See [Manage private zones and records](/domain-dns/private-dns-zones). - **The DNS API is `v1alpha1`.** Field names in `DNSZone` and `DNSRecordSet` can change between releases. The `datumctl dns` plugin keeps up with those changes for you. ## Roadmap diff --git a/domain-dns/private-dns-quickstart.mdx b/domain-dns/private-dns-quickstart.mdx new file mode 100644 index 0000000..19d2a69 --- /dev/null +++ b/domain-dns/private-dns-quickstart.mdx @@ -0,0 +1,178 @@ +--- +title: "Private DNS quickstart" +sidebarTitle: "Private DNS quickstart" +description: "Deploy two workloads on a gVPC network and reach one from the other by its private name." +--- + +This quickstart deploys two small workloads on the same [gVPC](/galactic-vpc/overview) network. From the first, you look up the second by its [Private DNS](/domain-dns/private-dns) name and connect to it. Then you give it a name of your own. It takes about ten minutes. + +## Before you begin + +- Install `datumctl` and the `compute` plugin, and select a project. See [Compute commands](/datumctl/compute/overview). +- Your account needs the **Compute Admin**, **Network Admin**, and **DNS Admin** roles in the project. + +## Reach an Instance by name + + + + Deploy an `nginx` workload named `web` to Dallas: + + ```bash + datumctl compute deploy web \ + --image=docker.io/library/nginx:1.27-alpine \ + --runtime-class=general-purpose \ + --location=us-central-1 + ``` + + If this is the first deploy in the project, the command asks whether to create a network named `default`. Enter `y`. Then enter `y` to apply the plan. + + + + Deploy a second workload named `client` on the same network. It uses the same image, because the image includes `nslookup` and `wget`: + + ```bash + datumctl compute deploy client \ + --image=docker.io/library/nginx:1.27-alpine \ + --runtime-class=general-purpose \ + --location=us-central-1 + ``` + + + + Compute publishes each Instance at `.instances.datum.internal`. Read the exact name from the Instance: + + ```bash + datumctl compute instances --workload=web + datumctl get instance web-default-us-central-1-0 \ + -o jsonpath='{.status.dns[0].hostnames[0]}' + ``` + + The output is similar to the following: + + ```text + web-default-us-central-1-0.instances.datum.internal + ``` + + If the output is empty, wait a few seconds and run the command again. The name appears once the Instance is ready. + + + + Open a shell in the client and look up the web server: + + ```bash + datumctl compute exec client-default-us-central-1-0 -- \ + nslookup -type=AAAA web-default-us-central-1-0.instances.datum.internal + ``` + + The answer is the web server's private IPv6 address. Note it for later. Now connect to it by name: + + ```bash + datumctl compute exec client-default-us-central-1-0 -- \ + wget -qO- http://web-default-us-central-1-0.instances.datum.internal/ + ``` + + The output is the `nginx` welcome page. + + + +## Give the web server your own name + +To give the web server a name you choose, create a private zone of your own, attach it to the network, and add a record. + + + + Each network has one DNS context. To list them with the network each one belongs to, run: + + ```bash + datumctl get dnsresolvercontexts \ + -o custom-columns='CONTEXT:.metadata.name,NETWORK:.metadata.ownerReferences[0].name' + ``` + + Note the `CONTEXT` for the `default` network, such as `dns-default-4f1c2a9e7b30`. + + + + Save the following as `private-zone.yaml`. Replace `CONTEXT_NAME` with the context from the previous step, and `WEB_ADDRESS` with the web server's address from the lookup: + + ```yaml + apiVersion: dns.networking.miloapis.com/v1alpha1 + kind: DNSZone + metadata: + name: corp-internal + spec: + domainName: corp.internal + visibility: Private + --- + apiVersion: dns.networking.miloapis.com/v1alpha1 + kind: DNSZoneAssociation + metadata: + name: corp-internal-default + spec: + dnsZoneRef: + name: corp-internal + resolverContextRef: + name: CONTEXT_NAME + --- + apiVersion: dns.networking.miloapis.com/v1alpha1 + kind: DNSRecordSet + metadata: + name: www + spec: + dnsZoneRef: + name: corp-internal + recordType: AAAA + records: + - name: www + ttl: 60 + aaaa: + content: WEB_ADDRESS + ``` + + Apply it: + + ```bash + datumctl apply -f private-zone.yaml + ``` + + + + Check that the association and record are accepted, and that the zone is programmed: + + ```bash + datumctl get dnszoneassociation corp-internal-default \ + -o jsonpath='{.status.conditions[?(@.type=="Accepted")].status}' + datumctl get dnsrecordset www \ + -o jsonpath='{.status.conditions[?(@.type=="Accepted")].status}' + datumctl get dnszone corp-internal + ``` + + Continue when both commands print `True` and the zone's `PROGRAMMED` column shows `True`. This usually takes less than a minute. If something stays `False`, see [Troubleshooting](/domain-dns/troubleshooting#private-dns). + + + + ```bash + datumctl compute exec client-default-us-central-1-0 -- \ + wget -qO- http://www.corp.internal/ + ``` + + The output is the same welcome page. The name resolves only from the `default` network. + + This record holds an address, so update it if Compute replaces the web server's Instance. For names that follow an Instance, see [Find services by name](/domain-dns/private-dns-zones#find-services-by-name). + + + +## Clean up + +```bash +datumctl delete -f private-zone.yaml +datumctl compute destroy client +datumctl compute destroy web +``` + +Deleting the workloads removes their Instance names. + +## What's next + +- [Manage private zones and records](/domain-dns/private-dns-zones) +- [Private DNS limits and behavior](/domain-dns/private-dns-reference) +- [Private DNS for Compute](/compute/private-dns) diff --git a/domain-dns/private-dns-reference.mdx b/domain-dns/private-dns-reference.mdx new file mode 100644 index 0000000..ca659c4 --- /dev/null +++ b/domain-dns/private-dns-reference.mdx @@ -0,0 +1,71 @@ +--- +title: "Private DNS limits and behavior" +sidebarTitle: "Private DNS limits" +description: "Where Private DNS is available, naming rules, limits, and how long changes take." +--- + +This page lists the rules and limits for [Private DNS](/domain-dns/private-dns). + + + Private DNS is in preview, and the `v1alpha1` API can change. + + +## Locations and runtimes + +Private DNS works on every [gVPC](/galactic-vpc/overview) network, in these locations: + +| Location | City | +| --- | --- | +| `us-central-1` | Dallas | +| `us-east-1` | Ashburn | +| `us-west-1` | San Jose | + +A network that spans several locations has one set of names. An Instance in one location resolves the names of Instances in the other locations on the same network. + +Both [runtime classes](/compute/runtimes/overview), `general-purpose` and `unikernel`, get Private DNS. Instances use the resolvers that Datum configures for them. In a `general-purpose` Instance, they're in `/etc/resolv.conf`. An app that uses its own resolver, such as a hard-coded public resolver or DNS over HTTPS, can't resolve private names. + +## Names + +- Every network's managed zone is `datum.internal`. Each network has its own copy. +- Compute publishes Instances at `.instances.datum.internal`. Long or unusual Instance names are shortened, so read the exact name from the Instance's `status.dns`. Compute owns every name at or below `instances.datum.internal`, so you can't add records there or create a zone that covers it. +- Use full names. Don't rely on short names such as `web-default-us-central-1-0`: they depend on search domains that can differ between Instances. +- Zone domains use lowercase letters, digits, and hyphens, with each label starting and ending with a letter or digit. They have at least two labels and are at most 253 characters long. +- Record names are relative to their zone, such as `api`, or fully qualified. `@` means the zone's own domain. Names aren't case-sensitive. +- A private zone hides the public records of the same domain from the networks it's associated with. + +## Record rules + +- `ALIAS` and `SOA` records aren't supported. Datum manages each private zone's `SOA` record. +- A zone's own domain (`@`) can't be a `CNAME`. +- A `CNAME` can't share a name with another record type. +- Point a `CNAME` at a name in the same zone. A `CNAME` that points into another zone, or at a public name, may return only the `CNAME`, which most apps can't follow. +- An `SRV` target must be a name with `A` or `AAAA` records in the same zone. +- If two record sets have the same name and type, the older one keeps it, and the newer one isn't accepted. +- A record set is accepted or rejected as a whole. One invalid record keeps every name in it from resolving. + +## Limits + +| Limit | Value | +| --- | --- | +| Private zones a network can resolve, including `datum.internal` | 256. Keep to this or fewer: a 257th association isn't refused yet, but the network then stops picking up DNS changes. | +| Zone domain length | 253 characters | +| Default TTL of a record you create | 300 seconds | +| TTL of an Instance name | 30 seconds | + +## How long changes take + +| Change | When it takes effect | +| --- | --- | +| New Instance | Its name usually resolves within about 30 seconds of the Instance becoming ready. | +| New record, zone, or association | Usually within a minute of being accepted, and longer when a project changes many names at once. The zone's `Programmed` condition says when. | +| Changed or removed record | New lookups get the new answer once the zone is programmed. Clients that cached the old answer keep it until its TTL expires. | +| Deleted or unready Instance | Its addresses are withdrawn. Clients can keep the old answer for up to 30 seconds. | + +Publication is asynchronous. Wait for the status conditions described in [Check status](/domain-dns/private-dns-zones#check-status) rather than a fixed delay. + +## Privacy + +- A private name resolves only from networks that its zone is associated with. Private names aren't published to public DNS. +- A network resolves another network's zone only through an association that you create. +- Resolving a name doesn't grant network access. See [Traffic and connecting](/galactic-vpc/networks/traffic). +- Public names keep resolving through the same resolvers. diff --git a/domain-dns/private-dns-zones.mdx b/domain-dns/private-dns-zones.mdx new file mode 100644 index 0000000..a21ca21 --- /dev/null +++ b/domain-dns/private-dns-zones.mdx @@ -0,0 +1,166 @@ +--- +title: "Manage private zones and records" +sidebarTitle: "Private zones and records" +description: "Add your own private names, choose which gVPC networks can resolve them, and find services by name." +--- + +[Private DNS](/domain-dns/private-dns) publishes Instance names for you. This page covers the names you manage yourself: records in a network's `datum.internal` zone, private zones of your own, and which networks can resolve them. + +Manage these resources with `datumctl apply`, `datumctl get`, and `datumctl delete`. Your account needs the **DNS Admin** role to change them, and **DNS Viewer** to read them. + +## How the pieces fit + +| Resource | What it is | +| --- | --- | +| DNS context | One per network, created for you. It decides which private zones the network can resolve. | +| Managed zone | The network's `datum.internal` zone, created for you. Compute publishes Instance names in it. | +| Private zone | A `DNSZone` with `visibility: Private` that you create, such as `corp.internal`. | +| Zone association | A `DNSZoneAssociation` that lets one network resolve one private zone. | +| Record set | A `DNSRecordSet` that holds records in a zone. | + +A private zone resolves only from the networks it's associated with. Two networks can each have a zone with the same domain, and each gets its own answers. + +## Find a network's DNS context and zone + +To list each network's DNS context and managed zone, run: + +```bash +datumctl get dnsresolvercontexts \ + -o custom-columns='CONTEXT:.metadata.name,NETWORK:.metadata.ownerReferences[0].name,ZONE:.status.managedNamespace.dnsZoneRef.name' +``` + +The output is similar to the following: + +```text +CONTEXT NETWORK ZONE +dns-default-4f1c2a9e7b30 default managed-8d03b6e1f2a4 +``` + +Use `CONTEXT` when you associate a zone with the network, and `ZONE` when you add records to the network's `datum.internal` zone. + +## Add a record to datum.internal + +To add a name to one network without creating a zone, add a record set to the network's managed zone. Replace `MANAGED_ZONE` with the `ZONE` from the previous section: + +```yaml +apiVersion: dns.networking.miloapis.com/v1alpha1 +kind: DNSRecordSet +metadata: + name: db +spec: + dnsZoneRef: + name: MANAGED_ZONE + recordType: AAAA + records: + - name: db + ttl: 60 + aaaa: + content: fd20:1::20 +``` + +`db.datum.internal` now resolves on that network only. You can't add records at or below `instances.datum.internal`, which Compute owns. + +## Create a private zone + +Create a zone when you want a namespace of your own, or one that several networks share: + +```yaml +apiVersion: dns.networking.miloapis.com/v1alpha1 +kind: DNSZone +metadata: + name: corp-internal +spec: + domainName: corp.internal + visibility: Private +``` + +Keep the following points in mind: + +- You can't change a zone's domain or visibility after you create it. Create a new zone instead. +- A private zone resolves nowhere until you associate it with a network. +- Prefer a domain you control, or one under `.internal`. If you create a private zone for a public domain, such as `example.com`, associated networks get your private answers instead of the public ones for every name in that domain. + +## Choose which networks resolve a zone + +Associate the zone with each network that should resolve it: + +```yaml +apiVersion: dns.networking.miloapis.com/v1alpha1 +kind: DNSZoneAssociation +metadata: + name: corp-internal-default +spec: + dnsZoneRef: + name: corp-internal + resolverContextRef: + name: dns-default-4f1c2a9e7b30 +``` + +To share the zone with another network, create another association that names that network's context. To stop a network from resolving the zone, delete its association. The zone and its records stay. + +An association can't be edited to point at a different zone or network. Delete it and create a new one. If you delete and recreate a zone with the same name, also recreate its associations. + +A network can't have two associated zones with the same domain. A zone can sit below another associated zone, such as `db.corp.internal` below `corp.internal`. Lookups use the zone with the longest matching domain. + +## Add records to a private zone + +Records in a private zone use the same `DNSRecordSet` resource as [public DNS](/domain-dns/dns): + +```yaml +apiVersion: dns.networking.miloapis.com/v1alpha1 +kind: DNSRecordSet +metadata: + name: corp-api +spec: + dnsZoneRef: + name: corp-internal + recordType: AAAA + records: + - name: api + ttl: 60 + aaaa: + content: fd20:1::5 + - name: api + ttl: 60 + aaaa: + content: fd20:1::6 +``` + +Private zones support `A`, `AAAA`, `CNAME`, `TXT`, `MX`, `SRV`, `CAA`, `NS`, `PTR`, `TLSA`, `HTTPS`, and `SVCB` records. For the rules that apply, see [Private DNS limits and behavior](/domain-dns/private-dns-reference#record-rules). + + + Instances have IPv6 addresses only. Use `AAAA` records for addresses on your network. + + +## Find services by name + +Use one of the following, depending on what you need: + +- **One Instance:** use its Compute name, such as `web-default-us-central-1-0.instances.datum.internal`. Read it from the Instance's `status.dns`. See [Private DNS for Compute](/compute/private-dns). +- **A stable name for a service:** add a `CNAME` to the network's `datum.internal` zone that points at an Instance name, such as `api.datum.internal` → `web-default-us-central-1-0.instances.datum.internal.`. Update the `CNAME` when you replace the Instance. +- **Several Instances behind one name:** create `AAAA` records for each address under one name, as in the example above. Clients pick an address from the answer. DNS doesn't check whether each address is healthy. + +## Check status + +A change goes through two steps. First the record set or association is accepted. Then the zone is programmed, and the name resolves. + +```bash +datumctl get dnsrecordset corp-api \ + -o jsonpath='{.status.conditions[?(@.type=="Accepted")].reason}' +datumctl get dnszone corp-internal +``` + +| Where | Condition | What it means | +| --- | --- | --- | +| Record set, association | `Accepted` | The change is valid. If it's `False`, the reason says why. | +| Zone | `Programmed` | The zone's latest records resolve from at least one resolver. | +| Zone | `Published` | Every resolver the zone needs has the latest records. | + +For what each reason means, see [Troubleshooting](/domain-dns/troubleshooting#private-dns). + +## Delete names and zones + +- Delete a record set to remove its names. Clients can keep an old answer until its TTL expires. +- Delete a zone association to stop one network from resolving the zone. +- Delete a zone to remove it from every network. Delete its record sets and associations too. +- Don't delete a network's managed zone or its association. Instance names on that network stop resolving. If you deleted one by mistake, contact [support@datum.net](mailto:support@datum.net). diff --git a/domain-dns/troubleshooting.mdx b/domain-dns/troubleshooting.mdx index b42877d..39ada65 100644 --- a/domain-dns/troubleshooting.mdx +++ b/domain-dns/troubleshooting.mdx @@ -75,3 +75,47 @@ If you use [ExternalDNS](/domain-dns/operations#automate-records-with-externaldn - The webhook needs permission to read `dnszones` and to manage `dnsrecordsets` in your project. For the webhook's metrics, see [Observability](/domain-dns/observability#externaldns-webhook-metrics). + +## Private DNS + +These checks apply to [Private DNS](/domain-dns/private-dns) names, which resolve only inside a gVPC network. + +### A private name doesn't resolve + +Work through these checks in order, from an Instance on the network: + +1. **Use the full name.** Look up `web-default-us-central-1-0.instances.datum.internal`, not `web-default-us-central-1-0`. Short names depend on search domains. +2. **Check the network.** A private name resolves only from networks its zone is associated with. An Instance name resolves only from the Instance's own network. +3. **Check the resolver.** Run `cat /etc/resolv.conf` in a `general-purpose` Instance. The app must use these resolvers. An app that uses its own resolver, such as DNS over HTTPS or a hard-coded public resolver, can't resolve private names. +4. **Check the Instance.** An Instance name exists only while the Instance is ready. Run `datumctl get instance INSTANCE_NAME -o yaml` and check `status.dns`. If its condition isn't `Ready`, the reason says why. +5. **Check the zone.** Run `datumctl get dnszone ZONE_NAME`. If `PROGRAMMED` isn't `True`, wait a minute and check again. A zone that isn't associated with any network shows no status. +6. **Check the record or association.** See the next section. +7. **Check `CNAME` targets.** A `CNAME` that points into another zone may return only the `CNAME`. Point it at a name in the same zone, or use `AAAA` records. + +### A record set or association isn't accepted + +Read the reason: + +```bash +datumctl get dnsrecordset RECORDSET_NAME \ + -o jsonpath='{.status.conditions[?(@.type=="Accepted")].reason}' +datumctl get dnszoneassociation ASSOCIATION_NAME \ + -o jsonpath='{.status.conditions[?(@.type=="Accepted")].reason}' +``` + +| Reason | What it means | What to do | +| --- | --- | --- | +| `UnsupportedPrivateRecord` | The record set uses a type or name that private zones don't support, such as `ALIAS`, `SOA`, or a `CNAME` at the zone's own domain. | Use a supported record. See [Record rules](/domain-dns/private-dns-reference#record-rules). | +| `ReservedScope` | The name is at or below a name that a Datum service owns, such as `instances.datum.internal`. | Use a different name. | +| `NameConflict` | An older record set already has this name and type, or a `CNAME` shares the name with another type. | Change the record in the record set that has it, or delete that record set first. | +| `MissingSRVTargetAddress` | An `SRV` target has no `A` or `AAAA` record in the same zone. | Add an address record for the target in the zone. | +| `ConflictingTTL` | One name in the record set has two different TTLs. | Use one TTL for each name. | +| `InvalidRecord`, `InvalidTTL` | A value doesn't match its record type, or the TTL is out of range. | Fix the value. | +| `ApexConflict` | Another zone with the same domain is associated with this network. The association whose name sorts first keeps the domain. | Delete the association you don't want. | +| `InvalidReference` | The association's zone or DNS context doesn't exist, was deleted, or was replaced by a new one with the same name. | Check both names. If they exist, delete the association and create it again. | + +A request can also be refused when you apply it. A message that starts with `ReservedScope:` means the same as the reason above. A `not found` error, or one that mentions `private zone lookup` or `resolver context lookup`, means the zone or DNS context you named doesn't exist in the project. + +### A name returns an old answer + +Clients and resolvers keep an answer until its TTL expires. Instance names have a 30 second TTL. Records you create default to 300 seconds. To make changes show up sooner, lower the record's TTL before you change it. diff --git a/galactic-vpc/limitations-and-roadmap.mdx b/galactic-vpc/limitations-and-roadmap.mdx index d0fd83c..7e65830 100644 --- a/galactic-vpc/limitations-and-roadmap.mdx +++ b/galactic-vpc/limitations-and-roadmap.mdx @@ -26,11 +26,9 @@ In addition to the [networking limitations that apply to all of Compute](/comput Datum is working on the following networking capabilities: - **Firewall rules:** Security groups that control the traffic to and from your Instances. -- **Private DNS:** Private DNS names, so Instances can find each other without IP addresses. - **Internet access setting:** A setting that turns internet access on or off for every Instance on a network. -- **Datum DNS resolver:** A DNS resolver that Datum runs for Instances, which also performs DNS64. -Outbound internet access, including IPv4 destinations, and viewing networks in the Datum Cloud portal are already available. For details, see [Reach the internet](/galactic-vpc/networks/traffic#reach-the-internet). +Outbound internet access, including IPv4 destinations, [Private DNS](/domain-dns/private-dns) names for Instances, and viewing networks in the Datum Cloud portal are already available. For details, see [Reach the internet](/galactic-vpc/networks/traffic#reach-the-internet). For what Datum is building next across the platform, see the [Platform roadmap](/platform/roadmap). diff --git a/galactic-vpc/networks/traffic.mdx b/galactic-vpc/networks/traffic.mdx index d436ee9..0b31e5a 100644 --- a/galactic-vpc/networks/traffic.mdx +++ b/galactic-vpc/networks/traffic.mdx @@ -21,7 +21,7 @@ The following table describes which kinds of traffic are possible: | To or from other addresses through an Instance | No | A network only delivers a packet addressed to an Instance's own address, and only accepts a packet from an Instance's own address. An Instance can't route traffic for other addresses, so a router or VPN appliance needs an overlay, such as VXLAN or a UDP tunnel, between Instances. | | Inbound from the internet | Through Datum's ALB | Instance addresses aren't reachable from the internet directly. Public HTTP and HTTPS traffic reaches Instances through Datum's [Application Load Balancer](/alb/overview). Raw TCP and UDP exposure is a preview limitation. | | Outbound to the internet | Yes | Instances can reach internet destinations over IPv6, and services that have only IPv4 addresses by hostname. See [Reach the internet](#reach-the-internet). | -| Lookups by name | Public names only | Instances resolve public DNS names. Private DNS names for Instances are on the [roadmap](/galactic-vpc/limitations-and-roadmap#planned-capabilities). Use IPv6 addresses to reach other Instances in the preview. | +| Lookups by name | Yes | Instances resolve public names, and the [Private DNS](/domain-dns/private-dns) names of other Instances on the same network, such as `web-default-us-central-1-0.instances.datum.internal`. | | Firewall filtering | Not in the preview | Firewall rules to filter traffic between Instances on a network are on the [roadmap](/galactic-vpc/limitations-and-roadmap#planned-capabilities). | The workload API accepts a `networkPolicy` field on each network interface, but the field has no effect. Don't rely on it to restrict traffic. To limit who can reach a service, check credentials in your app, or put services that must stay apart on different networks. Firewall rules for networks are on the [roadmap](/galactic-vpc/limitations-and-roadmap#planned-capabilities). @@ -32,7 +32,7 @@ To connect from one Instance to another on the same network, use the peer's priv - Make your app listen on IPv6 (`::`). An app that listens only on `0.0.0.0` accepts IPv4 connections only, and Instances don't have IPv4 addresses. - In a URL, put an IPv6 address in square brackets, such as `http://[fd20:4a3b:91c2:1::1:0:2]:8080/`. -- Private DNS names aren't available in the preview. To tell an app about its peers, pass their addresses in environment variables or a ConfigMap. +- Connect by name rather than by address. Each Instance has a [Private DNS](/compute/private-dns) name, such as `web-default-us-central-1-0.instances.datum.internal`, that follows the Instance's address. To try it, see the [Private DNS quickstart](/domain-dns/private-dns-quickstart). ## Reach the internet diff --git a/getting-started/first-workload.mdx b/getting-started/first-workload.mdx index f9c39e5..359f99c 100644 --- a/getting-started/first-workload.mdx +++ b/getting-started/first-workload.mdx @@ -107,7 +107,7 @@ This page deploys [draw.io](https://www.drawio.com/), an open source diagramming ## What's next -- To deploy your own image, check that your app listens on IPv6 and serves plain HTTP. During the preview, Instances have no persistent disks and no readiness checks. For details, see [Compute limitations](/compute/limitations-and-roadmap#limitations). +- To deploy your own image, make it listen on `::` (IPv6), not `0.0.0.0`, and serve plain HTTP. See [IPv6 readiness](/compute/troubleshooting#ipv6-readiness). During the preview, Instances have no persistent disks and no readiness checks. For details, see [Compute limitations](/compute/limitations-and-roadmap#limitations). - To pass configuration and secrets to a workload, see [Compute configuration](/compute/configuration). - To package your own app as a fast-starting unikernel, see [Unikernels](/compute/runtimes/unikernels). - To run in more locations or with more Instances, see [Placement and scaling](/compute/placement-and-scaling).