Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
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
-2
@@ -53,14 +53,14 @@ testing/runner/runner
|
|||||||
releases
|
releases
|
||||||
.*.uptodate
|
.*.uptodate
|
||||||
weave*.tar.gz
|
weave*.tar.gz
|
||||||
prog/weaveexec/weave
|
prog/weaver/weave
|
||||||
prog/weaveexec/weavehosts
|
prog/weaveexec/weavehosts
|
||||||
prog/weaveexec/weaveproxy
|
prog/weaveexec/weaveproxy
|
||||||
prog/weaveexec/weavewait
|
prog/weaveexec/weavewait
|
||||||
prog/weaveexec/weavewait_noop
|
prog/weaveexec/weavewait_noop
|
||||||
prog/weaveexec/weavewait_nomcast
|
prog/weaveexec/weavewait_nomcast
|
||||||
prog/weaveexec/sigproxy
|
prog/weaveexec/sigproxy
|
||||||
prog/weaveexec/weaveutil
|
prog/weaver/weaveutil
|
||||||
prog/weaveexec/docker*
|
prog/weaveexec/docker*
|
||||||
Vagrantfile.local
|
Vagrantfile.local
|
||||||
test/tls/tls
|
test/tls/tls
|
||||||
@@ -70,6 +70,7 @@ test/coverage.*
|
|||||||
*qemu-*-static
|
*qemu-*-static
|
||||||
terraform.tfstate
|
terraform.tfstate
|
||||||
terraform.tfstate.backup
|
terraform.tfstate.backup
|
||||||
|
prog/net-plugin/rootfs/
|
||||||
|
|
||||||
# Website
|
# Website
|
||||||
site-build
|
site-build
|
||||||
@@ -124,3 +124,12 @@
|
|||||||
[submodule "vendor/github.com/containernetworking/cni"]
|
[submodule "vendor/github.com/containernetworking/cni"]
|
||||||
path = vendor/github.com/containernetworking/cni
|
path = vendor/github.com/containernetworking/cni
|
||||||
url = https://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
|
||||||
+134
-1
@@ -1,8 +1,141 @@
|
|||||||
|
## 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
|
## Release 1.9.7
|
||||||
|
|
||||||
This is identical to 1.9.6 with one additional bug-fix:
|
This is identical to 1.9.6 with one additional bug-fix:
|
||||||
|
|
||||||
* weave-npc would block everything if `kubectl --hostname-override` was used #2995,#2996
|
* weave-npc would block everything if `kubelet --hostname-override` was used #2995,#2996
|
||||||
|
|
||||||
## Release 1.9.6
|
## Release 1.9.6
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -1,3 +1,3 @@
|
|||||||
DOCKER_VERSION=1.11.2
|
DOCKER_VERSION=1.13.1
|
||||||
KUBERNETES_VERSION=1.5.2
|
KUBERNETES_VERSION=1.6.2
|
||||||
KUBERNETES_CNI_VERSION=0.3.0.1
|
KUBERNETES_CNI_VERSION=0.5.1
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
.DEFAULT: all
|
.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="
|
# If you can use docker without being root, you can do "make SUDO="
|
||||||
SUDO=$(shell docker info >/dev/null 2>&1 || echo "sudo -E")
|
SUDO=$(shell docker info >/dev/null 2>&1 || echo "sudo -E")
|
||||||
@@ -82,10 +82,11 @@ endif
|
|||||||
DOCKERHUB_USER?=weaveworks
|
DOCKERHUB_USER?=weaveworks
|
||||||
# The default version that's chosen when pushing the images. Can/should be overridden
|
# The default version that's chosen when pushing the images. Can/should be overridden
|
||||||
WEAVE_VERSION?=git-$(shell git rev-parse --short=12 HEAD)
|
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
|
# Paths to all relevant binaries that should be compiled
|
||||||
WEAVER_EXE=prog/weaver/weaver
|
WEAVER_EXE=prog/weaver/weaver
|
||||||
WEAVEPROXY_EXE=prog/weaveproxy/weaveproxy
|
|
||||||
SIGPROXY_EXE=prog/sigproxy/sigproxy
|
SIGPROXY_EXE=prog/sigproxy/sigproxy
|
||||||
KUBEPEERS_EXE=prog/kube-peers/kube-peers
|
KUBEPEERS_EXE=prog/kube-peers/kube-peers
|
||||||
WEAVENPC_EXE=prog/weave-npc/weave-npc
|
WEAVENPC_EXE=prog/weave-npc/weave-npc
|
||||||
@@ -93,39 +94,44 @@ WEAVEWAIT_EXE=prog/weavewait/weavewait
|
|||||||
WEAVEWAIT_NOOP_EXE=prog/weavewait/weavewait_noop
|
WEAVEWAIT_NOOP_EXE=prog/weavewait/weavewait_noop
|
||||||
WEAVEWAIT_NOMCAST_EXE=prog/weavewait/weavewait_nomcast
|
WEAVEWAIT_NOMCAST_EXE=prog/weavewait/weavewait_nomcast
|
||||||
WEAVEUTIL_EXE=prog/weaveutil/weaveutil
|
WEAVEUTIL_EXE=prog/weaveutil/weaveutil
|
||||||
PLUGIN_EXE=prog/plugin/plugin
|
|
||||||
RUNNER_EXE=tools/runner/runner
|
RUNNER_EXE=tools/runner/runner
|
||||||
MANIFEST_TOOL_DIR=vendor/github.com/estesp/manifest-tool
|
MANIFEST_TOOL_DIR=vendor/github.com/estesp/manifest-tool
|
||||||
MANIFEST_TOOL_EXE=$(MANIFEST_TOOL_DIR)/manifest-tool
|
MANIFEST_TOOL_EXE=$(MANIFEST_TOOL_DIR)/manifest-tool
|
||||||
TEST_TLS_EXE=test/tls/tls
|
TEST_TLS_EXE=test/tls/tls
|
||||||
|
NETWORKTESTER_EXE=test/images/network-tester/webserver
|
||||||
|
|
||||||
# All binaries together in a list
|
# 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
|
# 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
|
BUILD_UPTODATE=.build.uptodate
|
||||||
WEAVER_UPTODATE=.weaver$(ARCH_EXT).uptodate
|
WEAVER_UPTODATE=.weaver$(ARCH_EXT).uptodate
|
||||||
WEAVEEXEC_UPTODATE=.weaveexec$(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
|
WEAVEKUBE_UPTODATE=.weavekube$(ARCH_EXT).uptodate
|
||||||
WEAVENPC_UPTODATE=.weavenpc$(ARCH_EXT).uptodate
|
WEAVENPC_UPTODATE=.weavenpc$(ARCH_EXT).uptodate
|
||||||
WEAVEDB_UPTODATE=.weavedb.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.
|
# 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)
|
WEAVER_IMAGE=$(DOCKERHUB_USER)/weave$(ARCH_EXT)
|
||||||
WEAVEEXEC_IMAGE=$(DOCKERHUB_USER)/weaveexec$(ARCH_EXT)
|
WEAVEEXEC_IMAGE=$(DOCKERHUB_USER)/weaveexec$(ARCH_EXT)
|
||||||
PLUGIN_IMAGE=$(DOCKERHUB_USER)/plugin$(ARCH_EXT)
|
|
||||||
WEAVEKUBE_IMAGE=$(DOCKERHUB_USER)/weave-kube$(ARCH_EXT)
|
WEAVEKUBE_IMAGE=$(DOCKERHUB_USER)/weave-kube$(ARCH_EXT)
|
||||||
WEAVENPC_IMAGE=$(DOCKERHUB_USER)/weave-npc$(ARCH_EXT)
|
WEAVENPC_IMAGE=$(DOCKERHUB_USER)/weave-npc$(ARCH_EXT)
|
||||||
BUILD_IMAGE=weaveworks/weavebuild
|
BUILD_IMAGE=weaveworks/weavebuild
|
||||||
WEAVEDB_IMAGE=$(DOCKERHUB_USER)/weavedb
|
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
|
PLUGIN_WORK_DIR="prog/net-plugin/rootfs"
|
||||||
PUSH_ML=push_ml_weave push_ml_weaveexec push_ml_plugin push_ml_weave-kube push_ml_weave-npc
|
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
|
WEAVE_EXPORT=weave$(ARCH_EXT).tar.gz
|
||||||
|
|
||||||
@@ -150,20 +156,21 @@ PACKAGE_BASE=$(shell go list -e ./)
|
|||||||
all: $(WEAVE_EXPORT)
|
all: $(WEAVE_EXPORT)
|
||||||
testrunner: $(RUNNER_EXE) $(TEST_TLS_EXE)
|
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
|
$(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
|
$(WEAVEUTIL_EXE): prog/weaveutil/*.go net/*.go plugin/net/*.go plugin/ipam/*.go db/*.go
|
||||||
$(SIGPROXY_EXE): prog/sigproxy/*.go
|
$(SIGPROXY_EXE): prog/sigproxy/*.go
|
||||||
$(KUBEPEERS_EXE): prog/kube-peers/*.go
|
$(KUBEPEERS_EXE): prog/kube-peers/*.go
|
||||||
$(WEAVENPC_EXE): prog/weave-npc/*.go npc/*.go npc/*/*.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
|
$(TEST_TLS_EXE): test/tls/*.go
|
||||||
$(RUNNER_EXE): tools/runner/*.go
|
$(RUNNER_EXE): tools/runner/*.go
|
||||||
$(MANIFEST_TOOL_EXE): $(MANIFEST_TOOL_DIR)/*.go
|
$(MANIFEST_TOOL_EXE): $(MANIFEST_TOOL_DIR)/*.go
|
||||||
$(WEAVEWAIT_NOOP_EXE): prog/weavewait/*.go
|
$(WEAVEWAIT_NOOP_EXE): prog/weavewait/*.go
|
||||||
$(WEAVEWAIT_EXE): prog/weavewait/*.go net/*.go
|
$(WEAVEWAIT_EXE): prog/weavewait/*.go net/*.go
|
||||||
$(WEAVEWAIT_NOMCAST_EXE): prog/weavewait/*.go net/*.go
|
$(WEAVEWAIT_NOMCAST_EXE): prog/weavewait/*.go net/*.go
|
||||||
|
$(NETWORKTESTER_EXE): test/images/network-tester/*.go
|
||||||
tests: tools/.git
|
tests: tools/.git
|
||||||
lint: tools/.git
|
lint: tools/.git
|
||||||
|
|
||||||
@@ -181,12 +188,13 @@ exes $(EXES) tests lint: $(BUILD_UPTODATE)
|
|||||||
-v $(shell pwd)/.pkg:/go/pkg \
|
-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 \
|
-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) $@
|
$(BUILD_IMAGE) COVERAGE=$(COVERAGE) WEAVE_VERSION=$(WEAVE_VERSION) CC=$(CC) QEMUARCH=$(QEMUARCH) CGO_LDFLAGS=$(CGO_LDFLAGS) $@
|
||||||
|
touch $@
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
exes: $(EXES)
|
exes: $(EXES)
|
||||||
|
|
||||||
$(WEAVER_EXE) $(WEAVEPROXY_EXE) $(PLUGIN_EXE):
|
$(WEAVER_EXE):
|
||||||
ifeq ($(COVERAGE),true)
|
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,))
|
$(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)/
|
go test -c -o ./$@ $(BUILD_FLAGS) -v -covermode=atomic -coverpkg $(COVERAGE_MODULES) ./$(@D)/
|
||||||
@@ -195,7 +203,7 @@ else
|
|||||||
endif
|
endif
|
||||||
$(NETGO_CHECK)
|
$(NETGO_CHECK)
|
||||||
|
|
||||||
$(WEAVEUTIL_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE):
|
$(WEAVEUTIL_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE) $(NETWORKTESTER_EXE):
|
||||||
go build $(BUILD_FLAGS) -o $@ ./$(@D)
|
go build $(BUILD_FLAGS) -o $@ ./$(@D)
|
||||||
$(NETGO_CHECK)
|
$(NETGO_CHECK)
|
||||||
|
|
||||||
@@ -246,25 +254,37 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# The targets below builds the weave images
|
# 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
|
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -f prog/weaver/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVER_IMAGE) prog/weaver
|
||||||
touch $@
|
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)
|
$(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 weave prog/weaveexec/weave
|
|
||||||
cp $(SIGPROXY_EXE) prog/weaveexec/sigproxy
|
cp $(SIGPROXY_EXE) prog/weaveexec/sigproxy
|
||||||
cp $(WEAVEPROXY_EXE) prog/weaveexec/weaveproxy
|
|
||||||
cp $(WEAVEWAIT_EXE) prog/weaveexec/weavewait
|
cp $(WEAVEWAIT_EXE) prog/weaveexec/weavewait
|
||||||
cp $(WEAVEWAIT_NOOP_EXE) prog/weaveexec/weavewait_noop
|
cp $(WEAVEWAIT_NOOP_EXE) prog/weaveexec/weavewait_noop
|
||||||
cp $(WEAVEWAIT_NOMCAST_EXE) prog/weaveexec/weavewait_nomcast
|
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
|
tar -xf $(DOCKER_DISTRIB) usr/local/bin/docker -O > prog/weaveexec/docker
|
||||||
chmod +x 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
|
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -f prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVEEXEC_IMAGE) prog/weaveexec
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
$(PLUGIN_UPTODATE): prog/plugin/Dockerfile.$(DOCKERHUB_USER) $(PLUGIN_EXE) $(WEAVER_UPTODATE)
|
# Builds Docker plugin.
|
||||||
$(SUDO) docker build -f prog/plugin/Dockerfile.$(DOCKERHUB_USER) -t $(PLUGIN_IMAGE) prog/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 $@
|
touch $@
|
||||||
|
|
||||||
$(WEAVEKUBE_UPTODATE): prog/weave-kube/Dockerfile.$(DOCKERHUB_USER) prog/weave-kube/launch.sh $(KUBEPEERS_EXE) $(WEAVER_UPTODATE)
|
$(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
|
$(SUDO) docker build -t $(WEAVEDB_IMAGE) prog/weavedb
|
||||||
touch $@
|
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)
|
$(WEAVE_EXPORT): $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE)
|
||||||
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker save $(addsuffix :latest,$(IMAGES)) | gzip > $@
|
$(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
|
# 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
|
# This target first runs "make publish" for each architecture
|
||||||
# Then it pushes the manifest lists
|
# Then it pushes the manifest lists
|
||||||
publish: $(addprefix sub-publish-,$(ALL_ARCHITECTURES)) $(WEAVEDB_UPTODATE)
|
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
|
$(MANIFEST_TOOL_EXE) push from-args --platforms $(ML_PLATFORMS) --template $(DOCKERHUB_USER)/$*-ARCH:latest --target $(DOCKERHUB_USER)/$*:latest
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
clean-work-dir:
|
||||||
|
rm -rf $(PLUGIN_WORK_DIR)
|
||||||
|
|
||||||
clean-bin:
|
clean-bin:
|
||||||
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(IMAGES)
|
-$(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 "Dockerfile.*" -not -name "Dockerfile.template" -print | xargs rm -f
|
||||||
find prog -type f -name "*qemu-*" -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
|
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)
|
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(BUILD_IMAGE)
|
||||||
rm -rf test/tls/*.pem test/coverage.* test/coverage $(BUILD_UPTODATE) $(MANIFEST_TOOL_EXE)
|
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://circleci.com/gh/weaveworks/weave)
|
||||||
[](https://coveralls.io/r/weaveworks/weave)
|
[](https://coveralls.io/r/weaveworks/weave)
|
||||||
[](https://goreportcard.com/report/github.com/weaveworks/weave)
|
[](https://goreportcard.com/report/github.com/weaveworks/weave)
|
||||||
[](https://slack.weave.works)
|
|
||||||
[](https://hub.docker.com/r/weaveworks/weave/)
|
[](https://hub.docker.com/r/weaveworks/weave/)
|
||||||
|
|
||||||
# About Weaveworks
|
# 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.
|
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.
|
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!
|
Your feedback is always welcome!
|
||||||
|
|
||||||
##Further Information
|
## Further Information
|
||||||
|
|
||||||
* [Installing Weave Net](https://www.weave.works/docs/net/latest/installing-weave/)
|
* [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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Special token used in place of a container identifier when:
|
// 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.
|
// which should be kept in mind if the entry needs to be removed at any point.
|
||||||
const NoContainerID string = "_"
|
const NoContainerID string = "_"
|
||||||
|
|
||||||
func (client *Client) ipamOp(ID string, op string) (*net.IPNet, error) {
|
func (client *Client) ipamOp(ID string, op string, values url.Values) (*net.IPNet, error) {
|
||||||
ip, err := client.httpVerb(op, fmt.Sprintf("/ip/%s", ID), nil)
|
ip, err := client.httpVerb(op, fmt.Sprintf("/ip/%s", ID), values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return parseIP(ip)
|
return parseIP(ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns an IP for the ID given, allocating a fresh one if necessary
|
func ipamValues(checkAlive bool) url.Values {
|
||||||
func (client *Client) AllocateIP(ID string) (*net.IPNet, error) {
|
values := make(url.Values)
|
||||||
return client.ipamOp(ID, "POST")
|
if checkAlive {
|
||||||
|
values.Set("check-alive", "true")
|
||||||
|
}
|
||||||
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) AllocateIPInSubnet(ID string, subnet *net.IPNet) (*net.IPNet, error) {
|
// returns an IP for the ID given, allocating a fresh one if necessary
|
||||||
ip, err := client.httpVerb("POST", fmt.Sprintf("/ip/%s/%s", ID, subnet), nil)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// returns an IP for the ID given, or nil if one has not been
|
||||||
// allocated
|
// allocated
|
||||||
func (client *Client) LookupIP(ID string) (*net.IPNet, error) {
|
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
|
// Claim a specific IP on behalf of the ID
|
||||||
func (client *Client) ClaimIP(ID string, cidr *net.IPNet) error {
|
func (client *Client) ClaimIP(ID string, cidr *net.IPNet, checkAlive bool) error {
|
||||||
_, err := client.httpVerb("PUT", fmt.Sprintf("/ip/%s/%s", ID, cidr), nil)
|
_, err := client.httpVerb("PUT", fmt.Sprintf("/ip/%s/%s", ID, cidr), ipamValues(checkAlive))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -76,6 +77,22 @@ func (client *Client) Connect(remote string) error {
|
|||||||
return err
|
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 {
|
type Logger interface {
|
||||||
Infof(string, ...interface{})
|
Infof(string, ...interface{})
|
||||||
Debugf(string, ...interface{})
|
Debugf(string, ...interface{})
|
||||||
|
|||||||
+2
-2
@@ -41,7 +41,7 @@ case "$1" in
|
|||||||
for i in $(seq $START $FINISH); do
|
for i in $(seq $START $FINISH); do
|
||||||
IP=$SUBNET.$i
|
IP=$SUBNET.$i
|
||||||
sudo ip addr add $IP/24 dev multiweave
|
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 "$@"
|
--name $(random_mac) --nickname weave$i "$@"
|
||||||
done
|
done
|
||||||
echo $(date -R) connecting
|
echo $(date -R) connecting
|
||||||
@@ -57,7 +57,7 @@ case "$1" in
|
|||||||
for i in $(seq $FINISH -1 $START); do
|
for i in $(seq $FINISH -1 $START); do
|
||||||
IP=$SUBNET.$i
|
IP=$SUBNET.$i
|
||||||
echo Stopping weave$i
|
echo Stopping weave$i
|
||||||
weave $i stop-router
|
weave $i stop
|
||||||
sudo ip addr del $IP/24 dev multiweave || true
|
sudo ip addr del $IP/24 dev multiweave || true
|
||||||
done
|
done
|
||||||
[ -z "$(ip -4 -o addr show multiweave)" ] && sudo ip link del multiweave
|
[ -z "$(ip -4 -o addr show multiweave)" ] && sudo ip link del multiweave
|
||||||
|
|||||||
@@ -191,6 +191,10 @@ publish() {
|
|||||||
make UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER publish
|
make UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER publish
|
||||||
echo "** Docker images tagged and pushed"
|
echo "** Docker images tagged and pushed"
|
||||||
|
|
||||||
|
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 "== Publishing pre-release on GitHub"
|
echo "== Publishing pre-release on GitHub"
|
||||||
|
|
||||||
github-release publish \
|
github-release publish \
|
||||||
@@ -223,6 +227,10 @@ publish() {
|
|||||||
make PUBLISH_WEAVEDB=$IS_MAINLINE UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER publish
|
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"
|
echo "** Docker images tagged and pushed"
|
||||||
|
|
||||||
|
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 "== Publishing release on GitHub"
|
echo "== Publishing release on GitHub"
|
||||||
|
|
||||||
github-release publish \
|
github-release publish \
|
||||||
|
|||||||
+3
-3
@@ -1,9 +1,9 @@
|
|||||||
FROM golang:1.7.4
|
FROM golang:1.8.1
|
||||||
|
|
||||||
# Support Raspberry Pi 2 and newer
|
# Support Raspberry Pi 2 and newer
|
||||||
ENV GOARM 7
|
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 \
|
ENV DEB_CROSSPLATFORMS \
|
||||||
armhf \
|
armhf \
|
||||||
arm64
|
arm64
|
||||||
@@ -18,7 +18,7 @@ ENV GCC_CROSSCOMPILERS \
|
|||||||
arm-linux-gnueabihf \
|
arm-linux-gnueabihf \
|
||||||
aarch64-linux-gnu
|
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
|
# 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 \
|
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 - \
|
&& 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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var ids []string
|
var ids []string
|
||||||
for _, c := range all {
|
for _, c := range containers {
|
||||||
ids = append(ids, c.ID)
|
ids = append(ids, c.ID)
|
||||||
}
|
}
|
||||||
return ids, nil
|
return ids, nil
|
||||||
@@ -213,6 +225,30 @@ func (c *Client) GetContainerIP(nameOrID string) (string, error) {
|
|||||||
return info.NetworkSettings.IPAddress, nil
|
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
|
// logging
|
||||||
|
|
||||||
func (c *Client) errorf(fmt string, args ...interface{}) {
|
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 (
|
const (
|
||||||
NameIdent = "peername"
|
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)
|
db, err := bolt.Open(dbPathname, 0660, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("[boltDB] Unable to open %s: %s", dbPathname, err)
|
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
|
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}
|
options := bolt.Options{Timeout: time.Millisecond * 50, ReadOnly: true}
|
||||||
|
dbPathname := Pathname(dbPrefix)
|
||||||
db, err := bolt.Open(dbPathname, 0660, &options)
|
db, err := bolt.Open(dbPathname, 0660, &options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("[boltDB] Unable to open %s: %s", dbPathname, err)
|
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
|
* Up-to-date versions of `git`, `go` etc
|
||||||
* Install GitHub release tool `go get github.com/weaveworks/github-release`
|
* Install GitHub release tool `go get github.com/weaveworks/github-release`
|
||||||
* Create a [github token for
|
* Create a [github token for
|
||||||
github-release](https://help.github.com/articles/creating-an-access-token-for-command-line-use/);
|
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
|
||||||
set and export `$GITHUB_TOKEN` with this value
|
|
||||||
|
|
||||||
## Release Types
|
## Release Types
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/weaveworks/weave/api"
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/weaveworks/weave/common"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/weaveworks/weave/net/address"
|
||||||
"github.com/weaveworks/weave/testing/gossip"
|
"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)
|
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) {
|
func TestAllocFree(t *testing.T) {
|
||||||
const (
|
const (
|
||||||
container1 = "abcdef"
|
container1 = "abcdef"
|
||||||
@@ -170,6 +175,8 @@ func TestAllocatorClaim(t *testing.T) {
|
|||||||
universe = "10.0.3.0/24"
|
universe = "10.0.3.0/24"
|
||||||
testAddr1 = "10.0.3.5/24"
|
testAddr1 = "10.0.3.5/24"
|
||||||
testAddr2 = "10.0.4.2/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"
|
testPre = "10.0.3.1/24"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -203,6 +210,9 @@ func TestAllocatorClaim(t *testing.T) {
|
|||||||
// claim for a different container should fail
|
// claim for a different container should fail
|
||||||
err = alloc.SimplyClaim(container1, addr1)
|
err = alloc.SimplyClaim(container1, addr1)
|
||||||
require.Error(t, err)
|
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
|
// claiming the address allocated on the other peer should fail
|
||||||
err = alloc.SimplyClaim(container1, address.MakeCIDR(subnet, addrx))
|
err = alloc.SimplyClaim(container1, address.MakeCIDR(subnet, addrx))
|
||||||
require.Error(t, err, "claiming address allocated on other peer should fail")
|
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)
|
addr2, _ := address.ParseCIDR(testAddr2)
|
||||||
err = alloc.SimplyClaim(container1, addr2)
|
err = alloc.SimplyClaim(container1, addr2)
|
||||||
require.NoError(t, err)
|
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() {
|
func (alloc *Allocator) pause() func() {
|
||||||
|
|||||||
+22
-7
@@ -40,10 +40,29 @@ func (c *claim) Try(alloc *Allocator) bool {
|
|||||||
return true
|
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) {
|
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.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)
|
c.sendResult(nil)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -85,11 +104,7 @@ func (c *claim) Try(alloc *Allocator) bool {
|
|||||||
// Unused address, we try to claim it:
|
// Unused address, we try to claim it:
|
||||||
if err := alloc.space.Claim(c.cidr.Addr); err == nil {
|
if err := alloc.space.Claim(c.cidr.Addr); err == nil {
|
||||||
alloc.debugln("Claimed", c.cidr, "for", c.ident)
|
alloc.debugln("Claimed", c.cidr, "for", c.ident)
|
||||||
if c.ident == api.NoContainerID {
|
addOwned()
|
||||||
alloc.addOwned(c.cidr.Addr.String(), c.cidr, c.isContainer)
|
|
||||||
} else {
|
|
||||||
alloc.addOwned(c.ident, c.cidr, c.isContainer)
|
|
||||||
}
|
|
||||||
c.sendResult(nil)
|
c.sendResult(nil)
|
||||||
} else {
|
} else {
|
||||||
c.sendResult(err)
|
c.sendResult(err)
|
||||||
|
|||||||
+34
-11
@@ -1,6 +1,7 @@
|
|||||||
package ipam
|
package ipam
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@@ -127,6 +128,39 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
|
|||||||
writeAddresses(w, addrs)
|
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) {
|
router.Methods("POST").Path("/ip/{id}/{ip}/{prefixlen}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
if subnet, ok := parseCIDR(w, vars["ip"]+"/"+vars["prefixlen"], true); ok {
|
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)
|
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) {
|
router.Methods("GET").Path("/ipinfo/tracker").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintf(w, tracker)
|
fmt.Fprintf(w, tracker)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import (
|
|||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/weaveworks/weave/common"
|
||||||
wnet "github.com/weaveworks/weave/net"
|
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/weaveworks/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -42,7 +41,7 @@ type AWSVPCTracker struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewAWSVPCTracker creates and initialises AWS VPC based tracker.
|
// NewAWSVPCTracker creates and initialises AWS VPC based tracker.
|
||||||
func NewAWSVPCTracker() (*AWSVPCTracker, error) {
|
func NewAWSVPCTracker(bridgeName string) (*AWSVPCTracker, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
session = session.New()
|
session = session.New()
|
||||||
@@ -69,9 +68,9 @@ func NewAWSVPCTracker() (*AWSVPCTracker, error) {
|
|||||||
t.routeTableID = *routeTableID
|
t.routeTableID = *routeTableID
|
||||||
|
|
||||||
// Detect Weave bridge link index
|
// Detect Weave bridge link index
|
||||||
link, err := netlink.LinkByName(wnet.WeaveBridgeName)
|
link, err := netlink.LinkByName(bridgeName)
|
||||||
if err != nil {
|
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
|
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)
|
vars = mux.Vars(r)
|
||||||
container = vars["container"]
|
container = vars["container"]
|
||||||
ipStr = vars["ip"]
|
ipStr = vars["ip"]
|
||||||
hostname = dns.Fqdn(r.FormValue("fqdn"))
|
fqdn = r.FormValue("fqdn")
|
||||||
ip, err = address.ParseIP(ipStr)
|
ip, err = address.ParseIP(ipStr)
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -35,16 +35,11 @@ func (n *Nameserver) HandleHTTP(router *mux.Router, dockerCli *docker.Client) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dns.IsSubDomain(n.domain, hostname) {
|
n.AddEntryFQDN(fqdn, container, n.ourName, ip)
|
||||||
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)
|
|
||||||
|
|
||||||
if r.FormValue("check-alive") == "true" && dockerCli != nil && dockerCli.IsContainerNotRunning(container) {
|
if r.FormValue("check-alive") == "true" && dockerCli != nil && dockerCli.IsContainerNotRunning(container) {
|
||||||
n.infof("container '%s' is not running: removing", 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)
|
w.WriteHeader(204)
|
||||||
|
|||||||
@@ -91,6 +91,15 @@ func (n *Nameserver) AddEntry(hostname, containerid string, origin mesh.PeerName
|
|||||||
n.broadcastEntries(entry)
|
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 {
|
func (n *Nameserver) Lookup(hostname string) []address.Address {
|
||||||
n.RLock()
|
n.RLock()
|
||||||
defer n.RUnlock()
|
defer n.RUnlock()
|
||||||
|
|||||||
@@ -160,6 +160,11 @@ func (cidr CIDR) String() string {
|
|||||||
return fmt.Sprintf("%s/%d", cidr.Addr.String(), cidr.PrefixLen)
|
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
|
// FromIP4 converts an ipv4 address to our integer address type
|
||||||
func FromIP4(ip4 net.IP) (r Address) {
|
func FromIP4(ip4 net.IP) (r Address) {
|
||||||
for _, b := range ip4.To4() {
|
for _, b := range ip4.To4() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package address
|
package address
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
"testing/quick"
|
"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.0.0"), cidr.Start(), "")
|
||||||
require.Equal(t, ip("10.0.1.0"), cidr.End(), "")
|
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
|
package net
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
import "io"
|
"fmt"
|
||||||
import "os"
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
// Configure the ARP cache parameters for the given interface. This
|
// Configure the ARP cache parameters for the given interface. This
|
||||||
// makes containers react more quickly to a change in the MAC address
|
// makes containers react more quickly to a change in the MAC address
|
||||||
// associated with an IP address.
|
// associated with an IP address.
|
||||||
func ConfigureARPCache(name string) error {
|
func ConfigureARPCache(procPath, name string) error {
|
||||||
if err := sysctl(fmt.Sprintf("net/ipv4/neigh/%s/base_reachable_time", name), "5"); err != nil {
|
if err := sysctl(procPath, fmt.Sprintf("net/ipv4/neigh/%s/base_reachable_time", name), "5"); err != nil {
|
||||||
return err
|
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
|
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 err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sysctl(variable, value string) error {
|
func sysctl(procPath, variable, value string) error {
|
||||||
f, err := os.OpenFile(fmt.Sprintf("/proc/sys/%s", variable), os.O_WRONLY, 0)
|
f, err := os.OpenFile(filepath.Join(procPath, "/sys/", variable), os.O_WRONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+418
-13
@@ -2,43 +2,136 @@ package net
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"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/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 (
|
const (
|
||||||
WeaveBridgeName = "weave"
|
WeaveBridgeName = "weave"
|
||||||
DatapathName = "datapath"
|
DatapathName = "datapath"
|
||||||
|
DatapathIfName = "vethwe-datapath"
|
||||||
None BridgeType = iota
|
BridgeIfName = "vethwe-bridge"
|
||||||
Bridge
|
PcapIfName = "vethwe-pcap"
|
||||||
Fastdp
|
|
||||||
BridgedFastdp
|
|
||||||
Inconsistent
|
|
||||||
)
|
)
|
||||||
|
|
||||||
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
|
||||||
|
}
|
||||||
|
|
||||||
|
var errBridgeFallback = errors.New("special error value used to trigger a fallback to bridge type")
|
||||||
|
|
||||||
|
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)
|
bridge, _ := netlink.LinkByName(weaveBridgeName)
|
||||||
datapath, _ := netlink.LinkByName(datapathName)
|
datapath, _ := netlink.LinkByName(datapathName)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case bridge == nil && datapath == nil:
|
case bridge == nil && datapath == nil:
|
||||||
return None
|
return nil, nil
|
||||||
case isBridge(bridge) && datapath == nil:
|
case isBridge(bridge) && datapath == nil:
|
||||||
return Bridge
|
return bridgeImpl{bridge: bridge}, nil
|
||||||
case isDatapath(bridge) && datapath == nil:
|
case isDatapath(bridge) && datapath == nil:
|
||||||
return Fastdp
|
return fastdpImpl{datapathName: datapathName}, nil
|
||||||
case isDatapath(datapath) && isBridge(bridge):
|
case isDatapath(datapath) && isBridge(bridge):
|
||||||
return BridgedFastdp
|
return bridgedFastdpImpl{bridgeImpl{bridge: bridge}, fastdpImpl{datapathName: datapathName}}, nil
|
||||||
default:
|
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 {
|
func isBridge(link netlink.Link) bool {
|
||||||
_, isBridge := link.(*netlink.Bridge)
|
_, isBridge := link.(*netlink.Bridge)
|
||||||
return isBridge
|
return isBridge
|
||||||
@@ -108,3 +201,315 @@ func FindBridgeIP(bridgeName string, subnet *net.IPNet) (net.IP, error) {
|
|||||||
// No subnet, or none in the required subnet; just return the first one
|
// No subnet, or none in the required subnet; just return the first one
|
||||||
return netdev.CIDRs[0].IP, nil
|
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) (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 err == errBridgeFallback {
|
||||||
|
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 err != nil {
|
||||||
|
return errors.Wrapf(err, "creating datapath %q", f.datapathName)
|
||||||
|
}
|
||||||
|
if !odpSupported {
|
||||||
|
return errBridgeFallback
|
||||||
|
}
|
||||||
|
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
|
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"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
@@ -80,5 +81,9 @@ func WithNetNSByPid(pid int, cmd string, args ...string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NSPathByPid(pid int) string {
|
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
|
return append(machineid, uuid...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPersistedPeerName(pathName string) (mesh.PeerName, error) {
|
func getPersistedPeerName(dbPrefix string) (mesh.PeerName, error) {
|
||||||
d, err := db.NewBoltDBReadOnly(pathName)
|
d, err := db.NewBoltDBReadOnly(dbPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mesh.UnknownPeerName, err
|
return mesh.UnknownPeerName, err
|
||||||
}
|
}
|
||||||
@@ -56,9 +56,8 @@ func getPersistedPeerName(pathName string) (mesh.PeerName, error) {
|
|||||||
func GetSystemPeerName(dbPrefix, hostRoot string) (string, error) {
|
func GetSystemPeerName(dbPrefix, hostRoot string) (string, error) {
|
||||||
// Check if we have a persisted name that matches the old-style ID for this host
|
// Check if we have a persisted name that matches the old-style ID for this host
|
||||||
if oldUUID, err := getOldStyleSystemUUID(); err == nil {
|
if oldUUID, err := getOldStyleSystemUUID(); err == nil {
|
||||||
pathName := dbPrefix + db.FileName
|
if _, err := os.Stat(db.Pathname(dbPrefix)); err == nil {
|
||||||
if _, err := os.Stat(pathName); err == nil {
|
persistedPeerName, err := getPersistedPeerName(dbPrefix)
|
||||||
persistedPeerName, err := getPersistedPeerName(pathName)
|
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
+83
-58
@@ -11,8 +11,6 @@ import (
|
|||||||
"github.com/j-keck/arping"
|
"github.com/j-keck/arping"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
"github.com/vishvananda/netns"
|
"github.com/vishvananda/netns"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common/odp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// create and attach a veth to the Weave bridge
|
// 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...)
|
return nil, fmt.Errorf(format, a...)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch bridgeType := DetectBridgeType(bridgeName, DatapathName); bridgeType {
|
bridgeType, err := ExistingBridgeType(bridgeName, DatapathName)
|
||||||
case Bridge, BridgedFastdp:
|
if err != nil {
|
||||||
if err := netlink.LinkSetMasterByIndex(veth, bridge.Attrs().Index); err != nil {
|
return cleanup("detect bridge type: %s", err)
|
||||||
return cleanup(`unable to set master of %s: %s`, name, 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 {
|
if init != nil {
|
||||||
@@ -111,8 +104,6 @@ func interfaceExistsInNamespace(netNSPath string, ifName string) bool {
|
|||||||
return err == nil
|
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 {
|
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool, hairpinMode bool) error {
|
||||||
ns, err := netns.GetFromPath(netNSPath)
|
ns, err := netns.GetFromPath(netNSPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -120,11 +111,6 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
|
|||||||
}
|
}
|
||||||
defer ns.Close()
|
defer ns.Close()
|
||||||
|
|
||||||
ipt, err := iptables.New()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !interfaceExistsInNamespace(netNSPath, ifName) {
|
if !interfaceExistsInNamespace(netNSPath, ifName) {
|
||||||
maxIDLen := IFNAMSIZ - 1 - len(vethPrefix+"pl")
|
maxIDLen := IFNAMSIZ - 1 - len(vethPrefix+"pl")
|
||||||
if len(id) > maxIDLen {
|
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 {
|
args := []string{ifName, fmt.Sprintf("%t", withMulticastRoute)}
|
||||||
newAddresses, err := AddAddresses(veth, cidrs)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if !exists {
|
||||||
// Add multicast ACCEPT rules for new subnets
|
if err := ipt.Insert("filter", "INPUT", 1, acceptRule...); err != nil {
|
||||||
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
|
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
|
return err
|
||||||
}
|
}
|
||||||
for _, ipnet := range newAddresses {
|
}
|
||||||
// If we don't wait for a bit here, we see the arp fail to reach the bridge.
|
return nil
|
||||||
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
|
// SetupIface is the implementation of the 'setup-iface' call above,
|
||||||
destinations. Without that, the kernel sets the DF flag on
|
// running in another process in the container's netns
|
||||||
multicast packets. Since RFC1122 prohibits sending of ICMP
|
func SetupIface(ifaceName, newIfName string) error {
|
||||||
errors for packets with multicast destinations, that causes
|
ipt, err := iptables.New()
|
||||||
packets larger than the PMTU to be dropped silently. */
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
_, multicast, _ := net.ParseCIDR("224.0.0.0/4")
|
link, err := netlink.LinkByName(ifaceName)
|
||||||
if err := AddRoute(veth, netlink.SCOPE_LINK, multicast, nil); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
if err := netlink.LinkSetName(link, newIfName); err != nil {
|
||||||
return nil
|
return err
|
||||||
}); err != nil {
|
}
|
||||||
|
// 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
|
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 {
|
func (npc *controller) withNS(name string, f func(ns *ns) error) error {
|
||||||
ns, found := npc.nss[name]
|
ns, found := npc.nss[name]
|
||||||
if !found {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -85,21 +85,10 @@ func (npc *controller) withNS(name string, f func(ns *ns) error) error {
|
|||||||
return nil
|
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 {
|
func (npc *controller) AddPod(obj *coreapi.Pod) error {
|
||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
defer npc.Unlock()
|
||||||
|
|
||||||
if !npc.checkLocalPod(obj, "AddPod") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
common.Log.Debugf("EVENT AddPod %s", js(obj))
|
common.Log.Debugf("EVENT AddPod %s", js(obj))
|
||||||
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
|
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.addPod(obj), "add pod")
|
return errors.Wrap(ns.addPod(obj), "add pod")
|
||||||
@@ -110,10 +99,6 @@ func (npc *controller) UpdatePod(oldObj, newObj *coreapi.Pod) error {
|
|||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
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))
|
common.Log.Debugf("EVENT UpdatePod %s %s", js(oldObj), js(newObj))
|
||||||
return npc.withNS(oldObj.ObjectMeta.Namespace, func(ns *ns) error {
|
return npc.withNS(oldObj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.updatePod(oldObj, newObj), "update pod")
|
return errors.Wrap(ns.updatePod(oldObj, newObj), "update pod")
|
||||||
@@ -124,9 +109,6 @@ func (npc *controller) DeletePod(obj *coreapi.Pod) error {
|
|||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
defer npc.Unlock()
|
||||||
|
|
||||||
if !npc.checkLocalPod(obj, "DeletePod") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
common.Log.Debugf("EVENT DeletePod %s", js(obj))
|
common.Log.Debugf("EVENT DeletePod %s", js(obj))
|
||||||
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
|
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.deletePod(obj), "delete pod")
|
return errors.Wrap(ns.deletePod(obj), "delete pod")
|
||||||
|
|||||||
+25
-5
@@ -19,6 +19,7 @@ type ns struct {
|
|||||||
ips ipset.Interface // interface to ipset
|
ips ipset.Interface // interface to ipset
|
||||||
|
|
||||||
name string // k8s Namespace name
|
name string // k8s Namespace name
|
||||||
|
nodeName string // my node name
|
||||||
namespace *coreapi.Namespace // k8s Namespace object
|
namespace *coreapi.Namespace // k8s Namespace object
|
||||||
pods map[types.UID]*coreapi.Pod // k8s Pod objects by UID
|
pods map[types.UID]*coreapi.Pod // k8s Pod objects by UID
|
||||||
policies map[types.UID]*extnapi.NetworkPolicy // k8s NetworkPolicy objects by UID
|
policies map[types.UID]*extnapi.NetworkPolicy // k8s NetworkPolicy objects by UID
|
||||||
@@ -31,7 +32,7 @@ type ns struct {
|
|||||||
rules *ruleSet
|
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)
|
allPods, err := newSelectorSpec(&unversioned.LabelSelector{}, name, ipset.HashIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -41,6 +42,7 @@ func newNS(name string, ipt *iptables.IPTables, ips ipset.Interface, nsSelectors
|
|||||||
ipt: ipt,
|
ipt: ipt,
|
||||||
ips: ips,
|
ips: ips,
|
||||||
name: name,
|
name: name,
|
||||||
|
nodeName: nodeName,
|
||||||
pods: make(map[types.UID]*coreapi.Pod),
|
pods: make(map[types.UID]*coreapi.Pod),
|
||||||
policies: make(map[types.UID]*extnapi.NetworkPolicy),
|
policies: make(map[types.UID]*extnapi.NetworkPolicy),
|
||||||
uid: uuid.NewUUID(),
|
uid: uuid.NewUUID(),
|
||||||
@@ -81,6 +83,13 @@ func (ns *ns) onNewPodSelector(selector *selector) error {
|
|||||||
return nil
|
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 {
|
func (ns *ns) addPod(obj *coreapi.Pod) error {
|
||||||
ns.pods[obj.ObjectMeta.UID] = obj
|
ns.pods[obj.ObjectMeta.UID] = obj
|
||||||
|
|
||||||
@@ -88,7 +97,9 @@ func (ns *ns) addPod(obj *coreapi.Pod) error {
|
|||||||
return nil
|
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)
|
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) {
|
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)
|
return ns.podSelectors.delFromMatching(oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasIP(oldObj) && hasIP(newObj) {
|
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)
|
return ns.podSelectors.addToMatching(newObj.ObjectMeta.Labels, newObj.Status.PodIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +157,9 @@ func (ns *ns) deletePod(obj *coreapi.Pod) error {
|
|||||||
return nil
|
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)
|
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 {
|
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)...)
|
return ns.ipt.Append(TableFilter, DefaultChain, bypassRule(ns.allPods.ipsetName)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ns) deleteBypassRule(nsIpsetName ipset.Name) error {
|
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)...)
|
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)
|
newDefaultDeny := isDefaultDeny(newObj)
|
||||||
|
|
||||||
if oldDefaultDeny != newDefaultDeny {
|
if oldDefaultDeny != newDefaultDeny {
|
||||||
|
common.Log.Infof("namespace DefaultDeny changed from %t to %t", oldDefaultDeny, newDefaultDeny)
|
||||||
if oldDefaultDeny {
|
if oldDefaultDeny {
|
||||||
return ns.ensureBypassRule(ns.allPods.ipsetName)
|
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
|
var ipnet *net.IPNet
|
||||||
|
|
||||||
if conf.Subnet == "" {
|
if conf.Subnet == "" {
|
||||||
ipnet, err = i.weave.AllocateIP(containerID)
|
ipnet, err = i.weave.AllocateIP(containerID, false)
|
||||||
} else {
|
} else {
|
||||||
var subnet *net.IPNet
|
var subnet *net.IPNet
|
||||||
subnet, err = types.ParseCIDR(conf.Subnet)
|
subnet, err = types.ParseCIDR(conf.Subnet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("subnet given in config, but not parseable: %s", err)
|
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 {
|
if err != nil {
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ func NewIpam(weave *api.Client) *Ipam {
|
|||||||
return &Ipam{weave: weave}
|
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) {
|
func (i *Ipam) GetDefaultAddressSpaces() (string, string, error) {
|
||||||
i.logReq("GetDefaultAddressSpaces")
|
i.logReq("GetDefaultAddressSpaces")
|
||||||
return "weavelocal", "weaveglobal", nil
|
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)
|
i.logReq("RequestAddress", poolID, address, options)
|
||||||
defer func() { i.logRes("RequestAddress", err, ip) }()
|
defer func() { i.logRes("RequestAddress", err, ip) }()
|
||||||
if poolID == "weavepool" { // old-style
|
if poolID == "weavepool" { // old-style
|
||||||
ip, err = i.weave.AllocateIP(api.NoContainerID)
|
ip, err = i.weave.AllocateIP(api.NoContainerID, false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
subnet, iprange, err := splitPoolID(poolID)
|
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
|
if address != nil { // try to claim specific address requested
|
||||||
ip = &net.IPNet{IP: address, Mask: subnet.Mask}
|
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
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We are lying slightly to IPAM here: the range is not a subnet
|
// 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
|
return
|
||||||
}
|
}
|
||||||
ip.Mask = subnet.Mask // fix up the subnet we lied about
|
ip.Mask = subnet.Mask // fix up the subnet we lied about
|
||||||
|
|||||||
+60
-12
@@ -28,25 +28,40 @@ type network struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type driver struct {
|
type driver struct {
|
||||||
name string
|
|
||||||
scope string
|
|
||||||
docker *docker.Client
|
|
||||||
sync.RWMutex
|
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{
|
driver := &driver{
|
||||||
name: name,
|
name: name,
|
||||||
scope: scope,
|
scope: scope,
|
||||||
docker: client,
|
docker: client,
|
||||||
networks: make(map[string]network),
|
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)
|
// Do not start watcher in the case of plugin v2, which prevents us from
|
||||||
if err != nil {
|
// configuring arp settings of containers.
|
||||||
return nil, err
|
if client != nil {
|
||||||
|
_, err := NewWatcher(client, weave, driver)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return driver, nil
|
return driver, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,12 +76,27 @@ func (driver *driver) GetCapabilities() (*api.GetCapabilityResponse, error) {
|
|||||||
return caps, nil
|
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 {
|
func (driver *driver) CreateNetwork(create *api.CreateNetworkRequest) error {
|
||||||
driver.logReq("CreateNetwork", create, create.NetworkID)
|
driver.logReq("CreateNetwork", create, create.NetworkID)
|
||||||
_, err := driver.setupNetworkInfo(create.NetworkID, true, stringOptions(create))
|
_, err := driver.setupNetworkInfo(create.NetworkID, true, stringOptions(create))
|
||||||
return err
|
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
|
// Deal with excessively-generic way the options get decoded from JSON
|
||||||
func stringOptions(create *api.CreateNetworkRequest) map[string]string {
|
func stringOptions(create *api.CreateNetworkRequest) map[string]string {
|
||||||
if create.Options != nil {
|
if create.Options != nil {
|
||||||
@@ -85,6 +115,7 @@ func stringOptions(create *api.CreateNetworkRequest) map[string]string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In Swarm mode, DeleteNetwork is called after a service has been removed.
|
||||||
func (driver *driver) DeleteNetwork(delreq *api.DeleteNetworkRequest) error {
|
func (driver *driver) DeleteNetwork(delreq *api.DeleteNetworkRequest) error {
|
||||||
driver.logReq("DeleteNetwork", delreq, delreq.NetworkID)
|
driver.logReq("DeleteNetwork", delreq, delreq.NetworkID)
|
||||||
driver.Lock()
|
driver.Lock()
|
||||||
@@ -163,12 +194,29 @@ func (driver *driver) JoinEndpoint(j *api.JoinRequest) (*api.JoinResponse, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (driver *driver) findNetworkInfo(id string) (network, 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()
|
driver.Lock()
|
||||||
network, found := driver.networks[id]
|
network, found := driver.networks[id]
|
||||||
driver.Unlock()
|
driver.Unlock()
|
||||||
if found {
|
if found {
|
||||||
return network, nil
|
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)
|
info, err := driver.docker.NetworkInfo(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return network, err
|
return network, err
|
||||||
|
|||||||
+12
-4
@@ -41,11 +41,19 @@ func (w *watcher) ContainerStarted(id string) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if network.isOurs {
|
if network.isOurs {
|
||||||
fqdn := fmt.Sprintf("%s.%s", info.Config.Hostname, info.Config.Domainname)
|
if w.driver.dns {
|
||||||
if err := w.weave.RegisterWithDNS(id, fqdn, net.IPAddress); err != nil {
|
fqdn := fmt.Sprintf("%s.%s", info.Config.Hostname, info.Config.Domainname)
|
||||||
w.driver.warn("ContainerStarted", "unable to register %s with weaveDNS: %s", id, err)
|
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)
|
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
|
DeleteEndpoint(delete *api.DeleteEndpointRequest) error
|
||||||
EndpointInfo(req *api.EndpointInfoRequest) (*api.EndpointInfoResponse, error)
|
EndpointInfo(req *api.EndpointInfoRequest) (*api.EndpointInfoResponse, error)
|
||||||
JoinEndpoint(j *api.JoinRequest) (response *api.JoinResponse, error 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
|
LeaveEndpoint(leave *api.LeaveRequest) error
|
||||||
DiscoverNew(discover *api.DiscoveryNotification) error
|
DiscoverNew(discover *api.DiscoveryNotification) error
|
||||||
DiscoverDelete(delete *api.DiscoveryNotification) error
|
DiscoverDelete(delete *api.DiscoveryNotification) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IpamCapability interface {
|
||||||
|
GetCapabilities() (RequiresMACAddress bool, RequiresRequestReplay bool, err error)
|
||||||
|
}
|
||||||
|
|
||||||
type listener struct {
|
type listener struct {
|
||||||
d Driver
|
d Driver
|
||||||
i ipamapi.Ipam
|
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, "EndpointOperInfo", listener.infoEndpoint)
|
||||||
handleMethod(networkReceiver, "Join", listener.joinEndpoint)
|
handleMethod(networkReceiver, "Join", listener.joinEndpoint)
|
||||||
handleMethod(networkReceiver, "Leave", listener.leaveEndpoint)
|
handleMethod(networkReceiver, "Leave", listener.leaveEndpoint)
|
||||||
|
handleMethod(networkReceiver, "AllocateNetwork", listener.networkAllocate)
|
||||||
|
handleMethod(networkReceiver, "FreeNetwork", listener.networkFree)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ipamDriver != nil {
|
if ipamDriver != nil {
|
||||||
|
handleMethod(ipamReceiver, "GetCapabilities", listener.getIpamCapabilities)
|
||||||
handleMethod(ipamReceiver, "GetDefaultAddressSpaces", listener.getDefaultAddressSpaces)
|
handleMethod(ipamReceiver, "GetDefaultAddressSpaces", listener.getDefaultAddressSpaces)
|
||||||
handleMethod(ipamReceiver, "RequestPool", listener.requestPool)
|
handleMethod(ipamReceiver, "RequestPool", listener.requestPool)
|
||||||
handleMethod(ipamReceiver, "ReleasePool", listener.releasePool)
|
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) {
|
func (listener *listener) deleteEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
var delete api.DeleteEndpointRequest
|
var delete api.DeleteEndpointRequest
|
||||||
if err := json.NewDecoder(r.Body).Decode(&delete); err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
emptyOrErrorResponse(w, listener.d.DeleteEndpoint(&delete))
|
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) {
|
func (listener *listener) infoEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
var req api.EndpointInfoRequest
|
var req api.EndpointInfoRequest
|
||||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
info, err := listener.d.EndpointInfo(&req)
|
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) {
|
func (listener *listener) joinEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
var join api.JoinRequest
|
var join api.JoinRequest
|
||||||
if err := json.NewDecoder(r.Body).Decode(&join); err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
res, err := listener.d.JoinEndpoint(&join)
|
res, err := listener.d.JoinEndpoint(&join)
|
||||||
objectOrErrorResponse(w, res, err)
|
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) {
|
func (listener *listener) leaveEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
var l api.LeaveRequest
|
var l api.LeaveRequest
|
||||||
if err := json.NewDecoder(r.Body).Decode(&l); err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
emptyOrErrorResponse(w, listener.d.LeaveEndpoint(&l))
|
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) {
|
func (listener *listener) discoverNew(w http.ResponseWriter, r *http.Request) {
|
||||||
var disco api.DiscoveryNotification
|
var disco api.DiscoveryNotification
|
||||||
if err := json.NewDecoder(r.Body).Decode(&disco); err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
emptyOrErrorResponse(w, listener.d.DiscoverNew(&disco))
|
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) {
|
func (listener *listener) discoverDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
var disco api.DiscoveryNotification
|
var disco api.DiscoveryNotification
|
||||||
if err := json.NewDecoder(r.Body).Decode(&disco); err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
emptyOrErrorResponse(w, listener.d.DiscoverDelete(&disco))
|
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) {
|
func (listener *listener) getDefaultAddressSpaces(w http.ResponseWriter, r *http.Request) {
|
||||||
local, global, err := listener.i.GetDefaultAddressSpaces()
|
local, global, err := listener.i.GetDefaultAddressSpaces()
|
||||||
response := &iapi.GetAddressSpacesResponse{
|
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
|
||||||
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"
|
WEAVE_NPC_OPTS="--expect-npc"
|
||||||
if [ "${EXPECT_NPC}" = "0" ]; then
|
if [ "${EXPECT_NPC}" = "0" ]; then
|
||||||
WEAVE_NPC_OPTS=""
|
WEAVE_NPC_OPTS=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export HOST_ROOT=/host
|
|
||||||
/home/weave/weave --local create-bridge --force $WEAVE_NPC_OPTS
|
|
||||||
|
|
||||||
# Kubernetes sets HOSTNAME to the host's hostname
|
# Kubernetes sets HOSTNAME to the host's hostname
|
||||||
# when running a pod in host namespace.
|
# when running a pod in host namespace.
|
||||||
NICKNAME_ARG=""
|
NICKNAME_ARG=""
|
||||||
@@ -69,17 +66,11 @@ if [ -n "$HOSTNAME" ] ; then
|
|||||||
NICKNAME_ARG="--nickname=$HOSTNAME"
|
NICKNAME_ARG="--nickname=$HOSTNAME"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
BRIDGE_OPTIONS="--datapath=datapath"
|
router_bridge_opts() {
|
||||||
if [ "$(/home/weave/weave --local bridge-type)" = "bridge" ] ; then
|
echo --datapath=datapath
|
||||||
# TODO: Call into weave script to do this
|
[ -z "$WEAVE_MTU" ] || echo --mtu "$WEAVE_MTU"
|
||||||
if ! ip link show vethwe-pcap >/dev/null 2>&1 ; then
|
[ -z "$WEAVE_NO_FASTDP" ] || echo --no-fastdp
|
||||||
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
|
|
||||||
|
|
||||||
if [ -z "$KUBE_PEERS" ]; then
|
if [ -z "$KUBE_PEERS" ]; then
|
||||||
if ! KUBE_PEERS=$(/home/weave/kube-peers) || [ -z "$KUBE_PEERS" ]; then
|
if ! KUBE_PEERS=$(/home/weave/kube-peers) || [ -z "$KUBE_PEERS" ]; then
|
||||||
@@ -114,6 +105,7 @@ post_start_actions() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
mkdir -p $HOST_ROOT/etc/cni/net.d
|
mkdir -p $HOST_ROOT/etc/cni/net.d
|
||||||
|
export HOST_ROOT
|
||||||
/home/weave/weave --local setup-cni
|
/home/weave/weave --local setup-cni
|
||||||
|
|
||||||
# Expose the weave network so host processes can communicate with pods
|
# Expose the weave network so host processes can communicate with pods
|
||||||
@@ -122,10 +114,13 @@ post_start_actions() {
|
|||||||
|
|
||||||
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 \
|
--http-addr=$HTTP_ADDR --status-addr=$STATUS_ADDR --docker-api='' --no-dns \
|
||||||
|
--db-prefix="/weavedb/weave-net" \
|
||||||
--ipalloc-range=$IPALLOC_RANGE $NICKNAME_ARG \
|
--ipalloc-range=$IPALLOC_RANGE $NICKNAME_ARG \
|
||||||
--ipalloc-init $IPALLOC_INIT \
|
--ipalloc-init $IPALLOC_INIT \
|
||||||
--conn-limit=$CONN_LIMIT \
|
--conn-limit=$CONN_LIMIT \
|
||||||
|
$WEAVE_NPC_OPTS \
|
||||||
"$@" \
|
"$@" \
|
||||||
$KUBE_PEERS
|
$KUBE_PEERS
|
||||||
@@ -1,126 +1,134 @@
|
|||||||
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
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: List
|
||||||
metadata:
|
items:
|
||||||
name: weave-net
|
- apiVersion: v1
|
||||||
namespace: kube-system
|
kind: ServiceAccount
|
||||||
---
|
|
||||||
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:
|
|
||||||
metadata:
|
metadata:
|
||||||
|
name: weave-net
|
||||||
|
labels:
|
||||||
|
name: weave-net
|
||||||
|
- 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:
|
labels:
|
||||||
name: weave-net
|
name: weave-net
|
||||||
spec:
|
spec:
|
||||||
hostNetwork: true
|
template:
|
||||||
hostPID: true
|
metadata:
|
||||||
containers:
|
labels:
|
||||||
- name: weave
|
name: weave-net
|
||||||
image: weaveworks/weave-kube:latest
|
spec:
|
||||||
imagePullPolicy: Always
|
containers:
|
||||||
command:
|
- name: weave
|
||||||
- /home/weave/launch.sh
|
command:
|
||||||
livenessProbe:
|
- /home/weave/launch.sh
|
||||||
initialDelaySeconds: 30
|
env:
|
||||||
httpGet:
|
- name: HOSTNAME
|
||||||
host: 127.0.0.1
|
valueFrom:
|
||||||
path: /status
|
fieldRef:
|
||||||
port: 6784
|
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:
|
securityContext:
|
||||||
privileged: true
|
seLinuxOptions: {}
|
||||||
volumeMounts:
|
serviceAccountName: weave-net
|
||||||
|
tolerations:
|
||||||
|
- effect: NoSchedule
|
||||||
|
operator: Exists
|
||||||
|
volumes:
|
||||||
- name: weavedb
|
- name: weavedb
|
||||||
mountPath: /weavedb
|
hostPath:
|
||||||
|
path: /var/lib/weave
|
||||||
- name: cni-bin
|
- name: cni-bin
|
||||||
mountPath: /host/opt
|
hostPath:
|
||||||
|
path: /opt
|
||||||
- name: cni-bin2
|
- name: cni-bin2
|
||||||
mountPath: /host/home
|
hostPath:
|
||||||
|
path: /home
|
||||||
- name: cni-conf
|
- name: cni-conf
|
||||||
mountPath: /host/etc
|
hostPath:
|
||||||
|
path: /etc
|
||||||
- name: dbus
|
- name: dbus
|
||||||
mountPath: /host/var/lib/dbus
|
hostPath:
|
||||||
|
path: /var/lib/dbus
|
||||||
- name: lib-modules
|
- name: lib-modules
|
||||||
mountPath: /lib/modules
|
hostPath:
|
||||||
resources:
|
path: /lib/modules
|
||||||
requests:
|
updateStrategy:
|
||||||
cpu: 10m
|
type: RollingUpdate
|
||||||
- name: weave-npc
|
|
||||||
image: weaveworks/weave-npc:latest
|
|
||||||
imagePullPolicy: Always
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 10m
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
env:
|
|
||||||
- name: HOSTNAME
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
apiVersion: v1
|
|
||||||
fieldPath: spec.nodeName
|
|
||||||
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
|
|
||||||
@@ -1,86 +1,93 @@
|
|||||||
apiVersion: extensions/v1beta1
|
apiVersion: v1
|
||||||
kind: DaemonSet
|
kind: List
|
||||||
metadata:
|
items:
|
||||||
name: weave-net
|
- apiVersion: v1
|
||||||
namespace: kube-system
|
kind: ServiceAccount
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
metadata:
|
metadata:
|
||||||
|
name: weave-net
|
||||||
|
labels:
|
||||||
|
name: weave-net
|
||||||
|
- apiVersion: extensions/v1beta1
|
||||||
|
kind: DaemonSet
|
||||||
|
metadata:
|
||||||
|
name: weave-net
|
||||||
labels:
|
labels:
|
||||||
name: weave-net
|
name: weave-net
|
||||||
annotations:
|
|
||||||
scheduler.alpha.kubernetes.io/tolerations: |
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"key": "dedicated",
|
|
||||||
"operator": "Equal",
|
|
||||||
"value": "master",
|
|
||||||
"effect": "NoSchedule"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
spec:
|
spec:
|
||||||
hostNetwork: true
|
template:
|
||||||
hostPID: true
|
metadata:
|
||||||
containers:
|
annotations:
|
||||||
- name: weave
|
scheduler.alpha.kubernetes.io/tolerations: >-
|
||||||
image: weaveworks/weave-kube:latest
|
[{"key":"dedicated","operator":"Equal","value":"master","effect":"NoSchedule"}]
|
||||||
imagePullPolicy: Always
|
labels:
|
||||||
command:
|
name: weave-net
|
||||||
- /home/weave/launch.sh
|
spec:
|
||||||
livenessProbe:
|
containers:
|
||||||
initialDelaySeconds: 30
|
- name: weave
|
||||||
httpGet:
|
command:
|
||||||
host: 127.0.0.1
|
- /home/weave/launch.sh
|
||||||
path: /status
|
env:
|
||||||
port: 6784
|
- 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:
|
securityContext:
|
||||||
privileged: true
|
seLinuxOptions: {}
|
||||||
volumeMounts:
|
serviceAccountName: weave-net
|
||||||
|
volumes:
|
||||||
- name: weavedb
|
- name: weavedb
|
||||||
mountPath: /weavedb
|
hostPath:
|
||||||
|
path: /var/lib/weave
|
||||||
- name: cni-bin
|
- name: cni-bin
|
||||||
mountPath: /host/opt
|
hostPath:
|
||||||
|
path: /opt
|
||||||
- name: cni-bin2
|
- name: cni-bin2
|
||||||
mountPath: /host/home
|
hostPath:
|
||||||
|
path: /home
|
||||||
- name: cni-conf
|
- name: cni-conf
|
||||||
mountPath: /host/etc
|
hostPath:
|
||||||
|
path: /etc
|
||||||
- name: dbus
|
- name: dbus
|
||||||
mountPath: /host/var/lib/dbus
|
hostPath:
|
||||||
|
path: /var/lib/dbus
|
||||||
- name: lib-modules
|
- name: lib-modules
|
||||||
mountPath: /lib/modules
|
hostPath:
|
||||||
resources:
|
path: /lib/modules
|
||||||
requests:
|
|
||||||
cpu: 10m
|
|
||||||
- name: weave-npc
|
|
||||||
image: weaveworks/weave-npc:latest
|
|
||||||
imagePullPolicy: Always
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 10m
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
env:
|
|
||||||
- name: HOSTNAME
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
apiVersion: v1
|
|
||||||
fieldPath: spec.nodeName
|
|
||||||
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
|
|
||||||
@@ -117,7 +117,6 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ipt.Append(npc.TableFilter, npc.MainChain,
|
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 {
|
"-m", "set", "!", "--match-set", npc.LocalIpset, "dst", "-j", "ACCEPT"); err != nil {
|
||||||
return err
|
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"]
|
ENTRYPOINT ["/home/weave/sigproxy", "/home/weave/weave"]
|
||||||
|
|
||||||
RUN apk add --update \
|
ADD ./sigproxy ./symlink /home/weave/
|
||||||
curl \
|
ADD ./docker /usr/bin/
|
||||||
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 ./weavewait /w/w
|
ADD ./weavewait /w/w
|
||||||
ADD ./weavewait_noop /w-noop/w
|
ADD ./weavewait_noop /w-noop/w
|
||||||
ADD ./weavewait_nomcast /w-nomcast/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
|
FROM ALPINE_BASEIMAGE
|
||||||
WORKDIR /home/weave
|
|
||||||
ADD ./weaver /home/weave/
|
# 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/
|
ADD weavedata.db /weavedb/
|
||||||
COPY ca-certificates.crt /etc/ssl/certs/
|
COPY ca-certificates.crt /etc/ssl/certs/
|
||||||
ENTRYPOINT ["/home/weave/weaver"]
|
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 != "" {
|
||||||
|
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 != "" {
|
||||||
|
// 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/mesh"
|
||||||
|
|
||||||
"github.com/weaveworks/go-checkpoint"
|
"github.com/weaveworks/go-checkpoint"
|
||||||
|
"github.com/weaveworks/weave/common"
|
||||||
"github.com/weaveworks/weave/ipam"
|
"github.com/weaveworks/weave/ipam"
|
||||||
"github.com/weaveworks/weave/nameserver"
|
"github.com/weaveworks/weave/nameserver"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/weaveworks/weave/net/address"
|
||||||
|
"github.com/weaveworks/weave/plugin"
|
||||||
|
"github.com/weaveworks/weave/proxy"
|
||||||
weave "github.com/weaveworks/weave/router"
|
weave "github.com/weaveworks/weave/router"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -178,7 +181,7 @@ var statusTemplate = defTemplate("status", `\
|
|||||||
{{if allIPAMOwnersUnreachable .IPAM}}\
|
{{if allIPAMOwnersUnreachable .IPAM}}\
|
||||||
Status: all IP ranges owned by unreachable peers - use 'rmpeer' if they are dead
|
Status: all IP ranges owned by unreachable peers - use 'rmpeer' if they are dead
|
||||||
{{else if len .IPAM.PendingAllocates}}\
|
{{else if len .IPAM.PendingAllocates}}\
|
||||||
Status: waiting for IP range grant from peers
|
Status: waiting for IP(s) to become available
|
||||||
{{else}}\
|
{{else}}\
|
||||||
Status: ready
|
Status: ready
|
||||||
{{end}}\
|
{{end}}\
|
||||||
@@ -202,6 +205,20 @@ var statusTemplate = defTemplate("status", `\
|
|||||||
TTL: {{.DNS.TTL}}
|
TTL: {{.DNS.TTL}}
|
||||||
Entries: {{countDNSEntries .DNS.Entries}}
|
Entries: {{countDNSEntries .DNS.Entries}}
|
||||||
{{end}}\
|
{{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", `\
|
var targetsTemplate = defTemplate("targetsTemplate", `\
|
||||||
@@ -273,22 +290,29 @@ func (v *VersionCheck) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WeaveStatus struct {
|
type WeaveStatus struct {
|
||||||
|
Ready bool
|
||||||
Version string
|
Version string
|
||||||
VersionCheck *VersionCheck `json:"VersionCheck,omitempty"`
|
VersionCheck *VersionCheck `json:"VersionCheck,omitempty"`
|
||||||
Router *weave.NetworkRouterStatus `json:"Router,omitempty"`
|
Router *weave.NetworkRouterStatus `json:"Router,omitempty"`
|
||||||
IPAM *ipam.Status `json:"IPAM,omitempty"`
|
IPAM *ipam.Status `json:"IPAM,omitempty"`
|
||||||
DNS *nameserver.Status `json:"DNS,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
|
// 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 {
|
status := func() WeaveStatus {
|
||||||
return WeaveStatus{
|
return WeaveStatus{
|
||||||
|
waitReady.IsDone(),
|
||||||
version,
|
version,
|
||||||
versionCheck(),
|
versionCheck(),
|
||||||
weave.NewNetworkRouterStatus(router),
|
weave.NewNetworkRouterStatus(router),
|
||||||
ipam.NewStatus(allocator, defaultSubnet),
|
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(
|
muxRouter.Methods("GET").Path("/report").Headers("Accept", "application/json").HandlerFunc(
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
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) {
|
defHandler := func(path string, template *template.Template) {
|
||||||
muxRouter.Methods("GET").Path(path).HandlerFunc(
|
muxRouter.Methods("GET").Path(path).HandlerFunc(
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
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)
|
http.Error(w, "error during template execution", http.StatusInternalServerError)
|
||||||
Log.Error(err)
|
Log.Error(err)
|
||||||
}
|
}
|
||||||
|
|||||||
+218
-79
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/pkg/profile"
|
"github.com/pkg/profile"
|
||||||
"github.com/weaveworks/common/mflag"
|
"github.com/weaveworks/common/mflag"
|
||||||
|
"github.com/weaveworks/common/mflagext"
|
||||||
"github.com/weaveworks/common/signals"
|
"github.com/weaveworks/common/signals"
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
|
|
||||||
@@ -25,6 +26,8 @@ import (
|
|||||||
"github.com/weaveworks/weave/nameserver"
|
"github.com/weaveworks/weave/nameserver"
|
||||||
weavenet "github.com/weaveworks/weave/net"
|
weavenet "github.com/weaveworks/weave/net"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/weaveworks/weave/net/address"
|
||||||
|
"github.com/weaveworks/weave/plugin"
|
||||||
|
weaveproxy "github.com/weaveworks/weave/proxy"
|
||||||
weave "github.com/weaveworks/weave/router"
|
weave "github.com/weaveworks/weave/router"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -53,7 +56,7 @@ type dnsConfig struct {
|
|||||||
func (c *ipamConfig) Enabled() bool {
|
func (c *ipamConfig) Enabled() bool {
|
||||||
var (
|
var (
|
||||||
hasPeerCount = c.PeerCount > 0
|
hasPeerCount = c.PeerCount > 0
|
||||||
hasMode = len(c.Mode) > 0
|
hasMode = c.HasMode()
|
||||||
hasRange = c.IPRangeCIDR != ""
|
hasRange = c.IPRangeCIDR != ""
|
||||||
hasSubnet = c.IPSubnetCIDR != ""
|
hasSubnet = c.IPSubnetCIDR != ""
|
||||||
)
|
)
|
||||||
@@ -63,9 +66,7 @@ func (c *ipamConfig) Enabled() bool {
|
|||||||
case !hasRange && hasSubnet:
|
case !hasRange && hasSubnet:
|
||||||
Log.Fatal("--ipalloc-default-subnet specified without --ipalloc-range.")
|
Log.Fatal("--ipalloc-default-subnet specified without --ipalloc-range.")
|
||||||
case !hasRange:
|
case !hasRange:
|
||||||
Log.Fatal("--ipalloc-init or --init-peer-count specified without --ipalloc-range.")
|
Log.Fatal("--ipalloc-init specified without --ipalloc-range.")
|
||||||
case hasMode && hasPeerCount:
|
|
||||||
Log.Fatal("At most one of --ipalloc-init or --init-peer-count may be specified.")
|
|
||||||
}
|
}
|
||||||
if hasMode {
|
if hasMode {
|
||||||
if err := c.parseMode(); err != nil {
|
if err := c.parseMode(); err != nil {
|
||||||
@@ -75,6 +76,10 @@ func (c *ipamConfig) Enabled() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c ipamConfig) HasMode() bool {
|
||||||
|
return len(c.Mode) > 0
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ipamConfig) parseMode() error {
|
func (c *ipamConfig) parseMode() error {
|
||||||
modeAndParam := strings.SplitN(c.Mode, "=", 2)
|
modeAndParam := strings.SplitN(c.Mode, "=", 2)
|
||||||
|
|
||||||
@@ -108,6 +113,13 @@ func (c *ipamConfig) parseMode() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getenvOrDefault(key, defaultVal string) string {
|
||||||
|
if v := os.Getenv(key); v != "" {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
procs := runtime.NumCPU()
|
procs := runtime.NumCPU()
|
||||||
// packet sniffing can block an OS thread, so we need one thread
|
// packet sniffing can block an OS thread, so we need one thread
|
||||||
@@ -120,15 +132,15 @@ func main() {
|
|||||||
var (
|
var (
|
||||||
justVersion bool
|
justVersion bool
|
||||||
config mesh.Config
|
config mesh.Config
|
||||||
|
bridgeConfig weavenet.BridgeConfig
|
||||||
networkConfig weave.NetworkConfig
|
networkConfig weave.NetworkConfig
|
||||||
protocolMinVersion int
|
protocolMinVersion int
|
||||||
resume bool
|
resume bool
|
||||||
ifaceName string
|
|
||||||
routerName string
|
routerName string
|
||||||
nickName string
|
nickName string
|
||||||
password string
|
password string
|
||||||
pktdebug bool
|
pktdebug bool
|
||||||
logLevel string
|
logLevel = "info"
|
||||||
prof string
|
prof string
|
||||||
bufSzMB int
|
bufSzMB int
|
||||||
noDiscovery bool
|
noDiscovery bool
|
||||||
@@ -139,40 +151,41 @@ func main() {
|
|||||||
peers []string
|
peers []string
|
||||||
noDNS bool
|
noDNS bool
|
||||||
dnsConfig dnsConfig
|
dnsConfig dnsConfig
|
||||||
datapathName string
|
|
||||||
trustedSubnetStr string
|
trustedSubnetStr string
|
||||||
dbPrefix string
|
dbPrefix string
|
||||||
isAWSVPC bool
|
hostRoot string
|
||||||
|
procPath string
|
||||||
defaultDockerHost = "unix:///var/run/docker.sock"
|
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 != "" {
|
mflag.BoolVar(&justVersion, []string{"-version"}, false, "print version and exit")
|
||||||
defaultDockerHost = val
|
|
||||||
}
|
|
||||||
|
|
||||||
mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit")
|
|
||||||
mflag.StringVar(&config.Host, []string{"-host"}, "", "router host")
|
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.IntVar(&protocolMinVersion, []string{"-min-protocol-version"}, mesh.ProtocolMinVersion, "minimum weave protocol version")
|
||||||
mflag.BoolVar(&resume, []string{"-resume"}, false, "resume connections to previous peers")
|
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(&bridgeConfig.WeaveBridgeName, []string{"-weave-bridge"}, "weave", "name of weave bridge")
|
||||||
mflag.StringVar(&routerName, []string{"#name", "-name"}, "", "name of router (defaults to MAC of interface)")
|
mflag.StringVar(&bridgeConfig.DockerBridgeName, []string{"-docker-bridge"}, "", "name of Docker bridge")
|
||||||
mflag.StringVar(&nickName, []string{"#nickname", "-nickname"}, "", "nickname of peer (defaults to hostname)")
|
mflag.BoolVar(&bridgeConfig.NPC, []string{"-expect-npc"}, false, "set up iptables rules for npc")
|
||||||
mflag.StringVar(&password, []string{"#password", "-password"}, "", "network password")
|
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.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.BoolVar(&pktdebug, []string{"-pkt-debug"}, false, "enable per-packet debug logging")
|
||||||
mflag.StringVar(&prof, []string{"#profile", "-profile"}, "", "enable profiling and write profiles to given path")
|
mflag.StringVar(&prof, []string{"-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.IntVar(&config.ConnLimit, []string{"-conn-limit"}, 30, "connection limit (0 for unlimited)")
|
||||||
mflag.BoolVar(&noDiscovery, []string{"#nodiscovery", "#-nodiscovery", "-no-discovery"}, false, "disable peer discovery")
|
mflag.BoolVar(&noDiscovery, []string{"-no-discovery"}, false, "disable peer discovery")
|
||||||
mflag.IntVar(&bufSzMB, []string{"#bufsz", "-bufsz"}, 8, "capture buffer size in MB")
|
mflag.IntVar(&bufSzMB, []string{"-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.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(&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.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.IPRangeCIDR, []string{"-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.StringVar(&ipamConfig.IPSubnetCIDR, []string{"-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{"-docker-api"}, defaultDockerHost, "Docker API endpoint")
|
||||||
mflag.StringVar(&dockerAPI, []string{"#api", "#-api", "-docker-api"}, defaultDockerHost, "Docker API endpoint")
|
|
||||||
mflag.BoolVar(&noDNS, []string{"-no-dns"}, false, "disable DNS server")
|
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.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")
|
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.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.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(&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(&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.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
|
// crude way of detecting that we probably have been started in a
|
||||||
// container, with `weave launch` --> suppress misleading paths in
|
// container, with `weave launch` --> suppress misleading paths in
|
||||||
@@ -195,19 +226,19 @@ func main() {
|
|||||||
|
|
||||||
mflag.Parse()
|
mflag.Parse()
|
||||||
|
|
||||||
|
if justVersion {
|
||||||
|
fmt.Printf("weave %s\n", version)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
peers = mflag.Args()
|
peers = mflag.Args()
|
||||||
if resume && len(peers) > 0 {
|
if resume && len(peers) > 0 {
|
||||||
Log.Fatalf("You must not specify an initial peer list in conjunction with --resume")
|
Log.Fatalf("You must not specify an initial peer list in conjunction with --resume")
|
||||||
}
|
}
|
||||||
|
|
||||||
common.SetLogLevel(logLevel)
|
common.SetLogLevel(logLevel)
|
||||||
|
|
||||||
if justVersion {
|
|
||||||
fmt.Printf("weave router %s\n", version)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Println("Command line options:", options())
|
Log.Println("Command line options:", options())
|
||||||
|
Log.Infoln("weave ", version)
|
||||||
|
|
||||||
if prof != "" {
|
if prof != "" {
|
||||||
defer profile.Start(profile.CPUProfile, profile.ProfilePath(prof), profile.NoShutdownHook).Stop()
|
defer profile.Start(profile.CPUProfile, profile.ProfilePath(prof), profile.NoShutdownHook).Stop()
|
||||||
@@ -218,26 +249,55 @@ func main() {
|
|||||||
}
|
}
|
||||||
config.ProtocolMinVersion = byte(protocolMinVersion)
|
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 {
|
if pktdebug {
|
||||||
networkConfig.PacketLogging = packetLogging{}
|
networkConfig.PacketLogging = packetLogging{}
|
||||||
} else {
|
} else {
|
||||||
networkConfig.PacketLogging = nopPacketLogging{}
|
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)
|
||||||
|
checkFatal(err)
|
||||||
|
Log.Println("Bridge type is", bridgeType)
|
||||||
|
|
||||||
config.Password = determinePassword(password)
|
config.Password = determinePassword(password)
|
||||||
|
|
||||||
overlay, bridge := createOverlay(datapathName, ifaceName, isAWSVPC, config.Host, config.Port, bufSzMB, config.Password != nil)
|
overlay, injectorConsumer := createOverlay(bridgeType, bridgeConfig, config.Host, config.Port, bufSzMB, config.Password != nil)
|
||||||
networkConfig.Bridge = bridge
|
networkConfig.InjectorConsumer = injectorConsumer
|
||||||
|
|
||||||
if bridge != nil {
|
if injectorConsumer != nil {
|
||||||
if err := weavenet.DetectHairpin("vethwe-bridge", Log); err != nil {
|
if err := weavenet.DetectHairpin("vethwe-bridge", Log); err != nil {
|
||||||
Log.Errorf("Setting may cause connectivity issues : %s", err)
|
Log.Errorf("Setting may cause connectivity issues : %s", err)
|
||||||
Log.Infof("Hairpin mode may have been enabled by other software on this machine")
|
Log.Infof("Hairpin mode may have been enabled by other software on this machine")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
name := peerName(routerName)
|
|
||||||
|
|
||||||
if nickName == "" {
|
if nickName == "" {
|
||||||
var err error
|
var err error
|
||||||
nickName, err = os.Hostname()
|
nickName, err = os.Hostname()
|
||||||
@@ -247,11 +307,14 @@ func main() {
|
|||||||
config.TrustedSubnets = parseTrustedSubnets(trustedSubnetStr)
|
config.TrustedSubnets = parseTrustedSubnets(trustedSubnetStr)
|
||||||
config.PeerDiscovery = !noDiscovery
|
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")
|
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)
|
checkFatal(err)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
@@ -259,7 +322,24 @@ func main() {
|
|||||||
checkFatal(err)
|
checkFatal(err)
|
||||||
Log.Println("Our name is", router.Ourself)
|
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)
|
Log.Fatal("Unable to get initial peer set: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,24 +376,26 @@ func main() {
|
|||||||
)
|
)
|
||||||
if ipamConfig.Enabled() {
|
if ipamConfig.Enabled() {
|
||||||
var t tracker.LocalRangeTracker
|
var t tracker.LocalRangeTracker
|
||||||
if isAWSVPC {
|
if bridgeConfig.AWSVPC {
|
||||||
Log.Infoln("Creating AWSVPC LocalRangeTracker")
|
Log.Infoln("Creating AWSVPC LocalRangeTracker")
|
||||||
t, err = tracker.NewAWSVPCTracker()
|
t, err = tracker.NewAWSVPCTracker(bridgeConfig.WeaveBridgeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Log.Fatalf("Cannot create AWSVPC LocalRangeTracker: %s", err)
|
Log.Fatalf("Cannot create AWSVPC LocalRangeTracker: %s", err)
|
||||||
}
|
}
|
||||||
trackerName = "awsvpc"
|
trackerName = "awsvpc"
|
||||||
}
|
}
|
||||||
var allContainerIDs []string
|
|
||||||
if dockerCli != nil {
|
preClaims, err := findExistingAddresses(dockerCli, bridgeConfig.WeaveBridgeName)
|
||||||
allContainerIDs, err = dockerCli.AllContainerIDs()
|
|
||||||
checkFatal(err)
|
|
||||||
}
|
|
||||||
preClaims, err := findExistingAddresses(dockerCli, allContainerIDs, weavenet.WeaveBridgeName)
|
|
||||||
checkFatal(err)
|
checkFatal(err)
|
||||||
|
|
||||||
allocator, defaultSubnet = createAllocator(router, ipamConfig, preClaims, db, t, isKnownPeer)
|
allocator, defaultSubnet = createAllocator(router, ipamConfig, preClaims, db, t, isKnownPeer)
|
||||||
observeContainers(allocator)
|
observeContainers(allocator)
|
||||||
allocator.PruneOwned(allContainerIDs)
|
|
||||||
|
if dockerCli != nil {
|
||||||
|
allContainerIDs, err := dockerCli.RunningContainerIDs()
|
||||||
|
checkFatal(err)
|
||||||
|
allocator.PruneOwned(allContainerIDs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -326,6 +408,9 @@ func main() {
|
|||||||
ns.Start()
|
ns.Start()
|
||||||
defer ns.Stop()
|
defer ns.Stop()
|
||||||
dnsserver.ActivateAndServe()
|
dnsserver.ActivateAndServe()
|
||||||
|
if dockerCli != nil {
|
||||||
|
populateDNS(ns, dockerCli, name, bridgeConfig.WeaveBridgeName)
|
||||||
|
}
|
||||||
defer dnsserver.Stop()
|
defer dnsserver.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,6 +420,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
checkFatal(router.CreateRestartSentinel())
|
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,
|
// The weave script always waits for a status call to succeed,
|
||||||
// so there is no point in doing "weave launch --http-addr ''".
|
// so there is no point in doing "weave launch --http-addr ''".
|
||||||
// This is here to support stand-alone use of weaver.
|
// This is here to support stand-alone use of weaver.
|
||||||
@@ -347,8 +436,12 @@ func main() {
|
|||||||
ns.HandleHTTP(muxRouter, dockerCli)
|
ns.HandleHTTP(muxRouter, dockerCli)
|
||||||
}
|
}
|
||||||
router.HandleHTTP(muxRouter)
|
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))
|
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))
|
http.Handle("/", common.LoggingHTTPHandler(muxRouter))
|
||||||
Log.Println("Listening for HTTP control messages on", httpAddr)
|
Log.Println("Listening for HTTP control messages on", httpAddr)
|
||||||
go listenAndServeHTTP(httpAddr, nil)
|
go listenAndServeHTTP(httpAddr, nil)
|
||||||
@@ -356,7 +449,7 @@ func main() {
|
|||||||
|
|
||||||
if statusAddr != "" {
|
if statusAddr != "" {
|
||||||
muxRouter := mux.NewRouter()
|
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))
|
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver))
|
||||||
statusMux := http.NewServeMux()
|
statusMux := http.NewServeMux()
|
||||||
statusMux.Handle("/", muxRouter)
|
statusMux.Handle("/", muxRouter)
|
||||||
@@ -364,16 +457,37 @@ func main() {
|
|||||||
go listenAndServeHTTP(statusAddr, statusMux)
|
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)
|
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 {
|
func options() map[string]string {
|
||||||
options := make(map[string]string)
|
options := make(map[string]string)
|
||||||
mflag.Visit(func(f *mflag.Flag) {
|
mflag.Visit(func(f *mflag.Flag) {
|
||||||
value := f.Value.String()
|
value := f.Value.String()
|
||||||
name := canonicalName(f)
|
name := canonicalName(f)
|
||||||
if name == "password" {
|
if name == "password" || name == "token" {
|
||||||
value = "<elided>"
|
value = "<redacted>"
|
||||||
}
|
}
|
||||||
options[name] = value
|
options[name] = value
|
||||||
})
|
})
|
||||||
@@ -407,34 +521,57 @@ func (nopPacketLogging) LogPacket(string, weave.PacketKey) {
|
|||||||
func (nopPacketLogging) LogForwardPacket(string, weave.ForwardPacketKey) {
|
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()
|
overlay := weave.NewOverlaySwitch()
|
||||||
var bridge weave.Bridge
|
var injectorConsumer weave.InjectorConsumer
|
||||||
var ignoreSleeve bool
|
var ignoreSleeve bool
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case isAWSVPC:
|
case config.AWSVPC:
|
||||||
vpc := weave.NewAWSVPC()
|
vpc := weave.NewAWSVPC()
|
||||||
overlay.Add("awsvpc", vpc)
|
overlay.Add("awsvpc", vpc)
|
||||||
bridge = weave.NullBridge{}
|
injectorConsumer = weave.NullInjectorConsumer{}
|
||||||
// Currently, we do not support any overlay with AWSVPC
|
// Currently, we do not support any overlay with AWSVPC
|
||||||
ignoreSleeve = true
|
ignoreSleeve = true
|
||||||
case datapathName != "" && ifaceName != "":
|
case bridgeType == nil:
|
||||||
Log.Fatal("At most one of --datapath and --iface must be specified.")
|
injectorConsumer = weave.NullInjectorConsumer{}
|
||||||
case datapathName != "":
|
case bridgeType.IsFastdp():
|
||||||
iface, err := weavenet.EnsureInterface(datapathName)
|
iface, err := weavenet.EnsureInterface(config.DatapathName)
|
||||||
checkFatal(err)
|
checkFatal(err)
|
||||||
fastdp, err := weave.NewFastDatapath(iface, port, enableEncryption)
|
fastdp, err := weave.NewFastDatapath(iface, port, enableEncryption)
|
||||||
checkFatal(err)
|
checkFatal(err)
|
||||||
bridge = fastdp.Bridge()
|
injectorConsumer = fastdp.InjectorConsumer()
|
||||||
overlay.Add("fastdp", fastdp.Overlay())
|
overlay.Add("fastdp", fastdp.Overlay())
|
||||||
case ifaceName != "":
|
case !bridgeType.IsFastdp():
|
||||||
iface, err := weavenet.EnsureInterface(ifaceName)
|
iface, err := weavenet.EnsureInterface(weavenet.PcapIfName)
|
||||||
checkFatal(err)
|
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)
|
checkFatal(err)
|
||||||
default:
|
|
||||||
bridge = weave.NullBridge{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ignoreSleeve {
|
if !ignoreSleeve {
|
||||||
@@ -443,7 +580,7 @@ func createOverlay(datapathName string, ifaceName string, isAWSVPC bool, host st
|
|||||||
overlay.SetCompatOverlay(sleeve)
|
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) {
|
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)
|
return []byte(password)
|
||||||
}
|
}
|
||||||
|
|
||||||
func peerName(routerName string) mesh.PeerName {
|
func peerName(routerName, bridgeName, dbPrefix, hostRoot string) mesh.PeerName {
|
||||||
if routerName == "" {
|
if routerName == "" {
|
||||||
iface, err := net.InterfaceByName(weavenet.WeaveBridgeName)
|
iface, err := net.InterfaceByName(bridgeName)
|
||||||
if err != nil {
|
if err == nil {
|
||||||
Log.Fatalf("Unable to find bridge %q", weavenet.WeaveBridgeName)
|
routerName = iface.HardwareAddr.String()
|
||||||
|
} else {
|
||||||
|
routerName, err = weavenet.GetSystemPeerName(dbPrefix, hostRoot)
|
||||||
|
checkFatal(err)
|
||||||
}
|
}
|
||||||
routerName = iface.HardwareAddr.String()
|
|
||||||
}
|
}
|
||||||
name, err := mesh.PeerNameFromUserInput(routerName)
|
name, err := mesh.PeerNameFromUserInput(routerName)
|
||||||
checkFatal(err)
|
checkFatal(err)
|
||||||
|
|||||||
@@ -118,10 +118,10 @@ func newMetrics(router *weave.NetworkRouter, allocator *ipam.Allocator, ns *name
|
|||||||
|
|
||||||
func (m *collector) Collect(ch chan<- prometheus.Metric) {
|
func (m *collector) Collect(ch chan<- prometheus.Metric) {
|
||||||
|
|
||||||
status := WeaveStatus{"", nil,
|
status := WeaveStatus{
|
||||||
weave.NewNetworkRouterStatus(m.router),
|
Router: weave.NewNetworkRouterStatus(m.router),
|
||||||
ipam.NewStatus(m.allocator, address.CIDR{}),
|
IPAM: ipam.NewStatus(m.allocator, address.CIDR{}),
|
||||||
nameserver.NewStatus(m.ns, m.dnsserver)}
|
DNS: nameserver.NewStatus(m.ns, m.dnsserver)}
|
||||||
|
|
||||||
for _, metric := range metrics {
|
for _, metric := range metrics {
|
||||||
metric.Collect(status, metric.Desc, ch)
|
metric.Collect(status, metric.Desc, ch)
|
||||||
|
|||||||
+55
-1
@@ -2,13 +2,16 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
docker "github.com/fsouza/go-dockerclient"
|
docker "github.com/fsouza/go-dockerclient"
|
||||||
|
|
||||||
|
"github.com/weaveworks/mesh"
|
||||||
"github.com/weaveworks/weave/api"
|
"github.com/weaveworks/weave/api"
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/weaveworks/weave/common"
|
||||||
weavedocker "github.com/weaveworks/weave/common/docker"
|
weavedocker "github.com/weaveworks/weave/common/docker"
|
||||||
"github.com/weaveworks/weave/ipam"
|
"github.com/weaveworks/weave/ipam"
|
||||||
|
"github.com/weaveworks/weave/nameserver"
|
||||||
weavenet "github.com/weaveworks/weave/net"
|
weavenet "github.com/weaveworks/weave/net"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"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
|
// Get all the existing Weave IPs at startup, so we can stop IPAM
|
||||||
// giving out any as duplicates
|
// 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)
|
Log.Infof("Checking for pre-existing addresses on %s bridge", bridgeName)
|
||||||
// First get the address for the bridge
|
// First get the address for the bridge
|
||||||
bridgeNetDev, err := weavenet.GetBridgeNetDev(bridgeName)
|
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
|
// Now iterate over all containers to see if they have a network
|
||||||
// namespace with an attached interface
|
// namespace with an attached interface
|
||||||
if dockerCli != nil {
|
if dockerCli != nil {
|
||||||
|
containerIDs, err := dockerCli.RunningContainerIDs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
for _, cid := range containerIDs {
|
for _, cid := range containerIDs {
|
||||||
container, err := dockerCli.InspectContainer(cid)
|
container, err := dockerCli.InspectContainer(cid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -82,3 +90,49 @@ func findExistingAddresses(dockerCli *weavedocker.Client, containerIDs []string,
|
|||||||
}
|
}
|
||||||
return addrs, nil
|
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
|
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
|
var containerIDs []string
|
||||||
containers := make(map[string]*docker.Container)
|
containers := make(map[string]*docker.Container)
|
||||||
|
|
||||||
for _, cid := range args[1:] {
|
for _, cid := range containerArgs {
|
||||||
if cid == "weave:expose" {
|
if cid == "weave:expose" {
|
||||||
netDev, err := weavenet.GetBridgeNetDev(bridgeName)
|
netDev, err := weavenet.GetBridgeNetDev(bridgeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
docker "github.com/fsouza/go-dockerclient"
|
docker "github.com/fsouza/go-dockerclient"
|
||||||
"github.com/vishvananda/netns"
|
"github.com/vishvananda/netns"
|
||||||
|
|
||||||
weavenet "github.com/weaveworks/weave/net"
|
weavenet "github.com/weaveworks/weave/net"
|
||||||
|
"github.com/weaveworks/weave/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
func attach(args []string) error {
|
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)
|
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,56 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
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)
|
||||||
|
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() {
|
func init() {
|
||||||
commands = map[string]func([]string) error{
|
commands = map[string]func([]string) error{
|
||||||
"help": help,
|
"help": help,
|
||||||
"netcheck": netcheck,
|
"netcheck": netcheck,
|
||||||
"docker-tls-args": dockerTLSArgs,
|
"docker-tls-args": dockerTLSArgs,
|
||||||
"create-datapath": createDatapath,
|
"create-bridge": createBridge,
|
||||||
"delete-datapath": deleteDatapath,
|
"detect-bridge-type": detectBridgeType,
|
||||||
"check-datapath": checkDatapath,
|
"create-datapath": createDatapath,
|
||||||
"add-datapath-interface": addDatapathInterface,
|
"delete-datapath": deleteDatapath,
|
||||||
"create-plugin-network": createPluginNetwork,
|
"check-datapath": checkDatapath,
|
||||||
"remove-plugin-network": removePluginNetwork,
|
"add-datapath-interface": addDatapathInterface,
|
||||||
"container-addrs": containerAddrs,
|
"remove-plugin-network": removePluginNetwork,
|
||||||
"process-addrs": processAddrs,
|
"container-addrs": containerAddrs,
|
||||||
"attach-container": attach,
|
"process-addrs": processAddrs,
|
||||||
"detach-container": detach,
|
"attach-container": attach,
|
||||||
"configure-arp": configureARP,
|
"detach-container": detach,
|
||||||
"check-iface": checkIface,
|
"configure-arp": configureARP,
|
||||||
"del-iface": delIface,
|
"check-iface": checkIface,
|
||||||
"setup-iface": setupIface,
|
"del-iface": delIface,
|
||||||
"list-netdevs": listNetDevs,
|
"setup-iface": setupIface,
|
||||||
"cni-net": cniNet,
|
"setup-iface-addrs": setupIfaceAddrs,
|
||||||
"cni-ipam": cniIPAM,
|
"list-netdevs": listNetDevs,
|
||||||
"expose-nat": exposeNAT,
|
"cni-net": cniNet,
|
||||||
"bridge-ip": bridgeIP,
|
"cni-ipam": cniIPAM,
|
||||||
"unique-id": uniqueID,
|
"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]]
|
cmd, found := commands[os.Args[1]]
|
||||||
if !found {
|
if !found {
|
||||||
|
fmt.Fprintf(os.Stderr, "%q cmd is not found\n", os.Args[1])
|
||||||
usage()
|
usage()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-16
@@ -6,7 +6,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/coreos/go-iptables/iptables"
|
|
||||||
"github.com/j-keck/arping"
|
"github.com/j-keck/arping"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
|
|
||||||
@@ -48,33 +47,35 @@ func setupIface(args []string) error {
|
|||||||
ifaceName := args[0]
|
ifaceName := args[0]
|
||||||
newIfName := args[1]
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
withMulticastRoute, err := strconv.ParseBool(args[1])
|
||||||
link, err := netlink.LinkByName(ifaceName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := netlink.LinkSetName(link, newIfName); err != nil {
|
cidrs, err := parseCIDRs(args[2:])
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := weavenet.ConfigureARPCache(newIfName); err != nil {
|
return weavenet.SetupIfaceAddrs(link, withMulticastRoute, cidrs)
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := ipt.Append("filter", "INPUT", "-i", newIfName, "-d", "224.0.0.0/4", "-j", "DROP"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureARP(args []string) error {
|
func configureARP(args []string) error {
|
||||||
if len(args) != 1 {
|
if len(args) != 2 {
|
||||||
cmdUsage("configure-arp", "<iface-name-prefix>")
|
cmdUsage("configure-arp", "<iface-name-prefix> <root-path>")
|
||||||
}
|
}
|
||||||
prefix := args[0]
|
prefix := args[0]
|
||||||
|
rootPath := args[1]
|
||||||
|
|
||||||
links, err := netlink.LinkList()
|
links, err := netlink.LinkList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -83,7 +84,7 @@ func configureARP(args []string) error {
|
|||||||
for _, link := range links {
|
for _, link := range links {
|
||||||
ifName := link.Attrs().Name
|
ifName := link.Attrs().Name
|
||||||
if strings.HasPrefix(ifName, prefix) {
|
if strings.HasPrefix(ifName, prefix) {
|
||||||
weavenet.ConfigureARPCache(ifName)
|
weavenet.ConfigureARPCache(rootPath+"/proc", ifName)
|
||||||
if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil {
|
if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil {
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName)
|
arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName)
|
||||||
|
|||||||
@@ -2,47 +2,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/docker/client"
|
||||||
docker "github.com/fsouza/go-dockerclient"
|
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 {
|
func removePluginNetwork(args []string) error {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
cmdUsage("remove-plugin-network", "<network-name>")
|
cmdUsage("remove-plugin-network", "<network-name>")
|
||||||
@@ -71,6 +38,41 @@ while Weave is not running`, networkName, containers)
|
|||||||
return nil
|
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) {
|
func newDockerClient() (*docker.Client, error) {
|
||||||
// API 1.21 is the first version that supports docker network
|
// API 1.21 is the first version that supports docker network
|
||||||
// commands
|
// commands
|
||||||
@@ -82,5 +84,6 @@ func newDockerClient() (*docker.Client, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to connect to docker: %s", err)
|
return nil, fmt.Errorf("unable to connect to docker: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, nil
|
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"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/fsouza/go-dockerclient"
|
"github.com/fsouza/go-dockerclient"
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/weaveworks/weave/common"
|
||||||
|
weavedocker "github.com/weaveworks/weave/common/docker"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -24,39 +23,6 @@ var (
|
|||||||
Log = common.Log
|
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 {
|
func unmarshalRequestBody(r *http.Request, target interface{}) error {
|
||||||
body, err := ioutil.ReadAll(r.Body)
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -113,7 +79,7 @@ func marshalResponseBody(r *http.Response, body interface{}) error {
|
|||||||
return nil
|
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)
|
subs := containerIDRegexp.FindStringSubmatch(path)
|
||||||
if subs == nil {
|
if subs == nil {
|
||||||
err := fmt.Errorf("No container id found in request with path %s", path)
|
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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -16,10 +15,11 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
docker "github.com/fsouza/go-dockerclient"
|
docker "github.com/fsouza/go-dockerclient"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
weaveapi "github.com/weaveworks/weave/api"
|
weaveapi "github.com/weaveworks/weave/api"
|
||||||
weavedocker "github.com/weaveworks/weave/common/docker"
|
weavedocker "github.com/weaveworks/weave/common/docker"
|
||||||
weavenet "github.com/weaveworks/weave/net"
|
weavenet "github.com/weaveworks/weave/net"
|
||||||
"github.com/weaveworks/weave/net/address"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -50,6 +50,7 @@ func dockerAPIEndpoint(endpoint string) *regexp.Regexp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
Enabled bool
|
||||||
HostnameFromLabel string
|
HostnameFromLabel string
|
||||||
HostnameMatch string
|
HostnameMatch string
|
||||||
HostnameReplacement string
|
HostnameReplacement string
|
||||||
@@ -62,6 +63,7 @@ type Config struct {
|
|||||||
Version string
|
Version string
|
||||||
WithoutDNS bool
|
WithoutDNS bool
|
||||||
NoMulticastRoute bool
|
NoMulticastRoute bool
|
||||||
|
KeepTXOn bool
|
||||||
DockerBridge string
|
DockerBridge string
|
||||||
DockerHost string
|
DockerHost string
|
||||||
}
|
}
|
||||||
@@ -75,7 +77,8 @@ type wait struct {
|
|||||||
type Proxy struct {
|
type Proxy struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
Config
|
Config
|
||||||
client *docker.Client
|
client *weavedocker.Client
|
||||||
|
weave *weaveapi.Client
|
||||||
dockerBridgeIP string
|
dockerBridgeIP string
|
||||||
hostnameMatchRegexp *regexp.Regexp
|
hostnameMatchRegexp *regexp.Regexp
|
||||||
weaveWaitVolume string
|
weaveWaitVolume string
|
||||||
@@ -122,16 +125,13 @@ func (j attachJob) Stop() {
|
|||||||
j.timer.Stop()
|
j.timer.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProxy(c Config) (*Proxy, error) {
|
func StubProxy(c Config) (*Proxy, error) {
|
||||||
p := &Proxy{
|
p := &Proxy{
|
||||||
Config: c,
|
Config: c,
|
||||||
waiters: make(map[*http.Request]*wait),
|
waiters: make(map[*http.Request]*wait),
|
||||||
attachJobs: make(map[string]*attachJob),
|
attachJobs: make(map[string]*attachJob),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
}
|
weave: weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), Log),
|
||||||
|
|
||||||
if err := p.TLSConfig.LoadCerts(); err != nil {
|
|
||||||
Log.Fatalf("Could not configure tls for proxy: %s", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We pin the protocol version to 1.18 (which corresponds to
|
// We pin the protocol version to 1.18 (which corresponds to
|
||||||
@@ -143,9 +143,21 @@ func NewProxy(c Config) (*Proxy, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if !p.WithoutDNS {
|
||||||
ip, err := weavenet.FindBridgeIP(c.DockerBridge, nil)
|
ip, err := weavenet.FindBridgeIP(c.DockerBridge, nil)
|
||||||
@@ -166,7 +178,7 @@ func NewProxy(c Config) (*Proxy, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
client.AddObserver(p)
|
p.client.AddObserver(p)
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
@@ -204,7 +216,7 @@ func (proxy *Proxy) findWeaveWaitVolumes() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) findVolume(v string) (string, error) {
|
func (proxy *Proxy) findVolume(v string) (string, error) {
|
||||||
container, err := proxy.client.InspectContainer("weaveproxy")
|
container, err := proxy.client.InspectContainer("weave")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("Could not find the weavewait volume: %s", err)
|
return "", fmt.Errorf("Could not find the weavewait volume: %s", err)
|
||||||
}
|
}
|
||||||
@@ -279,13 +291,17 @@ func (proxy *Proxy) Listen() []net.Listener {
|
|||||||
return listeners
|
return listeners
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) Serve(listeners []net.Listener) {
|
func (proxy *Proxy) Serve(listeners []net.Listener, ready func()) {
|
||||||
errs := make(chan error)
|
errs := make(chan error)
|
||||||
for _, listener := range listeners {
|
for _, listener := range listeners {
|
||||||
go func(listener net.Listener) {
|
go func(listener net.Listener) {
|
||||||
errs <- (&http.Server{Handler: proxy}).Serve(listener)
|
errs <- (&http.Server{Handler: proxy}).Serve(listener)
|
||||||
}(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 {
|
for range listeners {
|
||||||
err := <-errs
|
err := <-errs
|
||||||
if err != nil {
|
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) {
|
func (proxy *Proxy) StatusHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
for _, addr := range proxy.normalisedAddrs {
|
for _, addr := range proxy.normalisedAddrs {
|
||||||
fmt.Fprintln(w, addr)
|
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]
|
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) {
|
func (proxy *Proxy) createWait(r *http.Request, ident string) {
|
||||||
proxy.Lock()
|
proxy.Lock()
|
||||||
proxy.waiters[r] = &wait{ident: ident, ch: make(chan error, 1)}
|
proxy.waiters[r] = &wait{ident: ident, ch: make(chan error, 1)}
|
||||||
@@ -489,10 +489,6 @@ func (proxy *Proxy) attach(containerID string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
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 {
|
if !containerShouldAttach(container) || !container.State.Running {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -503,53 +499,77 @@ func (proxy *Proxy) attach(containerID string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
Log.Infof("Attaching container %s with WEAVE_CIDR \"%s\" to weave network", container.ID, strings.Join(cidrs, " "))
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
args := []string{"attach"}
|
fqdn := container.Config.Hostname + "." + container.Config.Domainname
|
||||||
args = append(args, cidrs...)
|
|
||||||
if !proxy.NoRewriteHosts {
|
if !proxy.NoRewriteHosts {
|
||||||
args = append(args, "--rewrite-hosts")
|
var extraHosts []string
|
||||||
|
|
||||||
if container.HostConfig != nil {
|
if container.HostConfig != nil {
|
||||||
for _, eh := range container.HostConfig.ExtraHosts {
|
extraHosts = container.HostConfig.ExtraHosts
|
||||||
args = append(args, fmt.Sprintf("--add-host=%s", eh))
|
}
|
||||||
|
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")
|
return err
|
||||||
}
|
|
||||||
args = append(args, container.ID)
|
|
||||||
return callWeaveAttach(container, args)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func callWeaveAttach(container *docker.Container, args []string) error {
|
func (proxy *Proxy) allocateCIDRs(containerID string, cidrs []string) ([]*net.IPNet, error) {
|
||||||
if _, stderr, err := callWeave(args...); err != nil {
|
if len(cidrs) == 0 {
|
||||||
Log.Warningf("Attaching container %s to weave network failed: %s", container.ID, string(stderr))
|
cidrs = []string{"net:default"}
|
||||||
return errors.New(string(stderr))
|
|
||||||
} else if len(stderr) > 0 {
|
|
||||||
Log.Warningf("Attaching container %s to weave network: %s", container.ID, string(stderr))
|
|
||||||
}
|
}
|
||||||
return nil
|
var ipnet *net.IPNet
|
||||||
}
|
var err error
|
||||||
|
var ipnets []*net.IPNet
|
||||||
func validateCIDRs(cidrs []string) error {
|
|
||||||
for _, cidr := range cidrs {
|
for _, cidr := range cidrs {
|
||||||
if cidr == "net:default" {
|
switch {
|
||||||
continue
|
case cidr == "net:default":
|
||||||
}
|
ipnet, err = proxy.weave.AllocateIP(containerID, true)
|
||||||
for _, prefix := range []string{"ip:", "net:", ""} {
|
case strings.HasPrefix(cidr, "net:"):
|
||||||
if strings.HasPrefix(cidr, prefix) {
|
var subnet *net.IPNet
|
||||||
if _, err := address.ParseCIDR(strings.TrimPrefix(cidr, prefix)); err == nil {
|
_, subnet, err = net.ParseCIDR(strings.TrimPrefix(cidr, "net:"))
|
||||||
break
|
if err != nil {
|
||||||
}
|
break
|
||||||
return fmt.Errorf("invalid WEAVE_CIDR: %s", cidr)
|
|
||||||
}
|
}
|
||||||
|
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) {
|
func (proxy *Proxy) weaveCIDRs(networkMode string, env []string) ([]string, error) {
|
||||||
@@ -598,8 +618,7 @@ func (proxy *Proxy) getDNSDomain() string {
|
|||||||
if proxy.WithoutDNS {
|
if proxy.WithoutDNS {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), Log)
|
domain, _ := proxy.weave.DNSDomain()
|
||||||
domain, _ := weave.DNSDomain()
|
|
||||||
return domain
|
return domain
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,7 +657,6 @@ func (proxy *Proxy) updateContainerNetworkSettings(container jsonObject) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) symlink(unixAddrs []string) (err error) {
|
func (proxy *Proxy) symlink(unixAddrs []string) (err error) {
|
||||||
var container *docker.Container
|
|
||||||
binds := []string{"/var/run/weave:/var/run/weave"}
|
binds := []string{"/var/run/weave:/var/run/weave"}
|
||||||
froms := []string{}
|
froms := []string{}
|
||||||
for _, addr := range unixAddrs {
|
for _, addr := range unixAddrs {
|
||||||
@@ -654,7 +672,10 @@ func (proxy *Proxy) symlink(unixAddrs []string) (err error) {
|
|||||||
if len(froms) == 0 {
|
if len(froms) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
return proxy.runTransientContainer([]string{"/home/weave/symlink", weaveSock}, froms, binds)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proxy *Proxy) runTransientContainer(entrypoint, cmd, binds []string) (err error) {
|
||||||
env := []string{
|
env := []string{
|
||||||
"PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
"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))
|
env = append(env, fmt.Sprintf("%s=%s", "WEAVE_DEBUG", val))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var container *docker.Container
|
||||||
container, err = proxy.client.CreateContainer(docker.CreateContainerOptions{
|
container, err = proxy.client.CreateContainer(docker.CreateContainerOptions{
|
||||||
Config: &docker.Config{
|
Config: &docker.Config{
|
||||||
Image: proxy.Image,
|
Image: proxy.Image,
|
||||||
Entrypoint: []string{"/home/weave/symlink", weaveSock},
|
Entrypoint: entrypoint,
|
||||||
Cmd: froms,
|
Cmd: cmd,
|
||||||
Env: env,
|
Env: env,
|
||||||
},
|
},
|
||||||
HostConfig: &docker.HostConfig{Binds: binds},
|
HostConfig: &docker.HostConfig{Binds: binds, NetworkMode: "none"},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
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
|
*FastDatapath
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fastdp *FastDatapath) Bridge() Bridge {
|
func (fastdp *FastDatapath) InjectorConsumer() InjectorConsumer {
|
||||||
return fastDatapathBridge{fastdp}
|
return fastDatapathInjectorConsumer{fastdp}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fastdp fastDatapathBridge) Interface() *net.Interface {
|
func (fastdp fastDatapathInjectorConsumer) Interface() *net.Interface {
|
||||||
return fastdp.iface
|
return fastdp.iface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fastdp fastDatapathBridge) String() string {
|
func (fastdp fastDatapathInjectorConsumer) String() string {
|
||||||
return fmt.Sprint(fastdp.iface.Name, " (via ODP)")
|
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()
|
lock := fastdp.startLock()
|
||||||
defer lock.unlock()
|
defer lock.unlock()
|
||||||
|
|
||||||
@@ -238,12 +238,12 @@ func (fastdp fastDatapathBridge) Stats() map[string]int {
|
|||||||
|
|
||||||
var routerBridgePortID = bridgePortID{router: true}
|
var routerBridgePortID = bridgePortID{router: true}
|
||||||
|
|
||||||
func (fastdp fastDatapathBridge) StartConsumingPackets(consumer BridgeConsumer) error {
|
func (fastdp fastDatapathInjectorConsumer) StartConsumingPackets(consumer Consumer) error {
|
||||||
fastdp.lock.Lock()
|
fastdp.lock.Lock()
|
||||||
defer fastdp.lock.Unlock()
|
defer fastdp.lock.Unlock()
|
||||||
|
|
||||||
if fastdp.sendToPort[routerBridgePortID] != nil {
|
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
|
// set up delivery to the weave router port on the bridge
|
||||||
@@ -257,7 +257,7 @@ func (fastdp fastDatapathBridge) StartConsumingPackets(consumer BridgeConsumer)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fastdp fastDatapathBridge) InjectPacket(key PacketKey) FlowOp {
|
func (fastdp fastDatapathInjectorConsumer) InjectPacket(key PacketKey) FlowOp {
|
||||||
lock := fastdp.startLock()
|
lock := fastdp.startLock()
|
||||||
defer lock.unlock()
|
defer lock.unlock()
|
||||||
return fastdp.bridge(routerBridgePortID, key, &lock)
|
return fastdp.bridge(routerBridgePortID, key, &lock)
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Interface to packet handling on the local virtual bridge
|
// Interface to packet handling on the local virtual bridge
|
||||||
type Bridge interface {
|
type InjectorConsumer interface {
|
||||||
// Inject a packet to be delivered locally
|
// Inject a packet to be delivered locally
|
||||||
InjectPacket(PacketKey) FlowOp
|
InjectPacket(PacketKey) FlowOp
|
||||||
|
|
||||||
// Start consuming packets from the bridge. Injected packets
|
// Start consuming packets from the bridge. Injected packets
|
||||||
// should not be included.
|
// should not be included.
|
||||||
StartConsumingPackets(BridgeConsumer) error
|
StartConsumingPackets(Consumer) error
|
||||||
|
|
||||||
Interface() *net.Interface
|
Interface() *net.Interface
|
||||||
String() string
|
String() string
|
||||||
@@ -19,26 +19,26 @@ type Bridge interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A function that determines how to handle locally captured packets.
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (NullBridge) StartConsumingPackets(BridgeConsumer) error {
|
func (NullInjectorConsumer) StartConsumingPackets(Consumer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (NullBridge) Interface() *net.Interface {
|
func (NullInjectorConsumer) Interface() *net.Interface {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (NullBridge) String() string {
|
func (NullInjectorConsumer) String() string {
|
||||||
return "no overlay bridge"
|
return "no overlay bridge"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (NullBridge) Stats() map[string]int {
|
func (NullInjectorConsumer) Stats() map[string]int {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -34,9 +34,9 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type NetworkConfig struct {
|
type NetworkConfig struct {
|
||||||
BufSz int
|
BufSz int
|
||||||
PacketLogging PacketLogging
|
PacketLogging PacketLogging
|
||||||
Bridge Bridge
|
InjectorConsumer InjectorConsumer
|
||||||
}
|
}
|
||||||
|
|
||||||
type PacketLogging interface {
|
type PacketLogging interface {
|
||||||
@@ -55,8 +55,8 @@ func NewNetworkRouter(config mesh.Config, networkConfig NetworkConfig, name mesh
|
|||||||
if overlay == nil {
|
if overlay == nil {
|
||||||
overlay = NullNetworkOverlay{}
|
overlay = NullNetworkOverlay{}
|
||||||
}
|
}
|
||||||
if networkConfig.Bridge == nil {
|
if networkConfig.InjectorConsumer == nil {
|
||||||
networkConfig.Bridge = NullBridge{}
|
networkConfig.InjectorConsumer = NullInjectorConsumer{}
|
||||||
}
|
}
|
||||||
|
|
||||||
meshRouter, err := mesh.NewRouter(config, name, nickName, overlay, common.LogLogger())
|
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
|
// Start listening for TCP connections, locally captured packets, and
|
||||||
// forwarded packets.
|
// forwarded packets.
|
||||||
func (router *NetworkRouter) Start() {
|
func (router *NetworkRouter) Start() {
|
||||||
log.Println("Sniffing traffic on", router.Bridge)
|
log.Println("Sniffing traffic on", router.InjectorConsumer)
|
||||||
checkFatal(router.Bridge.StartConsumingPackets(router.handleCapturedPacket))
|
checkFatal(router.InjectorConsumer.StartConsumingPackets(router.handleCapturedPacket))
|
||||||
checkFatal(router.Overlay.(NetworkOverlay).StartConsumingPackets(router.Ourself.Peer, router.Peers, router.handleForwardedPacket))
|
checkFatal(router.Overlay.(NetworkOverlay).StartConsumingPackets(router.Ourself.Peer, router.Peers, router.handleForwardedPacket))
|
||||||
router.Router.Start()
|
router.Router.Start()
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ func (router *NetworkRouter) handleForwardedPacket(key ForwardPacketKey) FlowOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
router.PacketLogging.LogForwardPacket("Injecting", key)
|
router.PacketLogging.LogForwardPacket("Injecting", key)
|
||||||
injectFop := router.Bridge.InjectPacket(key.PacketKey)
|
injectFop := router.InjectorConsumer.InjectPacket(key.PacketKey)
|
||||||
dstPeer := router.Macs.Lookup(dstMac)
|
dstPeer := router.Macs.Lookup(dstMac)
|
||||||
if dstPeer == router.Ourself.Peer {
|
if dstPeer == router.Ourself.Peer {
|
||||||
return injectFop
|
return injectFop
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ type MACStatus struct {
|
|||||||
func NewNetworkRouterStatus(router *NetworkRouter) *NetworkRouterStatus {
|
func NewNetworkRouterStatus(router *NetworkRouter) *NetworkRouterStatus {
|
||||||
return &NetworkRouterStatus{
|
return &NetworkRouterStatus{
|
||||||
mesh.NewStatus(router.Router),
|
mesh.NewStatus(router.Router),
|
||||||
router.Bridge.String(),
|
router.InjectorConsumer.String(),
|
||||||
router.Bridge.Stats(),
|
router.InjectorConsumer.Stats(),
|
||||||
NewMACStatusSlice(router.Macs)}
|
NewMACStatusSlice(router.Macs)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -27,7 +27,7 @@ type Pcap struct {
|
|||||||
readHandle *pcap.Handle
|
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)
|
wh, err := newPcapHandle(iface.Name, false, 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
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)
|
rh, err := newPcapHandle(p.iface.Name, true, 65535, p.bufSz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -122,7 +122,7 @@ func (p *Pcap) Process(frame []byte, dec *EthernetDecoder, broadcast bool) {
|
|||||||
checkWarn(p.writeHandle.WritePacketData(frame))
|
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()
|
dec := NewEthernetDecoder()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|||||||
+2
-2
@@ -42,8 +42,8 @@ On a fresh repository, the Makefile will do the following:
|
|||||||
- assemble the build container
|
- assemble the build container
|
||||||
- download specific versions of all the dependencies
|
- download specific versions of all the dependencies
|
||||||
- build the weave components in the build container
|
- build the weave components in the build container
|
||||||
- package them into three Docker images (`weaveworks/weave`,
|
- package them into two Docker images (`weaveworks/weave`,
|
||||||
`weaveworks/weaveexec`, and `weaveworks/plugin`)
|
`weaveworks/weaveexec`)
|
||||||
- Exported these images as `weave.tar.gz`
|
- Exported these images as `weave.tar.gz`
|
||||||
|
|
||||||
The first two steps may take a while - don't worry, they are
|
The first two steps may take a while - don't worry, they are
|
||||||
|
|||||||
@@ -108,5 +108,8 @@ For more information, see the
|
|||||||
|
|
||||||
### Caveats
|
### 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 Weave Net router container must be running for CNI to allocate addresses
|
||||||
- The CNI plugin does not add entries to weaveDNS.
|
- 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).
|
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,
|
You must permit traffic to flow through TCP 6783 and UDP 6783/6784,
|
||||||
which are Weave’s control and data ports.
|
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
|
on Google Cloud Platform a firewall rule for allowing ESP traffic has
|
||||||
to be installed.
|
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`
|
The official Ubuntu image does not contain the `ping` and `nc`
|
||||||
commands which are used in many of our examples throughout the
|
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/).
|
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
|
There are two plugin implementations for Weave Net: the
|
||||||
when there are network connectivity problems.
|
["Legacy"](/site/plugin.md) plugin which doesn't require an external
|
||||||
|
cluster store, and the ["V2"](/site/plugin-v2.md) plugin which
|
||||||
See [Integrating Docker via the Network Plugin](/site/plugin.md) for more details.
|
supports Docker swarm mode.
|
||||||
|
|
||||||
|
|
||||||
### <a name="cniplugin"></a>Weave Network CNI Plugin
|
### <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
|
Weave Net automatically assigns containers a unique IP address
|
||||||
across the network, and also releases that address when the container
|
across the network, and also releases that address when the container
|
||||||
exits. Unless you explicitly specify an address, this occurs for all
|
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
|
`attach`, `detach`, `expose`, and `hide` commands. Weave Net can also assign
|
||||||
addresses in multiple subnets.
|
addresses in multiple subnets.
|
||||||
|
|
||||||
@@ -203,4 +203,4 @@ named `weavedb` is used to store this data.
|
|||||||
**See Also**
|
**See Also**
|
||||||
|
|
||||||
* [Automatic Allocation Across Multiple Subnets](/site/ipam/allocation-multi-ipam.md)
|
* [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
|
Weave Net can be installed onto your CNI-enabled Kubernetes cluster
|
||||||
with a single command:
|
with a single command:
|
||||||
|
|
||||||
* Kubernetes versions `1.6` and above:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
$ kubectl apply -f https://git.io/weave-kube-1.6
|
$ kubectl apply -n kube-system -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
|
||||||
```
|
|
||||||
|
|
||||||
* Kubernetes versions up to `1.5`:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ kubectl apply -f https://git.io/weave-kube
|
|
||||||
```
|
```
|
||||||
|
|
||||||
After a few seconds, a Weave Net pod should be running on each
|
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
|
Then relaunch Kubernetes and install the addon as described
|
||||||
above.
|
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
|
**Note:** The URLs:
|
||||||
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
|
- [https://git.io/weave-kube](https://git.io/weave-kube), and
|
||||||
page](https://github.com/weaveworks/weave/releases).
|
- [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
|
## <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
|
### <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:
|
and so you will need to perform the procedure manually:
|
||||||
|
|
||||||
* Apply the updated addon manifest `kubectl apply -f https://git.io/weave-kube`
|
* 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
|
### <a name="configuration-options"></a> Changing Configuration Options
|
||||||
|
|
||||||
The default configuration settings can be changed by saving and editing the
|
#### Using `cloud.weave.works`
|
||||||
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.
|
|
||||||
|
|
||||||
Some parameters are changed by environment variables; these can be
|
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:
|
||||||
inserted into the YAML file like this:
|
|
||||||
|
|
||||||
```
|
- `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`.
|
||||||
containers:
|
- `password-secret`: name of the Kubernetes secret containing your password.
|
||||||
- name: weave
|
Example:
|
||||||
env:
|
|
||||||
- name: IPALLOC_RANGE
|
$ echo "s3cr3tp4ssw0rd" > /var/lib/weave/weave-passwd.txt
|
||||||
value: 10.0.0.0/16
|
$ 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:
|
The list of variables you can set is:
|
||||||
|
|
||||||
* `CHECKPOINT_DISABLE` - if set to 1, disable checking for new Weave Net
|
* `CHECKPOINT_DISABLE` - if set to 1, disable checking for new Weave Net
|
||||||
versions (default is blank, i.e. check is enabled)
|
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
|
* `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`)
|
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)
|
* `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
|
a larger size for better performance if your network supports jumbo
|
||||||
frames - see [here](/site/using-weave/fastdp.md#mtu) for more
|
frames - see [here](/site/using-weave/fastdp.md#mtu) for more
|
||||||
details.
|
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
|
Example:
|
||||||
kernel is one of those that can panic if hairpin is enabled, then you can disable it
|
```
|
||||||
by setting `HAIRPIN_MODE=false`.
|
$ 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
|
menu_order: 60
|
||||||
search_type: Documentation
|
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
|
Docker enables you to create multiple independent networks and attach
|
||||||
different sets of containers to each network. However, coordinating
|
different sets of containers to each network. However, coordinating
|
||||||
this between hosts, Docker requires that you configure a
|
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/#step-1-set-up-a-key-value-store).
|
["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
|
If your Docker installation has a key-value store, create a network
|
||||||
based on Weave Net as follows:
|
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
|
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**
|
**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
|
menu_order: 20
|
||||||
search_type: Documentation
|
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
|
### `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
|
There's no specific documentation from Docker on using a cluster
|
||||||
store, but the first part of
|
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.
|
>**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
|
network created when the plugin is first launched has the multicast
|
||||||
option turned on, but for any networks you create it defaults to off.
|
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**
|
**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
|
Service: proxy
|
||||||
Address: tcp://127.0.0.1:12375
|
Address: tcp://127.0.0.1:12375
|
||||||
|
|
||||||
Service: plugin
|
Service: plugin (legacy)
|
||||||
DriverName: weave
|
DriverName: weave
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -284,14 +284,11 @@ on reboot. This can be disabled via:
|
|||||||
|
|
||||||
weave launch --no-restart
|
weave launch --no-restart
|
||||||
|
|
||||||
Note that the
|
Note that the Weave Net router will create the `weave` network bridge
|
||||||
[Weave Net Docker API Proxy](/site/weave-docker-api.md)
|
if necessary when it restarts, and the [Weave Net Docker API
|
||||||
is responsible for reconfiguring the Weave router and re-attaching
|
Proxy](/site/weave-docker-api.md) will re-attach any application
|
||||||
application containers to the Weave network at startup, so if you
|
containers that it originally attached to the Weave network when they
|
||||||
choose not to run it you must make arrangements for this
|
restart.
|
||||||
reconfiguration to take place. In this scenario, set up your favourite
|
|
||||||
process manager to run `weave launch-router` every time the machine
|
|
||||||
reboots.
|
|
||||||
|
|
||||||
## <a name="snapshots"></a>Snapshot Releases
|
## <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**
|
**See Also**
|
||||||
|
|
||||||
* [Installing Weave Net](/site/installing-weave.md)
|
* [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 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.
|
>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
|
### Dynamically Detaching Containers
|
||||||
|
|
||||||
A container can be detached from a subnet, by using the `weave detach` command:
|
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)
|
||||||
+13
-18
@@ -7,8 +7,7 @@ search_type: Documentation
|
|||||||
The Docker API proxy automatically attaches containers to the Weave
|
The Docker API proxy automatically attaches containers to the Weave
|
||||||
network when they are started using the ordinary Docker
|
network when they are started using the ordinary Docker
|
||||||
[command-line interface](https://docs.docker.com/reference/commandline/cli/)
|
[command-line interface](https://docs.docker.com/reference/commandline/cli/)
|
||||||
or the [remote API](https://docs.docker.com/reference/api/docker_remote_api/),
|
or the [remote API](https://docs.docker.com/reference/api/docker_remote_api/).
|
||||||
instead of `weave run`.
|
|
||||||
|
|
||||||
### <a name="attaching-containers"></a>Attaching Containers to a Weave Network
|
### <a name="attaching-containers"></a>Attaching Containers to a Weave Network
|
||||||
|
|
||||||
@@ -29,26 +28,24 @@ Docker containers are started with the --net flag, for example:
|
|||||||
|
|
||||||
Note that if a Docker container is started with the --net flag, then the Weave Docker API Proxy
|
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.
|
is automatically disabled and is not used to attach containers.
|
||||||
See [Integrating Docker via the Network Plugin](/site/plugin.md).
|
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
|
**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.
|
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).
|
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
|
### <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
|
The proxy sits between the Docker client (command line or API) and the
|
||||||
Docker daemon, and intercepts the communication between the two. You can
|
Docker daemon, and intercepts the communication between the two.
|
||||||
start it simultaneously with the router and weaveDNS via `launch`:
|
It is started along with the router and weaveDNS when you run:
|
||||||
|
|
||||||
host1$ weave launch
|
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
|
By default, the proxy decides where to listen based on how the
|
||||||
launching client connects to Docker. If the launching client connected
|
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`
|
12375, on all network interfaces. This can be adjusted using the `-H`
|
||||||
argument, for example:
|
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
|
If no TLS or listening interfaces are set, TLS is auto-configured
|
||||||
based on the Docker daemon's settings, and the listening interfaces are
|
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
|
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
|
host1$ weave stop
|
||||||
|
|
||||||
or in conjunction with the router and weaveDNS via `stop`.
|
|
||||||
|
|
||||||
If you set your `DOCKER_HOST` to point at the proxy, you should revert
|
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**
|
**See Also**
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ Additionally, the hostname is matched against a regular expression `<regexp>` an
|
|||||||
|
|
||||||
For example, you can launch the proxy using all three flags, as follows:
|
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)
|
host1$ eval $(weave env)
|
||||||
|
|
||||||
>**Note:** regexp substitution groups must be pre-pended with a dollar sign
|
>**Note:** regexp substitution groups must be pre-pended with a dollar sign
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ 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
|
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:
|
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
|
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.
|
||||||
|
|||||||
@@ -4,44 +4,18 @@ menu_order: 50
|
|||||||
search_type: Documentation
|
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
|
This command always had limitations, and now we have Docker plugins
|
||||||
containers on to the Weave network using `weave run`:
|
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
|
The `weave start` and `weave restart` commands have also been removed,
|
||||||
can freely specify whatever Docker options you need.
|
for the same reasons.
|
||||||
|
|
||||||
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)
|
|
||||||
@@ -27,7 +27,7 @@ IP instead of the Weave IP, or you require name resolution for
|
|||||||
Docker-managed networks), the proxy must be launched using the
|
Docker-managed networks), the proxy must be launched using the
|
||||||
`--no-rewrite-hosts` flag.
|
`--no-rewrite-hosts` flag.
|
||||||
|
|
||||||
host1$ weave launch-router && weave launch-proxy --no-rewrite-hosts
|
host1$ weave launch --no-rewrite-hosts
|
||||||
|
|
||||||
**See Also**
|
**See Also**
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ attempts to duplicate it.
|
|||||||
|
|
||||||
In the standard auto-detection case you can launch a TLS-enabled proxy as follows:
|
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
|
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 `--no-detect-tls` flag, or you can manually configure the proxy's TLS using
|
||||||
@@ -22,7 +22,7 @@ daemon.
|
|||||||
For example, if you generated your certificates and keys
|
For example, if you generated your certificates and keys
|
||||||
into the Docker host's `/tls` directory, launch the proxy using:
|
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
|
--tlscert=/tls/server-cert.pem --tlskey=/tls/server-key.pem
|
||||||
|
|
||||||
The paths to your certificates and key must be provided as absolute
|
The paths to your certificates and key must be provided as absolute
|
||||||
|
|||||||
@@ -45,13 +45,13 @@ 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
|
Weave Net IP. If a container has more than one Weave Net IP, then the inspect call
|
||||||
only includes one of them.
|
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
|
### Multicast Traffic and Launching the Weave Proxy
|
||||||
|
|
||||||
By default, multicast traffic is routed over the Weave network.
|
By default, multicast traffic is routed over the Weave network.
|
||||||
To turn this off, for example, because you want to configure your own multicast
|
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
|
### 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
|
* `--no-restart` -- remove the default policy of `--restart=always`, if
|
||||||
you want to control start-up of the proxy yourself
|
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**
|
**See Also**
|
||||||
|
|
||||||
* [Setting Up The Weave Docker API Proxy](/site/weave-docker-api.md)
|
* [Setting Up The Weave Docker API Proxy](/site/weave-docker-api.md)
|
||||||
* [Securing Docker Communications With TLS](/site/weave-docker-api/securing-proxy.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.
|
registered, but it will still use weaveDNS for resolution.
|
||||||
|
|
||||||
To disable an application container's use of weaveDNS, add the
|
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.
|
disable weaveDNS itself, launch weave with the `--no-dns` option.
|
||||||
|
|
||||||
**See Also**
|
**See Also**
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ search_type: Documentation
|
|||||||
|
|
||||||
The weaveDNS service running on every host acts as the nameserver for
|
The weaveDNS service running on every host acts as the nameserver for
|
||||||
containers on that host. It learns about hostnames for local containers
|
containers on that host. It learns about hostnames for local containers
|
||||||
from the proxy and from the `weave run` command.
|
from the proxy and from the `weave attach` command.
|
||||||
|
|
||||||
If a hostname is in the `.weave.local` domain, then weaveDNS records the association of that
|
If a hostname is in the `.weave.local` domain, then weaveDNS records the association of that
|
||||||
name with the container's Weave Net IP address(es) in its in-memory
|
name with the container's Weave Net IP address(es) in its in-memory
|
||||||
@@ -38,7 +38,7 @@ In the event that weaveDNS is launched in this way, it's important that
|
|||||||
other calls to `weave` also specify the bridge device:
|
other calls to `weave` also specify the bridge device:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ sudo DOCKER_BRIDGE=someother weave run ...
|
$ sudo DOCKER_BRIDGE=someother weave attach ...
|
||||||
```
|
```
|
||||||
|
|
||||||
**See Also**
|
**See Also**
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ The following topics are discussed:
|
|||||||
## <a name="domain-search-path"></a>Configuring the domain search paths
|
## <a name="domain-search-path"></a>Configuring the domain search paths
|
||||||
|
|
||||||
If you don't supply a domain search path (with `--dns-search=`), Weave
|
If you don't supply a domain search path (with `--dns-search=`), Weave
|
||||||
Net (via the [proxy](/site/weave-docker-api.md) or via `weave run`)
|
Net (via the [proxy](/site/weave-docker-api.md) or via `weave attach`)
|
||||||
tells a container to look for "bare" hostnames, like `pingme`, in its
|
tells a container to look for "bare" hostnames, like `pingme`, in its
|
||||||
own domain (or in `weave.local` if it has no domain).
|
own domain (or in `weave.local` if it has no domain).
|
||||||
|
|
||||||
|
|||||||
Loaded 100 of 152 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user