Compare commits

..
175 Commits
Author SHA1 Message Date
Matthias Radestock 8c5248da43 Add release 1.0.2 2015-08-18 08:27:26 +01:00
Matthias Radestock 7fb597a8bf Merge pull request #1313 from weaveworks/issues/1306-dns-compress-1-0-2
Try to compress too long replies (when forwarding).

Fixes #1306.
2015-08-17 18:05:04 +01:00
Alvaro Saurin c50c90ea8d Try to compress too long replies (when forwarding). 2015-08-17 18:50:16 +02:00
Tom Wilkie d220542491 Add sudo apt-get update to circle.yml 2015-08-17 13:37:41 +00:00
Matthias Radestock 181ce4cc60 Merge pull request #1296 from weaveworks/1294_extract_proxy_container_start
extract test functions for "start container via proxy"

Fixes #1294.
2015-08-13 19:40:53 +01:00
Matthias Radestock 65578211ef extract test functions for "start container via proxy"
This also eliminates the redefinition of 'start_container' by some of
the tests, which causes failures when multiple tests are run with
`run_all.sh`.

Fixes #1294.
2015-08-13 15:01:15 +01:00
Matthias Radestock 90ed76853c fix test breakage
on master, and only when running via `run_all.sh`. Weird.
2015-08-13 14:36:30 +01:00
Matthias Radestock a3b4d6cdbf consistency: use $SMALL_IMAGE instead of $BASE_IMAGE
whenever possible
2015-08-13 14:06:43 +01:00
Matthias Radestock 84c5c52090 fix broken test silliness 2015-08-13 14:05:17 +01:00
Matthias Radestock bd41d114b5 Merge pull request #1291 from weaveworks/docker-1.8
Docker 1.8 compatibility.

Fixes #1287.
2015-08-13 13:53:03 +01:00
Matthias Radestock 94d2f84364 refactor: use proxy abstraction 2015-08-13 13:50:29 +01:00
Paul Bellamy bf2b456af1 Don't use .Volumes in tests, as it's gone in docker 1.8 2015-08-13 13:36:47 +01:00
Paul Bellamy 4961e83686 [proxy] support new docker 1.8 --net="default" 2015-08-13 13:36:47 +01:00
Paul Bellamy f70dc6660a [proxy] lock docker api usage to 1.15 2015-08-13 13:36:47 +01:00
Paul Bellamy 360c0cb642 Merge commit '74eef4dedae617' into 1.0 2015-08-13 12:38:51 +01:00
Matthias Radestock 1ce9551ba6 Merge branch 'latest_release_doc_updates' into 1.0 2015-08-13 11:34:56 +01:00
Matthias Radestock 4c566c8587 correct typo 2015-08-13 11:34:16 +01:00
Paul Bellamy 74eef4deda [proxy] mount all tls volumes as readonly 2015-08-13 11:13:22 +01:00
Paul Bellamy 2576e819a7 Revert "fix intermittent test failure"
This reverts commit e2fec3d007.

Was causing a failure on circleci
2015-08-13 11:12:50 +01:00
Paul Bellamy e2fec3d007 fix intermittent test failure
Tests were running in the same shell, so function definitions were
leaking between tests.
2015-08-12 11:14:51 +01:00
Paul Bellamy 12ed5cc9ee Merge pull request #1284 from weaveworks/1279_proxy_weave_run
prevent proxy from interferring with `weave run`
2015-08-11 14:54:27 +01:00
Matthias Radestock f8639a57e7 prevent proxy from interferring with weave run
...which could result in containers unexpectedly getting multiple IP
addresses.

Fixes #1279.
2015-08-11 14:02:23 +01:00
Matthias Radestock 9e65cc20cb cosmetic 2015-08-10 17:33:45 +01:00
Tom Wilkie 25c4a2961e Merge pull request #1278 from weaveworks/1276_warn_on_iprange_overlap
warn on -iprange overlap
2015-08-10 17:27:47 +01:00
Matthias Radestock f4e7c85219 warn on -iprange overlap
Closes #1276.
2015-08-10 13:27:06 +01:00
Alvaro 475daa82b3 Merge pull request #1273 from weaveworks/1270_mdns_result_race
ignore DuplicateError when inserting mDNS answer in zone
2015-08-10 11:15:47 +02:00
Matthias Radestock c3b653b1b9 ignore DuplicateError when inserting mDNS answer in zone
When we issue two concurrent mDNS queries for the same name, the
answer to the second one encounters a DuplicateError when inserting
into the zone. We would return that error, which causes the query
would fail. And we'd cache that fact. All bad.

So ignore DuplicateError.

Fixes #1270.
2015-08-08 22:01:45 +01:00
Adam Harrison ed3207afe7 Merge remote-tracking branch 'upstream/latest_release_doc_updates' into 1.0 2015-08-06 09:51:31 +01:00
Adam Harrison 8e5b0ceceb Merge pull request #1262 from weaveworks/latest_release_doc_udpates
Fix IPAM doc bug
2015-08-06 09:48:14 +01:00
Adam Harrison 4a1bb1a33a Fix IPAM doc bug 2015-08-05 17:53:24 +01:00
Adam Harrison 93984e1955 Merge pull request #1261 from weaveworks/arp_all_ips
send ARP update for *all* container IPs; not just the first one
2015-08-05 14:38:16 +01:00
Matthias Radestock 67aae051d6 send ARP update for *all* container IPs; not just the first one
This was missed in #498.
2015-08-05 13:35:35 +01:00
Paul Bellamy eee13e7dd9 Merge pull request #1253 from weaveworks/1241-no-command-specified
[proxy] Handle case where no command is specified.
2015-08-04 13:11:35 +01:00
Paul Bellamy 7cc53c4c68 [proxy] Handle case where no command is specified.
The docker daemon can't do this because we set /w/w.
2015-08-04 12:32:42 +01:00
Paul Bellamy 78e0e79b26 Merge pull request #1238 from weaveworks/1232-weavewait-image
[proxy] only mount /w into weavewaited containers
2015-07-31 10:57:26 +01:00
Paul Bellamy 4958b8d37a [proxy] Mount /w from the host for weavewaited containers
We set it at container create. Had tried also setting it at start, but
it seems to cause weird behaviour, and there is no way to do it from the
CLI.
2015-07-30 15:11:03 +01:00
Paul Bellamy e2389a4061 [proxy] Don't try to attach if container failed to start 2015-07-30 13:31:47 +01:00
Paul Bellamy 5e9bd5424a Removed all the imports from "code.google.com" 2015-07-29 15:47:02 +01:00
Matthias Radestock ba0ffd225e Merge pull request #1231 from weaveworks/issues/1229-explicitly-set-docker-bridge-mac
Enforce docker bridge address assignment type on launch

Fixes #1229.
2015-07-28 17:59:46 +01:00
Adam Harrison a14d4d9f8e Enforce docker bridge address assignment type on launch 2015-07-28 17:51:48 +01:00
Matthias Radestock d5e510f778 Merge branch 'latest_release_doc_updates' into 1.0 2015-07-27 14:24:33 +01:00
Matthias Radestock be8e414d5a Merge pull request #1217 from weaveworks/1186_document_root_docker
document how to run weave when docker access is root-only

Closes #1186.
2015-07-27 14:23:50 +01:00
Matthias Radestock 65e94f624b document how to run weave when docker access is root-only
Closes #1186.
2015-07-27 14:13:50 +01:00
Matthias Radestock a20ca49344 Merge pull request #1206 from weaveworks/1201-weavewait-ro
[proxy] Mount weavewait readonly so it can't be tampered with

Fixes #1201.
2015-07-21 11:41:48 +01:00
Paul Bellamy aa8466f688 [proxy] Mount weavewait readonly so it can't be tampered with 2015-07-21 11:30:56 +01:00
Paul Bellamy 53628fdeff Merge pull request #1187 from weaveworks/1182-proxy-tls-close
[proxy] Fully close TLS sockets, as they have no CloseWrite
2015-07-20 16:46:21 +01:00
Matthias Radestock dafa30725e Merge branch 'latest_release_doc_updates' into 1.0 2015-07-17 15:07:19 +01:00
Matthias Radestock 24b9a56e0a Merge pull request #1172 from weaveworks/issues/1061-improve-blockquote
Use Boostrap styles for warnings in docs

Fixes #1061.
2015-07-17 15:06:40 +01:00
David Kaltschmidt e7f6682593 Use bootstrap alert styles for blockquote 2015-07-17 15:14:29 +02:00
Paul Bellamy 3f4b385b0f [proxy] If we can't CloseWrite a connection (tls), just Close it so clients don't hang 2015-07-17 14:09:27 +01:00
Paul Bellamy 5fc16a8267 [proxy] use a waitgroup as it's more semantically accurate 2015-07-17 14:08:51 +01:00
Paul Bellamy 38176dcbb6 Merge remote-tracking branch 'upstream/latest_release_doc_updates' into 1.0 2015-07-17 12:46:48 +01:00
Paul Bellamy f3131fab57 Merge pull request #1175 from paulbellamy/975-boot2docker-documentation-update
updating boot2docker docs for proxy
2015-07-17 12:32:54 +01:00
Paul Bellamy 397f1398ee updating boot2docker docs for proxy 2015-07-17 12:30:14 +01:00
Paul Bellamy 1afdac4d2c Merge pull request #1167 from weaveworks/1157-proxy-net-host
[proxy] do not weave attach containers in '--net=host|container:<name|id>'
2015-07-16 15:24:37 +01:00
Paul Bellamy c6fa9cb17e refactor weaveCIDRsFromConfig to return an error message 2015-07-16 15:15:32 +01:00
Paul Bellamy 9619a27f8c [proxy] adding log message for ignored containers 2015-07-16 14:01:22 +01:00
Paul Bellamy c13154eea9 updating comment as per golint 2015-07-16 13:58:30 +01:00
Paul Bellamy 1132d26d47 [proxy] do not weave attach containers in '--net=host|container:<name|id>' 2015-07-16 13:58:27 +01:00
Adam Harrison 77bc56751b Merge pull request #1164 from weaveworks/1162_detect_host_netns_in_container
fix detection of host netns when weave script runs inside container
2015-07-16 13:33:19 +01:00
Matthias Radestock b32c017f33 fix detection of host netns when weave script runs inside container
$$ refers to the pid in the container's process namespace, so using it
as a reference into /hostproc is entirely wrong.

Fixes #1162.
2015-07-16 13:19:56 +01:00
Matthias Radestock a982146cbe Merge pull request #1153 from weaveworks/1143-non-weave-exec
[proxy] should not attempt weavewait in on weave container's execs

Fixes #1143.
2015-07-15 17:40:13 +01:00
Paul Bellamy e4422205e8 [proxy] should not attempt weavewait in on weave container's execs 2015-07-15 16:14:14 +01:00
Matthias Radestock b476bd2afe Merge pull request #1137 from weaveworks/1109-docker-bridge-ip
[proxy] respect custom DOCKER_BRIDGE

Fixes #1109.
2015-07-14 17:52:08 +01:00
Paul Bellamy acd8bdec21 [proxy] respect custom DOCKER_BRIDGE 2015-07-14 16:33:35 +01:00
Matthias Radestock 6386c1bd18 Merge branch 'latest_release_doc_updates' into 1.0 2015-07-14 15:36:55 +01:00
Matthias Radestock 2e93a4c18e Merge pull request #1132 from weaveworks/issues/945-secure-router-config
Improvements to password handling recommendations

Closes #945.
2015-07-14 15:31:20 +01:00
Adam Harrison e26e7e29f2 Improvements to password handling recommendations 2015-07-14 14:48:58 +01:00
Matthias Radestock 1f3d054b09 Merge pull request #1124 from weaveworks/issues/1037-mitigate-entropy-depletion
Mitigate entropy depletion

Closes #1037.
2015-07-13 19:06:54 +01:00
Adam Harrison e2f8b6f9fd Document /dev/random blocking issue 2015-07-13 15:02:31 +01:00
Adam Harrison f3c4a9fc6d Limit router accept rate with token bucket 2015-07-13 15:02:31 +01:00
Adam Harrison 9634526a67 Add token bucket implementation 2015-07-13 15:01:04 +01:00
Adam Harrison b67c102fe5 Remove simple sleep from router accept 2015-07-13 15:01:04 +01:00
Adam Harrison 835d99e6fe Merge pull request #1104 from weaveworks/1083-async-claim
Don't wait to claim addresses from IPAM
2015-07-10 14:03:05 +01:00
Bryan Boreham b93070f91a Fix log message on peer move 2015-07-09 12:51:52 +01:00
Bryan Boreham cf4ce0a07d Don't cancel address claim when caller closes socket 2015-07-09 10:47:34 +01:00
Bryan Boreham 78c4b06492 Don't wait for certainty before responding to Claim
Conflicts:
	ipam/claim.go
2015-07-09 10:47:27 +01:00
Matthias Radestock 2ced8b9469 Merge branch 'latest_release_doc_updates' into 1.0 2015-07-08 16:53:13 +01:00
Matthias Radestock 26c1bcf866 clarify role of IP allocator range
Part of #1035.
2015-07-08 16:51:25 +01:00
Adam Harrison bde445df9b Merge pull request #1089 from weaveworks/1086_dns_search_without_equals
detect `--dns-search <arg>`
2015-07-07 10:16:21 +01:00
Matthias Radestock 02715f88d5 cosmetic: re-order option parsing
to match the order in which we susequently process them.
2015-07-06 17:26:04 +01:00
Matthias Radestock 706f9ee352 detect --dns-search <arg>
...and not just `--dns-search=<arg>`

Fixes #1086.
2015-07-06 17:22:42 +01:00
Matthias Radestock e3ab396428 Merge branch 'latest_release_doc_updates' into 1.0 2015-07-06 10:59:34 +01:00
Matthias Radestock df31454c30 Merge commit 'c8032b6' into latest_release_doc_updates 2015-07-06 10:58:18 +01:00
Matthias Radestock bf73029d15 cosmetic: goimports -w . 2015-07-03 20:41:35 +01:00
Matthias Radestock 4dbd657a26 import gopacket from github instaead of google code
The latter redirects to the former, which breaks `go get`.

Closes #1071.
2015-07-03 20:32:27 +01:00
Matthias Radestock a3a7a19870 simplifying refactor 2015-07-03 14:28:18 +01:00
Matthias Radestock 251c68e85a Merge pull request #1064 from weaveworks/issues/1023-await-ipam-forever
Wait forever for IPAM

Fixes #1023.
2015-07-03 14:17:52 +01:00
Adam Harrison 227cb11f25 Router, DNS and proxy wait forever by default 2015-07-03 14:01:34 +01:00
Adam Harrison 6097dc8aaa Add wait forever capability to EnsureInterface 2015-07-03 14:01:34 +01:00
Matthias Radestock 9e32605183 Merge branch 'latest_release_doc_updates' into 1.0 2015-07-03 11:45:37 +01:00
Matthias Radestock 9009e0eb7f one more s/proxy/Weave Docker API proxy 2015-07-03 11:45:05 +01:00
Matthias Radestock 243d445d1b Merge branch 'latest_release_doc_updates' into 1.0 2015-07-03 10:59:10 +01:00
Matthias Radestock 65cd2b0e04 missed one 2015-07-03 10:58:22 +01:00
Matthias Radestock 33b230c114 Merge branch 'latest_release_doc_updates' into 1.0 2015-07-03 10:56:00 +01:00
Matthias Radestock 6389af6ea2 Merge pull request #1066 from weaveworks/1019_rename_proxy_in_docs
introduce 'Proxy' as 'Docker API Proxy'

Closes #1066.
2015-07-03 10:55:17 +01:00
Matthias Radestock 8b35f5e8fe fix typo in comment 2015-07-03 10:03:07 +01:00
Matthias Radestock 7d5dcfafc9 introduce 'Proxy' as 'Docker API Proxy'
in order to reduce potential confusion about its role.

Closes #1019.
2015-07-03 03:33:23 +01:00
Matthias Radestock af40ebcab4 Merge pull request #1062 from weaveworks/issues/1006-fix-hostname-derivation
Disable hostname derivation when container name is too long

Fixes #1006.
2015-07-02 16:34:40 +01:00
Adam Harrison d427c99161 Add smoke test 2015-07-02 14:29:38 +01:00
Adam Harrison d1a887857d Enforce maximum length on weave run hostname derivation 2015-07-02 14:29:38 +01:00
Adam Harrison 3914c4c018 Enforce maximum length on proxy hostname derivation 2015-07-02 14:29:34 +01:00
Matthias Radestock 3bd5ae56f0 fix make update
Trying to build the thing for which we want to fetch the dependencies
is rather silly.
2015-07-02 11:46:48 +01:00
Matthias Radestock a05a3c4b26 Merge pull request #1054 from weaveworks/1042-reset-first-10
Call `weave reset` earlier in smoke-test set-up, to improve reliability

Fixes #1042.
2015-07-01 14:01:29 +01:00
Bryan Boreham a938608cc8 Call weave reset before deleting containers, to improve clean-down 2015-07-01 13:19:43 +01:00
Matthias Radestock ba1e75405f Merge branch 'latest_release_doc_updates' into 1.0 2015-07-01 11:34:24 +01:00
Matthias Radestock 0f5f671054 Merge pull request #1051 from weaveworks/issues/1046-clarify-weavedns-docs
Draw attention to --hostname precedence

Fixes #1046.
2015-07-01 11:33:24 +01:00
Adam Harrison 5b9d350002 Draw attention to --hostname precedence 2015-07-01 11:15:08 +01:00
Matthias Radestock ec62029db5 Merge pull request #1024 from weaveworks/982-fix-mock-gossip3
Flush messages from mock gossip in IPAM test

Fixes #982.
2015-06-26 13:44:57 +01:00
Bryan Boreham c84c5dbcdf Make TestGossipRouter goroutine easier to follow 2015-06-26 11:53:14 +01:00
Bryan Boreham 6725c8355f Check the result of Allocate in TestFakeRouterSimple() 2015-06-26 11:53:03 +01:00
Bryan Boreham c659e3448a Add a flush() function to the mock gossip router, and call it where required 2015-06-26 11:40:58 +01:00
Bryan Boreham 959e5f0082 Use different object types for mock gossip messages 2015-06-26 11:38:25 +01:00
Bryan Boreham 6488b0d11c More idiomatic exitChan 2015-06-26 11:38:07 +01:00
Matthias Radestock 9253d45968 Merge pull request #1010 from bboreham/896-check-gossip
Try other peers for space if we get errors

Fixes #896
2015-06-25 17:05:40 +01:00
Bryan Boreham 8a4b0d536e Updated after review feedback 2015-06-25 15:41:06 +01:00
Bryan Boreham c76f640e2e Simpler implementation of weighted-random order 2015-06-25 14:54:44 +01:00
Bryan Boreham b472da18f0 Improve logging of unicast gossip errors 2015-06-25 14:04:37 +01:00
Bryan Boreham c58cc449c0 More complex ChoosePeersToAskForSpace, with better complexity 2015-06-25 13:19:49 +01:00
Bryan Boreham af9668f130 Keep trying peers to ask for space until we find one that doesn't error 2015-06-25 12:47:38 +01:00
Bryan Boreham 9f784b3c31 Report errors in unicasting gossip 2015-06-25 12:22:53 +01:00
Matthias Radestock 5f95de19ce Merge branch 'latest_release_doc_updates' into 1.0 2015-06-24 17:25:51 +01:00
Fintan Ryan 8fb00ff206 Merge pull request #1002 from weaveworks/include-css
Include stylesheet in repo, update footer
2015-06-24 17:09:53 +01:00
David Kaltschmidt 00744fb9b4 use relative paths for stylesheet in docs 2015-06-24 17:54:50 +02:00
David Kaltschmidt 8250e05618 include stylesheet in repo, update footer
need because website's custom.css is fingerprinted
2015-06-24 17:18:54 +02:00
Matthias Radestock 9ae45f6674 Merge branch 'latest_release_doc_updates' into 1.0 2015-06-24 02:52:37 +01:00
Matthias Radestock 6c3aa99595 bump min required docker version for build
to the same version we use everywhere else, e.g. in weaveexec
2015-06-24 02:51:24 +01:00
Matthias Radestock 2c73fd6dde Merge branch 'latest_release_doc_updates' into 1.0 2015-06-23 23:17:38 +01:00
Matthias Radestock 3b27413887 fix broken link 2015-06-23 23:17:05 +01:00
Adam Harrison 17ee829299 Merge branch 'latest_release_doc_updates' into 1.0 2015-06-23 15:05:02 +01:00
Adam Harrison 5db39466e8 Fix broken IPAM link 2015-06-23 15:04:37 +01:00
Matthias Radestock cc4ab80f62 Merge branch 'latest_release_doc_updates' into 1.0 2015-06-23 14:57:51 +01:00
Matthias Radestock 0e47cee661 remove references to dns, ipam and proxy docs from ToCs
Since they are now explained and referenced prominently from the main
Features documentation.
2015-06-23 14:53:49 +01:00
Adam Harrison d6dca80dd7 Merge branch 'latest_release_doc_updates' into 1.0
Pull in GCE fix
2015-06-23 14:49:36 +01:00
Tom Wilkie 74c391f19c Update gce.sh make_template command, and build a fresh template. 2015-06-23 14:48:48 +01:00
Adam Harrison 7e36dc01e8 Merge documentation from branch 'latest_release_doc_updates' into 1.0 2015-06-23 14:35:30 +01:00
Adam Harrison 9020c84f81 Merge pull request #990 from awh/feature_docs_proxy_section
Add docker integration section to feature docs
2015-06-23 14:34:25 +01:00
Adam Harrison d0a1514ab6 Removed redundant further reading section from feature docs 2015-06-23 14:33:33 +01:00
Adam Harrison 06c3a0cf2a Add docker integration section to feature docs 2015-06-23 14:33:29 +01:00
Adam Harrison a1913130e7 Merge documentation from branch 'latest_release_doc_updates' into 1.0 2015-06-23 14:18:42 +01:00
Matthias Radestock f29ee3ad05 Merge pull request #986 from awh/feature_docs_weavedns_section
Add service discovery section to features docs
2015-06-23 13:55:50 +01:00
Adam Harrison 19a3fc6b9e Add naming and discovery section to features docs 2015-06-23 13:50:37 +01:00
Adam Harrison 043d15355c Restore commit lost to force push 2015-06-23 11:53:22 +01:00
Matthias Radestock 9ec1ce3225 Merge pull request #981 from weaveworks/970_show_docker_py_test_failures
show docker-py test failures
2015-06-23 10:30:57 +01:00
Matthias Radestock 1b4f83c067 Merge branch 'latest_release_doc_updates' into 1.0 2015-06-23 09:53:44 +01:00
Matthias Radestock c126c403e7 Merge pull request #983 from rade/improve_ipam_doc_integration
improve IPAM doc integration
2015-06-23 09:52:39 +01:00
Matthias Radestock 90b9b3c1bf 'address allocation' is the feature
covering both automatic and manual allocation
2015-06-23 09:50:39 +01:00
Matthias Radestock 1a17b41bc3 reduce test output noise 2015-06-23 09:42:46 +01:00
Matthias Radestock 2e5e0a7730 remove pointless assertion 2015-06-23 09:42:46 +01:00
Matthias Radestock b2f62cc635 show test failure output
step towards fixing #970
2015-06-23 09:42:46 +01:00
Matthias Radestock 0a553d6630 Merge branch 'latest_release_doc_updates' into 1.0 2015-06-22 22:59:16 +01:00
Matthias Radestock e51c240ea1 fix broken links 2015-06-22 22:57:48 +01:00
Paul Bellamy f5201469a3 Merge pull request #980 from paulbellamy/only-one-entrypoint
[proxy] Only prepend weavewait if not already present
2015-06-22 17:28:20 +01:00
Paul Bellamy 34aa2e32d8 [proxy] Only prepend weavewait if not already present
This way `docker commit` will not stack up weavewaits.
2015-06-22 15:24:49 +01:00
Bryan Boreham 9a631d0ecd Merge documentation from branch 'latest_release_doc_updates' into 1.0 2015-06-22 14:25:56 +01:00
Bryan Boreham c8032b6b25 Merge pull request #977 from bboreham/proxy-net-syntax
Change one IPAM proxy example to use a network
2015-06-22 14:24:24 +01:00
Bryan Boreham 68ca6ebe04 Change one IPAM proxy example to use the 'net:' syntax 2015-06-22 14:15:24 +01:00
Adam Harrison 1bbec56cc7 Merge documenation from branch 'latest_release_doc_updates' into 1.0 2015-06-22 12:02:35 +01:00
Adam Harrison b86bae9c86 Fix incorrect address in service import/export examples 2015-06-22 12:00:57 +01:00
Matthias Radestock 6f798f723a Merge remote-tracking branch 'upstream/1.0' into 1.0 2015-06-22 11:17:40 +01:00
Adam Harrison b1bd1d4d6a Merge pull request #964 from awh/v1.0_use_proxy_doc_updates
Update documentation to leverage proxy
2015-06-22 10:46:00 +01:00
Adam Harrison 1e638be7ac Remove weave run from how it works 2015-06-22 10:36:56 +01:00
Adam Harrison acd2b9abeb Reword proxy hyperlink text in index 2015-06-22 10:36:56 +01:00
Adam Harrison 6ddecfc764 Update proxy docs 2015-06-22 10:36:56 +01:00
Adam Harrison f15ad71354 Update IPAM docs to use proxy 2015-06-22 10:36:56 +01:00
Adam Harrison 4d54af39b0 Update weaveDNS docs to use proxy 2015-06-22 10:36:56 +01:00
Adam Harrison 81d5a8f4f5 Update features docs to use proxy 2015-06-22 10:36:56 +01:00
Adam Harrison 344119f42a Update README examples to use proxy 2015-06-22 10:36:52 +01:00
Matthias Radestock 514db8efdd Merge branch 'latest_release_doc_updates' into 1.0 2015-06-22 10:31:20 +01:00
Paul Bellamy 0693ec55c6 Merge pull request #974 from rade/972_remove_proxy_d_option_from_docs
remove the `-D` proxy option from the docs
2015-06-22 10:29:16 +01:00
Matthias Radestock 56c720b078 remove the -D proxy option from the docs
It doesn't do anything useful since the weave script needs to be able
to talk to docker on the standard unix socket.

Also remove dangling reference to 'localhost', and move note about
firwalls to where it is most pertinent.

Part fix to #972.
2015-06-22 10:20:18 +01:00
Matthias Radestock 403b9654f1 Merge remote-tracking branch 'upstream/1.0' into latest_release_doc_updates 2015-06-21 10:41:38 +01:00
Matthias Radestock 84775e414b Add release 1.0.1 2015-06-21 10:05:52 +01:00
Matthias Radestock d913ca869c Merge branch '967_include_image_name_in_inspect_error' into 1.0 2015-06-21 09:38:42 +01:00
Matthias Radestock 3732f968d0 include image name in errors
The go docker client's ErrNoSuchImage does not include the image
name. However, it is imperative that this name appears in error
messages sent to clients, since the docker client, as of version
1.7.0, only automatically pulls images when their name is present in
the error.

Fixes #967.
2015-06-20 23:36:48 +01:00
68 changed files with 6867 additions and 621 deletions

No files matched your search

+20
View File
@@ -1,3 +1,23 @@
## Release 1.0.2
This release fixes a number of bugs, including some security
vulnerabilities in the Weave Docker API proxy, hangs and failures in
address allocation, and sporadic failures in name resolution.
More details in the
[change log](https://github.com/weaveworks/weave/issues?q=milestone%3A1.0.2).
The release is fully compatible with other 1.0.x versions, so existing
clusters can be upgraded incrementally.
## Release 1.0.1
This is a bug fix release, addressing the following issue:
- executing `docker run` from a Docker 1.7 client against the weave
proxy would report a `no such image` error when the requested image
wasn't present on the Docker host, instead of downloading it.
## Release 1.0.0
**Highlights**:
+1 -1
View File
@@ -38,7 +38,7 @@ all: $(EXPORTS)
travis: $(EXES)
update: $(EXES)
update:
go get -u -f -v -tags -netgo $(addprefix ./,$(dir $(EXES)))
$(WEAVER_EXE) $(WEAVEDNS_EXE) $(WEAVEPROXY_EXE) $(NETCHECK_EXE): common/*.go common/*/*.go net/*.go
+34 -28
View File
@@ -52,36 +52,38 @@ Say you have docker running on two hosts, accessible to each other as
`$HOST1` and `$HOST2`, and want to deploy an application consisting of
two containers, one on each host.
On `$HOST1` run
On $HOST1 we run:
host1$ weave launch
host1$ weave launch-dns
host1$ weave run --name a1 -ti ubuntu
host1$ weave launch && weave launch-dns && weave launch-proxy
host1$ eval $(weave proxy-env)
host1$ docker run --name a1 -ti ubuntu
The first two lines start the weave router and DNS, each inside their
own container - this needs to be done once per host. Whilst the
required docker images are downloaded automatically, there is also a
`weave setup` command for downloading all the images required for
weave operation; this is a strictly optional step which is especially
useful for automated installation of weave and ensures that any
subsequent weave commands do not encounter delays due to image
downloading.
> NB: If the first command results in an error like
> `http:///var/run/docker.sock/v1.19/containers/create: dial unix
> /var/run/docker.sock: permission denied. Are you trying to connect
> to a TLS-enabled daemon without TLS?` then you likely need to be
> 'root' in order to connect to the Docker daemon. If so, run the
> above and all subsequent commands in a *single* root shell (e.g. one
> created with `sudo -s`). Do *not* prefix individual commands with
> `sudo`, since some commands modify environment entries and hence
> they all need to be executed from the same shell.
The third line runs our application container, allocating it an IP
address on the weave network and registering it in DNS. `weave run`
invokes `docker run -d` behind the scenes, so we could be launching
any container this way; here we just take a stock ubuntu container and
launch a shell in it. There's also a `weave start` command, which
invokes `docker start` for starting existing containers.
The first line runs the weave router, DNS and Docker API proxy, each
in their own container. The second line sets the `DOCKER_HOST`
environment variable to point to the proxy, so that containers
launched via the docker command line are automatically attached to the
weave network. Finally, we run our application container; this happens
via the proxy so it is automatically allocated an IP address and
registered in DNS.
If our application consists of more than one container on this host we
simply launch them with a variation on third second line.
That's it! If our application consists of more than one container on
this host we simply launch them with `docker run` as appropriate.
Next we repeat similar steps on `$HOST2`...
host2$ weave launch $HOST1
host2$ weave launch-dns
host2$ weave run --name a2 -ti ubuntu
host2$ weave launch $HOST1 && weave launch-dns && weave launch-proxy
host2$ eval $(weave proxy-env)
host2$ docker run --name a2 -ti ubuntu
The only difference, apart from the name of the application container,
is that we tell our weave that it should peer with the weave on
@@ -98,21 +100,25 @@ available. Also, we can tell weave to connect to multiple peers by
supplying multiple addresses, separated by spaces. And we can
[add peers dynamically](http://docs.weave.works/weave/latest_release/features.html#dynamic-topologies).
The router, DNS and Docker API proxy need to be started once per
host. The relevant container images are pulled down on demand, but if
you wish you can preload them by running `weave setup` - this is
particularly useful for automated deployments, and ensures that there
are no delays during later operations.
Now that we've got everything set up, let's see whether our containers
can talk to each other...
On `$HOST1`...
In the container started on `$HOST1`...
host1$ docker attach a1
root@a1:/# ping -c 1 -q a2
PING a2.weave.local (10.160.0.2) 56(84) bytes of data.
--- a2.weave.local ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.341/0.341/0.341/0.000 ms
Similarly, on `$HOST2`...
Similarly, in the container started on `$HOST2`...
host2$ docker attach a2
root@a2:/# ping -c 1 -q a1
PING a1.weave.local (10.128.0.2) 56(84) bytes of data.
--- a1.weave.local ping statistics ---
@@ -125,8 +131,8 @@ to each other.
## Find out more
* [Documentation homepage](http://docs.weave.works/weave/latest_release/)
* [Getting Started Guides](http://weave.works/guides/)
* [Features](http://docs.weave.works/weave/latest_release/features.html)
* [Automatic Discovery with WeaveDNS](http://docs.weave.works/weave/latest_release/weavedns.html)
* [Troubleshooting](http://docs.weave.works/weave/latest_release/troubleshooting.html)
* [Building](http://docs.weave.works/weave/latest_release/building.html)
* [How it works](http://docs.weave.works/weave/latest_release/how-it-works.html)
+1
View File
@@ -26,6 +26,7 @@ dependencies:
docker save weaveworks/weave-build >$WEAVE_BUILD;
fi
post:
- sudo apt-get update
- sudo apt-get install bc
- pip install requests
- curl https://sdk.cloud.google.com | bash
+9 -3
View File
@@ -2,6 +2,7 @@ package ipam
import (
"fmt"
"github.com/weaveworks/weave/ipam/address"
)
@@ -42,9 +43,14 @@ func (g *allocate) Try(alloc *Allocator) bool {
}
// out of space
if donor, err := alloc.ring.ChoosePeerToAskForSpace(g.r.Start, g.r.End); err == nil {
alloc.debugln("Decided to ask peer", donor, "for space in range", g.r)
alloc.sendSpaceRequest(donor, g.r)
donors := alloc.ring.ChoosePeersToAskForSpace(g.r.Start, g.r.End)
for _, donor := range donors {
if err := alloc.sendSpaceRequest(donor, g.r); err != nil {
alloc.debugln("Problem asking peer", donor, "for space:", err)
} else {
alloc.debugln("Decided to ask peer", donor, "for space in range", g.r)
break
}
}
return false
+4 -5
View File
@@ -202,10 +202,9 @@ func (alloc *Allocator) Lookup(ident string, r address.Range) (address.Address,
}
// Claim an address that we think we should own (Sync)
func (alloc *Allocator) Claim(ident string, addr address.Address, cancelChan <-chan bool) error {
func (alloc *Allocator) Claim(ident string, addr address.Address) error {
resultChan := make(chan error)
op := &claim{resultChan: resultChan, ident: ident, addr: addr,
hasBeenCancelled: hasBeenCancelled(cancelChan)}
op := &claim{resultChan: resultChan, ident: ident, addr: addr}
alloc.doOperation(op, &alloc.pendingClaims)
return <-resultChan
}
@@ -575,14 +574,14 @@ func (alloc *Allocator) propose() {
alloc.gossip.GossipBroadcast(alloc.Gossip())
}
func (alloc *Allocator) sendSpaceRequest(dest router.PeerName, r address.Range) {
func (alloc *Allocator) sendSpaceRequest(dest router.PeerName, r address.Range) error {
buf := new(bytes.Buffer)
enc := gob.NewEncoder(buf)
if err := enc.Encode(r); err != nil {
panic(err)
}
msg := router.Concat([]byte{msgSpaceRequest}, buf.Bytes())
alloc.gossip.GossipUnicast(dest, msg)
return alloc.gossip.GossipUnicast(dest, msg)
}
func (alloc *Allocator) sendRingUpdate(dest router.PeerName) {
+8 -3
View File
@@ -143,7 +143,7 @@ func TestAllocatorClaim(t *testing.T) {
alloc.claimRingForTesting()
addr1, _ := address.ParseIP(testAddr1)
err := alloc.Claim(container3, addr1, nil)
err := alloc.Claim(container3, addr1)
wt.AssertNoErr(t, err)
// Check we get this address back if we try an allocate
addr3, _ := alloc.Allocate(container3, subnet, nil)
@@ -168,7 +168,7 @@ func TestCancel(t *testing.T) {
CIDR = "10.0.1.7/26"
)
router := TestGossipRouter{make(map[router.PeerName]chan gossipMessage), 0.0}
router := TestGossipRouter{make(map[router.PeerName]chan interface{}), 0.0}
alloc1, subnet := makeAllocator("01:00:00:02:00:00", CIDR, 2)
alloc1.SetInterfaces(router.connect(alloc1.ourName, alloc1))
@@ -256,13 +256,17 @@ func TestTransfer(t *testing.T) {
wt.AssertTrue(t, err == nil, "Failed to get address")
router.GossipBroadcast(alloc2.Gossip())
router.flush()
router.GossipBroadcast(alloc3.Gossip())
router.flush()
router.removePeer(alloc2.ourName)
router.removePeer(alloc3.ourName)
alloc2.Stop()
alloc3.Stop()
router.flush()
wt.AssertSuccess(t, alloc1.AdminTakeoverRanges(alloc2.ourName.String()))
wt.AssertSuccess(t, alloc1.AdminTakeoverRanges(alloc3.ourName.String()))
router.flush()
wt.AssertEquals(t, alloc1.NumFreeAddresses(subnet), address.Offset(1022))
@@ -282,7 +286,8 @@ func TestFakeRouterSimple(t *testing.T) {
alloc1 := allocs[0]
//alloc2 := allocs[1]
alloc1.Allocate("foo", subnet, nil)
_, err := alloc1.Allocate("foo", subnet, nil)
wt.AssertTrue(t, err == nil, "Failed to get address")
}
func TestAllocatorFuzz(t *testing.T) {
+24 -16
View File
@@ -3,28 +3,35 @@ package ipam
import (
"fmt"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/ipam/address"
"github.com/weaveworks/weave/router"
)
type claim struct {
resultChan chan<- error
ident string
addr address.Address
hasBeenCancelled func() bool
resultChan chan<- error
ident string
addr address.Address
}
func (c *claim) sendResult(result error) {
// Make sure we only send a result once, since listener stops listening after that
if c.resultChan != nil {
c.resultChan <- result
close(c.resultChan)
c.resultChan = nil
}
if result != nil {
common.Error.Println("[allocator] " + result.Error())
}
}
// Try returns true for success (or failure), false if we need to try again later
func (c *claim) Try(alloc *Allocator) bool {
if (c.hasBeenCancelled)() {
c.Cancel()
return true
}
if !alloc.ring.Contains(c.addr) {
// Address not within our universe; assume user knows what they are doing
alloc.infof("Ignored address %s claimed by %s - not in our universe\n", c.addr, c.ident)
c.resultChan <- nil
c.sendResult(nil)
return true
}
@@ -34,6 +41,7 @@ func (c *claim) Try(alloc *Allocator) bool {
owner := alloc.ring.Owner(c.addr)
if owner == router.UnknownPeerName {
alloc.infof("Ring is empty; will try later.\n", c.addr, owner)
c.sendResult(nil) // don't make the caller wait
return false
}
if owner != alloc.ourName {
@@ -41,34 +49,34 @@ func (c *claim) Try(alloc *Allocator) bool {
if found {
name = " (" + name + ")"
}
c.resultChan <- fmt.Errorf("address %s is owned by other peer %s%s", c.addr.String(), owner, name)
c.sendResult(fmt.Errorf("address %s is owned by other peer %s%s", c.addr.String(), owner, name))
return true
}
// We are the owner, check we haven't given it to another container
existingIdent := alloc.findOwner(c.addr)
if existingIdent == c.ident {
// same identifier is claiming same address; that's OK
c.resultChan <- nil
c.sendResult(nil)
return true
}
if existingIdent == "" {
err := alloc.space.Claim(c.addr)
if err != nil {
c.resultChan <- err
c.sendResult(err)
return true
}
alloc.debugln("Claimed", c.addr, "for", c.ident)
alloc.addOwned(c.ident, c.addr)
c.resultChan <- nil
c.sendResult(nil)
return true
}
// Addr already owned by container on this machine
c.resultChan <- fmt.Errorf("address %s is already owned by %s", c.addr.String(), existingIdent)
c.sendResult(fmt.Errorf("address %s is already owned by %s", c.addr.String(), existingIdent))
return true
}
func (c *claim) Cancel() {
c.resultChan <- fmt.Errorf("Operation cancelled.")
c.sendResult(fmt.Errorf("Operation cancelled."))
}
func (c *claim) String() string {
+1 -2
View File
@@ -19,14 +19,13 @@ func badRequest(w http.ResponseWriter, err error) {
// HandleHTTP wires up ipams HTTP endpoints to the provided mux.
func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CIDR, dockerCli *docker.Client) {
router.Methods("PUT").Path("/ip/{id}/{ip}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
closedChan := w.(http.CloseNotifier).CloseNotify()
vars := mux.Vars(r)
ident := vars["id"]
ipStr := vars["ip"]
if ip, err := address.ParseIP(ipStr); err != nil {
badRequest(w, err)
return
} else if err := alloc.Claim(ident, ip, closedChan); err != nil {
} else if err := alloc.Claim(ident, ip); err != nil {
badRequest(w, fmt.Errorf("Unable to claim: %s", err))
return
}
+1
View File
@@ -2,6 +2,7 @@ package paxos
import (
"fmt"
"github.com/weaveworks/weave/router"
)
+2 -1
View File
@@ -2,10 +2,11 @@ package paxos
import (
"fmt"
"github.com/weaveworks/weave/router"
"math/rand"
"testing"
"time"
"github.com/weaveworks/weave/router"
)
type TestNode struct {
+28 -19
View File
@@ -348,9 +348,9 @@ func (r *Ring) String() string {
return buffer.String()
}
// ReportFree is used by the allocator to tell the ring
// how many free ips are in a given range, so that ChoosePeerToAskForSpace
// can make more intelligent decisions.
// ReportFree is used by the allocator to tell the ring how many free
// ips are in a given range, so that ChoosePeersToAskForSpace can make
// more intelligent decisions.
func (r *Ring) ReportFree(freespace map[address.Address]address.Offset) {
r.assertInvariants()
defer r.assertInvariants()
@@ -392,9 +392,20 @@ func (r *Ring) ReportFree(freespace map[address.Address]address.Offset) {
}
}
// ChoosePeerToAskForSpace chooses a weighted-random peer to ask
// for space in the range [start, end). Assumes start<end.
func (r *Ring) ChoosePeerToAskForSpace(start, end address.Address) (result router.PeerName, err error) {
type weightedPeer struct {
weight float64
peername router.PeerName
}
type weightedPeers []weightedPeer
// Note Less is using > so that bigger weights sort earlier
func (ws weightedPeers) Less(i, j int) bool { return ws[i].weight > ws[j].weight }
func (ws weightedPeers) Len() int { return len(ws) }
func (ws weightedPeers) Swap(i, j int) { ws[i], ws[j] = ws[j], ws[i] }
// ChoosePeersToAskForSpace returns all peers we can ask for space in
// the range [start, end), in weighted-random order. Assumes start<end.
func (r *Ring) ChoosePeersToAskForSpace(start, end address.Address) []router.PeerName {
var (
sum address.Offset
totalSpacePerPeer = make(map[router.PeerName]address.Offset) // Compute total free space per peer
@@ -423,21 +434,19 @@ func (r *Ring) ChoosePeerToAskForSpace(start, end address.Address) (result route
sum += entry.Free
}
if sum == 0 {
err = ErrNoFreeSpace
return
}
// Pick random peer, weighted by total free space
rn := rand.Int63n(int64(sum))
// Compute weighted random numbers, then sort.
// This isn't perfect, e.g. an item with weight 2 will get chosen more than
// twice as often as an item with weight 1, but it's good enough for our purposes.
ws := make(weightedPeers, 0, len(totalSpacePerPeer))
for peername, space := range totalSpacePerPeer {
rn -= int64(space)
if rn < 0 {
return peername, nil
}
ws = append(ws, weightedPeer{weight: float64(space) * rand.Float64(), peername: peername})
}
panic("Should never reach this point")
sort.Sort(ws)
result := make([]router.PeerName, len(ws))
for i, wp := range ws {
result[i] = wp.peername
}
return result
}
func (r *Ring) PickPeerForTransfer() router.PeerName {
+20 -17
View File
@@ -345,39 +345,42 @@ func TestGossip(t *testing.T) {
func TestFindFree(t *testing.T) {
ring1 := New(start, end, peer1name)
_, err := ring1.ChoosePeerToAskForSpace(start, end)
wt.AssertTrue(t, err == ErrNoFreeSpace, "Expected ErrNoFreeSpace")
peers := ring1.ChoosePeersToAskForSpace(start, end)
wt.AssertTrue(t, len(peers) == 0, "Expected no peers")
ring1.Entries = []*entry{{Token: start, Peer: peer1name}}
_, err = ring1.ChoosePeerToAskForSpace(start, end)
wt.AssertTrue(t, err == ErrNoFreeSpace, "Expected ErrNoFreeSpace")
peers = ring1.ChoosePeersToAskForSpace(start, end)
wt.AssertTrue(t, len(peers) == 0, "Expected no peers")
// We shouldn't return outselves
ring1.ReportFree(map[address.Address]address.Offset{start: 10})
_, err = ring1.ChoosePeerToAskForSpace(start, end)
wt.AssertTrue(t, err == ErrNoFreeSpace, "Expected ErrNoFreeSpace")
peers = ring1.ChoosePeersToAskForSpace(start, end)
wt.AssertTrue(t, len(peers) == 0, "Expected no peers")
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 1},
{Token: middle, Peer: peer1name, Free: 1}}
_, err = ring1.ChoosePeerToAskForSpace(start, end)
wt.AssertTrue(t, err == ErrNoFreeSpace, "Expected ErrNoFreeSpace")
peers = ring1.ChoosePeersToAskForSpace(start, end)
wt.AssertTrue(t, len(peers) == 0, "Expected no peers")
ring1.assertInvariants()
// We should return others
ring1.Entries = []*entry{{Token: start, Peer: peer2name, Free: 1}}
peer, err := ring1.ChoosePeerToAskForSpace(start, end)
wt.AssertSuccess(t, err)
wt.AssertEquals(t, peer, peer2name)
peers = ring1.ChoosePeersToAskForSpace(start, end)
wt.AssertTrue(t, len(peers) == 1, "Expected one peer")
wt.AssertEquals(t, peers[0], peer2name)
ring1.Entries = []*entry{{Token: start, Peer: peer2name, Free: 1},
{Token: middle, Peer: peer3name, Free: 1}}
peer, err = ring1.ChoosePeerToAskForSpace(start, middle)
wt.AssertSuccess(t, err)
wt.AssertEquals(t, peer, peer2name)
peers = ring1.ChoosePeersToAskForSpace(start, middle)
wt.AssertTrue(t, len(peers) == 1, "Expected one peer")
wt.AssertEquals(t, peers[0], peer2name)
peer, err = ring1.ChoosePeerToAskForSpace(middle, end)
wt.AssertSuccess(t, err)
wt.AssertEquals(t, peer, peer3name)
peers = ring1.ChoosePeersToAskForSpace(middle, end)
wt.AssertTrue(t, len(peers) == 1, "Expected one peer")
wt.AssertEquals(t, peers[0], peer3name)
peers = ring1.ChoosePeersToAskForSpace(start, end)
wt.AssertTrue(t, len(peers) == 2, "Expected two peers")
ring1.assertInvariants()
}
+58 -36
View File
@@ -200,33 +200,47 @@ func AssertNothingSentErr(t *testing.T, ch <-chan error) {
}
// Router to convey gossip from one gossiper to another, for testing
type gossipMessage struct {
isUnicast bool
sender *router.PeerName
buf []byte // for unicast
data router.GossipData // for broadcast
exitChan chan bool
type unicastMessage struct {
sender router.PeerName
buf []byte
}
type broadcastMessage struct {
data router.GossipData
}
type exitMessage struct {
exitChan chan struct{}
}
type flushMessage struct {
flushChan chan struct{}
}
type TestGossipRouter struct {
gossipChans map[router.PeerName]chan gossipMessage
gossipChans map[router.PeerName]chan interface{}
loss float32 // 0.0 means no loss
}
func (grouter *TestGossipRouter) GossipBroadcast(update router.GossipData) error {
for _, gossipChan := range grouter.gossipChans {
select {
case gossipChan <- gossipMessage{data: update}:
case gossipChan <- broadcastMessage{data: update}:
default: // drop the message if we cannot send it
}
}
return nil
}
func (grouter *TestGossipRouter) flush() {
for _, gossipChan := range grouter.gossipChans {
flushChan := make(chan struct{})
gossipChan <- flushMessage{flushChan: flushChan}
<-flushChan
}
}
func (grouter *TestGossipRouter) removePeer(peer router.PeerName) {
gossipChan := grouter.gossipChans[peer]
resultChan := make(chan bool)
gossipChan <- gossipMessage{exitChan: resultChan}
resultChan := make(chan struct{})
gossipChan <- exitMessage{exitChan: resultChan}
<-resultChan
delete(grouter.gossipChans, peer)
}
@@ -236,39 +250,47 @@ type TestGossipRouterClient struct {
sender router.PeerName
}
func (grouter *TestGossipRouter) connect(sender router.PeerName, gossiper router.Gossiper) router.Gossip {
gossipChan := make(chan gossipMessage, 100)
func (grouter *TestGossipRouter) run(gossiper router.Gossiper, gossipChan chan interface{}) {
gossipTimer := time.Tick(10 * time.Second)
for {
select {
case gossip := <-gossipChan:
switch message := gossip.(type) {
case exitMessage:
close(message.exitChan)
return
go func() {
gossipTimer := time.Tick(10 * time.Second)
for {
select {
case message := <-gossipChan:
if message.exitChan != nil {
message.exitChan <- true
return
}
case flushMessage:
close(message.flushChan)
case unicastMessage:
if rand.Float32() > (1.0 - grouter.loss) {
continue
}
if err := gossiper.OnGossipUnicast(message.sender, message.buf); err != nil {
panic(fmt.Sprintf("Error doing gossip unicast to %s: %s", message.sender, err))
}
if message.isUnicast {
if err := gossiper.OnGossipUnicast(*message.sender, message.buf); err != nil {
panic(fmt.Sprintf("Error doing gossip unicast to %s: %s", sender, err))
}
} else {
for _, msg := range message.data.Encode() {
if _, err := gossiper.OnGossipBroadcast(msg); err != nil {
panic(fmt.Sprintf("Error doing gossip broadcast to %s: %s", sender, err))
}
case broadcastMessage:
if rand.Float32() > (1.0 - grouter.loss) {
continue
}
for _, msg := range message.data.Encode() {
if _, err := gossiper.OnGossipBroadcast(msg); err != nil {
panic(fmt.Sprintf("Error doing gossip broadcast: %s", err))
}
}
case <-gossipTimer:
grouter.GossipBroadcast(gossiper.Gossip())
}
case <-gossipTimer:
grouter.GossipBroadcast(gossiper.Gossip())
}
}()
}
}
func (grouter *TestGossipRouter) connect(sender router.PeerName, gossiper router.Gossiper) router.Gossip {
gossipChan := make(chan interface{}, 100)
go grouter.run(gossiper, gossipChan)
grouter.gossipChans[sender] = gossipChan
return TestGossipRouterClient{grouter, sender}
@@ -276,7 +298,7 @@ func (grouter *TestGossipRouter) connect(sender router.PeerName, gossiper router
func (client TestGossipRouterClient) GossipUnicast(dstPeerName router.PeerName, buf []byte) error {
select {
case client.router.gossipChans[dstPeerName] <- gossipMessage{isUnicast: true, sender: &client.sender, buf: buf}:
case client.router.gossipChans[dstPeerName] <- unicastMessage{sender: client.sender, buf: buf}:
default: // drop the message if we cannot send it
common.Error.Printf("Dropping message")
}
@@ -289,7 +311,7 @@ func (client TestGossipRouterClient) GossipBroadcast(update router.GossipData) e
func makeNetworkOfAllocators(size int, cidr string) ([]*Allocator, TestGossipRouter, address.Range) {
gossipRouter := TestGossipRouter{make(map[router.PeerName]chan gossipMessage), 0.0}
gossipRouter := TestGossipRouter{make(map[router.PeerName]chan interface{}), 0.0}
allocs := make([]*Allocator, size)
var subnet address.Range
@@ -303,7 +325,7 @@ func makeNetworkOfAllocators(size int, cidr string) ([]*Allocator, TestGossipRou
}
gossipRouter.GossipBroadcast(allocs[size-1].Gossip())
time.Sleep(1000 * time.Millisecond)
gossipRouter.flush()
return allocs, gossipRouter, subnet
}
+3
View File
@@ -395,6 +395,9 @@ func (s *DNSServer) notUsHandler(proto dnsProtocol) dns.HandlerFunc {
}
Debug.Printf("[dns msgid %d] Given answer by %s for query %s",
r.MsgHdr.Id, server, q.Name)
if reply.Len() > maxLen {
reply.Compress = true
}
w.WriteMsg(reply)
return
}
+20 -5
View File
@@ -3,12 +3,14 @@ package nameserver
import (
"encoding/binary"
"fmt"
"math/rand"
"net"
"testing"
"time"
"github.com/miekg/dns"
. "github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/ipam/address"
wt "github.com/weaveworks/weave/testing"
)
@@ -32,11 +34,12 @@ func TestUDPDNSServer(t *testing.T) {
setupForTest(t)
const (
successTestName = "test1.weave.local."
failTestName = "fail.weave.local."
nonLocalName = "weave.works."
testAddr1 = "10.2.2.1"
containerID = "somecontainer"
successTestName = "test1.weave.local."
failTestName = "fail.weave.local."
compressedTestName = "compressed.weave.works."
nonLocalName = "weave.works."
testAddr1 = "10.2.2.1"
containerID = "somecontainer"
)
testCIDR1 := testAddr1 + "/24"
@@ -72,6 +75,15 @@ func TestUDPDNSServer(t *testing.T) {
m.Answer[0] = &dns.PTR{Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: 0}, Ptr: "ns1.google.com."}
} else if q.Name == testRDNSfail && q.Qtype == dns.TypePTR {
m.Rcode = dns.RcodeNameError
} else if q.Name == compressedTestName {
// Construct a response that is >512 when uncompressed, <512 when compressed
header := makeHeader(m, &q, 300)
for m.Len() <= minUDPSize {
ip := address.Address(rand.Uint32()).IP4()
m.Answer = append(m.Answer, &dns.A{Hdr: *header, A: ip})
}
m.Compress = true
wt.AssertTrue(t, m.Len() <= minUDPSize, fmt.Sprintf("length: %d", m.Len()))
}
w.WriteMsg(m)
}
@@ -125,6 +137,9 @@ func TestUDPDNSServer(t *testing.T) {
assertExchange(t, testRDNSnonlocal, dns.TypePTR, testPort, 1, -1, 0)
_, r = assertExchange(t, compressedTestName, dns.TypeA, testPort, -1, -1, 0)
wt.AssertTrue(t, r.Len() > minUDPSize, "unexpected message length")
// Not testing MDNS functionality of server here (yet), since it
// needs two servers, each listening on its own address
}
+5 -3
View File
@@ -103,9 +103,11 @@ func (zone *ZoneDb) domainLookup(target string, lfun ZoneLookupFunc) (res []Zone
for _, answer := range lanswers {
r, err := remoteIdent.addIPToName(answer, now)
if err != nil {
zone.mx.Unlock()
Warning.Printf("[zonedb] '%s' insertion for %s failed: %s", answer, target, err)
return nil, err
if _, ok := err.(DuplicateError); !ok {
zone.mx.Unlock()
Warning.Printf("[zonedb] '%s' insertion for %s failed: %s", answer, target, err)
return nil, err
}
}
uniq.add(r)
}
+8 -1
View File
@@ -2,6 +2,7 @@ package net
import (
"fmt"
"math"
"net"
"time"
)
@@ -10,11 +11,17 @@ const (
sleepTime = 100 * time.Millisecond
)
// Wait `wait` seconds for an interface to come up. Pass zero to check once
// and return immediately, or a negative value to wait indefinitely.
func EnsureInterface(ifaceName string, wait int) (iface *net.Interface, err error) {
if iface, err = findInterface(ifaceName); err == nil || wait == 0 {
return
}
for i := time.Duration(wait) * time.Second / sleepTime; err != nil && i > 0; i-- {
i := int64(math.MaxInt64)
if wait > 0 {
i = int64(time.Duration(wait) * time.Second / sleepTime)
}
for ; err != nil && i > 0; i-- {
time.Sleep(sleepTime)
iface, err = findInterface(ifaceName)
}
+1 -1
View File
@@ -3,4 +3,4 @@ MAINTAINER Weaveworks Inc <help@weave.works>
WORKDIR /home/weave
ADD ./weavedns /home/weave/
EXPOSE 53/udp
ENTRYPOINT ["/home/weave/weavedns", "-wait", "20"]
ENTRYPOINT ["/home/weave/weavedns"]
+1 -1
View File
@@ -46,7 +46,7 @@ func main() {
flag.StringVar(&ifaceName, "iface", "", "name of interface to use for multicast")
flag.StringVar(&apiPath, "api", "unix:///var/run/docker.sock", "path to Docker API socket")
flag.StringVar(&domain, "domain", weavedns.DefaultLocalDomain, "local domain (ie, 'weave.local.')")
flag.IntVar(&wait, "wait", 0, "number of seconds to wait for interface to be created and come up")
flag.IntVar(&wait, "wait", -1, "number of seconds to wait for interfaces to come up (0=don't wait, -1=wait forever)")
flag.IntVar(&dnsPort, "dnsport", weavedns.DefaultServerPort, "port to listen to DNS requests")
flag.StringVar(&httpIfaceName, "httpiface", "", "interface on which to listen for HTTP requests (defaults to empty string which listens on all interfaces)")
flag.IntVar(&httpPort, "httpport", weavedns.DefaultHTTPPort, "port to listen to HTTP requests")
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"os"
"strings"
"code.google.com/p/getopt"
"github.com/pborman/getopt"
. "github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/proxy"
)
+1 -1
View File
@@ -2,4 +2,4 @@ FROM scratch
MAINTAINER Weaveworks Inc <help@weave.works>
WORKDIR /home/weave
ADD ./weaver /home/weave/
ENTRYPOINT ["/home/weave/weaver", "-wait", "20"]
ENTRYPOINT ["/home/weave/weaver"]
+2 -2
View File
@@ -11,8 +11,8 @@ import (
"runtime"
"strings"
"code.google.com/p/gopacket/layers"
"github.com/davecheney/profile"
"github.com/google/gopacket/layers"
"github.com/gorilla/mux"
. "github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/common/docker"
@@ -64,7 +64,7 @@ func main() {
flag.StringVar(&routerName, "name", "", "name of router (defaults to MAC of interface)")
flag.StringVar(&nickName, "nickname", "", "nickname of peer (defaults to hostname)")
flag.StringVar(&password, "password", "", "network password")
flag.IntVar(&wait, "wait", 0, "number of seconds to wait for interface to be created and come up (0 = don't wait)")
flag.IntVar(&wait, "wait", -1, "number of seconds to wait for interface to come up (0=don't wait, -1=wait forever)")
flag.BoolVar(&debug, "debug", false, "enable debug logging")
flag.BoolVar(&pktdebug, "pktdebug", false, "enable per-packet debug logging")
flag.StringVar(&prof, "profile", "", "enable profiling and write profiles to given path")
+14 -18
View File
@@ -6,33 +6,29 @@ import (
"os/exec"
"os/signal"
"syscall"
"time"
"github.com/weaveworks/weave/net"
weavenet "github.com/weaveworks/weave/net"
"github.com/weaveworks/weave/proxy"
)
func main() {
if len(os.Args) <= 1 {
os.Exit(0)
}
args := os.Args[1:]
signalWait := 20
if args[0] == "-s" {
signalWait = 0
args = args[1:]
}
interfaceWait := 20 - signalWait
usr2 := make(chan os.Signal)
signal.Notify(usr2, syscall.SIGUSR2)
select {
case <-usr2:
case <-time.After(time.Duration(signalWait) * time.Second):
if len(args) > 0 && args[0] == "-s" {
args = args[1:]
} else {
usr2 := make(chan os.Signal)
signal.Notify(usr2, syscall.SIGUSR2)
<-usr2
}
_, err := net.EnsureInterface("ethwe", interfaceWait)
_, err := weavenet.EnsureInterface("ethwe", -1)
checkErr(err)
if len(args) == 0 {
checkErr(proxy.ErrNoCommandSpecified)
}
binary, err := exec.LookPath(args[0])
checkErr(err)
+8 -1
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"regexp"
@@ -22,7 +23,13 @@ func callWeave(args ...string) ([]byte, error) {
args = append([]string{"--local"}, args...)
Debug.Print("Calling weave", args)
cmd := exec.Command("./weave", args...)
cmd.Env = []string{"PROCFS=/hostproc", "PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}
cmd.Env = []string{
"PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"PROCFS=/hostproc",
}
if bridge := os.Getenv("DOCKER_BRIDGE"); bridge != "" {
cmd.Env = append(cmd.Env, fmt.Sprintf("DOCKER_BRIDGE=%s", bridge))
}
out, err := cmd.CombinedOutput()
return out, err
}
+52 -6
View File
@@ -3,6 +3,7 @@ package proxy
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
@@ -13,6 +14,12 @@ import (
"github.com/weaveworks/weave/nameserver"
)
const MaxDockerHostname = 64
var (
ErrNoCommandSpecified = errors.New("No command specified")
)
type createContainerInterceptor struct{ proxy *Proxy }
type createContainerRequestBody struct {
@@ -21,6 +28,17 @@ type createContainerRequestBody struct {
MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty"`
}
// ErrNoSuchImage replaces docker.NoSuchImage, which does not contain the image
// name, which in turn breaks docker clients post 1.7.0 since they expect the
// image name to be present in errors.
type ErrNoSuchImage struct {
Name string
}
func (err *ErrNoSuchImage) Error() string {
return "No such image: " + err.Name
}
func (i *createContainerInterceptor) InterceptRequest(r *http.Request) error {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
@@ -33,15 +51,17 @@ func (i *createContainerInterceptor) InterceptRequest(r *http.Request) error {
return err
}
if cidrs, ok := i.proxy.weaveCIDRsFromConfig(container.Config); ok {
if cidrs, err := i.proxy.weaveCIDRsFromConfig(container.Config, container.HostConfig); err != nil {
Info.Printf("Ignoring container due to %s", err)
} else {
Info.Printf("Creating container with WEAVE_CIDR \"%s\"", strings.Join(cidrs, " "))
if container.HostConfig == nil {
container.HostConfig = &docker.HostConfig{}
}
container.HostConfig.VolumesFrom = append(container.HostConfig.VolumesFrom, "weaveproxy")
if container.Config == nil {
container.Config = &docker.Config{}
}
i.addWeaveWaitVolume(container.HostConfig)
if err := i.setWeaveWaitEntrypoint(container.Config); err != nil {
return err
}
@@ -60,10 +80,24 @@ func (i *createContainerInterceptor) InterceptRequest(r *http.Request) error {
return nil
}
func (i *createContainerInterceptor) addWeaveWaitVolume(hostConfig *docker.HostConfig) {
var binds []string
for _, bind := range hostConfig.Binds {
s := strings.Split(bind, ":")
if len(s) >= 2 && s[1] == "/w" {
continue
}
binds = append(binds, bind)
}
hostConfig.Binds = append(binds, fmt.Sprintf("%s:/w:ro", i.proxy.weaveWaitVolume))
}
func (i *createContainerInterceptor) setWeaveWaitEntrypoint(container *docker.Config) error {
if len(container.Entrypoint) == 0 {
image, err := i.proxy.client.InspectImage(container.Image)
if err != nil {
if err == docker.ErrNoSuchImage {
return &ErrNoSuchImage{container.Image}
} else if err != nil {
return err
}
@@ -76,7 +110,14 @@ func (i *createContainerInterceptor) setWeaveWaitEntrypoint(container *docker.Co
}
}
container.Entrypoint = append(weaveWaitEntrypoint, container.Entrypoint...)
if len(container.Entrypoint) == 0 && len(container.Cmd) == 0 {
return ErrNoCommandSpecified
}
if len(container.Entrypoint) == 0 || container.Entrypoint[0] != weaveWaitEntrypoint[0] {
container.Entrypoint = append(weaveWaitEntrypoint, container.Entrypoint...)
}
return nil
}
@@ -94,9 +135,14 @@ func (i *createContainerInterceptor) setWeaveDNS(container *createContainerReque
name := r.URL.Query().Get("name")
if container.Hostname == "" && name != "" {
container.Hostname = name
// Strip trailing period because it's unusual to see it used on the end of a host name
container.Domainname = strings.TrimSuffix(dnsDomain, ".")
trimmedDNSDomain := strings.TrimSuffix(dnsDomain, ".")
if len(name)+1+len(trimmedDNSDomain) > MaxDockerHostname {
Warning.Printf("Container name [%s] too long to be used as hostname", name)
} else {
container.Hostname = name
container.Domainname = trimmedDNSDomain
}
}
if len(container.HostConfig.DNSSearch) == 0 {
+5 -1
View File
@@ -29,7 +29,11 @@ func (i *createExecInterceptor) InterceptRequest(r *http.Request) error {
return err
}
if cidrs, ok := i.proxy.weaveCIDRsFromConfig(container.Config); ok {
_, hasWeaveWait := container.Volumes["/w"]
cidrs, err := i.proxy.weaveCIDRsFromConfig(container.Config, container.HostConfig)
if err != nil {
Info.Printf("Ignoring container %s due to %s", container.ID, err)
} else if hasWeaveWait {
Info.Printf("Exec in container %s with WEAVE_CIDR \"%s\"", container.ID, strings.Join(cidrs, " "))
cmd := append(weaveWaitEntrypoint, "-s")
options.Cmd = append(cmd, options.Cmd...)
+50 -8
View File
@@ -2,6 +2,8 @@ package proxy
import (
"crypto/tls"
"errors"
"fmt"
"net"
"net/http"
"net/url"
@@ -22,14 +24,18 @@ var (
containerCreateRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/create$")
containerStartRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/[^/]*/(re)?start$")
execCreateRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/[^/]*/exec$")
ErrWeaveCIDRNone = errors.New("WEAVE_CIDR=none")
ErrNoDefaultIPAM = errors.New("--no-default-ipam option")
)
type Proxy struct {
Config
dial func() (net.Conn, error)
client *docker.Client
dockerBridgeIP string
dial func() (net.Conn, error)
client *docker.Client
dockerBridgeIP string
weaveWaitVolume string
}
type Config struct {
@@ -75,14 +81,41 @@ func NewProxy(c Config) (*Proxy, error) {
Error.Fatalf("Could not configure tls for proxy: %s", err)
}
p.client, err = docker.NewClient(p.DockerAddr)
// We pin the protocol version to 1.15 (which corresponds to Docker 1.3.x;
// the earliest version supported by weave) in order to insulate ourselves
// from breaking changes to the API, as happened in 1.20 (Docker 1.8.0) when
// the presentation of volumes changed in inspect.
p.client, err = docker.NewVersionedClient(p.DockerAddr, "1.15")
if err != nil {
return nil, err
}
if err = p.findWeaveWaitVolume(); err != nil {
return nil, err
}
return p, nil
}
func (proxy *Proxy) findWeaveWaitVolume() error {
container, err := proxy.client.InspectContainer("weaveproxy")
if err != nil {
return fmt.Errorf("Could not find the weavewait volume: %s", err)
}
if container.Volumes == nil {
return fmt.Errorf("Could not find the weavewait volume")
}
volume, ok := container.Volumes["/w"]
if !ok {
return fmt.Errorf("Could not find the weavewait volume")
}
proxy.weaveWaitVolume = volume
return nil
}
func (proxy *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Info.Printf("%s %s", r.Method, r.URL)
path := r.URL.Path
@@ -115,14 +148,23 @@ func (proxy *Proxy) ListenAndServe() error {
return (&http.Server{Handler: proxy}).Serve(listener)
}
func (proxy *Proxy) weaveCIDRsFromConfig(config *docker.Config) ([]string, bool) {
func (proxy *Proxy) weaveCIDRsFromConfig(config *docker.Config, hostConfig *docker.HostConfig) ([]string, error) {
if hostConfig != nil &&
hostConfig.NetworkMode != "" &&
hostConfig.NetworkMode != "default" &&
hostConfig.NetworkMode != "bridge" {
return nil, fmt.Errorf("--net option: %q", hostConfig.NetworkMode)
}
for _, e := range config.Env {
if strings.HasPrefix(e, "WEAVE_CIDR=") {
if e[11:] == "none" {
return nil, false
return nil, ErrWeaveCIDRNone
}
return strings.Fields(e[11:]), true
return strings.Fields(e[11:]), nil
}
}
return nil, !proxy.NoDefaultIPAM
if proxy.NoDefaultIPAM {
return nil, ErrNoDefaultIPAM
}
return nil, nil
}
+23 -18
View File
@@ -9,6 +9,7 @@ import (
"net"
"net/http"
"net/http/httputil"
"sync"
"github.com/fsouza/go-dockerclient"
. "github.com/weaveworks/weave/common"
@@ -16,11 +17,10 @@ import (
func (proxy *Proxy) Intercept(i interceptor, w http.ResponseWriter, r *http.Request) {
if err := i.InterceptRequest(r); err != nil {
_, isNoSuchContainer := err.(*docker.NoSuchContainer)
switch {
case isNoSuchContainer:
switch err.(type) {
case *docker.NoSuchContainer:
http.Error(w, err.Error(), http.StatusNotFound)
case err == docker.ErrNoSuchImage:
case *ErrNoSuchImage:
http.Error(w, err.Error(), http.StatusNotFound)
default:
http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -95,25 +95,30 @@ func doRawStream(w http.ResponseWriter, resp *http.Response, client *httputil.Cl
return
}
upDone := make(chan struct{})
downDone := make(chan struct{})
go copyStream(down, io.MultiReader(rem, up), upDone)
go copyStream(up, downBuf, downDone)
<-upDone
<-downDone
var wg sync.WaitGroup
wg.Add(2)
go copyStream(down, io.MultiReader(rem, up), &wg)
go copyStream(up, downBuf, &wg)
wg.Wait()
}
func copyStream(dst io.Writer, src io.Reader, done chan struct{}) {
defer close(done)
type closeWriter interface {
CloseWrite() error
}
func copyStream(dst io.WriteCloser, src io.Reader, wg *sync.WaitGroup) {
defer wg.Done()
if _, err := io.Copy(dst, src); err != nil {
Warning.Print(err)
}
if c, ok := dst.(interface {
CloseWrite() error
}); ok {
if err := c.CloseWrite(); err != nil {
Warning.Printf("Error closing connection: %s", err)
}
var err error
if c, ok := dst.(closeWriter); ok {
err = c.CloseWrite()
} else {
err = dst.Close()
}
if err != nil {
Warning.Printf("Error closing connection: %s", err)
}
}
+7 -3
View File
@@ -16,14 +16,18 @@ func (i *startContainerInterceptor) InterceptRequest(r *http.Request) error {
}
func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error {
if r.StatusCode < 200 || r.StatusCode >= 300 { // Docker didn't do the start
return nil
}
container, err := inspectContainerInPath(i.proxy.client, r.Request.URL.Path)
if err != nil {
return err
}
cidrs, ok := i.proxy.weaveCIDRsFromConfig(container.Config)
if !ok {
Debug.Print("No Weave CIDR, ignoring")
cidrs, err := i.proxy.weaveCIDRsFromConfig(container.Config, container.HostConfig)
if err != nil {
Info.Printf("Ignoring container %s due to %s", container.ID, err)
return nil
}
Info.Printf("Attaching container %s with WEAVE_CIDR \"%s\" to weave network", container.ID, strings.Join(cidrs, " "))
+1 -1
View File
@@ -231,7 +231,7 @@ func (conn *LocalConnection) ReceivedHeartbeat(remoteUDPAddr *net.UDPAddr, connU
if oldRemoteUDPAddr == nil {
return conn.sendFastHeartbeats()
} else if oldRemoteUDPAddr.String() != remoteUDPAddr.String() {
log.Println("Peer", conn.remote, "moved from", old, "to", remoteUDPAddr)
log.Println("Peer", conn.remote, "moved from", oldRemoteUDPAddr, "to", remoteUDPAddr)
}
return nil
})
+4 -3
View File
@@ -1,15 +1,16 @@
package router
import (
"code.google.com/p/go-bit/bit"
"code.google.com/p/go.crypto/nacl/box"
"code.google.com/p/go.crypto/nacl/secretbox"
"crypto/rand"
"crypto/sha256"
"encoding/binary"
"encoding/gob"
"fmt"
"sync"
"github.com/andybalholm/go-bit"
"golang.org/x/crypto/nacl/box"
"golang.org/x/crypto/nacl/secretbox"
)
func GenerateKeyPair() (publicKey, privateKey *[32]byte, err error) {
+3 -2
View File
@@ -2,10 +2,11 @@ package router
import (
"bytes"
"code.google.com/p/gopacket"
"code.google.com/p/gopacket/layers"
"log"
"net"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
type EthernetDecoder struct {
+3 -2
View File
@@ -1,10 +1,11 @@
package router
import (
"code.google.com/p/gopacket"
"code.google.com/p/gopacket/layers"
"syscall"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
type ForwardedFrame struct {
+11 -5
View File
@@ -3,6 +3,7 @@ package router
import (
"bytes"
"encoding/gob"
"fmt"
"log"
"sync"
)
@@ -58,7 +59,12 @@ func (c *GossipChannel) deliverUnicast(srcName PeerName, origPayload []byte, dec
return err
}
if c.ourself.Name != destName {
return c.relayUnicast(destName, origPayload)
if err := c.relayUnicast(destName, origPayload); err != nil {
// just log errors from relayUnicast; a problem between us and destination
// is not enough reason to break the connection from the source
c.log(err)
}
return nil
}
var payload []byte
if err := dec.Decode(&payload); err != nil {
@@ -160,15 +166,15 @@ func (c *GossipChannel) GossipBroadcast(update GossipData) error {
return c.relayBroadcast(c.ourself.Name, update)
}
func (c *GossipChannel) relayUnicast(dstPeerName PeerName, buf []byte) error {
func (c *GossipChannel) relayUnicast(dstPeerName PeerName, buf []byte) (err error) {
if relayPeerName, found := c.routes.UnicastAll(dstPeerName); !found {
c.log("unknown relay destination:", dstPeerName)
err = fmt.Errorf("unknown relay destination: %s", dstPeerName)
} else if conn, found := c.ourself.ConnectionTo(relayPeerName); !found {
c.log("unable to find connection to relay peer", relayPeerName)
err = fmt.Errorf("unable to find connection to relay peer %s", relayPeerName)
} else {
conn.(ProtocolSender).SendProtocolMsg(ProtocolMsg{ProtocolGossipUnicast, buf})
}
return nil
return err
}
func (c *GossipChannel) relayBroadcast(srcName PeerName, update GossipData) error {
+2 -1
View File
@@ -1,8 +1,9 @@
package router
import (
wt "github.com/weaveworks/weave/testing"
"testing"
wt "github.com/weaveworks/weave/testing"
)
func TestFieldValidator(t *testing.T) {
+2 -1
View File
@@ -6,8 +6,9 @@
package router
import (
wt "github.com/weaveworks/weave/testing"
"testing"
wt "github.com/weaveworks/weave/testing"
)
// Add to peers a connection from peers.ourself to p
+2 -1
View File
@@ -1,8 +1,9 @@
package router
import (
"code.google.com/p/gopacket/pcap"
"fmt"
"github.com/google/gopacket/pcap"
)
type PcapIO struct {
+2 -1
View File
@@ -2,9 +2,10 @@ package router
import (
"fmt"
wt "github.com/weaveworks/weave/testing"
"math/rand"
"testing"
wt "github.com/weaveworks/weave/testing"
)
// TODO we should also test:
+10 -7
View File
@@ -11,21 +11,22 @@ import (
"syscall"
"time"
"code.google.com/p/gopacket/layers"
"github.com/google/gopacket/layers"
. "github.com/weaveworks/weave/common"
)
const (
macMaxAge = 10 * time.Minute // [1]
tcpAcceptDelay = 1 * time.Millisecond // [2]
macMaxAge = 10 * time.Minute // [1]
acceptMaxTokens = 100 // [2]
acceptTokenDelay = 100 * time.Millisecond // [3]
)
// [1] should be greater than typical ARP cache expiries, i.e. > 3/2 *
// /proc/sys/net/ipv4_neigh/*/base_reachable_time_ms on Linux
// [2] time to wait between accepting tcp connections. This guards
// against brute-force attacks on the password when encryption is in
// use. It is also a basic DoS defence.
// [2] capacity of token bucket for rate limiting accepts
// [3] control rate at which new tokens are added to the bucket
type LogFrameFunc func(string, []byte, *layers.Ethernet)
@@ -50,6 +51,7 @@ type Router struct {
gossipChannels GossipChannels
TopologyGossip Gossip
UDPListener *net.UDPConn
acceptLimiter *TokenBucket
}
type PacketSource interface {
@@ -81,6 +83,7 @@ func NewRouter(config Config, name PeerName, nickName string) *Router {
router.Routes = NewRoutes(router.Ourself, router.Peers)
router.ConnectionMaker = NewConnectionMaker(router.Ourself, router.Peers, router.Port, router.PeerDiscovery)
router.TopologyGossip = router.NewGossip("topology", router)
router.acceptLimiter = NewTokenBucket(acceptMaxTokens, acceptTokenDelay)
return router
}
@@ -212,7 +215,7 @@ func (router *Router) listenTCP(localPort int) {
continue
}
router.acceptTCP(tcpConn)
time.Sleep(tcpAcceptDelay)
router.acceptLimiter.Wait()
}
}()
}
+42
View File
@@ -0,0 +1,42 @@
package router
import (
"time"
)
type TokenBucket struct {
capacity int64 // Maximum capacity of bucket
tokenInterval time.Duration // Token replenishment rate
refillDuration time.Duration // Time to refill from empty
earliestUnspentToken time.Time
}
func NewTokenBucket(capacity int64, tokenInterval time.Duration) *TokenBucket {
tb := TokenBucket{
capacity: capacity,
tokenInterval: tokenInterval,
refillDuration: tokenInterval * time.Duration(capacity)}
tb.earliestUnspentToken = tb.capacityToken()
return &tb
}
func (tb *TokenBucket) Wait() {
// If earliest unspent token is in the future, sleep until then
time.Sleep(tb.earliestUnspentToken.Sub(time.Now()))
// Alternatively, enforce bucket capacity if necessary
capacityToken := tb.capacityToken()
if tb.earliestUnspentToken.Before(capacityToken) {
tb.earliestUnspentToken = capacityToken
}
// 'Remove' a token from the bucket
tb.earliestUnspentToken = tb.earliestUnspentToken.Add(tb.tokenInterval)
}
// Determine the historic token timestamp representing a full bucket
func (tb *TokenBucket) capacityToken() time.Time {
return time.Now().Add(-tb.refillDuration).Truncate(tb.tokenInterval)
}
+3 -2
View File
@@ -1,11 +1,12 @@
package router
import (
"code.google.com/p/gopacket"
"code.google.com/p/gopacket/layers"
"log"
"net"
"syscall"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
type UDPSender interface {
+19 -8
View File
@@ -2,38 +2,49 @@
<div class="section footer">
<div class="container">
<div class="row clearfix">
<div class="col-md-3 col-md-offset-2 column">
<div class="col-sm-3 col-md-2">
<b>Company</b><br>
<a href="http://weave.works/about.html">About Weave</a><br>
<!-- <a href="#">Meet the Team</a><br> -->
<a href="http://weave.works/team.html">Meet the Team</a><br>
<!-- <a href="#">Careers</a><br> -->
<a href="http://blog.weave.works">Blog</a><br>
<br>
<a href="http://weave.works/articles/">Learn More</a><br>
</div>
<div class="col-sm-3 col-md-2">
<b>Community</b><br>
<a href="http://weave.works/help/index.html#partners">Partners</a><br>
<a href="http://github.com/weaveworks">Code</a><br>
</div>
<div class="col-md-3 column">
<div class="col-sm-3 col-md-2">
<b>Documentation</b><br>
<a href="http://docs.weave.works">Docs</a><br>
<a href="http://weave.works/guides/">Getting Started Guides</a><br>
<a href="http://weave.works/help/index.html">Help and Support</a><br>
<a href="http://blog.weave.works">Blog</a><br>
</div>
<div class="col-md-3 column">
<div class="col-sm-3 col-md-2">
<b>Get in Touch</b><br>
<a href="mailto:help@weave.works">help@weave.works</a><br>
<div class="hidden-md hidden-lg">
<a href="mailto:help@weave.works">help@weave.works</a><br>
</div>
<a href="http://twitter.com/weaveworks">Twitter</a><br>
<a href="http://github.com/weaveworks">Github</a><br>
<a href="http://slideshare.net/weaveworks">Slideshare</a><br>
<a href="https://www.linkedin.com/company/weaveworks">Linkedin</a><br>
<a href="https://plus.google.com/+WeaveWorksInc/">GooglePlus</a><br>
</div>
<div class="col-md-3 hidden-xs hidden-sm">
<b>Talk to a human</b>
<div align="center">
<br>
<a href="mailto:help@weave.works" class="btn btn-lg">Drop us a line</a>
</div>
</div>
</div>
<div class="row clearfix weavefooter">
<div class="row">
<br>
<br>
<div class="col-md-4 col-md-offset-2">
<div class="col-sm-4">
<p class="copyright">&copy; Weaveworks 2014 &dash; 2015</p>
</div>
</div>
+8 -6
View File
@@ -1,9 +1,10 @@
<div class="section header navbaronly">
<nav class="navbar navbar-inverse">
<div class="section section-header navbaronly">
<div class="navbar navbar-inverse">
<div class="container">
<div><!-- class="navbar-header"> -->
<a class="navbar-brand" href="http://weave.works/"><img src="http://weave.works/img/weave-logo.png"></a>
</div>
<div class="navbar-header">
<a class="navbar-brand" href="http://weave.works/"><img src="http://weave.works/img/weave-logo.png"></a>
</div>
<div class="nav-wrapper">
<ul class="nav navbar-nav navbar-right">
<li>
<a href="http://docs.weave.works">Docs</a>
@@ -18,6 +19,7 @@
<a href="http://weave.works/help/index.html">Help &amp; Support</a>
</li>
</ul>
</div>
</div>
</nav>
</div>
</div>
+3 -3
View File
@@ -19,7 +19,7 @@
<!-- CSS
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
<link rel="stylesheet" type="text/css" href="http://weave.works/less/custom.css">
<link rel="stylesheet" type="text/css" href="assets/custom.css?v=1">
<!-- Favicon
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
@@ -33,8 +33,8 @@
<div class="content">
{% include header-navbaronly.html %}
<div class="container">
<div class="col-md-10 col-md-offset-1">
<div class="container markdown-page">
<div class="col-md-8 col-md-offset-2">
{{ content }}
</div>
</div>
File diff suppressed because it is too large. Load diff
+18 -12
View File
@@ -7,23 +7,29 @@ layout: default
If you are running Docker inside the Boot2Docker VM, e.g. because you
are on a Mac, then the following changes are required to the weave
instructions:
instructions. First, we need to get Boot2Docker running:
host1$ boot2docker init
host1$ boot2docker start
host1$ eval "$(boot2docker shellinit)"
Assuming you have fetched the 'weave' script via curl or similar, and
it is in the current directory, transfer it to the Boot2Docker VM and
make it executable like this:
it is in the current directory, launch weave on the Boot2Docker VM and
configure our shell. Because Boot2Docker uses TLS, we have to pass a
few extra options when launching the docker API proxy:
host1$ boot2docker ssh "cat > weave" < weave
host1$ boot2docker ssh "chmod a+x weave"
host1$ ./weave launch
host1$ ./weave launch-dns
host1$ ./weave launch-proxy --tls \
--tlscacert /var/lib/boot2docker/tls/ca.pem \
--tlscert /var/lib/boot2docker/tls/server.pem \
--tlskey /var/lib/boot2docker/tls/serverkey.pem
host1$ eval "$(./weave proxy-env)"
Then, if we were trying to create the same containers as in the first
example above, the 'launch' command would be run like this:
Now, we can use the docker command to run our containers, as shown in
the [proxy documentation](proxy.html):
host1$ boot2docker ssh "sudo ./weave launch"
and the 'run' command like this:
host1$ C=$(boot2docker ssh "sudo ./weave run 10.2.1.1/24 -t -i ubuntu")
host1$ docker run -it ubuntu
For more information about how to access services running in
Boot2Docker from the host or other machines (i.e. outside of the weave
+1 -1
View File
@@ -11,7 +11,7 @@ You only need to build weave if you want to work on the weave codebase
Apart from the `weave` shell script, weave is delivered as a set of
container images. There is no distribution-specific packaging, so in
principle it shouldn't matter which Linux distribution you build
under. But naturally, Docker is a prerequisite (version 1.3.0 or
under. But naturally, Docker is a prerequisite (version 1.3.1 or
later). And it is difficult to build under Fedora because [Fedora
does not include static
libraries](http://fedoraproject.org/wiki/Packaging:Guidelines#Packaging_Static_Libraries).
+88 -64
View File
@@ -9,7 +9,9 @@ Weave has a few more features beyond those illustrated by the [basic
example](https://github.com/weaveworks/weave#example):
* [Virtual ethernet switch](#virtual-ethernet-switch)
* [Manual addressing](#manual-addressing)
* [Seamless Docker integration](#docker)
* [Address allocation](#addressing)
* [Naming and discovery](#naming-and-discovery)
* [Application isolation](#application-isolation)
* [Dynamic network attachment](#dynamic-network-attachment)
* [Security](#security)
@@ -23,9 +25,6 @@ example](https://github.com/weaveworks/weave#example):
* [Dynamic topologies](#dynamic-topologies)
* [Container mobility](#container-mobility)
* [Fault tolerance](#fault-tolerance)
* [Automatic IP address management](#ipam)
* [Automatic discovery with WeaveDNS](#dns)
* [Working with the Docker CLI and API](#proxy)
### <a name="virtual-ethernet-switch"></a>Virtual Ethernet Switch
@@ -56,36 +55,57 @@ now re-use the same tools and techniques when deploying applications
as containers as we would have done when deploying them 'on metal' in
our data centre.
### <a name="manual-addressing"></a>Manual addressing
### <a name="docker"></a>Seamless Docker integration
The examples so far have leveraged weave's [address allocation](#ipam)
and [discovery](#dns) features, meaning that we've not had to concern
ourselves with IP addresses at all. It is, however, possible to
specify address and network explicitly using [CIDR
notation](http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation)
Weave includes a [Docker API proxy](proxy.html) so that containers
launched via the Docker
[command-line interface](https://docs.docker.com/reference/commandline/cli/)
or
[remote API](https://docs.docker.com/reference/api/docker_remote_api/)
are attached to the weave network before they begin execution.
### <a name="addressing"></a>Address allocation
Containers are automatically allocated an IP address that is unique
across the weave network. You can see which address was allocated with
[`weave ps`](troubleshooting.html#list-attached-containers):
host1$ weave ps a1
a7aee7233393 7a:44:d3:11:10:70 10.128.0.2/10
Weave detects when a container has exited and releases its
automatically allocated addresses so they can be re-used.
See the [Automatic IP Address Management](ipam.html) documentation for
further details.
Instead of getting weave to allocate IP addresses automatically, it is
also possible to specify an address and network explicitly, expressed
in
[CIDR notation](http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation)
- let's see how the first example would have looked:
On $HOST1:
host1$ C=$(weave run 10.2.1.1/24 -ti ubuntu)
host1$ docker run -e WEAVE_CIDR=10.2.1.1/24 -ti ubuntu
root@7ca0f6ecf59f:/#
And $HOST2:
host2$ C=$(weave run 10.2.1.2/24 -ti ubuntu)
host2$ docker run -e WEAVE_CIDR=10.2.1.2/24 -ti ubuntu
root@04c4831fafd3:/#
Then on $HOST1...
Then in the container on $HOST1...
host1$ docker attach $C
root@28841bd02eff:/# ping -c 1 -q 10.2.1.2
root@7ca0f6ecf59f:/# ping -c 1 -q 10.2.1.2
PING 10.2.1.2 (10.2.1.2): 48 data bytes
--- 10.2.1.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 1.048/1.048/1.048/0.000 ms
Similarly, on $HOST2...
Similarly, in the container on $HOST2...
host2$ docker attach $C
root@f76829496120:/# ping -c 1 -q 10.2.1.1
root@04c4831fafd3:/# ping -c 1 -q 10.2.1.1
PING 10.2.1.1 (10.2.1.1): 48 data bytes
--- 10.2.1.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
@@ -93,10 +113,24 @@ Similarly, on $HOST2...
The IP addresses and netmasks can be anything you like, but make sure
they don't conflict with any IP ranges in use on the hosts (including
those delegated to IPAM) or IP addresses of external services the
hosts or containers need to connect to. The same IP range must be used
everywhere, and the individual IP addresses must, of course, be
unique.
those delegated to weave's [automatic IP address allocator](ipam.html)) or
IP addresses of external services the hosts or containers need to
connect to. The same IP range must be used everywhere, and the
individual IP addresses must, of course, be unique.
### <a name="naming-and-discovery"></a>Naming and discovery
Named containers are automatically registered in
[weaveDNS](weavedns.html), which makes them discoverable through
simple name lookups:
host1$ docker run -dti --name=service ubuntu
host1$ docker run -ti ubuntu
root@7b21498fb103:/# ping service
This feature supports load balancing, fault resilience and hot
swapping; see the [weaveDNS](weavedns.html) documentation for more
details.
### <a name="application-isolation"></a>Application isolation
@@ -109,27 +143,27 @@ Let's begin by configuring weave's allocator to manage multiple
subnets:
host1$ weave launch -iprange 10.2.0.0/16 -ipsubnet 10.2.1.0/24
host1$ weave launch-dns
host1$ weave launch-dns && weave launch-proxy
host1$ eval $(weave proxy-env)
host2$ weave launch -iprange 10.2.0.0/16 -ipsubnet 10.2.1.0/24 $HOST1
host2$ weave launch-dns
host2$ weave launch-dns && weave launch-proxy
host2$ eval $(weave proxy-env)
This delegates the entire 10.2.0.0/16 subnet to weave, and instructs
it to allocate from 10.2.1.0/24 within that if no specific subnet is
specified. Now we can launch some containers in the default subnet:
host1$ weave run --name a1 -ti ubuntu
host2$ weave run --name a2 -ti ubuntu
host1$ docker run --name a1 -ti ubuntu
host2$ docker run --name a2 -ti ubuntu
And some more containers in a different subnet:
host1$ weave run net:10.2.2.0/24 --name b1 -ti ubuntu
host2$ weave run net:10.2.2.0.24 --name b2 -ti ubuntu
host1$ docker run -e WEAVE_CIDR=net:10.2.2.0/24 --name b1 -ti ubuntu
host2$ docker run -e WEAVE_CIDR=net:10.2.2.0.24 --name b2 -ti ubuntu
A quick 'ping' test in the containers confirms that they can talk to
each other but not the containers of our first application...
host1:~$ docker attach b1
root@b1:/# ping -c 1 -q b2
PING b2.weave.local (10.2.2.128) 56(84) bytes of data.
--- b2.weave.local ping statistics ---
@@ -153,7 +187,11 @@ well-known technique from the 'on metal' days to containers.
If desired, a container can be attached to multiple subnets when it is
started:
host1$ weave run net:default net:10.2.2.0/24 -ti ubuntu
host1$ docker run -e WEAVE_CIDR="net:default net:10.2.2.0/24" -ti ubuntu
`net:default` is used here to request allocation of an address from
the default subnet in addition to one from an explicitly specified
range.
NB: By default docker permits communication between containers on the
same host, via their docker-assigned IP addresses. For complete
@@ -166,17 +204,19 @@ be accomplished by starting them with the `--cap-drop net_raw` option.
### <a name="dynamic-network-attachment"></a>Dynamic network attachment
In some scenarios containers are started independently, e.g. via some
existing tool chain, or require more complex startup sequences than
provided by `weave run`. And sometimes the decision which application
network a container should be part of is made post-startup. For these
situations, weave allows an existing, running container to be attached
to the weave network. To illustrate, we can achieve the same effect as
the first example with
Sometimes the application network to which a container should be
attached is not known in advance. For these situations, weave allows
an existing, running container to be attached to the weave network. To
illustrate, we can achieve the same effect as the first example with
host1$ C=$(docker run -d -t -i ubuntu)
host1$ C=$(docker run -e WEAVE_CIDR=none -dti ubuntu)
host1$ weave attach $C
(Note that since we modified `DOCKER_HOST` to point to the proxy
earlier, we have to pass `-e WEAVE_CIDR=none` to start a container
that _doesn't_ get automatically attached to the weave network for the
purposes of this example.)
There is a matching `weave detach` command:
host1$ weave detach $C
@@ -205,16 +245,21 @@ In order to connect containers across untrusted networks, weave peers
can be told to encrypt traffic by supplying a `-password` option or
`WEAVE_PASSWORD` environment variable when launching weave, e.g.
host1$ weave launch -password wEaVe
host1$ weave launch -password wfvAwt7sj
or
host1$ export WEAVE_PASSWORD=wEaVe
host1$ export WEAVE_PASSWORD=wfvAwt7sj
host1$ weave launch
_NOTE: The command line option takes precedence over the environment
variable._
> To avoid leaking your password via the kernel process table or your
> shell history, we recommend you store it in a file and capture it
> into a shell variable prior to launching weave: `export
> WEAVE_PASSWORD=$(cat /path/to/password-file)`
The password needs to be reasonably strong to guard against online
dictionary attacks. We recommend at least 50 bits of entropy. An easy
way to generate a random password which satsifies this requirement is
@@ -333,7 +378,7 @@ service.
-j DNAT --to-destination $HOST3:2211
This allows any application container to reach the service by
connecting to 10.2.1.101:3322. So if `$HOST3` is indeed running a netcat
connecting to 10.2.1.3:3322. So if `$HOST3` is indeed running a netcat
service on port 2211, e.g.
host3$ nc -lk -p 2211
@@ -390,7 +435,7 @@ Now any host on the same network as `$HOST2` can access the service with
Furthermore, as explained in [service-binding](#service-binding), we
can dynamically alter the service locations without having to touch
the applications that access them, e.g. we could move the example
netcat service to `$HOST4:2211` while retaining its 10.2.1.101:3322
netcat service to `$HOST4:2211` while retaining its 10.2.1.3:3322
endpoint in the weave network.
### <a name="multi-cloud-networking"></a>Multi-cloud networking
@@ -478,24 +523,3 @@ stop`) and restart it. Application containers do *not* have to be
restarted in that event, and indeed may not even experience a
temporary connectivity failure if the weave container is restarted
quickly enough.
### <a name="ipam"></a>Automatic IP Address Management
Weave can automatically assign unique IP addresses to each container
across the network. The `run`, `start`, `attach`, `expose` and `hide`
commands will then fetch an address automatically if none is
specified. See the [IPAM](ipam.html) documentation for details on how
to enable and use this feature.
### <a name="dns"></a>Automatic discovery with WeaveDNS
WeaveDNS is a distributed DNS service for weave networks, enabling
containers to address each other by name rather than IP address. Find
out more about WeaveDNS from its [documentation](weavedns.html).
### <a name="proxy"></a>Working with the Docker CLI and API
Instead of the `weave` command-line utility, you may prefer to use the
standard Docker command-line interface, or the Docker remote API, for
starting weave-enabled containers. This can be accomplished with the
[Weave Proxy](proxy.html).
+37 -3
View File
@@ -29,8 +29,9 @@ encrypted, which carry encapsulated network packets. These
Weave creates a network bridge on the host. Each container is
connected to that bridge via a veth pair, the container side of which
is given the IP address & netmask supplied in 'weave run'. Also
connected to the bridge is the weave router container.
is given an IP address & netmask supplied either by the user or
Weave's IP address allocator. Also connected to the bridge is the
weave router container.
A weave router captures Ethernet packets from its bridge-connected
interface in promiscuous mode, using 'pcap'. This typically excludes
@@ -277,7 +278,7 @@ password, and the result is hashed through SHA256, to form the final
ephemeral session key. Thus the supplied password is never exchanged
directly, and is thoroughly mixed into the shared secret. Furthermore,
the rate at which TCP connections are accepted is limited by weave to
1kHz, which twarts online dictionary attacks on reasonably strong
10Hz, which twarts online dictionary attacks on reasonably strong
passwords.
The shared key formed by Diffie-Hellman is 256 bits long, appending
@@ -292,6 +293,39 @@ not be able to form valid ephemeral session keys.
The same ephemeral session key is used for both TCP and UDP traffic
between two peers.
<a name="csprng"></a> Generating fresh keys for every connection
provides forward secrecy at the cost of placing a demand on the Linux
CSPRNG (accessed by `GenerateKey` via `/dev/urandom`) proportional to
the number of inbound connection attempts. Weave has accept throttling
to mitigate against denial of service attacks that seek to deplete the
CSPRNG entropy pool, however even at the lower bound of ten requests
per second there may not be enough entropy gathered on a headless
system to keep pace.
Under such conditions, the consequences will be limited to slowing
down processes reading from the blocking `/dev/random` device as the
kernel waits for enough new entropy to be harvested. It is important
to note that contrary to intuition this low entropy state does not
compromise the ongoing use of `/dev/urandom` - [expert
opinion](http://blog.cr.yp.to/20140205-entropy.html)
asserts that as long as the CSPRNG is seeded with enough entropy (e.g.
256 bits) before random number generation commences then the output is
entirely safe for use as key material.
By way of comparison, this is exactly how OpenSSL works - it reads 256
bits of entropy at startup, and uses that to seed an internal CSPRNG
which is used thenceforth to generate keys. Whilst we could have taken
the same approach and built our own CSPRNG to work around the
potential `/dev/random` blocking issue, we thought it was much more
prudent to rely on the [heavily
scrutinised](http://eprint.iacr.org/2012/251.pdf) Linux random number
generator as [advised
here](http://cr.yp.to/highspeed/coolnacl-20120725.pdf) (page 10,
'Centralizing randomness'). The aforementioned notwithstanding, if
weave's demand on `/dev/urandom` is causing you problems with blocking
`/dev/random` reads, please get in touch with us - we'd love to hear
about your use case.
#### TCP
TCP connection are only used to exchange topology information between
-3
View File
@@ -8,9 +8,6 @@ layout: default
* [Introduction, Installation and Example](https://github.com/weaveworks/weave#readme)
* [Getting Started Guides](http://weave.works/guides/)
* [Features](features.html)
* [Automatic IP Address Management](ipam.html)
* [Automatic Discovery with WeaveDNS](weavedns.html)
* [Working with the Docker CLI and API](proxy.html)
* [Troubleshooting](troubleshooting.html)
* [Building](building.html)
* [How it works](how-it-works.html)
+27 -42
View File
@@ -5,10 +5,13 @@ layout: default
# Automatic IP Address Management
Weave can automatically assign containers an IP address that is unique
across the network.
Weave automatically assigns containers an IP address that is unique
across the network, and releases that address when a container
exits. This happens for all invocations of the `run`, `start`,
`attach`, `detach`, `expose`, `hide` and `launch-dns` commands, unless
the user explictly specified an address. Weave can also assign
addresses in multiple subnets.
* [Usage](#usage)
* [Initialisation](#initialisation)
* [Choosing an allocation range](#range)
* [Automatic allocation across multiple subnets](#subnets)
@@ -16,25 +19,6 @@ across the network.
* [Stopping and removing peers](#stop)
* [Troubleshooting](#troubleshooting)
## <a name="usage"></a>Usage
Containers are automatically allocated an IP address when none is
specified when the container is started, e.g.
host1# C=$(weave run -ti ubuntu)
You can see which address was allocated with
[`weave ps`](troubleshooting.html#list-attached-containers):
host1# weave ps $C
a7aff7249393 7a:51:d1:09:21:78 10.128.0.1/10
Weave detects when a container has exited and releases its
automatically allocated addresses so they can be re-used.
Automatic IP address assignment is available for the `run`, `start`,
`attach`, `detach`, `expose`, `hide` and `launch-dns` commands.
## <a name="initialisation"></a>Initialisation
Just once, when the first automatic IP address allocation is requested
@@ -106,10 +90,18 @@ would be safe wrt weave's startup quorum:
By default, weave will allocate IP addresses in the 10.128.0.0/10
range. This can be overridden with the `-iprange` option, e.g.
host1# weave launch -iprange 10.2.0.0/16
host1$ weave launch -iprange 10.2.0.0/16
and must be the same on every host.
> The specified range is for *exclusive* use by the IP allocator. In
> particular, when starting containers with manually assigned IP
> addresses, these must be outside the IP allocator's range. If, in
> our example, you subsequently executed `docker run -e
> WEAVE_CIDR=10.2.3.1/24 -ti ubuntu`, the IP allocator might assign
> the same address to another container, which will break IP routing
> for the containers sharing an address.
The range parameter is written in
[CIDR notation](http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) -
in this example "/16" means the first 16 bits of the address form the
@@ -124,14 +116,6 @@ the rest (a partition), they can continue to work with the address
ranges they had before isolation, and can subsequently be re-connected
to the rest of the network without any conflicts arising.
Once you have given a range of addresses to the IP allocator, you must
not use any addresses in that range for anything else. If, in our
example, you subsequently executed `weave run 10.2.3.1/24 -ti ubuntu`,
you run the risk that the IP allocator will assign the same address to
another container, which will make network traffic delivery
intermittent or non-existent for the containers that share the same IP
address.
## <a name="subnets"></a>Automatic allocation across multiple subnets
When
@@ -140,20 +124,20 @@ you may wish to request the allocation of an address from a particular
subnet. This is done by specifying the subnet with `net:<subnet>`, in
CIDR notation, e.g.
host1# C=$(weave run net:10.2.7.0/24 -ti ubuntu)
host1$ docker run -e WEAVE_CIDR=net:10.2.7.0/24 -ti ubuntu
You can ask for multiple addresses in different subnets and add in
manually-assigned addresses (outside the automatic allocation range),
for instance:
host1# C=$(weave run net:10.2.7.0/24 net:10.2.8.0/24 ip:10.3.9.1/24 -ti ubuntu)
host1$ docker run -e WEAVE_CIDR="net:10.2.7.0/24 net:10.2.8.0/24 ip:10.3.9.1/24" -ti ubuntu
When working with multiple subnets in this way, it is usually
desirable to constrain the default subnet - i.e. the one chosen by the
allocator when no subnet is supplied - so that it does not overlap
with others. One can specify that with `-ipsubnet`:
host1# weave launch -iprange 10.2.0.0/16 -ipsubnet 10.2.3.0/24
host1$ weave launch -iprange 10.2.0.0/16 -ipsubnet 10.2.3.0/24
`-iprange` should cover the entire range that you will ever use for
allocation, and `-ipsubnet` is the subnet that will be used when you
@@ -170,7 +154,7 @@ have the containers communicate with each other*, you can choose a
`-iprange` that is smaller than `-ipsubnet`, For example, if you
launch weave with:
host1# weave launch -iprange 10.9.0.0/17 -ipsubnet 10.9.0.0/16
host1$ weave launch -iprange 10.9.0.0/17 -ipsubnet 10.9.0.0/16
then you can run all containers in the 10.9.0.0/16 subnet, with
automatic allocation using the lower half, leaving the upper half free
@@ -213,22 +197,23 @@ The command
reports on the current status of the weave router and IP allocator:
````
weave router git-8f675f15c0b5
...
Allocator universe 10.2.0.0/16
Owned Ranges:
10.2.1.1 -> 96:e9:e2:2e:2d:bc (host1) (v3)
10.2.1.128 -> ea:84:25:9b:31:2e (host2) (v3)
10.2.1.192 -> ea:6c:21:09:cf:f0 (host3) (v9)
Allocator default subnet: 10.2.1.0/24
...
````
The first section covers the router; see the [troubleshooting
guide](troubleshooting.html#status-report) for full details.
The 'Allocator' section, which is only present if weave has been
started with the `-iprange` option, summarises the overall position and
lists which address ranges have been assigned to which peer. Each
range begins at the address shown and ends just before the next
address, or wraps around at the end of the subnet. The 'v' number
denotes how many times that entry has been updated.
The 'Allocator' section summarises the overall position and lists
which address ranges have been assigned to which peer. Each range
begins at the address shown and ends just before the next address, or
wraps around at the end of the subnet. The 'v' number denotes how many
times that entry has been updated.
+43 -68
View File
@@ -1,12 +1,12 @@
---
title: Weave Proxy
title: Weave Docker API Proxy
layout: default
---
# Weave Proxy
# Weave Docker API Proxy
The proxy automatically attaches containers to the weave network when
they are started using the ordinary Docker
The Docker API proxy automatically attaches containers to the weave
network when they are started using the ordinary Docker
[command-line interface](https://docs.docker.com/reference/commandline/cli/)
or
[remote API](https://docs.docker.com/reference/api/docker_remote_api/),
@@ -16,8 +16,8 @@ instead of `weave run`.
* [Usage](#usage)
* [Automatic IP address assignment](#ipam)
* [Automatic discovery](#dns)
* [Multi-host example](#multi-host)
* [Securing the docker communication with TLS](#tls)
* [Launching containers without the proxy](#without-proxy)
* [Troubleshooting](#troubleshooting)
## <a name="setup"></a>Setup
@@ -29,17 +29,14 @@ To start the proxy, run
host1$ weave launch-proxy
By default, the proxy will connect to docker at
`unix:///var/run/docker.sock`. This can be adjusted with the `-D`
argument, e.g.
host1$ weave launch-proxy -D tcp://127.0.0.1:4243
By default, the proxy listens on port 12375, on all network
interfaces. This can be adjusted with the `-H` argument, e.g.
host1$ weave launch-proxy -H tcp://127.0.0.1:9999
If you are working with a remote docker daemon, then any firewalls
inbetween need to be configured to permit access to the proxy port.
All docker commands can be run via the proxy, so it is safe to adjust
your `DOCKER_HOST` to point at the proxy. Weave provides a convenient
command for this:
@@ -52,11 +49,6 @@ Alternatively, the proxy host can be set on a per-command basis with
host1$ docker $(weave proxy-config) ps
If you are working with a remote docker daemon, then `localhost` in
the above needs to be replaced with the docker daemon host, and any
firewalls inbetween need to be configured to permit access to
the proxy port.
The proxy can be stopped with
host1$ weave stop-proxy
@@ -90,12 +82,6 @@ Multiple IP addresses and networks can be supplied in the `WEAVE_CIDR`
variable by space-separating them, as in
`WEAVE_CIDR="10.2.1.1/24 10.2.2.1/24"`.
Using the proxy brings some additional benefits over `weave run`. The
proxy ensures that the weave network interface is available before
starting a container's application process. Furthermore, containers
can be started in foreground mode, and can be automatically removed
(with the ususal `--rm`).
## <a name="ipam"></a>Automatic IP address assignment
If [automatic IP address assignment](ipam.html) is enabled in weave,
@@ -105,9 +91,9 @@ special environment variables or other options*.
host1$ docker run -ti ubuntu
To use a specific IP, we pass a `WEAVE_CIDR` to the container, e.g.
To use a specific subnet, we pass a `WEAVE_CIDR` to the container, e.g.
host1$ docker run -ti -e WEAVE_CIDR=10.2.1.1/24 ubuntu
host1$ docker run -ti -e WEAVE_CIDR=net:10.128.0.0/24 ubuntu
To start a container without connecting it to the weave network, pass
`WEAVE_CIDR=none`, e.g.
@@ -117,7 +103,7 @@ To start a container without connecting it to the weave network, pass
If you do not want IPAM to be used by default, the proxy needs to be
passed the `--no-default-ipam` flag, e.g.
host1$ docker launch-proxy --no-default-ipam
host1$ weave launch-proxy --no-default-ipam
In this configuration, containers with no `WEAVE_CIDR` environment
variable will not be connected to the weave network. Containers
@@ -129,48 +115,10 @@ container with a blank `WEAVE_CIDR`, e.g.
## <a name="dns"></a>Automatic discovery
Containers started via the proxy are automatically registered in
[weaveDNS](weavedns.html) if they have a hostname in the weaveDNS
domain (usually `.weave.local`). In order for containers to be able to
look up such names, their DNS resolver needs to be configured to point
at weaveDNS. This will be done automatically by the proxy while
weaveDNS is running. To override this behaviour launch the proxy with
either `--with-dns` or `--without-dns`, which will force the proxy to
always/never set the resolver to weaveDNS. If there is no hostname
provided, the container will be registered in weaveDNS using its
container name. Otherwise, if there is no container name, and no
hostname (or a hostname outside the weaveDNS domain), the container
will not be registered in weaveDNS.
## <a name="multi-host"></a>Multi-host example
Here's a complete example of using weave proxies configured with
[automatic IP address assignment](#ipam) and
[automatic discovery](#dns) to start containers on two hosts such that
one can reach the other by name.
First, let us start weave, weaveDNS and the proxy, and set DOCKER_HOST
to point at the latter:
host1$ weave launch
host1$ weave launch-dns
host1$ weave launch-proxy
host1$ eval "$(weave proxy-env)"
host2$ weave launch host1
host2$ weave launch-dns
host2$ weave launch-proxy
host2$ eval "$(weave proxy-env)"
Now let us start a named container on one host, and ping it, by name,
from a container on the other host.
host1$ docker run --name=pingme -dti ubuntu
host2$ docker run -ti ubuntu ping pingme
PING pingme.weave.local (10.128.0.2) 56(84) bytes of data.
64 bytes from pingme.weave.local (10.128.0.2): icmp_seq=1 ttl=64 time=0.047 ms
...
Containers launched via the proxy will use [weaveDNS](weavedns.html)
automatically if it is running at the point when they are started -
see the [weaveDNS usage](weavedns.html#usage) section for an in-depth
explanation of the behaviour and how to control it.
## <a name="tls"></a>Securing the docker communication with TLS
@@ -193,7 +141,7 @@ Because the proxy connects to the docker daemon at
listening there. To do this, you need to pass the `-H
unix:///var/run/docker.sock` option when starting the docker daemon,
in addition to the `-H` options for configuring the TCP listener. See
[the Docker documentation](https://docs.docker.com/articles/basics/#bind-docker-to-another-hostport-or-a-unix-socket)
[the Docker documentation](https://docs.docker.com/articles/basics/#bind-docker-to-another-host-port-or-a-unix-socket)
for an example.
With the proxy running over TLS, we can configure our regular docker
@@ -218,6 +166,33 @@ which is exactly the same configuration as when connecting to the
docker daemon directly, except that the specified port is the weave
proxy port.
## <a name="without-proxy"></a>Launching containers without the proxy
If you cannot or do not want to use the proxy you can launch
containers on the weave network with `weave run`:
$ weave run -ti ubuntu
The arguments after `run` are passed through to `docker run` so you
can freely specify whichever docker options are appropriate. Once the
container is started, `weave run` attaches it to the weave network, in
this example with an address allocated by IPAM. If you wish you can
specify addresses manually instead:
$ weave run 10.2.1.1/24 -ti ubuntu
There are some limitations to starting containers with `weave run`:
* containers are always started in the background, i.e. the equivalent
of always supplying the -d option to docker run
* the --rm option to docker run, for automatically removing containers
after they stop, is not available
* the weave network interface may not be available immediately on
container startup.
Finally, there is a `weave start` command which starts existing
containers with `docker start` and attaches them to the weave network.
## <a name="troubleshooting"></a>Troubleshooting
The command
+5 -3
View File
@@ -38,9 +38,11 @@ the following format:
You can also use the [connect][] command to add participating hosts dynamically.
Additionally, if you want to enable [encryption][] you can specify a password with
`WEAVE_PASSWORD="MakeSureThisIsSecure"` in the `/etc/sysconfig/weave` environment
file, and it will get picked up by weave on launch.
Additionally, if you want to enable [encryption][] you can specify a
password with e.g. `WEAVE_PASSWORD="wfvAwt7sj"` in the
`/etc/sysconfig/weave` environment file, and it will get picked up by
weave on launch. Recommendations for choosing a suitably strong
password can be found [here](features.html#security).
You now should be able to launch weave with
+1 -1
View File
@@ -142,7 +142,7 @@ is waiting for a while before connecting again.
There may also be further sections for the
[IP address allocator](ipam.html#troubleshooting),
[weaveDNS](weavedns.html#troubleshooting), and
[proxy](proxy.html#troubleshooting).
[Weave Docker API Proxy](proxy.html#troubleshooting).
### <a name="list-attached-containers"></a>List attached containers
+58 -126
View File
@@ -21,7 +21,6 @@ hosts.
* [Configuring a custom TTL](#ttl)
* [Configuring the domain search path](#domain-search-path)
* [Using a different local domain](#local-domain)
* [Using weaveDNS without `weave run`](#without-run)
* [Troubleshooting](#troubleshooting)
* [Present limitations](#limitations)
@@ -30,76 +29,54 @@ hosts.
WeaveDNS is deployed as a set of containers that communicate with each
other over the weave network. One such container needs to be started
on every weave host, by invoking the weave script command
`launch-dns`.
`launch-dns`:
```bash
$ weave launch
$ weave launch-dns 10.2.254.1/24
host1$ weave launch && weave launch-dns && weave launch-proxy
host1$ eval $(weave proxy-env)
```
Containers started while weaveDNS is running are automatically
registered in [weaveDNS](weavedns.html) if they have a hostname in the
weaveDNS domain (usually `.weave.local`). In order for containers to
be able to look up such names, their DNS resolver needs to be
configured to point at weaveDNS. This will be done automatically while
weaveDNS is running. If there is no hostname provided, the container
will be registered in weaveDNS using its container name. Otherwise, if
there is no container name, and no hostname (or a hostname outside the
weaveDNS domain), the container will not be registered in weaveDNS.
For example, to use the container name as the hostname:
Application containers will use weaveDNS automatically if it is
running at the point when they are started. They will use it for name
resolution, and will register themselves if they have either a
hostname in the weaveDNS domain (`weave.local` by default) or have
been given an explicit container name:
```bash
$ weave run 10.2.1.25/24 -ti --name=pingme ubuntu
$ shell1=$(weave run 10.2.1.26/24 -ti --name=ubuntu ubuntu)
$ docker attach $shell1
host1$ docker run -dti --name=pingme ubuntu
host1$ docker run -ti --hostname=ubuntu.weave.local ubuntu
root@ubuntu:/# ping pingme
...
```
If you start an application container sans `--with-dns` you can still register
it in weaveDNS simply by giving the container a hostname in the
`.weave.local.` domain:
```
$ weave run 10.2.1.25/24 -ti -h pingme.weave.local ubuntu
```
> **Please note** if both hostname and container name are specified at
> the same time the hostname takes precedence; in this circumstance if
> the hostname is not in the weaveDNS domain the container will *not* be
> registered, but will still use weaveDNS for resolution.
It is also possible to force or forbid an application container's use
of weaveDNS with the `--with-dns` and `--without-dns` options to
`weave run`; these override the runtime detection of the weaveDNS
container.
`weave run` and `weave launch-proxy`; these override the runtime
detection of the weaveDNS container.
Each weaveDNS container started with `launch-dns` needs to be given
its own, unique, IP address, in a subnet that is common to all
weaveDNS containers and not in use on any of the hosts.
Each weaveDNS container started with `launch-dns` needs its own unique
IP address in a subnet that is common to all weaveDNS containers. In
the example above we did not specify such an address, so one was
allocated automatically by IPAM from the default subnet; you can
however specify an address in CIDR format manually. In this case you
are responsible for ensuring that the IP addresses specified are
uniquely allocated and not in use by any other container.
In our example the weaveDNS address is in subnet 10.2.254.0/24 and the
application containers are in subnet 10.2.1.0/24. So, to launch and
use weaveDNS on a second host we would run:
```bash
host2$ weave launch $HOST1
host2$ weave launch-dns 10.2.254.2/24
host2$ shell2=$(weave run 10.2.1.36/24 -ti --name=ubuntu2 ubuntu)
host2$ docker attach $shell2
root@ubuntu2:/# ping pingme
...
```
Notice the different IP address in the 10.2.254.0/24 subnet we gave to
`weave launch-dns`, compared to what we supplied on the first host.
WeaveDNS containers can be stopped with `stop-dns`.
Finally, WeaveDNS containers can be stopped with `stop-dns`.
## <a name="how-it-works"></a>How it works
The weaveDNS container running on every host acts as the nameserver
for containers on that host. It is told about hostnames for local
containers by the `weave run` command. If a hostname is in the
`.weave.local` domain then weaveDNS records the association of that
name with the container's weave IP address(es).
for containers on that host. It learns about hostnames for local
containers from the Weave Docker API proxy and from the `weave run`
command. If a hostname is in the `.weave.local` domain then weaveDNS
records the association of that name with the container's weave IP
address(es).
When weaveDNS is queried for a name in the `.weave.local` domain, it
first checks its own records. If the name is not found there, it asks
@@ -116,7 +93,7 @@ different Docker bridge device. To supply a different bridge device,
use the environment variable `DOCKER_BRIDGE`, e.g.,
```bash
$ sudo DOCKER_BRIDGE=someother weave launch-dns 10.2.254.1/24
$ sudo DOCKER_BRIDGE=someother weave launch-dns
```
In the event that weaveDNS is launched in this way, it's important that
@@ -136,20 +113,21 @@ Returning to our earlier example, let us start an additional `pingme`
container, this time on the 2nd host, and then run some ping tests...
```bash
host2$ weave run 10.2.1.35/24 -ti --name=pingme ubuntu
host2$ docker attach $shell2
host2$ weave launch && weave launch-dns && weave launch-proxy
host2$ eval $(weave proxy-env)
host2$ docker run -dti --name=pingme ubuntu
root@ubuntu2:/# ping -nq -c 1 pingme
PING pingme.weave.local (10.2.1.35) 56(84) bytes of data.
root@ubuntu:/# ping -nq -c 1 pingme
PING pingme.weave.local (10.128.0.2) 56(84) bytes of data.
...
root@ubuntu2:/# ping -nq -c 1 pingme
PING pingme.weave.local (10.2.1.25) 56(84) bytes of data.
root@ubuntu:/# ping -nq -c 1 pingme
PING pingme.weave.local (10.160.0.1) 56(84) bytes of data.
...
root@ubuntu2:/# ping -nq -c 1 pingme
PING pingme.weave.local (10.2.1.25) 56(84) bytes of data.
root@ubuntu:/# ping -nq -c 1 pingme
PING pingme.weave.local (10.160.0.1) 56(84) bytes of data.
...
root@ubuntu2:/# ping -nq -c 1 pingme
PING pingme.weave.local (10.2.1.35) 56(84) bytes of data.
root@ubuntu:/# ping -nq -c 1 pingme
PING pingme.weave.local (10.128.0.2) 56(84) bytes of data.
...
```
@@ -170,8 +148,8 @@ If you want to give the container a name in DNS *other* than its
hostname, you can register it using the `dns-add` command. For example:
```bash
$ shell2=(weave run 10.2.1.27/24 -ti ubuntu)
$ weave dns-add 10.2.1.28 $shell2 -h pingme2.weave.local
$ C=$(docker run -e WEAVE_CIDR=10.2.1.27/24 -ti ubuntu)
$ weave dns-add 10.2.1.27 $C -h pingme2.weave.local
```
You can also use `dns-add` to add the container's configured hostname
@@ -180,7 +158,7 @@ and domain, simply by omitting `-h <fqdn>`.
The inverse operation can be carried out using the `dns-remove` command:
```bash
$ weave dns-remove 10.2.1.27 $shell2
$ weave dns-remove 10.2.1.27 $C
```
When queried about a name with multiple IPs, weaveDNS returns a random
@@ -202,7 +180,7 @@ containers that die. You can tell it not to, by adding `--watch=false`
to the container args:
```bash
$ weave launch-dns 10.2.254.1/24 --watch=false
$ weave launch-dns --watch=false
```
## <a name="ttl"></a>Configuring a custom TTL
@@ -215,7 +193,7 @@ However, you can force a different TTL value by launching weaveDNS with
the `--ttl` argument:
```bash
$ weave launch-dns 10.2.254.1/24 --ttl=10
$ weave launch-dns --ttl=10
```
This will shorten the lifespan of answers sent to other peers,
@@ -240,7 +218,7 @@ hostnames across all sub-domains plus some external domains, you need
behaviour.
```bash
weave run --with-dns 10.2.1.4/24 -ti \
docker run -ti \
--dns-search=zone1.weave.local --dns-search=zone2.weave.local \
--dns-search=corp1.com --dns-search=corp2.com \
--dns-search=weave.local ubuntu
@@ -254,60 +232,13 @@ can force weaveDNS to use a different domain by launching it
with the `--domain` argument. For example,
```bash
$ weave launch-dns 10.2.254.1/24 --domain="mycompany.local."
$ weave launch-dns --domain="mycompany.local."
```
The local domain should end with `local.`, since these names are
link-local as per [RFC6762](https://tools.ietf.org/html/rfc6762),
(though this is not strictly necessary).
## <a name="without-run"></a>Using weaveDNS without `weave run`
When weaveDNS is running, both `weave run` and `weave attach` register
the hostname of the given container against the given weave network IP
address. And if you use the `--with-dns` option, `weave run`
automatically supplies the DNS server address to the new container.
In some circumstances, you may not want to use the `weave run` command
to start containers. You can still take advantage of a running
weaveDNS, with some extra manual steps.
### Supplying the DNS server
If you want to start containers with `docker run` rather than `weave
run`, you can supply the docker bridge IP as the `--dns` option to
make it use weaveDNS:
```bash
$ docker_ip=$(docker inspect --format='{{ .NetworkSettings.Gateway }}' weavedns)
$ shell2=$(docker run --dns=$docker_ip -ti ubuntu)
$ weave attach 10.2.1.27/24 $shell2
```
This isn't very useful unless the container is also attached to the
weave network (as in the last line above).
Also note that this means of finding the Docker bridge's IP address
requires a running container (any one would do); another way to find
it is:
```bash
$ docker_ip=$(ip -4 addr show dev docker0 | grep -o 'inet [0-9.]*' | cut -d ' ' -f 2)
```
### Supplying the domain search path
By default, Docker provides containers with a `/etc/resolv.conf` that
matches that for the host. In some circumstances, this may include a
DNS search path, which will break the nice "bare names resolve"
property above.
Therefore, when starting containers with `docker run` instead of
`weave run`, you will usually want to supply a domain search path so
that you can use unqualified hostnames. Use `--dns-search=.` to make
the resolver use the container's domain, or e.g.,
`--dns-search=weave.local` to make it look in `weave.local`.
## <a name="troubleshooting"></a>Troubleshooting
The command
@@ -318,19 +249,20 @@ reports on the current status of various weave components, including
DNS:
````
weave router git-8f675f15c0b5
...
weave DNS git-8f675f15c0b5
Local domain weave.local.
weave DNS 1.0.0
Listen address :53
mDNS interface &{26 65535 ethwe fa:b6:b1:85:ac:9b up|broadcast|multicast}
Fallback DNS config &{[66.28.0.45 8.8.8.8] [] 53 1 5 2}
Fallback DNS config &{[10.0.2.3] [] 53 1 5 2}
Local domain weave.local.
Interface &{74 65535 ethwe 82:0c:92:84:0e:88 up|broadcast|multicast}
Zone database:
710978857a88 10.2.1.26 wiff.weave.local.
e8d85b1dcdb1 10.2.1.27 waff.weave.local.
26bd05f9a0cb 10.2.1.28 ping.weave.local.
1ab0e8b17c39 10.2.1.29 pong.weave.local.
144b75a9b873: pingme.weave.local.[10.160.0.1]/OBS:1
74a5510a91ad: ubuntu.weave.local.[10.160.0.2]
weave:remote: pingme.weave.local.[10.128.0.2]/TTL:30
...
````
The first section covers the router; see the [troubleshooting
+2 -2
View File
@@ -7,8 +7,8 @@ C2=10.2.1.7
start_suite "Ping over encrypted cross-host weave network"
weave_on $HOST1 launch -password notverysecure
weave_on $HOST2 launch -password notverysecure $HOST1
weave_on $HOST1 launch -password wfvAwt7sj
weave_on $HOST2 launch -password wfvAwt7sj $HOST1
start_container $HOST1 $C1/24 --name=c1
start_container $HOST2 $C2/24 --name=c2
+4
View File
@@ -33,4 +33,8 @@ assert_expected_fqdn "$HOSTNAME" -h $HOSTNAME --name=$NAME
assert_expected_fqdn "$HOSTNAME" --hostname=$HOSTNAME --name=$NAME
assert_expected_fqdn "$HOSTNAME" --hostname $HOSTNAME --name=$NAME
# Ensure we can launch a container with a name that is too long for hostname derivation
SIXTY_FIVE_CHARS=01234567890123456789012345678901234567890123456789012345678901234
assert_raises "start_container $HOST1 --name=$SIXTY_FIVE_CHARS"
end_suite
+13 -7
View File
@@ -4,13 +4,19 @@
start_suite "Run docker-py test suite against the proxy"
docker_on $HOST1 pull joffrey/docker-py >/dev/null
weave_on $HOST1 launch-proxy --no-default-ipam
assert_raises "docker_on $HOST1 ps | grep weaveproxy"
assert_raises "docker_on $HOST1 run \
-e NOT_ON_HOST=true \
-e DOCKER_HOST=tcp://172.17.42.1:12375 \
-v /tmp:/tmp \
-v /var/run/docker.sock:/var/run/docker.sock \
joffrey/docker-py python tests/integration_test.py"
if docker_on $HOST1 run \
-e NOT_ON_HOST=true \
-e DOCKER_HOST=tcp://172.17.42.1:12375 \
-v /tmp:/tmp \
-v /var/run/docker.sock:/var/run/docker.sock \
joffrey/docker-py python tests/integration_test.py ; then
assert_raises "true"
else
assert_raises "false"
fi
end_suite
+27 -1
View File
@@ -2,6 +2,10 @@
. ./config.sh
entrypoint() {
docker_on $HOST1 inspect --format="{{.Config.Entrypoint}}" "$@"
}
start_suite "Proxy waits for weave to be ready before running container commands"
weave_on $HOST1 launch-proxy
BASE_IMAGE=busybox
@@ -10,6 +14,28 @@ if (docker_on $HOST1 images $BASE_IMAGE | grep -q $BASE_IMAGE); then
docker_on $HOST1 rmi $BASE_IMAGE
fi
assert_raises "proxy docker_on $HOST1 run -e 'WEAVE_CIDR=10.2.1.1/24' $BASE_IMAGE $CHECK_ETHWE_UP"
assert_raises "proxy docker_on $HOST1 run --name c1 -e 'WEAVE_CIDR=10.2.1.1/24' $BASE_IMAGE $CHECK_ETHWE_UP"
# Check committed containers only have one weavewait prepended
COMMITTED_IMAGE=$(proxy docker_on $HOST1 commit c1)
assert_raises "proxy docker_on $HOST1 run --name c2 $COMMITTED_IMAGE"
assert "entrypoint c2" "$(entrypoint $COMMITTED_IMAGE)"
# Check exec works on containers without weavewait
docker_on $HOST1 run -dit --name c3 $SMALL_IMAGE /bin/sh
assert_raises "proxy docker_on $HOST1 exec c3 true"
# Check we can't modify weavewait
assert_raises "proxy docker_on $HOST1 run -e 'WEAVE_CIDR=10.2.1.2/24' $BASE_IMAGE touch /w/w" 1
# Check only user-specified volumes and /w are mounted
dirs_sans_proxy=$(docker_on $HOST1 run --rm $SMALL_IMAGE mount | wc -l)
dirs_with_proxy=$(proxy docker_on $HOST1 run --rm -v /tmp/1:/srv1 -v /tmp/2:/srv2 -e 'WEAVE_CIDR=10.2.1.3/24' $SMALL_IMAGE mount | wc -l)
assert "echo $((dirs_with_proxy-3))" $dirs_sans_proxy
# Check errors are returned (when docker returns an error code)
assert_raises "proxy docker_on $HOST1 run -e 'WEAVE_CIDR=10.2.1.3/24' $SMALL_IMAGE foo 2>&1 | grep 'exec: \"foo\": executable file not found in \$PATH'"
# Check errors still happen when no command is specified
assert_raises "proxy docker_on $HOST1 run -e 'WEAVE_CIDR=10.2.1.3/24' $SMALL_IMAGE 2>&1 | grep 'Error response from daemon: No command specified'"
end_suite
+2 -2
View File
@@ -8,8 +8,8 @@ C1_NAME=c1.weave.local
C2_NAME=seetwo.weave.local
boot_containers() {
proxy docker_on $HOST1 run -e WEAVE_CIDR=$C2/24 -dt --name=c2 -h $C2_NAME $DNS_IMAGE /bin/sh
proxy docker_on $HOST1 run -e WEAVE_CIDR=$C1/24 -dt --name=c1 $DNS_IMAGE /bin/sh
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C2/24 -dt --name=c2 -h $C2_NAME
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C1/24 -dt --name=c1
}
kill_containers() {
+4 -8
View File
@@ -9,19 +9,15 @@ C4=10.2.0.99
DOMAIN=weave.local
NAME=seeone.$DOMAIN
start_container() {
proxy docker_on $HOST1 run "$@" -dt $DNS_IMAGE /bin/sh
}
start_suite "Resolve unqualified names"
weave_on $HOST1 launch-dns 10.2.254.1/24
weave_on $HOST1 launch-proxy
start_container -e WEAVE_CIDR=$C1/24 --name=c1 -h $NAME
start_container -e WEAVE_CIDR=$C2/24 --name=c2 -h seetwo.$DOMAIN
start_container -e WEAVE_CIDR=$C3/24 --name=c3 --dns-search=$DOMAIN
container=$(start_container -e WEAVE_CIDR=$C4/24)
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C1/24 --name=c1 -h $NAME
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C2/24 --name=c2 -h seetwo.$DOMAIN
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C3/24 --name=c3 --dns-search=$DOMAIN
container=$(proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C4/24)
check() {
assert "proxy exec_on $HOST1 $1 getent hosts seeone | tr -s ' '" "$C1 $NAME"
+2 -2
View File
@@ -10,8 +10,8 @@ start_suite "Proxy restart reattaches networking to containers"
launch_dns_on $HOST1 10.2.254.1/24
weave_on $HOST1 launch-proxy --with-dns
proxy docker_on $HOST1 run -e WEAVE_CIDR=$C2/24 -dt --name=c2 -h $NAME $SMALL_IMAGE /bin/sh
proxy docker_on $HOST1 run -e WEAVE_CIDR=$C1/24 -dt --name=c1 $DNS_IMAGE /bin/sh
proxy_start_container $HOST1 -e WEAVE_CIDR=$C2/24 -dt --name=c2 -h $NAME
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C1/24 -dt --name=c1
proxy docker_on $HOST1 restart c2
assert_raises "proxy exec_on $HOST1 c2 $CHECK_ETHWE_UP"
+12 -10
View File
@@ -4,12 +4,6 @@
UNIVERSE=10.2.2.0/24
start() {
host=$1
shift
proxy docker_on "$host" run "$@" -dt $SMALL_IMAGE /bin/sh
}
assert_no_ethwe() {
assert_raises "container_ip $1 $2" 1
assert_raises "proxy exec_on $1 $2 ip link show | grep -v ethwe"
@@ -22,17 +16,25 @@ weave_on $HOST2 launch -iprange $UNIVERSE $HOST1
weave_on $HOST1 launch-proxy
weave_on $HOST2 launch-proxy --no-default-ipam
start $HOST1 --name=auto
start $HOST1 --name=none -e WEAVE_CIDR=none
start $HOST2 --name=zero -e WEAVE_CIDR=
start $HOST2 --name=no-default
proxy_start_container $HOST1 --name=auto
proxy_start_container $HOST1 --name=none -e WEAVE_CIDR=none
proxy_start_container $HOST2 --name=zero -e WEAVE_CIDR=
proxy_start_container $HOST2 --name=no-default
proxy_start_container $HOST1 --name=bridge --net=bridge
proxy_start_container $HOST1 --name=host --net=host
proxy_start_container $HOST1 --name=other --net=container:auto
AUTO=$(container_ip $HOST1 auto)
ZERO=$(container_ip $HOST2 zero)
BRIDGE=$(container_ip $HOST1 bridge)
OTHER=$(container_ip $HOST1 other)
assert_raises "proxy exec_on $HOST1 auto $PING $ZERO"
assert_raises "proxy exec_on $HOST2 zero $PING $AUTO"
assert_raises "proxy exec_on $HOST2 zero $PING $BRIDGE"
assert_raises "proxy exec_on $HOST2 zero $PING $OTHER"
assert_no_ethwe $HOST1 none
assert_no_ethwe $HOST2 no-default
assert_no_ethwe $HOST1 host
end_suite
+16
View File
@@ -0,0 +1,16 @@
#! /bin/bash
. ./config.sh
C1=10.2.1.13
start_suite "Start containers with 'weave run' via proxy"
weave_on $HOST1 launch
weave_on $HOST1 launch-proxy
proxy start_container $HOST1 $C1/24 --name=c1
# check we get exactly one IP back, the one specified
assert "weave_on $HOST1 ps c1 | cut -d ' ' -f 3-" $C1/24
end_suite
+13 -1
View File
@@ -120,6 +120,18 @@ start_container_with_dns() {
weave_on $host run --with-dns "$@" -t $DNS_IMAGE /bin/sh
}
proxy_start_container() {
host=$1
shift 1
proxy docker_on $host run "$@" -dt $SMALL_IMAGE /bin/sh
}
proxy_start_container_with_dns() {
host=$1
shift 1
proxy docker_on $host run "$@" -dt $DNS_IMAGE /bin/sh
}
rm_containers() {
host=$1
shift
@@ -170,8 +182,8 @@ assert_dns_ptr_record() {
start_suite() {
for host in $HOST1 $HOST2; do
[ -z "$DEBUG" ] || echo "Cleaning up on $host: removing all containers and resetting weave"
rm_containers $host $(docker_on $host ps -aq 2>/dev/null)
weave_on $host reset 2>/dev/null
rm_containers $host $(docker_on $host ps -aq 2>/dev/null)
done
whitely echo "$@"
}
+7 -5
View File
@@ -3,6 +3,7 @@
# ./gce.sh setup - starts two VMs on GCE and configures them to run our integration tests
# . ./gce.sh; ./run_all.sh - set a bunch of environment variables for the tests
# ./gce.sh destroy - tear down the VMs
# ./gce.sh make_template - make a fresh VM template; update TEMPLATE_NAME first!
set -ex
@@ -10,7 +11,7 @@ KEY_FILE=/tmp/gce_private_key.json
SSH_KEY_FILE=$HOME/.ssh/gce_ssh_key
PROJECT=positive-cocoa-90213
IMAGE=ubuntu-14-04
TEMPLATE_NAME="test-template"
TEMPLATE_NAME="test-template-2"
ZONE=us-central1-a
NUM_HOSTS=2
SUFFIX=""
@@ -96,12 +97,13 @@ function setup {
}
function make_template {
gcloud compute instances create template --image $IMAGE --zone $ZONE
gcloud compute instances create $TEMPLATE_NAME --image $IMAGE --zone $ZONE
gcloud compute config-ssh --ssh-key-file $SSH_KEY_FILE
name="template.$ZONE.$PROJECT"
name="$TEMPLATE_NAME.$ZONE.$PROJECT"
try_connect $name
install_docker_on $name
gcloud compute instances delete template --keep-disks boot -zone $ZONE
gcloud compute images create $TEMPLATE_NAME --source-disk example-disk --source-disk-zone $ZONE
gcloud -q compute instances delete $TEMPLATE_NAME --keep-disks boot --zone $ZONE
gcloud compute images create $TEMPLATE_NAME --source-disk $TEMPLATE_NAME --source-disk-zone $ZONE
}
function hosts {
+46 -16
View File
@@ -93,6 +93,22 @@ check_docker_version() {
fi
}
enforce_docker_bridge_addr_assign_type() {
if ! ADDR_ASSIGN_TYPE=$(cat /sys/class/net/$DOCKER_BRIDGE/addr_assign_type 2>/dev/null) ; then
echo "Could not determine address assignment type of $DOCKER_BRIDGE" >&2
return
fi
# From include/uapi/linux/netdevice.h
# #define NET_ADDR_PERM 0 /* address is permanent (default) */
# #define NET_ADDR_RANDOM 1 /* address is generated randomly */
# #define NET_ADDR_STOLEN 2 /* address is stolen from other device */
# #define NET_ADDR_SET 3 /* address is set using dev_set_mac_address() */
if [ $ADDR_ASSIGN_TYPE != 3 ] ; then
echo "Setting $DOCKER_BRIDGE MAC (mitigate https://github.com/docker/docker/issues/14908)" >&2
ip link set dev $DOCKER_BRIDGE address $(random_mac) || true
fi
}
is_cidr() {
echo "$1" | grep -E "^$CIDR_REGEXP$" >/dev/null
}
@@ -142,7 +158,7 @@ if [ "$1" = "run" ] ; then
shift $(dns_arg_count "$@")
collect_cidr_args "$@"
shift $CIDR_ARG_COUNT
CONTAINER=$(docker $DOCKER_CLIENT_ARGS run $DNS_ARGS -d "$@")
CONTAINER=$(docker $DOCKER_CLIENT_ARGS run -e WEAVE_CIDR=none $DNS_ARGS -d "$@")
exec_remote attach $CIDR_ARGS --or-die $CONTAINER
echo $CONTAINER
exit 0
@@ -359,7 +375,7 @@ netnsenter() {
}
connect_container_to_bridge() {
if [ -h "$PROCFS/$CONTAINER_PID/ns/net" -a -h "$PROCFS/$$/ns/net" -a "$(readlink $PROCFS/$CONTAINER_PID/ns/net)" = "$(readlink $PROCFS/$$/ns/net)" ] ; then
if [ -h "$PROCFS/$CONTAINER_PID/ns/net" -a -h "/proc/$$/ns/net" -a "$(readlink $PROCFS/$CONTAINER_PID/ns/net)" = "$(readlink /proc/$$/ns/net)" ] ; then
echo "Container is running in the host network namespace, and therefore cannot be" >&2
echo "connected to weave. Perhaps the container was started with --net=host." >&2
return 1
@@ -433,7 +449,9 @@ attach() {
netnsenter ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME
fi
arp_update $CONTAINER_IFNAME $1 "netnsenter"
for ADDR in "$@" ; do
arp_update $CONTAINER_IFNAME $ADDR "netnsenter"
done
}
detach() {
@@ -664,8 +682,11 @@ dns_args() {
WITHOUT_DNS=
while [ $# -gt 0 ] ; do
case "$1" in
--dns-search=*)
DNS_SEARCH_SPECIFIED=1
--with-dns)
WITH_DNS=1
;;
--without-dns)
WITHOUT_DNS=1
;;
--name)
NAME_ARG="$2"
@@ -677,11 +698,8 @@ dns_args() {
-h|--hostname|--hostname=*)
HOSTNAME_SPECIFIED=1
;;
--with-dns)
WITH_DNS=1
;;
--without-dns)
WITHOUT_DNS=1
--dns-search|--dns-search=*)
DNS_SEARCH_SPECIFIED=1
;;
esac
shift
@@ -693,8 +711,13 @@ dns_args() {
DNS_ARGS="--dns $DOCKER_BRIDGE_IP"
if [ -n "$NAME_ARG" -a -z "$HOSTNAME_SPECIFIED" ] ; then
DOMAIN=$(dns_domain)
DNS_ARGS="$DNS_ARGS --hostname=$NAME_ARG.${DOMAIN%.}"
HOSTNAME_SPECIFIED=1
HOSTNAME="$NAME_ARG.${DOMAIN%.}"
if [ ${#HOSTNAME} -gt 64 ] ; then
echo "Container name too long to be used as hostname" >&2
else
DNS_ARGS="$DNS_ARGS --hostname=$HOSTNAME"
HOSTNAME_SPECIFIED=1
fi
fi
if [ -z "$DNS_SEARCH_SPECIFIED" ] ; then
if [ -z "$HOSTNAME_SPECIFIED" ] ; then
@@ -859,7 +882,7 @@ ipam_cidrs_or_die() {
# TODO: Handle args with spaces
tls_arg() {
filename=${3:-$2}
PROXY_VOLUMES="$PROXY_VOLUMES -v $1:/home/weave/tls/$filename.pem"
PROXY_VOLUMES="$PROXY_VOLUMES -v $1:/home/weave/tls/$filename.pem:ro"
PROXY_ARGS="$PROXY_ARGS --tls$2 /home/weave/tls/$filename.pem"
}
@@ -971,6 +994,7 @@ case "$COMMAND" in
;;
launch)
check_not_running $CONTAINER_NAME $BASE_IMAGE
enforce_docker_bridge_addr_assign_type
create_bridge
# We set the router name to the bridge mac since that is
# stable across re-creations of the containers.
@@ -1017,10 +1041,15 @@ case "$COMMAND" in
if [ -z "$IPRANGE_SPECIFIED" ] ; then
IPRANGE="10.128.0.0/10"
if command_exists netcheck && ! netcheck $IPRANGE ; then
echo "Default -iprange $IPRANGE overlaps with existing route." >&2
echo "Please pick another range and set it on all hosts." >&2
echo "ERROR: Default -iprange $IPRANGE overlaps with existing route on host." >&2
echo "You must pick another range and set it on all hosts." >&2
exit 1
fi
else
if command_exists netcheck && ! netcheck $IPRANGE ; then
echo "WARNING: Specified -iprange $IPRANGE overlaps with existing route on host." >&2
echo "Unless this is deliberate, you must pick another range and set it on all hosts." >&2
fi
fi
# Set WEAVE_DOCKER_ARGS in the environment in order to supply
# additional parameters, such as resource limits, to docker
@@ -1071,6 +1100,7 @@ case "$COMMAND" in
-v /proc:/hostproc \
-e PROCFS=/hostproc \
-e WEAVE_CIDR=none \
-e DOCKER_BRIDGE \
--entrypoint=/home/weave/weaveproxy \
$WEAVEPROXY_DOCKER_ARGS $EXEC_IMAGE $PROXY_ARGS)
wait_for_log $PROXY_CONTAINER_NAME "proxy listening"
@@ -1130,7 +1160,7 @@ case "$COMMAND" in
shift $(dns_arg_count "$@")
collect_cidr_args "$@"
shift $CIDR_ARG_COUNT
CONTAINER=$(docker run $DNS_ARGS -d "$@")
CONTAINER=$(docker run -e WEAVE_CIDR=none $DNS_ARGS -d "$@")
create_bridge
ipam_cidrs_or_die $CONTAINER $CIDR_ARGS
with_container_netns_or_die $CONTAINER attach $ALL_CIDRS