Skip to content

Instantly share code, notes, and snippets.

@colmmacc
Last active December 16, 2015 11:08
Show Gist options
  • Save colmmacc/5424866 to your computer and use it in GitHub Desktop.
Save colmmacc/5424866 to your computer and use it in GitHub Desktop.
Denominator rrset configuration feedback

Original thread; https://groups.google.com/forum/#!topic/denominator-dev/aOtc4r9TLTI

Just wanted to chime in with some brief suggestions.

Routing precedence

I think the proposals are both ambiguous about the precedence applied between weighting and geo selection. Some providers support just one precedence order between weighted and geo, some support both, and obviously we can never predict what future providers may support.

Geo->Weighted as a use-case makes intuitive sense, a good example is routing everyone on the East coast of the US to a datacenter on the east coast, but then balancing load across multiple endpoints "within" that selection. I think all the providers support this precedence order today.

Weighted->Geo can make sense too though, and allows people to do "trial runs" of geo-configurations. E.g. an admin might add/remove some states/territories to a geo configuration, but then want to slowly "blend in" that configuration to production, to avoid big shifts of load as users change regions. I think at least two providers support this today, and it can also be simulated by using intermediate CNAMEs or aliases if neccessary.

So based on that, rather than being locked in to a single implicit precedence by having weighted and geo groupings be equal peers in a list or map, it might be good to have some kind of explicit precedence. This could be done with nested maps in a JSON-like configuration as here, or another option with java would be to use annotating decorators, e.g.

@Geo(Group = "US")
@Weighted(weight = 2)
public ResourceRecordSet( ...

makes things pretty easy for callers and the precedence is unambiguous. Then again aspects are so niggly to use in method blocks that nested maps may the way to go :)

Keeping names and q-tuples together

Further down the road, when it comes to implementing DNSSEC, it's useful to keep in mind that NSEC/NSEC3 imply at least two ordered indexes; an ordered index of all names (or hashes of those names for NSEC3) for generating signed record chains, and an iterable ordered mapping of name->types tuples for generating the bitsets of types that exist for a given name. If RRSets can only be instantiated at the object level with "Name, Type" key pairings as the main input - it's easy to maintain these indeces and mappings.

The configuration language doesn't split these out as explicit keys , they're just peer meta-data to an rrset. If they're non-optional it might be equivalent, but it might also make it harder to easily maintain indices later. For example it can make it easier to maintain indices if you make these things immutable. So another way to go might be something like;

public ResourceRecordSet www = new ResourceRecordSet("www.example.com", "A");
www.setTTL(300); 
www.setRData( ... );
www.setConfig( ... );

In that kind of model the implementation naturally lends itself to the indexes which need to be maintained and regular Comparable() implementations can be used to order them, no need to worry about re-sorting on mutation.

Normalising group names/ids?

I found the group names and territory interaction a bit confusing. In a configuration like;

{
   "groupName": "West",
   "territoryNames": ["California", "Oregon"]
}

What's really going on? Is the groupName merely an arbitrary uniqueness identifier for a member rrset in a group? (in which case would something like "memberName" or "id" be more appropriate?) or does the configuration define the group - for later re-use? E.g. in a different rrset if I say "groupName" : "West" does that also apply the California and Oregon Territories?

Would it be useful to give groups/regions their own meta-configuration. E.g. allow global configuration of regions, say;

regions = { "West" : [ "California", "Oregon" ] }

and then permit rrsets to refer to those previously defined region names? You still get uniqueness at the rrset level, but also get a convenient form of abstractions and meta-configuration. Do operators really tinker with mappings on a record by record basis? (and if so is it too inconvenient to use region names to manage that?).

Random observation

The case of lowering TTLs on a per-region basis is super interesting, that's some impressive dedication to detail! It can be worth considering the same effect on weighted configuration though, if two weighted records exist for a given name/type pair, e.g.

foo.example.com A 192.0.2.1 , ttl = 300 weight = 1
bar.example.com A 192.0.2.2 , ttl = 100 weight = 1

the records are unlikely to be "actually" evenly weighted - because caching effects will supercede the weights. Not sure how paternalistic Denominator is planned to be, but something to keep in mind.

@codefromthecrypt
Copy link

Interesting thought about nested map vs list wrt precedence. I think nested exposes the relationship more explicitly than an ordered list, but also looks hairier. I feel like precedence can be equally expressed as ordered list ex. [geo, sourceIp] vs { geo : { sourceIp }} However, relationships that are nested with multiple children can't easily be expressed without making it more complex than a list. Ex [weighted, geo, sourceip] vs weighted : [geo, sourceIp].

Currently netflix doesn't use relationships more complex than can be expressed as a list. However, we should think through carefully where to optimize and how we are paying for such optimization ( ex more complexity vs less applicability). We need to think about that.

Wrt region stuff, I think I'll open a new post. We definitely use per record region groups and also assign ttls at the region level. The codes are a mess and incompatible. Ex UltraDNS use an extended version of ISO-3166, but territories are grouped into units not always expressed there. DynECT has a doc page saying all the codes possible but there's no programmatic means to compare or evaluate them. So we have a few questions. how to structure the data? Ex nested map vs a list of codes or names. In the case there's no back end means to group territories what do we do? How do we address things like fallback, proxied, and unknown source? What do we do about the fact that all 3 providers we use have no compatible territory values without data conversion?

Thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment