Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8222d76d9 | ||
|
|
88a3b41135 | ||
|
|
fb7aa9298d | ||
|
|
b79cc948b3 | ||
|
|
e7092612a9 | ||
|
|
15c512388d | ||
|
|
f37377264b | ||
|
|
bd44b20b4a | ||
|
|
e25da3c619 | ||
|
|
3499dbfe09 | ||
|
|
81c4a0ffce | ||
|
|
a0064f7535 | ||
|
|
79c9eff2b9 | ||
|
|
b8bcf0c87d | ||
|
|
179a560e1d | ||
|
|
2245bd25e9 | ||
|
|
c256daceb0 | ||
|
|
73b29050b9 | ||
|
|
162da63522 | ||
|
|
01194ee267 | ||
|
|
d958cff58e | ||
|
|
d0662b519f | ||
|
|
d75a96e9ba | ||
|
|
bd7ed1b41a | ||
|
|
b5e6d235ba | ||
|
|
3cc537b978 | ||
|
|
ac0c0db942 | ||
|
|
0affbad976 | ||
|
|
ced84955d3 | ||
|
|
b86fc67adf | ||
|
|
59de4c3435 | ||
|
|
8e418b8743 | ||
|
|
f2b003379d | ||
|
|
0d083077ab | ||
|
|
db1a94a02c | ||
|
|
fdbc7dfe04 | ||
|
|
70f004cc62 | ||
|
|
c02cb45c6c | ||
|
|
8dccc88613 | ||
|
|
bb5914dbce | ||
|
|
4698ec1a37 | ||
|
|
e29c98faad | ||
|
|
444d6be6c9 | ||
|
|
28aa181480 | ||
|
|
97e0fcb765 | ||
|
|
052fdb30c0 | ||
|
|
2e2b667864 | ||
|
|
666631134c | ||
|
|
de4cfe2b8b | ||
|
|
a7ebe53cfa | ||
|
|
66a569fc40 | ||
|
|
3a646ffdba | ||
|
|
7cfd71c0bd | ||
|
|
3265d60d52 | ||
|
|
640b417b39 | ||
|
|
b655a3aede | ||
|
|
819b395ae4 | ||
|
|
2584335b11 | ||
|
|
4e5a8f348a | ||
|
|
f91a9c2562 | ||
|
|
ea098ac53e | ||
|
|
a0d0b00938 | ||
|
|
31a4657467 | ||
|
|
2ddb8fcec3 | ||
|
|
21d4fff450 | ||
|
|
00036ec277 | ||
|
|
a5d7fb66f0 | ||
|
|
b01a204c1f | ||
|
|
e9310eba98 | ||
|
|
69285270e5 | ||
|
|
6f96d6d63e | ||
|
|
91f476d2c6 | ||
|
|
7871a0b7a4 | ||
|
|
6bd11a426e | ||
|
|
1abdc3afcf | ||
|
|
b8f98a5387 | ||
|
|
cb3b858df6 | ||
|
|
d7025e7dfa | ||
|
|
b2b9c47a50 | ||
|
|
211003f542 | ||
|
|
f8227c3f47 | ||
|
|
258d764af8 | ||
|
|
37526728e0 | ||
|
|
7f4ad03a5c | ||
|
|
d60ad1f40a | ||
|
|
5106317e5d | ||
|
|
a5e4a19f06 | ||
|
|
067ce6de9f | ||
|
|
9facab53b7 | ||
|
|
4f20f545dc | ||
|
|
4bbf84f551 | ||
|
|
c617612794 | ||
|
|
0c89bbb8df | ||
|
|
a7206bee95 | ||
|
|
0e3a749f69 | ||
|
|
535bf9b066 | ||
|
|
ceb7206117 | ||
|
|
1273157ace | ||
|
|
5a92200dc6 | ||
|
|
d021e61dfa | ||
|
|
3ae505d6c6 | ||
|
|
a1ddb336c1 | ||
|
|
646ac3c74d | ||
|
|
d383a29e00 | ||
|
|
b44e295562 | ||
|
|
8a1f8d549e | ||
|
|
a2b674e094 | ||
|
|
c4796dcdf5 | ||
|
|
992b4a65df | ||
|
|
6928929bc9 | ||
|
|
508b424234 | ||
|
|
7f68a96f75 | ||
|
|
535e22e5f8 | ||
|
|
348a926af4 | ||
|
|
aa84c4788a | ||
|
|
66293e8caa | ||
|
|
1e60cff2ef | ||
|
|
701519a15c | ||
|
|
3cb6569d55 | ||
|
|
bebaa48520 | ||
|
|
af246225a9 | ||
|
|
582a792c71 | ||
|
|
98c4bd9ee5 | ||
|
|
933b395de4 | ||
|
|
4f485f856b | ||
|
|
280651da9c | ||
|
|
77201e949d | ||
|
|
292a50a891 | ||
|
|
a36fc867d1 | ||
|
|
def9f2d407 | ||
|
|
b0da4f6b91 | ||
|
|
cbf1230f6d | ||
|
|
71d6e881f2 | ||
|
|
da40771739 | ||
|
|
694314cc00 | ||
|
|
3025738377 | ||
|
|
cbe0f4e6e5 | ||
|
|
e0088e0252 | ||
|
|
e0bb49aa23 | ||
|
|
81d79a64e6 | ||
|
|
4f08879321 | ||
|
|
6d6394c408 | ||
|
|
bf3ecaf48a | ||
|
|
6ba2bf80b8 | ||
|
|
9f4030cdb6 | ||
|
|
cce818995a | ||
|
|
1e2dc43df6 | ||
|
|
06caf03d70 | ||
|
|
7226b26e8e | ||
|
|
7c72d69e2f | ||
|
|
bc1d6c47ba | ||
|
|
8ec0e025d3 | ||
|
|
9f40d913c9 | ||
|
|
3595c71d8b | ||
|
|
9740478151 | ||
|
|
442a55d539 | ||
|
|
01fce0c6b1 | ||
|
|
0e3ac00ff5 | ||
|
|
2285942384 | ||
|
|
0273491e6e | ||
|
|
b1917d909a | ||
|
|
edbf85655a | ||
|
|
be917eb86b | ||
|
|
0a2521e7a4 | ||
|
|
1b8d115b63 | ||
|
|
70929cec57 | ||
|
|
7611cd963c | ||
|
|
3e0eb4ac1e | ||
|
|
f8d501ae50 | ||
|
|
cb614f01c3 | ||
|
|
9be11d9cf0 | ||
|
|
8ca83de332 | ||
|
|
89d3fedcd4 | ||
|
|
71ca91db09 | ||
|
|
5cf973f03a | ||
|
|
2c7693b2c5 | ||
|
|
43249a8d39 | ||
|
|
b654ac178c | ||
|
|
ccac18b21c | ||
|
|
8a5fef98ab | ||
|
|
c85fff8f23 | ||
|
|
fc57e72853 | ||
|
|
ce94e69fd5 | ||
|
|
b46ccc0937 | ||
|
|
e89fc8f66a | ||
|
|
ad4fe86285 | ||
|
|
34ec7bd1c9 | ||
|
|
9a90898c7d | ||
|
|
8e80cd1441 | ||
|
|
d5d45de5a4 | ||
|
|
2ebd358aeb | ||
|
|
bb66b6161a | ||
|
|
f7130b8c21 | ||
|
|
a497e1ab8a | ||
|
|
e1ff2197c0 | ||
|
|
f684ea563d | ||
|
|
88cb871654 | ||
|
|
507e734d1a | ||
|
|
cb8599ebd5 | ||
|
|
7714952574 | ||
|
|
aaa974353a | ||
|
|
1cca9d6d79 | ||
|
|
d28b1dcd9f | ||
|
|
e4cab53a11 | ||
|
|
c342bc4188 | ||
|
|
73a0df56b2 | ||
|
|
e0303a0dda | ||
|
|
280a0fed69 | ||
|
|
264a2cd2ad | ||
|
|
907ba8f53b | ||
|
|
d2cbb2749e | ||
|
|
eab5ec206a | ||
|
|
fa8753cab3 | ||
|
|
9459d4b739 | ||
|
|
f517a09f0f | ||
|
|
34642a04a4 | ||
|
|
4bb4d943ba | ||
|
|
db855715ab | ||
|
|
c27e4d020d | ||
|
|
a16ad4d6e6 | ||
|
|
33ce8c5060 | ||
|
|
f2568627af | ||
|
|
334974472d | ||
|
|
8227a3f67c | ||
|
|
4f7d476907 | ||
|
|
a731d47d97 | ||
|
|
44beed4027 | ||
|
|
9fd1a43769 | ||
|
|
1c6abbbe41 | ||
|
|
c4a715747a | ||
|
|
3bdea732fc | ||
|
|
bfe8e79653 | ||
|
|
7d812e3087 | ||
|
|
05d9cf8235 | ||
|
|
108f4784a6 | ||
|
|
a7feb41e62 | ||
|
|
fddb3ee06e | ||
|
|
c59c86c660 | ||
|
|
8f02c81f16 | ||
|
|
b3fac8ed6a | ||
|
|
3574da267b | ||
|
|
c929b2d5f9 | ||
|
|
f479e57870 | ||
|
|
ae625a18c8 | ||
|
|
41a261bdcd | ||
|
|
4ad1c22ef6 | ||
|
|
ef9f95f653 | ||
|
|
3b54372eab | ||
|
|
f05bb6c4e0 | ||
|
|
c8e0c12d34 | ||
|
|
ab380ed2c1 | ||
|
|
9494f0655d | ||
|
|
c3a41286fd | ||
|
|
8297652204 | ||
|
|
a26fc67ded | ||
|
|
abadbf883a | ||
|
|
833eb6166f | ||
|
|
e7e3608642 | ||
|
|
dd232775e6 | ||
|
|
a8eb7966b6 | ||
|
|
8051f51d46 | ||
|
|
6fd9f471ff | ||
|
|
2d037d874c | ||
|
|
8e5384ee01 | ||
|
|
7dd37d2a13 | ||
|
|
36521b04a2 | ||
|
|
f5d0a277fb | ||
|
|
986a3f8079 | ||
|
|
de4ec23809 | ||
|
|
1cc0794e75 | ||
|
|
3cca0887c7 | ||
|
|
0e1d39120e | ||
|
|
a072cf2e0a | ||
|
|
0f0f3649a4 | ||
|
|
54c95c04af | ||
|
|
7c5dda353d | ||
|
|
c42400de4f | ||
|
|
9b5cef9167 | ||
|
|
6081c400fb | ||
|
|
cb339523de | ||
|
|
538902b207 | ||
|
|
8961041469 | ||
|
|
cfe26ae346 | ||
|
|
bdfa06dbe9 | ||
|
|
1a3537a8f4 | ||
|
|
09606db9c3 | ||
|
|
4a708c2a82 | ||
|
|
735a7f9154 | ||
|
|
7478e78ab7 | ||
|
|
01bfa602ad | ||
|
|
332762201a | ||
|
|
568290afb7 | ||
|
|
3c11c8aa38 | ||
|
|
2ba360f33a | ||
|
|
7fc56e54b3 | ||
|
|
16062ea62d | ||
|
|
e852ae99ca | ||
|
|
0ff37d3492 | ||
|
|
b3866ebd94 | ||
|
|
3031372442 | ||
|
|
d3d2de5f1f | ||
|
|
d7306c66f7 | ||
|
|
1f42a9d2f9 | ||
|
|
8c917eeb17 | ||
|
|
a81a873703 | ||
|
|
da04d97fb5 | ||
|
|
4f42029228 | ||
|
|
4916badcc4 | ||
|
|
82b56848a9 | ||
|
|
889dc856af | ||
|
|
2ba8764615 | ||
|
|
eb5435d275 | ||
|
|
b048b6deb0 | ||
|
|
0c23e47124 | ||
|
|
0af2111535 | ||
|
|
5bbd886e6f | ||
|
|
b753bcd982 | ||
|
|
d6a5eaec3f | ||
|
|
771f57029e | ||
|
|
c223ff1c7d | ||
|
|
481214776b | ||
|
|
98e6571059 | ||
|
|
19a31a5b82 | ||
|
|
090878c157 | ||
|
|
53cc270f47 | ||
|
|
ceb0186f46 | ||
|
|
46762a40b0 | ||
|
|
c291324d14 | ||
|
|
b307b9872a | ||
|
|
5e290aa11f | ||
|
|
5f6c5f6692 | ||
|
|
bc47866880 | ||
|
|
e6a692424b | ||
|
|
f293063538 | ||
|
|
6321512ddb | ||
|
|
0ca125ff2c | ||
|
|
57efe0145b | ||
|
|
bd53462ab2 | ||
|
|
c44d98b798 | ||
|
|
c8adcb2e79 | ||
|
|
768f89c3de | ||
|
|
e2d644b86b | ||
|
|
09977a2e04 | ||
|
|
63a0b964ab | ||
|
|
1b7c386351 | ||
|
|
293f1990bc | ||
|
|
0bb62ae75a | ||
|
|
77b193791a | ||
|
|
74a7bef472 | ||
|
|
fc78bf4d11 | ||
|
|
84cdf54079 | ||
|
|
fa08bb9df6 | ||
|
|
3e030f7971 | ||
|
|
d0e0df9bd4 | ||
|
|
f5bdf916f5 | ||
|
|
ea36d232ac | ||
|
|
916ff7aa39 | ||
|
|
e74783b987 | ||
|
|
0b4c19a369 | ||
|
|
def9d8d004 | ||
|
|
2301e8dbf7 | ||
|
|
ac430e4c42 | ||
|
|
c6457981ab | ||
|
|
8862d4f76e | ||
|
|
d313ec935c | ||
|
|
40e759733d | ||
|
|
dee57aca37 | ||
|
|
7ac2301247 | ||
|
|
1d55ee19e4 | ||
|
|
9810a84475 | ||
|
|
b128562b41 | ||
|
|
8f44dc0986 | ||
|
|
ca523fa335 | ||
|
|
5860332e49 | ||
|
|
c06d4d1b00 | ||
|
|
bec2470ddf | ||
|
|
9516b1a91b | ||
|
|
8468183738 | ||
|
|
39563fc142 | ||
|
|
104d2240ec | ||
|
|
9bec84da5b | ||
|
|
e3a37c8d71 | ||
|
|
fd28740108 | ||
|
|
fa74d1b9bb | ||
|
|
11d120bb5b | ||
|
|
e2c96cfa85 | ||
|
|
eee3e8d331 | ||
|
|
0c68ad4acb | ||
|
|
26b566b541 | ||
|
|
16bbee2831 | ||
|
|
96f7c6ebab | ||
|
|
5b06063442 |
No files matched your search
@@ -0,0 +1,65 @@
|
||||
<!--
|
||||
Hi, thank you for opening an issue!
|
||||
Before hitting the button...
|
||||
|
||||
** Is this a REQUEST FOR HELP? **
|
||||
If so, please have a look at:
|
||||
- our FAQ: https://www.weave.works/docs/net/latest/faq/
|
||||
- our troubleshooting page: https://www.weave.works/docs/net/latest/troubleshooting/
|
||||
- our help page, to choose the best channel (Slack, etc.) to reach out: https://www.weave.works/help/
|
||||
|
||||
** Is this a FEATURE REQUEST? **
|
||||
If so, please search existing feature requests, and if you find a similar one, up-vote it and/or add your comments to it instead.
|
||||
If you did not find a similar one, please describe in details:
|
||||
- why: your use-case, specific constraints you may have, etc.
|
||||
- what: the feature/behaviour/change you would like to see in Weave Net
|
||||
Do not hesitate, when appropriate, to share the exact commands or API you would like, and/or to share a diagram (e.g.: asciiflow.com): "a picture is worth a thousand words".
|
||||
|
||||
** Is this a BUG REPORT? **
|
||||
Please fill in as much of the template below as you can.
|
||||
|
||||
Thank you!
|
||||
-->
|
||||
|
||||
## What you expected to happen?
|
||||
|
||||
## What happened?
|
||||
<!-- Error message, actual behaviour, etc. -->
|
||||
|
||||
## How to reproduce it?
|
||||
<!-- Specific steps, as minimally and precisely as possible. -->
|
||||
|
||||
## Anything else we need to know?
|
||||
<!-- Cloud provider? Hardware? How did you configure your cluster? Kubernetes YAML, KOPS, etc. -->
|
||||
|
||||
## Versions:
|
||||
<!-- Please paste in the output of these commands; 'kubectl' only if using Kubernetes -->
|
||||
```
|
||||
$ weave version
|
||||
$ docker version
|
||||
$ uname -a
|
||||
$ kubectl version
|
||||
```
|
||||
|
||||
## Logs:
|
||||
```
|
||||
$ docker logs weave
|
||||
```
|
||||
or, if using Kubernetes:
|
||||
```
|
||||
$ kubectl logs -n kube-system <weave-net-pod> weave
|
||||
```
|
||||
<!-- (If output is long, please consider a Gist.) -->
|
||||
<!-- Anything interesting or unusual output by the below, potentially relevant, commands?
|
||||
$ journalctl -u docker.service --no-pager
|
||||
$ journalctl -u kubelet --no-pager
|
||||
$ kubectl get events
|
||||
-->
|
||||
|
||||
## Network:
|
||||
<!-- If your problem has anything to do with one network endpoint not being able to contact another, please run the following commands -->
|
||||
```
|
||||
$ ip route
|
||||
$ ip -4 -o addr
|
||||
$ sudo iptables-save
|
||||
```
|
||||
+3
-4
@@ -37,7 +37,6 @@ coverage.html
|
||||
prog/weaver/weaver
|
||||
prog/weavedns/weavedns
|
||||
prog/weavehosts/weavehosts
|
||||
prog/weaveproxy/weaveproxy
|
||||
prog/sigproxy/sigproxy
|
||||
prog/weavewait/weavewait
|
||||
prog/weavewait/weavewait_noop
|
||||
@@ -53,14 +52,13 @@ testing/runner/runner
|
||||
releases
|
||||
.*.uptodate
|
||||
weave*.tar.gz
|
||||
prog/weaveexec/weave
|
||||
prog/weaver/weave
|
||||
prog/weaveexec/weavehosts
|
||||
prog/weaveexec/weaveproxy
|
||||
prog/weaveexec/weavewait
|
||||
prog/weaveexec/weavewait_noop
|
||||
prog/weaveexec/weavewait_nomcast
|
||||
prog/weaveexec/sigproxy
|
||||
prog/weaveexec/weaveutil
|
||||
prog/weaver/weaveutil
|
||||
prog/weaveexec/docker*
|
||||
Vagrantfile.local
|
||||
test/tls/tls
|
||||
@@ -70,6 +68,7 @@ test/coverage.*
|
||||
*qemu-*-static
|
||||
terraform.tfstate
|
||||
terraform.tfstate.backup
|
||||
prog/net-plugin/rootfs/
|
||||
|
||||
# Website
|
||||
site-build
|
||||
@@ -124,3 +124,12 @@
|
||||
[submodule "vendor/github.com/containernetworking/cni"]
|
||||
path = vendor/github.com/containernetworking/cni
|
||||
url = https://github.com/containernetworking/cni
|
||||
[submodule "vendor/google.golang.org/grpc"]
|
||||
path = vendor/google.golang.org/grpc
|
||||
url = https://github.com/grpc/grpc-go
|
||||
[submodule "vendor/github.com/docker/go-units"]
|
||||
path = vendor/github.com/docker/go-units
|
||||
url = https://github.com/docker/go-units
|
||||
[submodule "vendor/golang.org/x/net"]
|
||||
path = vendor/golang.org/x/net
|
||||
url = https://github.com/golang/net
|
||||
+152
@@ -1,3 +1,155 @@
|
||||
## Release 2.0.1
|
||||
|
||||
Bug fixes and minor improvements
|
||||
|
||||
* Fall back to slower data path (`sleeve`), rather than crashing, when the machine lacks VXLAN support (required for “fast data path”, `fastdp`) #3043
|
||||
* Fix bug in processing of arguments when Docker has TLS enabled, rather than crashing with invalid peers list, e.g. `lookup --tlsverify: no such host` #3039
|
||||
* Add `kube-system` namespace back to `weave-kube`'s YAMLs, preventing omissions leading to errors like `error contacting APIServer: the server does not allow access to the requested resource` #3033,#3042
|
||||
* Fix release script to prevent ARM64 binaries to end up in AMD64 `net-plugin`, leading to `Error response from daemon: dial unix /run/docker/plugins/<id>/weave.sock: connect: no such file or directory` when installing `net-plugin` #3045
|
||||
* `weave reset` and `weave rmpeer` now only contact Weave Cloud when Weave Net is configured with a Weave Cloud token, preventing unnecessary requests and potentially confusing `401 Unauthorized` errors in Weave Net’s logs #3044
|
||||
|
||||
[Full list of changes](https://github.com/weaveworks/weave/milestone/58?closed=1).
|
||||
|
||||
|
||||
## Release 2.0.0
|
||||
|
||||
New Features
|
||||
|
||||
Peer Discovery via Weave Cloud
|
||||
|
||||
You can now get all your Weave Net peers to find each other via the
|
||||
Weave Cloud service, instead of maintaining a list of peers at
|
||||
startup. #2799,#2827
|
||||
|
||||
See the [docs
|
||||
page](https://github.com/weaveworks/weave/blob/master/site/using-weave/weave-cloud.md)
|
||||
for more details
|
||||
|
||||
New Docker Plugin
|
||||
|
||||
Docker has a [new plugin
|
||||
system](https://docs.docker.com/engine/extend/) which improves the
|
||||
installation UX and solves some issues around startup. This means
|
||||
Weave Net 2.0 can now run with Docker in "swarm mode" and supports the
|
||||
`docker service` command. #2396,#2397,#2651,#2727,#2805,#2816,#2905,
|
||||
#2906,#2929,#2932,#2945,#2950,#2956,#2963,#2964,#2966,#3019
|
||||
|
||||
The previous Docker Plugin is still available and can be installed as before.
|
||||
|
||||
All of Weave Net now runs in one container
|
||||
|
||||
Previously we had three separate containers for routing, Docker API
|
||||
proxy and Docker plugin. Running everything in one simplifies start-up
|
||||
and removes the need to detect various error
|
||||
conditions. #1642,#2897,#2936,#2945,#2946,#2951,#2960
|
||||
|
||||
The individual commands ‘weave launch-router’, ‘weave launch-plugin’,
|
||||
etc., have been removed. You can turn off the plugin and proxy with
|
||||
new command-line options. In keeping with Semantic Versioning, we have
|
||||
changed the major version number for this release.
|
||||
|
||||
Other new features
|
||||
|
||||
* Kubernetes configuration now comes from our “Launch Generator” that
|
||||
allows different options to be selected via
|
||||
URL. #2754,#2903,#3000,#3001
|
||||
* `weave-kube` now stores data about IP allocation in `/var/lib/weave`
|
||||
on the host instead of in a Kubernetes volume. This means that the
|
||||
data will persist across pod deletion and re-creation, e.g. during
|
||||
an upgrade of Weave Net, which makes restarts more
|
||||
reliable. #2610,#2967
|
||||
* `weave-kube` turned on rolling updates, so careful manual handling
|
||||
of updates is no longer required. #3024
|
||||
|
||||
Bug fixes
|
||||
|
||||
* Kubernetes Network Policies which allowed a specific set of pods to
|
||||
connect would block all pods on other hosts. Revert the change in
|
||||
v1.9.6 which ignored pods on other hosts #3025,#3028
|
||||
|
||||
Features removed
|
||||
|
||||
* `weave run` has been removed. This was the original method provided
|
||||
to start containers with Weave Net, but it always required care over
|
||||
timing of start-up, and we now provide three alternative, better,
|
||||
ways. You can replicate the effect by calling `docker run` then
|
||||
`weave attach`. Similarly `weave start` and `weave restart` were
|
||||
removed. #2353,#2885
|
||||
* Everything deprecated more than one release ago has been removed, so
|
||||
if you use it now you get an error rather than a warning. This
|
||||
includes the ‘create-bridge’ command and older command-line
|
||||
arguments, e.g. `--iprange` was replaced by `--ipalloc-range`
|
||||
#2901,#2909,#2913,#2942,#2989,#2991
|
||||
|
||||
Functions moved from shell-script to Go code.
|
||||
|
||||
This enables more precise error-checking and runs a bit faster. It has
|
||||
also enabled us to shrink the size of images downloaded: `weave-kube`
|
||||
is 101MB compared to 163MB previously #2953,#2954,#2974
|
||||
|
||||
Specific items that moved from shell-script to Go:
|
||||
* Setting up the `weave` bridge #1958,#2975,#2977,#2978
|
||||
* Container attachment #2947
|
||||
* Creation of the ’weave’ default plugin network #2920
|
||||
|
||||
Minor improvements
|
||||
|
||||
* You can now restart the Weave Net router without requiring the proxy to be enabled #2112
|
||||
* Plugin (legacy version) now respects `--ipalloc-default-subnet` option #2919
|
||||
* The `weave` script now detects and issues an error message if
|
||||
`weave-kube` is running and you attempt to launch again from the script. #2709/#2966
|
||||
* It is now possible to choose the the MAC address of the `weave`
|
||||
bridge using `--name`, in case your hosts have identical unique
|
||||
IDs. #2900
|
||||
* Relaxed Kubernetes tolerations for Weave Net's daemonset in order to
|
||||
match any node (previously, only taints directed at master). #3018
|
||||
* Kubernetes' `seLinuxOptions` configuration is now empty by default,
|
||||
to reduce spurious failures on hosts not using seLinux. #3001
|
||||
* Improved reliability of namespace changes via `nsenter`. #2992
|
||||
* `weave ps` now fetches the list container IDs internally, rather
|
||||
than calling out to `docker ps` #2814,#2898
|
||||
* at startup, actively remove dead containers’ Weave Net IP addresses from IPAM #3013
|
||||
* at startup, only check live containers to see if they have an
|
||||
existing Weave Net IP address #2815,#2829
|
||||
* Weave Net CNI plugin now logs but does not raise an error if
|
||||
anything goes wrong during network interface delete, to be more
|
||||
compatible with Kubernetes 1.6. #2928
|
||||
* Stop running a shell in “privileged” mode when it’s only writing a file #2838
|
||||
* New internal REST endpoint to return all IP address mappings. #1350
|
||||
* Changed the wording where we do not log the password #2833
|
||||
* Fixed typo in plugin error messages #2894
|
||||
|
||||
Build and test
|
||||
|
||||
* Weave Net is now built with Go version 1.8, which has better code
|
||||
generation and garbage collection #2914
|
||||
* During smoke-tests, use a webserver instead of just `ping` so we get
|
||||
a more realistic test that the Weave network is working #2918
|
||||
* When installing dependencies for the build container, use a
|
||||
keyserver port that's better for firewalls #2812
|
||||
* Kubernetes test script now scales up to more hosts, and works with
|
||||
Kubernetes 1.6 #2837,#2853,#2923
|
||||
* Other minor build improvements and refactoring #2760,#2910
|
||||
|
||||
[Full list of changes](https://github.com/weaveworks/weave/milestone/49?closed=1).
|
||||
|
||||
|
||||
## Release 1.9.8
|
||||
|
||||
Bug fixes and minor improvements
|
||||
|
||||
* Fix weave-npc blocking NodePort and any other non-local access #3011,#3014
|
||||
* Fix bug where IPAM would duplicate a fixed IP address assigned via Docker plugin #3003,#3010
|
||||
|
||||
[Full list of changes](https://github.com/weaveworks/weave/milestone/56?closed=1).
|
||||
|
||||
|
||||
## Release 1.9.7
|
||||
|
||||
This is identical to 1.9.6 with one additional bug-fix:
|
||||
|
||||
* weave-npc would block everything if `kubelet --hostname-override` was used #2995,#2996
|
||||
|
||||
## Release 1.9.6
|
||||
|
||||
Bug fixes and minor improvements
|
||||
|
||||
+3
-3
@@ -1,3 +1,3 @@
|
||||
DOCKER_VERSION=1.11.2
|
||||
KUBERNETES_VERSION=1.5.2
|
||||
KUBERNETES_CNI_VERSION=0.3.0.1
|
||||
DOCKER_VERSION=1.13.1
|
||||
KUBERNETES_VERSION=1.6.2
|
||||
KUBERNETES_CNI_VERSION=0.5.1
|
||||
@@ -1,5 +1,5 @@
|
||||
.DEFAULT: all
|
||||
.PHONY: all exes testrunner update tests lint publish-one-arch $(PUBLISH) clean clean-bin prerequisites build run-smoketests
|
||||
.PHONY: all exes testrunner update tests lint publish-one-arch $(PUBLISH) clean clean-bin clean-work-dir prerequisites build run-smoketests
|
||||
|
||||
# If you can use docker without being root, you can do "make SUDO="
|
||||
SUDO=$(shell docker info >/dev/null 2>&1 || echo "sudo -E")
|
||||
@@ -82,10 +82,11 @@ endif
|
||||
DOCKERHUB_USER?=weaveworks
|
||||
# The default version that's chosen when pushing the images. Can/should be overridden
|
||||
WEAVE_VERSION?=git-$(shell git rev-parse --short=12 HEAD)
|
||||
# Docker Store does not allow the "latest" tag.
|
||||
NET_PLUGIN_LATEST=latest_release
|
||||
|
||||
# Paths to all relevant binaries that should be compiled
|
||||
WEAVER_EXE=prog/weaver/weaver
|
||||
WEAVEPROXY_EXE=prog/weaveproxy/weaveproxy
|
||||
SIGPROXY_EXE=prog/sigproxy/sigproxy
|
||||
KUBEPEERS_EXE=prog/kube-peers/kube-peers
|
||||
WEAVENPC_EXE=prog/weave-npc/weave-npc
|
||||
@@ -93,39 +94,44 @@ WEAVEWAIT_EXE=prog/weavewait/weavewait
|
||||
WEAVEWAIT_NOOP_EXE=prog/weavewait/weavewait_noop
|
||||
WEAVEWAIT_NOMCAST_EXE=prog/weavewait/weavewait_nomcast
|
||||
WEAVEUTIL_EXE=prog/weaveutil/weaveutil
|
||||
PLUGIN_EXE=prog/plugin/plugin
|
||||
RUNNER_EXE=tools/runner/runner
|
||||
MANIFEST_TOOL_DIR=vendor/github.com/estesp/manifest-tool
|
||||
MANIFEST_TOOL_EXE=$(MANIFEST_TOOL_DIR)/manifest-tool
|
||||
TEST_TLS_EXE=test/tls/tls
|
||||
NETWORKTESTER_EXE=test/images/network-tester/webserver
|
||||
|
||||
# All binaries together in a list
|
||||
EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVEUTIL_EXE) $(PLUGIN_EXE) $(RUNNER_EXE) $(TEST_TLS_EXE) $(MANIFEST_TOOL_EXE)
|
||||
EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVEUTIL_EXE) $(RUNNER_EXE) $(TEST_TLS_EXE) $(MANIFEST_TOOL_EXE) $(NETWORKTESTER_EXE)
|
||||
|
||||
# These stamp files are used to mark the current state of the build; whether an image has been built or not
|
||||
BUILD_UPTODATE=.build.uptodate
|
||||
WEAVER_UPTODATE=.weaver$(ARCH_EXT).uptodate
|
||||
WEAVEEXEC_UPTODATE=.weaveexec$(ARCH_EXT).uptodate
|
||||
PLUGIN_UPTODATE=.plugin$(ARCH_EXT).uptodate
|
||||
PLUGIN_UPTODATE=.net-plugin$(ARCH_EXT).uptodate
|
||||
WEAVEKUBE_UPTODATE=.weavekube$(ARCH_EXT).uptodate
|
||||
WEAVENPC_UPTODATE=.weavenpc$(ARCH_EXT).uptodate
|
||||
WEAVEDB_UPTODATE=.weavedb.uptodate
|
||||
NETWORKTESTER_UPTODATE=.networktester$(ARCH_EXT).uptodate
|
||||
|
||||
IMAGES_UPTODATE=$(WEAVER_UPTODATE) $(WEAVEEXEC_UPTODATE) $(PLUGIN_UPTODATE) $(WEAVEKUBE_UPTODATE) $(WEAVENPC_UPTODATE)
|
||||
IMAGES_UPTODATE=$(WEAVER_UPTODATE) $(WEAVEEXEC_UPTODATE) $(WEAVEKUBE_UPTODATE) $(WEAVENPC_UPTODATE) $(NETWORKTESTER_UPTODATE)
|
||||
|
||||
# The names of the images. Note that the images for other architectures than amd64 have a suffix in the image name.
|
||||
WEAVER_IMAGE=$(DOCKERHUB_USER)/weave$(ARCH_EXT)
|
||||
WEAVEEXEC_IMAGE=$(DOCKERHUB_USER)/weaveexec$(ARCH_EXT)
|
||||
PLUGIN_IMAGE=$(DOCKERHUB_USER)/plugin$(ARCH_EXT)
|
||||
WEAVEKUBE_IMAGE=$(DOCKERHUB_USER)/weave-kube$(ARCH_EXT)
|
||||
WEAVENPC_IMAGE=$(DOCKERHUB_USER)/weave-npc$(ARCH_EXT)
|
||||
BUILD_IMAGE=weaveworks/weavebuild
|
||||
WEAVEDB_IMAGE=$(DOCKERHUB_USER)/weavedb
|
||||
PLUGIN_IMAGE=$(DOCKERHUB_USER)/net-plugin
|
||||
NETWORKTESTER_IMAGE=$(DOCKERHUB_USER)/network-tester
|
||||
|
||||
IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(PLUGIN_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE)
|
||||
IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE) $(NETWORKTESTER_IMAGE)
|
||||
|
||||
PUBLISH=publish_weave publish_weaveexec publish_plugin publish_weave-kube publish_weave-npc
|
||||
PUSH_ML=push_ml_weave push_ml_weaveexec push_ml_plugin push_ml_weave-kube push_ml_weave-npc
|
||||
PLUGIN_WORK_DIR="prog/net-plugin/rootfs"
|
||||
PLUGIN_BUILD_IMG="plugin-builder"
|
||||
|
||||
PUBLISH=publish_weave publish_weaveexec publish_weave-kube publish_weave-npc
|
||||
PUSH_ML=push_ml_weave push_ml_weaveexec push_ml_weave-kube push_ml_weave-npc
|
||||
|
||||
WEAVE_EXPORT=weave$(ARCH_EXT).tar.gz
|
||||
|
||||
@@ -150,20 +156,21 @@ PACKAGE_BASE=$(shell go list -e ./)
|
||||
all: $(WEAVE_EXPORT)
|
||||
testrunner: $(RUNNER_EXE) $(TEST_TLS_EXE)
|
||||
|
||||
$(WEAVER_EXE) $(WEAVEPROXY_EXE) $(WEAVEUTIL_EXE): common/*.go common/*/*.go net/*.go net/*/*.go
|
||||
$(WEAVER_EXE) $(WEAVEUTIL_EXE): common/*.go common/*/*.go net/*.go net/*/*.go
|
||||
$(WEAVER_EXE): router/*.go ipam/*.go ipam/*/*.go db/*.go nameserver/*.go prog/weaver/*.go
|
||||
$(WEAVEPROXY_EXE): proxy/*.go prog/weaveproxy/*.go
|
||||
$(WEAVER_EXE): api/*.go plugin/*.go plugin/*/*
|
||||
$(WEAVER_EXE): proxy/*.go
|
||||
$(WEAVEUTIL_EXE): prog/weaveutil/*.go net/*.go plugin/net/*.go plugin/ipam/*.go db/*.go
|
||||
$(SIGPROXY_EXE): prog/sigproxy/*.go
|
||||
$(KUBEPEERS_EXE): prog/kube-peers/*.go
|
||||
$(WEAVENPC_EXE): prog/weave-npc/*.go npc/*.go npc/*/*.go
|
||||
$(PLUGIN_EXE): prog/plugin/*.go plugin/*/*.go api/*.go common/*.go common/docker/*.go net/*.go
|
||||
$(TEST_TLS_EXE): test/tls/*.go
|
||||
$(RUNNER_EXE): tools/runner/*.go
|
||||
$(MANIFEST_TOOL_EXE): $(MANIFEST_TOOL_DIR)/*.go
|
||||
$(WEAVEWAIT_NOOP_EXE): prog/weavewait/*.go
|
||||
$(WEAVEWAIT_EXE): prog/weavewait/*.go net/*.go
|
||||
$(WEAVEWAIT_NOMCAST_EXE): prog/weavewait/*.go net/*.go
|
||||
$(NETWORKTESTER_EXE): test/images/network-tester/*.go
|
||||
tests: tools/.git
|
||||
lint: tools/.git
|
||||
|
||||
@@ -181,12 +188,13 @@ exes $(EXES) tests lint: $(BUILD_UPTODATE)
|
||||
-v $(shell pwd)/.pkg:/go/pkg \
|
||||
-e GOARCH=$(ARCH) -e CGO_ENABLED=1 -e GOOS=linux -e CIRCLECI -e CIRCLE_BUILD_NUM -e CIRCLE_NODE_TOTAL -e CIRCLE_NODE_INDEX -e COVERDIR -e SLOW -e DEBUG \
|
||||
$(BUILD_IMAGE) COVERAGE=$(COVERAGE) WEAVE_VERSION=$(WEAVE_VERSION) CC=$(CC) QEMUARCH=$(QEMUARCH) CGO_LDFLAGS=$(CGO_LDFLAGS) $@
|
||||
touch $@
|
||||
|
||||
else
|
||||
|
||||
exes: $(EXES)
|
||||
|
||||
$(WEAVER_EXE) $(WEAVEPROXY_EXE) $(PLUGIN_EXE):
|
||||
$(WEAVER_EXE):
|
||||
ifeq ($(COVERAGE),true)
|
||||
$(eval COVERAGE_MODULES := $(shell (go list ./$(@D); go list -f '{{join .Deps "\n"}}' ./$(@D) | grep "^$(PACKAGE_BASE)/") | grep -v "^$(PACKAGE_BASE)/vendor/" | paste -s -d,))
|
||||
go test -c -o ./$@ $(BUILD_FLAGS) -v -covermode=atomic -coverpkg $(COVERAGE_MODULES) ./$(@D)/
|
||||
@@ -195,7 +203,7 @@ else
|
||||
endif
|
||||
$(NETGO_CHECK)
|
||||
|
||||
$(WEAVEUTIL_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE):
|
||||
$(WEAVEUTIL_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE) $(NETWORKTESTER_EXE):
|
||||
go build $(BUILD_FLAGS) -o $@ ./$(@D)
|
||||
$(NETGO_CHECK)
|
||||
|
||||
@@ -246,25 +254,37 @@ else
|
||||
endif
|
||||
|
||||
# The targets below builds the weave images
|
||||
$(WEAVER_UPTODATE): prog/weaver/Dockerfile.$(DOCKERHUB_USER) $(WEAVER_EXE) $(WEAVEEXEC_UPTODATE)
|
||||
$(WEAVER_UPTODATE): prog/weaver/Dockerfile.$(DOCKERHUB_USER) $(WEAVER_EXE) weave $(WEAVEUTIL_EXE)
|
||||
cp $(WEAVEUTIL_EXE) prog/weaver/weaveutil
|
||||
cp weave prog/weaver/weave
|
||||
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -f prog/weaver/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVER_IMAGE) prog/weaver
|
||||
touch $@
|
||||
|
||||
$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) prog/weaveexec/symlink $(DOCKER_DISTRIB) weave $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVEUTIL_EXE)
|
||||
cp weave prog/weaveexec/weave
|
||||
$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) prog/weaveexec/symlink $(DOCKER_DISTRIB) $(SIGPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVER_UPTODATE)
|
||||
cp $(SIGPROXY_EXE) prog/weaveexec/sigproxy
|
||||
cp $(WEAVEPROXY_EXE) prog/weaveexec/weaveproxy
|
||||
cp $(WEAVEWAIT_EXE) prog/weaveexec/weavewait
|
||||
cp $(WEAVEWAIT_NOOP_EXE) prog/weaveexec/weavewait_noop
|
||||
cp $(WEAVEWAIT_NOMCAST_EXE) prog/weaveexec/weavewait_nomcast
|
||||
cp $(WEAVEUTIL_EXE) prog/weaveexec/weaveutil
|
||||
tar -xf $(DOCKER_DISTRIB) usr/local/bin/docker -O > prog/weaveexec/docker
|
||||
chmod +x prog/weaveexec/docker
|
||||
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -f prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVEEXEC_IMAGE) prog/weaveexec
|
||||
touch $@
|
||||
|
||||
$(PLUGIN_UPTODATE): prog/plugin/Dockerfile.$(DOCKERHUB_USER) $(PLUGIN_EXE) $(WEAVER_UPTODATE)
|
||||
$(SUDO) docker build -f prog/plugin/Dockerfile.$(DOCKERHUB_USER) -t $(PLUGIN_IMAGE) prog/plugin
|
||||
# Builds Docker plugin.
|
||||
$(PLUGIN_UPTODATE): prog/net-plugin/launch.sh prog/net-plugin/config.json $(WEAVER_UPTODATE)
|
||||
-$(SUDO) docker rm -f $(PLUGIN_BUILD_IMG) 2>/dev/null
|
||||
$(SUDO) docker create --name=$(PLUGIN_BUILD_IMG) $(WEAVER_IMAGE) true
|
||||
rm -rf $(PLUGIN_WORK_DIR)
|
||||
mkdir $(PLUGIN_WORK_DIR)
|
||||
$(SUDO) docker export $(PLUGIN_BUILD_IMG) | tar -x -C $(PLUGIN_WORK_DIR)
|
||||
$(SUDO) docker rm -f $(PLUGIN_BUILD_IMG)
|
||||
cp prog/net-plugin/launch.sh $(PLUGIN_WORK_DIR)/home/weave/launch.sh
|
||||
-$(SUDO) docker plugin disable $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null
|
||||
-$(SUDO) docker plugin rm $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null
|
||||
$(SUDO) docker plugin create $(PLUGIN_IMAGE):$(WEAVE_VERSION) prog/net-plugin
|
||||
-$(SUDO) docker plugin disable $(PLUGIN_IMAGE):$(NET_PLUGIN_LATEST) 2>/dev/null
|
||||
-$(SUDO) docker plugin rm $(PLUGIN_IMAGE):$(NET_PLUGIN_LATEST) 2>/dev/null
|
||||
$(SUDO) docker plugin create $(PLUGIN_IMAGE):$(NET_PLUGIN_LATEST) prog/net-plugin
|
||||
touch $@
|
||||
|
||||
$(WEAVEKUBE_UPTODATE): prog/weave-kube/Dockerfile.$(DOCKERHUB_USER) prog/weave-kube/launch.sh $(KUBEPEERS_EXE) $(WEAVER_UPTODATE)
|
||||
@@ -280,6 +300,10 @@ $(WEAVEDB_UPTODATE): prog/weavedb/Dockerfile
|
||||
$(SUDO) docker build -t $(WEAVEDB_IMAGE) prog/weavedb
|
||||
touch $@
|
||||
|
||||
$(NETWORKTESTER_UPTODATE): test/images/network-tester/Dockerfile $(NETWORKTESTER_EXE)
|
||||
$(SUDO) docker build -t $(NETWORKTESTER_IMAGE) test/images/network-tester
|
||||
touch $@
|
||||
|
||||
$(WEAVE_EXPORT): $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE)
|
||||
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker save $(addsuffix :latest,$(IMAGES)) | gzip > $@
|
||||
|
||||
@@ -292,6 +316,14 @@ tools/.git $(MANIFEST_TOOL_DIR)/.git:
|
||||
|
||||
# CODE FOR PUBLISHING THE IMAGES
|
||||
|
||||
# Push plugin
|
||||
plugin_publish: $(PLUGIN_UPTODATE)
|
||||
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker plugin push $(PLUGIN_IMAGE):$(WEAVE_VERSION)
|
||||
# "$(NET_PLUGIN_LATEST)" means "stable release" here, so only push that if explicitly told to
|
||||
ifeq ($(UPDATE_LATEST),true)
|
||||
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker plugin push $(PLUGIN_IMAGE):$(NET_PLUGIN_LATEST)
|
||||
endif
|
||||
|
||||
# This target first runs "make publish" for each architecture
|
||||
# Then it pushes the manifest lists
|
||||
publish: $(addprefix sub-publish-,$(ALL_ARCHITECTURES)) $(WEAVEDB_UPTODATE)
|
||||
@@ -344,13 +376,16 @@ ifneq ($(UPDATE_LATEST),false)
|
||||
$(MANIFEST_TOOL_EXE) push from-args --platforms $(ML_PLATFORMS) --template $(DOCKERHUB_USER)/$*-ARCH:latest --target $(DOCKERHUB_USER)/$*:latest
|
||||
endif
|
||||
|
||||
clean-work-dir:
|
||||
rm -rf $(PLUGIN_WORK_DIR)
|
||||
|
||||
clean-bin:
|
||||
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(IMAGES)
|
||||
find prog -type f -name "Dockerfile.*" -not -name "Dockerfile.template" -print | xargs rm -f
|
||||
find prog -type f -name "*qemu-*" -print | xargs rm -f
|
||||
rm -rf $(EXES) $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE) weave*.tar.gz $(DOCKER_DISTRIB) prog/weaveexec/docker .pkg
|
||||
|
||||
clean: clean-bin
|
||||
clean: clean-bin clean-work-dir
|
||||
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(BUILD_IMAGE)
|
||||
rm -rf test/tls/*.pem test/coverage.* test/coverage $(BUILD_UPTODATE) $(MANIFEST_TOOL_EXE)
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[](https://circleci.com/gh/weaveworks/weave)
|
||||
[](https://coveralls.io/r/weaveworks/weave)
|
||||
[](https://goreportcard.com/report/github.com/weaveworks/weave)
|
||||
[](https://slack.weave.works)
|
||||
[](https://hub.docker.com/r/weaveworks/weave/)
|
||||
|
||||
# About Weaveworks
|
||||
@@ -13,7 +12,9 @@ Docker containers.
|
||||
|
||||
This repository contains [Weave Net](https://www.weave.works/products/weave-net/), the first product developed by Weaveworks, and with over 8 million downloads to date, it enables you to get started with Docker clusters and portable apps in a fraction of the time compared with other solutions.
|
||||
|
||||
Weaveworks' product [Weave Cloud](https://www.weave.works/solution/cloud/) takes the heavy lifting out of building, integrating and operating open source components, so you don’t have to manage databases, storage and availability.
|
||||
## Weave Cloud:
|
||||
|
||||
[Weave Cloud](https://www.weave.works/product/cloud/) is software-as-a-service that simplifies deployment, monitoring and management for containers and microservices. It extends and complements popular orchestrators, and enables developers and DevOps to realize faster deployments, insightful monitoring, visualization and networking.
|
||||
|
||||
Weave Cloud is built using these Open Source projects: [Weave Scope](https://www.weave.works/products/weave-scope/), a powerful container monitoring tool that automatically maps Docker containers and their interactions, [Weave Cortex](https://github.com/weaveworks/cortex), a horizontally-scalable version of Prometheus, and [Weave Flux](https://www.weave.works/products/weave-flux/), a continuous deployment tool that works with Kubernetes.
|
||||
|
||||
@@ -36,7 +37,7 @@ If you have any questions about, feedback for or a problem with Weave Net:
|
||||
|
||||
Your feedback is always welcome!
|
||||
|
||||
##Further Information
|
||||
## Further Information
|
||||
|
||||
* [Installing Weave Net](https://www.weave.works/docs/net/latest/installing-weave/)
|
||||
* [Weave Net Product Overview](https://www.weave.works/products/weave-net/)
|
||||
* [Weave Net Product Overview](https://www.weave.works/products/weave-net/)
|
||||
+19
-10
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// Special token used in place of a container identifier when:
|
||||
@@ -14,21 +15,29 @@ import (
|
||||
// which should be kept in mind if the entry needs to be removed at any point.
|
||||
const NoContainerID string = "_"
|
||||
|
||||
func (client *Client) ipamOp(ID string, op string) (*net.IPNet, error) {
|
||||
ip, err := client.httpVerb(op, fmt.Sprintf("/ip/%s", ID), nil)
|
||||
func (client *Client) ipamOp(ID string, op string, values url.Values) (*net.IPNet, error) {
|
||||
ip, err := client.httpVerb(op, fmt.Sprintf("/ip/%s", ID), values)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parseIP(ip)
|
||||
}
|
||||
|
||||
// returns an IP for the ID given, allocating a fresh one if necessary
|
||||
func (client *Client) AllocateIP(ID string) (*net.IPNet, error) {
|
||||
return client.ipamOp(ID, "POST")
|
||||
func ipamValues(checkAlive bool) url.Values {
|
||||
values := make(url.Values)
|
||||
if checkAlive {
|
||||
values.Set("check-alive", "true")
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
func (client *Client) AllocateIPInSubnet(ID string, subnet *net.IPNet) (*net.IPNet, error) {
|
||||
ip, err := client.httpVerb("POST", fmt.Sprintf("/ip/%s/%s", ID, subnet), nil)
|
||||
// returns an IP for the ID given, allocating a fresh one if necessary
|
||||
func (client *Client) AllocateIP(ID string, checkAlive bool) (*net.IPNet, error) {
|
||||
return client.ipamOp(ID, "POST", ipamValues(checkAlive))
|
||||
}
|
||||
|
||||
func (client *Client) AllocateIPInSubnet(ID string, subnet *net.IPNet, checkAlive bool) (*net.IPNet, error) {
|
||||
ip, err := client.httpVerb("POST", fmt.Sprintf("/ip/%s/%s", ID, subnet), ipamValues(checkAlive))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -38,12 +47,12 @@ func (client *Client) AllocateIPInSubnet(ID string, subnet *net.IPNet) (*net.IPN
|
||||
// returns an IP for the ID given, or nil if one has not been
|
||||
// allocated
|
||||
func (client *Client) LookupIP(ID string) (*net.IPNet, error) {
|
||||
return client.ipamOp(ID, "GET")
|
||||
return client.ipamOp(ID, "GET", nil)
|
||||
}
|
||||
|
||||
// Claim a specific IP on behalf of the ID
|
||||
func (client *Client) ClaimIP(ID string, cidr *net.IPNet) error {
|
||||
_, err := client.httpVerb("PUT", fmt.Sprintf("/ip/%s/%s", ID, cidr), nil)
|
||||
func (client *Client) ClaimIP(ID string, cidr *net.IPNet, checkAlive bool) error {
|
||||
_, err := client.httpVerb("PUT", fmt.Sprintf("/ip/%s/%s", ID, cidr), ipamValues(checkAlive))
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -76,6 +77,22 @@ func (client *Client) Connect(remote string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// IsReady returns true if the API server is up and running
|
||||
// (note it returns StatusServiceUnavailable until all parts are ready,
|
||||
// but callers of this function are expected to be ok with a partial service)
|
||||
func (client *Client) IsReady() bool {
|
||||
resp, err := http.Get(client.baseURL + "/status")
|
||||
return err == nil &&
|
||||
(resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusServiceUnavailable)
|
||||
}
|
||||
|
||||
// WaitAPIServer waits until the API server is ready to serve.
|
||||
func (client *Client) WaitAPIServer(n int) {
|
||||
for i := 0; i < n && !client.IsReady(); i++ {
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
type Logger interface {
|
||||
Infof(string, ...interface{})
|
||||
Debugf(string, ...interface{})
|
||||
|
||||
+2
-2
@@ -41,7 +41,7 @@ case "$1" in
|
||||
for i in $(seq $START $FINISH); do
|
||||
IP=$SUBNET.$i
|
||||
sudo ip addr add $IP/24 dev multiweave
|
||||
weave $i launch-router --datapath '' --iface '' --no-dns --host $IP \
|
||||
weave $i launch --datapath '' --iface '' --no-dns --host $IP \
|
||||
--name $(random_mac) --nickname weave$i "$@"
|
||||
done
|
||||
echo $(date -R) connecting
|
||||
@@ -57,7 +57,7 @@ case "$1" in
|
||||
for i in $(seq $FINISH -1 $START); do
|
||||
IP=$SUBNET.$i
|
||||
echo Stopping weave$i
|
||||
weave $i stop-router
|
||||
weave $i stop
|
||||
sudo ip addr del $IP/24 dev multiweave || true
|
||||
done
|
||||
[ -z "$(ip -4 -o addr show multiweave)" ] && sudo ip link del multiweave
|
||||
|
||||
@@ -187,6 +187,10 @@ publish() {
|
||||
fi
|
||||
|
||||
if [ "$RELEASE_TYPE" = 'PRERELEASE' ] ; then
|
||||
echo "== Building and pushing plugin"
|
||||
make UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER plugin_publish
|
||||
echo "** Plugin built and pushed"
|
||||
|
||||
echo "== Tagging and pushing images on docker hub as user $DOCKERHUB_USER"
|
||||
make UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER publish
|
||||
echo "** Docker images tagged and pushed"
|
||||
@@ -219,6 +223,10 @@ publish() {
|
||||
fi
|
||||
echo '** Sanity checks OK for publishing tag' $LATEST_TAG as $DOCKERHUB_USER/weave:$VERSION
|
||||
|
||||
echo "== Building and pushing plugin"
|
||||
make UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER plugin_publish
|
||||
echo "** Plugin built and pushed"
|
||||
|
||||
echo "== Tagging and pushing images on docker hub as user $DOCKERHUB_USER"
|
||||
make PUBLISH_WEAVEDB=$IS_MAINLINE UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER publish
|
||||
echo "** Docker images tagged and pushed"
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
FROM golang:1.7.4
|
||||
FROM golang:1.8.1
|
||||
|
||||
# Support Raspberry Pi 2 and newer
|
||||
ENV GOARM 7
|
||||
|
||||
# The names of the architectures that we're fetching cross-compilers for from the Ubuntu packages
|
||||
# The names of the architectures that we're fetching cross-compilers for from the Debian packages
|
||||
ENV DEB_CROSSPLATFORMS \
|
||||
armhf \
|
||||
arm64
|
||||
@@ -18,7 +18,7 @@ ENV GCC_CROSSCOMPILERS \
|
||||
arm-linux-gnueabihf \
|
||||
aarch64-linux-gnu
|
||||
|
||||
# Temporarily add the Ubuntu repositories, because we're going to install gcc cross-compilers from there
|
||||
# Temporarily add the Debian repositories, because we're going to install gcc cross-compilers from there
|
||||
# Install the build-essential and crossbuild-essential-ARCH packages
|
||||
RUN echo "deb http://emdebian.org/tools/debian/ jessie main" > /etc/apt/sources.list.d/cgocrosscompiling.list \
|
||||
&& curl http://emdebian.org/tools/debian/emdebian-toolchain-archive.key | apt-key add - \
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
## Community Code of Conduct
|
||||
|
||||
Weaveworks follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior
|
||||
may be reported by contacting a Weaveworks project maintainer, or
|
||||
Alexis Richardson alexis@weave.works.
|
||||
+38
-2
@@ -165,13 +165,25 @@ func (pending pendingStarts) finish(id string) {
|
||||
}
|
||||
}
|
||||
|
||||
// AllContainerIDs returns all the IDs of Docker containers,
|
||||
// whether they are running or not.
|
||||
func (c *Client) AllContainerIDs() ([]string, error) {
|
||||
all, err := c.ListContainers(docker.ListContainersOptions{All: true})
|
||||
return c.containerIDs(true)
|
||||
}
|
||||
|
||||
// RunningContainerIDs returns all the IDs of the running
|
||||
// Docker containers.
|
||||
func (c *Client) RunningContainerIDs() ([]string, error) {
|
||||
return c.containerIDs(false)
|
||||
}
|
||||
|
||||
func (c *Client) containerIDs(all bool) ([]string, error) {
|
||||
containers, err := c.ListContainers(docker.ListContainersOptions{All: all})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ids []string
|
||||
for _, c := range all {
|
||||
for _, c := range containers {
|
||||
ids = append(ids, c.ID)
|
||||
}
|
||||
return ids, nil
|
||||
@@ -213,6 +225,30 @@ func (c *Client) GetContainerIP(nameOrID string) (string, error) {
|
||||
return info.NetworkSettings.IPAddress, nil
|
||||
}
|
||||
|
||||
func (c *Client) EnsureNetwork(networkName, driver, subnet string, options map[string]interface{}) error {
|
||||
_, err := c.CreateNetwork(
|
||||
docker.CreateNetworkOptions{
|
||||
Name: networkName,
|
||||
CheckDuplicate: true,
|
||||
Driver: driver,
|
||||
IPAM: docker.IPAMOptions{
|
||||
Driver: driver,
|
||||
Config: []docker.IPAMConfig{{Subnet: subnet}},
|
||||
},
|
||||
Options: options,
|
||||
})
|
||||
if err != docker.ErrNetworkAlreadyExists && err != nil {
|
||||
// Despite appearances to the contrary, CreateNetwork does
|
||||
// sometimes(always?) *not* return ErrNetworkAlreadyExists
|
||||
// when the network already exists. Hence we need to check for
|
||||
// this explicitly.
|
||||
if _, err2 := c.NetworkInfo(networkName); err2 != nil {
|
||||
return fmt.Errorf("unable to create network: %s", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// logging
|
||||
|
||||
func (c *Client) errorf(fmt string, args ...interface{}) {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
type WaitGroup struct {
|
||||
wg sync.WaitGroup
|
||||
count int32
|
||||
}
|
||||
|
||||
// Increase the count of things waiting and return a closure which calls Done
|
||||
func (w *WaitGroup) Add() func() {
|
||||
atomic.AddInt32(&w.count, 1)
|
||||
w.wg.Add(1)
|
||||
return func() {
|
||||
w.wg.Done()
|
||||
atomic.AddInt32(&w.count, -1)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WaitGroup) IsDone() bool {
|
||||
return atomic.LoadInt32(&w.count) == 0
|
||||
}
|
||||
+9
-3
@@ -26,10 +26,15 @@ var (
|
||||
|
||||
const (
|
||||
NameIdent = "peername"
|
||||
FileName = "data.db"
|
||||
fileName = "data.db"
|
||||
)
|
||||
|
||||
func NewBoltDB(dbPathname string) (*BoltDB, error) {
|
||||
func Pathname(dbPrefix string) string {
|
||||
return dbPrefix + fileName
|
||||
}
|
||||
|
||||
func NewBoltDB(dbPrefix string) (*BoltDB, error) {
|
||||
dbPathname := Pathname(dbPrefix)
|
||||
db, err := bolt.Open(dbPathname, 0660, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[boltDB] Unable to open %s: %s", dbPathname, err)
|
||||
@@ -38,8 +43,9 @@ func NewBoltDB(dbPathname string) (*BoltDB, error) {
|
||||
return &BoltDB{db: db}, err
|
||||
}
|
||||
|
||||
func NewBoltDBReadOnly(dbPathname string) (*BoltDB, error) {
|
||||
func NewBoltDBReadOnly(dbPrefix string) (*BoltDB, error) {
|
||||
options := bolt.Options{Timeout: time.Millisecond * 50, ReadOnly: true}
|
||||
dbPathname := Pathname(dbPrefix)
|
||||
db, err := bolt.Open(dbPathname, 0660, &options)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[boltDB] Unable to open %s: %s", dbPathname, err)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# Weave Net Benchmarks
|
||||
|
||||
## 2017-02-16: Fast Datapath Encryption
|
||||
|
||||
Results: https://www.weave.works/weave-net-performance-fast-datapath/
|
||||
|
||||
* Two `c3.8xlarge` instances running Ubuntu 16.04 LTS (`ami-d8f4deab`) in
|
||||
`eu-west-1` region of AWS.
|
||||
* 10 Gigabit [Enhanced Networking](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enhanced-networking.html).
|
||||
* `iperf 3.0.11`.
|
||||
|
||||
### fastdp
|
||||
|
||||
* Encrypted:
|
||||
|
||||
```
|
||||
host1$ WEAVE_MTU=8916 weave launch --password=foobar
|
||||
host1$ docker $(weave config) run --rm -ti --name server networkstatic/iperf3 -s
|
||||
|
||||
host2$ WEAVE_MTU=8916 weave launch --password=foobar host1
|
||||
host2$ docker $(weave config) run --rm -ti networkstatic/iperf3 -c server
|
||||
```
|
||||
|
||||
* Non-encrypted:
|
||||
|
||||
```
|
||||
host1$ WEAVE_MTU=8950 weave launch
|
||||
host1$ docker $(weave config) run --rm -ti --name server networkstatic/iperf3 -s
|
||||
|
||||
host2$ WEAVE_MTU=8950 weave launch --password=foobar host1
|
||||
host2$ docker $(weave config) run --rm -ti networkstatic/iperf3 -c server
|
||||
```
|
||||
|
||||
### sleeve
|
||||
|
||||
* Encrypted:
|
||||
|
||||
```
|
||||
host1$ WEAVE_NO_FASTDP=1 weave launch --password=foobar
|
||||
host1$ docker $(weave config) run --rm -ti --name server networkstatic/iperf3 -s
|
||||
|
||||
host2$ WEAVE_NO_FASTDP=1 weave launch --password=foobar host1
|
||||
host2$ docker $(weave config) run --rm -ti networkstatic/iperf3 -c server
|
||||
```
|
||||
|
||||
* Non-encrypted:
|
||||
|
||||
```
|
||||
host1$ WEAVE_NO_FASTDP=1 weave launch
|
||||
host1$ docker $(weave config) run --rm -ti --name server networkstatic/iperf3 -s
|
||||
|
||||
host2$ WEAVE_NO_FASTDP=1 weave launch --password=foobar host1
|
||||
host2$ docker $(weave config) run --rm -ti networkstatic/iperf3 -c server
|
||||
```
|
||||
|
||||
### host
|
||||
|
||||
* Non-encrypted:
|
||||
|
||||
```
|
||||
host1$ iperf -s
|
||||
host2$ iperf -c host1
|
||||
```
|
||||
|
||||
* Encrypted:
|
||||
|
||||
```
|
||||
host1$ export KEY1="0x466454f2b1a770f8f872f9afbc35ebeac57e00fc11ac86ed1f82716f010b20f0cf532274"
|
||||
host1$ export KEY2="0x3531151241a770f8f872f9afbc35ebeac57e00fc11ac86ed1f82716f010b20f0cf532274"
|
||||
host1# ip xfrm state add src ${IP1} dst ${IP2} proto esp spi 0x4c856ffc replay-window 256 flag esn reqid 0 mode transport aead 'rfc4106(gcm(aes))' ${KEY1} 128
|
||||
host1# ip xfrm state add src ${IP2} dst ${IP1} proto esp spi 0x9b0830bc replay-window 256 flag esn reqid 0 mode transport aead 'rfc4106(gcm(aes))' ${KEY2} 128
|
||||
host1# ip xfrm policy add src ${IP1}/32 dst ${IP2}/32 dir out tmpl src ${IP1} dst ${IP2} proto esp spi 0x4c856ffc reqid 0 mode transport
|
||||
host1$ iperf -s
|
||||
|
||||
host2$ export KEY1="0x466454f2b1a770f8f872f9afbc35ebeac57e00fc11ac86ed1f82716f010b20f0cf532274"
|
||||
host2$ export KEY2="0x3531151241a770f8f872f9afbc35ebeac57e00fc11ac86ed1f82716f010b20f0cf532274"
|
||||
host2# ip xfrm state add src ${IP2} dst ${IP1} proto esp spi 0x9b0830bc reqid 0 replay-window 256 flag esn mode transport aead 'rfc4106(gcm(aes))' ${KEY2} 128
|
||||
host2# ip xfrm state add src ${IP1} dst ${IP2} proto esp spi 0x4c856ffc reqid 0 replay-window 256 flag esn mode transport aead 'rfc4106(gcm(aes))' ${KEY1} 128
|
||||
host2# ip xfrm policy add src ${IP2}/32 dst ${IP1}/32 dir out tmpl src ${IP1} dst ${IP2} proto esp spi 0x9b0830bc reqid 0 mode transport
|
||||
host2$ iperf -c host1
|
||||
```
|
||||
@@ -0,0 +1,70 @@
|
||||
# Entrypoints
|
||||
|
||||
This document describes the various ways that weave as a binary gets launched, and where and how it processes options.
|
||||
|
||||
The goal is to enable maintainers to modify functionality without having to reverse engineer the code to find all of the places you can start a weave binary and what it depends upon.
|
||||
|
||||
## Components
|
||||
### weaver
|
||||
|
||||
`weaver` is the primary binary: it sets up the weave bridge to which containers are attached, manages IP address allocation, serves DNS requests and does many more things.
|
||||
|
||||
Since version 2.0, `weaver` also bundles the Docker Plugin (legacy version) and Docker API Proxy which used to be shipped as separate containers.
|
||||
|
||||
### weaveutil
|
||||
weaveutil is a binary which provides a number of functions for managing an existing weave network. It gets information about the network, attaches and detaches containers, etc.
|
||||
|
||||
For the majority of interactions with an existing weave network, you will launch `weaveutil` in some manner or another.
|
||||
|
||||
Almost all options can be passed as `--option` to `weaveutil`. These options are created in `prog/weaveutil/main.go` with a table mapping each command to a dedicated golang function.
|
||||
|
||||
In addition to operating in normal mode, `weaveutil` has several additional operating modes. Before processing any commands, `weaveutil` checks the filename with which it was called.
|
||||
|
||||
* If it was `weave-ipam` it delegates responsibility to the `cniIPAM()` function in `prog/weaveutil/cni.go`, which, in turn, calls the standard CNI plugin function `cni.PluginMain()`, passing it weave's IPAM implementation from `plugin/ipam`.
|
||||
* If it was `weave-net` it delegates responsibility to the `cniNet()` function in `prog/weaveutil/cni.go`, which, in turn, calls the standard CNI plugin function `cni.PluginMain()`, passing it weave's net plugin implementation from `plugin/net`.
|
||||
|
||||
Finally, `weaveutil` is called by `weaver` when it needs to operate in a different network namespace.
|
||||
Go programs cannot safely switch namespaces; see this [issue](http://github.com/vishvananda/netns/issues/17).
|
||||
The call chain is `weaver`->`nsenter`->`weaveutil`.
|
||||
|
||||
### weave
|
||||
Wrapping `weaver` and `weaveutil` is `weave`, a `sh` script that provides help information and calls `weaveutil` as relevant.
|
||||
|
||||
### weave-kube
|
||||
weave-kube is an image with the weave binaries and a wrapper script installed. It is responsible for:
|
||||
|
||||
1. Setting up the weave network
|
||||
2. Connecting to peers
|
||||
3. Copy the weave CNI-compatible binary plugin `weaveutil` to `/opt/cni/bin/weave-net` and weave config in `/etc/cni/net.d/10-weave.conf`
|
||||
4. Running the weave network policy controller (weave-npc) to implement kubernetes' `NetworkPolicy`
|
||||
|
||||
Once installation is complete, each network-relevant change in a container leads `kubelet` to:
|
||||
|
||||
1. Set certain environment variables to configure the CNI plugin, mostly related to the container ID
|
||||
2. Launch `/opt/cni/bin/weave-net`
|
||||
3. Pass the CNI config - the contents of `/etc/cni/net.d/10-weave.conf` to `weave-net`
|
||||
|
||||
Thus, when each container is changed, and `kubelet` calls weave as a CNI plugin, it really just is launching `weaveutil` as `weave-net`.
|
||||
|
||||
The installation and setup of all of the above - and therefore the entrypoint to the weave-kube image - is the script `prog/weave-kube/launch.sh`. `launch.sh` does the following:
|
||||
|
||||
1. Read configuration variables from the environment. When the documentation for `weave-kube` describes configuring the weave network by changing the environment variables in the daemonset in the `.yml` file, `launch.sh` reads these environment variables.
|
||||
2. Set up the config file at `/etc/cni/net.d/10-weave.conf`
|
||||
3. Run the `weave` initialization script
|
||||
4. Run `weaver` with the correct configuration passed as command-line options
|
||||
|
||||
|
||||
## Adding Options
|
||||
To add new options to how weave should run with each invocation, you would do the following:
|
||||
|
||||
1. determine to which `weave` command you want to add the option(s). `weave` normally is launched as `weave <command> <options> ...`.
|
||||
2. Add the option to `weave` script help for each `weave` command you wish to make it available. As of this writing, all of the commands and their options are listed in the function `usage_no_exist()`.
|
||||
3. Add the option to `weave` script option processing for the `weave` command, under the `case $COMMAND in` in the main `weave` script.
|
||||
4. In the function for the `weave` command, determine if the command should be passed on to `weaveutil` or `weaver`. Pass the option on to `weaveutil` or `weaver`, as appropriate, in the format `--option`, in the function for the `weave` command.
|
||||
5. Add a command-line option `--option` to `weaveutil` or `weaver` as appropriate.
|
||||
6. If the option can be configured for CNI:
|
||||
* have `prog/weave-kube/launch.sh` read it as an environment variable and set inside
|
||||
* set a default for the environment variable in `prog/weave-kube/weave-daemonset-k8s-1.6.yaml` and `weave-daemonset.yaml`
|
||||
* if it should be set via `weaver` globally on its one-time initialization invocation, pass it on in `launch.sh`
|
||||
* if it needs to be set via `weaveutil` on each invocation of `weave-net`, have `launch.sh` save it as an option in the CNI config file `/etc/cni/net.d/10-weave.conf` and then have the CNI code in `plugin/net/cni.go` in `weaveutil` read it and use where appropriate
|
||||
7. Document it!
|
||||
@@ -4,8 +4,7 @@
|
||||
* Up-to-date versions of `git`, `go` etc
|
||||
* Install GitHub release tool `go get github.com/weaveworks/github-release`
|
||||
* Create a [github token for
|
||||
github-release](https://help.github.com/articles/creating-an-access-token-for-command-line-use/);
|
||||
set and export `$GITHUB_TOKEN` with this value
|
||||
github-release](https://help.github.com/articles/creating-an-access-token-for-command-line-use/); select the `repo` OAuth scope; set and export `$GITHUB_TOKEN` with this value
|
||||
|
||||
## Release Types
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/weaveworks/weave/api"
|
||||
"github.com/weaveworks/weave/common"
|
||||
"github.com/weaveworks/weave/net/address"
|
||||
"github.com/weaveworks/weave/testing/gossip"
|
||||
@@ -30,6 +31,10 @@ func (alloc *Allocator) SimplyClaim(ident string, cidr address.CIDR) error {
|
||||
return alloc.Claim(ident, cidr, true, true, returnFalse)
|
||||
}
|
||||
|
||||
func (alloc *Allocator) AnonymousClaim(cidr address.CIDR) error {
|
||||
return alloc.Claim(api.NoContainerID, cidr, false, true, returnFalse)
|
||||
}
|
||||
|
||||
func TestAllocFree(t *testing.T) {
|
||||
const (
|
||||
container1 = "abcdef"
|
||||
@@ -170,6 +175,8 @@ func TestAllocatorClaim(t *testing.T) {
|
||||
universe = "10.0.3.0/24"
|
||||
testAddr1 = "10.0.3.5/24"
|
||||
testAddr2 = "10.0.4.2/24"
|
||||
testAddr4 = "10.0.2.3/23"
|
||||
subnet4 = "10.0.2.0/23"
|
||||
testPre = "10.0.3.1/24"
|
||||
)
|
||||
|
||||
@@ -203,6 +210,9 @@ func TestAllocatorClaim(t *testing.T) {
|
||||
// claim for a different container should fail
|
||||
err = alloc.SimplyClaim(container1, addr1)
|
||||
require.Error(t, err)
|
||||
// claim for an anonymous container, will assume it's the same one
|
||||
err = alloc.AnonymousClaim(addr1)
|
||||
require.NoError(t, err)
|
||||
// claiming the address allocated on the other peer should fail
|
||||
err = alloc.SimplyClaim(container1, address.MakeCIDR(subnet, addrx))
|
||||
require.Error(t, err, "claiming address allocated on other peer should fail")
|
||||
@@ -215,6 +225,15 @@ func TestAllocatorClaim(t *testing.T) {
|
||||
addr2, _ := address.ParseCIDR(testAddr2)
|
||||
err = alloc.SimplyClaim(container1, addr2)
|
||||
require.NoError(t, err)
|
||||
err = alloc.SimplyClaim(container3, addr2)
|
||||
require.Error(t, err)
|
||||
// Anonymous claim outside of our universe
|
||||
addr4, _ := address.ParseCIDR(testAddr4)
|
||||
subnet4cidr, _ := address.ParseCIDR(subnet4)
|
||||
require.NoError(t, alloc.AnonymousClaim(addr4))
|
||||
addr5, err := alloc.Allocate(api.NoContainerID, subnet4cidr, false, returnFalse)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, addr4.Start(), addr5)
|
||||
}
|
||||
|
||||
func (alloc *Allocator) pause() func() {
|
||||
|
||||
+22
-7
@@ -40,10 +40,29 @@ func (c *claim) Try(alloc *Allocator) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
addOwned := func() {
|
||||
if c.ident == api.NoContainerID {
|
||||
alloc.addOwned(c.cidr.Addr.String(), c.cidr, c.isContainer)
|
||||
} else {
|
||||
alloc.addOwned(c.ident, c.cidr, c.isContainer)
|
||||
}
|
||||
}
|
||||
|
||||
if !alloc.ring.Contains(c.cidr.Addr) {
|
||||
// Address not within our universe; assume user knows what they are doing
|
||||
alloc.infof("Address %s claimed by %s - not in our range", c.cidr, c.ident)
|
||||
alloc.addOwned(c.ident, c.cidr, c.isContainer)
|
||||
previousOwner := alloc.findOwner(c.cidr.Addr)
|
||||
switch {
|
||||
case previousOwner == "":
|
||||
addOwned()
|
||||
case previousOwner == c.ident: // already owned by this ID
|
||||
case c.ident == api.NoContainerID: // already owned by anonymous container
|
||||
// do nothing (no automatic fall-through in Go)
|
||||
case !alloc.dead[previousOwner].IsZero(): // already owned by dead container
|
||||
alloc.removeOwned(previousOwner, c.cidr.Addr)
|
||||
addOwned()
|
||||
default:
|
||||
c.sendResult(fmt.Errorf("address %s already in use by %s", c.cidr, previousOwner))
|
||||
}
|
||||
c.sendResult(nil)
|
||||
return true
|
||||
}
|
||||
@@ -85,11 +104,7 @@ func (c *claim) Try(alloc *Allocator) bool {
|
||||
// Unused address, we try to claim it:
|
||||
if err := alloc.space.Claim(c.cidr.Addr); err == nil {
|
||||
alloc.debugln("Claimed", c.cidr, "for", c.ident)
|
||||
if c.ident == api.NoContainerID {
|
||||
alloc.addOwned(c.cidr.Addr.String(), c.cidr, c.isContainer)
|
||||
} else {
|
||||
alloc.addOwned(c.ident, c.cidr, c.isContainer)
|
||||
}
|
||||
addOwned()
|
||||
c.sendResult(nil)
|
||||
} else {
|
||||
c.sendResult(err)
|
||||
|
||||
+34
-11
@@ -1,6 +1,7 @@
|
||||
package ipam
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
@@ -127,6 +128,39 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
|
||||
writeAddresses(w, addrs)
|
||||
})
|
||||
|
||||
router.Methods("GET").Path("/ip").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
type mapping struct {
|
||||
ContainerID string `json:"containerid"`
|
||||
Addrs []string `json:"addrs"`
|
||||
}
|
||||
|
||||
type mappings struct {
|
||||
Owned []mapping `json:"owned"`
|
||||
}
|
||||
|
||||
resultChan := make(chan mappings)
|
||||
alloc.actionChan <- func() {
|
||||
ms := mappings{}
|
||||
for containerid, d := range alloc.owned {
|
||||
m := mapping{
|
||||
ContainerID: containerid,
|
||||
Addrs: []string{},
|
||||
}
|
||||
for _, addr := range d.Cidrs {
|
||||
m.Addrs = append(m.Addrs, addr.String())
|
||||
}
|
||||
ms.Owned = append(ms.Owned, m)
|
||||
}
|
||||
resultChan <- ms
|
||||
}
|
||||
ms := <-resultChan
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(ms); err != nil {
|
||||
common.Log.Warningln("[allocator]:", err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
router.Methods("POST").Path("/ip/{id}/{ip}/{prefixlen}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
if subnet, ok := parseCIDR(w, vars["ip"]+"/"+vars["prefixlen"], true); ok {
|
||||
@@ -164,17 +198,6 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
|
||||
w.WriteHeader(204)
|
||||
})
|
||||
|
||||
router.Methods("DELETE").Path("/peer").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
alloc.Shutdown()
|
||||
w.WriteHeader(204)
|
||||
})
|
||||
|
||||
router.Methods("DELETE").Path("/peer/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ident := mux.Vars(r)["id"]
|
||||
transferred := alloc.AdminTakeoverRanges(ident)
|
||||
fmt.Fprintf(w, "%d IPs taken over from %s\n", transferred, ident)
|
||||
})
|
||||
|
||||
router.Methods("GET").Path("/ipinfo/tracker").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, tracker)
|
||||
})
|
||||
|
||||
@@ -30,7 +30,6 @@ import (
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
"github.com/weaveworks/weave/common"
|
||||
wnet "github.com/weaveworks/weave/net"
|
||||
"github.com/weaveworks/weave/net/address"
|
||||
)
|
||||
|
||||
@@ -42,7 +41,7 @@ type AWSVPCTracker struct {
|
||||
}
|
||||
|
||||
// NewAWSVPCTracker creates and initialises AWS VPC based tracker.
|
||||
func NewAWSVPCTracker() (*AWSVPCTracker, error) {
|
||||
func NewAWSVPCTracker(bridgeName string) (*AWSVPCTracker, error) {
|
||||
var (
|
||||
err error
|
||||
session = session.New()
|
||||
@@ -69,9 +68,9 @@ func NewAWSVPCTracker() (*AWSVPCTracker, error) {
|
||||
t.routeTableID = *routeTableID
|
||||
|
||||
// Detect Weave bridge link index
|
||||
link, err := netlink.LinkByName(wnet.WeaveBridgeName)
|
||||
link, err := netlink.LinkByName(bridgeName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot find \"%s\" interface: %s", wnet.WeaveBridgeName, err)
|
||||
return nil, fmt.Errorf("cannot find \"%s\" interface: %s", bridgeName, err)
|
||||
}
|
||||
t.linkIndex = link.Attrs().Index
|
||||
|
||||
|
||||
+3
-8
@@ -27,7 +27,7 @@ func (n *Nameserver) HandleHTTP(router *mux.Router, dockerCli *docker.Client) {
|
||||
vars = mux.Vars(r)
|
||||
container = vars["container"]
|
||||
ipStr = vars["ip"]
|
||||
hostname = dns.Fqdn(r.FormValue("fqdn"))
|
||||
fqdn = r.FormValue("fqdn")
|
||||
ip, err = address.ParseIP(ipStr)
|
||||
)
|
||||
if err != nil {
|
||||
@@ -35,16 +35,11 @@ func (n *Nameserver) HandleHTTP(router *mux.Router, dockerCli *docker.Client) {
|
||||
return
|
||||
}
|
||||
|
||||
if !dns.IsSubDomain(n.domain, hostname) {
|
||||
n.infof("Ignoring registration %s %s %s (not a subdomain of %s)", hostname, ipStr, container, n.domain)
|
||||
return
|
||||
}
|
||||
|
||||
n.AddEntry(hostname, container, n.ourName, ip)
|
||||
n.AddEntryFQDN(fqdn, container, n.ourName, ip)
|
||||
|
||||
if r.FormValue("check-alive") == "true" && dockerCli != nil && dockerCli.IsContainerNotRunning(container) {
|
||||
n.infof("container '%s' is not running: removing", container)
|
||||
n.Delete(hostname, container, ipStr, ip)
|
||||
n.Delete(dns.Fqdn(fqdn), container, ipStr, ip)
|
||||
}
|
||||
|
||||
w.WriteHeader(204)
|
||||
|
||||
@@ -91,6 +91,15 @@ func (n *Nameserver) AddEntry(hostname, containerid string, origin mesh.PeerName
|
||||
n.broadcastEntries(entry)
|
||||
}
|
||||
|
||||
func (n *Nameserver) AddEntryFQDN(fqdn, containerid string, origin mesh.PeerName, addr address.Address) {
|
||||
hostname := dns.Fqdn(fqdn)
|
||||
if !dns.IsSubDomain(n.domain, hostname) {
|
||||
n.infof("Ignoring registration %s %s %s (not a subdomain of %s)", hostname, addr.String(), containerid, n.domain)
|
||||
return
|
||||
}
|
||||
n.AddEntry(hostname, containerid, origin, addr)
|
||||
}
|
||||
|
||||
func (n *Nameserver) Lookup(hostname string) []address.Address {
|
||||
n.RLock()
|
||||
defer n.RUnlock()
|
||||
|
||||
@@ -160,6 +160,11 @@ func (cidr CIDR) String() string {
|
||||
return fmt.Sprintf("%s/%d", cidr.Addr.String(), cidr.PrefixLen)
|
||||
}
|
||||
|
||||
func (cidr CIDR) IPNet() (r *net.IPNet) {
|
||||
mask := net.CIDRMask(cidr.PrefixLen, 8*net.IPv4len)
|
||||
return &net.IPNet{IP: cidr.Addr.IP4(), Mask: mask}
|
||||
}
|
||||
|
||||
// FromIP4 converts an ipv4 address to our integer address type
|
||||
func FromIP4(ip4 net.IP) (r Address) {
|
||||
for _, b := range ip4.To4() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package address
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
|
||||
@@ -67,3 +68,15 @@ func TestCIDRStartAndEnd(t *testing.T) {
|
||||
require.Equal(t, ip("10.0.0.0"), cidr.Start(), "")
|
||||
require.Equal(t, ip("10.0.1.0"), cidr.End(), "")
|
||||
}
|
||||
|
||||
func TestConversions(t *testing.T) {
|
||||
addrStr := "10.2.3.0"
|
||||
cidrStr := addrStr + "/24"
|
||||
addr := ip(addrStr)
|
||||
require.Equal(t, addr.String(), addrStr)
|
||||
require.Equal(t, addr.IP4(), net.ParseIP(addrStr).To4())
|
||||
cidr, _ := ParseCIDR(cidrStr)
|
||||
require.Equal(t, cidr.String(), cidrStr)
|
||||
_, ipnet, _ := net.ParseCIDR(cidrStr)
|
||||
require.Equal(t, cidr.IPNet(), ipnet)
|
||||
}
|
||||
+12
-9
@@ -1,27 +1,30 @@
|
||||
package net
|
||||
|
||||
import "fmt"
|
||||
import "io"
|
||||
import "os"
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Configure the ARP cache parameters for the given interface. This
|
||||
// makes containers react more quickly to a change in the MAC address
|
||||
// associated with an IP address.
|
||||
func ConfigureARPCache(name string) error {
|
||||
if err := sysctl(fmt.Sprintf("net/ipv4/neigh/%s/base_reachable_time", name), "5"); err != nil {
|
||||
func ConfigureARPCache(procPath, name string) error {
|
||||
if err := sysctl(procPath, fmt.Sprintf("net/ipv4/neigh/%s/base_reachable_time", name), "5"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := sysctl(fmt.Sprintf("net/ipv4/neigh/%s/delay_first_probe_time", name), "2"); err != nil {
|
||||
if err := sysctl(procPath, fmt.Sprintf("net/ipv4/neigh/%s/delay_first_probe_time", name), "2"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := sysctl(fmt.Sprintf("net/ipv4/neigh/%s/ucast_solicit", name), "1"); err != nil {
|
||||
if err := sysctl(procPath, fmt.Sprintf("net/ipv4/neigh/%s/ucast_solicit", name), "1"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sysctl(variable, value string) error {
|
||||
f, err := os.OpenFile(fmt.Sprintf("/proc/sys/%s", variable), os.O_WRONLY, 0)
|
||||
func sysctl(procPath, variable, value string) error {
|
||||
f, err := os.OpenFile(filepath.Join(procPath, "/sys/", variable), os.O_WRONLY, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+424
-13
@@ -2,43 +2,137 @@ package net
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/coreos/go-iptables/iptables"
|
||||
"github.com/j-keck/arping"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
"github.com/weaveworks/weave/common/odp"
|
||||
)
|
||||
|
||||
type BridgeType int
|
||||
/* This code implements three possible configurations to connect
|
||||
containers to the Weave Net overlay:
|
||||
|
||||
1. Bridge
|
||||
+-------+
|
||||
(container-veth)-+ weave +-(vethwe-bridge)--(vethwe-pcap)
|
||||
+-------+
|
||||
|
||||
"weave" is a Linux bridge. "vethwe-pcap" (end of veth pair) is used
|
||||
to capture and inject packets, by router/pcap.go.
|
||||
|
||||
2. BridgedFastdp
|
||||
|
||||
+-------+ /----------\
|
||||
(container-veth)-+ weave +-(vethwe-bridge)--(vethwe-datapath)-+ datapath +
|
||||
+-------+ \----------/
|
||||
|
||||
"weave" is a Linux bridge and "datapath" is an Open vSwitch datapath;
|
||||
they are connected via a veth pair. Packet capture and injection use
|
||||
the "datapath" device, via "router/fastdp.go:fastDatapathBridge"
|
||||
|
||||
3. Fastdp
|
||||
|
||||
/-------\
|
||||
(container-veth)-+ weave +
|
||||
\-------/
|
||||
|
||||
"weave" is an Open vSwitch datapath, and capture/injection are as in
|
||||
BridgedFastdp. Not used by default due to missing conntrack support in
|
||||
datapath of old kernel versions (https://github.com/weaveworks/weave/issues/1577).
|
||||
*/
|
||||
|
||||
const (
|
||||
WeaveBridgeName = "weave"
|
||||
DatapathName = "datapath"
|
||||
|
||||
None BridgeType = iota
|
||||
Bridge
|
||||
Fastdp
|
||||
BridgedFastdp
|
||||
Inconsistent
|
||||
DatapathIfName = "vethwe-datapath"
|
||||
BridgeIfName = "vethwe-bridge"
|
||||
PcapIfName = "vethwe-pcap"
|
||||
)
|
||||
|
||||
func DetectBridgeType(weaveBridgeName, datapathName string) BridgeType {
|
||||
type Bridge interface {
|
||||
init(config *BridgeConfig) error // create and initialise bridge device(s)
|
||||
attach(veth *netlink.Veth) error // attach veth to bridge
|
||||
IsFastdp() bool // does this bridge use fastdp?
|
||||
String() string // human-readable type string
|
||||
}
|
||||
|
||||
// Used to indicate a fallback to the Bridge type
|
||||
var errBridgeNotSupported = errors.New("bridge not supported")
|
||||
|
||||
type bridgeImpl struct{ bridge netlink.Link }
|
||||
type fastdpImpl struct{ datapathName string }
|
||||
type bridgedFastdpImpl struct {
|
||||
bridgeImpl
|
||||
fastdpImpl
|
||||
}
|
||||
|
||||
// Returns a string that is consistent with the weave script
|
||||
func (bridgeImpl) String() string { return "bridge" }
|
||||
func (fastdpImpl) String() string { return "fastdp" }
|
||||
func (bridgedFastdpImpl) String() string { return "bridged_fastdp" }
|
||||
|
||||
// Used to decide whether to manage ODP tunnels
|
||||
func (bridgeImpl) IsFastdp() bool { return false }
|
||||
func (fastdpImpl) IsFastdp() bool { return true }
|
||||
func (bridgedFastdpImpl) IsFastdp() bool { return true }
|
||||
|
||||
func ExistingBridgeType(weaveBridgeName, datapathName string) (Bridge, error) {
|
||||
bridge, _ := netlink.LinkByName(weaveBridgeName)
|
||||
datapath, _ := netlink.LinkByName(datapathName)
|
||||
|
||||
switch {
|
||||
case bridge == nil && datapath == nil:
|
||||
return None
|
||||
return nil, nil
|
||||
case isBridge(bridge) && datapath == nil:
|
||||
return Bridge
|
||||
return bridgeImpl{bridge: bridge}, nil
|
||||
case isDatapath(bridge) && datapath == nil:
|
||||
return Fastdp
|
||||
return fastdpImpl{datapathName: datapathName}, nil
|
||||
case isDatapath(datapath) && isBridge(bridge):
|
||||
return BridgedFastdp
|
||||
return bridgedFastdpImpl{bridgeImpl{bridge: bridge}, fastdpImpl{datapathName: datapathName}}, nil
|
||||
default:
|
||||
return Inconsistent
|
||||
return nil, errors.New("Inconsistent bridge state detected. Please do 'weave reset' and try again")
|
||||
}
|
||||
}
|
||||
|
||||
func EnforceAddrAssignType(bridgeName string) (setAddr bool, err error) {
|
||||
sysctlFilename := filepath.Join("/sys/class/net/", bridgeName, "/addr_assign_type")
|
||||
addrAssignType, err := ioutil.ReadFile(sysctlFilename)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "reading %q", sysctlFilename)
|
||||
}
|
||||
|
||||
// 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() */
|
||||
// Note the file typically has a newline at the end, so we just look at the first char
|
||||
if addrAssignType[0] != '3' {
|
||||
link, err := netlink.LinkByName(bridgeName)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "EnforceAddrAssignType finding bridge %s", bridgeName)
|
||||
}
|
||||
|
||||
mac, err := RandomMAC()
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "creating random MAC")
|
||||
}
|
||||
|
||||
if err := netlink.LinkSetHardwareAddr(link, mac); err != nil {
|
||||
return false, errors.Wrapf(err, "setting bridge %s address to %v", bridgeName, mac)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isBridge(link netlink.Link) bool {
|
||||
_, isBridge := link.(*netlink.Bridge)
|
||||
return isBridge
|
||||
@@ -108,3 +202,320 @@ func FindBridgeIP(bridgeName string, subnet *net.IPNet) (net.IP, error) {
|
||||
// No subnet, or none in the required subnet; just return the first one
|
||||
return netdev.CIDRs[0].IP, nil
|
||||
}
|
||||
|
||||
type BridgeConfig struct {
|
||||
DockerBridgeName string
|
||||
WeaveBridgeName string
|
||||
DatapathName string
|
||||
NoFastdp bool
|
||||
NoBridgedFastdp bool
|
||||
AWSVPC bool
|
||||
NPC bool
|
||||
MTU int
|
||||
Mac string
|
||||
Port int
|
||||
}
|
||||
|
||||
func (config *BridgeConfig) configuredBridgeType() Bridge {
|
||||
switch {
|
||||
case config.NoFastdp:
|
||||
return bridgeImpl{}
|
||||
case config.NoBridgedFastdp:
|
||||
return fastdpImpl{datapathName: config.WeaveBridgeName}
|
||||
default:
|
||||
return bridgedFastdpImpl{fastdpImpl: fastdpImpl{datapathName: config.DatapathName}}
|
||||
}
|
||||
}
|
||||
|
||||
func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger) (Bridge, error) {
|
||||
bridgeType, err := ExistingBridgeType(config.WeaveBridgeName, config.DatapathName)
|
||||
if bridgeType != nil || err != nil {
|
||||
return bridgeType, err
|
||||
}
|
||||
|
||||
bridgeType = config.configuredBridgeType()
|
||||
for {
|
||||
if err := bridgeType.init(config); err != nil {
|
||||
if errors.Cause(err) == errBridgeNotSupported {
|
||||
log.Warnf("Skipping bridge creation of %q due to: %s", bridgeType, err)
|
||||
bridgeType = bridgeImpl{}
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if err := configureIPTables(config); err != nil {
|
||||
return bridgeType, errors.Wrap(err, "configuring iptables")
|
||||
}
|
||||
|
||||
if config.AWSVPC {
|
||||
// Set proxy_arp on the bridge, so that it could accept packets destined
|
||||
// to containers within the same subnet but running on remote hosts.
|
||||
// Without it, exact routes on each container are required.
|
||||
if err := sysctl(procPath, "net/ipv4/conf/"+config.WeaveBridgeName+"/proxy_arp", "1"); err != nil {
|
||||
return bridgeType, errors.Wrap(err, "setting proxy_arp")
|
||||
}
|
||||
// Avoid delaying the first ARP request. Also, setting it to 0 avoids
|
||||
// placing the request into a bounded queue as it can be seen:
|
||||
// https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/net/ipv4/arp.c?id=refs/tags/v4.6.1#n819
|
||||
if err := sysctl(procPath, "net/ipv4/neigh/"+config.WeaveBridgeName+"/proxy_delay", "0"); err != nil {
|
||||
return bridgeType, errors.Wrap(err, "setting proxy_arp")
|
||||
}
|
||||
}
|
||||
|
||||
if err := linkSetUpByName(config.WeaveBridgeName); err != nil {
|
||||
return bridgeType, err
|
||||
}
|
||||
|
||||
if err := ConfigureARPCache(procPath, config.WeaveBridgeName); err != nil {
|
||||
return bridgeType, errors.Wrapf(err, "configuring ARP cache on bridge %q", config.WeaveBridgeName)
|
||||
}
|
||||
|
||||
return bridgeType, nil
|
||||
}
|
||||
|
||||
func (b bridgeImpl) initPrep(config *BridgeConfig) error {
|
||||
mac, err := net.ParseMAC(config.Mac)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "parsing bridge MAC %q", config.Mac)
|
||||
}
|
||||
|
||||
linkAttrs := netlink.NewLinkAttrs()
|
||||
linkAttrs.Name = config.WeaveBridgeName
|
||||
linkAttrs.HardwareAddr = mac
|
||||
if config.MTU == 0 {
|
||||
config.MTU = 65535
|
||||
}
|
||||
b.bridge = &netlink.Bridge{LinkAttrs: linkAttrs}
|
||||
if err = netlink.LinkAdd(b.bridge); err != nil {
|
||||
return errors.Wrapf(err, "creating bridge %q", config.WeaveBridgeName)
|
||||
}
|
||||
if err := netlink.LinkSetHardwareAddr(b.bridge, mac); err != nil {
|
||||
return errors.Wrapf(err, "setting bridge %q mac %v", config.WeaveBridgeName, mac)
|
||||
}
|
||||
// Attempting to set the bridge MTU to a high value directly
|
||||
// fails. Bridges take the lowest MTU of their interfaces. So
|
||||
// instead we create a temporary interface with the desired MTU,
|
||||
// attach that to the bridge, and then remove it again.
|
||||
dummy := &netlink.Dummy{LinkAttrs: netlink.NewLinkAttrs()}
|
||||
dummy.LinkAttrs.Name = "vethwedu"
|
||||
if err = netlink.LinkAdd(dummy); err != nil {
|
||||
return errors.Wrap(err, "creating dummy interface")
|
||||
}
|
||||
if err := netlink.LinkSetMTU(dummy, config.MTU); err != nil {
|
||||
return errors.Wrapf(err, "setting dummy interface mtu to %d", config.MTU)
|
||||
}
|
||||
if err := netlink.LinkSetMasterByIndex(dummy, b.bridge.Attrs().Index); err != nil {
|
||||
return errors.Wrap(err, "setting dummy interface master")
|
||||
}
|
||||
if err := netlink.LinkDel(dummy); err != nil {
|
||||
return errors.Wrap(err, "deleting dummy interface")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b bridgeImpl) init(config *BridgeConfig) error {
|
||||
if err := b.initPrep(config); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := CreateAndAttachVeth(BridgeIfName, PcapIfName, config.WeaveBridgeName, config.MTU, true, func(veth netlink.Link) error {
|
||||
return netlink.LinkSetUp(veth)
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "creating pcap veth pair")
|
||||
}
|
||||
if err := EthtoolTXOff(config.WeaveBridgeName); err != nil {
|
||||
return errors.Wrap(err, "setting tx off")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f fastdpImpl) init(config *BridgeConfig) error {
|
||||
odpSupported, err := odp.CreateDatapath(f.datapathName)
|
||||
if !odpSupported {
|
||||
msg := ""
|
||||
if err != nil {
|
||||
msg = err.Error()
|
||||
}
|
||||
return errors.Wrap(errBridgeNotSupported, msg)
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "creating datapath %q", f.datapathName)
|
||||
}
|
||||
datapath, err := netlink.LinkByName(f.datapathName)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "finding datapath %q", f.datapathName)
|
||||
}
|
||||
if config.MTU == 0 {
|
||||
/* GCE has the lowest underlay network MTU we're likely to encounter on
|
||||
a local network, at 1460 bytes. To get the overlay MTU from that we
|
||||
subtract 20 bytes for the outer IPv4 header, 8 bytes for the outer
|
||||
UDP header, 8 bytes for the vxlan header, and 14 bytes for the inner
|
||||
ethernet header. In addition, we subtract 34 bytes for the ESP overhead
|
||||
which is needed for the vxlan encryption. */
|
||||
config.MTU = 1376
|
||||
}
|
||||
if err := netlink.LinkSetMTU(datapath, config.MTU); err != nil {
|
||||
return errors.Wrapf(err, "setting datapath %q mtu %d", f.datapathName, config.MTU)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bf bridgedFastdpImpl) init(config *BridgeConfig) error {
|
||||
if err := bf.fastdpImpl.init(config); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := bf.bridgeImpl.initPrep(config); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := CreateAndAttachVeth(BridgeIfName, DatapathIfName, config.WeaveBridgeName, config.MTU, true, func(veth netlink.Link) error {
|
||||
if err := netlink.LinkSetUp(veth); err != nil {
|
||||
return errors.Wrapf(err, "setting link up on %q", veth.Attrs().Name)
|
||||
}
|
||||
if err := odp.AddDatapathInterface(bf.datapathName, veth.Attrs().Name); err != nil {
|
||||
return errors.Wrapf(err, "adding interface %q to datapath %q", veth.Attrs().Name, bf.datapathName)
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "creating bridged fastdp veth pair")
|
||||
}
|
||||
|
||||
if err := linkSetUpByName(bf.datapathName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b bridgeImpl) attach(veth *netlink.Veth) error {
|
||||
return netlink.LinkSetMasterByIndex(veth, b.bridge.Attrs().Index)
|
||||
}
|
||||
|
||||
func (bf bridgedFastdpImpl) attach(veth *netlink.Veth) error {
|
||||
return bf.bridgeImpl.attach(veth)
|
||||
}
|
||||
|
||||
func (f fastdpImpl) attach(veth *netlink.Veth) error {
|
||||
return odp.AddDatapathInterface(f.datapathName, veth.Attrs().Name)
|
||||
}
|
||||
|
||||
func configureIPTables(config *BridgeConfig) error {
|
||||
ipt, err := iptables.New()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "creating iptables object")
|
||||
}
|
||||
if config.DockerBridgeName != "" {
|
||||
if config.WeaveBridgeName != config.DockerBridgeName {
|
||||
err := ipt.Insert("filter", "FORWARD", 1, "-i", config.DockerBridgeName, "-o", config.WeaveBridgeName, "-j", "DROP")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
dockerBridgeIP, err := FindBridgeIP(config.DockerBridgeName, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// forbid traffic to the Weave port from other containers
|
||||
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.DockerBridgeName, "-p", "tcp", "--dst", dockerBridgeIP.String(), "--dport", fmt.Sprint(config.Port), "-j", "DROP"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.DockerBridgeName, "-p", "udp", "--dst", dockerBridgeIP.String(), "--dport", fmt.Sprint(config.Port), "-j", "DROP"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.DockerBridgeName, "-p", "udp", "--dst", dockerBridgeIP.String(), "--dport", fmt.Sprint(config.Port+1), "-j", "DROP"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// let DNS traffic to weaveDNS, since otherwise it might get blocked by the likes of UFW
|
||||
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.DockerBridgeName, "-p", "udp", "--dport", "53", "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.DockerBridgeName, "-p", "tcp", "--dport", "53", "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if config.NPC {
|
||||
// Steer traffic via the NPC
|
||||
_ = ipt.NewChain("filter", "WEAVE-NPC") // ignore error because it might already exist
|
||||
// If WEAVE-NPC chain doesn't exist then next line will fail
|
||||
if err = ipt.AppendUnique("filter", "FORWARD", "-o", config.WeaveBridgeName, "-j", "WEAVE-NPC"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ipt.AppendUnique("filter", "FORWARD", "-o", config.WeaveBridgeName, "-m", "state", "--state", "NEW", "-j", "NFLOG", "--nflog-group", "86"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ipt.AppendUnique("filter", "FORWARD", "-o", config.WeaveBridgeName, "-j", "DROP"); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Work around the situation where there are no rules allowing traffic
|
||||
// across our bridge. E.g. ufw
|
||||
if err = ipt.AppendUnique("filter", "FORWARD", "-i", config.WeaveBridgeName, "-o", config.WeaveBridgeName, "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Forward from weave to the rest of the world
|
||||
if err = ipt.AppendUnique("filter", "FORWARD", "-i", config.WeaveBridgeName, "!", "-o", config.WeaveBridgeName, "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
// and allow replies back
|
||||
if err = ipt.AppendUnique("filter", "FORWARD", "-o", config.WeaveBridgeName, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create a chain for masquerading
|
||||
if err = ipt.ClearChain("nat", "WEAVE"); err != nil {
|
||||
return errors.Wrap(err, "clearing WEAVE chain")
|
||||
}
|
||||
if err = ipt.AppendUnique("nat", "POSTROUTING", "-j", "WEAVE"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func linkSetUpByName(linkName string) error {
|
||||
link, err := netlink.LinkByName(linkName)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "setting link up on %q", linkName)
|
||||
}
|
||||
return netlink.LinkSetUp(link)
|
||||
}
|
||||
|
||||
func AddBridgeAddr(bridgeName string, addr *net.IPNet, removeDefaultRoute bool) error {
|
||||
link, err := netlink.LinkByName(bridgeName)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "AddBridgeAddr finding bridge %q", bridgeName)
|
||||
}
|
||||
newAddresses, err := AddAddresses(link, []*net.IPNet{addr})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "adding address %v to %q", addr, bridgeName)
|
||||
}
|
||||
for _, ipnet := range newAddresses {
|
||||
arping.GratuitousArpOverIfaceByName(ipnet.IP, bridgeName)
|
||||
}
|
||||
if removeDefaultRoute {
|
||||
routeFilter := &netlink.Route{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Dst: &net.IPNet{IP: addr.IP.Mask(addr.Mask), Mask: addr.Mask},
|
||||
Protocol: 2, // RTPROT_KERNEL
|
||||
}
|
||||
filterMask := netlink.RT_FILTER_OIF | netlink.RT_FILTER_DST | netlink.RT_FILTER_PROTOCOL
|
||||
routes, err := netlink.RouteListFiltered(netlink.FAMILY_V4, routeFilter, filterMask)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get route list for bridge %q", bridgeName)
|
||||
}
|
||||
for _, r := range routes {
|
||||
if err = netlink.RouteDel(&r); err != nil {
|
||||
return errors.Wrapf(err, "failed to delete default route %+v", r)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -82,3 +82,25 @@ func findInterface(ifaceName string) (iface *net.Interface, err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func LocalAddresses() ([]*net.IPNet, error) {
|
||||
links, err := netlink.LinkList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
retval := []*net.IPNet{}
|
||||
for _, link := range links {
|
||||
if _, isBridge := link.(*netlink.Bridge); isBridge || (link.Attrs().Flags&net.FlagLoopback) != 0 {
|
||||
continue
|
||||
}
|
||||
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
retval = append(retval, addr.IPNet)
|
||||
}
|
||||
}
|
||||
return retval, nil
|
||||
}
|
||||
+6
-1
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
@@ -80,5 +81,9 @@ func WithNetNSByPid(pid int, cmd string, args ...string) ([]byte, error) {
|
||||
}
|
||||
|
||||
func NSPathByPid(pid int) string {
|
||||
return fmt.Sprintf("/proc/%d/ns/net", pid)
|
||||
return NSPathByPidWithRoot("/", pid)
|
||||
}
|
||||
|
||||
func NSPathByPidWithRoot(root string, pid int) string {
|
||||
return filepath.Join(root, fmt.Sprintf("/proc/%d/ns/net", pid))
|
||||
}
|
||||
+4
-5
@@ -36,8 +36,8 @@ func getSystemUUID(hostRoot string) ([]byte, error) {
|
||||
return append(machineid, uuid...), nil
|
||||
}
|
||||
|
||||
func getPersistedPeerName(pathName string) (mesh.PeerName, error) {
|
||||
d, err := db.NewBoltDBReadOnly(pathName)
|
||||
func getPersistedPeerName(dbPrefix string) (mesh.PeerName, error) {
|
||||
d, err := db.NewBoltDBReadOnly(dbPrefix)
|
||||
if err != nil {
|
||||
return mesh.UnknownPeerName, err
|
||||
}
|
||||
@@ -56,9 +56,8 @@ func getPersistedPeerName(pathName string) (mesh.PeerName, error) {
|
||||
func GetSystemPeerName(dbPrefix, hostRoot string) (string, error) {
|
||||
// Check if we have a persisted name that matches the old-style ID for this host
|
||||
if oldUUID, err := getOldStyleSystemUUID(); err == nil {
|
||||
pathName := dbPrefix + db.FileName
|
||||
if _, err := os.Stat(pathName); err == nil {
|
||||
persistedPeerName, err := getPersistedPeerName(pathName)
|
||||
if _, err := os.Stat(db.Pathname(dbPrefix)); err == nil {
|
||||
persistedPeerName, err := getPersistedPeerName(dbPrefix)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
+83
-58
@@ -11,8 +11,6 @@ import (
|
||||
"github.com/j-keck/arping"
|
||||
"github.com/vishvananda/netlink"
|
||||
"github.com/vishvananda/netns"
|
||||
|
||||
"github.com/weaveworks/weave/common/odp"
|
||||
)
|
||||
|
||||
// create and attach a veth to the Weave bridge
|
||||
@@ -40,22 +38,17 @@ func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, keepTXOn bo
|
||||
return nil, fmt.Errorf(format, a...)
|
||||
}
|
||||
|
||||
switch bridgeType := DetectBridgeType(bridgeName, DatapathName); bridgeType {
|
||||
case Bridge, BridgedFastdp:
|
||||
if err := netlink.LinkSetMasterByIndex(veth, bridge.Attrs().Index); err != nil {
|
||||
return cleanup(`unable to set master of %s: %s`, name, err)
|
||||
bridgeType, err := ExistingBridgeType(bridgeName, DatapathName)
|
||||
if err != nil {
|
||||
return cleanup("detect bridge type: %s", err)
|
||||
}
|
||||
if err := bridgeType.attach(veth); err != nil {
|
||||
return cleanup("attaching veth %q to %q: %s", name, bridgeName, err)
|
||||
}
|
||||
if !bridgeType.IsFastdp() && !keepTXOn {
|
||||
if err := EthtoolTXOff(veth.PeerName); err != nil {
|
||||
return cleanup(`unable to set tx off on %q: %s`, peerName, err)
|
||||
}
|
||||
if bridgeType == Bridge && !keepTXOn {
|
||||
if err := EthtoolTXOff(peerName); err != nil {
|
||||
return cleanup(`unable to set tx off on %q: %s`, peerName, err)
|
||||
}
|
||||
}
|
||||
case Fastdp:
|
||||
if err := odp.AddDatapathInterface(bridgeName, name); err != nil {
|
||||
return cleanup(`failed to attach %s to device "%s": %s`, name, bridgeName, err)
|
||||
}
|
||||
default:
|
||||
return cleanup(`invalid bridge configuration`)
|
||||
}
|
||||
|
||||
if init != nil {
|
||||
@@ -111,8 +104,6 @@ func interfaceExistsInNamespace(netNSPath string, ifName string) bool {
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// NB: This function can be used only by a process that terminates immediately
|
||||
// after calling the function as it changes netns via WithNetNSLinkUnsafe.
|
||||
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool, hairpinMode bool) error {
|
||||
ns, err := netns.GetFromPath(netNSPath)
|
||||
if err != nil {
|
||||
@@ -120,11 +111,6 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
|
||||
}
|
||||
defer ns.Close()
|
||||
|
||||
ipt, err := iptables.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !interfaceExistsInNamespace(netNSPath, ifName) {
|
||||
maxIDLen := IFNAMSIZ - 1 - len(vethPrefix+"pl")
|
||||
if len(id) > maxIDLen {
|
||||
@@ -149,51 +135,90 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
|
||||
|
||||
}
|
||||
|
||||
if err := WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error {
|
||||
newAddresses, err := AddAddresses(veth, cidrs)
|
||||
args := []string{ifName, fmt.Sprintf("%t", withMulticastRoute)}
|
||||
for _, cidr := range cidrs {
|
||||
args = append(args, cidr.String())
|
||||
}
|
||||
if _, err := WithNetNS(netNSPath, "setup-iface-addrs", args...); err != nil {
|
||||
return fmt.Errorf("error setting up interface addresses: %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetupIfaceAddrs is the implementation of the 'setup-iface-addrs' call above,
|
||||
// running in another process in the container's netns
|
||||
func SetupIfaceAddrs(veth netlink.Link, withMulticastRoute bool, cidrs []*net.IPNet) error {
|
||||
newAddresses, err := AddAddresses(veth, cidrs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ifName := veth.Attrs().Name
|
||||
ipt, err := iptables.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add multicast ACCEPT rules for new subnets
|
||||
for _, ipnet := range newAddresses {
|
||||
acceptRule := []string{"-i", ifName, "-s", subnet(ipnet), "-d", "224.0.0.0/4", "-j", "ACCEPT"}
|
||||
exists, err := ipt.Exists("filter", "INPUT", acceptRule...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add multicast ACCEPT rules for new subnets
|
||||
for _, ipnet := range newAddresses {
|
||||
acceptRule := []string{"-i", ifName, "-s", subnet(ipnet), "-d", "224.0.0.0/4", "-j", "ACCEPT"}
|
||||
exists, err := ipt.Exists("filter", "INPUT", acceptRule...)
|
||||
if err != nil {
|
||||
if !exists {
|
||||
if err := ipt.Insert("filter", "INPUT", 1, acceptRule...); err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
if err := ipt.Insert("filter", "INPUT", 1, acceptRule...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := netlink.LinkSetUp(veth); err != nil {
|
||||
if err := netlink.LinkSetUp(veth); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, ipnet := range newAddresses {
|
||||
// If we don't wait for a bit here, we see the arp fail to reach the bridge.
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
arping.GratuitousArpOverIfaceByName(ipnet.IP, ifName)
|
||||
}
|
||||
if withMulticastRoute {
|
||||
/* Route multicast packets across the weave network.
|
||||
This must come last in 'attach'. If you change this, change weavewait to match.
|
||||
|
||||
TODO: Add the MTU lock to prevent PMTU discovery for multicast
|
||||
destinations. Without that, the kernel sets the DF flag on
|
||||
multicast packets. Since RFC1122 prohibits sending of ICMP
|
||||
errors for packets with multicast destinations, that causes
|
||||
packets larger than the PMTU to be dropped silently. */
|
||||
|
||||
_, multicast, _ := net.ParseCIDR("224.0.0.0/4")
|
||||
if err := AddRoute(veth, netlink.SCOPE_LINK, multicast, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, ipnet := range newAddresses {
|
||||
// If we don't wait for a bit here, we see the arp fail to reach the bridge.
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
arping.GratuitousArpOverIfaceByName(ipnet.IP, ifName)
|
||||
}
|
||||
if withMulticastRoute {
|
||||
/* Route multicast packets across the weave network.
|
||||
This must come last in 'attach'. If you change this, change weavewait to match.
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
TODO: Add the MTU lock to prevent PMTU discovery for multicast
|
||||
destinations. Without that, the kernel sets the DF flag on
|
||||
multicast packets. Since RFC1122 prohibits sending of ICMP
|
||||
errors for packets with multicast destinations, that causes
|
||||
packets larger than the PMTU to be dropped silently. */
|
||||
// SetupIface is the implementation of the 'setup-iface' call above,
|
||||
// running in another process in the container's netns
|
||||
func SetupIface(ifaceName, newIfName string) error {
|
||||
ipt, err := iptables.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, multicast, _ := net.ParseCIDR("224.0.0.0/4")
|
||||
if err := AddRoute(veth, netlink.SCOPE_LINK, multicast, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
link, err := netlink.LinkByName(ifaceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := netlink.LinkSetName(link, newIfName); err != nil {
|
||||
return err
|
||||
}
|
||||
// This is only called by AttachContainer which is only called in host pid namespace
|
||||
if err := ConfigureARPCache("/proc", newIfName); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ipt.Append("filter", "INPUT", "-i", newIfName, "-d", "224.0.0.0/4", "-j", "DROP"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
+1
-19
@@ -66,7 +66,7 @@ func (npc *controller) onNewNsSelector(selector *selector) error {
|
||||
func (npc *controller) withNS(name string, f func(ns *ns) error) error {
|
||||
ns, found := npc.nss[name]
|
||||
if !found {
|
||||
newNs, err := newNS(name, npc.ipt, npc.ips, npc.nsSelectors)
|
||||
newNs, err := newNS(name, npc.nodeName, npc.ipt, npc.ips, npc.nsSelectors)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -85,21 +85,10 @@ func (npc *controller) withNS(name string, f func(ns *ns) error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (npc *controller) checkLocalPod(obj *coreapi.Pod, event string) bool {
|
||||
if obj.Spec.NodeName != npc.nodeName {
|
||||
common.Log.Debugf("%s ignored for pod %s/%s on node %s", event, obj.ObjectMeta.Namespace, obj.ObjectMeta.Name, obj.Spec.NodeName)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (npc *controller) AddPod(obj *coreapi.Pod) error {
|
||||
npc.Lock()
|
||||
defer npc.Unlock()
|
||||
|
||||
if !npc.checkLocalPod(obj, "AddPod") {
|
||||
return nil
|
||||
}
|
||||
common.Log.Debugf("EVENT AddPod %s", js(obj))
|
||||
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||
return errors.Wrap(ns.addPod(obj), "add pod")
|
||||
@@ -110,10 +99,6 @@ func (npc *controller) UpdatePod(oldObj, newObj *coreapi.Pod) error {
|
||||
npc.Lock()
|
||||
defer npc.Unlock()
|
||||
|
||||
// Pods don't move across nodes so we only check the new version
|
||||
if !npc.checkLocalPod(newObj, "UpdatePod") {
|
||||
return nil
|
||||
}
|
||||
common.Log.Debugf("EVENT UpdatePod %s %s", js(oldObj), js(newObj))
|
||||
return npc.withNS(oldObj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||
return errors.Wrap(ns.updatePod(oldObj, newObj), "update pod")
|
||||
@@ -124,9 +109,6 @@ func (npc *controller) DeletePod(obj *coreapi.Pod) error {
|
||||
npc.Lock()
|
||||
defer npc.Unlock()
|
||||
|
||||
if !npc.checkLocalPod(obj, "DeletePod") {
|
||||
return nil
|
||||
}
|
||||
common.Log.Debugf("EVENT DeletePod %s", js(obj))
|
||||
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||
return errors.Wrap(ns.deletePod(obj), "delete pod")
|
||||
|
||||
+25
-5
@@ -19,6 +19,7 @@ type ns struct {
|
||||
ips ipset.Interface // interface to ipset
|
||||
|
||||
name string // k8s Namespace name
|
||||
nodeName string // my node name
|
||||
namespace *coreapi.Namespace // k8s Namespace object
|
||||
pods map[types.UID]*coreapi.Pod // k8s Pod objects by UID
|
||||
policies map[types.UID]*extnapi.NetworkPolicy // k8s NetworkPolicy objects by UID
|
||||
@@ -31,7 +32,7 @@ type ns struct {
|
||||
rules *ruleSet
|
||||
}
|
||||
|
||||
func newNS(name string, ipt *iptables.IPTables, ips ipset.Interface, nsSelectors *selectorSet) (*ns, error) {
|
||||
func newNS(name, nodeName string, ipt *iptables.IPTables, ips ipset.Interface, nsSelectors *selectorSet) (*ns, error) {
|
||||
allPods, err := newSelectorSpec(&unversioned.LabelSelector{}, name, ipset.HashIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -41,6 +42,7 @@ func newNS(name string, ipt *iptables.IPTables, ips ipset.Interface, nsSelectors
|
||||
ipt: ipt,
|
||||
ips: ips,
|
||||
name: name,
|
||||
nodeName: nodeName,
|
||||
pods: make(map[types.UID]*coreapi.Pod),
|
||||
policies: make(map[types.UID]*extnapi.NetworkPolicy),
|
||||
uid: uuid.NewUUID(),
|
||||
@@ -81,6 +83,13 @@ func (ns *ns) onNewPodSelector(selector *selector) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ns *ns) checkLocalPod(obj *coreapi.Pod) bool {
|
||||
if obj.Spec.NodeName != ns.nodeName {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (ns *ns) addPod(obj *coreapi.Pod) error {
|
||||
ns.pods[obj.ObjectMeta.UID] = obj
|
||||
|
||||
@@ -88,7 +97,9 @@ func (ns *ns) addPod(obj *coreapi.Pod) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
ns.ips.AddEntry(LocalIpset, obj.Status.PodIP)
|
||||
if ns.checkLocalPod(obj) {
|
||||
ns.ips.AddEntry(LocalIpset, obj.Status.PodIP)
|
||||
}
|
||||
return ns.podSelectors.addToMatching(obj.ObjectMeta.Labels, obj.Status.PodIP)
|
||||
}
|
||||
|
||||
@@ -101,12 +112,16 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
||||
}
|
||||
|
||||
if hasIP(oldObj) && !hasIP(newObj) {
|
||||
ns.ips.DelEntry(LocalIpset, oldObj.Status.PodIP)
|
||||
if ns.checkLocalPod(oldObj) {
|
||||
ns.ips.DelEntry(LocalIpset, oldObj.Status.PodIP)
|
||||
}
|
||||
return ns.podSelectors.delFromMatching(oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
|
||||
}
|
||||
|
||||
if !hasIP(oldObj) && hasIP(newObj) {
|
||||
ns.ips.AddEntry(LocalIpset, newObj.Status.PodIP)
|
||||
if ns.checkLocalPod(newObj) {
|
||||
ns.ips.AddEntry(LocalIpset, newObj.Status.PodIP)
|
||||
}
|
||||
return ns.podSelectors.addToMatching(newObj.ObjectMeta.Labels, newObj.Status.PodIP)
|
||||
}
|
||||
|
||||
@@ -142,7 +157,9 @@ func (ns *ns) deletePod(obj *coreapi.Pod) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
ns.ips.DelEntry(LocalIpset, obj.Status.PodIP)
|
||||
if ns.checkLocalPod(obj) {
|
||||
ns.ips.DelEntry(LocalIpset, obj.Status.PodIP)
|
||||
}
|
||||
return ns.podSelectors.delFromMatching(obj.ObjectMeta.Labels, obj.Status.PodIP)
|
||||
}
|
||||
|
||||
@@ -234,10 +251,12 @@ func bypassRule(nsIpsetName ipset.Name) []string {
|
||||
}
|
||||
|
||||
func (ns *ns) ensureBypassRule(nsIpsetName ipset.Name) error {
|
||||
common.Log.Debugf("ensuring rule for DefaultAllow in namespace: %s, set %s", ns.name, nsIpsetName)
|
||||
return ns.ipt.Append(TableFilter, DefaultChain, bypassRule(ns.allPods.ipsetName)...)
|
||||
}
|
||||
|
||||
func (ns *ns) deleteBypassRule(nsIpsetName ipset.Name) error {
|
||||
common.Log.Debugf("removing default rule in namespace: %s, set %s", ns.name, nsIpsetName)
|
||||
return ns.ipt.Delete(TableFilter, DefaultChain, bypassRule(ns.allPods.ipsetName)...)
|
||||
}
|
||||
|
||||
@@ -261,6 +280,7 @@ func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
|
||||
newDefaultDeny := isDefaultDeny(newObj)
|
||||
|
||||
if oldDefaultDeny != newDefaultDeny {
|
||||
common.Log.Infof("namespace DefaultDeny changed from %t to %t", oldDefaultDeny, newDefaultDeny)
|
||||
if oldDefaultDeny {
|
||||
return ns.ensureBypassRule(ns.allPods.ipsetName)
|
||||
}
|
||||
|
||||
+2
-2
@@ -38,14 +38,14 @@ func (i *Ipam) Allocate(args *skel.CmdArgs) (types.Result, error) {
|
||||
var ipnet *net.IPNet
|
||||
|
||||
if conf.Subnet == "" {
|
||||
ipnet, err = i.weave.AllocateIP(containerID)
|
||||
ipnet, err = i.weave.AllocateIP(containerID, false)
|
||||
} else {
|
||||
var subnet *net.IPNet
|
||||
subnet, err = types.ParseCIDR(conf.Subnet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("subnet given in config, but not parseable: %s", err)
|
||||
}
|
||||
ipnet, err = i.weave.AllocateIPInSubnet(containerID, subnet)
|
||||
ipnet, err = i.weave.AllocateIPInSubnet(containerID, subnet, false)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -19,6 +19,11 @@ func NewIpam(weave *api.Client) *Ipam {
|
||||
return &Ipam{weave: weave}
|
||||
}
|
||||
|
||||
func (i *Ipam) GetCapabilities() (RequiresMACAddress bool, RequiresRequestReplay bool, err error) {
|
||||
i.logReq("GetCapabilities")
|
||||
return false, false, nil
|
||||
}
|
||||
|
||||
func (i *Ipam) GetDefaultAddressSpaces() (string, string, error) {
|
||||
i.logReq("GetDefaultAddressSpaces")
|
||||
return "weavelocal", "weaveglobal", nil
|
||||
@@ -73,7 +78,7 @@ func (i *Ipam) RequestAddress(poolID string, address net.IP, options map[string]
|
||||
i.logReq("RequestAddress", poolID, address, options)
|
||||
defer func() { i.logRes("RequestAddress", err, ip) }()
|
||||
if poolID == "weavepool" { // old-style
|
||||
ip, err = i.weave.AllocateIP(api.NoContainerID)
|
||||
ip, err = i.weave.AllocateIP(api.NoContainerID, false)
|
||||
return
|
||||
}
|
||||
subnet, iprange, err := splitPoolID(poolID)
|
||||
@@ -82,12 +87,12 @@ func (i *Ipam) RequestAddress(poolID string, address net.IP, options map[string]
|
||||
}
|
||||
if address != nil { // try to claim specific address requested
|
||||
ip = &net.IPNet{IP: address, Mask: subnet.Mask}
|
||||
if err = i.weave.ClaimIP(api.NoContainerID, ip); err != nil {
|
||||
if err = i.weave.ClaimIP(api.NoContainerID, ip, false); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// We are lying slightly to IPAM here: the range is not a subnet
|
||||
if ip, err = i.weave.AllocateIPInSubnet(api.NoContainerID, iprange); err != nil {
|
||||
if ip, err = i.weave.AllocateIPInSubnet(api.NoContainerID, iprange, false); err != nil {
|
||||
return
|
||||
}
|
||||
ip.Mask = subnet.Mask // fix up the subnet we lied about
|
||||
|
||||
+60
-12
@@ -28,25 +28,40 @@ type network struct {
|
||||
}
|
||||
|
||||
type driver struct {
|
||||
name string
|
||||
scope string
|
||||
docker *docker.Client
|
||||
sync.RWMutex
|
||||
networks map[string]network
|
||||
name string
|
||||
scope string
|
||||
// Docker API is not available for plugin-v2
|
||||
docker *docker.Client
|
||||
dns bool
|
||||
isPluginV2 bool
|
||||
// Enable multicast regardless whether multicast opt is passed to Docker;
|
||||
// used only by plugin-v2
|
||||
forceMulticast bool
|
||||
networks map[string]network
|
||||
}
|
||||
|
||||
func New(client *docker.Client, weave *weaveapi.Client, name, scope string) (skel.Driver, error) {
|
||||
func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2, forceMulticast bool) (skel.Driver, error) {
|
||||
driver := &driver{
|
||||
name: name,
|
||||
scope: scope,
|
||||
docker: client,
|
||||
networks: make(map[string]network),
|
||||
name: name,
|
||||
scope: scope,
|
||||
docker: client,
|
||||
dns: dns,
|
||||
isPluginV2: isPluginV2,
|
||||
// make sure that it's used only by plugin-v2
|
||||
forceMulticast: isPluginV2 && forceMulticast,
|
||||
networks: make(map[string]network),
|
||||
}
|
||||
|
||||
_, err := NewWatcher(client, weave, driver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Do not start watcher in the case of plugin v2, which prevents us from
|
||||
// configuring arp settings of containers.
|
||||
if client != nil {
|
||||
_, err := NewWatcher(client, weave, driver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
@@ -61,12 +76,27 @@ func (driver *driver) GetCapabilities() (*api.GetCapabilityResponse, error) {
|
||||
return caps, nil
|
||||
}
|
||||
|
||||
// In Swarm mode, CreateNetwork is called on each Swarm node when a new service
|
||||
// is created.
|
||||
func (driver *driver) CreateNetwork(create *api.CreateNetworkRequest) error {
|
||||
driver.logReq("CreateNetwork", create, create.NetworkID)
|
||||
_, err := driver.setupNetworkInfo(create.NetworkID, true, stringOptions(create))
|
||||
return err
|
||||
}
|
||||
|
||||
// NetworkAllocate is called on a Swarm node (master) which creates the network.
|
||||
// The returned options are passed to CreateNetwork.
|
||||
func (driver *driver) NetworkAllocate(alloc *api.AllocateNetworkRequest) (*api.AllocateNetworkResponse, error) {
|
||||
driver.logReq("NetworkAllocate", alloc, alloc.NetworkID)
|
||||
return &api.AllocateNetworkResponse{Options: alloc.Options}, nil
|
||||
}
|
||||
|
||||
// NetworkFree is called on a Swarm master node which created the network.
|
||||
func (driver *driver) NetworkFree(free *api.FreeNetworkRequest) (*api.FreeNetworkResponse, error) {
|
||||
driver.logReq("NetworkFree", free, free.NetworkID)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Deal with excessively-generic way the options get decoded from JSON
|
||||
func stringOptions(create *api.CreateNetworkRequest) map[string]string {
|
||||
if create.Options != nil {
|
||||
@@ -85,6 +115,7 @@ func stringOptions(create *api.CreateNetworkRequest) map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// In Swarm mode, DeleteNetwork is called after a service has been removed.
|
||||
func (driver *driver) DeleteNetwork(delreq *api.DeleteNetworkRequest) error {
|
||||
driver.logReq("DeleteNetwork", delreq, delreq.NetworkID)
|
||||
driver.Lock()
|
||||
@@ -163,12 +194,29 @@ func (driver *driver) JoinEndpoint(j *api.JoinRequest) (*api.JoinResponse, error
|
||||
}
|
||||
|
||||
func (driver *driver) findNetworkInfo(id string) (network, error) {
|
||||
var network network
|
||||
|
||||
// plugin-v2 does not have access to docker.sock, so we cannot call Docker
|
||||
// API for the network info.
|
||||
if driver.isPluginV2 {
|
||||
// safe to set, as isOurs used only by the watcher which is disabled for plugin-v2
|
||||
network.isOurs = true
|
||||
network.hasMulticastRoute = driver.forceMulticast
|
||||
|
||||
return network, nil
|
||||
}
|
||||
|
||||
driver.Lock()
|
||||
network, found := driver.networks[id]
|
||||
driver.Unlock()
|
||||
if found {
|
||||
return network, nil
|
||||
}
|
||||
|
||||
if driver.docker == nil {
|
||||
return network, fmt.Errorf("Docker client disabled; unable to get network info")
|
||||
}
|
||||
|
||||
info, err := driver.docker.NetworkInfo(id)
|
||||
if err != nil {
|
||||
return network, err
|
||||
|
||||
+12
-4
@@ -41,11 +41,19 @@ func (w *watcher) ContainerStarted(id string) {
|
||||
continue
|
||||
}
|
||||
if network.isOurs {
|
||||
fqdn := fmt.Sprintf("%s.%s", info.Config.Hostname, info.Config.Domainname)
|
||||
if err := w.weave.RegisterWithDNS(id, fqdn, net.IPAddress); err != nil {
|
||||
w.driver.warn("ContainerStarted", "unable to register %s with weaveDNS: %s", id, err)
|
||||
if w.driver.dns {
|
||||
fqdn := fmt.Sprintf("%s.%s", info.Config.Hostname, info.Config.Domainname)
|
||||
if err := w.weave.RegisterWithDNS(id, fqdn, net.IPAddress); err != nil {
|
||||
w.driver.warn("ContainerStarted", "unable to register %s with weaveDNS: %s", id, err)
|
||||
}
|
||||
}
|
||||
if _, err := weavenet.WithNetNSByPid(info.State.Pid, "configure-arp", weavenet.VethName); err != nil {
|
||||
rootDir := "/"
|
||||
if w.driver.isPluginV2 {
|
||||
// We bind mount host's /proc to /host/proc for plugin-v2
|
||||
rootDir = "/host"
|
||||
}
|
||||
netNSPath := weavenet.NSPathByPidWithRoot(rootDir, info.State.Pid)
|
||||
if _, err := weavenet.WithNetNS(netNSPath, "configure-arp", weavenet.VethName, rootDir); err != nil {
|
||||
w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/libnetwork/ipamapi"
|
||||
weaveapi "github.com/weaveworks/weave/api"
|
||||
"github.com/weaveworks/weave/common"
|
||||
"github.com/weaveworks/weave/common/docker"
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
ipamplugin "github.com/weaveworks/weave/plugin/ipam"
|
||||
netplugin "github.com/weaveworks/weave/plugin/net"
|
||||
"github.com/weaveworks/weave/plugin/skel"
|
||||
)
|
||||
|
||||
const (
|
||||
pluginV2Name = "net-plugin"
|
||||
defaultNetwork = "weave"
|
||||
MulticastOption = netplugin.MulticastOption
|
||||
)
|
||||
|
||||
var Log = common.Log
|
||||
|
||||
type Config struct {
|
||||
Socket string
|
||||
MeshSocket string
|
||||
Enable bool
|
||||
EnableV2 bool
|
||||
EnableV2Multicast bool
|
||||
DNS bool
|
||||
DefaultSubnet string
|
||||
}
|
||||
|
||||
type Plugin struct {
|
||||
Config
|
||||
}
|
||||
|
||||
func NewPlugin(config Config) *Plugin {
|
||||
if !config.Enable && !config.EnableV2 {
|
||||
return nil
|
||||
}
|
||||
plugin := &Plugin{Config: config}
|
||||
return plugin
|
||||
}
|
||||
|
||||
func (plugin *Plugin) Start(weaveAPIAddr string, dockerClient *docker.Client, ready func()) {
|
||||
weave := weaveapi.NewClient(weaveAPIAddr, Log)
|
||||
|
||||
Log.Info("Waiting for Weave API Server...")
|
||||
weave.WaitAPIServer(30)
|
||||
Log.Info("Finished waiting for Weave API Server")
|
||||
|
||||
if err := plugin.run(dockerClient, weave, ready); err != nil {
|
||||
Log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, ready func()) error {
|
||||
endChan := make(chan error, 1)
|
||||
|
||||
if plugin.Socket != "" {
|
||||
globalListener, err := listenAndServe(dockerClient, weave, plugin.Socket, endChan, "global", false, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(plugin.Socket)
|
||||
defer globalListener.Close()
|
||||
}
|
||||
if plugin.MeshSocket != "" {
|
||||
meshListener, err := listenAndServe(dockerClient, weave, plugin.MeshSocket, endChan, "local", true, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(plugin.MeshSocket)
|
||||
defer meshListener.Close()
|
||||
if !plugin.EnableV2 {
|
||||
Log.Printf("Creating default %q network", defaultNetwork)
|
||||
options := map[string]interface{}{MulticastOption: "true"}
|
||||
dockerClient.EnsureNetwork(defaultNetwork, pluginNameFromAddress(plugin.MeshSocket), plugin.DefaultSubnet, options)
|
||||
}
|
||||
}
|
||||
ready()
|
||||
|
||||
return <-endChan
|
||||
}
|
||||
|
||||
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, dns bool, isPluginV2, forceMulticast bool) (net.Listener, error) {
|
||||
var name string
|
||||
if isPluginV2 {
|
||||
name = pluginV2Name
|
||||
} else {
|
||||
name = pluginNameFromAddress(address)
|
||||
}
|
||||
|
||||
d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2, forceMulticast)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var i ipamapi.Ipam
|
||||
if withIpam {
|
||||
i = ipamplugin.NewIpam(weave)
|
||||
}
|
||||
|
||||
listener, err := weavenet.ListenUnixSocket(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
Log.Printf("Listening on %s for %s scope", address, scope)
|
||||
|
||||
go func() {
|
||||
endChan <- skel.Listen(listener, d, i)
|
||||
}()
|
||||
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
// Take a socket address like "/run/docker/plugins/weavemesh.sock" and extract the plugin name "weavemesh"
|
||||
func pluginNameFromAddress(address string) string {
|
||||
return strings.TrimSuffix(path.Base(address), ".sock")
|
||||
}
|
||||
+49
-6
@@ -26,11 +26,17 @@ type Driver interface {
|
||||
DeleteEndpoint(delete *api.DeleteEndpointRequest) error
|
||||
EndpointInfo(req *api.EndpointInfoRequest) (*api.EndpointInfoResponse, error)
|
||||
JoinEndpoint(j *api.JoinRequest) (response *api.JoinResponse, error error)
|
||||
NetworkAllocate(*api.AllocateNetworkRequest) (*api.AllocateNetworkResponse, error)
|
||||
NetworkFree(*api.FreeNetworkRequest) (*api.FreeNetworkResponse, error)
|
||||
LeaveEndpoint(leave *api.LeaveRequest) error
|
||||
DiscoverNew(discover *api.DiscoveryNotification) error
|
||||
DiscoverDelete(delete *api.DiscoveryNotification) error
|
||||
}
|
||||
|
||||
type IpamCapability interface {
|
||||
GetCapabilities() (RequiresMACAddress bool, RequiresRequestReplay bool, err error)
|
||||
}
|
||||
|
||||
type listener struct {
|
||||
d Driver
|
||||
i ipamapi.Ipam
|
||||
@@ -58,9 +64,12 @@ func Listen(socket net.Listener, driver Driver, ipamDriver ipamapi.Ipam) error {
|
||||
handleMethod(networkReceiver, "EndpointOperInfo", listener.infoEndpoint)
|
||||
handleMethod(networkReceiver, "Join", listener.joinEndpoint)
|
||||
handleMethod(networkReceiver, "Leave", listener.leaveEndpoint)
|
||||
handleMethod(networkReceiver, "AllocateNetwork", listener.networkAllocate)
|
||||
handleMethod(networkReceiver, "FreeNetwork", listener.networkFree)
|
||||
}
|
||||
|
||||
if ipamDriver != nil {
|
||||
handleMethod(ipamReceiver, "GetCapabilities", listener.getIpamCapabilities)
|
||||
handleMethod(ipamReceiver, "GetDefaultAddressSpaces", listener.getDefaultAddressSpaces)
|
||||
handleMethod(ipamReceiver, "RequestPool", listener.requestPool)
|
||||
handleMethod(ipamReceiver, "ReleasePool", listener.releasePool)
|
||||
@@ -137,7 +146,7 @@ func (listener *listener) createEndpoint(w http.ResponseWriter, r *http.Request)
|
||||
func (listener *listener) deleteEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||
var delete api.DeleteEndpointRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&delete); err != nil {
|
||||
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
|
||||
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
emptyOrErrorResponse(w, listener.d.DeleteEndpoint(&delete))
|
||||
@@ -146,7 +155,7 @@ func (listener *listener) deleteEndpoint(w http.ResponseWriter, r *http.Request)
|
||||
func (listener *listener) infoEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||
var req api.EndpointInfoRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
|
||||
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
info, err := listener.d.EndpointInfo(&req)
|
||||
@@ -156,17 +165,37 @@ func (listener *listener) infoEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||
func (listener *listener) joinEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||
var join api.JoinRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&join); err != nil {
|
||||
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
|
||||
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
res, err := listener.d.JoinEndpoint(&join)
|
||||
objectOrErrorResponse(w, res, err)
|
||||
}
|
||||
|
||||
func (listener *listener) networkAllocate(w http.ResponseWriter, r *http.Request) {
|
||||
var alloc api.AllocateNetworkRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&alloc); err != nil {
|
||||
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
res, err := listener.d.NetworkAllocate(&alloc)
|
||||
objectOrErrorResponse(w, res, err)
|
||||
}
|
||||
|
||||
func (listener *listener) networkFree(w http.ResponseWriter, r *http.Request) {
|
||||
var free api.FreeNetworkRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&free); err != nil {
|
||||
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
res, err := listener.d.NetworkFree(&free)
|
||||
objectOrErrorResponse(w, res, err)
|
||||
}
|
||||
|
||||
func (listener *listener) leaveEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||
var l api.LeaveRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&l); err != nil {
|
||||
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
|
||||
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
emptyOrErrorResponse(w, listener.d.LeaveEndpoint(&l))
|
||||
@@ -175,7 +204,7 @@ func (listener *listener) leaveEndpoint(w http.ResponseWriter, r *http.Request)
|
||||
func (listener *listener) discoverNew(w http.ResponseWriter, r *http.Request) {
|
||||
var disco api.DiscoveryNotification
|
||||
if err := json.NewDecoder(r.Body).Decode(&disco); err != nil {
|
||||
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
|
||||
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
emptyOrErrorResponse(w, listener.d.DiscoverNew(&disco))
|
||||
@@ -184,7 +213,7 @@ func (listener *listener) discoverNew(w http.ResponseWriter, r *http.Request) {
|
||||
func (listener *listener) discoverDelete(w http.ResponseWriter, r *http.Request) {
|
||||
var disco api.DiscoveryNotification
|
||||
if err := json.NewDecoder(r.Body).Decode(&disco); err != nil {
|
||||
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
|
||||
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
emptyOrErrorResponse(w, listener.d.DiscoverDelete(&disco))
|
||||
@@ -192,6 +221,20 @@ func (listener *listener) discoverDelete(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
// ===
|
||||
|
||||
func (listener *listener) getIpamCapabilities(w http.ResponseWriter, r *http.Request) {
|
||||
c, ok := listener.i.(IpamCapability)
|
||||
if !ok {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
requiresMACAddress, requiresRequestReplay, err := c.GetCapabilities()
|
||||
response := &ipamapi.Capability{
|
||||
RequiresMACAddress: requiresMACAddress,
|
||||
RequiresRequestReplay: requiresRequestReplay,
|
||||
}
|
||||
objectOrErrorResponse(w, response, err)
|
||||
}
|
||||
|
||||
func (listener *listener) getDefaultAddressSpaces(w http.ResponseWriter, r *http.Request) {
|
||||
local, global, err := listener.i.GetDefaultAddressSpaces()
|
||||
response := &iapi.GetAddressSpacesResponse{
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package plugin
|
||||
|
||||
type Status struct {
|
||||
Config Config
|
||||
DriverName string
|
||||
MeshDriverName string `json:"MeshDriverName,omitempty"`
|
||||
}
|
||||
|
||||
func (plugin *Plugin) NewStatus() *Status {
|
||||
if plugin == nil {
|
||||
return nil
|
||||
}
|
||||
status := &Status{
|
||||
DriverName: pluginNameFromAddress(plugin.Socket),
|
||||
MeshDriverName: pluginNameFromAddress(plugin.MeshSocket),
|
||||
Config: plugin.Config,
|
||||
}
|
||||
return status
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"description": "Weave Net plugin for Docker",
|
||||
"documentation": "https://weave.works",
|
||||
"entrypoint": [
|
||||
"/home/weave/launch.sh"
|
||||
],
|
||||
"interface": {
|
||||
"socket": "weave.sock",
|
||||
"types": [
|
||||
"docker.networkdriver/1.0"
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"capabilities": [
|
||||
"CAP_SYS_ADMIN",
|
||||
"CAP_NET_ADMIN"
|
||||
]
|
||||
},
|
||||
"mounts": [
|
||||
{
|
||||
"destination": "/host/proc/",
|
||||
"type": "bind",
|
||||
"source": "/proc/",
|
||||
"options": ["rbind", "rw"]
|
||||
},
|
||||
{
|
||||
"destination": "/var/run/docker.sock",
|
||||
"source": "/var/run/docker.sock",
|
||||
"type": "bind",
|
||||
"options": ["rbind"]
|
||||
},
|
||||
{
|
||||
"destination": "/host/var/lib/",
|
||||
"source": "/var/lib/",
|
||||
"type": "bind",
|
||||
"options": ["rbind"]
|
||||
},
|
||||
{
|
||||
"destination": "/host/etc/",
|
||||
"source": "/etc/",
|
||||
"type": "bind",
|
||||
"options": ["rbind"]
|
||||
}
|
||||
],
|
||||
"env": [
|
||||
{
|
||||
"description": "Extra args to `weaver` and `plugin`",
|
||||
"name": "EXTRA_ARGS",
|
||||
"settable": [
|
||||
"value"
|
||||
],
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"description": "Encryption password",
|
||||
"name": "WEAVE_PASSWORD",
|
||||
"settable": [
|
||||
"value"
|
||||
],
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"description": "MTU",
|
||||
"name": "WEAVE_MTU",
|
||||
"settable": [
|
||||
"value"
|
||||
],
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"description": "Enable multicast for all Weave networks",
|
||||
"name": "WEAVE_MULTICAST",
|
||||
"settable": [
|
||||
"value"
|
||||
],
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"description": "The range of IP addresses used by Weave Net",
|
||||
"name": "IPALLOC_RANGE",
|
||||
"settable": [
|
||||
"value"
|
||||
],
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"network": {
|
||||
"type": "host"
|
||||
},
|
||||
"workdir": ""
|
||||
}
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# Default if not supplied - same as weave net default
|
||||
IPALLOC_RANGE=${IPALLOC_RANGE:-10.32.0.0/12}
|
||||
HTTP_ADDR=${WEAVE_HTTP_ADDR:-127.0.0.1:6784}
|
||||
STATUS_ADDR=${WEAVE_STATUS_ADDR:-0.0.0.0:6782}
|
||||
HOST_ROOT=${HOST_ROOT:-/host}
|
||||
WEAVE_DIR="/host/var/lib/weave"
|
||||
|
||||
mkdir $WEAVE_DIR || true
|
||||
|
||||
echo "Starting launch.sh"
|
||||
|
||||
# Check if the IP range overlaps anything existing on the host
|
||||
/usr/bin/weaveutil netcheck $IPALLOC_RANGE weave
|
||||
|
||||
# We need to get a list of Swarm nodes which might run the net-plugin:
|
||||
# - In the case of missing restart.sentinel, we assume that net-plugin has started
|
||||
# for the first time via the docker-plugin cmd. So it's safe to request docker.sock.
|
||||
# - If restart.sentinel present, let weaver restore from it as docker.sock is not
|
||||
# available to any plugin in general (https://github.com/moby/moby/issues/32815).
|
||||
|
||||
PEERS=
|
||||
if [ ! -f "/restart.sentinel" ]; then
|
||||
PEERS=$(/usr/bin/weaveutil swarm-manager-peers)
|
||||
fi
|
||||
|
||||
router_bridge_opts() {
|
||||
echo --datapath=datapath
|
||||
[ -z "$WEAVE_MTU" ] || echo --mtu "$WEAVE_MTU"
|
||||
[ -z "$WEAVE_NO_FASTDP" ] || echo --no-fastdp
|
||||
}
|
||||
|
||||
multicast_opt() {
|
||||
[ -z "$WEAVE_MULTICAST" ] || echo "--plugin-v2-multicast"
|
||||
}
|
||||
|
||||
exec /home/weave/weaver $EXTRA_ARGS --port=6783 $(router_bridge_opts) \
|
||||
--host-root=/host \
|
||||
--proc-path=/host/proc \
|
||||
--http-addr=$HTTP_ADDR --status-addr=$STATUS_ADDR \
|
||||
--no-dns \
|
||||
--ipalloc-range=$IPALLOC_RANGE \
|
||||
--nickname "$(hostname)" \
|
||||
--log-level=debug \
|
||||
--db-prefix="$WEAVE_DIR/weave" \
|
||||
--plugin-v2 \
|
||||
$(multicast_opt) \
|
||||
--plugin-mesh-socket='' \
|
||||
--docker-api='' \
|
||||
$PEERS
|
||||
@@ -1,3 +0,0 @@
|
||||
FROM DOCKERHUB_USER/weaveARCH_EXT
|
||||
ADD ./plugin /home/weave/
|
||||
ENTRYPOINT ["/home/weave/plugin"]
|
||||
@@ -1,140 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/libnetwork/ipamapi"
|
||||
weaveapi "github.com/weaveworks/weave/api"
|
||||
"github.com/weaveworks/weave/common"
|
||||
"github.com/weaveworks/weave/common/docker"
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
ipamplugin "github.com/weaveworks/weave/plugin/ipam"
|
||||
netplugin "github.com/weaveworks/weave/plugin/net"
|
||||
"github.com/weaveworks/weave/plugin/skel"
|
||||
)
|
||||
|
||||
var version = "unreleased"
|
||||
|
||||
var Log = common.Log
|
||||
|
||||
func main() {
|
||||
var (
|
||||
justVersion bool
|
||||
address string
|
||||
meshAddress string
|
||||
logLevel string
|
||||
noMulticastRoute bool
|
||||
)
|
||||
|
||||
flag.BoolVar(&justVersion, "version", false, "print version and exit")
|
||||
flag.StringVar(&logLevel, "log-level", "info", "logging level (debug, info, warning, error)")
|
||||
flag.StringVar(&address, "socket", "/run/docker/plugins/weave.sock", "socket on which to listen")
|
||||
flag.StringVar(&meshAddress, "meshsocket", "/run/docker/plugins/weavemesh.sock", "socket on which to listen in mesh mode")
|
||||
flag.BoolVar(&noMulticastRoute, "no-multicast-route", false, "deprecated (this is now the default)")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if justVersion {
|
||||
fmt.Printf("weave plugin %s\n", version)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
common.SetLogLevel(logLevel)
|
||||
|
||||
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), Log)
|
||||
|
||||
// API 1.21 is the first version that supports docker network commands
|
||||
dockerClient, err := docker.NewVersionedClientFromEnv("1.21")
|
||||
if err != nil {
|
||||
Log.Fatalf("unable to connect to docker: %s", err)
|
||||
}
|
||||
|
||||
Log.Println("Weave plugin", version, "Command line options:", os.Args[1:])
|
||||
if noMulticastRoute {
|
||||
Log.Warning("--no-multicast-route option has been removed; multicast is off by default")
|
||||
}
|
||||
Log.Info(dockerClient.Info())
|
||||
|
||||
err = run(dockerClient, weave, address, meshAddress)
|
||||
if err != nil {
|
||||
Log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddress string) error {
|
||||
endChan := make(chan error, 1)
|
||||
if address != "" {
|
||||
globalListener, err := listenAndServe(dockerClient, weave, address, endChan, "global", false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(address)
|
||||
defer globalListener.Close()
|
||||
}
|
||||
if meshAddress != "" {
|
||||
meshListener, err := listenAndServe(dockerClient, weave, meshAddress, endChan, "local", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(meshAddress)
|
||||
defer meshListener.Close()
|
||||
}
|
||||
|
||||
statusListener, err := weavenet.ListenUnixSocket("/home/weave/status.sock")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go serveStatus(statusListener)
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
select {
|
||||
case sig := <-sigChan:
|
||||
Log.Debugf("Caught signal %s; shutting down", sig)
|
||||
return nil
|
||||
case err := <-endChan:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam bool) (net.Listener, error) {
|
||||
name := strings.TrimSuffix(path.Base(address), ".sock")
|
||||
d, err := netplugin.New(dockerClient, weave, name, scope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var i ipamapi.Ipam
|
||||
if withIpam {
|
||||
i = ipamplugin.NewIpam(weave)
|
||||
}
|
||||
|
||||
listener, err := weavenet.ListenUnixSocket(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
Log.Printf("Listening on %s for %s scope", address, scope)
|
||||
|
||||
go func() {
|
||||
endChan <- skel.Listen(listener, d, i)
|
||||
}()
|
||||
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
func serveStatus(listener net.Listener) {
|
||||
server := &http.Server{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "ok")
|
||||
})}
|
||||
if err := server.Serve(listener); err != nil {
|
||||
Log.Fatalf("ListenAndServeStatus failed: %s", err)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
weavetest "github.com/weaveworks/weave/testing"
|
||||
)
|
||||
|
||||
func TestMain(t *testing.T) {
|
||||
weavetest.TrimTestArgs()
|
||||
main()
|
||||
}
|
||||
+11
-16
@@ -53,15 +53,12 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# Explicitly create the bridge so we can pass --expect-npc
|
||||
# Default is that npc will be running; allow caller to override
|
||||
WEAVE_NPC_OPTS="--expect-npc"
|
||||
if [ "${EXPECT_NPC}" = "0" ]; then
|
||||
WEAVE_NPC_OPTS=""
|
||||
fi
|
||||
|
||||
export HOST_ROOT=/host
|
||||
/home/weave/weave --local create-bridge --force $WEAVE_NPC_OPTS
|
||||
|
||||
# Kubernetes sets HOSTNAME to the host's hostname
|
||||
# when running a pod in host namespace.
|
||||
NICKNAME_ARG=""
|
||||
@@ -69,17 +66,11 @@ if [ -n "$HOSTNAME" ] ; then
|
||||
NICKNAME_ARG="--nickname=$HOSTNAME"
|
||||
fi
|
||||
|
||||
BRIDGE_OPTIONS="--datapath=datapath"
|
||||
if [ "$(/home/weave/weave --local bridge-type)" = "bridge" ] ; then
|
||||
# TODO: Call into weave script to do this
|
||||
if ! ip link show vethwe-pcap >/dev/null 2>&1 ; then
|
||||
ip link add name vethwe-bridge type veth peer name vethwe-pcap
|
||||
ip link set vethwe-bridge up
|
||||
ip link set vethwe-pcap up
|
||||
ip link set vethwe-bridge master weave
|
||||
fi
|
||||
BRIDGE_OPTIONS="--iface=vethwe-pcap"
|
||||
fi
|
||||
router_bridge_opts() {
|
||||
echo --datapath=datapath
|
||||
[ -z "$WEAVE_MTU" ] || echo --mtu "$WEAVE_MTU"
|
||||
[ -z "$WEAVE_NO_FASTDP" ] || echo --no-fastdp
|
||||
}
|
||||
|
||||
if [ -z "$KUBE_PEERS" ]; then
|
||||
if ! KUBE_PEERS=$(/home/weave/kube-peers) || [ -z "$KUBE_PEERS" ]; then
|
||||
@@ -114,6 +105,7 @@ post_start_actions() {
|
||||
fi
|
||||
fi
|
||||
mkdir -p $HOST_ROOT/etc/cni/net.d
|
||||
export HOST_ROOT
|
||||
/home/weave/weave --local setup-cni
|
||||
|
||||
# Expose the weave network so host processes can communicate with pods
|
||||
@@ -122,10 +114,13 @@ post_start_actions() {
|
||||
|
||||
post_start_actions &
|
||||
|
||||
/home/weave/weaver $EXTRA_ARGS --port=6783 $BRIDGE_OPTIONS \
|
||||
/home/weave/weaver $EXTRA_ARGS --port=6783 $(router_bridge_opts) \
|
||||
--host-root=$HOST_ROOT \
|
||||
--http-addr=$HTTP_ADDR --status-addr=$STATUS_ADDR --docker-api='' --no-dns \
|
||||
--db-prefix="/weavedb/weave-net" \
|
||||
--ipalloc-range=$IPALLOC_RANGE $NICKNAME_ARG \
|
||||
--ipalloc-init $IPALLOC_INIT \
|
||||
--conn-limit=$CONN_LIMIT \
|
||||
$WEAVE_NPC_OPTS \
|
||||
"$@" \
|
||||
$KUBE_PEERS
|
||||
@@ -1,120 +1,136 @@
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: weave-net
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
- namespaces
|
||||
- nodes
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- extensions
|
||||
resources:
|
||||
- networkpolicies
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: weave-net
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: weave-net
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
spec:
|
||||
template:
|
||||
kind: List
|
||||
items:
|
||||
- apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ''
|
||||
resources:
|
||||
- pods
|
||||
- namespaces
|
||||
- nodes
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- extensions
|
||||
resources:
|
||||
- networkpolicies
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: weave-net
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
- apiVersion: extensions/v1beta1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
spec:
|
||||
hostNetwork: true
|
||||
hostPID: true
|
||||
containers:
|
||||
- name: weave
|
||||
image: weaveworks/weave-kube:latest
|
||||
imagePullPolicy: Always
|
||||
command:
|
||||
- /home/weave/launch.sh
|
||||
livenessProbe:
|
||||
initialDelaySeconds: 30
|
||||
httpGet:
|
||||
host: 127.0.0.1
|
||||
path: /status
|
||||
port: 6784
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: weave-net
|
||||
spec:
|
||||
containers:
|
||||
- name: weave
|
||||
command:
|
||||
- /home/weave/launch.sh
|
||||
env:
|
||||
- name: HOSTNAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: spec.nodeName
|
||||
image: 'weaveworks/weave-kube:latest'
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
host: 127.0.0.1
|
||||
path: /status
|
||||
port: 6784
|
||||
initialDelaySeconds: 30
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- name: weavedb
|
||||
mountPath: /weavedb
|
||||
- name: cni-bin
|
||||
mountPath: /host/opt
|
||||
- name: cni-bin2
|
||||
mountPath: /host/home
|
||||
- name: cni-conf
|
||||
mountPath: /host/etc
|
||||
- name: dbus
|
||||
mountPath: /host/var/lib/dbus
|
||||
- name: lib-modules
|
||||
mountPath: /lib/modules
|
||||
- name: weave-npc
|
||||
image: 'weaveworks/weave-npc:latest'
|
||||
imagePullPolicy: Always
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
securityContext:
|
||||
privileged: true
|
||||
hostNetwork: true
|
||||
hostPID: true
|
||||
restartPolicy: Always
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
seLinuxOptions: {}
|
||||
serviceAccountName: weave-net
|
||||
tolerations:
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
volumes:
|
||||
- name: weavedb
|
||||
mountPath: /weavedb
|
||||
hostPath:
|
||||
path: /var/lib/weave
|
||||
- name: cni-bin
|
||||
mountPath: /host/opt
|
||||
hostPath:
|
||||
path: /opt
|
||||
- name: cni-bin2
|
||||
mountPath: /host/home
|
||||
hostPath:
|
||||
path: /home
|
||||
- name: cni-conf
|
||||
mountPath: /host/etc
|
||||
hostPath:
|
||||
path: /etc
|
||||
- name: dbus
|
||||
mountPath: /host/var/lib/dbus
|
||||
hostPath:
|
||||
path: /var/lib/dbus
|
||||
- name: lib-modules
|
||||
mountPath: /lib/modules
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
- name: weave-npc
|
||||
image: weaveworks/weave-npc:latest
|
||||
imagePullPolicy: Always
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
securityContext:
|
||||
privileged: true
|
||||
restartPolicy: Always
|
||||
tolerations:
|
||||
- key: node-role.kubernetes.io/master
|
||||
effect: NoSchedule
|
||||
serviceAccountName: weave-net
|
||||
securityContext:
|
||||
seLinuxOptions:
|
||||
type: spc_t
|
||||
volumes:
|
||||
- name: weavedb
|
||||
emptyDir: {}
|
||||
- name: cni-bin
|
||||
hostPath:
|
||||
path: /opt
|
||||
- name: cni-bin2
|
||||
hostPath:
|
||||
path: /home
|
||||
- name: cni-conf
|
||||
hostPath:
|
||||
path: /etc
|
||||
- name: dbus
|
||||
hostPath:
|
||||
path: /var/lib/dbus
|
||||
- name: lib-modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
updateStrategy:
|
||||
type: RollingUpdate
|
||||
@@ -1,80 +1,95 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
spec:
|
||||
template:
|
||||
apiVersion: v1
|
||||
kind: List
|
||||
items:
|
||||
- apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
annotations:
|
||||
scheduler.alpha.kubernetes.io/tolerations: |
|
||||
[
|
||||
{
|
||||
"key": "dedicated",
|
||||
"operator": "Equal",
|
||||
"value": "master",
|
||||
"effect": "NoSchedule"
|
||||
}
|
||||
]
|
||||
namespace: kube-system
|
||||
- apiVersion: extensions/v1beta1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
spec:
|
||||
hostNetwork: true
|
||||
hostPID: true
|
||||
containers:
|
||||
- name: weave
|
||||
image: weaveworks/weave-kube:latest
|
||||
imagePullPolicy: Always
|
||||
command:
|
||||
- /home/weave/launch.sh
|
||||
livenessProbe:
|
||||
initialDelaySeconds: 30
|
||||
httpGet:
|
||||
host: 127.0.0.1
|
||||
path: /status
|
||||
port: 6784
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
scheduler.alpha.kubernetes.io/tolerations: >-
|
||||
[{"key":"dedicated","operator":"Equal","value":"master","effect":"NoSchedule"}]
|
||||
labels:
|
||||
name: weave-net
|
||||
spec:
|
||||
containers:
|
||||
- name: weave
|
||||
command:
|
||||
- /home/weave/launch.sh
|
||||
env:
|
||||
- name: HOSTNAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: spec.nodeName
|
||||
image: 'weaveworks/weave-kube:latest'
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
host: 127.0.0.1
|
||||
path: /status
|
||||
port: 6784
|
||||
initialDelaySeconds: 30
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- name: weavedb
|
||||
mountPath: /weavedb
|
||||
- name: cni-bin
|
||||
mountPath: /host/opt
|
||||
- name: cni-bin2
|
||||
mountPath: /host/home
|
||||
- name: cni-conf
|
||||
mountPath: /host/etc
|
||||
- name: dbus
|
||||
mountPath: /host/var/lib/dbus
|
||||
- name: lib-modules
|
||||
mountPath: /lib/modules
|
||||
- name: weave-npc
|
||||
image: 'weaveworks/weave-npc:latest'
|
||||
imagePullPolicy: Always
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
securityContext:
|
||||
privileged: true
|
||||
hostNetwork: true
|
||||
hostPID: true
|
||||
restartPolicy: Always
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
seLinuxOptions: {}
|
||||
serviceAccountName: weave-net
|
||||
volumes:
|
||||
- name: weavedb
|
||||
mountPath: /weavedb
|
||||
hostPath:
|
||||
path: /var/lib/weave
|
||||
- name: cni-bin
|
||||
mountPath: /host/opt
|
||||
hostPath:
|
||||
path: /opt
|
||||
- name: cni-bin2
|
||||
mountPath: /host/home
|
||||
hostPath:
|
||||
path: /home
|
||||
- name: cni-conf
|
||||
mountPath: /host/etc
|
||||
hostPath:
|
||||
path: /etc
|
||||
- name: dbus
|
||||
mountPath: /host/var/lib/dbus
|
||||
hostPath:
|
||||
path: /var/lib/dbus
|
||||
- name: lib-modules
|
||||
mountPath: /lib/modules
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
- name: weave-npc
|
||||
image: weaveworks/weave-npc:latest
|
||||
imagePullPolicy: Always
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
securityContext:
|
||||
privileged: true
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: weavedb
|
||||
emptyDir: {}
|
||||
- name: cni-bin
|
||||
hostPath:
|
||||
path: /opt
|
||||
- name: cni-bin2
|
||||
hostPath:
|
||||
path: /home
|
||||
- name: cni-conf
|
||||
hostPath:
|
||||
path: /etc
|
||||
- name: dbus
|
||||
hostPath:
|
||||
path: /var/lib/dbus
|
||||
- name: lib-modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
@@ -117,7 +117,6 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
|
||||
return err
|
||||
}
|
||||
if err := ipt.Append(npc.TableFilter, npc.MainChain,
|
||||
"-m", "set", "--match-set", npc.LocalIpset, "src",
|
||||
"-m", "set", "!", "--match-set", npc.LocalIpset, "dst", "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,34 +1,10 @@
|
||||
FROM ALPINE_BASEIMAGE
|
||||
FROM DOCKERHUB_USER/weaveARCH_EXT
|
||||
|
||||
# If we're building for another architecture than amd64, the CROSS_BUILD_ placeholder is removed so e.g. CROSS_BUILD_COPY turns into COPY
|
||||
# If we're building normally, for amd64, CROSS_BUILD lines are removed
|
||||
CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/
|
||||
|
||||
LABEL maintainer "Weaveworks Inc <help@weave.works>"
|
||||
LABEL works.weave.role=system \
|
||||
org.label-schema.name="Weave Net" \
|
||||
org.label-schema.description="Weave Net creates a virtual network that connects Docker containers across multiple hosts and enables their automatic discovery" \
|
||||
org.label-schema.url="https://weave.works" \
|
||||
org.label-schema.vcs-url="https://github.com/weaveworks/weave" \
|
||||
org.label-schema.vendor="Weaveworks"
|
||||
|
||||
WORKDIR /home/weave
|
||||
ENTRYPOINT ["/home/weave/sigproxy", "/home/weave/weave"]
|
||||
|
||||
RUN apk add --update \
|
||||
curl \
|
||||
ethtool \
|
||||
iptables \
|
||||
ipset \
|
||||
iproute2 \
|
||||
util-linux \
|
||||
conntrack-tools \
|
||||
bind-tools \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
ADD ./weave ./sigproxy ./weaveproxy ./symlink /home/weave/
|
||||
ADD ./weaveutil /usr/bin/
|
||||
ADD ./sigproxy ./symlink /home/weave/
|
||||
ADD ./docker /usr/bin/
|
||||
ADD ./weavewait /w/w
|
||||
ADD ./weavewait_noop /w-noop/w
|
||||
ADD ./weavewait_nomcast /w-nomcast/w
|
||||
ADD ./docker /usr/bin/
|
||||
WORKDIR /home/weave
|
||||
@@ -1,84 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/weaveworks/common/mflag"
|
||||
"github.com/weaveworks/common/mflagext"
|
||||
"github.com/weaveworks/common/signals"
|
||||
"github.com/weaveworks/weave/common"
|
||||
"github.com/weaveworks/weave/proxy"
|
||||
)
|
||||
|
||||
var version = "unreleased"
|
||||
|
||||
var Log = common.Log
|
||||
|
||||
func getenv(key, defaultVal string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
justVersion bool
|
||||
logLevel = "info"
|
||||
c proxy.Config
|
||||
withDNS bool
|
||||
)
|
||||
|
||||
c.Version = version
|
||||
|
||||
mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit")
|
||||
mflag.StringVar(&logLevel, []string{"-log-level"}, "info", "logging level (debug, info, warning, error)")
|
||||
mflagext.ListVar(&c.ListenAddrs, []string{"H"}, nil, "addresses on which to listen")
|
||||
mflag.StringVar(&c.HostnameFromLabel, []string{"-hostname-from-label"}, "", "Key of container label from which to obtain the container's hostname")
|
||||
mflag.StringVar(&c.HostnameMatch, []string{"-hostname-match"}, "(.*)", "Regexp pattern to apply on container names (e.g. '^aws-[0-9]+-(.*)$')")
|
||||
mflag.StringVar(&c.HostnameReplacement, []string{"-hostname-replacement"}, "$1", "Expression to generate hostnames based on matches from --hostname-match (e.g. 'my-app-$1')")
|
||||
mflag.BoolVar(&c.RewriteInspect, []string{"-rewrite-inspect"}, false, "Rewrite 'inspect' calls to return the weave network settings (if attached)")
|
||||
mflag.BoolVar(&c.NoDefaultIPAM, []string{"#-no-default-ipam", "-no-default-ipalloc"}, false, "do not automatically allocate addresses for containers without a WEAVE_CIDR")
|
||||
mflag.BoolVar(&c.NoRewriteHosts, []string{"-no-rewrite-hosts"}, false, "do not automatically rewrite /etc/hosts. Use if you need the docker IP to remain in /etc/hosts")
|
||||
mflag.StringVar(&c.TLSConfig.CACert, []string{"#tlscacert", "-tlscacert"}, "", "Trust certs signed only by this CA")
|
||||
mflag.StringVar(&c.TLSConfig.Cert, []string{"#tlscert", "-tlscert"}, "", "Path to TLS certificate file")
|
||||
mflag.BoolVar(&c.TLSConfig.Enabled, []string{"#tls", "-tls"}, false, "Use TLS; implied by --tlsverify")
|
||||
mflag.StringVar(&c.TLSConfig.Key, []string{"#tlskey", "-tlskey"}, "", "Path to TLS key file")
|
||||
mflag.BoolVar(&c.TLSConfig.Verify, []string{"#tlsverify", "-tlsverify"}, false, "Use TLS and verify the remote")
|
||||
mflag.BoolVar(&withDNS, []string{"#-with-dns", "#w"}, false, "option removed")
|
||||
mflag.BoolVar(&c.WithoutDNS, []string{"-without-dns"}, false, "instruct created containers to never use weaveDNS as their nameserver")
|
||||
mflag.BoolVar(&c.NoMulticastRoute, []string{"-no-multicast-route"}, false, "do not add a multicast route via the weave interface when attaching containers")
|
||||
mflag.Parse()
|
||||
|
||||
if justVersion {
|
||||
fmt.Printf("weave proxy %s\n", version)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
common.SetLogLevel(logLevel)
|
||||
|
||||
Log.Infoln("weave proxy", version)
|
||||
Log.Infoln("Command line arguments:", strings.Join(os.Args[1:], " "))
|
||||
|
||||
if withDNS {
|
||||
Log.Warning("--with-dns option has been removed; DNS is on by default")
|
||||
}
|
||||
|
||||
c.Image = getenv("EXEC_IMAGE", "weaveworks/weaveexec")
|
||||
c.DockerBridge = getenv("DOCKER_BRIDGE", "docker0")
|
||||
c.DockerHost = getenv("DOCKER_HOST", "unix:///var/run/docker.sock")
|
||||
|
||||
p, err := proxy.NewProxy(c)
|
||||
if err != nil {
|
||||
Log.Fatalf("Could not start proxy: %s", err)
|
||||
}
|
||||
defer p.Stop()
|
||||
|
||||
listeners := p.Listen()
|
||||
p.AttachExistingContainers()
|
||||
go p.Serve(listeners)
|
||||
go p.ListenAndServeStatus("/home/weave/status.sock")
|
||||
signals.SignalHandlerLoop(common.Log)
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
weavetest "github.com/weaveworks/weave/testing"
|
||||
)
|
||||
|
||||
func TestMain(t *testing.T) {
|
||||
weavetest.TrimTestArgs()
|
||||
main()
|
||||
}
|
||||
@@ -1,6 +1,31 @@
|
||||
FROM DOCKERHUB_USER/weaveexecARCH_EXT
|
||||
WORKDIR /home/weave
|
||||
ADD ./weaver /home/weave/
|
||||
FROM ALPINE_BASEIMAGE
|
||||
|
||||
# If we're building for another architecture than amd64, the CROSS_BUILD_ placeholder is removed so e.g. CROSS_BUILD_COPY turns into COPY
|
||||
# If we're building normally, for amd64, CROSS_BUILD lines are removed
|
||||
CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/
|
||||
|
||||
LABEL maintainer "Weaveworks Inc <help@weave.works>"
|
||||
LABEL works.weave.role=system \
|
||||
org.label-schema.name="Weave Net" \
|
||||
org.label-schema.description="Weave Net creates a virtual network that connects Docker containers across multiple hosts and enables their automatic discovery" \
|
||||
org.label-schema.url="https://weave.works" \
|
||||
org.label-schema.vcs-url="https://github.com/weaveworks/weave" \
|
||||
org.label-schema.vendor="Weaveworks"
|
||||
|
||||
RUN apk add --update \
|
||||
curl \
|
||||
ethtool \
|
||||
iptables \
|
||||
ipset \
|
||||
iproute2 \
|
||||
util-linux \
|
||||
conntrack-tools \
|
||||
bind-tools \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
ADD ./weave ./weaver /home/weave/
|
||||
ADD ./weaveutil /usr/bin/
|
||||
ADD weavedata.db /weavedb/
|
||||
COPY ca-certificates.crt /etc/ssl/certs/
|
||||
ENTRYPOINT ["/home/weave/weaver"]
|
||||
WORKDIR /home/weave
|
||||
@@ -0,0 +1,104 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/weaveworks/weave/ipam"
|
||||
)
|
||||
|
||||
// TODO: move these definitions somewhere more shareable
|
||||
type PeerUpdateRequest struct {
|
||||
Name string `json:"peername"`
|
||||
Nickname string `json:"nickname"` // optional
|
||||
Addresses []string `json:"addresses"` // can be empty
|
||||
}
|
||||
|
||||
type PeerUpdateResponse struct {
|
||||
Addresses []string `json:"addresses"`
|
||||
PeerCount int `json:"peercount"`
|
||||
}
|
||||
|
||||
var httpClient = &http.Client{Timeout: 30 * time.Second}
|
||||
|
||||
func do(verb string, discoveryEndpoint, token string, request interface{}, response interface{}) error {
|
||||
body := new(bytes.Buffer)
|
||||
err := json.NewEncoder(body).Encode(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequest(verb, discoveryEndpoint+"/peer", body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Scope-Probe token=%s", token))
|
||||
req.Header.Set("X-Weave-Net-Version", version)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
Log.Printf("Calling peer discovery %s with %s", req.URL, request)
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
rbody, _ := ioutil.ReadAll(resp.Body)
|
||||
return errors.New(resp.Status + ": " + string(rbody))
|
||||
}
|
||||
if response == nil {
|
||||
return nil
|
||||
}
|
||||
err = json.NewDecoder(resp.Body).Decode(response)
|
||||
Log.Printf("peer discovery result: (%v) %v", err, response)
|
||||
return err
|
||||
}
|
||||
|
||||
func peerDiscoveryUpdate(discoveryEndpoint, token, peername, nickname string, addresses []string) ([]string, int, error) {
|
||||
request := PeerUpdateRequest{
|
||||
Name: peername,
|
||||
Nickname: nickname,
|
||||
Addresses: addresses,
|
||||
}
|
||||
var updateResponse PeerUpdateResponse
|
||||
err := do("POST", discoveryEndpoint, token, request, &updateResponse)
|
||||
return updateResponse.Addresses, updateResponse.PeerCount, err
|
||||
}
|
||||
|
||||
func peerDiscoveryDelete(discoveryEndpoint, token, peername string) error {
|
||||
request := PeerUpdateRequest{Name: peername}
|
||||
return do("DELETE", discoveryEndpoint, token, request, nil)
|
||||
}
|
||||
|
||||
func HandleHTTPPeer(router *mux.Router, alloc *ipam.Allocator, discoveryEndpoint, token, peername string) {
|
||||
router.Methods("DELETE").Path("/peer").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if discoveryEndpoint != "" && token != "" {
|
||||
if err := peerDiscoveryDelete(discoveryEndpoint, token, peername); err != nil {
|
||||
Log.Errorf("Error while deleting self from peer discovery: %s", err)
|
||||
}
|
||||
}
|
||||
if alloc != nil {
|
||||
alloc.Shutdown()
|
||||
}
|
||||
w.WriteHeader(204)
|
||||
})
|
||||
|
||||
router.Methods("DELETE").Path("/peer/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ident := mux.Vars(r)["id"]
|
||||
if discoveryEndpoint != "" && token != "" {
|
||||
// TODO: deal with this being either a peername or a nickname
|
||||
if err := peerDiscoveryDelete(discoveryEndpoint, token, ident); err != nil {
|
||||
Log.Errorf("Error while deleting self from peer discovery: %s", err)
|
||||
}
|
||||
}
|
||||
if alloc != nil {
|
||||
transferred := alloc.AdminTakeoverRanges(ident)
|
||||
fmt.Fprintf(w, "%d IPs taken over from %s\n", transferred, ident)
|
||||
}
|
||||
})
|
||||
}
|
||||
+32
-4
@@ -13,9 +13,12 @@ import (
|
||||
"github.com/weaveworks/mesh"
|
||||
|
||||
"github.com/weaveworks/go-checkpoint"
|
||||
"github.com/weaveworks/weave/common"
|
||||
"github.com/weaveworks/weave/ipam"
|
||||
"github.com/weaveworks/weave/nameserver"
|
||||
"github.com/weaveworks/weave/net/address"
|
||||
"github.com/weaveworks/weave/plugin"
|
||||
"github.com/weaveworks/weave/proxy"
|
||||
weave "github.com/weaveworks/weave/router"
|
||||
)
|
||||
|
||||
@@ -178,7 +181,7 @@ var statusTemplate = defTemplate("status", `\
|
||||
{{if allIPAMOwnersUnreachable .IPAM}}\
|
||||
Status: all IP ranges owned by unreachable peers - use 'rmpeer' if they are dead
|
||||
{{else if len .IPAM.PendingAllocates}}\
|
||||
Status: waiting for IP range grant from peers
|
||||
Status: waiting for IP(s) to become available
|
||||
{{else}}\
|
||||
Status: ready
|
||||
{{end}}\
|
||||
@@ -202,6 +205,20 @@ var statusTemplate = defTemplate("status", `\
|
||||
TTL: {{.DNS.TTL}}
|
||||
Entries: {{countDNSEntries .DNS.Entries}}
|
||||
{{end}}\
|
||||
{{if .Proxy}}\
|
||||
|
||||
Service: proxy
|
||||
Address: {{printList .Proxy.Addresses}}
|
||||
{{end}}\
|
||||
{{if .Plugin}}\
|
||||
|
||||
{{if .Plugin.Config.EnableV2}}\
|
||||
Service: plugin (v2)
|
||||
{{else}}\
|
||||
Service: plugin (legacy)
|
||||
DriverName: {{.Plugin.DriverName}}
|
||||
{{end}}\
|
||||
{{end}}\
|
||||
`)
|
||||
|
||||
var targetsTemplate = defTemplate("targetsTemplate", `\
|
||||
@@ -273,22 +290,29 @@ func (v *VersionCheck) String() string {
|
||||
}
|
||||
|
||||
type WeaveStatus struct {
|
||||
Ready bool
|
||||
Version string
|
||||
VersionCheck *VersionCheck `json:"VersionCheck,omitempty"`
|
||||
Router *weave.NetworkRouterStatus `json:"Router,omitempty"`
|
||||
IPAM *ipam.Status `json:"IPAM,omitempty"`
|
||||
DNS *nameserver.Status `json:"DNS,omitempty"`
|
||||
Proxy *proxy.Status `json:"Proxy,omitempty"`
|
||||
Plugin *plugin.Status `json:"Plugin,omitempty"`
|
||||
}
|
||||
|
||||
// Read-only functions, suitable for exposing on an unprotected socket
|
||||
func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRouter, allocator *ipam.Allocator, defaultSubnet address.CIDR, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer) {
|
||||
func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRouter, allocator *ipam.Allocator, defaultSubnet address.CIDR, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer, prxy *proxy.Proxy, plugin *plugin.Plugin, waitReady *common.WaitGroup) {
|
||||
status := func() WeaveStatus {
|
||||
return WeaveStatus{
|
||||
waitReady.IsDone(),
|
||||
version,
|
||||
versionCheck(),
|
||||
weave.NewNetworkRouterStatus(router),
|
||||
ipam.NewStatus(allocator, defaultSubnet),
|
||||
nameserver.NewStatus(ns, dnsserver)}
|
||||
nameserver.NewStatus(ns, dnsserver),
|
||||
proxy.NewStatus(prxy),
|
||||
plugin.NewStatus(),
|
||||
}
|
||||
}
|
||||
muxRouter.Methods("GET").Path("/report").Headers("Accept", "application/json").HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -324,7 +348,11 @@ func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRout
|
||||
defHandler := func(path string, template *template.Template) {
|
||||
muxRouter.Methods("GET").Path(path).HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := template.Execute(w, status()); err != nil {
|
||||
s := status()
|
||||
if !s.Ready {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
}
|
||||
if err := template.Execute(w, s); err != nil {
|
||||
http.Error(w, "error during template execution", http.StatusInternalServerError)
|
||||
Log.Error(err)
|
||||
}
|
||||
|
||||
+218
-79
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pkg/profile"
|
||||
"github.com/weaveworks/common/mflag"
|
||||
"github.com/weaveworks/common/mflagext"
|
||||
"github.com/weaveworks/common/signals"
|
||||
"github.com/weaveworks/mesh"
|
||||
|
||||
@@ -25,6 +26,8 @@ import (
|
||||
"github.com/weaveworks/weave/nameserver"
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
"github.com/weaveworks/weave/net/address"
|
||||
"github.com/weaveworks/weave/plugin"
|
||||
weaveproxy "github.com/weaveworks/weave/proxy"
|
||||
weave "github.com/weaveworks/weave/router"
|
||||
)
|
||||
|
||||
@@ -53,7 +56,7 @@ type dnsConfig struct {
|
||||
func (c *ipamConfig) Enabled() bool {
|
||||
var (
|
||||
hasPeerCount = c.PeerCount > 0
|
||||
hasMode = len(c.Mode) > 0
|
||||
hasMode = c.HasMode()
|
||||
hasRange = c.IPRangeCIDR != ""
|
||||
hasSubnet = c.IPSubnetCIDR != ""
|
||||
)
|
||||
@@ -63,9 +66,7 @@ func (c *ipamConfig) Enabled() bool {
|
||||
case !hasRange && hasSubnet:
|
||||
Log.Fatal("--ipalloc-default-subnet specified without --ipalloc-range.")
|
||||
case !hasRange:
|
||||
Log.Fatal("--ipalloc-init or --init-peer-count specified without --ipalloc-range.")
|
||||
case hasMode && hasPeerCount:
|
||||
Log.Fatal("At most one of --ipalloc-init or --init-peer-count may be specified.")
|
||||
Log.Fatal("--ipalloc-init specified without --ipalloc-range.")
|
||||
}
|
||||
if hasMode {
|
||||
if err := c.parseMode(); err != nil {
|
||||
@@ -75,6 +76,10 @@ func (c *ipamConfig) Enabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c ipamConfig) HasMode() bool {
|
||||
return len(c.Mode) > 0
|
||||
}
|
||||
|
||||
func (c *ipamConfig) parseMode() error {
|
||||
modeAndParam := strings.SplitN(c.Mode, "=", 2)
|
||||
|
||||
@@ -108,6 +113,13 @@ func (c *ipamConfig) parseMode() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getenvOrDefault(key, defaultVal string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
func main() {
|
||||
procs := runtime.NumCPU()
|
||||
// packet sniffing can block an OS thread, so we need one thread
|
||||
@@ -120,15 +132,15 @@ func main() {
|
||||
var (
|
||||
justVersion bool
|
||||
config mesh.Config
|
||||
bridgeConfig weavenet.BridgeConfig
|
||||
networkConfig weave.NetworkConfig
|
||||
protocolMinVersion int
|
||||
resume bool
|
||||
ifaceName string
|
||||
routerName string
|
||||
nickName string
|
||||
password string
|
||||
pktdebug bool
|
||||
logLevel string
|
||||
logLevel = "info"
|
||||
prof string
|
||||
bufSzMB int
|
||||
noDiscovery bool
|
||||
@@ -139,40 +151,41 @@ func main() {
|
||||
peers []string
|
||||
noDNS bool
|
||||
dnsConfig dnsConfig
|
||||
datapathName string
|
||||
trustedSubnetStr string
|
||||
dbPrefix string
|
||||
isAWSVPC bool
|
||||
|
||||
defaultDockerHost = "unix:///var/run/docker.sock"
|
||||
hostRoot string
|
||||
procPath string
|
||||
discoveryEndpoint string
|
||||
token string
|
||||
advertiseAddress string
|
||||
pluginConfig plugin.Config
|
||||
defaultDockerHost = getenvOrDefault("DOCKER_HOST", "unix:///var/run/docker.sock")
|
||||
)
|
||||
|
||||
if val := os.Getenv("DOCKER_HOST"); val != "" {
|
||||
defaultDockerHost = val
|
||||
}
|
||||
|
||||
mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit")
|
||||
mflag.BoolVar(&justVersion, []string{"-version"}, false, "print version and exit")
|
||||
mflag.StringVar(&config.Host, []string{"-host"}, "", "router host")
|
||||
mflag.IntVar(&config.Port, []string{"#port", "-port"}, mesh.Port, "router port")
|
||||
mflag.IntVar(&config.Port, []string{"-port"}, mesh.Port, "router port")
|
||||
mflag.IntVar(&protocolMinVersion, []string{"-min-protocol-version"}, mesh.ProtocolMinVersion, "minimum weave protocol version")
|
||||
mflag.BoolVar(&resume, []string{"-resume"}, false, "resume connections to previous peers")
|
||||
mflag.StringVar(&ifaceName, []string{"#iface", "-iface"}, "", "name of interface to capture/inject from (disabled if blank)")
|
||||
mflag.StringVar(&routerName, []string{"#name", "-name"}, "", "name of router (defaults to MAC of interface)")
|
||||
mflag.StringVar(&nickName, []string{"#nickname", "-nickname"}, "", "nickname of peer (defaults to hostname)")
|
||||
mflag.StringVar(&password, []string{"#password", "-password"}, "", "network password")
|
||||
mflag.StringVar(&bridgeConfig.WeaveBridgeName, []string{"-weave-bridge"}, "weave", "name of weave bridge")
|
||||
mflag.StringVar(&bridgeConfig.DockerBridgeName, []string{"-docker-bridge"}, "", "name of Docker bridge")
|
||||
mflag.BoolVar(&bridgeConfig.NPC, []string{"-expect-npc"}, false, "set up iptables rules for npc")
|
||||
mflag.StringVar(&routerName, []string{"-name"}, "", "name of router (defaults to MAC of interface)")
|
||||
mflag.StringVar(&nickName, []string{"-nickname"}, "", "nickname of peer (defaults to hostname)")
|
||||
mflag.StringVar(&password, []string{"-password"}, "", "network password")
|
||||
mflag.StringVar(&logLevel, []string{"-log-level"}, "info", "logging level (debug, info, warning, error)")
|
||||
mflag.BoolVar(&pktdebug, []string{"#pktdebug", "#-pktdebug", "-pkt-debug"}, false, "enable per-packet debug logging")
|
||||
mflag.StringVar(&prof, []string{"#profile", "-profile"}, "", "enable profiling and write profiles to given path")
|
||||
mflag.IntVar(&config.ConnLimit, []string{"#connlimit", "#-connlimit", "-conn-limit"}, 30, "connection limit (0 for unlimited)")
|
||||
mflag.BoolVar(&noDiscovery, []string{"#nodiscovery", "#-nodiscovery", "-no-discovery"}, false, "disable peer discovery")
|
||||
mflag.IntVar(&bufSzMB, []string{"#bufsz", "-bufsz"}, 8, "capture buffer size in MB")
|
||||
mflag.StringVar(&httpAddr, []string{"#httpaddr", "#-httpaddr", "-http-addr"}, "", "address to bind HTTP interface to (disabled if blank, absolute path indicates unix domain socket)")
|
||||
mflag.BoolVar(&pktdebug, []string{"-pkt-debug"}, false, "enable per-packet debug logging")
|
||||
mflag.StringVar(&prof, []string{"-profile"}, "", "enable profiling and write profiles to given path")
|
||||
mflag.IntVar(&config.ConnLimit, []string{"-conn-limit"}, 30, "connection limit (0 for unlimited)")
|
||||
mflag.BoolVar(&noDiscovery, []string{"-no-discovery"}, false, "disable peer discovery")
|
||||
mflag.IntVar(&bufSzMB, []string{"-bufsz"}, 8, "capture buffer size in MB")
|
||||
mflag.IntVar(&bridgeConfig.MTU, []string{"-mtu"}, 0, "MTU size")
|
||||
mflag.StringVar(&httpAddr, []string{"-http-addr"}, "", "address to bind HTTP interface to (disabled if blank, absolute path indicates unix domain socket)")
|
||||
mflag.StringVar(&statusAddr, []string{"-status-addr"}, "", "address to bind status+metrics interface to (disabled if blank, absolute path indicates unix domain socket)")
|
||||
mflag.StringVar(&ipamConfig.Mode, []string{"-ipalloc-init"}, "", "allocator initialisation strategy (consensus, seed or observer)")
|
||||
mflag.StringVar(&ipamConfig.IPRangeCIDR, []string{"#iprange", "#-iprange", "-ipalloc-range"}, "", "IP address range reserved for automatic allocation, in CIDR notation")
|
||||
mflag.StringVar(&ipamConfig.IPSubnetCIDR, []string{"#ipsubnet", "#-ipsubnet", "-ipalloc-default-subnet"}, "", "subnet to allocate within by default, in CIDR notation")
|
||||
mflag.IntVar(&ipamConfig.PeerCount, []string{"#initpeercount", "#-initpeercount", "-init-peer-count"}, 0, "number of peers in network (for IP address allocation)")
|
||||
mflag.StringVar(&dockerAPI, []string{"#api", "#-api", "-docker-api"}, defaultDockerHost, "Docker API endpoint")
|
||||
mflag.StringVar(&ipamConfig.IPRangeCIDR, []string{"-ipalloc-range"}, "", "IP address range reserved for automatic allocation, in CIDR notation")
|
||||
mflag.StringVar(&ipamConfig.IPSubnetCIDR, []string{"-ipalloc-default-subnet"}, "", "subnet to allocate within by default, in CIDR notation")
|
||||
mflag.StringVar(&dockerAPI, []string{"-docker-api"}, defaultDockerHost, "Docker API endpoint")
|
||||
mflag.BoolVar(&noDNS, []string{"-no-dns"}, false, "disable DNS server")
|
||||
mflag.StringVar(&dnsConfig.Domain, []string{"-dns-domain"}, nameserver.DefaultDomain, "local domain to server requests for")
|
||||
mflag.StringVar(&dnsConfig.ListenAddress, []string{"-dns-listen-address"}, nameserver.DefaultListenAddress, "address to listen on for DNS requests")
|
||||
@@ -180,10 +193,28 @@ func main() {
|
||||
mflag.DurationVar(&dnsConfig.ClientTimeout, []string{"-dns-fallback-timeout"}, nameserver.DefaultClientTimeout, "timeout for fallback DNS requests")
|
||||
mflag.StringVar(&dnsConfig.EffectiveListenAddress, []string{"-dns-effective-listen-address"}, "", "address DNS will actually be listening, after Docker port mapping")
|
||||
mflag.StringVar(&dnsConfig.ResolvConf, []string{"-resolv-conf"}, "", "path to resolver configuration for fallback DNS lookups")
|
||||
mflag.StringVar(&datapathName, []string{"-datapath"}, "", "ODP datapath name")
|
||||
mflag.StringVar(&bridgeConfig.DatapathName, []string{"-datapath"}, "", "ODP datapath name")
|
||||
mflag.BoolVar(&bridgeConfig.NoFastdp, []string{"-no-fastdp"}, false, "Disable Fast Datapath")
|
||||
mflag.StringVar(&trustedSubnetStr, []string{"-trusted-subnets"}, "", "comma-separated list of trusted subnets in CIDR notation")
|
||||
mflag.StringVar(&dbPrefix, []string{"-db-prefix"}, "/weavedb/weave", "pathname/prefix of filename to store data")
|
||||
mflag.BoolVar(&isAWSVPC, []string{"-awsvpc"}, false, "use AWS VPC for routing")
|
||||
mflag.StringVar(&procPath, []string{"-proc-path"}, "/proc", "path to reach host /proc filesystem")
|
||||
mflag.BoolVar(&bridgeConfig.AWSVPC, []string{"-awsvpc"}, false, "use AWS VPC for routing")
|
||||
mflag.StringVar(&hostRoot, []string{"-host-root"}, "", "path to reach host filesystem")
|
||||
mflag.StringVar(&discoveryEndpoint, []string{"-peer-discovery-url"}, "https://cloud.weave.works/api/net", "url for peer discovery")
|
||||
mflag.StringVar(&token, []string{"-token"}, "", "token for peer discovery")
|
||||
mflag.StringVar(&advertiseAddress, []string{"-advertise-address"}, "", "address to advertise for peer discovery")
|
||||
|
||||
mflag.BoolVar(&pluginConfig.Enable, []string{"-plugin"}, false, "enable Docker plugin (v1)")
|
||||
mflag.BoolVar(&pluginConfig.EnableV2, []string{"-plugin-v2"}, false, "enable Docker plugin (v2)")
|
||||
mflag.BoolVar(&pluginConfig.EnableV2Multicast, []string{"-plugin-v2-multicast"}, false, "enable multicast for Docker plugin (v2)")
|
||||
mflag.StringVar(&pluginConfig.Socket, []string{"-plugin-socket"}, "/run/docker/plugins/weave.sock", "plugin socket on which to listen")
|
||||
mflag.StringVar(&pluginConfig.MeshSocket, []string{"-plugin-mesh-socket"}, "/run/docker/plugins/weavemesh.sock", "plugin socket on which to listen in mesh mode")
|
||||
|
||||
proxyConfig := configureProxy(version, defaultDockerHost)
|
||||
if bridgeConfig.AWSVPC {
|
||||
proxyConfig.NoMulticastRoute = true
|
||||
proxyConfig.KeepTXOn = true
|
||||
}
|
||||
|
||||
// crude way of detecting that we probably have been started in a
|
||||
// container, with `weave launch` --> suppress misleading paths in
|
||||
@@ -195,19 +226,19 @@ func main() {
|
||||
|
||||
mflag.Parse()
|
||||
|
||||
if justVersion {
|
||||
fmt.Printf("weave %s\n", version)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
peers = mflag.Args()
|
||||
if resume && len(peers) > 0 {
|
||||
Log.Fatalf("You must not specify an initial peer list in conjunction with --resume")
|
||||
}
|
||||
|
||||
common.SetLogLevel(logLevel)
|
||||
|
||||
if justVersion {
|
||||
fmt.Printf("weave router %s\n", version)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
Log.Println("Command line options:", options())
|
||||
Log.Infoln("weave ", version)
|
||||
|
||||
if prof != "" {
|
||||
defer profile.Start(profile.CPUProfile, profile.ProfilePath(prof), profile.NoShutdownHook).Stop()
|
||||
@@ -218,26 +249,55 @@ func main() {
|
||||
}
|
||||
config.ProtocolMinVersion = byte(protocolMinVersion)
|
||||
|
||||
var waitReady common.WaitGroup
|
||||
|
||||
var proxy *weaveproxy.Proxy
|
||||
var err error
|
||||
if proxyConfig.Enabled {
|
||||
// Start Weave Proxy:
|
||||
proxy, err = weaveproxy.NewProxy(*proxyConfig)
|
||||
if err != nil {
|
||||
Log.Fatalf("Could not start proxy: %s", err)
|
||||
}
|
||||
defer proxy.Stop()
|
||||
listeners := proxy.Listen()
|
||||
proxy.AttachExistingContainers()
|
||||
go proxy.Serve(listeners, waitReady.Add())
|
||||
}
|
||||
|
||||
if pktdebug {
|
||||
networkConfig.PacketLogging = packetLogging{}
|
||||
} else {
|
||||
networkConfig.PacketLogging = nopPacketLogging{}
|
||||
}
|
||||
|
||||
if bridgeConfig.DockerBridgeName != "" {
|
||||
if setAddr, err := weavenet.EnforceAddrAssignType(bridgeConfig.DockerBridgeName); err != nil {
|
||||
Log.Errorf("While checking address assignment type of %s: %s", bridgeConfig.DockerBridgeName, err)
|
||||
} else if setAddr {
|
||||
Log.Warningf("Setting %s MAC (mitigate https://github.com/docker/docker/issues/14908)", bridgeConfig.DockerBridgeName)
|
||||
}
|
||||
}
|
||||
|
||||
name := peerName(routerName, bridgeConfig.WeaveBridgeName, dbPrefix, hostRoot)
|
||||
|
||||
bridgeConfig.Mac = name.String()
|
||||
bridgeType, err := weavenet.EnsureBridge(procPath, &bridgeConfig, Log)
|
||||
checkFatal(err)
|
||||
Log.Println("Bridge type is", bridgeType)
|
||||
|
||||
config.Password = determinePassword(password)
|
||||
|
||||
overlay, bridge := createOverlay(datapathName, ifaceName, isAWSVPC, config.Host, config.Port, bufSzMB, config.Password != nil)
|
||||
networkConfig.Bridge = bridge
|
||||
overlay, injectorConsumer := createOverlay(bridgeType, bridgeConfig, config.Host, config.Port, bufSzMB, config.Password != nil)
|
||||
networkConfig.InjectorConsumer = injectorConsumer
|
||||
|
||||
if bridge != nil {
|
||||
if injectorConsumer != nil {
|
||||
if err := weavenet.DetectHairpin("vethwe-bridge", Log); err != nil {
|
||||
Log.Errorf("Setting may cause connectivity issues : %s", err)
|
||||
Log.Infof("Hairpin mode may have been enabled by other software on this machine")
|
||||
}
|
||||
}
|
||||
|
||||
name := peerName(routerName)
|
||||
|
||||
if nickName == "" {
|
||||
var err error
|
||||
nickName, err = os.Hostname()
|
||||
@@ -247,11 +307,14 @@ func main() {
|
||||
config.TrustedSubnets = parseTrustedSubnets(trustedSubnetStr)
|
||||
config.PeerDiscovery = !noDiscovery
|
||||
|
||||
if isAWSVPC && len(config.Password) > 0 {
|
||||
if bridgeConfig.AWSVPC && len(config.Password) > 0 {
|
||||
Log.Fatalf("--awsvpc mode is not compatible with the --password option")
|
||||
}
|
||||
if bridgeConfig.AWSVPC && !ipamConfig.Enabled() {
|
||||
Log.Fatalf("--awsvpc mode requires IPAM enabled")
|
||||
}
|
||||
|
||||
db, err := db.NewBoltDB(dbPrefix + db.FileName)
|
||||
db, err := db.NewBoltDB(dbPrefix)
|
||||
checkFatal(err)
|
||||
defer db.Close()
|
||||
|
||||
@@ -259,7 +322,24 @@ func main() {
|
||||
checkFatal(err)
|
||||
Log.Println("Our name is", router.Ourself)
|
||||
|
||||
if peers, err = router.InitialPeers(resume, peers); err != nil {
|
||||
if token != "" {
|
||||
var addresses []string
|
||||
if advertiseAddress == "" {
|
||||
localAddrs, err := weavenet.LocalAddresses()
|
||||
checkFatal(err)
|
||||
for _, addr := range localAddrs {
|
||||
addresses = append(addresses, addr.IP.String())
|
||||
}
|
||||
} else {
|
||||
addresses = strings.Split(advertiseAddress, ",")
|
||||
}
|
||||
discoveredPeers, count, err := peerDiscoveryUpdate(discoveryEndpoint, token, name.String(), nickName, addresses)
|
||||
checkFatal(err)
|
||||
if !ipamConfig.HasMode() {
|
||||
ipamConfig.PeerCount = len(peers) + count
|
||||
}
|
||||
peers = append(peers, discoveredPeers...)
|
||||
} else if peers, err = router.InitialPeers(resume, peers); err != nil {
|
||||
Log.Fatal("Unable to get initial peer set: ", err)
|
||||
}
|
||||
|
||||
@@ -296,24 +376,26 @@ func main() {
|
||||
)
|
||||
if ipamConfig.Enabled() {
|
||||
var t tracker.LocalRangeTracker
|
||||
if isAWSVPC {
|
||||
if bridgeConfig.AWSVPC {
|
||||
Log.Infoln("Creating AWSVPC LocalRangeTracker")
|
||||
t, err = tracker.NewAWSVPCTracker()
|
||||
t, err = tracker.NewAWSVPCTracker(bridgeConfig.WeaveBridgeName)
|
||||
if err != nil {
|
||||
Log.Fatalf("Cannot create AWSVPC LocalRangeTracker: %s", err)
|
||||
}
|
||||
trackerName = "awsvpc"
|
||||
}
|
||||
var allContainerIDs []string
|
||||
if dockerCli != nil {
|
||||
allContainerIDs, err = dockerCli.AllContainerIDs()
|
||||
checkFatal(err)
|
||||
}
|
||||
preClaims, err := findExistingAddresses(dockerCli, allContainerIDs, weavenet.WeaveBridgeName)
|
||||
|
||||
preClaims, err := findExistingAddresses(dockerCli, bridgeConfig.WeaveBridgeName)
|
||||
checkFatal(err)
|
||||
|
||||
allocator, defaultSubnet = createAllocator(router, ipamConfig, preClaims, db, t, isKnownPeer)
|
||||
observeContainers(allocator)
|
||||
allocator.PruneOwned(allContainerIDs)
|
||||
|
||||
if dockerCli != nil {
|
||||
allContainerIDs, err := dockerCli.RunningContainerIDs()
|
||||
checkFatal(err)
|
||||
allocator.PruneOwned(allContainerIDs)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -326,6 +408,9 @@ func main() {
|
||||
ns.Start()
|
||||
defer ns.Stop()
|
||||
dnsserver.ActivateAndServe()
|
||||
if dockerCli != nil {
|
||||
populateDNS(ns, dockerCli, name, bridgeConfig.WeaveBridgeName)
|
||||
}
|
||||
defer dnsserver.Stop()
|
||||
}
|
||||
|
||||
@@ -335,6 +420,10 @@ func main() {
|
||||
}
|
||||
checkFatal(router.CreateRestartSentinel())
|
||||
|
||||
pluginConfig.DNS = !noDNS
|
||||
pluginConfig.DefaultSubnet = defaultSubnet.String()
|
||||
plugin := plugin.NewPlugin(pluginConfig)
|
||||
|
||||
// The weave script always waits for a status call to succeed,
|
||||
// so there is no point in doing "weave launch --http-addr ''".
|
||||
// This is here to support stand-alone use of weaver.
|
||||
@@ -347,8 +436,12 @@ func main() {
|
||||
ns.HandleHTTP(muxRouter, dockerCli)
|
||||
}
|
||||
router.HandleHTTP(muxRouter)
|
||||
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver)
|
||||
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady)
|
||||
HandleHTTPPeer(muxRouter, allocator, discoveryEndpoint, token, name.String())
|
||||
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver))
|
||||
if proxy != nil {
|
||||
muxRouter.Methods("GET").Path("/proxyaddrs").HandlerFunc(proxy.StatusHTTP)
|
||||
}
|
||||
http.Handle("/", common.LoggingHTTPHandler(muxRouter))
|
||||
Log.Println("Listening for HTTP control messages on", httpAddr)
|
||||
go listenAndServeHTTP(httpAddr, nil)
|
||||
@@ -356,7 +449,7 @@ func main() {
|
||||
|
||||
if statusAddr != "" {
|
||||
muxRouter := mux.NewRouter()
|
||||
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver)
|
||||
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady)
|
||||
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver))
|
||||
statusMux := http.NewServeMux()
|
||||
statusMux.Handle("/", muxRouter)
|
||||
@@ -364,16 +457,37 @@ func main() {
|
||||
go listenAndServeHTTP(statusAddr, statusMux)
|
||||
}
|
||||
|
||||
if plugin != nil {
|
||||
go plugin.Start(httpAddr, dockerCli, waitReady.Add())
|
||||
}
|
||||
|
||||
if bridgeConfig.AWSVPC {
|
||||
// Run this on its own goroutine because the allocator can block
|
||||
// We remove the default route installed by the kernel,
|
||||
// because awsvpc has installed it as well
|
||||
go expose(allocator, defaultSubnet, bridgeConfig.WeaveBridgeName, bridgeConfig.AWSVPC, waitReady.Add())
|
||||
}
|
||||
|
||||
signals.SignalHandlerLoop(common.Log, router)
|
||||
}
|
||||
|
||||
func expose(alloc *ipam.Allocator, subnet address.CIDR, bridgeName string, removeDefaultRoute bool, ready func()) {
|
||||
addr, err := alloc.Allocate("weave:expose", subnet, false, func() bool { return false })
|
||||
checkFatal(err)
|
||||
cidr := address.MakeCIDR(subnet, addr)
|
||||
err = weavenet.AddBridgeAddr(bridgeName, cidr.IPNet(), removeDefaultRoute)
|
||||
checkFatal(err)
|
||||
Log.Printf("Bridge %q exposed on address %v", bridgeName, cidr)
|
||||
ready()
|
||||
}
|
||||
|
||||
func options() map[string]string {
|
||||
options := make(map[string]string)
|
||||
mflag.Visit(func(f *mflag.Flag) {
|
||||
value := f.Value.String()
|
||||
name := canonicalName(f)
|
||||
if name == "password" {
|
||||
value = "<elided>"
|
||||
if name == "password" || name == "token" {
|
||||
value = "<redacted>"
|
||||
}
|
||||
options[name] = value
|
||||
})
|
||||
@@ -407,34 +521,57 @@ func (nopPacketLogging) LogPacket(string, weave.PacketKey) {
|
||||
func (nopPacketLogging) LogForwardPacket(string, weave.ForwardPacketKey) {
|
||||
}
|
||||
|
||||
func createOverlay(datapathName string, ifaceName string, isAWSVPC bool, host string, port int, bufSzMB int, enableEncryption bool) (weave.NetworkOverlay, weave.Bridge) {
|
||||
func configureProxy(version string, defaultDockerHost string) *weaveproxy.Config {
|
||||
proxyConfig := weaveproxy.Config{
|
||||
Version: version,
|
||||
Image: getenvOrDefault("EXEC_IMAGE", "weaveworks/weaveexec"),
|
||||
DockerBridge: getenvOrDefault("DOCKER_BRIDGE", "docker0"),
|
||||
DockerHost: defaultDockerHost,
|
||||
}
|
||||
mflag.BoolVar(&proxyConfig.Enabled, []string{"-proxy"}, false, "instruct Weave Net to start its Docker proxy")
|
||||
mflagext.ListVar(&proxyConfig.ListenAddrs, []string{"H"}, nil, "addresses on which to listen for Docker proxy")
|
||||
mflag.StringVar(&proxyConfig.HostnameFromLabel, []string{"-hostname-from-label"}, "", "Key of container label from which to obtain the container's hostname")
|
||||
mflag.StringVar(&proxyConfig.HostnameMatch, []string{"-hostname-match"}, "(.*)", "Regexp pattern to apply on container names (e.g. '^aws-[0-9]+-(.*)$')")
|
||||
mflag.StringVar(&proxyConfig.HostnameReplacement, []string{"-hostname-replacement"}, "$1", "Expression to generate hostnames based on matches from --hostname-match (e.g. 'my-app-$1')")
|
||||
mflag.BoolVar(&proxyConfig.RewriteInspect, []string{"-rewrite-inspect"}, false, "Rewrite 'inspect' calls to return the weave network settings (if attached)")
|
||||
mflag.BoolVar(&proxyConfig.NoDefaultIPAM, []string{"-no-default-ipalloc"}, false, "proxy: do not automatically allocate addresses for containers without a WEAVE_CIDR")
|
||||
mflag.BoolVar(&proxyConfig.NoRewriteHosts, []string{"-no-rewrite-hosts"}, false, "proxy: do not automatically rewrite /etc/hosts. Use if you need the docker IP to remain in /etc/hosts")
|
||||
mflag.StringVar(&proxyConfig.TLSConfig.CACert, []string{"-tlscacert"}, "", "Trust certs signed only by this CA")
|
||||
mflag.StringVar(&proxyConfig.TLSConfig.Cert, []string{"-tlscert"}, "", "Path to TLS certificate file")
|
||||
mflag.BoolVar(&proxyConfig.TLSConfig.Enabled, []string{"-tls"}, false, "Use TLS; implied by --tlsverify")
|
||||
mflag.StringVar(&proxyConfig.TLSConfig.Key, []string{"-tlskey"}, "", "Path to TLS key file")
|
||||
mflag.BoolVar(&proxyConfig.TLSConfig.Verify, []string{"-tlsverify"}, false, "Use TLS and verify the remote")
|
||||
mflag.BoolVar(&proxyConfig.WithoutDNS, []string{"-without-dns"}, false, "proxy: instruct created containers to never use weaveDNS as their nameserver")
|
||||
mflag.BoolVar(&proxyConfig.NoMulticastRoute, []string{"-no-multicast-route"}, false, "proxy: do not add a multicast route via the weave interface when attaching containers")
|
||||
return &proxyConfig
|
||||
}
|
||||
|
||||
func createOverlay(bridgeType weavenet.Bridge, config weavenet.BridgeConfig, host string, port int, bufSzMB int, enableEncryption bool) (weave.NetworkOverlay, weave.InjectorConsumer) {
|
||||
overlay := weave.NewOverlaySwitch()
|
||||
var bridge weave.Bridge
|
||||
var injectorConsumer weave.InjectorConsumer
|
||||
var ignoreSleeve bool
|
||||
|
||||
switch {
|
||||
case isAWSVPC:
|
||||
case config.AWSVPC:
|
||||
vpc := weave.NewAWSVPC()
|
||||
overlay.Add("awsvpc", vpc)
|
||||
bridge = weave.NullBridge{}
|
||||
injectorConsumer = weave.NullInjectorConsumer{}
|
||||
// Currently, we do not support any overlay with AWSVPC
|
||||
ignoreSleeve = true
|
||||
case datapathName != "" && ifaceName != "":
|
||||
Log.Fatal("At most one of --datapath and --iface must be specified.")
|
||||
case datapathName != "":
|
||||
iface, err := weavenet.EnsureInterface(datapathName)
|
||||
case bridgeType == nil:
|
||||
injectorConsumer = weave.NullInjectorConsumer{}
|
||||
case bridgeType.IsFastdp():
|
||||
iface, err := weavenet.EnsureInterface(config.DatapathName)
|
||||
checkFatal(err)
|
||||
fastdp, err := weave.NewFastDatapath(iface, port, enableEncryption)
|
||||
checkFatal(err)
|
||||
bridge = fastdp.Bridge()
|
||||
injectorConsumer = fastdp.InjectorConsumer()
|
||||
overlay.Add("fastdp", fastdp.Overlay())
|
||||
case ifaceName != "":
|
||||
iface, err := weavenet.EnsureInterface(ifaceName)
|
||||
case !bridgeType.IsFastdp():
|
||||
iface, err := weavenet.EnsureInterface(weavenet.PcapIfName)
|
||||
checkFatal(err)
|
||||
bridge, err = weave.NewPcap(iface, bufSzMB*1024*1024) // bufsz flag is in MB
|
||||
injectorConsumer, err = weave.NewPcap(iface, bufSzMB*1024*1024) // bufsz flag is in MB
|
||||
checkFatal(err)
|
||||
default:
|
||||
bridge = weave.NullBridge{}
|
||||
}
|
||||
|
||||
if !ignoreSleeve {
|
||||
@@ -443,7 +580,7 @@ func createOverlay(datapathName string, ifaceName string, isAWSVPC bool, host st
|
||||
overlay.SetCompatOverlay(sleeve)
|
||||
}
|
||||
|
||||
return overlay, bridge
|
||||
return overlay, injectorConsumer
|
||||
}
|
||||
|
||||
func createAllocator(router *weave.NetworkRouter, config ipamConfig, preClaims []ipam.PreClaim, db db.DB, track tracker.LocalRangeTracker, isKnownPeer func(mesh.PeerName) bool) (*ipam.Allocator, address.CIDR) {
|
||||
@@ -536,13 +673,15 @@ func determinePassword(password string) []byte {
|
||||
return []byte(password)
|
||||
}
|
||||
|
||||
func peerName(routerName string) mesh.PeerName {
|
||||
func peerName(routerName, bridgeName, dbPrefix, hostRoot string) mesh.PeerName {
|
||||
if routerName == "" {
|
||||
iface, err := net.InterfaceByName(weavenet.WeaveBridgeName)
|
||||
if err != nil {
|
||||
Log.Fatalf("Unable to find bridge %q", weavenet.WeaveBridgeName)
|
||||
iface, err := net.InterfaceByName(bridgeName)
|
||||
if err == nil {
|
||||
routerName = iface.HardwareAddr.String()
|
||||
} else {
|
||||
routerName, err = weavenet.GetSystemPeerName(dbPrefix, hostRoot)
|
||||
checkFatal(err)
|
||||
}
|
||||
routerName = iface.HardwareAddr.String()
|
||||
}
|
||||
name, err := mesh.PeerNameFromUserInput(routerName)
|
||||
checkFatal(err)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(t *testing.T) {
|
||||
weavetest.TrimTestArgs()
|
||||
main()
|
||||
if weavetest.TrimTestArgs() {
|
||||
main()
|
||||
}
|
||||
}
|
||||
@@ -118,10 +118,10 @@ func newMetrics(router *weave.NetworkRouter, allocator *ipam.Allocator, ns *name
|
||||
|
||||
func (m *collector) Collect(ch chan<- prometheus.Metric) {
|
||||
|
||||
status := WeaveStatus{"", nil,
|
||||
weave.NewNetworkRouterStatus(m.router),
|
||||
ipam.NewStatus(m.allocator, address.CIDR{}),
|
||||
nameserver.NewStatus(m.ns, m.dnsserver)}
|
||||
status := WeaveStatus{
|
||||
Router: weave.NewNetworkRouterStatus(m.router),
|
||||
IPAM: ipam.NewStatus(m.allocator, address.CIDR{}),
|
||||
DNS: nameserver.NewStatus(m.ns, m.dnsserver)}
|
||||
|
||||
for _, metric := range metrics {
|
||||
metric.Collect(status, metric.Desc, ch)
|
||||
|
||||
+55
-1
@@ -2,13 +2,16 @@ package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
|
||||
"github.com/weaveworks/mesh"
|
||||
"github.com/weaveworks/weave/api"
|
||||
"github.com/weaveworks/weave/common"
|
||||
weavedocker "github.com/weaveworks/weave/common/docker"
|
||||
"github.com/weaveworks/weave/ipam"
|
||||
"github.com/weaveworks/weave/nameserver"
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
"github.com/weaveworks/weave/net/address"
|
||||
)
|
||||
@@ -20,7 +23,7 @@ func a(cidr *net.IPNet) address.CIDR {
|
||||
|
||||
// Get all the existing Weave IPs at startup, so we can stop IPAM
|
||||
// giving out any as duplicates
|
||||
func findExistingAddresses(dockerCli *weavedocker.Client, containerIDs []string, bridgeName string) (addrs []ipam.PreClaim, err error) {
|
||||
func findExistingAddresses(dockerCli *weavedocker.Client, bridgeName string) (addrs []ipam.PreClaim, err error) {
|
||||
Log.Infof("Checking for pre-existing addresses on %s bridge", bridgeName)
|
||||
// First get the address for the bridge
|
||||
bridgeNetDev, err := weavenet.GetBridgeNetDev(bridgeName)
|
||||
@@ -50,6 +53,11 @@ func findExistingAddresses(dockerCli *weavedocker.Client, containerIDs []string,
|
||||
// Now iterate over all containers to see if they have a network
|
||||
// namespace with an attached interface
|
||||
if dockerCli != nil {
|
||||
containerIDs, err := dockerCli.RunningContainerIDs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, cid := range containerIDs {
|
||||
container, err := dockerCli.InspectContainer(cid)
|
||||
if err != nil {
|
||||
@@ -82,3 +90,49 @@ func findExistingAddresses(dockerCli *weavedocker.Client, containerIDs []string,
|
||||
}
|
||||
return addrs, nil
|
||||
}
|
||||
|
||||
func populateDNS(ns *nameserver.Nameserver, dockerCli *weavedocker.Client, ourName mesh.PeerName, bridgeName string) (addrs []ipam.PreClaim, err error) {
|
||||
// Find all veths connected to the bridge
|
||||
peerIDs, err := weavenet.ConnectedToBridgeVethPeerIds(bridgeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Now iterate over all containers to see if they have a network
|
||||
// namespace with an attached interface
|
||||
if dockerCli != nil {
|
||||
containerIDs, err := dockerCli.RunningContainerIDs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, cid := range containerIDs {
|
||||
container, err := dockerCli.InspectContainer(cid)
|
||||
if err != nil {
|
||||
if _, ok := err.(*docker.NoSuchContainer); ok {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if container.State.Pid != 0 {
|
||||
// Docker allows containers to have fqdns in two wauys:
|
||||
// where the container explicitly has a domain name, and when its
|
||||
// hostname contains the domain name, recognized by it having dots.
|
||||
if container.Config.Domainname == "" && !strings.Contains(container.Config.Hostname, ".") {
|
||||
continue
|
||||
}
|
||||
netDevs, err := weavenet.GetNetDevsByVethPeerIds(container.State.Pid, peerIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fqdn := container.Config.Hostname + "." + container.Config.Domainname
|
||||
for _, netDev := range netDevs {
|
||||
for _, cidr := range netDev.CIDRs {
|
||||
ns.AddEntryFQDN(fqdn, cid, ourName, address.FromIP4(cidr.IP))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return addrs, nil
|
||||
}
|
||||
+16
-1
@@ -27,10 +27,25 @@ func containerAddrs(args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
containerArgs := []string{}
|
||||
for _, cid := range args[1:] {
|
||||
if cid == "weave:allids" { // expand to all container IDs
|
||||
all, err := client.ListContainers(docker.ListContainersOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, c := range all {
|
||||
containerArgs = append(containerArgs, c.ID)
|
||||
}
|
||||
} else {
|
||||
containerArgs = append(containerArgs, cid)
|
||||
}
|
||||
}
|
||||
|
||||
var containerIDs []string
|
||||
containers := make(map[string]*docker.Container)
|
||||
|
||||
for _, cid := range args[1:] {
|
||||
for _, cid := range containerArgs {
|
||||
if cid == "weave:expose" {
|
||||
netDev, err := weavenet.GetBridgeNetDev(bridgeName)
|
||||
if err != nil {
|
||||
|
||||
@@ -3,13 +3,16 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
"github.com/vishvananda/netns"
|
||||
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
"github.com/weaveworks/weave/proxy"
|
||||
)
|
||||
|
||||
func attach(args []string) error {
|
||||
@@ -114,3 +117,30 @@ func detach(args []string) error {
|
||||
}
|
||||
return weavenet.DetachContainer(weavenet.NSPathByPid(pid), args[0], weavenet.VethName, cidrs)
|
||||
}
|
||||
|
||||
func rewriteEtcHosts(args []string) error {
|
||||
if len(args) < 4 {
|
||||
cmdUsage("rewrite-etc-hosts", "<hosts-path> <fqdn> <image> <cidr>... [name:addr...]")
|
||||
}
|
||||
hostsPath := args[0]
|
||||
fqdn := args[1]
|
||||
image := args[2]
|
||||
var ips []*net.IPNet
|
||||
for _, cidr := range strings.Fields(args[3]) {
|
||||
_, ipnet, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ips = append(ips, ipnet)
|
||||
}
|
||||
extraHosts := args[4:]
|
||||
docker := os.Getenv("DOCKER_HOST")
|
||||
if docker == "" {
|
||||
docker = "unix:///var/run/docker.sock"
|
||||
}
|
||||
p, err := proxy.StubProxy(proxy.Config{DockerHost: docker, Image: image})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.RewriteEtcHosts(hostsPath, fqdn, ips, extraHosts)
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/weaveworks/weave/common"
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
)
|
||||
|
||||
func detectBridgeType(args []string) error {
|
||||
if len(args) != 2 {
|
||||
cmdUsage("detect-bridge-type", "<weave-bridge-name> <datapath-name>")
|
||||
}
|
||||
bridgeType, err := weavenet.ExistingBridgeType(args[0], args[1])
|
||||
if err != nil {
|
||||
return err
|
||||
} else if bridgeType == nil {
|
||||
fmt.Println("none")
|
||||
} else {
|
||||
fmt.Println(bridgeType.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createBridge(args []string) error {
|
||||
if len(args) != 10 {
|
||||
cmdUsage("create-bridge", "<docker-bridge-name> <weave-bridge-name> <datapath-name> <mtu> <port> <mac> <no-fastdp> <no-bridged-fastdp> <proc-path> <expect-npc>")
|
||||
}
|
||||
|
||||
mtu, err := strconv.Atoi(args[3])
|
||||
if err != nil && args[3] != "" {
|
||||
return err
|
||||
}
|
||||
port, err := strconv.Atoi(args[4])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config := weavenet.BridgeConfig{
|
||||
DockerBridgeName: args[0],
|
||||
WeaveBridgeName: args[1],
|
||||
DatapathName: args[2],
|
||||
MTU: mtu,
|
||||
Port: port,
|
||||
Mac: args[5],
|
||||
NoFastdp: args[6] != "",
|
||||
NoBridgedFastdp: args[7] != "",
|
||||
NPC: args[9] == "--expect-npc",
|
||||
}
|
||||
procPath := args[8]
|
||||
bridgeType, err := weavenet.EnsureBridge(procPath, &config, common.Log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(bridgeType.String())
|
||||
return nil
|
||||
}
|
||||
+29
-23
@@ -14,29 +14,34 @@ var commands map[string]func([]string) error
|
||||
|
||||
func init() {
|
||||
commands = map[string]func([]string) error{
|
||||
"help": help,
|
||||
"netcheck": netcheck,
|
||||
"docker-tls-args": dockerTLSArgs,
|
||||
"create-datapath": createDatapath,
|
||||
"delete-datapath": deleteDatapath,
|
||||
"check-datapath": checkDatapath,
|
||||
"add-datapath-interface": addDatapathInterface,
|
||||
"create-plugin-network": createPluginNetwork,
|
||||
"remove-plugin-network": removePluginNetwork,
|
||||
"container-addrs": containerAddrs,
|
||||
"process-addrs": processAddrs,
|
||||
"attach-container": attach,
|
||||
"detach-container": detach,
|
||||
"configure-arp": configureARP,
|
||||
"check-iface": checkIface,
|
||||
"del-iface": delIface,
|
||||
"setup-iface": setupIface,
|
||||
"list-netdevs": listNetDevs,
|
||||
"cni-net": cniNet,
|
||||
"cni-ipam": cniIPAM,
|
||||
"expose-nat": exposeNAT,
|
||||
"bridge-ip": bridgeIP,
|
||||
"unique-id": uniqueID,
|
||||
"help": help,
|
||||
"netcheck": netcheck,
|
||||
"docker-tls-args": dockerTLSArgs,
|
||||
"create-bridge": createBridge,
|
||||
"detect-bridge-type": detectBridgeType,
|
||||
"create-datapath": createDatapath,
|
||||
"delete-datapath": deleteDatapath,
|
||||
"check-datapath": checkDatapath,
|
||||
"add-datapath-interface": addDatapathInterface,
|
||||
"remove-plugin-network": removePluginNetwork,
|
||||
"container-addrs": containerAddrs,
|
||||
"process-addrs": processAddrs,
|
||||
"attach-container": attach,
|
||||
"detach-container": detach,
|
||||
"configure-arp": configureARP,
|
||||
"check-iface": checkIface,
|
||||
"del-iface": delIface,
|
||||
"setup-iface": setupIface,
|
||||
"setup-iface-addrs": setupIfaceAddrs,
|
||||
"list-netdevs": listNetDevs,
|
||||
"cni-net": cniNet,
|
||||
"cni-ipam": cniIPAM,
|
||||
"expose-nat": exposeNAT,
|
||||
"bridge-ip": bridgeIP,
|
||||
"unique-id": uniqueID,
|
||||
"swarm-manager-peers": swarmManagerPeers,
|
||||
"is-docker-plugin-enabled": isDockerPluginEnabled,
|
||||
"rewrite-etc-hosts": rewriteEtcHosts,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +70,7 @@ func main() {
|
||||
}
|
||||
cmd, found := commands[os.Args[1]]
|
||||
if !found {
|
||||
fmt.Fprintf(os.Stderr, "%q cmd is not found\n", os.Args[1])
|
||||
usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
+17
-16
@@ -6,7 +6,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/go-iptables/iptables"
|
||||
"github.com/j-keck/arping"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
@@ -48,33 +47,35 @@ func setupIface(args []string) error {
|
||||
ifaceName := args[0]
|
||||
newIfName := args[1]
|
||||
|
||||
ipt, err := iptables.New()
|
||||
return weavenet.SetupIface(ifaceName, newIfName)
|
||||
}
|
||||
|
||||
// setupIfaceAddrs sets up addresses on an interface. It expects to be called inside the container's netns.
|
||||
func setupIfaceAddrs(args []string) error {
|
||||
if len(args) < 1 {
|
||||
cmdUsage("setup-iface-addrs", "<iface-name> <with-multicast> <cidr>...")
|
||||
}
|
||||
link, err := netlink.LinkByName(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
link, err := netlink.LinkByName(ifaceName)
|
||||
withMulticastRoute, err := strconv.ParseBool(args[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := netlink.LinkSetName(link, newIfName); err != nil {
|
||||
cidrs, err := parseCIDRs(args[2:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := weavenet.ConfigureARPCache(newIfName); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ipt.Append("filter", "INPUT", "-i", newIfName, "-d", "224.0.0.0/4", "-j", "DROP"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return weavenet.SetupIfaceAddrs(link, withMulticastRoute, cidrs)
|
||||
}
|
||||
|
||||
func configureARP(args []string) error {
|
||||
if len(args) != 1 {
|
||||
cmdUsage("configure-arp", "<iface-name-prefix>")
|
||||
if len(args) != 2 {
|
||||
cmdUsage("configure-arp", "<iface-name-prefix> <root-path>")
|
||||
}
|
||||
prefix := args[0]
|
||||
rootPath := args[1]
|
||||
|
||||
links, err := netlink.LinkList()
|
||||
if err != nil {
|
||||
@@ -83,7 +84,7 @@ func configureARP(args []string) error {
|
||||
for _, link := range links {
|
||||
ifName := link.Attrs().Name
|
||||
if strings.HasPrefix(ifName, prefix) {
|
||||
weavenet.ConfigureARPCache(ifName)
|
||||
weavenet.ConfigureARPCache(rootPath+"/proc", ifName)
|
||||
if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil {
|
||||
for _, addr := range addrs {
|
||||
arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName)
|
||||
|
||||
@@ -2,47 +2,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
|
||||
"github.com/weaveworks/weave/plugin/net"
|
||||
)
|
||||
|
||||
func createPluginNetwork(args []string) error {
|
||||
if len(args) != 3 {
|
||||
cmdUsage("create-plugin-network", "<network-name> <driver-name> <default-subnet>")
|
||||
}
|
||||
networkName := args[0]
|
||||
driverName := args[1]
|
||||
subnet := args[2]
|
||||
d, err := newDockerClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.CreateNetwork(
|
||||
docker.CreateNetworkOptions{
|
||||
Name: networkName,
|
||||
CheckDuplicate: true,
|
||||
Driver: driverName,
|
||||
IPAM: docker.IPAMOptions{
|
||||
Driver: driverName,
|
||||
Config: []docker.IPAMConfig{{Subnet: subnet}},
|
||||
},
|
||||
Options: map[string]interface{}{plugin.MulticastOption: "true"},
|
||||
})
|
||||
if err != docker.ErrNetworkAlreadyExists && err != nil {
|
||||
// Despite appearances to the contrary, CreateNetwork does
|
||||
// sometimes(always?) *not* return ErrNetworkAlreadyExists
|
||||
// when the network already exists. Hence we need to check for
|
||||
// this explicitly.
|
||||
if _, err2 := d.NetworkInfo(networkName); err2 != nil {
|
||||
return fmt.Errorf("unable to create network: %s", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func removePluginNetwork(args []string) error {
|
||||
if len(args) != 1 {
|
||||
cmdUsage("remove-plugin-network", "<network-name>")
|
||||
@@ -71,6 +38,41 @@ while Weave is not running`, networkName, containers)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exits with 0 if the given plugin (v2) is enabled.
|
||||
//
|
||||
// Any failure due to missing plugin support is non-harmful as plugin (v2)
|
||||
// cannot be enabled when Docker does not support it.
|
||||
func isDockerPluginEnabled(args []string) error {
|
||||
if len(args) != 1 {
|
||||
cmdUsage("is-docker-plugin-enabled", "<plugin-name>")
|
||||
}
|
||||
|
||||
pluginName := args[0]
|
||||
|
||||
// This is messed up: we are using docker/docker/client instead of
|
||||
// fsouza/go-dockerclient because the latter does not support plugins.
|
||||
c, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to connect to docker: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
plugins, err := c.PluginList(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, p := range plugins {
|
||||
if p.Enabled && strings.Contains(p.Name, pluginName) {
|
||||
fmt.Println(p.Name)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("plugin %q not found", pluginName)
|
||||
}
|
||||
|
||||
func newDockerClient() (*docker.Client, error) {
|
||||
// API 1.21 is the first version that supports docker network
|
||||
// commands
|
||||
@@ -82,5 +84,6 @@ func newDockerClient() (*docker.Client, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to connect to docker: %s", err)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fsouza/go-dockerclient"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const DOCKER_API_VERSION = "1.26"
|
||||
|
||||
func swarmManagerPeers(args []string) error {
|
||||
info, err := dockerInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ips := make([]string, 0)
|
||||
|
||||
for _, managerNode := range info.Swarm.RemoteManagers {
|
||||
ip, err := ipFromAddr(managerNode.Addr)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "ipFromAddr")
|
||||
}
|
||||
ips = append(ips, ip)
|
||||
}
|
||||
|
||||
fmt.Println(strings.Join(ips, " "))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func dockerInfo() (*docker.DockerInfo, error) {
|
||||
client, err := docker.NewVersionedClientFromEnv(DOCKER_API_VERSION)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "docker.NewVersionedClientFromEnv")
|
||||
}
|
||||
|
||||
info, err := client.Info()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "docker.Info")
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func ipFromAddr(addr string) (string, error) {
|
||||
parts := strings.Split(addr, ":")
|
||||
if len(parts) != 2 {
|
||||
return "", fmt.Errorf("invalid address: %q", addr)
|
||||
}
|
||||
|
||||
return parts[0], nil
|
||||
}
|
||||
+2
-36
@@ -6,13 +6,12 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/fsouza/go-dockerclient"
|
||||
"github.com/weaveworks/weave/common"
|
||||
weavedocker "github.com/weaveworks/weave/common/docker"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -24,39 +23,6 @@ var (
|
||||
Log = common.Log
|
||||
)
|
||||
|
||||
func callWeave(args ...string) ([]byte, []byte, error) {
|
||||
args = append([]string{"--local"}, args...)
|
||||
cmd := exec.Command("./weave", args...)
|
||||
cmd.Env = []string{
|
||||
"PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
}
|
||||
|
||||
propagateEnv := func(key string) {
|
||||
if val := os.Getenv(key); val != "" {
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, val))
|
||||
}
|
||||
}
|
||||
|
||||
propagateEnv("DOCKER_HOST")
|
||||
|
||||
// Propagate WEAVE_DEBUG, to make debugging easier.
|
||||
propagateEnv("WEAVE_DEBUG")
|
||||
|
||||
// This prevents the code coverage contortions in our
|
||||
// integration test suite breaking things.
|
||||
propagateEnv("COVERAGE")
|
||||
|
||||
// In case the router control endpoint address is non-standard.
|
||||
propagateEnv("WEAVE_HTTP_ADDR")
|
||||
|
||||
Log.Debug("Calling weave args: ", args, "env: ", cmd.Env)
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
err := cmd.Run()
|
||||
return stdout.Bytes(), stderr.Bytes(), err
|
||||
}
|
||||
|
||||
func unmarshalRequestBody(r *http.Request, target interface{}) error {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
@@ -113,7 +79,7 @@ func marshalResponseBody(r *http.Response, body interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func inspectContainerInPath(client *docker.Client, path string) (*docker.Container, error) {
|
||||
func inspectContainerInPath(client *weavedocker.Client, path string) (*docker.Container, error) {
|
||||
subs := containerIDRegexp.FindStringSubmatch(path)
|
||||
if subs == nil {
|
||||
err := fmt.Errorf("No container id found in request with path %s", path)
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// rewrite /etc/hosts, unlinking the file (so Docker does not modify it again) but
|
||||
// leaving it with valid contents...
|
||||
func (proxy *Proxy) RewriteEtcHosts(hostsPath, fqdn string, ips []*net.IPNet, extraHosts []string) error {
|
||||
hostsPathDir := path.Dir(hostsPath)
|
||||
mnt := "/container"
|
||||
mntHosts := path.Join(mnt, path.Base(hostsPath))
|
||||
var buf bytes.Buffer
|
||||
writeEtcHostsContents(&buf, fqdn, ips, extraHosts)
|
||||
contents := buf.String()
|
||||
cmdLine := fmt.Sprintf("echo '%s' > %s && rm -f %s && echo '%s' > %s", contents, mntHosts, mntHosts, contents, mntHosts)
|
||||
mounts := []string{hostsPathDir + ":" + mnt}
|
||||
proxy.runTransientContainer([]string{"sh"}, []string{"-c", cmdLine}, mounts)
|
||||
return nil
|
||||
}
|
||||
|
||||
// we assume (for compatibility with the weave script) that fqdn has a dot
|
||||
// between hostname and domain. domain may be blank.
|
||||
func writeEtcHostsContents(w io.Writer, fqdn string, cidrs []*net.IPNet, extraHosts []string) {
|
||||
index := strings.Index(fqdn, ".")
|
||||
name := fqdn[:index]
|
||||
var hostnames string
|
||||
if index == len(fqdn)-1 { // dot comes at the end - no domain
|
||||
hostnames = name
|
||||
} else {
|
||||
if fqdn[len(fqdn)-1] == '.' { // strip a final trailing dot
|
||||
fqdn = fqdn[:len(fqdn)-1]
|
||||
}
|
||||
hostnames = fqdn + " " + name
|
||||
}
|
||||
|
||||
fmt.Fprintln(w, "# created by Weave - BEGIN")
|
||||
fmt.Fprintln(w, "# container hostname")
|
||||
for _, cidr := range cidrs {
|
||||
fmt.Fprintf(w, "%-15s %s\n", cidr.IP, hostnames)
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
fmt.Fprintln(w, "# static names added with --add-host")
|
||||
for _, eh := range extraHosts {
|
||||
parts := strings.SplitN(eh, ":", 2)
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "%-15s %s\n", parts[1], parts[0])
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
fmt.Fprintln(w, "# default localhost entries")
|
||||
fmt.Fprintln(w, "127.0.0.1 localhost")
|
||||
fmt.Fprintln(w, "::1 ip6-localhost ip6-loopback")
|
||||
fmt.Fprintln(w, "fe00::0 ip6-localnet")
|
||||
fmt.Fprintln(w, "ff00::0 ip6-mcastprefix")
|
||||
fmt.Fprintln(w, "ff02::1 ip6-allnodes")
|
||||
fmt.Fprintln(w, "ff02::2 ip6-allrouters")
|
||||
fmt.Fprintln(w, "# created by Weave - END")
|
||||
}
|
||||
+93
-71
@@ -3,7 +3,6 @@ package proxy
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -16,10 +15,11 @@ import (
|
||||
"time"
|
||||
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
weaveapi "github.com/weaveworks/weave/api"
|
||||
weavedocker "github.com/weaveworks/weave/common/docker"
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
"github.com/weaveworks/weave/net/address"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -50,6 +50,7 @@ func dockerAPIEndpoint(endpoint string) *regexp.Regexp {
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Enabled bool
|
||||
HostnameFromLabel string
|
||||
HostnameMatch string
|
||||
HostnameReplacement string
|
||||
@@ -62,6 +63,7 @@ type Config struct {
|
||||
Version string
|
||||
WithoutDNS bool
|
||||
NoMulticastRoute bool
|
||||
KeepTXOn bool
|
||||
DockerBridge string
|
||||
DockerHost string
|
||||
}
|
||||
@@ -75,7 +77,8 @@ type wait struct {
|
||||
type Proxy struct {
|
||||
sync.Mutex
|
||||
Config
|
||||
client *docker.Client
|
||||
client *weavedocker.Client
|
||||
weave *weaveapi.Client
|
||||
dockerBridgeIP string
|
||||
hostnameMatchRegexp *regexp.Regexp
|
||||
weaveWaitVolume string
|
||||
@@ -122,16 +125,13 @@ func (j attachJob) Stop() {
|
||||
j.timer.Stop()
|
||||
}
|
||||
|
||||
func NewProxy(c Config) (*Proxy, error) {
|
||||
func StubProxy(c Config) (*Proxy, error) {
|
||||
p := &Proxy{
|
||||
Config: c,
|
||||
waiters: make(map[*http.Request]*wait),
|
||||
attachJobs: make(map[string]*attachJob),
|
||||
quit: make(chan struct{}),
|
||||
}
|
||||
|
||||
if err := p.TLSConfig.LoadCerts(); err != nil {
|
||||
Log.Fatalf("Could not configure tls for proxy: %s", err)
|
||||
weave: weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), Log),
|
||||
}
|
||||
|
||||
// We pin the protocol version to 1.18 (which corresponds to
|
||||
@@ -143,9 +143,21 @@ func NewProxy(c Config) (*Proxy, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
Log.Info(client.Info())
|
||||
p.client = client
|
||||
return p, nil
|
||||
}
|
||||
|
||||
p.client = client.Client
|
||||
func NewProxy(c Config) (*Proxy, error) {
|
||||
p, err := StubProxy(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := p.TLSConfig.LoadCerts(); err != nil {
|
||||
Log.Fatalf("Could not configure tls for proxy: %s", err)
|
||||
}
|
||||
|
||||
Log.Info(p.client.Info())
|
||||
|
||||
if !p.WithoutDNS {
|
||||
ip, err := weavenet.FindBridgeIP(c.DockerBridge, nil)
|
||||
@@ -166,7 +178,7 @@ func NewProxy(c Config) (*Proxy, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client.AddObserver(p)
|
||||
p.client.AddObserver(p)
|
||||
|
||||
return p, nil
|
||||
}
|
||||
@@ -204,7 +216,7 @@ func (proxy *Proxy) findWeaveWaitVolumes() error {
|
||||
}
|
||||
|
||||
func (proxy *Proxy) findVolume(v string) (string, error) {
|
||||
container, err := proxy.client.InspectContainer("weaveproxy")
|
||||
container, err := proxy.client.InspectContainer("weave")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Could not find the weavewait volume: %s", err)
|
||||
}
|
||||
@@ -279,13 +291,17 @@ func (proxy *Proxy) Listen() []net.Listener {
|
||||
return listeners
|
||||
}
|
||||
|
||||
func (proxy *Proxy) Serve(listeners []net.Listener) {
|
||||
func (proxy *Proxy) Serve(listeners []net.Listener, ready func()) {
|
||||
errs := make(chan error)
|
||||
for _, listener := range listeners {
|
||||
go func(listener net.Listener) {
|
||||
errs <- (&http.Server{Handler: proxy}).Serve(listener)
|
||||
}(listener)
|
||||
}
|
||||
// It would be better if we could delay calling Done() until all
|
||||
// the listeners are ready, but it doesn't seem to be possible to
|
||||
// hook the right point in http.Server
|
||||
ready()
|
||||
for range listeners {
|
||||
err := <-errs
|
||||
if err != nil {
|
||||
@@ -294,17 +310,6 @@ func (proxy *Proxy) Serve(listeners []net.Listener) {
|
||||
}
|
||||
}
|
||||
|
||||
func (proxy *Proxy) ListenAndServeStatus(socket string) {
|
||||
listener, err := weavenet.ListenUnixSocket(socket)
|
||||
if err != nil {
|
||||
Log.Fatalf("ListenAndServeStatus failed: %s", err)
|
||||
}
|
||||
handler := http.HandlerFunc(proxy.StatusHTTP)
|
||||
if err := (&http.Server{Handler: handler}).Serve(listener); err != nil {
|
||||
Log.Fatalf("ListenAndServeStatus failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (proxy *Proxy) StatusHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
for _, addr := range proxy.normalisedAddrs {
|
||||
fmt.Fprintln(w, addr)
|
||||
@@ -408,11 +413,6 @@ func containerShouldAttach(container *docker.Container) bool {
|
||||
return len(container.Config.Entrypoint) > 0 && container.Config.Entrypoint[0] == weaveWaitEntrypoint[0]
|
||||
}
|
||||
|
||||
func containerIsWeaveRouter(container *docker.Container) bool {
|
||||
return container.Name == weaveContainerName &&
|
||||
len(container.Config.Entrypoint) > 0 && container.Config.Entrypoint[0] == weaveEntrypoint
|
||||
}
|
||||
|
||||
func (proxy *Proxy) createWait(r *http.Request, ident string) {
|
||||
proxy.Lock()
|
||||
proxy.waiters[r] = &wait{ident: ident, ch: make(chan error, 1)}
|
||||
@@ -489,10 +489,6 @@ func (proxy *Proxy) attach(containerID string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if containerIsWeaveRouter(container) {
|
||||
Log.Infof("Attaching weave router container: %s", container.ID)
|
||||
return callWeaveAttach(container, []string{"attach-router"})
|
||||
}
|
||||
if !containerShouldAttach(container) || !container.State.Running {
|
||||
return nil
|
||||
}
|
||||
@@ -503,53 +499,77 @@ func (proxy *Proxy) attach(containerID string) error {
|
||||
return nil
|
||||
}
|
||||
Log.Infof("Attaching container %s with WEAVE_CIDR \"%s\" to weave network", container.ID, strings.Join(cidrs, " "))
|
||||
if err := validateCIDRs(cidrs); err != nil {
|
||||
ips, err := proxy.allocateCIDRs(container.ID, cidrs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
args := []string{"attach"}
|
||||
args = append(args, cidrs...)
|
||||
fqdn := container.Config.Hostname + "." + container.Config.Domainname
|
||||
if !proxy.NoRewriteHosts {
|
||||
args = append(args, "--rewrite-hosts")
|
||||
|
||||
var extraHosts []string
|
||||
if container.HostConfig != nil {
|
||||
for _, eh := range container.HostConfig.ExtraHosts {
|
||||
args = append(args, fmt.Sprintf("--add-host=%s", eh))
|
||||
extraHosts = container.HostConfig.ExtraHosts
|
||||
}
|
||||
proxy.RewriteEtcHosts(container.HostsPath, fqdn, ips, extraHosts)
|
||||
}
|
||||
|
||||
pid := container.State.Pid
|
||||
// Passing 0 for mtu means it will be taken from the bridge
|
||||
err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, weavenet.WeaveBridgeName, 0, !proxy.NoMulticastRoute, ips, proxy.KeepTXOn, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !proxy.WithoutDNS {
|
||||
for _, ip := range ips {
|
||||
if err := proxy.weave.RegisterWithDNS(container.ID, fqdn, ip.IP.String()); err != nil {
|
||||
return errors.Wrapf(err, "unable to register %s with weaveDNS: %s", container.ID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if proxy.NoMulticastRoute {
|
||||
args = append(args, "--no-multicast-route")
|
||||
}
|
||||
args = append(args, container.ID)
|
||||
return callWeaveAttach(container, args)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func callWeaveAttach(container *docker.Container, args []string) error {
|
||||
if _, stderr, err := callWeave(args...); err != nil {
|
||||
Log.Warningf("Attaching container %s to weave network failed: %s", container.ID, string(stderr))
|
||||
return errors.New(string(stderr))
|
||||
} else if len(stderr) > 0 {
|
||||
Log.Warningf("Attaching container %s to weave network: %s", container.ID, string(stderr))
|
||||
func (proxy *Proxy) allocateCIDRs(containerID string, cidrs []string) ([]*net.IPNet, error) {
|
||||
if len(cidrs) == 0 {
|
||||
cidrs = []string{"net:default"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateCIDRs(cidrs []string) error {
|
||||
var ipnet *net.IPNet
|
||||
var err error
|
||||
var ipnets []*net.IPNet
|
||||
for _, cidr := range cidrs {
|
||||
if cidr == "net:default" {
|
||||
continue
|
||||
}
|
||||
for _, prefix := range []string{"ip:", "net:", ""} {
|
||||
if strings.HasPrefix(cidr, prefix) {
|
||||
if _, err := address.ParseCIDR(strings.TrimPrefix(cidr, prefix)); err == nil {
|
||||
break
|
||||
}
|
||||
return fmt.Errorf("invalid WEAVE_CIDR: %s", cidr)
|
||||
switch {
|
||||
case cidr == "net:default":
|
||||
ipnet, err = proxy.weave.AllocateIP(containerID, true)
|
||||
case strings.HasPrefix(cidr, "net:"):
|
||||
var subnet *net.IPNet
|
||||
_, subnet, err = net.ParseCIDR(strings.TrimPrefix(cidr, "net:"))
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
ipnet, err = proxy.weave.AllocateIPInSubnet(containerID, subnet, true)
|
||||
case strings.HasPrefix(cidr, "ip:"):
|
||||
ipnet, err = proxy.claimCIDR(containerID, strings.TrimPrefix(cidr, "ip:"))
|
||||
default:
|
||||
ipnet, err = proxy.claimCIDR(containerID, cidr)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "for %q", cidr)
|
||||
}
|
||||
ipnets = append(ipnets, ipnet)
|
||||
}
|
||||
return nil
|
||||
return ipnets, nil
|
||||
}
|
||||
|
||||
func (proxy *Proxy) claimCIDR(containerID, cidr string) (*net.IPNet, error) {
|
||||
ip, ipnet, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipnet.IP = ip // we want the specific IP plus the mask
|
||||
err = proxy.weave.ClaimIP(containerID, ipnet, true)
|
||||
return ipnet, err
|
||||
}
|
||||
|
||||
func (proxy *Proxy) weaveCIDRs(networkMode string, env []string) ([]string, error) {
|
||||
@@ -598,8 +618,7 @@ func (proxy *Proxy) getDNSDomain() string {
|
||||
if proxy.WithoutDNS {
|
||||
return ""
|
||||
}
|
||||
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), Log)
|
||||
domain, _ := weave.DNSDomain()
|
||||
domain, _ := proxy.weave.DNSDomain()
|
||||
return domain
|
||||
}
|
||||
|
||||
@@ -638,7 +657,6 @@ func (proxy *Proxy) updateContainerNetworkSettings(container jsonObject) error {
|
||||
}
|
||||
|
||||
func (proxy *Proxy) symlink(unixAddrs []string) (err error) {
|
||||
var container *docker.Container
|
||||
binds := []string{"/var/run/weave:/var/run/weave"}
|
||||
froms := []string{}
|
||||
for _, addr := range unixAddrs {
|
||||
@@ -654,7 +672,10 @@ func (proxy *Proxy) symlink(unixAddrs []string) (err error) {
|
||||
if len(froms) == 0 {
|
||||
return
|
||||
}
|
||||
return proxy.runTransientContainer([]string{"/home/weave/symlink", weaveSock}, froms, binds)
|
||||
}
|
||||
|
||||
func (proxy *Proxy) runTransientContainer(entrypoint, cmd, binds []string) (err error) {
|
||||
env := []string{
|
||||
"PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
}
|
||||
@@ -663,14 +684,15 @@ func (proxy *Proxy) symlink(unixAddrs []string) (err error) {
|
||||
env = append(env, fmt.Sprintf("%s=%s", "WEAVE_DEBUG", val))
|
||||
}
|
||||
|
||||
var container *docker.Container
|
||||
container, err = proxy.client.CreateContainer(docker.CreateContainerOptions{
|
||||
Config: &docker.Config{
|
||||
Image: proxy.Image,
|
||||
Entrypoint: []string{"/home/weave/symlink", weaveSock},
|
||||
Cmd: froms,
|
||||
Entrypoint: entrypoint,
|
||||
Cmd: cmd,
|
||||
Env: env,
|
||||
},
|
||||
HostConfig: &docker.HostConfig{Binds: binds},
|
||||
HostConfig: &docker.HostConfig{Binds: binds, NetworkMode: "none"},
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package proxy
|
||||
|
||||
type Status struct {
|
||||
Addresses []string
|
||||
}
|
||||
|
||||
func NewStatus(proxy *Proxy) *Status {
|
||||
if proxy == nil {
|
||||
return nil
|
||||
}
|
||||
status := &Status{
|
||||
Addresses: proxy.normalisedAddrs,
|
||||
}
|
||||
return status
|
||||
}
|
||||
+10
-10
@@ -209,25 +209,25 @@ func (lock *fastDatapathLock) relock() {
|
||||
}
|
||||
}
|
||||
|
||||
// Bridge bits
|
||||
// InjectorConsumer bits
|
||||
|
||||
type fastDatapathBridge struct {
|
||||
type fastDatapathInjectorConsumer struct {
|
||||
*FastDatapath
|
||||
}
|
||||
|
||||
func (fastdp *FastDatapath) Bridge() Bridge {
|
||||
return fastDatapathBridge{fastdp}
|
||||
func (fastdp *FastDatapath) InjectorConsumer() InjectorConsumer {
|
||||
return fastDatapathInjectorConsumer{fastdp}
|
||||
}
|
||||
|
||||
func (fastdp fastDatapathBridge) Interface() *net.Interface {
|
||||
func (fastdp fastDatapathInjectorConsumer) Interface() *net.Interface {
|
||||
return fastdp.iface
|
||||
}
|
||||
|
||||
func (fastdp fastDatapathBridge) String() string {
|
||||
func (fastdp fastDatapathInjectorConsumer) String() string {
|
||||
return fmt.Sprint(fastdp.iface.Name, " (via ODP)")
|
||||
}
|
||||
|
||||
func (fastdp fastDatapathBridge) Stats() map[string]int {
|
||||
func (fastdp fastDatapathInjectorConsumer) Stats() map[string]int {
|
||||
lock := fastdp.startLock()
|
||||
defer lock.unlock()
|
||||
|
||||
@@ -238,12 +238,12 @@ func (fastdp fastDatapathBridge) Stats() map[string]int {
|
||||
|
||||
var routerBridgePortID = bridgePortID{router: true}
|
||||
|
||||
func (fastdp fastDatapathBridge) StartConsumingPackets(consumer BridgeConsumer) error {
|
||||
func (fastdp fastDatapathInjectorConsumer) StartConsumingPackets(consumer Consumer) error {
|
||||
fastdp.lock.Lock()
|
||||
defer fastdp.lock.Unlock()
|
||||
|
||||
if fastdp.sendToPort[routerBridgePortID] != nil {
|
||||
return fmt.Errorf("FastDatapath already has a BridgeConsumer")
|
||||
return fmt.Errorf("FastDatapath already has a Consumer")
|
||||
}
|
||||
|
||||
// set up delivery to the weave router port on the bridge
|
||||
@@ -257,7 +257,7 @@ func (fastdp fastDatapathBridge) StartConsumingPackets(consumer BridgeConsumer)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fastdp fastDatapathBridge) InjectPacket(key PacketKey) FlowOp {
|
||||
func (fastdp fastDatapathInjectorConsumer) InjectPacket(key PacketKey) FlowOp {
|
||||
lock := fastdp.startLock()
|
||||
defer lock.unlock()
|
||||
return fastdp.bridge(routerBridgePortID, key, &lock)
|
||||
|
||||
@@ -5,13 +5,13 @@ import (
|
||||
)
|
||||
|
||||
// Interface to packet handling on the local virtual bridge
|
||||
type Bridge interface {
|
||||
type InjectorConsumer interface {
|
||||
// Inject a packet to be delivered locally
|
||||
InjectPacket(PacketKey) FlowOp
|
||||
|
||||
// Start consuming packets from the bridge. Injected packets
|
||||
// should not be included.
|
||||
StartConsumingPackets(BridgeConsumer) error
|
||||
StartConsumingPackets(Consumer) error
|
||||
|
||||
Interface() *net.Interface
|
||||
String() string
|
||||
@@ -19,26 +19,26 @@ type Bridge interface {
|
||||
}
|
||||
|
||||
// A function that determines how to handle locally captured packets.
|
||||
type BridgeConsumer func(PacketKey) FlowOp
|
||||
type Consumer func(PacketKey) FlowOp
|
||||
|
||||
type NullBridge struct{}
|
||||
type NullInjectorConsumer struct{}
|
||||
|
||||
func (NullBridge) InjectPacket(PacketKey) FlowOp {
|
||||
func (NullInjectorConsumer) InjectPacket(PacketKey) FlowOp {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NullBridge) StartConsumingPackets(BridgeConsumer) error {
|
||||
func (NullInjectorConsumer) StartConsumingPackets(Consumer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NullBridge) Interface() *net.Interface {
|
||||
func (NullInjectorConsumer) Interface() *net.Interface {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NullBridge) String() string {
|
||||
func (NullInjectorConsumer) String() string {
|
||||
return "no overlay bridge"
|
||||
}
|
||||
|
||||
func (NullBridge) Stats() map[string]int {
|
||||
func (NullInjectorConsumer) Stats() map[string]int {
|
||||
return nil
|
||||
}
|
||||
@@ -34,9 +34,9 @@ var (
|
||||
)
|
||||
|
||||
type NetworkConfig struct {
|
||||
BufSz int
|
||||
PacketLogging PacketLogging
|
||||
Bridge Bridge
|
||||
BufSz int
|
||||
PacketLogging PacketLogging
|
||||
InjectorConsumer InjectorConsumer
|
||||
}
|
||||
|
||||
type PacketLogging interface {
|
||||
@@ -55,8 +55,8 @@ func NewNetworkRouter(config mesh.Config, networkConfig NetworkConfig, name mesh
|
||||
if overlay == nil {
|
||||
overlay = NullNetworkOverlay{}
|
||||
}
|
||||
if networkConfig.Bridge == nil {
|
||||
networkConfig.Bridge = NullBridge{}
|
||||
if networkConfig.InjectorConsumer == nil {
|
||||
networkConfig.InjectorConsumer = NullInjectorConsumer{}
|
||||
}
|
||||
|
||||
meshRouter, err := mesh.NewRouter(config, name, nickName, overlay, common.LogLogger())
|
||||
@@ -77,8 +77,8 @@ func NewNetworkRouter(config mesh.Config, networkConfig NetworkConfig, name mesh
|
||||
// Start listening for TCP connections, locally captured packets, and
|
||||
// forwarded packets.
|
||||
func (router *NetworkRouter) Start() {
|
||||
log.Println("Sniffing traffic on", router.Bridge)
|
||||
checkFatal(router.Bridge.StartConsumingPackets(router.handleCapturedPacket))
|
||||
log.Println("Sniffing traffic on", router.InjectorConsumer)
|
||||
checkFatal(router.InjectorConsumer.StartConsumingPackets(router.handleCapturedPacket))
|
||||
checkFatal(router.Overlay.(NetworkOverlay).StartConsumingPackets(router.Ourself.Peer, router.Peers, router.handleForwardedPacket))
|
||||
router.Router.Start()
|
||||
}
|
||||
@@ -156,7 +156,7 @@ func (router *NetworkRouter) handleForwardedPacket(key ForwardPacketKey) FlowOp
|
||||
}
|
||||
|
||||
router.PacketLogging.LogForwardPacket("Injecting", key)
|
||||
injectFop := router.Bridge.InjectPacket(key.PacketKey)
|
||||
injectFop := router.InjectorConsumer.InjectPacket(key.PacketKey)
|
||||
dstPeer := router.Macs.Lookup(dstMac)
|
||||
if dstPeer == router.Ourself.Peer {
|
||||
return injectFop
|
||||
|
||||
@@ -23,8 +23,8 @@ type MACStatus struct {
|
||||
func NewNetworkRouterStatus(router *NetworkRouter) *NetworkRouterStatus {
|
||||
return &NetworkRouterStatus{
|
||||
mesh.NewStatus(router.Router),
|
||||
router.Bridge.String(),
|
||||
router.Bridge.Stats(),
|
||||
router.InjectorConsumer.String(),
|
||||
router.InjectorConsumer.Stats(),
|
||||
NewMACStatusSlice(router.Macs)}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -27,7 +27,7 @@ type Pcap struct {
|
||||
readHandle *pcap.Handle
|
||||
}
|
||||
|
||||
func NewPcap(iface *net.Interface, bufSz int) (Bridge, error) {
|
||||
func NewPcap(iface *net.Interface, bufSz int) (InjectorConsumer, error) {
|
||||
wh, err := newPcapHandle(iface.Name, false, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -36,7 +36,7 @@ func NewPcap(iface *net.Interface, bufSz int) (Bridge, error) {
|
||||
return &Pcap{iface: iface, bufSz: bufSz, writeHandle: wh}, nil
|
||||
}
|
||||
|
||||
func (p *Pcap) StartConsumingPackets(consumer BridgeConsumer) error {
|
||||
func (p *Pcap) StartConsumingPackets(consumer Consumer) error {
|
||||
rh, err := newPcapHandle(p.iface.Name, true, 65535, p.bufSz)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -122,7 +122,7 @@ func (p *Pcap) Process(frame []byte, dec *EthernetDecoder, broadcast bool) {
|
||||
checkWarn(p.writeHandle.WritePacketData(frame))
|
||||
}
|
||||
|
||||
func (p *Pcap) sniff(readHandle *pcap.Handle, consumer BridgeConsumer) {
|
||||
func (p *Pcap) sniff(readHandle *pcap.Handle, consumer Consumer) {
|
||||
dec := NewEthernetDecoder()
|
||||
|
||||
for {
|
||||
|
||||
+2
-2
@@ -42,8 +42,8 @@ On a fresh repository, the Makefile will do the following:
|
||||
- assemble the build container
|
||||
- download specific versions of all the dependencies
|
||||
- build the weave components in the build container
|
||||
- package them into three Docker images (`weaveworks/weave`,
|
||||
`weaveworks/weaveexec`, and `weaveworks/plugin`)
|
||||
- package them into two Docker images (`weaveworks/weave`,
|
||||
`weaveworks/weaveexec`)
|
||||
- Exported these images as `weave.tar.gz`
|
||||
|
||||
The first two steps may take a while - don't worry, they are
|
||||
|
||||
@@ -108,5 +108,8 @@ For more information, see the
|
||||
|
||||
### Caveats
|
||||
|
||||
- The program `nsenter` must be present on the host; it is required by
|
||||
the CNI plugin. In some distros (e.g. Alpine, Ubuntu) it is in the
|
||||
util-linux package
|
||||
- The Weave Net router container must be running for CNI to allocate addresses
|
||||
- The CNI plugin does not add entries to weaveDNS.
|
||||
+2
-2
@@ -87,7 +87,7 @@ See [Using Fast Datapath](/site/using-weave/fastdp.md) for more information.
|
||||
Yes, of course! Weave allows you to run isolated networks and still allow open communications between individual containers from those isolated networks. You can find information on how to do this in [Application Isolation](/site/using-weave/application-isolation.md).
|
||||
|
||||
|
||||
**<a name=ports></a>Q: Which ports does Weave Net use (e.g. if I am configuring a firewall) ?**
|
||||
**<a name="ports"></a>Q: Which ports does Weave Net use (e.g. if I am configuring a firewall) ?**
|
||||
|
||||
You must permit traffic to flow through TCP 6783 and UDP 6783/6784,
|
||||
which are Weave’s control and data ports.
|
||||
@@ -105,7 +105,7 @@ network does not block ESP traffic (IP protocol 50). For instance
|
||||
on Google Cloud Platform a firewall rule for allowing ESP traffic has
|
||||
to be installed.
|
||||
|
||||
**<a name=own-image></a>Q: Why do you use your own Docker image `weaveworks/ubuntu`?**
|
||||
**<a name="own-image"></a>Q: Why do you use your own Docker image `weaveworks/ubuntu`?**
|
||||
|
||||
The official Ubuntu image does not contain the `ping` and `nc`
|
||||
commands which are used in many of our examples throughout the
|
||||
|
||||
+4
-5
@@ -83,11 +83,10 @@ named `weave` is created by `weave launch`, which is used as follows:
|
||||
|
||||
Using the Weave plugin enables you to take advantage of [Docker's network functionality](https://docs.docker.com/engine/extend/plugins_network/).
|
||||
|
||||
Also, Weave’s Docker Network plugin doesn't require an external cluster store and you can start and stop containers even
|
||||
when there are network connectivity problems.
|
||||
|
||||
See [Integrating Docker via the Network Plugin](/site/plugin.md) for more details.
|
||||
|
||||
There are two plugin implementations for Weave Net: the
|
||||
["Legacy"](/site/plugin.md) plugin which doesn't require an external
|
||||
cluster store, and the ["V2"](/site/plugin-v2.md) plugin which
|
||||
supports Docker swarm mode.
|
||||
|
||||
### <a name="cniplugin"></a>Weave Network CNI Plugin
|
||||
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ search_type: Documentation
|
||||
Weave Net automatically assigns containers a unique IP address
|
||||
across the network, and also releases that address when the container
|
||||
exits. Unless you explicitly specify an address, this occurs for all
|
||||
invocations of the `run`, `start`,
|
||||
invocations of the
|
||||
`attach`, `detach`, `expose`, and `hide` commands. Weave Net can also assign
|
||||
addresses in multiple subnets.
|
||||
|
||||
@@ -203,4 +203,4 @@ named `weavedb` is used to store this data.
|
||||
**See Also**
|
||||
|
||||
* [Automatic Allocation Across Multiple Subnets](/site/ipam/allocation-multi-ipam.md)
|
||||
* [Integrating Docker via the Network Plugin](/site/plugin.md)
|
||||
* [Integrating Docker via the Network Plugin (Legacy)](/site/plugin.md)
|
||||
+78
-31
@@ -21,16 +21,8 @@ The following topics are discussed:
|
||||
Weave Net can be installed onto your CNI-enabled Kubernetes cluster
|
||||
with a single command:
|
||||
|
||||
* Kubernetes versions `1.6` and above:
|
||||
|
||||
```
|
||||
$ kubectl apply -f https://git.io/weave-kube-1.6
|
||||
```
|
||||
|
||||
* Kubernetes versions up to `1.5`:
|
||||
|
||||
```
|
||||
$ kubectl apply -f https://git.io/weave-kube
|
||||
$ kubectl apply -n kube-system -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
|
||||
```
|
||||
|
||||
After a few seconds, a Weave Net pod should be running on each
|
||||
@@ -63,10 +55,20 @@ Shut down Kubernetes, and _on all nodes_ perform the following:
|
||||
Then relaunch Kubernetes and install the addon as described
|
||||
above.
|
||||
|
||||
The URLs [https://git.io/weave-kube](https://git.io/weave-kube) and [https://git.io/weave-kube-1.6](https://git.io/weave-kube-1.6) point
|
||||
to the YAML file for the [latest release](https://github.com/weaveworks/weave/releases/tag/latest_release) of the Weave Net addon.
|
||||
Historic versions are archived on our [GitHub release
|
||||
page](https://github.com/weaveworks/weave/releases).
|
||||
**Note:** The URLs:
|
||||
|
||||
- [https://git.io/weave-kube](https://git.io/weave-kube), and
|
||||
- [https://git.io/weave-kube-1.6](https://git.io/weave-kube-1.6)
|
||||
|
||||
point to:
|
||||
|
||||
- [https://cloud.weave.works/k8s/v1.5/net](https://cloud.weave.works/k8s/v1.5/net), and
|
||||
- [https://cloud.weave.works/k8s/v1.6/net](https://cloud.weave.works/k8s/v1.6/net).
|
||||
|
||||
In the past, these URLs pointed to the static YAML files for the [latest release](https://github.com/weaveworks/weave/releases/tag/latest_release) of the Weave Net addon, respectively:
|
||||
|
||||
- [`latest_release/weave-daemonset.yaml`](https://github.com/weaveworks/weave/releases/download/latest_release/weave-daemonset.yaml) and
|
||||
- [`latest_release/weave-daemonset-k8s-1.6.yaml`](https://github.com/weaveworks/weave/releases/download/latest_release/weave-daemonset-k8s-1.6.yaml).
|
||||
|
||||
## <a name="kube-1.6-upgrade"></a> Upgrading Kubernetes to version 1.6
|
||||
|
||||
@@ -85,7 +87,12 @@ you will need to re-make your changes against the new version.
|
||||
|
||||
### <a name="daemon-sets"></a> Upgrading the Daemon Sets
|
||||
|
||||
Kubernetes does not currently support rolling upgrades of daemon sets,
|
||||
For Kubernetes 1.6 and above the DaemonSet definition specifies
|
||||
[Rolling Updates](https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/),
|
||||
so when you apply a new version Kubernetes will automatically restart
|
||||
the Weave Net pods one by one.
|
||||
|
||||
Kubernetes v1.5 and below does not support rolling upgrades of daemon sets,
|
||||
and so you will need to perform the procedure manually:
|
||||
|
||||
* Apply the updated addon manifest `kubectl apply -f https://git.io/weave-kube`
|
||||
@@ -205,26 +212,32 @@ UDP connection from 10.32.0.7:56648 to 10.32.0.11:80 blocked by Weave NPC.
|
||||
|
||||
### <a name="configuration-options"></a> Changing Configuration Options
|
||||
|
||||
The default configuration settings can be changed by saving and editing the
|
||||
addon YAML before running `kubectl apply`. Additional arguments may be
|
||||
supplied to the Weave router process by adding them to the `command:`
|
||||
array in the YAML file.
|
||||
#### Using `cloud.weave.works`
|
||||
|
||||
Some parameters are changed by environment variables; these can be
|
||||
inserted into the YAML file like this:
|
||||
If the YAML file is from `cloud.weave.works` as described above, then you can customise it by passing some of Weave Net's options, arguments and environment variables as query parameters:
|
||||
|
||||
```
|
||||
containers:
|
||||
- name: weave
|
||||
env:
|
||||
- name: IPALLOC_RANGE
|
||||
value: 10.0.0.0/16
|
||||
```
|
||||
- `version`: Weave Net's version. Default: `latest`, i.e. latest release. *N.B.*: This only changes the specified version inside the generated YAML file, it does not ensure that the rest of the YAML is compatible with that version. To freeze the YAML version save a copy of the YAML file from the [release page](https://github.com/weaveworks/weave/releases) and use that copy instead of downloading it each time from `cloud.weave.works`.
|
||||
- `password-secret`: name of the Kubernetes secret containing your password.
|
||||
Example:
|
||||
|
||||
$ echo "s3cr3tp4ssw0rd" > /var/lib/weave/weave-passwd.txt
|
||||
$ kubectl create secret -n kube-system generic weave-passwd --from-file=/var/lib/weave/weave-passwd.txt
|
||||
$ kubectl apply -n kube-system -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')&password-secret=weave-passwd"
|
||||
|
||||
- `known-peers`: comma-separated list of hosts. Default: empty.
|
||||
- `trusted-subnets`: comma-separated list of CIDRs. Default: empty.
|
||||
- `disable-npc`: boolean (`true|false`). Default: `false`.
|
||||
- `env.NAME=VALUE`: add environment variable `NAME` and set it to `VALUE`.
|
||||
- `seLinuxOptions.NAME=VALUE`: add SELinux option `NAME` and set it to `VALUE`, e.g. `seLinuxOptions.type=spc_t`
|
||||
|
||||
The list of variables you can set is:
|
||||
|
||||
* `CHECKPOINT_DISABLE` - if set to 1, disable checking for new Weave Net
|
||||
versions (default is blank, i.e. check is enabled)
|
||||
* `HAIRPIN_MODE` - Weave Net defaults to enabling hairpin on the bridge side of
|
||||
the `veth` pair for containers attached. If you need to disable hairpin, e.g. your
|
||||
kernel is one of those that can panic if hairpin is enabled, then you can disable it
|
||||
by setting `HAIRPIN_MODE=false`.
|
||||
* `IPALLOC_RANGE` - the range of IP addresses used by Weave Net
|
||||
and the subnet they are placed in (CIDR format; default `10.32.0.0/12`)
|
||||
* `EXPECT_NPC` - set to 0 to disable Network Policy Controller (default is on)
|
||||
@@ -241,7 +254,41 @@ The list of variables you can set is:
|
||||
a larger size for better performance if your network supports jumbo
|
||||
frames - see [here](/site/using-weave/fastdp.md#mtu) for more
|
||||
details.
|
||||
* `HAIRPIN_MODE` - Weave Net defaults to enabling hairpin on the bridge side of
|
||||
the `veth` pair for containers attached. If you need to disable hairpin, e.g. your
|
||||
kernel is one of those that can panic if hairpin is enabled, then you can disable it
|
||||
by setting `HAIRPIN_MODE=false`.
|
||||
|
||||
Example:
|
||||
```
|
||||
$ kubectl apply -n kube-system -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')&env.WEAVE_MTU=1337"
|
||||
```
|
||||
This command -- notice `&env.WEAVE_MTU=1337` at the end of the URL -- generates a YAML file containing, among others:
|
||||
|
||||
```
|
||||
[...]
|
||||
containers:
|
||||
- name: weave
|
||||
[...]
|
||||
env:
|
||||
- name: WEAVE_MTU
|
||||
value: '1337'
|
||||
[...]
|
||||
```
|
||||
|
||||
**Note**: The YAML file can also be saved for later use or manual editing by using, for example:
|
||||
```
|
||||
$ curl -fsSLo weave-daemonset.yaml "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
|
||||
```
|
||||
|
||||
#### Manually editing the YAML file
|
||||
|
||||
Whether you saved the YAML file served from `cloud.weave.works` or downloaded a static YAML file from our [releases page](https://github.com/weaveworks/weave/releases), you can manually edit it to suit your needs.
|
||||
|
||||
For example,
|
||||
- additional arguments may be supplied to the Weave router process by adding them to the `command:` array in the YAML file,
|
||||
- additional parameters can be set via the environment variables listed above; these can be inserted into the YAML file like this:
|
||||
|
||||
```
|
||||
containers:
|
||||
- name: weave
|
||||
env:
|
||||
- name: IPALLOC_RANGE
|
||||
value: 10.0.0.0/16
|
||||
```
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: Integrating Docker via the Network Plugin (V2)
|
||||
menu_order: 65
|
||||
search_type: Documentation
|
||||
---
|
||||
|
||||
* [Installation](#installation)
|
||||
* [Configuring the Plugin](#configuring)
|
||||
* [Running Services or Containers Using the Plugin](#usage)
|
||||
|
||||
Docker Engine version 1.12 introduced [a new plugin system (V2)](https://docs.docker.com/engine/extend/).
|
||||
This document describes how to use [the Network Plugin V2 of Weave Net](https://store.docker.com/plugins/weave-net-plugin).
|
||||
|
||||
Before using the plugin, please keep in mind the plugin works only in Swarm
|
||||
mode and requires Docker version 1.13 or later.
|
||||
|
||||
### <a name="installation"></a>Installation
|
||||
|
||||
To install the plugin run the following command on _each_ host already
|
||||
participating in a Swarm cluster, i.e. on all master and worker nodes:
|
||||
|
||||
$ docker plugin install store/weaveworks/net-plugin:latest_release
|
||||
|
||||
Docker will pull the plugin from Docker Store, and it will ask to grant
|
||||
privileges before installing the plugin. Afterwards, it will start `weaver`
|
||||
process which will try to connect to Swarm masters running Weave Net.
|
||||
|
||||
### <a name="configuring"></a>Configuring the Plugin
|
||||
|
||||
There are several configuration parameters which can be set with:
|
||||
|
||||
$ docker plugin set store/weaveworks/net-plugin:latest_release PARAM=VALUE
|
||||
|
||||
The parameters include:
|
||||
|
||||
* `WEAVE_PASSWORD` - if non empty, it will instruct Weave Net to encrypt
|
||||
traffic - see [here](/site/using-weave/security-untrusted-networks.md) for
|
||||
more details.
|
||||
* `WEAVE_MULTICAST` - set to 1 on each host running the plugin to enable
|
||||
multicast traffic on any Weave Net network.
|
||||
* `WEAVE_MTU` - Weave Net defaults to 1376 bytes, but you can set a
|
||||
smaller size if your underlying network has a tighter limit, or set
|
||||
a larger size for better performance if your network supports jumbo
|
||||
frames - see [here](/site/using-weave/fastdp.md#mtu) for more
|
||||
details.
|
||||
* `IPALLOC_RANGE` - the range of IP addresses used by Weave Net and the subnet
|
||||
they are placed in (CIDR format; default 10.32.0.0/12).
|
||||
See [here](/site/using-weave/configuring-weave.md) for more details.
|
||||
|
||||
Before setting any parameter, the plugin has to be disabled with:
|
||||
|
||||
$ docker plugin disable store/weaveworks/net-plugin:latest_release
|
||||
|
||||
To re-enable the plugin run the following command:
|
||||
|
||||
$ docker plugin enable store/weaveworks/net-plugin:latest_release
|
||||
|
||||
### <a name="usage"></a>Running Services or Containers Using the Plugin
|
||||
|
||||
After you have launched the plugin, you can create a network for Docker Swarm
|
||||
services by running the following command on any Docker Swarm master node:
|
||||
|
||||
$ docker network create --driver=store/weaveworks/net-plugin:latest_release mynetwork
|
||||
|
||||
Or you can create a network for any Docker container with:
|
||||
|
||||
$ docker network create --driver=store/weaveworks/net-plugin:latest_release --attachable mynetwork
|
||||
|
||||
To start a service attached to the network run, for example:
|
||||
|
||||
$ docker service create --network=mynetwork ...
|
||||
|
||||
Or to start a container:
|
||||
|
||||
$ docker run --network=mynetwork ...
|
||||
|
||||
**See Also**
|
||||
|
||||
* [Integrating Docker via the Network Plugin (Legacy)](/site/plugin.md)
|
||||
* [How the Weave Network Plugins Work](/site/plugin/plugin-how-it-works.md)
|
||||
+8
-21
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Integrating Docker via the Network Plugin
|
||||
title: Integrating Docker via the Network Plugin (Legacy)
|
||||
menu_order: 60
|
||||
search_type: Documentation
|
||||
---
|
||||
@@ -59,8 +59,12 @@ then run your containers using the Docker command-line:
|
||||
|
||||
Docker enables you to create multiple independent networks and attach
|
||||
different sets of containers to each network. However, coordinating
|
||||
this between hosts, Docker requires that you configure a
|
||||
["key-value store"](https://docs.docker.com/engine/userguide/networking/get-started-overlay/#step-1-set-up-a-key-value-store).
|
||||
this between hosts requires that you run Docker in ["swarm mode"](https://docs.docker.com/engine/swarm/swarm-mode/) or configure a
|
||||
["key-value store"](https://docs.docker.com/engine/userguide/networking/get-started-overlay/#/set-up-a-key-value-store).
|
||||
|
||||
To operate in swarm mode, you are required to use the plugin v2 of Weave Net.
|
||||
See [Integrating Docker via the Network Plugin (V2)](/site/plugin-v2.md) for
|
||||
more details.
|
||||
|
||||
If your Docker installation has a key-value store, create a network
|
||||
based on Weave Net as follows:
|
||||
@@ -90,23 +94,6 @@ If you are using `systemd` with Docker 1.9, it is advised that you modify the Do
|
||||
TimeoutStartSec=0
|
||||
|
||||
|
||||
### <a name="configuring"></a>Configuring the Plugin
|
||||
|
||||
The plugin accepts a number of configuration parameters. To supply
|
||||
these, instead of running `weave launch`, start the router and plugin
|
||||
separately with:
|
||||
|
||||
$ weave launch-router [other peers]
|
||||
$ weave launch-plugin [plugin parameters]
|
||||
|
||||
The plugin configuration parameters are:
|
||||
|
||||
* `--log-level=debug|info|warning|error` --tells the plugin
|
||||
how much information to emit for debugging.
|
||||
* `--no-restart` -- remove the default policy of `--restart=always`, if
|
||||
you want to control start-up of the plugin yourself
|
||||
|
||||
|
||||
**See Also**
|
||||
|
||||
* [How the Weave Network Plugin Works](/site/plugin/plugin-how-it-works.md)
|
||||
* [How the Weave Network Plugins Work](/site/plugin/plugin-how-it-works.md)
|
||||
@@ -1,11 +1,15 @@
|
||||
---
|
||||
title: How the Weave Net Docker Network Plugin Works
|
||||
title: How the Weave Net Docker Network Plugins Work
|
||||
menu_order: 20
|
||||
search_type: Documentation
|
||||
---
|
||||
|
||||
|
||||
The Weave Net plugin actually provides *two* network drivers to Docker - one named `weavemesh` that can operate without a cluster store and another one named `weave` that can only work with one (like Docker's overlay driver).
|
||||
The Weave Net legacy plugin actually provides *two* network drivers to Docker -
|
||||
one named `weavemesh` that can operate without a cluster store and another one
|
||||
named `weave` that can only work with one (like Docker's overlay driver), while
|
||||
the V2 plugin provides *one* - `store/weaveworks/net-plugin:latest_release`
|
||||
operating only in swarm mode.
|
||||
|
||||
### `weavemesh` driver
|
||||
|
||||
@@ -23,7 +27,7 @@ If you do create additional networks using the `weavemesh` driver, containers at
|
||||
|
||||
There's no specific documentation from Docker on using a cluster
|
||||
store, but the first part of
|
||||
[Getting Started with Docker Multi-host Networking](https://github.com/docker/docker/blob/master/docs/userguide/networking/get-started-overlay.md) is a good place to start.
|
||||
[Getting Started with Docker Multi-host Networking](https://docs.docker.com/engine/userguide/networking/get-started-overlay/) is a good place to start.
|
||||
|
||||
>**Note:** In the case of multiple networks using the `weave` driver, all containers are on the same virtual network but Docker allocates their addresses on different subnets so they cannot talk to each other directly.
|
||||
|
||||
@@ -37,7 +41,16 @@ The plugin accepts the following options via `docker network create ... --opt`:
|
||||
network created when the plugin is first launched has the multicast
|
||||
option turned on, but for any networks you create it defaults to off.
|
||||
|
||||
### `store/weaveworks/net-plugin:latest_release` driver
|
||||
|
||||
* The driver runs within the plugin V2.
|
||||
* Requires Docker to run in [swarm mode](https://docs.docker.com/engine/swarm/swarm-mode/).
|
||||
* Supports multiple networks.
|
||||
* Used with Docker's IPAM.
|
||||
|
||||
|
||||
**See Also**
|
||||
|
||||
* [Integrating Docker via the Network Plugin](/site/plugin.md)
|
||||
* [Integrating Docker via the Network Plugin (Legacy)](/site/plugin.md)
|
||||
* [Integrating Docker via the Network Plugin (V2)](/site/plugin-v2.md)
|
||||
|
||||
@@ -74,7 +74,7 @@ $ weave status
|
||||
Service: proxy
|
||||
Address: tcp://127.0.0.1:12375
|
||||
|
||||
Service: plugin
|
||||
Service: plugin (legacy)
|
||||
DriverName: weave
|
||||
```
|
||||
|
||||
@@ -284,14 +284,11 @@ on reboot. This can be disabled via:
|
||||
|
||||
weave launch --no-restart
|
||||
|
||||
Note that the
|
||||
[Weave Net Docker API Proxy](/site/weave-docker-api.md)
|
||||
is responsible for reconfiguring the Weave router and re-attaching
|
||||
application containers to the Weave network at startup, so if you
|
||||
choose not to run it you must make arrangements for this
|
||||
reconfiguration to take place. In this scenario, set up your favourite
|
||||
process manager to run `weave launch-router` every time the machine
|
||||
reboots.
|
||||
Note that the Weave Net router will create the `weave` network bridge
|
||||
if necessary when it restarts, and the [Weave Net Docker API
|
||||
Proxy](/site/weave-docker-api.md) will re-attach any application
|
||||
containers that it originally attached to the Weave network when they
|
||||
restart.
|
||||
|
||||
## <a name="snapshots"></a>Snapshot Releases
|
||||
|
||||
|
||||
+3
-1
@@ -136,5 +136,7 @@ Weave Net supports *any* protocol, and it doesn't have to be over TCP/IP. For ex
|
||||
**See Also**
|
||||
|
||||
* [Installing Weave Net](/site/installing-weave.md)
|
||||
* [Using Weave Cloud to get started with Weave Net](/site/using-weave/weave-cloud.md)
|
||||
* [Using Fastdp With Weave Net](/site/using-weave/fastdp.md)
|
||||
* [Using the Weave Net Docker Network Plugin](/site/plugin.md)
|
||||
* [Integrating Docker via the Network Plugin (Legacy)](/site/plugin.md)
|
||||
* [Integrating Docker via the Network Plugin (V2)](/site/plugin-v2.md)
|
||||
@@ -21,6 +21,22 @@ where,
|
||||
|
||||
>Note If you are using the Weave Docker API proxy, it will have modified `DOCKER_HOST` to point to the proxy and therefore you will 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.
|
||||
|
||||
If `weave attach` sees the container has a hostname with a
|
||||
domain-name, it will add those into WeaveDNS (unless you turn this off
|
||||
with the `--without-dns` argument).
|
||||
|
||||
host1$ docker run -dti --name=c1 --hostname=c1.weave.local weaveworks/ubuntu
|
||||
host1$ weave attach c1
|
||||
10.32.0.1
|
||||
host1$ weave dns-lookup c1
|
||||
10.32.0.1
|
||||
|
||||
If you would like `/etc/hosts` to contain the Weave Net address (the
|
||||
same way [the proxy does](/site/weave-docker-api/name-resolution-proxy.md)),
|
||||
specify `--rewrite-hosts` when running `weave attach`:
|
||||
|
||||
host1$ weave attach --rewrite-hosts c1
|
||||
|
||||
### Dynamically Detaching Containers
|
||||
|
||||
A container can be detached from a subnet, by using the `weave detach` command:
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 121 KiB |
@@ -0,0 +1,128 @@
|
||||
---
|
||||
title: Using Weave Cloud to get started with Weave Net
|
||||
menu_order: 10
|
||||
search_type: Documentation
|
||||
---
|
||||
|
||||
Weave Net provides a simple to deploy networking solution for containerized apps. Here, we describe how to manage a Weave container network using a sample application which consists of two simple `netcat` services deployed to containers on two separate hosts.
|
||||
|
||||
This section contains the following topics:
|
||||
|
||||
* [Signing in to Weave Cloud](#signing-in)
|
||||
* [Launching Weave Net](#launching)
|
||||
* [Launching on Additional Hosts](#peer-connections)
|
||||
* [How Peer Discovery Works](#how-it-works)
|
||||
|
||||
### <a name="signing-in"></a>Signing in to Weave Cloud
|
||||
|
||||
Weave Cloud is a fast and simple way to visualize, manage and monitor
|
||||
containers and microservices. In order to use Weave Cloud to set up
|
||||
Weave Net, you must sign up to Weave Cloud and create an "Instance".
|
||||
|
||||
The instance will have a Service Token which is a 32-character string
|
||||
used to uniquely identify it. Get hold of the Service Token for your
|
||||
Instance, as shown below:
|
||||
|
||||

|
||||
|
||||
For the purpose of these instructions we will use a dummy Service
|
||||
Token `dk6hz1acdd58aea6b75migoy4axqasdf`.
|
||||
|
||||
|
||||
### <a name="launching"></a>Launching Weave Net
|
||||
|
||||
Before launching Weave Net and deploying your apps, ensure that Docker
|
||||
is [installed](https://docs.docker.com/engine/installation/) on both
|
||||
hosts.
|
||||
|
||||
On `$HOST1` run:
|
||||
|
||||
host1$ weave launch --token=dk6hz1acdd58aea6b75migoy4axqasdf
|
||||
host1$ eval $(weave env)
|
||||
host1$ docker run --name a1 -ti weaveworks/ubuntu
|
||||
|
||||
Where,
|
||||
|
||||
* The first line runs Weave Net.
|
||||
|
||||
* The second line configures the Weave Net environment, so that containers launched via the Docker command line are automatically attached to the Weave network, and,
|
||||
* The third line runs the [application container](/site/faq.md#own-image) using [a Docker command](https://docs.docker.com/engine/reference/run/).
|
||||
|
||||
> **Note** If the first command results in an error like
|
||||
> ```
|
||||
> Cannot connect to the Docker daemon. Is the docker daemon running on this host?
|
||||
> ```
|
||||
> 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:
|
||||
> ```
|
||||
> host1$ sudo -s
|
||||
> host1# weave launch --token=dk6hz1acdd58aea6b75migoy4axqasdf
|
||||
> host1# eval $(weave env)
|
||||
> host1# docker run --name a1 -ti weaveworks/ubuntu
|
||||
> ```
|
||||
> 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.
|
||||
|
||||
Weave Net must be launched once per host. The relevant container images will be pulled down from Docker Hub on demand during `weave launch`.
|
||||
|
||||
You can also preload the images by running `weave setup`. Preloaded images are useful for automated deployments, and ensure there are no delays during later operations.
|
||||
|
||||
If you are deploying an application that consists of more than one container to the same host, launch them one after another using `docker run`, as appropriate.
|
||||
|
||||
|
||||
### <a name="peer-connections"></a>Launching on Additional Hosts
|
||||
|
||||
To launch Weave Net on an additional host and create a peer
|
||||
connection, run exactly the same commands as on the first host:
|
||||
|
||||
host2$ weave launch --token=dk6hz1acdd58aea6b75migoy4axqasdf
|
||||
host2$ eval $(weave env)
|
||||
host2$ docker run --name a2 -ti weaveworks/ubuntu
|
||||
|
||||
Because you are using Weave Cloud, the second peer will discover the
|
||||
first and automatically create a connection to it.
|
||||
|
||||
>**Note:** If there is a firewall between `$HOST1` and `$HOST2`, you must permit traffic to flow through TCP 6783 and UDP 6783/6784, which are Weave’s control and data ports.
|
||||
|
||||
Now you can proceed to [test container communications](/site/using-weave#testing)
|
||||
|
||||
### <a name="how-it-works"></a>How Peer Discovery Works
|
||||
|
||||
The Weave Cloud back-end maintains a database of all the peers that
|
||||
have registered in each instance. You can create as many instances as
|
||||
you like in the Weave Cloud console: for different projects, or to
|
||||
separate test and production.
|
||||
|
||||
As each peer starts up, it looks for all network instances that
|
||||
another peer might be able to contact it on, and registers those with the back-end.
|
||||
If you want to control which addresses are used, add the `--advertise-address` flag:
|
||||
|
||||
host1$ weave launch --token=dk6hz1acdd58aea6b75migoy4axqasdf --advertise-address=192.0.2.1,198.51.100.4
|
||||
|
||||
When the new peer registers itself, it also fetches a list of all
|
||||
other peers in the instance, and begins to contact them.
|
||||
|
||||
If the peer cannot contact the Weave Cloud back-end it will print an
|
||||
error message in its log and exit. To check the logs run:
|
||||
|
||||
host1$ docker logs weave
|
||||
|
||||
When a Weave Net instance is formed for the first time, the peers must
|
||||
initialize the [IP Allocation Manager](/site/ipam.md). This process,
|
||||
and the configuration options available, are unchanged when using
|
||||
Weave Cloud.
|
||||
|
||||
When you shut down a peer for good, use [the `weave reset`
|
||||
command](/site/ipam/stop-remove-peers-ipam.md) and it will be removed
|
||||
from the Weave Cloud database so future peers will not attempt to
|
||||
connect to it.
|
||||
|
||||
**See Also**
|
||||
|
||||
* [Installing Weave Net](/site/installing-weave.md)
|
||||
* [Using Weave Net](/site/using-weave.md)
|
||||
* [Using Fastdp With Weave Net](/site/using-weave/fastdp.md)
|
||||
* [Integrating Docker via the Network Plugin (Legacy)](/site/plugin.md)
|
||||
* [Integrating Docker via the Network Plugin (V2)](/site/plugin-v2.md)
|
||||
+22
-27
@@ -7,48 +7,45 @@ search_type: Documentation
|
||||
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 the [remote API](https://docs.docker.com/reference/api/docker_remote_api/),
|
||||
instead of `weave run`.
|
||||
or the [remote API](https://docs.docker.com/reference/api/docker_remote_api/).
|
||||
|
||||
### <a name="attaching-containers"></a>Attaching Containers to a Weave Network
|
||||
|
||||
There are three ways to attach containers to a Weave network (which method to use is
|
||||
There are three ways to attach containers to a Weave network (which method to use is
|
||||
entirely up to you):
|
||||
|
||||
**1.** The Weave Net Docker API Proxy. See [Setting Up the Weave Net Docker API Proxy](#weave-api-proxy).
|
||||
**1.** The Weave Net Docker API Proxy. See [Setting Up the Weave Net Docker API Proxy](#weave-api-proxy).
|
||||
|
||||
**2.** The Docker Network Plugin framework. The Docker Network Plugin is used when
|
||||
Docker containers are started with the --net flag, for example:
|
||||
**2.** The Docker Network Plugin framework. The Docker Network Plugin is used when
|
||||
Docker containers are started with the --net flag, for example:
|
||||
|
||||
`docker run --net <docker-run-options>`
|
||||
|
||||
**Where,**
|
||||
**Where,**
|
||||
|
||||
* `<docker-run-options>` are the [docker run options](https://docs.docker.com/engine/reference/run/)
|
||||
you give to your container on start
|
||||
* `<docker-run-options>` are the [docker run options](https://docs.docker.com/engine/reference/run/)
|
||||
you give to your container on start
|
||||
|
||||
Note that if a Docker container is started with the --net flag, then the Weave Docker API Proxy
|
||||
is automatically disabled and is not used to attach containers.
|
||||
See [Integrating Docker via the Network Plugin](/site/plugin.md).
|
||||
is automatically disabled and is not used to attach containers.
|
||||
See [Integrating Docker via the Network Plugin (Legacy)](/site/plugin.md) and
|
||||
[Integrating Docker via the Network Plugin (V2)](/site/plugin-v2.md).
|
||||
|
||||
**3.** Containers can also be attached to the Weave network with `weave run` commands. This method also
|
||||
does not use the Weave Docker API Proxy.
|
||||
See [Launching Containers With Weave Run (without the Proxy)](/site/weave-docker-api/launching-without-proxy.md).
|
||||
**3.** Containers can also be attached to the Weave network with `weave attach` commands. This method also
|
||||
does not use the Weave Docker API Proxy.
|
||||
See [Dynamically Attaching and Detaching Containers](/site/using-weave/dynamically-attach-containers.md).
|
||||
|
||||
### <a name="weave-api-proxy"></a>Setting Up The Weave Net Docker API Proxy
|
||||
|
||||
The proxy sits between the Docker client (command line or API) and the
|
||||
Docker daemon, and intercepts the communication between the two. You can
|
||||
start it simultaneously with the router and weaveDNS via `launch`:
|
||||
Docker daemon, and intercepts the communication between the two.
|
||||
It is started along with the router and weaveDNS when you run:
|
||||
|
||||
host1$ weave launch
|
||||
|
||||
or independently via `launch-proxy`:
|
||||
**N.B.**: Prior to version 2.0, the `launch-proxy` command allowed to pass configuration options and to start the proxy independently.
|
||||
This command has been removed in 2.0 and `launch` now also accepts configuration options for the proxy.
|
||||
|
||||
host1$ weave launch-router && weave launch-proxy
|
||||
|
||||
The first form is more convenient. But only `launch-proxy` can be passed configuration arguments.
|
||||
Therefore if you need to modify the default behaviour of the proxy, you must use `launch-proxy`.
|
||||
|
||||
By default, the proxy decides where to listen based on how the
|
||||
launching client connects to Docker. If the launching client connected
|
||||
@@ -57,7 +54,7 @@ the launching client connects over TCP, the proxy listens on port
|
||||
12375, on all network interfaces. This can be adjusted using the `-H`
|
||||
argument, for example:
|
||||
|
||||
host1$ weave launch-proxy -H tcp://127.0.0.1:9999
|
||||
host1$ weave launch -H tcp://127.0.0.1:9999
|
||||
|
||||
If no TLS or listening interfaces are set, TLS is auto-configured
|
||||
based on the Docker daemon's settings, and the listening interfaces are
|
||||
@@ -82,14 +79,12 @@ Alternatively, the proxy host can be set on a per-command basis with
|
||||
|
||||
host1$ docker $(weave config) ps
|
||||
|
||||
The proxy can be stopped independently with
|
||||
The proxy can be stopped, along with the router and weaveDNS, with
|
||||
|
||||
host1$ weave stop-proxy
|
||||
|
||||
or in conjunction with the router and weaveDNS via `stop`.
|
||||
host1$ weave stop
|
||||
|
||||
If you set your `DOCKER_HOST` to point at the proxy, you should revert
|
||||
to the original settings prior to stopping the proxy.
|
||||
to the original settings prior to running `stop`.
|
||||
|
||||
|
||||
**See Also**
|
||||
|
||||
@@ -19,17 +19,17 @@ For those situations, the proxy provides the following flags:
|
||||
* `--hostname-from-label<labelkey>`
|
||||
* `--hostname-match <regexp>`
|
||||
* `--hostname-replacement <replacement>`
|
||||
|
||||
|
||||
When launching a container, the hostname is initialized to the
|
||||
value of the container label using key `<labelkey>`. If no `<labelkey>` was
|
||||
provided, then the container name is used.
|
||||
provided, then the container name is used.
|
||||
|
||||
Additionally, the hostname is matched against a regular expression `<regexp>` and based on that match,
|
||||
`<replacement>` is used to obtain the final hostname, and then handed over to weaveDNS for registration.
|
||||
|
||||
For example, you can launch the proxy using all three flags, as follows:
|
||||
|
||||
host1$ weave launch-router && weave launch-proxy --hostname-from-label hostname-label --hostname-match '^aws-[0-9]+-(.*)$' --hostname-replacement 'my-app-$1'
|
||||
host1$ weave launch --hostname-from-label hostname-label --hostname-match '^aws-[0-9]+-(.*)$' --hostname-replacement 'my-app-$1'
|
||||
host1$ eval $(weave env)
|
||||
|
||||
>**Note:** regexp substitution groups must be pre-pended with a dollar sign
|
||||
|
||||
@@ -25,18 +25,18 @@ To start a container without connecting it to the Weave network, pass
|
||||
If you do not want an IP to be assigned by default, the proxy needs to
|
||||
be passed the `--no-default-ipalloc` flag, for example:
|
||||
|
||||
host1$ weave launch-proxy --no-default-ipalloc
|
||||
host1$ weave launch --no-default-ipalloc
|
||||
|
||||
In this configuration, containers using no `WEAVE_CIDR` environment
|
||||
variable are not connected to the Weave network.
|
||||
variable are not connected to the Weave network.
|
||||
|
||||
Containers started with a `WEAVE_CIDR` environment variable are handled as before.
|
||||
Containers started with a `WEAVE_CIDR` environment variable are handled as before.
|
||||
To automatically assign an address in this mode, start the
|
||||
container with a blank `WEAVE_CIDR`, for example:
|
||||
|
||||
host1$ docker run -ti -e WEAVE_CIDR="" weaveworks/ubuntu
|
||||
|
||||
|
||||
**See Also**
|
||||
|
||||
* [Address Allocation with IP Address Management (IPAM)](/site/ipam.md)
|
||||
* [How to Manually Specify IP Addresses and Subnets](/site/using-weave/manual-ip-address.md)
|
||||
* [How to Manually Specify IP Addresses and Subnets](/site/using-weave/manual-ip-address.md)
|
||||
@@ -4,44 +4,18 @@ menu_order: 50
|
||||
search_type: Documentation
|
||||
---
|
||||
|
||||
In prior versions of Weave Net, we supported a command `weave run`
|
||||
which would run a container and attach it to the Weave Network.
|
||||
|
||||
If you don't want to use the proxy, you can also launch
|
||||
containers on to the Weave network using `weave run`:
|
||||
This command always had limitations, and now we have Docker plugins
|
||||
and the Weave Net Docker API Proxy which do not have those
|
||||
limitations, we have removed `weave run`.
|
||||
|
||||
$ weave run -ti weaveworks/ubuntu
|
||||
If you have scripts using `weave run`, you can achieve exactly the
|
||||
same effect by combining `docker run` and `weave attach`; see
|
||||
[Dynamically Attaching and Detaching
|
||||
Containers](/site/using-weave/dynamically-attach-containers.md) for
|
||||
details.
|
||||
|
||||
The arguments after `run` are passed through to `docker run`. Therefore you
|
||||
can freely specify whatever Docker options you need.
|
||||
|
||||
Once the container is started, `weave run` attaches it to the Weave network, and in
|
||||
this example, it obtains an automatically allocated IP.
|
||||
|
||||
You can specify IP addresses manually instead:
|
||||
|
||||
$ weave run 10.2.1.1/24 -ti weaveworks/ubuntu
|
||||
|
||||
`weave run` rewrites `/etc/hosts` in the same way
|
||||
[the proxy does](/site/weave-docker-api/name-resolution-proxy.md). If you need to keep
|
||||
the original file, specify `--no-rewrite-hosts` when running
|
||||
the container:
|
||||
|
||||
$ weave run --no-rewrite-hosts 10.2.1.1/24 -ti weaveworks/ubuntu
|
||||
|
||||
There are some limitations to starting containers using `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 using `docker start` and attaches them to the Weave network.
|
||||
|
||||
|
||||
**See Also**
|
||||
|
||||
* [Setting Up The Weave Docker API Proxy](/site/weave-docker-api.md)
|
||||
* [Securing Docker Communications With TLS](/site/weave-docker-api/securing-proxy.md)
|
||||
* [Name Resolution via `/etc/hosts`](/site/weave-docker-api/name-resolution-proxy.md)
|
||||
The `weave start` and `weave restart` commands have also been removed,
|
||||
for the same reasons.
|
||||
@@ -9,7 +9,7 @@ When starting Weave Net enabled containers, the proxy automatically
|
||||
replaces the container's `/etc/hosts` file, and disables Docker's control
|
||||
over it. The new file contains an entry for the container's hostname
|
||||
and Weave Net IP address, as well as additional entries that have been
|
||||
specified using the `--add-host` parameters.
|
||||
specified using the `--add-host` parameters.
|
||||
|
||||
This ensures that:
|
||||
|
||||
@@ -27,9 +27,9 @@ IP instead of the Weave IP, or you require name resolution for
|
||||
Docker-managed networks), the proxy must be launched using the
|
||||
`--no-rewrite-hosts` flag.
|
||||
|
||||
host1$ weave launch-router && weave launch-proxy --no-rewrite-hosts
|
||||
|
||||
host1$ weave launch --no-rewrite-hosts
|
||||
|
||||
**See Also**
|
||||
|
||||
* [Using Automatic Discovery With the Weave Proxy](/site/weave-docker-api/automatic-discovery-proxy.md)
|
||||
|
||||
* [Using Automatic Discovery With the Weave Proxy](/site/weave-docker-api/automatic-discovery-proxy.md)
|
||||
|
||||
@@ -8,21 +8,21 @@ If you are [connecting to the docker daemon with
|
||||
TLS](https://docs.docker.com/articles/https/), you most likely want
|
||||
to do the same when connecting to the proxy. The proxy
|
||||
automatically detects the Docker daemon's TLS configuration, and
|
||||
attempts to duplicate it.
|
||||
attempts to duplicate it.
|
||||
|
||||
In the standard auto-detection case you can launch a TLS-enabled proxy as follows:
|
||||
|
||||
host1$ weave launch-proxy
|
||||
host1$ weave launch
|
||||
|
||||
To disable auto-detection of TLS configuration, you can either pass
|
||||
the `--no-detect-tls` flag, or you can manually configure the proxy's TLS using
|
||||
the same TLS-related command-line flags supplied to the Docker
|
||||
daemon.
|
||||
daemon.
|
||||
|
||||
For example, if you generated your certificates and keys
|
||||
into the Docker host's `/tls` directory, launch the proxy using:
|
||||
|
||||
host1$ weave launch-proxy --tlsverify --tlscacert=/tls/ca.pem \
|
||||
host1$ weave launch --tlsverify --tlscacert=/tls/ca.pem \
|
||||
--tlscert=/tls/server-cert.pem --tlskey=/tls/server-key.pem
|
||||
|
||||
The paths to your certificates and key must be provided as absolute
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
title: Troubleshooting
|
||||
menu_order: 60
|
||||
search_type: Documentation
|
||||
---
|
||||
|
||||
The command
|
||||
|
||||
weave status
|
||||
|
||||
reports on the current status of various Weave Net components, including
|
||||
the proxy, if it is running:
|
||||
|
||||
```
|
||||
...
|
||||
Service: proxy
|
||||
Address: tcp://127.0.0.1:12375
|
||||
...
|
||||
```
|
||||
|
||||
Information on the operation of the proxy can be obtained from the
|
||||
weaveproxy container logs using:
|
||||
|
||||
docker logs weaveproxy
|
||||
|
||||
**See Also**
|
||||
|
||||
* [Troubleshooting Weave](/site/troubleshooting.md)
|
||||
@@ -5,13 +5,13 @@ search_type: Documentation
|
||||
---
|
||||
|
||||
|
||||
When containers are created via the Weave Net proxy, their entrypoint is
|
||||
When containers are created via the Weave Net proxy, their entrypoint is
|
||||
modified to wait for the Weave network interface to become
|
||||
available.
|
||||
available.
|
||||
|
||||
When they are started via the Weave Net proxy, containers are
|
||||
When they are started via the Weave Net proxy, containers are
|
||||
[automatically assigned IP addresses](/site/ipam.md) and connected to the
|
||||
Weave network.
|
||||
Weave network.
|
||||
|
||||
### Creating and Starting Containers with the Weave Net Proxy
|
||||
|
||||
@@ -39,19 +39,19 @@ variable by space-separating them, as in
|
||||
The Docker NetworkSettings (including IP address, MacAddress, and
|
||||
IPPrefixLen), are still returned when `docker inspect` is run. If you want
|
||||
`docker inspect` to return the Weave NetworkSettings instead, then the
|
||||
proxy must be launched using the `--rewrite-inspect` flag.
|
||||
proxy must be launched using the `--rewrite-inspect` flag.
|
||||
|
||||
This command substitutes the Weave network settings when the container has a
|
||||
Weave Net IP. If a container has more than one Weave Net IP, then the inspect call
|
||||
only includes one of them.
|
||||
|
||||
host1$ weave launch-router && weave launch-proxy --rewrite-inspect
|
||||
host1$ weave launch --rewrite-inspect
|
||||
|
||||
### Multicast Traffic and Launching the Weave Proxy
|
||||
|
||||
By default, multicast traffic is routed over the Weave network.
|
||||
To turn this off, for example, because you want to configure your own multicast
|
||||
route, add the `--no-multicast-route` flag to `weave launch-proxy`.
|
||||
route, add the `--no-multicast-route` flag to `weave launch`.
|
||||
|
||||
### Other Weave Proxy options
|
||||
|
||||
@@ -61,8 +61,14 @@ route, add the `--no-multicast-route` flag to `weave launch-proxy`.
|
||||
* `--no-restart` -- remove the default policy of `--restart=always`, if
|
||||
you want to control start-up of the proxy yourself
|
||||
|
||||
### Disabling Weave Proxy
|
||||
|
||||
If for some reason you need to disable the proxy, but still want to start other Weave Net components (router, weaveDNS), you can do so using:
|
||||
|
||||
weave launch --proxy=false
|
||||
|
||||
|
||||
**See Also**
|
||||
|
||||
* [Setting Up The Weave Docker API Proxy](/site/weave-docker-api.md)
|
||||
* [Securing Docker Communications With TLS](/site/weave-docker-api/securing-proxy.md)
|
||||
* [Launching Containers With Weave Run (without the Proxy)](/site/weave-docker-api/launching-without-proxy.md)
|
||||
+1
-1
@@ -40,7 +40,7 @@ the hostname is not in the weaveDNS domain, the container is *not*
|
||||
registered, but it will still use weaveDNS for resolution.
|
||||
|
||||
To disable an application container's use of weaveDNS, add the
|
||||
`--without-dns` option to `weave run` or `weave launch-proxy`. To
|
||||
`--without-dns` option to `weave launch`. To
|
||||
disable weaveDNS itself, launch weave with the `--no-dns` option.
|
||||
|
||||
**See Also**
|
||||
|
||||
Loaded 100 of 156 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user