Domain Driven Architecture

23. Januar 2019 By: Vlad Bokov

Iproute in dda-serverspec

A while ago I asked people on twitter, how do they test that what's intended to be run == what's actually running ? Kubernetes appeared in replies instantly, but we will talk about a level beyond.

Imagine we have several network interfaces connected to a Linux server. One of them will become the default gateway for network packets. In order to redirect traffic to a specific destination (say 1.1.1.1) via network interface connected to another gateway (say 192.168.56.1) we have to do something like that:

echo 200 uplink2 >> /etc/iproute2/rt_tables
ip route add default via 192.168.56.2 table uplink2
ip rule add to 1.1.1.1 table uplink2

Routing tables belong to kernel stuff and they are exposed by iproute package. Now you can run ip route get 1.1.1.1 and get this reporting everything is ok:

1.1.1.1 via 192.168.56.1 dev enp0s8 table uplink2 src 192.168.56.101 uid 0
    cache

At this point a small lyrical digression here. Unix has got it right: small programs which do only one job (but they must do it well) should be just connected together via pipes to get everything you want. And iproute does its job - managing routing tables - well. The only thing at which it's bad is outputting its state. Unless you're using regular expressions upon its output (but then you'll have 2 problems, you know).

So basically you could compose a shell and run it against all your boxes. But maybe you've heard about dda-serverspec and in the new release you can do the same leveraging all the power of the library (execution against multiple servers in parallel, batching several commands and others matchers) in a very declarative and concise way.

For the impatient, this looks like this:

Now let's do this step by step:

Install

Go to the latest GitHub release and download dda-serverspec-standalone.jar

Inspect Targets

You may already suspect, we need to point to the running servers, which we want to test. This is ubuntu-targets.edn contents, which you can use for almost any other tools in DomainDrivenArchitecture.

{:existing [{:node-name "..." :node-ip "x.x.x.x"}]
 :provisioning-user {:login "..."
                     ;; there are more secure ways in DDA, just KISS it for now
                     :password {:plain "..."}}}

Inspect Testdefinition

We've already prepared a sample dda-serverspec test configuration, but right now we're interested only in :iproute section key and it's multiple variations of usage (ubuntu-serverspec.edn):

{:iproute [{:ip "1.1.1.1" :via "10.0.2.2"}
           {:hostname "stackoverflow.com" :via "10.0.2.2"}
           {:ip "2a00:1450:4001:81a:0:0:0:200e" :src "2001:0:53aa:64c:2822:4d:923c:d08d"}
           {:hostname "google.com" :src "2001:0:53aa:64c:2822:4d:923c:d08d"}
           {:hostname "ipv6.google.com" :dev "teredo"}]}

As you can see values are essential parts of iproute output. You can specify various combinations for both ipv4 and ipv6 like:

  • ip (or hostname) and gateway
  • ip (or hostname) and outgoing interface ip
  • ip (or hostname) and outgoing device name

Hostnames will be expanded to several ip tests and they will issue several iproute get commands in batch, parse results and pattern match expectations.

Spawn Probe and execute the Test

java -jar dda-serverspec-standalone.jar -v -t ubuntu-targets.edn ubuntu-serverspec.edn

In result either all tests passed, or you'll see yours expectation and found facts highlighted if they don't match:

test host: 1.1.1.1 [1_1_1_1],
missed: {:via "10.0.2.2"},
found facts: {:via "192.168.56.1", :src "192.168.56.101", :dev "enp0s8"}

Afterthoughts

Another small lyrical digression. Rich Hickey got it right: a database can (and probably should) be treated as a value at some point in time inside of your program. Why cannot we treat a remote server like that? Right now in kubernetes, this state is living encapsulated inside a golang process and it exposes endpoints like OOP is exposing public methods of some objects. Nice, but why cannot we do functional approach to this by decoupling state from the behavior?

A couple of years ago Facebook introduced (and still supports) a tool, which exposes the current system in SQL: osquery. But why restrict yourself to the tables? Why the binary should be copied over the target machines and executed there if we could do fire remote commands via ssh in parallel against different servers? Star dda-serverspec if you like this idea. This most recent support of iproute in the library is just a small step towards the tested data-oriented future of infrastructure management.


Tags: routing dda-serverspec-crate dda-pallet

Powered by Cryogen | Free Website Template by Download Website Templates | Datenschutzerklärung | Impressum