Compare commits

...
350 Commits
Author SHA1 Message Date
Bryan Boreham c7a235a54a Add release v2.6.4 2020-05-30 10:11:08 +00:00
Bryan Boreham bef50d3730 Merge pull request #3811 from weaveworks/allow-dnat-127
Only drop traffic to the Weave Net port on 127.0.0.1
2020-05-30 11:07:13 +01:00
Bryan Boreham a46d18da0c Use a more targeted iptables rule to block access to control port
Only block the specific port Weave Net is listening on.
Add a comment so users know what the rule is for.

Remove the rule added in v2.6.3 because it was too coarse.
2020-05-29 19:58:41 +00:00
Bryan Boreham 95c020fbe0 Merge pull request #3809 from weaveworks/move-ansible-install
Move ansible install out from every CI run
2020-05-29 20:58:05 +01:00
Bryan Boreham 7c2084b9af Move ansible install out from every CI run
to only where we create images.
2020-05-29 13:33:30 +00:00
Bryan Boreham f78c4dacc5 Add release v2.6.3 2020-05-28 10:12:54 +00:00
Bryan Boreham 9245b73913 Merge pull request #3805 from weaveworks/block-remote-localhost
Block non-local traffic to the Weave control port
2020-05-28 10:50:55 +01:00
Bryan Boreham 6ee961b068 Block non-local traffic to the Weave control port
We expect the loopback address 127.0.0.1 to be accessible only from
the local host.

We need to allow RELATED,ESTABLISHED traffic which may be the return
path of a Kubernetes HostPort.
2020-05-27 16:43:50 +00:00
Bryan Boreham 1f920513de Merge pull request #3804 from weaveworks/npc-errors-metrics2
metric for NPC errors
2020-05-23 20:43:55 +01:00
Bryan Boreham 15f21f1899 Merge pull request #3801 from weaveworks/disable-accept-ra
Disable accept_ra on Weave Net interfaces
2020-05-22 11:00:50 +01:00
Bryan Boreham 09a204b978 NPC: increment metric each time an error is logged 2020-05-22 09:55:07 +00:00
Murali Reddy 77fbb2c12b introduce weavenpc_policy_enforcement_errors prometheus metric
to track number of errors occured during enforcing network policies

Fixes #3791
2020-05-22 09:54:11 +00:00
Bryan Boreham 6ad3e69faf Plumb through /proc path config to Docker plugin 2020-05-18 14:47:26 +00:00
Bryan Boreham e2088ef401 Disable accept_ra setting on interfaces we create 2020-05-14 10:21:41 +00:00
Bryan Boreham 0f3864968e refactor: supply /proc path to CreateAndAttachVeth()
Move the assumptions about where we're running up towards the caller.
2020-05-14 10:21:09 +00:00
Bryan Boreham 2f235daa1c Merge pull request #3777 from weaveworks/eks
add steps to install weave-net on EKS
2020-04-02 12:32:21 +01:00
Murali Reddy 438a5f5fd1 clarify pods connect to api server 2020-04-02 16:12:02 +05:30
Bryan Boreham b051ef0878 Merge pull request #3790 from weaveworks/npc-errors
Weave-npc: while logging differentiate between fatal and non-fatal errors
2020-04-02 11:24:10 +01:00
Murali Reddy 48015aa7be Weave-npc: while logging differentiate between fatal and non-fatal errors 2020-04-02 15:08:15 +05:30
Murali Reddy 14730f8572 Add release v2.6.2 2020-03-17 20:36:24 +05:30
Bryan Boreham e7a24eaf0a Merge pull request #3783 from weaveworks/issue-3781
send FastDatapathCryptoInitSARemote control message only if encryption is enabled
2020-03-12 10:09:26 +00:00
Bryan Boreham 15ad210bec Merge pull request #3782 from weaveworks/fix-pcap-timeout
Reduce pcap timeout to avoid overflow
2020-03-11 16:32:32 +00:00
Murali Reddy 6bc0e5e71c send FastDatapathCryptoInitSARemote control message only if encryption is enabled
Fixes #3781
2020-03-11 21:26:09 +05:30
Bryan Boreham 0ca831f50b Reduce pcap timeout to avoid overflow
The value is passed by google/gopacket into a signed 32-bit int, so we
must pick a timeout which is less than 2^31 microseconds.

See https://github.com/google/gopacket/issues/708
2020-03-11 12:21:07 +00:00
Murali Reddy 57bca8e955 Add release v2.6.1 2020-03-06 18:36:33 +05:30
Bryan Boreham 709f820ab6 Merge pull request #3763 from weaveworks/no-lock-round-send
Move send of ipsec message outside lock
2020-03-05 10:21:18 +00:00
Bryan Boreham 599b99a6c4 Merge pull request #3770 from weaveworks/fix-manifests
fix weave-kube manifests
2020-02-26 11:37:01 +00:00
Murali Reddy 4e3acfdc02 add note on apiserver being on EKS managed network 2020-02-26 10:29:50 +05:30
Murali Reddy 11915948a2 add steps to install weave-net on EKS 2020-02-26 10:27:01 +05:30
Bryan Boreham bb51a4f36d Merge pull request #3766 from weaveworks/static-ips-doc
Note different ways to ask for static IPs
2020-02-14 09:31:13 +00:00
Murali Reddy 5d0e44bb6f add missing dnsPolicy: ClusterFirstWithHostNet in weave-daemonset-k8s-1.11.yaml
update apiVersion from rbac.authorization.k8s.io/v1beta1 to rbac.authorization.k8s.io/v1
2020-02-11 13:15:33 +05:30
Bryan Boreham 6e7a469a62 Note different ways to ask for static IPs 2020-02-05 09:57:12 +00:00
Bryan Boreham ca0498b860 Fix warning log to use formatted variant 2020-01-28 15:15:28 +00:00
Bryan Boreham bbfa682083 Move send of ipsec message outside lock
The send may block, so do all changes to the forwarder object and
release the lock before attempting to send.
2020-01-28 15:13:33 +00:00
Bryan Boreham f763c40c10 Update connection limit in docs 2020-01-28 12:53:14 +00:00
Bryan Boreham 67037b43b0 Merge pull request #3760 from weaveworks/update-ruby-262
Update Ruby version for Netlify build
2020-01-27 17:46:51 +00:00
Bryan Boreham 861395011c Update Ruby version for the benefit of Netlify build
Picked 2.6.2 based on message from Netlify build:
"Included versions: 2.3.6 2.5.4 2.4.5 2.4.3 2.2.9 2.6.2"
2020-01-27 17:05:46 +00:00
Bryan Boreham 8bdfcd3042 Merge pull request #3747 from weaveworks/iptables1.8
support Iptables 1.8 with legacy and nf_tables support
2020-01-08 10:46:41 +00:00
Murali Reddy 83024b946f use softlinks to link iptables to backend specific commands and update docs 2020-01-08 15:44:22 +05:30
Murali Reddy 4f48670345 set iptables backend to use if specified explicitly or auto-detect 2020-01-08 15:44:10 +05:30
Murali Reddy 4b30d97d4e update alpine base image to 3.10 that has iptables ver 1.8.3 2020-01-08 15:43:51 +05:30
Bryan Boreham c9e813cfcb Merge pull request #3740 from weaveworks/raise-cpu-requests
Raise Kubernetes CPU requests from 10m to 50m
2019-12-13 12:27:24 +00:00
Bryan Boreham c97c50b76e Merge pull request #3735 from weaveworks/release-script-add-k11
Add weave-daemonset-k8s-1.11.yaml to release script
2019-12-13 11:37:09 +00:00
Bryan Boreham f919d06e2c Merge pull request #3745 from AlejoAsd/fix/site-kube-addon-md-link-fix
Fix kube-addon documentation broken markdown link
2019-12-13 11:32:47 +00:00
Bryan Boreham 526538d9d1 Merge branch 'master' into 2.6 2019-12-07 11:55:16 +00:00
Bryan Boreham f43f3fc2e8 Merge pull request #3744 from weaveworks/issue-3741
upgrade to newer terraform that is compatible with google cloud API
2019-12-07 11:54:47 +00:00
Alejo Carballude 8b220f6383 Fix kube-addon documentation broken markdown link. 2019-12-06 16:00:03 -03:00
Murali Reddy d44e34584a Update tools submodule to latest commit 2a2df527894bcaa5d42ad80654c43e1e5a6b03d7 2019-12-06 18:48:49 +05:30
Murali Reddy 6d2366ca4c upgrade to newer terraform that is compatible with google cloud API
Fixes #3741
2019-12-06 10:19:27 +05:30
Bryan Boreham 7c1b615c98 Add a note about dropping CAP_NET_RAW in Kubernetes 2019-12-04 21:04:55 +00:00
Bryan Boreham 390a4099d0 Merge branch '2.6' 2019-11-28 20:47:39 +00:00
Bryan Boreham 01237446eb Update docs to match new memory requests 2019-11-22 23:23:55 +00:00
Bryan Boreham 18deb42df1 Raise Kubernetes CPU requests from 10m to 50m
This setting is passed by Kubelet to the Linux scheduler to ask for a share of
available CPU, so we should ask for a bit more than 1% of 1 CPU. Otherwise if a
CPU is contended Weave Net will get throttled frequently.

Weave Net in fastdp mode shouldn't need a lot of CPU most of the time, but at
startup there is quite a lot to do.

The setting is also used by the Kubernetes scheduler to decide how much will fit
on a node, so setting it much higher will reserve CPU that we shouldn't need most
of the time.
2019-11-22 22:30:03 +00:00
Bryan Boreham 5c508f837e Add manifest for Kubernetes 1.11 and above 2019-11-11 10:15:53 +00:00
Bryan Boreham e000472af7 Release 2.6 2019-11-05 19:40:45 +00:00
Bryan Boreham 6d70284c21 Increase default connection limit to 200
Improvements in resource consumption in larger clusters mean we can
raise this limit.
2019-11-05 19:40:45 +00:00
Bryan Boreham 4529d1587c Release 2.6 2019-11-05 16:12:30 +00:00
Bryan Boreham b0d05f5e37 Increase default connection limit to 200
Improvements in resource consumption in larger clusters mean we can
raise this limit.
2019-11-05 14:21:24 +00:00
Bryan Boreham 4a5d203e58 Merge pull request #3732 from weaveworks/mesh-0-4
Update Weave Mesh library to 0.4
2019-11-05 14:21:07 +00:00
Murali Reddy 640c5c346c add mocks for GossipNeighbourSubset 2019-11-05 13:25:56 +00:00
Bryan Boreham 3780ce4dfb Update Weave Mesh library to 0.4 2019-11-05 12:26:14 +00:00
Bryan Boreham b871c1eecb Delete test binary committed in error 2019-11-05 12:16:45 +00:00
Bryan Boreham 02ecea4576 Merge pull request #3728 from weaveworks/issues/3727-fix-320-flake
Tell 'timeout' to use signal 9, so command dies immediately
2019-11-04 16:12:36 +00:00
Bryan Boreham 6876507641 Merge pull request #3712 from weaveworks/go-1-13-1
Update to Go 1.13.3
2019-11-04 16:11:48 +00:00
Bryan Boreham d2c78d3196 Tell 'timeout' to use signal 9, so command dies immediately
We were seeing flakes in test 320, seemingly because the 'docker run'
command would sometimes send a delete request for the container it had
started, before dying.

We need the container to carry on running so we can check it does get
attached when the cluster reaches quorum. Sending signal 9 means the
command dies immediately and does not get a chance to delete the
container.
2019-11-01 16:39:34 +00:00
Bryan Boreham 5b8365687e Merge pull request #3725 from weaveworks/retry-pending-claims
Retry IP allocator claims
2019-10-29 10:50:47 +00:00
Bryan Boreham a43bd88ddd Add the error message why an IP claim is denied 2019-10-25 17:13:59 +00:00
Bryan Boreham e8fcd21baa Retry IP allocator claims
It may be that we cannot talk to a peer straight away, so allow claims
to be retried a few times before giving up.
2019-10-25 17:13:11 +00:00
Michael Merrill 6a48da60ec Handling concurrent updates to configmap and IP reclamation (#3724)
checking if peer to be removed has been removed by another pod

Signed-off-by: mmerrill3 <michael.merrill@vonage.com>
2019-10-24 20:01:02 +01:00
Bryan Boreham 886dea9b10 Merge pull request #3715 from weaveworks/update-mesh
Update weaveworks/mesh to v0.3
2019-10-22 13:39:52 +01:00
Bryan Boreham 80e9dee9b2 Update CI image again 2019-10-22 11:19:51 +00:00
Bryan Boreham 5110a604f8 Bump to Go 1.13.3 2019-10-22 09:31:31 +00:00
Bryan Boreham 404f1bbef3 Bump image used in CI to Go 1.13.1 2019-10-15 09:29:38 +00:00
Bryan Boreham 56491b35f1 Go 1.13 needs different static linking flags
We don't need to pre-build the Go standard library or use -i flag
either - Go sorts that all out for us now.
2019-10-15 09:29:38 +00:00
Bryan Boreham dd70668b89 Update tools submodule to latest commit f041a74ffbf2 2019-10-15 09:29:38 +00:00
Bryan Boreham e5441b44e9 Bump Go version in build container to 1.13.1 2019-10-15 09:27:45 +00:00
Bryan Boreham 4da2501d7a Add sleeps in tests for topology gossip to propagate
The new weaveworks/mesh version defers topology updates by up to 1
second, so we can't expect to connect two nodes and immediately ping
between them.
2019-10-15 09:01:00 +00:00
Bryan Boreham 04680fc52c Update weaveworks/mesh to v0.3 2019-10-15 09:01:00 +00:00
Bryan Boreham cb4a8769a8 Merge pull request #3708 from weaveworks/3693-split-ranges
Handle range wrap-around when checking for allocations
2019-10-15 09:19:37 +01:00
Bryan Boreham 62c1d28524 Merge pull request #3716 from weaveworks/870-flake
Randomise wait to reclaim IPs on node deletion, and fix flaky test 870
2019-10-15 09:17:04 +01:00
Bryan Boreham 92b21ccd44 Merge pull request #3710 from weaveworks/exclude-self
Exclude myself when building a list of peers that may need deleted
2019-10-15 08:41:21 +01:00
Bryan Boreham 88cd86a5f2 Add checksum file for s390x qemu binary 2019-10-12 12:45:17 +00:00
Bryan Boreham b18c88524d Merge branch '2.5' 2019-10-12 11:10:09 +00:00
Bryan Boreham 90e0c43bf2 Add a note on how to secure the Kubernetes Addon configuration.
Original author Vladimir Pouzanov <farcaller@google.com>
2019-10-12 11:08:57 +00:00
Bryan Boreham 4215618177 Merge pull request #3447 from farcaller/patch-1
Add a note on how to secure the configuration.
2019-10-12 12:02:46 +01:00
Bryan Boreham cb5798f94d Merge pull request #3697 from christian-2/system-node-critical
mark pods weave-net with priorityClassName: system-node-critical
2019-10-12 12:00:13 +01:00
Bryan Boreham 79e032c984 Reduce time test script waits for IPs to be reclaimed
Now we have a callback when a node is removed, there should be no
reason to wait 90 seconds.

The reclaim does wait up to 5 seconds before starting, so allowing 10
seconds in the script should be sufficient.
2019-10-11 20:29:58 +00:00
Bryan Boreham 821b787774 Move printing of node addresses after reclaim loop
Otherwise we see all the node addresses in the middle of the log.
2019-10-11 20:29:58 +00:00
Bryan Boreham 3ed7894e39 Debug log the node-deletion event
So we know when it came in, also which node.
2019-10-11 20:29:58 +00:00
Bryan Boreham 30ed34bd2c Shut down Kubernetes in test of deleted node 2019-10-11 20:29:58 +00:00
Bryan Boreham f5c2f51964 Use a different seed for random numbers each run
Without this, each run gets the same random numbers so all nodes are
racing to remove the deleted node.
2019-10-11 20:29:58 +00:00
Bryan Boreham 4d7f0f5014 Merge pull request #3685 from linux-on-ibm-z/s390x-crossbuild-support
Build with Go 1.12.7; Added support for crossbuilding s390x binaries and images
2019-10-10 18:00:23 +01:00
Bryan Boreham d1ed6c5747 Exclude myself when building a list of peers that may need deleted
We already avoid actually doing the delete, but adding this check
stops the program logging that it was thinking about it.
2019-10-10 13:22:20 +00:00
Bryan Boreham 44f91950cb Improve logging of ring merge
Turn some Sprint() calls into `%v` in the outer format string.
Remove one debug log line on duplicate token, since that info is already logged.

Add an Info log line when we accept another peer's token, since that
should be a rare event, and it's important if we've made a mistake.
2019-10-10 11:14:41 +00:00
Bryan Boreham d2f0287fa3 Handle range wrap-around when checking for allocations
Ring wraps around at zero but Space doesn't know about this, so we
have to normalise ranges coming out of Ring.  In turn we may need to
split one range into two, across the end of the Ring.
2019-10-10 11:14:41 +00:00
Bryan Boreham 9c09e36135 refactor: extract function to normalise a single range that may span zero 2019-10-10 11:13:47 +00:00
Bryan Boreham cb8e06c994 Merge branch '2.5' 2019-10-03 16:58:07 +00:00
Bryan Boreham 753c7cce1e Merge pull request #3705 from weaveworks/buffer-docker-events
Use buffered chan to avoid losing docker events
2019-10-03 14:01:14 +01:00
Bryan Boreham 30b2bada28 Merge pull request #3701 from weaveworks/issues/3698-alpine-3-8
Bump Alpine version to 3.8
2019-10-02 15:52:06 +01:00
Bryan Boreham eeec3833a3 Merge pull request #3692 from sidharthsurana/fix-dnspolicy
Change the dnsPolicy for the weave-net pods to ClusterFirstWithHostNet
2019-10-02 14:57:27 +01:00
Bryan Boreham ee47f0c3ee Use buffered chan to avoid losing docker events
Docker imposes a limit that events have to be retrieved within 100ms
or they are dropped on the sending side. Adding buffer space within
the Weave Net process allows those events to be collected from Docker
more quickly.

1024 is an arbitrary number, much higher than we expect to need.
2019-09-30 15:16:24 +00:00
Bryan Boreham 36a2146ed8 Bump Alpine version to 3.8 2019-09-23 18:17:53 +00:00
christian-2 6afedb881c mark pods weave-net with priorityClassName: system-node-critical
* fixes #3691
* `weave-daemonset-k8s-1.11.yaml` is `weave-daemonset-k8s-1.9.yaml` plus `priorityClassName: system-node-critical`
* notice that a Kubernetes cluster created with `kubeadm` has its `kube-proxy`s marked as `system-node-critical` (and several other pods, such as `kube-apiserver` marked as `system-cluster-critical`)
2019-09-04 14:16:46 +02:00
Bryan Boreham 05ab1139db Merge pull request #3669 from hpdvanwyk/issue-3666
Fix incorrect xfrm policy being deleted by ipsec.Destroy().
2019-09-02 11:48:08 +01:00
Sidharth Surana e90cbf290b Change the dnsPolicy for the weave-net pods to ClusterFirstWithHostNet 2019-08-30 10:12:57 -07:00
Bryan Boreham 1e0431f6b2 Merge pull request #3674 from weaveworks/weave-daemonset
delete weave-daemonset.yaml
2019-08-30 10:25:45 +01:00
Bryan Boreham 9971fc3dac ÂAdd a note about incompatibility with iptables 1.8 2019-08-29 16:24:07 +00:00
Bryan Boreham 7aa7e3c00d Merge pull request #3654 from kitt1987/fix-issue-3653
Fix iptable rules generated for Ingress NetworkPolicy when both port and IP block specified
2019-08-29 14:46:35 +01:00
Bryan Boreham a4dd7fa198 Merge branch '2.5' 2019-08-29 13:38:15 +00:00
Bryan Boreham e2157a5d04 Merge pull request #3676 from hpdvanwyk/issue-3675
Do not do ipsec.InitSARemote on a stopped fastDatapathForwarder.
2019-08-29 13:58:37 +01:00
Daniel Holbach fc199d0df5 Answer how Weave Net works
Actually Bryan answered it, when a reader of our website asked.

Signed-off-by: Daniel Holbach <daniel@weave.works>
2019-08-29 12:36:32 +00:00
Bryan Boreham cc6d10c9b1 Pin busybox version to 1.28 to avoid CI issues 2019-08-29 12:23:25 +00:00
Bryan Boreham ace2c12608 Merge pull request #3660 from Pensu/daemonset_api
Move daemonset API to apps/v1
2019-08-29 13:11:57 +01:00
Bryan Boreham 57c464d60e Merge pull request #3679 from weaveworks/how-does-it-work
Answer how Weave Net works
2019-08-29 12:48:37 +01:00
Daniel Holbach 65b3894a8e Answer how Weave Net works
Actually Bryan answered it, when a reader of our website asked.

Signed-off-by: Daniel Holbach <daniel@weave.works>
2019-08-29 11:47:28 +00:00
Bryan Boreham 77bfa6a7e4 Remove references to weave-daemonset.yaml from release script and docs 2019-08-29 11:37:55 +00:00
Murali Reddy 9d485d0f21 delete weave-daemonset.yaml which predates the manifest weave-daemonset-k8s-1.6/1.7/1.8.yaml
naming is counter intutive
2019-08-29 11:37:55 +00:00
Peeyush Gupta 991945081a Move daemonset API to apps/v1 2019-08-29 13:57:16 +05:30
Bryan Boreham 123762ec8d Merge pull request #3673 from weaveworks/slack-channel
add net-dev as channel to ask question regarding weave-net
2019-08-28 11:13:15 +01:00
Bryan Boreham b07db6479a Merge pull request #3655 from tanishq-dubey/master
Add tolerations for nodes tainted with NoExecute
2019-08-28 11:11:26 +01:00
Bryan Boreham d3f62905b7 Merge pull request #3683 from ReillyProcentive/fix-issue-3342
Add wrapper script to weave-npc
2019-08-28 11:03:30 +01:00
Bryan Boreham 22b3393cfd Merge pull request #3689 from weaveworks/3680-pin-busybox
Pin busybox version to 1.28 to avoid CI failure in Python test
2019-08-19 14:08:05 +01:00
Bryan Boreham c8e7dbd600 Pin busybox version to 1.28 to avoid CI issues 2019-08-14 13:59:41 +00:00
Reilly Brogan ef26b306e4 Forgot to make this change 2019-08-08 14:52:29 -05:00
Reilly Brogan 1588a7259d add newline 2019-08-08 14:43:48 -05:00
Reilly Brogan 3a92050ebb Add weave-npc wrapper script 2019-08-08 14:42:56 -05:00
guirish 04c63879b8 Added support for crossbuilding s390x binaries and images 2019-08-07 09:04:05 -04:00
Hendrik van Wyk 96291d1de4 Do not do ipsec.InitSARemote on a stopped fastDatapathForwarder.
Fixes 3675

It is possible for ipsec.InitSARemote to be called after ipsec.Destroy.
If an xfrm policy for that source/destination pair exists it will be
updated to the SPI from the Destroyed connection causing IPSEC to stop
working.
2019-07-31 11:17:37 +02:00
Murali Reddy 9090fddd9f add net-dev as channel to ask question regarding weave-net
Fixes #3667
2019-07-31 11:33:10 +05:30
Hendrik van Wyk 5bcd33c930 Fix incorrect xfrm policy being deleted by ipsec.Destroy().
Added a check to make sure the xfrm policy has not yet been updated to
a new spi. The ipsec mutex is held at this point so nothing else should
be modifying this policy.
2019-07-26 11:59:11 +02:00
Tanishq Dubey 959d0bf2e2 Add tolerations for nodes tainted with NoExecute 2019-06-30 00:27:57 -04:00
Kitt Hsu a547d4571c Fix the source of iptable rules generated for Ingress NetworkPolicy when both port and IP block specified 2019-06-28 15:02:22 +08:00
Bryan Boreham b05c5f63c8 Merge pull request #3647 from weaveworks/nsselector
add support for combination of podSelector and namespaceSelector in network policies
2019-06-14 14:25:02 +01:00
Bryan Boreham 309a85b29c Merge pull request #3637 from weaveworks/issue-1962
resolve inconsistencies detected during ring merge
2019-06-14 14:24:36 +01:00
Murali Reddy 90ccc4a014 use space to check if entry in a range has allocations while doing ring merge 2019-06-07 18:12:35 +05:30
Murali Reddy a6f2ee5ccc add seperate match function to matach pod/namespace/namespacedpod selectors 2019-06-07 11:52:40 +05:30
Bryan Boreham dcadc0f8cc Merge pull request #3648 from weaveworks/k8s-src-ip
Fix the incorrect case #4 in k8s-src-ip.md
2019-06-06 11:04:39 +01:00
Murali Reddy 332808c524 add details of kube-proxy mode iptables/ipvs and falgs 2019-06-06 11:05:25 +05:30
Murali Reddy db006060e6 Fix the incorrect case #4 in k8s-src-ip.md
With cluster IP, traffic is masquraded only when --masquerade-all option is specified
or --cluster-cidr is specified and the source is not from the cluster CIDR range

https://github.com/kubernetes/kubernetes/blob/v1.14.2/pkg/proxy/iptables/proxier.go#L842
2019-06-03 10:20:15 +05:30
Murali Reddy 7a6ba40982 fix unit test failures 2019-05-30 15:58:18 +05:30
Murali Reddy 75e106b667 using an explicti selector set for network policies with both namespace and pod lable selectors 2019-05-30 12:03:28 +05:30
Bryan Boreham b28e2ee384 Merge branch '2.5' 2019-05-29 08:08:41 +00:00
Bryan Boreham 785b6b4584 Merge pull request #3646 from weaveworks/npcdesign
update weavenpc design document to reflect current design
2019-05-29 09:08:19 +01:00
Murali Reddy 391613d015 add details of ipset used for ipblock's excpet list 2019-05-29 08:04:23 +00:00
Murali Reddy 7334869134 update weavenpc design document to reflect current design 2019-05-29 08:04:18 +00:00
Murali Reddy bb4f51499d add support for combination of podSelector and namespaceSelector
in network policies

- enhance selectorSpec to accomodate both pod and namespace selectors
- enhance analysePolicy to handle policies with both selectors

Fixes #3312
2019-05-28 12:40:39 +05:30
Murali Reddy cc88aa2145 Merge branch '2.5' 2019-05-16 18:11:30 +05:30
Murali Reddy 4b5d827d94 Add release v2.5.2 2019-05-16 11:42:47 +05:30
Bryan Boreham 802ede1cd3 Merge branch '2.5' 2019-05-14 09:06:15 +00:00
Murali Reddy 5e69e8a7b4 check for allocations in the range that got transffered when its split 2019-05-13 20:02:36 +05:30
Murali Reddy 2d912263b1 add ring debug log during merge() 2019-05-13 12:43:19 +05:30
Bryan Boreham 6e78a34a00 Merge pull request #3638 from weaveworks/pruneowned
return error in case Weave CNI plug-in fails to perform CmdDel
2019-05-10 15:32:47 +01:00
Murali Reddy ac9d72875d ignore the error on IPAM delete for the container with 0 addresses 2019-05-10 17:25:58 +05:30
Murali Reddy 51d7f455c9 move code to reset the entry free space from entries.merge() to Ring.Merge() 2019-05-10 17:23:45 +05:30
Murali Reddy 89db74338e during merge we receive update to an entry that ring owns, and has a newer version, set our version to the one received plus one, effectively imposing our existing entry 2019-05-09 16:05:22 +05:30
Bryan Boreham 4c6879679d Merge pull request #3639 from weaveworks/allowegress
lazily add iptables rule to drop egress traffic from the pods only if network policies are applied
2019-05-07 14:38:39 +01:00
Bryan Boreham d35f2236e1 Merge pull request #3603 from weaveworks/pmtu-message
Improve 'expecting PMTU update' message with address
2019-05-07 14:34:12 +01:00
Bryan Boreham 27848992b1 Merge branch '2.5' 2019-05-07 13:32:55 +00:00
Bryan Boreham 690b6ff2cd Merge pull request #3623 from weaveworks/ensure-cml-initialised
Avoid panic on nil map in reclaimPeer()
2019-05-07 14:30:40 +01:00
Murali Reddy ea2084d871 return from further processign networkpolicy if base rule failed to gets created 2019-05-06 16:27:38 +05:30
Bryan Boreham 8a4fc9c02a Fix peer-list fuzz test to re-fetch list when it may be nil 2019-05-03 17:25:36 +00:00
Bryan Boreham 760bc10074 Merge pull request #3629 from weaveworks/issue-3628
gossip broadcast updated ring on donating a range to other peer
2019-05-03 16:32:23 +01:00
Bryan Boreham 20d55fe47a Moved 'expecting PMTU' message to debug level 2019-05-03 15:28:44 +00:00
Murali Reddy 4a1fbc7c38 lazily add iptables rule to drop egress traffic from the pods only
if network policies are applied

does not address #3464 but just avoids the issue atleast for those who
dont use network policies
2019-05-03 18:40:59 +05:30
Murali Reddy 11c55a3a07 fix lint 2019-05-03 10:55:13 +05:30
Murali Reddy a400d43df7 resolve inconsistencies detected during ring merge
Fixes #1962
2019-05-03 10:55:13 +05:30
Bryan Boreham 189cfa995c Merge pull request #3630 from weaveworks/logringupdates
add debug log for ipam ring and entry updates
2019-04-30 10:25:39 +01:00
Bryan Boreham 47d8f24e56 Merge pull request #3635 from weaveworks/issue-3632
bump up the version of entry by large value so that transfer of range takes precedence
2019-04-30 10:24:53 +01:00
Murali Reddy 4f8fe2c13f gossip broadcast updated rin on donating a range to other peer
Fixes #3628
2019-04-26 15:21:23 +05:30
Murali Reddy 873781ab58 bump up the version of entry by large value so that transfer of range
takes precedence (if there is any conflict in merging entry) over
other operations on the entry that increments the version

Fixes #3612
2019-04-26 15:15:47 +05:30
Murali Reddy 06e0e6ace0 add debug log for ipam ring and entry updates
Fixes #3627
2019-04-09 12:39:16 +05:30
Bryan Boreham eb7ba691ee Fetch storedPeerList after read from Kubernetes
This avoids a race condition where the peer has added itself to the
list and the annotation since we read storedPeerList.
2019-04-02 09:11:27 +00:00
Bryan Boreham 15b9b7416a Re-read peers ConfigMap from Kubernetes at start of every reclaim
A previous reclaim may have left the map set to nil.
2019-03-26 17:25:34 +00:00
Bryan Boreham 5024270232 Avoid panic on nil map
It can be set to nil after a failed update; check rather than crashing.
2019-03-26 17:20:24 +00:00
Bryan Boreham bd24dd7dae Make test harness and comments match Kubernetes behaviour on conflict error
Kubernetes always returns nil on error; somehow I had the wrong idea
here.
2019-03-26 17:19:22 +00:00
Bryan Boreham 2c2a074a83 Merge branch '2.5' 2019-03-26 16:49:33 +00:00
Bryan Boreham 698e1b6d87 Improve 'expecting PMTU update' message with address
Also remove "EMGSIZE" because it looks like an error in the log file.
2019-02-27 08:49:42 +00:00
Bryan Boreham b248e021ec Merge pull request #3457 from weaveworks/release-process-update
Update release process doc with minor details
2019-02-13 12:06:54 +00:00
Bryan Boreham 0d481ef0e9 Merge pull request #3597 from weaveworks/grammaticalChangesToReadme
small grammatical changes to readme
2019-02-13 10:51:56 +00:00
Dimitri Mitropoulos 0c2e046c86 makes passive voice more explicit 2019-02-12 15:54:55 -05:00
Dimitri Mitropoulos 21bc724632 breaks long sentence (with dangling subject) into two sentence
ask yourself: does `enables` refer to `this repository` or `weave net`, and it should become clear that it's unclear at best.  if you take out the parentheticals, it reads:

> This repository contains Weave Net enables you to get started...

breaking into two sentences helps smooth this bumpiness.
2019-02-12 15:50:29 -05:00
Dimitri Mitropoulos 16051a89b6 removes unnecessary line return
which, remember, github's markdown parser is going to ignore anyway
2019-02-12 15:46:06 -05:00
Dimitri Mitropoulos 6130699ae5 removes extraneous trailing space 2019-02-12 15:45:22 -05:00
Bryan Boreham e23e364476 Merge pull request #3594 from weaveworks/document_weave_log_warning_and_error_levels
Document weave log warning and error levels
2019-02-07 16:38:46 +00:00
Jerry Jackson 8a5aa1a6ae Document weave log warning and error levels 2019-02-07 08:19:46 -07:00
Bryan Boreham 9654df4d50 Merge pull request #3585 from weaveworks/0peers
handle single node case where return peer list from kube-utils is empty
2019-02-04 14:57:13 +00:00
Bryan Boreham 6f39a15b53 Merge pull request #3589 from weaveworks/release-docs
fix use of manifest tool in release process
2019-02-04 13:45:23 +00:00
Bryan Boreham e8f35a848e Merge pull request #3590 from mkumatag/update_gopacket
Vendor update gopacket and unix package
2019-02-03 13:00:54 +00:00
Manjunath A Kumatagi 43d3339b39 Vendor update gopacket and unix package 2019-02-01 21:28:56 -06:00
Murali Reddy 13644ee1b0 fix use of manifest tool in release process 2019-01-29 12:58:09 +05:30
Murali Reddy 54d24e65ef Merge branch '2.5' 2019-01-21 19:40:21 +05:30
Murali Reddy b8bce1c28f Add release v2.5.1 2019-01-21 13:14:17 +05:30
Bryan Boreham e1e4a7887a Merge branch '2.5' 2019-01-18 11:20:25 +00:00
Bryan Boreham 9f0ac3dbe7 Merge pull request #3582 from weaveworks/print-peers-error
Check and report the error return from getKubePeers()
2019-01-18 10:56:33 +00:00
Murali Reddy 17b45d9efa handle single node case where return peer list from kube-utils is empty
fixes side affet introduced in #3454
2019-01-18 01:06:37 +05:30
Bryan Boreham 27178b1c79 Check and report the error return from getKubePeers() 2019-01-15 11:15:36 +00:00
Matthias Radestock 1bf07d86aa Merge pull request #3576 from dholbach/drop-email
weave-users mailing list is closed
2019-01-07 12:33:13 +00:00
Daniel Holbach bba7b44248 weave-users mailing list is closed: https://groups.google.com/a/weave.works/forum/#!topic/weave-users/0QXWGOPdBfY
Signed-off-by: Daniel Holbach <daniel@weave.works>
2019-01-07 17:55:48 +05:30
Bryan Boreham d4d9ba1e35 Merge pull request #3454 from weaveworks/self-peer
prevent kubernetes node connecting to self
2019-01-03 16:16:49 +00:00
Bryan Boreham f6c22ef9b5 Merge pull request #3573 from Rich-Core/revert-ruby-version
Revert Ruby version to 2.3.0
2018-12-24 11:59:12 +00:00
Rich Powell 040cb19fc5 Reverted Ruby version to 2.3.0 2018-12-21 17:19:00 +00:00
Bryan Boreham 928d08fb19 Merge pull request #3413 from weaveworks/connlimit
document connection limit
2018-12-05 12:17:02 +00:00
Murali Reddy f82440f792 modification to reflect CONN_LIMIT only for Kubernetes 2018-12-05 16:14:41 +05:30
Murali Reddy ad2dc562af document connection limit
Fixes #3395
2018-12-05 15:52:57 +05:30
Bryan Boreham ab1953e8ca Merge pull request #3461 from dholbach/fix-kubeaddon-link
fix link to kube-addon doc
2018-12-05 10:21:06 +00:00
Bryan Boreham a332af3146 Merge pull request #3453 from weaveworks/issue-3449
add --physdev-is-bridged flag when using physdev module for iptables
2018-12-05 10:18:21 +00:00
Bryan Boreham 5e271363cf Merge pull request #3458 from weaveworks/ruby-236
Update Ruby version to match Weaveworks website
2018-12-04 10:13:40 +00:00
Murali Reddy d2a9a51296 follow project conventions in ordering the imports 2018-12-04 10:58:43 +05:30
Murali Reddy 99e360ce3b skip egress network policies for the traffic node->bridge ip 2018-12-04 09:43:50 +05:30
Daniel Holbach 1c855f9bc1 fix link - thanks Manish on Slack for noticing
Signed-off-by: Daniel Holbach <daniel@weave.works>
2018-11-26 10:25:34 +01:00
Bryan Boreham 6b6580413d Update Ruby version to match Weaveworks website
This file is read when generating previews on Netlify.
2018-11-22 14:29:00 +00:00
Bryan Boreham 583eea1ec5 Update release process doc with minor details 2018-11-22 14:26:18 +00:00
Murali Reddy 81b17469f4 prevent kubernetes node connecting to self by excluding the node IP from the list of the peers passed to weaver
Fixes #3398
2018-11-21 11:47:30 +05:30
Murali Reddy 06669325a7 add --physdev-is-bridged flag when using physdev module for iptables
rules created by weave-npc to prevent warning in kernel logs

Fixes #3449
2018-11-20 13:34:10 +05:30
Vladimir Pouzanov 1c81fcb693 Change the wording in the header, add trusted-subnets note 2018-11-12 14:38:25 +00:00
Vladimir Pouzanov 4a22dda13f Add a note on how to secure the configuration. 2018-11-06 17:25:53 +00:00
Bryan Boreham 6e3f8a1c7a Add release v2.5.0 2018-11-05 15:34:36 +00:00
Bryan Boreham eb77970534 Make build image depend on tools subdir
Missed from 0164d24583
2018-11-05 15:33:37 +00:00
Bryan Boreham f53dfdea61 Merge pull request #3442 from weaveworks/issues/3336-promisc
net: Do not set bridge hw addr when creating it
2018-11-01 21:09:34 +00:00
Martynas Pumputis 6c58bd7815 net: Do not set bridge hw addr when creating it
Prior "bridge: Change local fdb entries whenever mac address of bridge device changes" [1],
FDB entry for a bridge was not inserted when creating the bridge and it could
only be inserted when a hw address of the bridge was changed. Therefore, on
an older than the 3.14 kernel containers were not able to reach
the "weave" bridge w/o setting the promiscuous mode on.

This should have hit hard Kubernetes users as the weave bridge in their
case is used as a default gateway, and thus it works only after manually
enabling the promiscuous mode.

Additionally, w/o the promiscuous mode a packet sent from a container and
destined to the gateway is flooded on all ports, so it can reach
the "datapath" device resulting in the "Vetoed installation of hairpin flow" error.

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a4b816d8ba1c1917842dc3de97cbf8ef116e043e
2018-11-01 18:58:59 +02:00
Bryan Boreham 83d9292a5b Merge branch '2.4' 2018-11-01 14:19:09 +00:00
Bryan Boreham 37bc04f851 Fix master deploy step: run newer manifest-tool and build all architectures
The version of manifest-tool in `weshigbee/manifest-tool` is version
0.3.0 and is erroring on every build; latest is 0.8.0 and doesn't error.

Since we are no longer limited to what will run in a container at
CircleCI, also build all architectures.
2018-11-01 12:26:49 +00:00
Bryan Boreham a5161b28f5 Merge pull request #3399 from weaveworks/rmpeer
watch for Kubernetes node delete events and reclaim removed peers IP space on delete event
2018-11-01 11:08:53 +00:00
Bryan Boreham c6cd5f53db Merge pull request #3439 from Ashiroq/master
Change log-level to debug for proxy access
2018-11-01 11:07:47 +00:00
Bryan Boreham 29bbd321b4 Merge pull request #3431 from weaveworks/issue-3324
add checkpoint to include Kubernetes cluster information
2018-11-01 11:06:47 +00:00
Bryan Boreham ba469bd641 Merge pull request #3415 from weaveworks/db-panic
prevent a case where tryOps endsup called recursivley when persisted data exists but has empty data
2018-11-01 11:05:06 +00:00
Murali Reddy bc9939fcdc add delay before checking ipam status 2018-11-01 14:51:19 +05:30
Murali Reddy c48c746791 replace peerlist with current set of Kubernetes nodes 2018-10-31 18:06:48 +05:30
Murali Reddy d3c5241f12 addressing review comments 2018-10-31 17:26:55 +05:30
Adrian Suwała 4d4584db2b Change log-level to debug for proxy access 2018-10-30 14:46:26 +01:00
Murali Reddy 427d694e1b add checkpoint to include Kubernetes cluster information
Fixes #3324
2018-10-30 13:33:12 +05:30
Murali Reddy f16d4561e0 remove realunch weave pod to test the unreachable_ip_addresses_count 2018-10-30 12:34:28 +05:30
Murali Reddy f334575e69 perform weave connect replace on node delete with empty peer list 2018-10-30 11:54:59 +05:30
Murali Reddy ea423755cc review comment: removing unnessary verbose code 2018-10-30 10:56:05 +05:30
Bryan Boreham db697fdaa5 Merge pull request #3435 from weaveworks/issues/fix-golint-import-path
Fix and improve build/Dockerfile
2018-10-29 16:37:53 +00:00
Martynas Pumputis c3aa03229c Use https for downloading libpcap 2018-10-26 10:07:50 +03:00
Martynas Pumputis 637bdf66b1 Change golint import path
See https://github.com/golang/lint/issues/415
2018-10-26 09:57:42 +03:00
Murali Reddy 4a40380d0f addressing review comments 2018-10-24 13:45:35 +05:30
Murali Reddy df467be26e watch for node delete events and call reclaimRemovedPeers 2018-10-24 13:45:35 +05:30
Murali Reddy edba711283 update client-go to include informeres, listers 2018-10-24 13:45:35 +05:30
Bryan Boreham 1b01da45f5 Merge pull request #3430 from weaveworks/bump-go-odp
Bump go-odp dependency
2018-10-17 18:03:44 +01:00
Bryan Boreham bf9985b0c8 Merge pull request #3423 from weaveworks/issue-3344
Replace weave-local-pods ipset with physdev iptables rule
2018-10-17 18:03:26 +01:00
Murali Reddy 408e5f7bdd make error message more appropriate 2018-10-17 21:16:52 +05:30
Martynas Pumputis 46177657b2 Bump go-odp dependency
To include the fix https://github.com/weaveworks/go-odp/pull/7.
2018-10-17 15:23:38 +03:00
Murali Reddy d351b9f020 remove weave-local-pods ipset which no longer used by weave-npc 2018-10-17 15:34:46 +05:30
Bryan Boreham 727fe46b2a Merge pull request #3385 from weaveworks/retry_forwarder
Add logic to re-try chooseBest() (which will select best forwarder)
2018-10-16 16:37:31 +01:00
Bryan Boreham b10af5a6cb Fix golint path - it moved upstream 2018-10-16 14:04:33 +00:00
Bryan Boreham 965b5c627e Merge pull request #3421 from weaveworks/2018-09-28-moar-initialDelaySeconds
kubernetes: Morph the livenessProbe into readinessProbe
2018-10-16 14:46:34 +01:00
Murali Reddy d00e7335bb dont maintain weave-local-pods ipset on pod add/delete/update 2018-10-16 14:02:23 +05:30
Murali Reddy e3eb16a1f9 addressing review comments 2018-10-09 11:21:47 +05:30
Bryan Boreham 078b76f3f1 Merge pull request #3416 from weaveworks/issue-3386
own action to reclaim when peer does not exist
2018-10-05 09:27:46 +01:00
Murali Reddy 6b2631e378 addressing review comment. keep forwarder running forever even on heart beat timeouts 2018-10-05 09:47:23 +05:30
Murali Reddy 59c1abe9b9 addressing review comments 2018-10-04 14:08:56 +05:30
Murali Reddy 4f9f0dfc3e Replace weave-local-pods ipset with physdev iptables rule
by-pass ingress network policy chains and accept the packet if
destination is not one of the local pods

return the packets so the egress network policy chains are skipped
in case packet's source is not one of the local pods

Fixes #3344
2018-10-02 11:02:36 +05:30
Damien Lespiau 8d44f49edd kubernetes: Morph the livenessProbe into readinessProbe
The liveness probe has the not-so-great side effect of killing the weave pods
if anything goes wrong, making debugging really difficult.

Not only that, we also bumped into the livenessProbe killing pods before they
had a chance to start (see below for the full story).

The readinessProbe is only used for Kubernetes Services: no traffic will be
routed to non-Ready pods when using the Service IP. We can use to to signal the
user something in wrong with Weave Net while not having Kubernetes delete the
pods behind our backs.

I removed the ininitialDelaySeconds field as Kurbernetes won't kill the pod if
not ready.

Notes from a debugging session:

Some nodes may have a vast amount of iptables rules, making each iptables
command take a few seconds (~5-10s). At startup, when the weave container
creates its chains, it runs quite a few iptables commands and the total time of
execution was > 30s.

It's important to note that, at this point, the weave process hasn't started as
those iptables commands are run by an initial script.

Kubernetes was trying to check for the container liveness, was failing, and
then proceeded to kill the weave pods before they had a chance to fully start.
2018-09-28 15:50:39 +01:00
Murali Reddy 7a959df648 handles an edge case where peer claimed to own the action (to reclaim) but no longer
exists hence lock persists foever, fix makes a peer own the reclaim when nonexistent node found

Fixes #3386
2018-09-27 16:00:44 +05:30
Bryan Boreham 53fd33044a Merge pull request #3412 from weaveworks/gke
add rbac prerequisite for using weave net on GKE
2018-09-26 14:41:59 +01:00
Murali Reddy 1806ca5665 add rbac prerequisite for using weave net on GKE
fixes #3111
2018-09-26 18:51:40 +05:30
Murali Reddy 7141ccc271 prevent a case where tryOps endsup called recursivley when persisted data exists
but has empty data

Fixes #3067
2018-09-26 16:10:06 +05:30
Bryan Boreham a73330f752 Merge branch '2.4' 2018-09-26 10:20:04 +01:00
Bryan Boreham 427e7a6868 Merge pull request #3408 from weaveworks/issues/3405-tracker-nil-deref
ipam: Do not deref nil in GET /ipinfo/tracker if tracker doesn't exist
2018-09-25 12:29:03 +01:00
Murali Reddy b3cb38eda4 addressing review comments 2018-09-24 17:53:28 +05:30
Murali Reddy 62758ca337 log the heartbeat send/recieve/miss 2018-09-21 16:45:47 +05:30
Murali Reddy 3c67c3c5f1 changes differentiate beteween fatal errors (for e.g. ipsec init)
from transient errors (heartbeast misses). In case of transient
errors OverlayForwarder is marked to be unhealty. When overlay forwarder
is unhealty its hept on hold so chooseBest() will skip selecting the forwrder

Once OverlayForwarder is considered healthy run chooseBest() again so the
forwarder can be selected if its the best forwarder

Fixes #1737
2018-09-21 16:45:47 +05:30
Martynas Pumputis 79f77f94f4 ipam: Do not deref nil in GET /ipinfo/tracker if tracker doesn't exist
In some cases, we do not create any IPAM tracker, which leads
to a panic when GET'ing /ipinfo/tracker.
2018-09-21 13:29:03 +03:00
Bryan Boreham fc759e2df9 Merge branch '2.4' 2018-09-13 16:59:03 +00:00
Bryan Boreham 1fcd521f67 Add release v2.4.1 2018-09-13 15:25:47 +00:00
Martynas Pumputis 66bd443183 Merge remote-tracking branch 'origin/2.4' 2018-09-12 18:25:30 +03:00
Martynas Pumputis fa74e9f290 Merge pull request #3400 from weaveworks/issues/3384-peerlist-race
Fix two race conditions in Kubernetes IPAM reclaim

Fix #3384
2018-09-12 18:13:56 +03:00
Bryan Boreham 008eeb03ad Improve comments and error checking 2018-09-12 14:11:09 +00:00
Bryan Boreham 41c48dc678 Update test to call reclaimPeer() 2018-09-12 14:11:09 +00:00
Bryan Boreham 09be35dee0 Fetch stored peer list every time round the retry loop
This ensures we take account of other peers' updates and closes a race
condition whereby another peer's changes can be overwritten.
2018-09-12 14:11:09 +00:00
Bryan Boreham c3ad641d94 Refactor: extract reclaimPeer() function 2018-09-12 14:11:09 +00:00
Bryan Boreham bacb3952a3 Fetch Kubernetes node list every time round reclaim loop
If we retain the Kubernetes list for a long time we might see a peer
appear in the Weave list and conclude it has been deleted. We must
always fetch the Kubernetes list after fetching the Weave list, during
deletion.
2018-09-12 14:10:59 +00:00
Bryan Boreham 70257a6c19 Add test for kube-utils peer list
- In parallel on several goroutines, randomly add and remove peers.
 - Maintain the test's own idea of current state.
 - Check that the test's state and kube-utils' state are consistent.
2018-09-12 12:37:16 +00:00
Bryan Boreham bfe9f00e55 Fake kubernetes API which implements optimistic locking
Mostly copied from kubernetes/client-go files
2018-09-12 12:37:16 +00:00
Bryan Boreham 591be2d08f Refactor: Introduce an interface so weave client can be mocked 2018-09-12 12:37:16 +00:00
Bryan Boreham c3ce052cc5 Refactor: use Kubernetes.Interface instead of *Clientset
So we can call with a mock for testing
2018-09-12 12:35:34 +00:00
Bryan Boreham 7dcd4bdf47 Refactor: extract peerlist fns to new file 2018-09-12 12:35:34 +00:00
Bryan Boreham 2d8373249a Vendor mock Kubernetes APIs for testing 2018-09-12 12:35:33 +00:00
Bryan Boreham 4979ce1f5f Update to dep v5
This adds more metadata to Gopkg.lock, and seems to have deleted a few
more files.
2018-09-12 12:35:33 +00:00
Martynas Pumputis 79d812a9c2 Merge remote-tracking branch 'origin/2.4' 2018-09-12 13:58:08 +03:00
Martynas Pumputis 78e00f9a3a Merge pull request #3397 from weaveworks/issues/3394-delete-old-me
Reclaim IPs when node name is re-used
2018-09-12 13:57:12 +03:00
Bryan Boreham 2ff0bbe150 Reclaim IPs when node name is re-used
Change the map used to reclaim peers so it is indexed by PeerName
which should be unique over time, rather than NodeName which can be
re-used.  Create an auxilliary set of NodeNames to help.

This way, if we can see that a different peer was previously running
with the same node name, it can be included for reclaim.
2018-09-10 15:10:51 +00:00
Martynas Pumputis a182bd4514 Merge pull request #3388 from myENA/feature/skip-nat-via-weave-expose
add --without-masquerade option to `weave expose`
2018-09-10 15:45:52 +03:00
Bryan Boreham 231d0c633e Merge branch '2.4' 2018-09-06 14:24:40 +00:00
Bryan Boreham a6e1165e71 Merge pull request #3369 from dholbach/fix-3338
docs: update ECS references
2018-09-06 14:24:15 +00:00
Bryan Boreham 0e26b4621d Merge pull request #3369 from dholbach/fix-3338
docs: update ECS references
2018-09-06 15:21:26 +01:00
Bryan Boreham fc211b15e9 Merge pull request #3393 from weaveworks/issues/3392-get-peers-with-no-ip
Do not exclude k8s node without any IP addr in reclaim
2018-09-06 15:20:33 +01:00
Martynas Pumputis acc24f1237 Do not exclude k8s node without any IP addr in reclaim
Otherwise, such node will be rmpeer'd which can lead to the IPAM
inconsistencies "Received update for IP range I own at <..>".
2018-09-06 14:49:20 +03:00
Bryan Boreham 612e265123 Merge pull request #3391 from weaveworks/debug-log
add documentation to enable debug logging
2018-09-06 12:45:58 +01:00
Murali Reddy 9cf50588b5 remove weave-npc logging details 2018-09-06 11:45:02 +00:00
Murali Reddy 6c2de466c0 add documnetatin to enable debug logging 2018-09-06 11:44:53 +00:00
Bryan Boreham 6f26c732f1 Merge pull request #3356 from weaveworks/portmap
support for portmap as additional plugin with wave-net
2018-09-05 11:06:58 +01:00
Murali Reddy ddfec13f17 add portmap requirement in kube-addon.md 2018-09-05 12:06:13 +05:30
Murali Reddy b8b47787be integration test for HostPort support 2018-09-05 08:35:27 +05:30
Martynas Pumputis 4d1f968eb6 Merge pull request #3381 from weaveworks/issue-3133
Monitor and throw error message in the logs if Weave bridge interface is down

Fix #3133
2018-09-03 15:43:34 +03:00
Murali Reddy 16a8988e41 addressing review comments 2018-09-03 15:25:57 +05:30
Aaron Hurt c9f1d30f49 updates to address comments by @bboreham 2018-08-31 14:26:00 -05:00
Aaron Hurt 4b9c533b94 add the ability to skip creation of MASQUERADE rules via iptables when executing weave expose command 2018-08-31 11:46:31 -05:00
Murali Reddy 90907a7647 Fix to use 10-weave.conflist instead of 10-weave.conf as CNI config file.
Also adds support for portmap as additional plugin along with weave-net

Fixes #3016
2018-08-31 16:11:24 +05:30
Bryan Boreham ad4e4238a5 Merge pull request #3360 from dholbach/licenses-fix
license: document vendored code which is under LGPL3 and MPL-2.0
2018-08-23 10:44:26 +01:00
Murali Reddy 40980aeb90 Monitor and throw error message in the logs if Weave bridge interface
is found to be in DOWN state

Fixes #3133 Do something more useful when the weave bridge is DOWN

On Weave restart there is already logic in place to create the bridge interface
and bring it up, this fix only monotors the weave bridge interface and logs error if
it is in DOWN state
2018-08-23 10:02:21 +05:30
Martynas Pumputis f68579654b Merge pull request #3375 from weaveworks/issue-3302
Fix weave-npc crash when named ports specified in the named ports
2018-08-17 14:20:41 +02:00
Martynas Pumputis 9899780f35 Merge branch '2.4' 2018-08-17 12:24:23 +02:00
Martynas Pumputis dd5994c7cf Merge pull request #3379 from weaveworks/issue-3226
add missing --token argument in help for `weave launch`

Fix #3226
2018-08-17 11:15:53 +02:00
Murali Reddy e6ba59f029 add missing --token argument in help for weave launch
Fixes #3226
2018-08-17 14:40:05 +05:30
Murali Reddy e0359a32f2 Merge pull request #3367 from weaveworks/issues/3168-ingress-ipblock
Add ipBlock support for Ingress netpol
2018-08-16 13:24:47 +05:30
Murali Reddy a19d025677 addressing review comment 2018-08-14 20:16:04 +05:30
Daniel Holbach 528baedd99 make markdownlint happier 2018-08-14 12:32:57 +02:00
Daniel Holbach e1579ecc1e update license bits after #3358 was fixed, don't include licenses we already ship in the code 2018-08-14 12:30:04 +02:00
Daniel Holbach c72e8bbd36 license: document vendored code which is under LGPL3 and MPL-2.0 2018-08-14 11:59:51 +02:00
Martynas Pumputis 6d921802e2 Add recommendation to docs about ingress.ipBlock usage
Also, update link to NetworkPolicy API object spec.
2018-08-14 11:59:12 +02:00
Martynas Pumputis 7c78cdd45d Merge pull request #3366 from weaveworks/issues/3358-bump-client-go
Use k8s/client-go v8.0.0

Fix #3358
2018-08-14 11:57:15 +02:00
Murali Reddy 6625e29071 addressing review comments 2018-08-10 19:36:18 +05:30
Bryan Boreham d1d618ccb3 SRCDIR removed from this step 2018-08-10 14:02:12 +00:00
Bryan Boreham 80e2ff0353 Adjust for change in docker login command 2018-08-10 13:39:21 +00:00
Murali Reddy d5e864736b weave-npc doesn't handle named ports
Support for names ports in enhancement, but with this PR just adding more graceful failure.

Fixes #3032
2018-08-10 18:37:08 +05:30
Bryan Boreham 5b4040704b Fix CircleCI parse error
Also remember to check the source out
2018-08-10 12:51:44 +00:00
Bryan Boreham c85bc059eb Merge branch '2.4' 2018-08-10 12:34:04 +00:00
Bryan Boreham 8fb3da6fc8 Merge pull request #3371 from weaveworks/parse-labels
Parse labels
2018-08-10 13:33:22 +01:00
Bryan Boreham 55354900da Remove out-of-date CONTRIBUTORS file 2018-08-09 13:06:34 +00:00
Daniel Holbach c654640bde Remove the reference to the CoreOS guide.
It appears the guide was removed from the website some time
  before as well. I guess the old content lives here now:
  https://github.com/weaveworks-guides/old-guides/tree/master/coreos-simple
2018-08-09 12:15:07 +02:00
Bryan Boreham 1814bbd2f2 Test container args-parsing code
Extract function just to parse args, so we can call it separately and
test it.
2018-08-08 13:24:53 +00:00
Bryan Boreham 374fed4699 Support --label flag on run-container command 2018-08-08 13:24:53 +00:00
Daniel Holbach cd48ec5959 docs: update ECS references
- point to up-to-date AMIs
  - remove reference to out-of-date ECS guide

  closes #3338
2018-08-08 11:00:46 +02:00
Martynas Pumputis aec8756151 npc: Add integration test case for ingress.ipBlock 2018-08-03 17:17:50 +02:00
Martynas Pumputis c742ec4993 npc: Enable ipBlock for Ingress policy
When using ipBlock in Ingress policy, one should be aware
that source IP addr of packet destined to Pod in many cases
is mangled, see docs/k8s-src-ip.md for the cases.

However, the mangling in some cases can be prevented with
setting externalTrafficPolicy to Local.
2018-08-03 13:21:45 +02:00
Martynas Pumputis b8bb7d7696 Sleep more in the 840 smoke test 2018-08-03 10:37:59 +02:00
Martynas Pumputis 8288da2240 Use k8s/client-go v8.0.0
Avoids including juju/ratelimit licensed under LGPL3.
2018-08-03 10:15:28 +02:00
Martynas Pumputis dcaf77a900 Merge pull request #3270 from weaveworks/circle20
Convert CI build to CircleCI 2.0

Fix #3255
2018-08-02 12:38:09 +02:00
Bryan Boreham e64656d16f Specify https for security 2018-08-02 10:11:42 +00:00
Bryan Boreham e3231bb373 Stop running VM creation in the background
There's nothing else happening in parallel in this step now.
2018-07-30 10:19:28 +00:00
Bryan Boreham 44e0c6add7 Try to fix failing test 840 2018-07-30 10:19:28 +00:00
Bryan Boreham 1a8794e90f Run coverage analysis in separate step, and save results
Remove CircleCI 1.0 implementation which used scp to contact other
lanes.

Note we can't use an env var in store_artifacts clause
2018-07-30 10:18:57 +00:00
Bryan Boreham e3576e13a7 Don't copy the source directory somewhere else 2018-07-30 10:16:18 +00:00
Bryan Boreham b3e77e81ea Split into several jobs
Run build, lint and unit-test steps in a container, using a pre-built
image to save rebuilding at CircleCI

Move a couple of scripts up to config.yml for clarity
2018-07-30 10:16:18 +00:00
Bryan Boreham b13eb5ada5 Run gen_coverage as a 'deploy' 2018-07-30 10:16:18 +00:00
Bryan Boreham 6337972c8a Don't need to pipe background commands to file in Circle 2.0 2018-07-30 10:16:18 +00:00
Bryan Boreham 8620d0ae4f Change CircleCI config to 2.0 version
Environment variables are moved out to a script, because CircleCI 2.0
does not support expansion of '$foo' in 'env' section.
2018-07-30 10:16:18 +00:00
Bryan Boreham fc77e33d1d Move circleci config to 2.0 location 2018-07-30 10:09:07 +00:00
Bryan Boreham 0164d24583 Tag build image with current git commit 2018-07-30 10:09:07 +00:00
Bryan Boreham 76ee9874d6 Add coverage commands to build image 2018-07-30 10:09:07 +00:00
Bryan Boreham 3699f89b98 Add docker command to build container 2018-07-30 10:09:07 +00:00
Bryan Boreham 911751d0c1 Remove docs-only support in CI - docs moved to Netlify 2018-07-30 09:22:34 +00:00
Martynas Pumputis e669ac6ef8 Merge remote-tracking branch 'origin/2.3' into 2.4 2018-07-30 10:03:56 +02:00
Martynas Pumputis 4263ac1ac5 Merge pull request #3362 from weaveworks/issues/3361-defunct-procs
Print defunct processes if such exist
2018-07-30 08:33:41 +02:00
Martynas Pumputis 8176048268 Print defunct processes if such exist
Instead of printing their count. Helps to determine which
process causes the zombies.
2018-07-28 15:27:10 +02:00
Martynas Pumputis 973e1075b9 Merge pull request #3349 from weaveworks/remove-old-k8s
Remove mention of Kubernetes 1.6 from docs: it's very old now
2018-07-21 17:23:05 +02:00
Bryan Boreham 7f1945f06e Remove mention of Kubernetes 1.6 from docs: it's very old now 2018-07-17 12:24:20 +01:00
1256 changed files with 144574 additions and 28515 deletions

No files matched your search

+123
View File
@@ -0,0 +1,123 @@
version: 2
defaults: &defaults
docker:
- image: weaveworks/weavebuild:go-1-13-1-5110a604
working_directory: /go/src/github.com/weaveworks/weave
jobs:
lint:
<<: *defaults
steps:
- checkout
- run: git submodule update --init
- run: make DEBUG=1 BUILD_IN_CONTAINER=false lint
unit-test:
<<: *defaults
parallelism: 2
steps:
- checkout
- run: COVERDIR=test/coverage make BUILD_IN_CONTAINER=false tests
- persist_to_workspace:
root: .
paths:
- test/coverage
build:
<<: *defaults
steps:
- checkout
- setup_remote_docker
- run: git submodule update --init
- run: make COVERAGE=true BUILD_IN_CONTAINER=false SUDO= exes all
- persist_to_workspace:
root: .
paths:
- weave.tar.gz
- tools/runner/runner
- test/tls/tls
smoke-tests:
machine:
image: circleci/classic:201709-01
working_directory: /home/circleci/src/github.com/weaveworks/weave
environment:
SRCDIR: /home/circleci/src/github.com/weaveworks/weave
CIRCLE_ARTIFACTS: /tmp/artifacts
parallelism: 2
steps:
- checkout
- run: mkdir $CIRCLE_ARTIFACTS
- run: git submodule update --init
- attach_workspace:
at: .
# kick off creation of test VMs
- run: bin/provision_test_vms.sh
# when VMs are ready, copy built software to them
- run: bin/circle-test-pre
- run:
command: bin/circle-test-smoke
no_output_timeout: 360s
# Destroy testing VMs:
- run:
command: bin/circle-destroy-vms
background: true
- persist_to_workspace:
root: .
paths:
- test/coverage
- store_artifacts:
path: /tmp/artifacts
gen-coverage:
<<: *defaults
environment:
CIRCLE_ARTIFACTS: /tmp/artifacts
steps:
- checkout
- run: mkdir $CIRCLE_ARTIFACTS
- attach_workspace:
at: .
- run: cd test; ./gen_coverage_reports.sh
- run: goveralls -repotoken $COVERALLS_REPO_TOKEN -coverprofile=test/profile.cov -service=circleci
- run: cp test/coverage.* $CIRCLE_ARTIFACTS
- store_artifacts:
path: /tmp/artifacts
deploy:
<<: *defaults
steps:
- checkout
- setup_remote_docker
# Register qemu hooks, rebuild without coverage and push to dockerhub
- deploy:
command: |
docker login -u $DOCKER_USER -p $DOCKER_PASS
docker run --rm --privileged multiarch/qemu-user-static:register --reset
wget https://github.com/estesp/manifest-tool/releases/download/v0.8.0/manifest-tool-linux-amd64
chmod +x manifest-tool-linux-amd64
make clean-bin
make publish MANIFEST_TOOL_CMD=./manifest-tool-linux-amd64 UPDATE_LATEST=latest-only SUDO= BUILD_IN_CONTAINER=false
workflows:
version: 2
build_test:
jobs:
- lint
- unit-test
- build
- smoke-tests:
requires:
- lint
- unit-test
- build
- gen-coverage:
requires:
- unit-test
- smoke-tests
- deploy:
requires:
- smoke-tests
filters:
branches:
only: master
-1
View File
@@ -4,7 +4,6 @@
# avoid breaking the build on make lint:
bin/circle-deploy-issues
bin/circle-deploy-master
bin/circle-teardown-pre
bin/circle-test-teardown
bin/circle-test-unit
bin/install-wordepress
+1 -1
View File
@@ -1 +1 @@
2.3.0
2.6.2
+208
View File
@@ -1,3 +1,211 @@
## Release 2.6.4
Improves the iptables rule added in 2.6.3 to block just the Weave Net
control port and avoid blocking other uses of 127.0.0.1. #3811
## Release 2.6.3
This release has a couple of security improvements, and some other fixes.
* Block non-local traffic to the Weave control port #3805
* Tell Linux not to accept router advisory messages #3801
* Network Policy Controller: add a metric to show errors while operating #3804
* Network Policy Controller: don't treat named port as a fatal error #3790
## Release 2.6.2
This release fixes a regression found in 2.6.1 release and removes a possible case
of CPU spinning when pcap is used in sleeve mode
### Bug fixes
* Weave Net can not be used in fastdp mode and always falls back to sleeve mode #3781, #3783
* Restrict timeout value passed to pcap library to a value less than 2^31 microseconds to
prevent CPU spinning #3782
## Release 2.6.1
This release fixes a bug discovered since the release of Weave Net 2.6.0 and
an improvement to support iptables 1.8
### Bug fixes
* Weave Net on node restart unable to form connections to peers and connections get stuck in
pending state and stops responding to API endpoint #3762 #3763
### Other improvements
* Weave Net Kubernetes images by default uses iptables 1.8 with legacy (netfilter) backend with
option to choose netfilter as backend #3465, #3747
## Release 2.6.0
This release reduces CPU and memory usage in larger clusters, by
sending notifications to a smaller set of peers and coalescing updates
to reduce topology recalculation. #3715, #3732
The default soft limit on connections has been raised from 100 to 200.
### Bug fixes
* Fix a race condition in Kubernetes addon when reclaiming IP
addresses after node deletion #3724, #3716
* Buffer events so Docker won't drop them, and Weave Net can clean up
after dead containers #3432, #3705
* Weave reconnect occasionally fails after network interface
disconnect #3666, #3669, #3676
* Ingress NetworkPolicy would accepts all traffic when specifying both
IPBlock and port #3653, #3654
### Kubernetes improvements
* Support both podSelector and namespaceSelector in NetworkPolicy #3312, #3647
* Only add default-drop egress rule if network policies are in use #3639
* Manifests use 'apps/v1' rather than deprecated 'apps/v1beta1' #3660
* Avoid Weave Net pods being evicted by setting priorityClassName: system-node-critical #3697
* Manifests use recommended DNS policy ClusterFirstWithHostNet #3692
* Weave Net now tolerates 'NoExecute' taint #3655
* Allow extra arguments to NetworkPolicy controller to be set in an environment variable #3683
* Stop reporting a failure to connect to self #3454, #3585
* Minor reduction in log noise when reclaiming IPs #3710
### Other improvements
* Avoid isolating nodes which have restarted by automatically
repairing inconsistencies in IP allocation data #1962, #3637, #3708
* Build Weave Net for the s390x architecture #3685
* When a IP address is requested that may be in use, make several
attempts to claim it before returning an error #3725
* Improve logging for IP allocation updates #3627, #3630
* Improve 'expecting PMTU update' log message on initial connection #3603
### Build and test
* Shut down Kubernetes on node when testing node deletion #3716
* Update the base 'Alpine' container image to version 3.8 #3701
* Update Go to version 1.13.3 #3712
* Update gopacket library #3590
* Pin busybox version to 1.28 to avoid CI failure in Python test #3689
* Remove obsolete weave-daemonset.yaml file #3674
Thanks to contributors @christian-2, @hpdvanwyk, @guirish, @kitt1987,
@mmerrill3, @Pensu, @scritchley, @sidharthsurana, @tanishq-dubey
[Full list of changes](https://github.com/weaveworks/weave/milestone/78?closed=1)
## Release 2.5.2
This release fixes several bugs causing inconsistencies in IPAM and fixes a
panic in daemon that reclaims and forgets deleted nodes in Kubernetes clusters.
### Bug fixes
* leaking IP addresses in IPAM when weave-net hangs or restarting #3587, #3638
* Panic in kube-utils after config map update error resulting in reclaim daemon
not performing weave forget on deleted node #3613, #3623
* preventing inconsistent IPAM entries and resolving the conflict in case of
conflict during IPAM ring merge #3629, #3635, #3632, #3444
[Full list of changes](https://github.com/weaveworks/weave/milestone/79?closed=1)
## Release 2.5.1
This release fixes bugs reported for 2.5 release and small improvements.
### Bug fixes
* prevent warnings in kernal logs due to use of physdev model for
non-bridged traffic #3449, #3453
* Check and report the error occurred while getting the list of Kubernetes
peers #3581, #3582
### Other improvements
* Update Ruby version to match Weaveworks website #3458
* Fix the link to "Troubleshooting the Kubernetes Addon" section in the docs #3461
* Document concept of connection limit in Weave #3395, #3413
[Full list of changes](https://github.com/weaveworks/weave/milestone/77?closed=1)
## Release 2.5.0
This release adds support for Kubernetes `hostPort` mapping (#3016,#3356)
and the `ipBlock` NetworkPolicy feature (#3168,#3367)
### Bug fixes
* Fix a crash at start-up on Docker for Mac #3405, #3408
* Network policy: block ingress traffic when no namespaceSelector or
podSelector is specified #3347
* Reclaim IP addresses which are locked by a non-existent peer #3386, #3416
* Fix a crash when blank IP data was loaded #3067, #3415
### Other improvements
* If a connection is downgraded to the slower "sleeve" mode, Weave Net
will now periodically try to upgrade it to "fast datapath" again. #1737, #3385
* Reclaim removed Kubernetes nodes' IP space when they are deleted,
rather than on next restart #3372, #3399
* Replace Kubernetes livenessProbe with readinessProbe, so the pod is
not killed if it runs slowly #3471, #3421
* In Kubernetes NetworkPolicy controller, remove the need to maintain
a set of local pod IP addresses #3344, #3423
* Don't crash on Kubernetes named port in NetworkPolicy, just report as unsupported #3375
* Ensure the `weave` network bridge is accessible on Linux kernels
older than 3.14 #3442, #3297, #3239
* Better reporting in the logs if the `weave` network device is in the Down state #3133, #3381
* Change log-level to debug of calls through the Docker proxy, to reduce noise #3439
* Add `--without-masquerade` option to `weave expose`, so external
services can see the original container IP address #3388
* Include Kubernetes cluster information in checkpoint call #3324,#3431
* Bump go-odp dependency, so that `fastdp` works on the 4.19 kernel #3430
### Build and Testing
* CI builds on master branch now publish images for all platforms
* Fix golint path and use https for download of libpcap #3435
* Update Kubernetes client-go to v8.0.0, removing code licenced under LGPL3 #3358,#3366
* Migrate CircleCI to V2, which is much faster #3255,#3270
### External Contributors
Thanks to the following contributors:
* @Ashiroq
* @leprechau
* @lkpdn
[Full list of changes](https://github.com/weaveworks/weave/milestone/74?closed=1)
## Release 2.4.1
This release fixes several bugs causing inconsistencies in IPAM for
Kubernetes users whose clusters scale up and down over time.
### Bug fixes
* Nodes unable to connect after Kubernetes addon erroneously reclaimed
node without any IP addresses #3392, #3393
* Kubernetes addon could have run out of free IP addresses after nodes
are deleted #3384, #3400
* Kubernetes addon had reduced free IP addresses due to not reclaiming
IP addresses when node name is re-used #3397
### Other improvements
* Support `--label` in `WEAVE_DOCKER_ARGS` when starting Weave #3370,#3371
* Add missing `--token` argument in help for `weave launch` #3226, #3379
* Print defunct processes after smoke-tests #3362
[Full list of changes](https://github.com/weaveworks/weave/milestone/75?closed=1)
## Release 2.4.0
This release introduces a support for Kubernetes Egress Network Policy (#2624, #3313)
-5
View File
@@ -1,5 +0,0 @@
This file lists all individuals having contributed content to the
repository.
Matthew Sackman <matthew@wellquite.org>
Matthias Radestock <matthias.radestock@gmail.com>
@@ -1,23 +1,14 @@
package cmd
./test/assert.sh is a copy of
func initLgpl() {
Licenses["lgpl"] = License{
Name: "GNU Lesser General Public License",
PossibleMatches: []string{"lgpl", "lesser gpl", "gnu lgpl"},
Header: `
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
https://github.com/lehmannro/assert.sh/blob/master/assert.sh
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
Since it was imported from its original source, it has only received
cosmetic modifications. As it is licensed under the LGPL-3, here's the
license text in its entirety:
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.`,
Text: ` GNU LESSER GENERAL PUBLIC LICENSE
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
@@ -181,6 +172,4 @@ General Public License ever published by the Free Software Foundation.
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.`,
}
}
Library.
Generated
+401 -45
View File
File diff suppressed because it is too large. Load diff
+5
View File
@@ -24,6 +24,11 @@
branch = "master"
name = "github.com/docker/distribution"
# v8.0.0 removes juju/ratelimit licensed under LGPL3
[[constraint]]
name = "k8s.io/client-go"
revision = "v8.0.0"
[prune]
go-tests = true
unused-packages = true
+38 -31
View File
@@ -17,15 +17,15 @@ QEMU_VERSION=v2.7.0
# A list of all supported architectures here. Should be named as Go is naming platforms
# All supported architectures must have an "ifeq" block below that customizes the parameters
ALL_ARCHITECTURES=amd64 arm arm64 ppc64le
ML_PLATFORMS=linux/amd64,linux/arm,linux/arm64,linux/ppc64le
ALL_ARCHITECTURES=amd64 arm arm64 ppc64le s390x
ML_PLATFORMS=linux/amd64,linux/arm,linux/arm64,linux/ppc64le,linux/s390x
ifeq ($(ARCH),amd64)
# The architecture to use when downloading the docker binary
WEAVEEXEC_DOCKER_ARCH?=x86_64
# The name of the alpine baseimage to use as the base for weave images
ALPINE_BASEIMAGE?=alpine:3.6
ALPINE_BASEIMAGE?=alpine:3.10
# The extension for the made images
# Specifying none means for example weaveworks/weave:latest
@@ -42,7 +42,7 @@ ifeq ($(ARCH),arm)
WEAVEEXEC_DOCKER_ARCH?=armel
# Using the (semi-)official alpine image
ALPINE_BASEIMAGE?=arm32v6/alpine:3.6
ALPINE_BASEIMAGE?=arm32v6/alpine:3.8
# arm images have the -arm suffix, for instance weaveworks/weave-arm:latest
ARCH_EXT?=-arm
@@ -62,7 +62,7 @@ ifeq ($(ARCH),arm64)
WEAVEEXEC_DOCKER_ARCH?=armel
# Using the (semi-)official alpine image
ALPINE_BASEIMAGE?=arm64v8/alpine:3.6
ALPINE_BASEIMAGE?=arm64v8/alpine:3.8
# arm64 images have the -arm64 suffix, for instance weaveworks/weave-arm64:latest
ARCH_EXT?=-arm64
@@ -82,7 +82,7 @@ ifeq ($(ARCH),ppc64le)
WEAVEEXEC_DOCKER_ARCH?=ppc64le
# Using the (semi-)official alpine image
ALPINE_BASEIMAGE?=ppc64le/alpine:3.6
ALPINE_BASEIMAGE?=ppc64le/alpine:3.8
# ppc64le images have the -ppc64le suffix, for instance weaveworks/weave-ppc64le:latest
ARCH_EXT?=-ppc64le
@@ -97,6 +97,26 @@ ifeq ($(ARCH),ppc64le)
# Tell the gcc linker to search for libpcap here
CGO_LDFLAGS="-L/usr/local/lib/$(CC)"
endif
ifeq ($(ARCH),s390x)
# The architecture to use when downloading the docker binary
WEAVEEXEC_DOCKER_ARCH?=s390x
# Using the (semi-)official alpine image
ALPINE_BASEIMAGE?=s390x/alpine:3.6
# s390x images have the -s390x suffix, for instance weaveworks/weave-s390x:latest
ARCH_EXT?=-s390x
# The name of the gcc binary
CC=s390x-linux-gnu-gcc
# The architecture name to use when downloading a prebuilt QEMU binary
QEMUARCH=s390x
# In the weaveworks/build image; libpcap libraries for s390x are placed here
# Tell the gcc linker to search for libpcap here
CGO_LDFLAGS="-L/usr/local/lib/$(CC)"
endif
# The name of the user that this Makefile should produce image artifacts for. Can/should be overridden
DOCKERHUB_USER?=weaveworks
@@ -116,8 +136,8 @@ WEAVEWAIT_NOOP_EXE=prog/weavewait/weavewait_noop
WEAVEWAIT_NOMCAST_EXE=prog/weavewait/weavewait_nomcast
WEAVEUTIL_EXE=prog/weaveutil/weaveutil
RUNNER_EXE=tools/runner/runner
# manifest-tool needs registry credentials; we assume here that the active user has logged in
MANIFEST_TOOL_CMD=docker run --rm -v $(HOME)/.docker:/.docker weshigbee/manifest-tool --docker-cfg=/.docker
# Get this from https://github.com/estesp/manifest-tool/releases
MANIFEST_TOOL_CMD=manifest-tool
TEST_TLS_EXE=test/tls/tls
NETWORKTESTER_EXE=test/images/network-tester/webserver
@@ -156,18 +176,11 @@ PUSH_ML=push_ml_weave push_ml_weaveexec push_ml_weave-kube push_ml_weave-npc
WEAVE_EXPORT=weave$(ARCH_EXT).tar.gz
NETGO_CHECK=@strings $@ | grep cgo_stub\\\.go >/dev/null || { \
rm $@; \
echo "\nYour go standard library was built without the 'netgo' build tag."; \
echo "To fix that, run"; \
echo " sudo go clean -i net"; \
echo " sudo go install -tags netgo std"; \
false; \
}
# The flags we are passing to go build. -extldflags -static for making a static binary,
# -linkmode external for linking external C libraries into the binary, -X main.version for telling the
# Go binary which version it is, -tags netgo for enforcing the native Go DNS resolver
BUILD_FLAGS=-i -ldflags "-linkmode external -extldflags -static -X main.version=$(WEAVE_VERSION)" -tags netgo
# -X main.version for telling the Go binary which version it is,
# -s -w drop symbol tables used by debuggers (not Go's internal symbol info)
# -tags "osusergo netgo" to use native Go UID and DNS implementations
BUILD_FLAGS=-ldflags "-extldflags -static -X main.version=$(WEAVE_VERSION) -s -w" -tags "osusergo netgo"
PACKAGE_BASE=$(shell go list -e ./)
@@ -196,10 +209,8 @@ ifeq ($(BUILD_IN_CONTAINER),true)
# This make target compiles all binaries inside of the weaveworks/build container
# It bind-mounts the source into the container and passes all important variables
exes $(EXES) tests lint: $(BUILD_UPTODATE)
@mkdir -p $(shell pwd)/.pkg
$(SUDO) docker run $(RM) $(RUN_FLAGS) \
-v $(shell pwd):/go/src/github.com/weaveworks/weave \
-v $(shell pwd)/.pkg:/go/pkg \
-e GOARCH=$(ARCH) -e CGO_ENABLED=1 -e GOOS=linux -e CIRCLECI -e CIRCLE_BUILD_NUM -e CIRCLE_NODE_TOTAL -e CIRCLE_NODE_INDEX -e COVERDIR -e SLOW -e DEBUG \
$(BUILD_IMAGE) COVERAGE=$(COVERAGE) WEAVE_VERSION=$(WEAVE_VERSION) CC=$(CC) QEMUARCH=$(QEMUARCH) CGO_LDFLAGS=$(CGO_LDFLAGS) $@
touch $@
@@ -215,19 +226,15 @@ ifeq ($(COVERAGE),true)
else
go build $(BUILD_FLAGS) -o $@ ./$(@D)
endif
$(NETGO_CHECK)
$(WEAVEUTIL_EXE) $(KUBEUTILS_EXE) $(WEAVENPC_EXE) $(NETWORKTESTER_EXE):
go build $(BUILD_FLAGS) -o $@ ./$(@D)
$(NETGO_CHECK)
$(WEAVEWAIT_EXE):
go build $(BUILD_FLAGS) -tags "netgo iface mcast" -o $@ ./$(@D)
$(NETGO_CHECK)
go build $(BUILD_FLAGS) -tags "osusergo netgo iface mcast" -o $@ ./$(@D)
$(WEAVEWAIT_NOMCAST_EXE):
go build $(BUILD_FLAGS) -tags "netgo iface" -o $@ ./$(@D)
$(NETGO_CHECK)
go build $(BUILD_FLAGS) -tags "osusergo netgo iface" -o $@ ./$(@D)
# These programs need a separate rule as they fail the netgo check in
# the main build stanza due to not importing net package
@@ -244,8 +251,9 @@ endif
# This rule makes sure the build image is up-to-date.
# It also makes sure the multiarch hooks are reqistered in the kernel so the QEMU emulation works
$(BUILD_UPTODATE): build/*
$(BUILD_UPTODATE): build/* tools/.git
$(SUDO) docker build -t $(BUILD_IMAGE) build/
$(SUDO) docker tag $(BUILD_IMAGE) $(BUILD_IMAGE):$(shell tools/image-tag)
$(SUDO) docker run --rm --privileged multiarch/qemu-user-static:register --reset
touch $@
@@ -391,15 +399,14 @@ clean-bin:
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(IMAGES)
find prog -type f -name "Dockerfile.*" -not -name "Dockerfile.template" -print | xargs rm -f
find prog -type f -name "*qemu-*" -print | xargs rm -f
rm -rf $(EXES) $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE) weave*.tar.gz .pkg
go clean ./...
rm -rf $(EXES) $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE) weave*.tar.gz .cache
clean: clean-bin clean-work-dir
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(BUILD_IMAGE)
rm -rf test/tls/*.pem test/coverage.* test/coverage $(BUILD_UPTODATE)
build:
$(SUDO) go clean -i net
$(SUDO) go install -tags netgo std
$(MAKE)
run-smoketests: all testrunner
+6 -8
View File
@@ -7,12 +7,11 @@
# About Weaveworks
[Weaveworks](https://www.weave.works) is the company that delivers the most productive way for developers to connect, observe and control
Docker containers.
[Weaveworks](https://www.weave.works) is the company that delivers the most productive way for developers to connect, observe and control 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, 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, with over 8 million downloads to date. Weave Net enables you to get started with Docker clusters and portable apps in a fraction of the time required by other solutions.
## Weave Cloud:
## 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.
@@ -29,11 +28,10 @@ Services provided by application containers on the Weave network can be exposed
If you have any questions about, feedback for or a problem with Weave Net:
- Read [the Weave Net docs](https://www.weave.works/docs/net/latest/overview).
- Invite yourself to the <a href="https://weaveworks.github.io/community-slack/" target="_blank"> #weave-community </a> slack channel.
- Ask a question on the <a href="https://weave-community.slack.com/messages/general/"> #weave-community</a> slack channel.
- Invite yourself to the <a href="https://slack.weave.works/" target="_blank">Weave Users Slack</a>.
- Ask a question on the [#net-dev](https://weave-community.slack.com/messages/net-dev/) slack channel.
- Join the <a href="https://www.meetup.com/pro/Weave/"> Weave User Group </a> and get invited to online talks, hands-on training and meetups in your area.
- Send an email to <a href="mailto:weave-users@weave.works">weave-users@weave.works</a>
- <a href="https://github.com/weaveworks/weave/issues/new">File an issue.</a>
- [File an issue](https://github.com/weaveworks/weave/issues/new).
Your feedback is always welcome!
+17
View File
@@ -0,0 +1,17 @@
# Use of vendored code in Weave Net
Weave Net is licensed under the [Apache 2.0 license](LICENSE).
Some vendored code is under different licenses though, all of them ship the
entire license text they are under.
- https://github.com/weaveworks/go-checkpoint
can be found in the ./vendor/ directory, is under MPL-2.0.
- Pulled in by dependencies are
https://github.com/hashicorp/golang-lru (MPL-2.0)
https://github.com/hashicorp/go-cleanhttp (MPL-2.0)
https://github.com/opencontainers/go-digest (docs are under CC by-sa 4.0)
[One file used in tests](COPYING.LGPL-3) is under LGPL-3, that's why we ship
the license text in this repository.
+7
View File
@@ -3,6 +3,7 @@ package api
import (
"fmt"
"net"
"net/url"
)
// Expose calls the router to assign the given IP addr to the weave bridge.
@@ -10,3 +11,9 @@ func (client *Client) Expose(ipAddr *net.IPNet) error {
_, err := client.httpVerb("POST", fmt.Sprintf("/expose/%s", ipAddr), nil)
return err
}
// ReplacePeers replace the current set of peers
func (client *Client) ReplacePeers(peers []string) error {
_, err := client.httpVerb("POST", "/connect", url.Values{"replace": {"true"}, "peer": peers})
return err
}
-17
View File
@@ -1,17 +0,0 @@
#!/bin/bash
set -e
source "$STATE"
if [ -n "$TEST_AND_PUBLISH" ]; then
cd "$SRCDIR"
git submodule update --init
cd "$SRCDIR/build"
../tools/rebuild-image weaveworks/weavebuild . Dockerfile build.sh
touch "$SRCDIR/.build.uptodate"
sudo chown -R ubuntu /usr/local/go
cd "$SRCDIR"
make testrunner
make COVERAGE=true RM= exes all
fi
-36
View File
@@ -1,36 +0,0 @@
#!/bin/bash
set -e
echo "TEST_AND_PUBLISH=1" >"$STATE"
# Avoid doing a full build if we can. Note if the PR doesn't exist
# when the build is kicked off, we can't run this check so we do a
# full build. Subsequent pushes to the same branch will have the desired behaviour
if [ -n "$CI_PULL_REQUEST" -a "$CI_PULL_REQUEST" = "$CI_PULL_REQUESTS" ]; then
if PR=$(echo "$CI_PULL_REQUEST" | grep -oP '(?<=^https://github.com/weaveworks/weave/pull/)[0-9]+$'); then
echo "GH_PR=$PR" >>"$STATE"
if FILES=$(curl -s "https://api.github.com/repos/weaveworks/weave/pulls/$PR/files" | jq -r '.[]|.filename'); then
echo "PR touches [$FILES]"
if ! echo "$FILES" | grep -v ^site/; then
echo "PR contains site changes only - skipping tests"
echo "TEST_AND_PUBLISH=" >>"$STATE"
else
echo "PR contains non-site changes - running tests"
fi
else
echo "Unable to get files for PR $PR" >&2
fi
else
echo "Unable to extract PR number from $CI_PULL_REQUEST" >&2
fi
fi
source "$STATE"
mkdir -p "$(dirname "$SRCDIR")" && cp -r "$(pwd)/" "$SRCDIR"
if [ -n "$TEST_AND_PUBLISH" ]; then
cd "$SRCDIR"
git submodule update --init
fi
+4 -9
View File
@@ -2,12 +2,7 @@
set -e
source "$STATE"
if [ -n "$TEST_AND_PUBLISH" ] ; then
docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
cd $SRCDIR
make clean-bin
# CircleCI doesn't let us install the qemu module to do ARM docker builds
make publish ALL_ARCHITECTURES=amd64 UPDATE_LATEST=latest-only
fi
docker login -u $DOCKER_USER -p $DOCKER_PASS
make clean-bin
# CircleCI doesn't let us install the qemu module to do ARM docker builds
make publish ALL_ARCHITECTURES=amd64 UPDATE_LATEST=latest-only SUDO= BUILD_IN_CONTAINER=false
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
set -e
source "$SRCDIR/bin/circle-env"
cd "$SRCDIR/test"
./run-integration-tests.sh destroy
+11
View File
@@ -0,0 +1,11 @@
# Set environment variables here because CircleCI can't expand $FOO in 'env' section
export PATH="$PATH:$HOME/.local/bin:/opt/google-cloud-sdk/bin"
export CLOUDSDK_CORE_DISABLE_PROMPTS=1
# Base name of VMs for integration tests:
export NAME=test-$CIRCLE_BUILD_NUM-$CIRCLE_NODE_INDEX
export TEST_VMS_PROV_AND_CONF_LOCK_FILE=$CIRCLE_ARTIFACTS/test_vms_provisioned_and_configured.txt
export TEST_VMS_READY_LOCK_FILE=$CIRCLE_ARTIFACTS/test_vms_ready.txt
# Google Cloud Platorm images for integration tests:
export USE_IMAGE=1
export DISK_NAME_PREFIX=test-$CIRCLE_BUILD_NUM-0
-13
View File
@@ -1,13 +0,0 @@
#!/bin/bash
set -e
source "$STATE"
if [ -n "$TEST_AND_PUBLISH" ] ; then
if [ "$CIRCLE_NODE_INDEX" = "0" ] ; then
go get github.com/mattn/goveralls
goveralls -repotoken $COVERALLS_REPO_TOKEN -coverprofile=$SRCDIR/test/profile.cov -service=circleci
cd $SRCDIR/test; cp coverage.* $CIRCLE_ARTIFACTS
fi
fi
+14 -15
View File
@@ -9,22 +9,21 @@ function signal_failure() {
}
trap signal_failure ERR
source "$STATE"
source "$(dirname "$0")/wait_for.sh"
if [ -n "$TEST_AND_PUBLISH" ]; then
[ -n "$SECRET_KEY" ] || {
echo "Cannot run smoke tests: no secret key"
exit 1
}
[ -n "$SECRET_KEY" ] || {
echo "Cannot run smoke tests: no secret key"
exit 1
}
# Provisioning from image typically take 90 seconds,
# but if we are creating a GCP image, it can take more than 10 minutes:
wait_for 900 "$TEST_VMS_PROV_AND_CONF_LOCK_FILE"
source "$SRCDIR/bin/circle-env"
# Upload built binaries to testing VMs:
cd "$SRCDIR/test" # Ensures we generate Terraform state files in the right folder, for later use by integration tests.
./run-integration-tests.sh setup >>"$TEST_VMS_SETUP_OUTPUT_FILE" 2>&1
echo "OK" >"$TEST_VMS_READY_LOCK_FILE"
echo "Test VMs now ready. $(date)." >>"$TEST_VMS_SETUP_OUTPUT_FILE"
fi
# Provisioning from image typically take 90 seconds,
# but if we are creating a GCP image, it can take more than 10 minutes:
wait_for 900 "$TEST_VMS_PROV_AND_CONF_LOCK_FILE"
# Upload built binaries to testing VMs:
cd "$SRCDIR/test" # Ensures we generate Terraform state files in the right folder, for later use by integration tests.
./run-integration-tests.sh setup
echo "OK" >"$TEST_VMS_READY_LOCK_FILE"
echo "Test VMs now ready. $(date)."
+14 -15
View File
@@ -2,22 +2,21 @@
set -e
source "$STATE"
source "$(dirname "$0")/wait_for.sh"
if [ -n "$TEST_AND_PUBLISH" ]; then
[ -n "$SECRET_KEY" ] || {
echo "Cannot run smoke tests: no secret key"
exit 1
}
[ -n "$SECRET_KEY" ] || {
echo "Cannot run smoke tests: no secret key"
exit 1
}
# Provisioning from image typically take 90 seconds,
# but if we are creating a GCP image, it can take more than 10 minutes:
wait_for 900 "$TEST_VMS_READY_LOCK_FILE"
source "$SRCDIR/bin/circle-env"
# Run integration tests:
export COVERAGE=true
export WEAVE_NET_SANITY_CHECKS_FILES="$CIRCLE_ARTIFACTS/weave_net_sanity_check_*.log"
cd "$SRCDIR/test" # Ensures we generate code coverage files in the right folder, and use the Terraform state of previously provisionned VMs.
./run-integration-tests.sh test
fi
# Provisioning from image typically take 90 seconds,
# but if we are creating a GCP image, it can take more than 10 minutes:
wait_for 900 "$TEST_VMS_READY_LOCK_FILE"
# Run integration tests:
export COVERAGE=true
export WEAVE_NET_SANITY_CHECKS_FILES="$CIRCLE_ARTIFACTS/weave_net_sanity_check_*.log"
cd "$SRCDIR/test" # Ensures we generate code coverage files in the right folder, and use the Terraform state of previously provisionned VMs.
./run-integration-tests.sh test
-10
View File
@@ -1,10 +0,0 @@
#!/bin/bash
set -e
source "$STATE"
if [ -n "$TEST_AND_PUBLISH" ] ; then
cd $SRCDIR/test
test "$CIRCLE_NODE_INDEX" != "0" || (cd $SRCDIR/test; ./gen_coverage_reports.sh)
fi
-11
View File
@@ -1,11 +0,0 @@
#!/bin/bash
set -e
source "$STATE"
if [ -n "$TEST_AND_PUBLISH" ] ; then
cd $SRCDIR
make DEBUG=1 lint
COVERDIR=test/coverage make RM= tests
fi
+13 -24
View File
@@ -9,35 +9,24 @@ function signal_failure() {
}
trap signal_failure ERR
source "$STATE"
function install_terraform() {
curl -fsS https://releases.hashicorp.com/terraform/0.8.5/terraform_0.8.5_linux_amd64.zip | gunzip >terraform && chmod +x terraform && sudo mv terraform /usr/bin
curl -fsS https://releases.hashicorp.com/terraform/0.11.14/terraform_0.11.14_linux_amd64.zip | gunzip >terraform && chmod +x terraform && sudo mv terraform /usr/bin
}
function install_ansible() {
sudo apt-get update || true
sudo apt-get install -qq -y python-pip python-dev libffi-dev libssl-dev \
&& pip install --user -U setuptools cffi \
&& pip install --user ansible
export PATH="$PATH:$HOME/.local/bin"
[ -n "$SECRET_KEY" ] || {
echo "Cannot run smoke tests: no secret key"
exit 1
}
if [ -n "$TEST_AND_PUBLISH" ]; then
[ -n "$SECRET_KEY" ] || {
echo "Cannot run smoke tests: no secret key"
exit 1
}
source "$SRCDIR/bin/circle-env"
install_terraform >>"$TEST_VMS_SETUP_OUTPUT_FILE" 2>&1
install_ansible >>"$TEST_VMS_SETUP_OUTPUT_FILE" 2>&1
install_terraform
# Only attempt to create GCP image in first container, wait for it to be created otherwise:
[ "$CIRCLE_NODE_INDEX" != "0" ] && export CREATE_IMAGE=0
# Only attempt to create GCP image in first container, wait for it to be created otherwise:
[ "$CIRCLE_NODE_INDEX" != "0" ] && export CREATE_IMAGE=0
# Provision and configure testing VMs:
cd "$SRCDIR/test" # Ensures we generate Terraform state files in the right folder, for later use by integration tests.
./run-integration-tests.sh configure >>"$TEST_VMS_SETUP_OUTPUT_FILE" 2>&1
echo "OK" >"$TEST_VMS_PROV_AND_CONF_LOCK_FILE"
echo "Test VMs now provisioned and configured. $(date)." >>"$TEST_VMS_SETUP_OUTPUT_FILE"
fi
# Provision and configure testing VMs:
cd "$SRCDIR/test" # Ensures we generate Terraform state files in the right folder, for later use by integration tests.
./run-integration-tests.sh configure
echo "OK" >"$TEST_VMS_PROV_AND_CONF_LOCK_FILE"
echo "Test VMs now provisioned and configured. $(date)."
+31 -16
View File
@@ -89,10 +89,11 @@ build() {
## Inject the version numbers and build the distributables
## (library versions?)
sed -i.bak "/SCRIPT_VERSION=/ c\SCRIPT_VERSION=\"$VERSION\"" ./weave
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset.yaml
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.6.yaml
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.7.yaml
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.8.yaml
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.9.yaml
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.11.yaml
make SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER
if make tests; then
@@ -161,13 +162,6 @@ draft() {
--name "weave" \
--file "./weave"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag $LATEST_TAG \
--name "weave-daemonset.yaml" \
--file "./prog/weave-kube/weave-daemonset.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
@@ -188,7 +182,21 @@ draft() {
--tag $LATEST_TAG \
--name "weave-daemonset-k8s-1.8.yaml" \
--file "./prog/weave-kube/weave-daemonset-k8s-1.8.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag $LATEST_TAG \
--name "weave-daemonset-k8s-1.9.yaml" \
--file "./prog/weave-kube/weave-daemonset-k8s-1.9.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag $LATEST_TAG \
--name "weave-daemonset-k8s-1.11.yaml" \
--file "./prog/weave-kube/weave-daemonset-k8s-1.11.yaml"
echo "** Draft $TYPE $RELEASE_NAME $VERSION created at"
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
}
@@ -276,13 +284,6 @@ publish() {
--name "weave" \
--file "./weave"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag latest_release \
--name "weave-daemonset.yaml" \
--file "./prog/weave-kube/weave-daemonset.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
@@ -304,6 +305,20 @@ publish() {
--name "weave-daemonset-k8s-1.8.yaml" \
--file "./prog/weave-kube/weave-daemonset-k8s-1.8.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag latest_release \
--name "weave-daemonset-k8s-1.9.yaml" \
--file "./prog/weave-kube/weave-daemonset-k8s-1.9.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag latest_release \
--name "weave-daemonset-k8s-1.11.yaml" \
--file "./prog/weave-kube/weave-daemonset-k8s-1.11.yaml"
echo "** Release $RELEASE_NAME $VERSION published at"
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/latest_release"
+1 -1
View File
@@ -16,6 +16,6 @@ wait_for() {
if ! ((i % 10)); then echo "[$i seconds]: Waiting for $lock_file to be created..."; fi
sleep 1
done
echo "Timed out waiting for test VMs to be ready. See details in: $TEST_VMS_SETUP_OUTPUT_FILE" >&2
echo "Timed out waiting for test VMs to be ready." >&2
return 1
}
+15 -23
View File
@@ -1,4 +1,4 @@
FROM golang:1.10.1-stretch
FROM golang:1.13.3-buster
# Support Raspberry Pi 2 and newer
ENV GOARM 7
@@ -7,25 +7,25 @@ ENV GOARM 7
ENV DEB_CROSSPLATFORMS \
armhf \
arm64 \
ppc64el
ppc64el \
s390x
# The go platforms we are supporting to cross-compile
ENV GO_CROSSPLATFORMS \
linux/arm \
linux/arm64 \
linux/ppc64le
linux/ppc64le \
linux/s390x
# The names of the gcc cross-compilers we have installed
ENV GCC_CROSSCOMPILERS \
arm-linux-gnueabihf \
aarch64-linux-gnu \
powerpc64le-linux-gnu
powerpc64le-linux-gnu \
s390x-linux-gnu
# Temporarily add the Debian repositories, because we're going to install gcc cross-compilers from there
# Install the build-essential and crossbuild-essential-ARCH packages
RUN echo "deb http://emdebian.org/tools/debian/ jessie main" > /etc/apt/sources.list.d/cgocrosscompiling.list \
&& curl http://emdebian.org/tools/debian/emdebian-toolchain-archive.key | apt-key add - \
&& for platform in ${DEB_CROSSPLATFORMS}; do dpkg --add-architecture $platform; done \
RUN for platform in ${DEB_CROSSPLATFORMS}; do dpkg --add-architecture $platform; done \
&& apt-get update \
&& apt-get install -y build-essential \
&& for platform in ${DEB_CROSSPLATFORMS}; do apt-get install -y crossbuild-essential-${platform}; done \
@@ -50,31 +50,20 @@ RUN curl -fsSLo shfmt https://github.com/mvdan/sh/releases/download/v1.3.0/shfmt
# Install common Go tools
RUN go get \
github.com/golang/lint/golint \
github.com/weaveworks/build-tools/cover \
github.com/mattn/goveralls \
golang.org/x/lint/golint \
github.com/fzipp/gocyclo \
github.com/fatih/hclfmt \
github.com/client9/misspell/cmd/misspell
# First clean, because we're gonna rebuild the std both with -race enabled and disabled
# Running go install std twice is intentional and required, as content is written in two different directories
# (/usr/local/go/pkg/linux_amd64 vs /usr/local/go/pkg/linux_amd64_race)
# The other architectures do not have support for -race
RUN go clean -i net \
&& go install -tags netgo std \
&& go install -race -tags netgo std
# Prebuild std for the other architectures
RUN for platform in ${GO_CROSSPLATFORMS}; do \
GOOS=${platform%/*} GOARCH=${platform##*/} \
go install -tags netgo std; done
# Allow full write access to the Go folders for anyone
RUN chmod -R a+w /usr/local/go
# The libpcap version from Debian packages is 1.6.2, matching that version here although newer versions of libpcap have been released
# We have to cross-compile the libpcap library for the new architectures, that's what we're doing here
ENV LIBPCAP_CROSS_VERSION=1.6.2
RUN curl -sSL http://www.tcpdump.org/release/libpcap-${LIBPCAP_CROSS_VERSION}.tar.gz | tar -xz \
RUN curl -sSL https://www.tcpdump.org/release/libpcap-${LIBPCAP_CROSS_VERSION}.tar.gz | tar -xz \
&& cd libpcap-${LIBPCAP_CROSS_VERSION} \
&& for crosscompiler in ${GCC_CROSSCOMPILERS}; do \
CC=${crosscompiler}-gcc ac_cv_linux_vers=2 ./configure --host=${crosscompiler} --with-pcap=linux \
@@ -86,5 +75,8 @@ RUN curl -sSL http://www.tcpdump.org/release/libpcap-${LIBPCAP_CROSS_VERSION}.ta
&& ln -sf libpcap.so.${MAJOR_VER} /usr/local/lib/libpcap.so \
&& make clean; done
# Install Docker
RUN curl -fsSL https://get.docker.com | VERSION=18.06.0-ce /bin/sh
COPY build.sh /
ENTRYPOINT ["sh", "/build.sh"]
@@ -0,0 +1 @@
bab3b4d04263479b3d9f85cf59bd0cad1f2b434f29856b2204f8288f2f3598e4 qemu-s390x-static
-66
View File
@@ -1,66 +0,0 @@
general:
branches:
ignore:
- gh\-pages
machine:
pre:
- curl -sSL https://s3.amazonaws.com/circle-downloads/install-circleci-docker.sh | bash -s -- 1.10.0
services:
- docker
environment:
GOPATH: /home/ubuntu:$GOPATH
SRCDIR: /home/ubuntu/src/github.com/weaveworks/weave
PATH: $PATH:$HOME/.local/bin:/opt/google-cloud-sdk/bin
CLOUDSDK_CORE_DISABLE_PROMPTS: 1
STATE: /home/ubuntu/state.env
# Base name of VMs for integration tests:
NAME: test-$CIRCLE_BUILD_NUM-$CIRCLE_NODE_INDEX
TEST_VMS_SETUP_OUTPUT_FILE: $CIRCLE_ARTIFACTS/test_vms_setup_output.txt
TEST_VMS_PROV_AND_CONF_LOCK_FILE: $CIRCLE_ARTIFACTS/test_vms_provisioned_and_configured.txt
TEST_VMS_READY_LOCK_FILE: $CIRCLE_ARTIFACTS/test_vms_ready.txt
# Google Cloud Platorm images for integration tests:
USE_IMAGE: 1
DISK_NAME_PREFIX: test-$CIRCLE_BUILD_NUM-0
dependencies:
cache_directories:
- "~/docker"
post:
- bin/circle-dependencies-post-sources
# Provision & configure testing VMs:
- "while [ ! -d $SRCDIR ]; do sleep 1; done; $SRCDIR/bin/provision_test_vms.sh":
parallel: true
background: true
- bin/circle-dependencies-post
test:
pre:
- "$SRCDIR/bin/circle-test-pre":
parallel: true
background: true
override:
- "$SRCDIR/bin/circle-test-unit":
parallel: true
- "$SRCDIR/bin/circle-test-smoke":
parallel: true
timeout: 360
post:
- "$SRCDIR/bin/circle-test-teardown":
parallel: true
teardown:
pre:
# Destroy testing VMs:
- "cd $SRCDIR/test && ./run-integration-tests.sh destroy":
parallel: true
background: true
- "$SRCDIR/bin/circle-teardown-pre":
parallel: true
deployment:
master:
branch: master
owner: weaveworks
commands:
- "$SRCDIR/bin/circle-deploy-master"
+3 -1
View File
@@ -99,7 +99,9 @@ func (c *Client) AddObserver(ob ContainerObserver) error {
pending := make(pendingStarts)
retryInterval := InitialInterval
for {
events := make(chan *docker.APIEvents)
// Use a buffered chan so the client library can run ahead of the listener
// - Docker will drop an event if it is not collected quickly enough.
events := make(chan *docker.APIEvents, 1024)
if err := c.AddEventListener(events); err != nil {
c.errorf("Unable to add listener to Docker API: %s - retrying in %ds", err, retryInterval/time.Second)
} else {
+6
View File
@@ -54,6 +54,12 @@ func SetLogLevel(levelname string) {
Log.Level = level
}
func CheckError(e error) {
if e != nil {
Log.Error(e)
}
}
func CheckFatal(e error) {
if e != nil {
Log.Fatal(e)
+5 -5
View File
@@ -35,21 +35,21 @@ weave-kube is an image with the weave binaries and a wrapper script installed. I
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`
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.conflist`
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`
3. Pass the CNI config - the contents of `/etc/cni/net.d/10-weave.conflist` 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`
2. Set up the config file at `/etc/cni/net.d/10-weave.conflist`
3. Run the `weave` initialization script
4. Run `weaver` with the correct configuration passed as command-line options
@@ -64,7 +64,7 @@ To add new options to how weave should run with each invocation, you would do th
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`
* set a default for the environment variable in `prog/weave-kube/weave-daemonset-k8s-N.N.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
* 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.conflist` and then have the CNI code in `plugin/net/cni.go` in `weaveutil` read it and use where appropriate
7. Document it!
+2 -2
View File
@@ -4,7 +4,7 @@
* Weave Net: v2.2.1.
* Kubernetes: v1.10.0.
* kube-proxy: iptables mode (default kubeadm options).
* kube-proxy: iptables/ipvs mode with `--masquerade-all=false` and `--cluster-cidr` unspecified(default kubeadm options).
* Hosts: `h1` and `h2`.
## Source IP
@@ -14,7 +14,7 @@
1 | Pod_h1 | ip(Pod_h2) | Pod_h2 | ip(Pod_h1) | OK
2 | h1 | ClusterIP | Pod_h1 | ip(weave_h1) | **NOK**
3 | h1 | ClusterIP | Pod_h2 | ip(weave_h1) | OK
4 | Pod_h1 | ClusterIP | Pod_h1 | ip(weave_h1) | **NOK**
4 | Pod_h1 | ClusterIP | Pod_h1 | ip(Pod_h1) | OK
5 | Pod_h1 | ClusterIP | Pod_h2 | ip(weave_h1) | OK
6 | h1 | ip(h1):NodePort | Pod_h1 | ip(weave_h1) | **NOK**
7 | h1 | ip(h1):NodePort | Pod_h2 | ip(weave_h1) | OK
+5 -1
View File
@@ -3,6 +3,7 @@
* Up-to-date versions of `git`, `go` etc
* Install GitHub release tool `go get github.com/weaveworks/github-release`
* Install manifest tool `go get github.com/estesp/manifest-tool`
* Create a [github token for
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
@@ -135,7 +136,7 @@ Now, you can validate whether images were published for all platforms:
# Published platforms per image:
for img in $(grep '^PUBLISH=' Makefile); do
img="weaveworks/$(echo $img | cut -d_ -f2):${TAG#v}"
platforms=$(vendor/github.com/estesp/manifest-tool/manifest-tool \
platforms=$(manifest-tool \
inspect --raw "$img" | \
jq '.[].Platform | .os + "/" +.architecture' | \
tr '\n' ' ')
@@ -154,6 +155,7 @@ Weave Net is [available in Docker Store](https://store.docker.com/plugins/weave-
* Go to "_Plans & Pricing_" > "_Free Tier_".
* Under "_Source Repositories & Tags_", click on "_Add Source_", select "_net-plugin_" under "_Repository_" and the version to release under "_Tag_".
* Under "_Resources_" > "_Installation Instructions_", update the lines containing `export NET_VERSION=<version>`.
* Click "_Save_"
* Click "_Submit For Review_". You should see a message like: "_Your product has been submitted for approval. [...] We'll be in touch with next steps soon!_".
* You should receive an email saying:
@@ -177,6 +179,8 @@ Weave Net is [available in Docker Store](https://store.docker.com/plugins/weave-
https://checkpoint-api.weave.works/admin
* File a PR to update the version of the daemonset at
https://github.com/kubernetes/kops/tree/master/upup/models/cloudup/resources/addons/networking.weave
and kops/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go
and kops/upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/weave/manifest.yaml
## Troubleshooting
+62 -12
View File
@@ -9,7 +9,9 @@ destroyed automatically in response to Pod, Namespace and
NetworkPolicy object updates from the k8s API server:
* A `hash:ip` set per namespace, containing the IP addresses of all
pods in that namespace
pods in that namespace for which default ingress is allowed
* A `hash:ip` set per namespace, containing the IP addresses of all
pods in that namespace for which default egress is allowed
* A `list:set` per distinct (across all network policies in all
namespaces) namespace selector mentioned in a network policy,
containing the names of any of the above hash:ip sets whose
@@ -18,6 +20,9 @@ NetworkPolicy object updates from the k8s API server:
containing network policy's namespace) pod selector mentioned in a
network policy, containing the IP addresses of all pods in the
namespace whose labels match that selector
* A `hash:net` set for each distinct (within the scope of the
containing network policy's namespace) `except` list of CIDR's mentioned in
the network policies
IPsets are implemented by the kernel module `xt_set`, without which
weave-npc will not work.
@@ -38,11 +43,21 @@ hashing to avoid clashes.
# iptables chains
The policy controller maintains two iptables chains in response to
changes to pods, namespaces and network policies. One chain contains
the ingress rules that implement the network policy specifications,
and the other is used to bypass the ingress rules for namespaces which
have an ingress isolation policy of `DefaultAllow`.
The policy controller maintains several iptables chains in response to
changes to pods, namespaces and network policies.
## Static `WEAVE-NPC` chain
`WEAVE-NPC` chain contains static rules to ACCEPT traffic that is `RELATED,ESTABLISHED`
and run `NEW` traffic through `WEAVE-NPC-DEFAULT` followed by `WEAVE-NPC-INGRESS` chains
Static configuration:
```
iptables -A WEAVE-NPC -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-DEFAULT
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-INGRESS
```
## Dynamically maintained `WEAVE-NPC-DEFAULT` chain
@@ -63,23 +78,58 @@ For each namespace network policy ingress rule peer/port combination:
iptables -A WEAVE-NPC-INGRESS -p $PROTO [-m set --match-set $SRCSET] -m set --match-set $DSTSET --dport $DPORT -j ACCEPT
```
## Static `WEAVE-NPC` chain
## Static `WEAVE-NPC-EGRESS` chain
`WEAVE-NPC-EGRESS` chain contains static rules to ACCEPT traffic that is `RELATED,ESTABLISHED`
and run `NEW` traffic through `WEAVE-NPC-EGRESS-DEFAULT` followed by `WEAVE-NPC-EGRESS-CUSTOM` chains
Static configuration:
```
iptables -A WEAVE-NPC -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-DEFAULT
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-INGRESS
iptables -A WEAVE-NPC-EGRESS -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A WEAVE-NPC-EGRESS -m state --state NEW -j WEAVE-NPC-EGRESS-DEFAULT
iptables -A WEAVE-NPC-EGRESS -m state --state NEW -m mark ! --mark 0x40000/0x40000 -j WEAVE-NPC-EGRESS-CUSTOM
iptables -A WEAVE-NPC-EGRESS -m mark ! --mark 0x40000/0x40000 -j DROP
```
## Dynamically maintained `WEAVE-NPC-EGRESS-DEFAULT` chain
The policy controller maintains a rule in this chain for every
namespace whose egress isolation policy is `DefaultAllow`. The
purpose of this rule is simply to ACCEPT any traffic originating from such namespace before it reaches the egress chain.
```
iptables -A WEAVE-NPC-EGRESS-DEFAULT -m set --match-set $NSIPSET src -j WEAVE-NPC-EGRESS-ACCEPT
iptables -A WEAVE-NPC-EGRESS-DEFAULT -m set --match-set $NSIPSET src -j RETURN
```
## Static `WEAVE-NPC-EGRESS-ACCEPT` chain
`WEAVE-NPC-EGRESS-ACCEPTS` chain contains static rules to mark traffic
Static configuration:
```
iptables -A WEAVE-NPC-EGRESS-ACCEPT -j MARK --set-xmark 0x40000/0x40000
```
## Dynamically maintained `WEAVE-NPC-EGRESS-CUSTOM` chain
For each namespace network policy egress rule peer/port combination:
```
iptables -A WEAVE-NPC-EGRESS-CUSTOM -p $PROTO [-m set --match-set $SRCSET] -m set --match-set $DSTSET --dport $DPORT -j ACCEPT
```
# Steering traffic into the policy engine
To direct traffic into the policy engine:
```
iptables -A FORWARD -o weave -m physdev ! --physdev-out vethwe-bridge -j WEAVE-NPC
iptables -A FORWARD -o weave -m physdev ! --physdev-out vethwe-bridge -j DROP
iptables -A INPUT -i weave -j WEAVE-NPC-EGRESS
iptables -A FORWARD -i weave -j WEAVE-NPC-EGRESS
iptables -A FORWARD -o weave -j WEAVE-NPC
```
Note this only affects traffic which egresses the bridge on a physical
+14 -3
View File
@@ -275,7 +275,7 @@ func (alloc *Allocator) spaceRequestDenied(sender mesh.PeerName, r address.Range
for i := 0; i < len(alloc.pendingClaims); {
claim := alloc.pendingClaims[i].(*claim)
if r.Contains(claim.cidr.Addr) {
claim.deniedBy(alloc, sender)
claim.deniedBy(alloc, sender, nil)
alloc.pendingClaims = append(alloc.pendingClaims[:i], alloc.pendingClaims[i+1:]...)
continue
}
@@ -814,6 +814,16 @@ func (alloc *Allocator) sendRingUpdate(dest mesh.PeerName) {
alloc.gossip.GossipUnicast(dest, msg)
}
func (alloc *Allocator) hasAllocations(rs []address.Range) bool {
for _, r := range rs {
alloc.debugf("hasAllocations: %v %v vs %v", r, alloc.space.NumFreeAddressesInRange(r), r.Size())
if alloc.space.NumFreeAddressesInRange(r) != r.Size() {
return true
}
}
return false
}
func (alloc *Allocator) update(sender mesh.PeerName, msg []byte) error {
reader := bytes.NewReader(msg)
decoder := gob.NewDecoder(reader)
@@ -832,7 +842,7 @@ func (alloc *Allocator) update(sender mesh.PeerName, msg []byte) error {
// If someone sent us a ring, merge it into ours. Note this will move us
// out of the awaiting-consensus state if we didn't have a ring already.
case data.Ring != nil:
updated, err := alloc.ring.Merge(*data.Ring)
updated, err := alloc.ring.Merge(*data.Ring, alloc.hasAllocations)
switch err {
case nil:
if updated {
@@ -910,6 +920,7 @@ func (alloc *Allocator) donateSpace(r address.Range, to mesh.PeerName) {
alloc.debugln("Giving range", chunk, "to", to)
alloc.ring.GrantRangeToHost(chunk.Start, chunk.End, to)
alloc.persistRing()
alloc.gossip.GossipBroadcast(alloc.Gossip())
}
func (alloc *Allocator) assertInvariants() {
@@ -985,7 +996,7 @@ func (alloc *Allocator) loadPersistedData() bool {
alloc.persistOwned()
}
if !nameFound || !ringFound {
if !nameFound || !ringFound || persistedRing == nil || persistedRing.Empty() {
overwritePersisted("No valid persisted data")
return false
}
+15 -4
View File
@@ -12,6 +12,7 @@ import (
type claim struct {
resultChan chan<- error
tryCount int
ident string // a container ID, something like "weave:expose", or api.NoContainerID
cidr address.CIDR // single address being claimed
isContainer bool // true if ident is a container ID
@@ -19,6 +20,8 @@ type claim struct {
hasBeenCancelled func() bool
}
const maxTryCount = 5
// Send an error (or nil for success) back to caller listening on resultChan
func (c *claim) sendResult(result error) {
// Make sure we only send a result once, since listener stops listening after that
@@ -40,6 +43,8 @@ func (c *claim) Try(alloc *Allocator) bool {
return true
}
c.tryCount++
addOwned := func() {
if c.ident == api.NoContainerID {
alloc.addOwned(c.cidr.Addr.String(), c.cidr, c.isContainer)
@@ -90,8 +95,10 @@ func (c *claim) Try(alloc *Allocator) bool {
if c.noErrorOnUnknown {
alloc.infof("Claim %s for %s: %s; will try later.", c.cidr, c.ident, err)
c.sendResult(nil)
} else { // just tell the user they can't do this.
c.deniedBy(alloc, owner)
} else if c.tryCount > maxTryCount {
// give up, tell the user they can't do this
c.deniedBy(alloc, owner, err)
return true
}
}
return false
@@ -128,12 +135,16 @@ func (c *claim) Try(alloc *Allocator) bool {
return true
}
func (c *claim) deniedBy(alloc *Allocator, owner mesh.PeerName) {
func (c *claim) deniedBy(alloc *Allocator, owner mesh.PeerName, err error) {
name, found := alloc.nicknames[owner]
if found {
name = " (" + name + ")"
}
c.sendResult(fmt.Errorf("address %s is owned by other peer %s%s", c.cidr.String(), owner, name))
reason := ""
if err != nil {
reason = fmt.Sprintf(" - %s", err)
}
c.sendResult(fmt.Errorf("address %s is owned by other peer %s%s%s", c.cidr.String(), owner, name, reason))
}
func (c *claim) Cancel() {
+5 -1
View File
@@ -199,6 +199,10 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
})
router.Methods("GET").Path("/ipinfo/tracker").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, alloc.tracker.String())
tracker := ""
if alloc.tracker != nil {
tracker = alloc.tracker.String()
}
fmt.Fprintf(w, tracker)
})
}
+2
View File
@@ -1,6 +1,7 @@
package ring
import (
"fmt"
"sort"
"github.com/weaveworks/mesh"
@@ -25,6 +26,7 @@ func (e *entry) Equal(e2 *entry) bool {
func (e *entry) update(peername mesh.PeerName, free address.Count) {
e.Peer = peername
e.Version++
common.Log.Debugln(fmt.Sprintf("Updating ring token=%s current peer=%s updated peer=%s new version=%s", e.Token, e.Peer, peername, fmt.Sprint(e.Version)))
e.Free = free
}
+65 -18
View File
@@ -213,7 +213,7 @@ func (r *Ring) GrantRangeToHost(start, end address.Address, peer mesh.PeerName)
// Merge the given ring into this ring and indicate whether this ring
// got updated as a result.
func (r *Ring) Merge(gossip Ring) (bool, error) {
func (r *Ring) Merge(gossip Ring, hasAllocations func(r []address.Range) bool) (bool, error) {
r.assertInvariants()
defer r.trackUpdates()()
@@ -238,12 +238,22 @@ func (r *Ring) Merge(gossip Ring) (bool, error) {
return false, ErrDifferentRange
}
result, updated, err := r.Entries.merge(gossip.Entries, r.Peer)
result, updated, err := r.Entries.merge(gossip.Entries, r.Peer, r, hasAllocations)
if err != nil {
return false, err
}
// reset the free space for entries if there is invalid free space
// due to accepting an unexpected update from the peers
for i := 0; i < len(result); i++ {
distance := r.distance(result.entry(i).Token, result.entry(i+1).Token)
if result.entry(i).Peer == r.Peer && result.entry(i).Free > distance {
// case that can arise when a range that we own that got split and had no allocations
result.entry(i).Free = distance
}
}
if err := r.checkEntries(result); err != nil {
return false, fmt.Errorf("Merge of incoming data causes: %s", err)
}
@@ -260,7 +270,7 @@ func (r *Ring) Merge(gossip Ring) (bool, error) {
// entries belonging to ourPeer. Returns the merged entries and an
// indication whether the merge resulted in any changes, i.e. the
// result differs from the original.
func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, updated bool, err error) {
func (es entries) merge(other entries, ourPeer mesh.PeerName, r *Ring, hasAllocations func(r []address.Range) bool) (result entries, updated bool, err error) {
var mine, theirs *entry
var previousOwner *mesh.PeerName
addToResult := func(e entry) { result = append(result, &e) }
@@ -274,6 +284,7 @@ func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, u
var i, j int
for i < len(es) && j < len(other) {
mine, theirs = es[i], other[j]
common.Log.Debugf("[ring %s]: Merge mine.Token=%s theirs.Token=%s mine.Peer=%s theirs.Peer=%s mine.Version=%v theirs.Version=%v", ourPeer, mine.Token, theirs.Token, mine.Peer, theirs.Peer, mine.Version, theirs.Version)
switch {
case mine.Token < theirs.Token:
addToResult(*mine)
@@ -282,8 +293,11 @@ func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, u
case mine.Token > theirs.Token:
// insert, checking that a range owned by us hasn't been split
if previousOwner != nil && *previousOwner == ourPeer && theirs.Peer != ourPeer {
err = errEntryInMyRange(theirs)
return
// check we have no allocations in the range that got split
if hasAllocations(r.makeRanges(theirs.Token, mine.Token)) {
err = errEntryInMyRange(theirs)
return
}
}
addTheirs(*theirs)
j++
@@ -292,17 +306,44 @@ func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, u
switch {
case mine.Version >= theirs.Version:
if mine.Version == theirs.Version && !mine.Equal(theirs) {
err = errInconsistentEntry(mine, theirs)
return
if mine.Peer == ourPeer {
// if we own the entry and has allocations
if hasAllocations(r.makeRanges(theirs.Token, es.entry(i+1).Token)) {
err = errInconsistentEntry(mine, theirs)
return
}
}
// tie-break here, pick the entry with the highest free count
if mine.Free >= theirs.Free {
addToResult(*mine)
previousOwner = &mine.Peer
} else {
addTheirs(*theirs)
}
} else {
addToResult(*mine)
previousOwner = &mine.Peer
}
addToResult(*mine)
previousOwner = &mine.Peer
case mine.Version < theirs.Version:
if mine.Peer == ourPeer { // We shouldn't receive updates to our own tokens
err = errNewerVersion(mine, theirs)
return
if mine.Peer == ourPeer {
// We received update to our own tokens accept the received entry
// if either it belongs to a different peer and we do not have allocations
// in the range effectively given away, or it belongs to our own peer, in
// which case we should set our version to the one received plus one,
// effectively imposing our existing entry.
if theirs.Peer != ourPeer && !hasAllocations(r.makeRanges(mine.Token, es.entry(i+1).Token)) {
common.Log.Infof("ring: repair inconsistent data by accepting token %v from %v - no allocations up to %v", theirs.Token, theirs.Peer, es.entry(i+1).Token)
addTheirs(*theirs)
} else if theirs.Peer == ourPeer {
mine.Version = theirs.Version + 1
addToResult(*mine)
} else {
err = errNewerVersion(mine, theirs)
return
}
} else {
addTheirs(*theirs)
}
addTheirs(*theirs)
}
i++
j++
@@ -334,6 +375,11 @@ func (r *Ring) Empty() bool {
return len(r.Entries) == 0
}
// convenience function to normalise a single range that may span zero
func (r *Ring) makeRanges(start, end address.Address) []address.Range {
return r.splitRangesOverZero([]address.Range{{Start: start, End: end}})
}
// Given a slice of ranges which are all in the right order except
// possibly the last one spans zero, fix that up and return the slice
func (r *Ring) splitRangesOverZero(ranges []address.Range) []address.Range {
@@ -384,10 +430,7 @@ type RangeInfo struct {
func (r *Ring) AllRangeInfo() (result []RangeInfo) {
for i, entry := range r.Entries {
nextEntry := r.Entries.entry(i + 1)
ranges := []address.Range{{Start: entry.Token, End: nextEntry.Token}}
ranges = r.splitRangesOverZero(ranges)
for _, r := range ranges {
for _, r := range r.makeRanges(entry.Token, r.Entries.entry(i+1).Token) {
result = append(result, RangeInfo{entry.Peer, r, entry.Version})
}
}
@@ -485,6 +528,7 @@ func (r *Ring) ReportFree(freespace map[address.Address]address.Count) (updated
entries[i].Free = free
entries[i].Version++
common.Log.Debugf("[ring %s]: ReportFree token=%s peer=%s version=%v", r.Peer, entries[i].Token, entries[i].Peer, entries[i].Version)
updated = true
}
return
@@ -565,7 +609,10 @@ func (r *Ring) Transfer(from, to mesh.PeerName) []address.Range {
for i, entry := range r.Entries {
if entry.Peer == from {
entry.Peer = to
entry.Version++
// bump version by large value so that transfer of range takes precedence (if there is any conflict in merging entry)
// over other opertaions on the entry that increments the version
entry.Version = entry.Version + 100
common.Log.Debugf("[ring %s]: Transfer token=%s from=%s to=%s version=%v", r.Peer, entry.Token, from, to, entry.Version)
newRanges = append(newRanges, address.Range{Start: entry.Token, End: r.Entries.entry(i + 1).Token})
}
}
+76 -8
View File
@@ -32,7 +32,27 @@ func ParseIP(s string) address.Address {
}
func merge(r1, r2 *Ring) error {
_, err := r1.Merge(*r2)
distance := func(start, end address.Address) address.Count {
if end > start {
return address.Count(end - start)
}
return address.Count((r1.End - start) + (end - r1.Start))
}
check := func(rs []address.Range) bool {
for _, r := range rs {
size := distance(r.Start, r.End)
entry, found := r1.Entries.get(r.Start)
if !found {
continue
}
if entry.Free < size {
return true
}
}
return false
}
_, err := r1.Merge(*r2, check)
return err
}
@@ -219,6 +239,61 @@ func TestMergeSimple(t *testing.T) {
require.Equal(t, ring2.Entries, ring1.Entries)
}
func TestMergeWithConflicts(t *testing.T) {
// received update to entry with a token and version identical to an entry we have
// but but holding different content, if there are no allocations, resolve the
// conflict by picking entry one with high free count
ring1 := NewRing(start, end, peer1name)
ring2 := NewRing(start, end, peer2name)
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 256, Version: 1}}
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Free: 256, Version: 1}}
require.NoError(t, merge(ring1, ring2))
// received update to entry with a token and version identical to an entry we have
// but but holding different content, if there are allocations, then reject the received
// entry
ring1 = NewRing(start, end, peer1name)
ring2 = NewRing(start, end, peer2name)
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 128, Version: 1}}
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Free: 256, Version: 1}}
require.Error(t, merge(ring1, ring2), "Expected error")
// received an entry with update to one of our own tokens and with new version,
// accept the received entry if its still going to belong to us
ring1 = NewRing(start, end, peer1name)
ring2 = NewRing(start, end, peer2name)
ring1.Entries = []*entry{{Token: start, Peer: peer1name}}
ring2.Entries = []*entry{{Token: start, Peer: peer1name, Version: 1}}
require.NoError(t, merge(ring1, ring2))
// received an entry with update to one of our own tokens and with new version,
// but belongs to a different peer, accept the received entry if we do not
// have allocations in the range
ring1 = NewRing(start, end, peer1name)
ring2 = NewRing(start, end, peer2name)
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 256}}
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Free: 256, Version: 1}}
require.NoError(t, merge(ring1, ring2))
// received an entry with update to one of our own tokens and with new version,
// reject received entry if we have allocations in the range
ring1 = NewRing(start, end, peer1name)
ring2 = NewRing(start, end, peer2name)
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 128}}
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Version: 1}}
require.Error(t, merge(ring1, ring2), "Expected error")
// we receive an entry that splits one of our ranges, giving some of it
// away to another peer. accept the entry provided that we have no allocations
// in the range that got given away.
ring1 = NewRing(start, end, peer1name)
ring2 = NewRing(start, end, peer2name)
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 256, Version: 1}}
ring2.Entries = []*entry{{Token: start, Peer: peer1name, Free: 128, Version: 2}, {Token: middle, Peer: peer2name, Free: 128}}
require.NoError(t, merge(ring1, ring2))
}
func TestMergeErrors(t *testing.T) {
// Cannot Merge in an invalid ring
ring1 := NewRing(start, end, peer1name)
@@ -231,13 +306,6 @@ func TestMergeErrors(t *testing.T) {
ring2.Entries = []*entry{}
require.True(t, merge(ring1, ring2) == ErrDifferentRange, "Expected ErrDifferentRange")
// Cannot Merge newer version of entry I own
ring2 = NewRing(start, end, peer2name)
ring1.Entries = []*entry{{Token: start, Peer: peer1name}}
ring2.Entries = []*entry{{Token: start, Peer: peer1name, Version: 1}}
fmt.Println(merge(ring1, ring2))
require.Error(t, merge(ring1, ring2), "Expected error")
// Cannot Merge two entries with same version but different hosts
ring1.Entries = []*entry{{Token: start, Peer: peer1name}}
ring2.Entries = []*entry{{Token: start, Peer: peer2name}}
+3
View File
@@ -65,6 +65,9 @@ func (m *mockGossipComms) GossipBroadcast(update mesh.GossipData) {
}
}
func (m *mockGossipComms) GossipNeighbourSubset(update mesh.GossipData) {
m.GossipBroadcast(update)
}
func equalByteBuffer(a, b []byte) bool {
if len(a) != len(b) {
return false
+59 -13
View File
@@ -5,6 +5,7 @@ import (
"io/ioutil"
"net"
"path/filepath"
"syscall"
"github.com/coreos/go-iptables/iptables"
"github.com/pkg/errors"
@@ -62,10 +63,10 @@ const (
)
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
init(procPath string, config *BridgeConfig) error // create and initialise bridge device(s)
attach(veth *netlink.Veth) error // attach veth to bridge
IsFastdp() bool // does this bridge use fastdp?
String() string // human-readable type string
}
// Used to indicate a fallback to the Bridge type
@@ -220,6 +221,7 @@ type BridgeConfig struct {
MTU int
Mac string
Port int
ControlPort string
NoMasqLocal bool
}
@@ -249,7 +251,7 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
}
for {
if err := bridgeType.init(config); err != nil {
if err := bridgeType.init(procPath, config); err != nil {
if errors.Cause(err) == errBridgeNotSupported {
log.Warnf("Skipping bridge creation of %q due to: %s", bridgeType, err)
bridgeType = bridgeImpl{}
@@ -278,11 +280,19 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
return bridgeType, errors.Wrap(err, "setting proxy_arp")
}
}
// No ipv6 router advertisments please
if err := sysctl(procPath, "net/ipv6/conf/"+config.WeaveBridgeName+"/accept_ra", "0"); err != nil {
return bridgeType, errors.Wrap(err, "setting accept_ra to 0")
}
if err := linkSetUpByName(config.WeaveBridgeName); err != nil {
return bridgeType, err
}
if err := monitorInterface(config.WeaveBridgeName, log); 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)
}
@@ -304,7 +314,10 @@ func (b bridgeImpl) initPrep(config *BridgeConfig) error {
linkAttrs := netlink.NewLinkAttrs()
linkAttrs.Name = config.WeaveBridgeName
linkAttrs.HardwareAddr = mac
// NB: Do not set MAC addr when creating the bridge, set it manually
// afterwards instead. Otherwise, on an older than 3.14 kernel FDB
// entry won't be created which results in containers not being able to
// reach the bridge w/o promiscuous mode.
if config.MTU == 0 {
config.MTU = 65535
}
@@ -337,11 +350,11 @@ func (b bridgeImpl) initPrep(config *BridgeConfig) error {
return nil
}
func (b bridgeImpl) init(config *BridgeConfig) error {
func (b bridgeImpl) init(procPath string, config *BridgeConfig) error {
if err := b.initPrep(config); err != nil {
return err
}
if _, err := CreateAndAttachVeth(BridgeIfName, PcapIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
if _, err := CreateAndAttachVeth(procPath, BridgeIfName, PcapIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
return netlink.LinkSetUp(veth)
}); err != nil {
return errors.Wrap(err, "creating pcap veth pair")
@@ -353,7 +366,7 @@ func (b bridgeImpl) init(config *BridgeConfig) error {
return nil
}
func (f fastdpImpl) init(config *BridgeConfig) error {
func (f fastdpImpl) init(procPath string, config *BridgeConfig) error {
odpSupported, err := odp.CreateDatapath(f.datapathName)
if !odpSupported {
msg := ""
@@ -384,14 +397,14 @@ func (f fastdpImpl) init(config *BridgeConfig) error {
return nil
}
func (bf bridgedFastdpImpl) init(config *BridgeConfig) error {
if err := bf.fastdpImpl.init(config); err != nil {
func (bf bridgedFastdpImpl) init(procPath string, config *BridgeConfig) error {
if err := bf.fastdpImpl.init(procPath, 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, false, func(veth netlink.Link) error {
if _, err := CreateAndAttachVeth(procPath, BridgeIfName, DatapathIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
if err := netlink.LinkSetUp(veth); err != nil {
return errors.Wrapf(err, "setting link up on %q", veth.Attrs().Name)
}
@@ -457,6 +470,18 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
}
}
if config.ControlPort != "" {
if err = ipt.AppendUnique("filter", "INPUT", "-p", "tcp", "--dst", "127.0.0.1", "--dport", config.ControlPort,
"-m", "addrtype", "!", "--src-type", "LOCAL",
"-m", "conntrack", "!", "--ctstate", "RELATED,ESTABLISHED",
"-m", "comment", "--comment", "Block non-local access to Weave Net control port",
"-j", "DROP"); err != nil {
return err
}
}
// Remove the rule from Weave Net 2.6.3 which dropped too much.
_ = ipt.Delete("filter", "INPUT", "-p", "tcp", "--dst", "127.0.0.1", "-m", "addrtype", "!", "--src-type", "LOCAL", "-m", "conntrack", "!", "--ctstate", "RELATED,ESTABLISHED", "-j", "DROP")
if config.NPC {
// Steer traffic via the NPC.
@@ -602,10 +627,31 @@ func reexpose(config *BridgeConfig, log *logrus.Logger) error {
for _, addr := range addrs {
log.Infof("Re-exposing %s on bridge %q", addr.IPNet, config.WeaveBridgeName)
if err := Expose(config.WeaveBridgeName, addr.IPNet, config.AWSVPC, config.NPC); err != nil {
if err := Expose(config.WeaveBridgeName, addr.IPNet, config.AWSVPC, config.NPC, false); err != nil {
return errors.Wrapf(err, "unable to re-expose %s on bridge: %q", addr.IPNet, config.WeaveBridgeName)
}
}
return nil
}
func monitorInterface(ifaceName string, log *logrus.Logger) error {
_, err := netlink.LinkByName(ifaceName)
if err != nil {
return fmt.Errorf("Unable to find link %q: %s", ifaceName, err)
}
updatesChannel := make(chan netlink.LinkUpdate)
if err := netlink.LinkSubscribe(updatesChannel, nil); err != nil {
return errors.Wrapf(err, "error monitoring link %q for UP/DOWN notifications", ifaceName)
}
go func() {
for update := range updatesChannel {
if update.Link.Attrs().Name == ifaceName && update.IfInfomsg.Flags&syscall.IFF_UP == 0 {
log.Errorf("Interface %q which needs to be in UP state for Weave functioning is found to be in DOWN state", ifaceName)
}
}
}()
return nil
}
+6 -3
View File
@@ -18,7 +18,8 @@ import (
// * "ipAddr" - IP addr to be assigned to the bridge.
// * "removeDefaultRoute" - whether to remove a default route installed by the kernel (used only in the AWSVPC mode).
// * "npc" - whether is Weave NPC running.
func Expose(bridgeName string, ipAddr *net.IPNet, removeDefaultRoute, npc bool) error {
// * "skipNAT" - whether to skip adding iptables NAT rules
func Expose(bridgeName string, ipAddr *net.IPNet, removeDefaultRoute, npc bool, skipNAT bool) error {
ipt, err := iptables.New()
if err != nil {
return errors.Wrap(err, "iptables.New")
@@ -29,8 +30,10 @@ func Expose(bridgeName string, ipAddr *net.IPNet, removeDefaultRoute, npc bool)
return errors.Wrap(err, "addBridgeIPAddr")
}
if err := exposeNAT(ipt, cidr); err != nil {
return errors.Wrap(err, "exposeNAT")
if !skipNAT {
if err := exposeNAT(ipt, cidr); err != nil {
return errors.Wrap(err, "exposeNAT")
}
}
if !npc {
+22 -16
View File
@@ -85,7 +85,7 @@ func New(log *logrus.Logger) (*IPSec, error) {
// InitSALocal initializes inbound ipsec from remotePeer and triggers
// the initialization on remotePeer.
func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uint64, localIP, remoteIP net.IP, udpPort int, sessionKey *[32]byte, initRemote func([]byte) error) error {
func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uint64, localIP, remoteIP net.IP, udpPort int, sessionKey *[32]byte) ([]byte, error) {
// ID of inbound SPI
spiID := getSPIId(remotePeer, localPeer, connUID)
@@ -95,17 +95,17 @@ func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uin
// Derive SA key
nonce, err := genNonce()
if err != nil {
return errors.Wrap(err, "generate nonce")
return nil, errors.Wrap(err, "generate nonce")
}
key, err := deriveKey(sessionKey[:], nonce, localPeer)
if err != nil {
return errors.Wrap(err, "derive key")
return nil, errors.Wrap(err, "derive key")
}
// Allocate SA
sa, err := netlink.XfrmStateAllocSpi(xfrmAllocSpiState(remoteIP, localIP))
if err != nil {
return errors.Wrap(err, fmt.Sprintf("ip xfrm state allocspi (in, %s, %s)", remoteIP, localIP))
return nil, errors.Wrap(err, fmt.Sprintf("ip xfrm state allocspi (in, %s, %s)", remoteIP, localIP))
}
// Use SPI generated by the kernel. The kernel ensures {dstIP, spi} to
@@ -117,28 +117,24 @@ func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uin
// Create SA
if sa, err := xfrmState(remoteIP, localIP, spi, false, key); err == nil {
if err := netlink.XfrmStateUpdate(sa); err != nil {
return errors.Wrap(err, fmt.Sprintf("xfrm state update (in, %s, %s, 0x%x)", sa.Src, sa.Dst, sa.Spi))
return nil, errors.Wrap(err, fmt.Sprintf("xfrm state update (in, %s, %s, 0x%x)", sa.Src, sa.Dst, sa.Spi))
}
} else {
return errors.Wrap(err, "new xfrm state (in)")
return nil, errors.Wrap(err, "new xfrm state (in)")
}
// Install iptables rules
if err := ipsec.installDropNonEncrypted(localIP, remoteIP, udpPort, spi); err != nil {
return errors.Wrap(err, fmt.Sprintf("install protecting rules (%s, %s, %d, 0x%x)", localIP, remoteIP, udpPort, spi))
return nil, errors.Wrap(err, fmt.Sprintf("install protecting rules (%s, %s, %d, 0x%x)", localIP, remoteIP, udpPort, spi))
}
si := spiInfo{spi: spi, isDirOut: false}
ipsec.spiInfo[spiID] = si
ipsec.spis[spi] = &si
// Trigger the initialization on the remote peer
// Generate the message to trigger initialization on the remote peer
msg := &msgInitSARemote{nonce, spi}
if err := initRemote(msg.serialize()); err != nil {
return errors.Wrap(err, "send InitSARemote")
}
return nil
return msg.serialize(), nil
}
// InitSARemote initializes outbound ipsec to remotePeer.
@@ -223,9 +219,19 @@ func (ipsec *IPSec) Destroy(localPeer, remotePeer mesh.PeerName, connUID uint64,
if outSPIInfo, ok := ipsec.spiInfo[outSPIID]; ok {
ipsec.log.Infof("ipsec: destroy: out %s -> %s 0x%x", localIP, remoteIP, outSPIInfo.spi)
if err := netlink.XfrmPolicyDel(xfrmPolicy(localIP, remoteIP, outSPIInfo.spi)); err != nil {
ipsec.log.Warnf("ipsec: xfrm policy del (%s, %s, 0x%x) failed: %s", localIP, remoteIP, outSPIInfo.spi, err)
policy, err := netlink.XfrmPolicyGet(xfrmPolicy(localIP, remoteIP, outSPIInfo.spi))
if err != nil {
ipsec.log.Warnf("ipsec: xfrm policy get (%s, %s, 0x%x) failed: %s", localIP, remoteIP, outSPIInfo.spi, err)
} else {
if len(policy.Tmpls) == 1 {
if policy.Tmpls[0].Spi == int(outSPIInfo.spi) {
if err := netlink.XfrmPolicyDel(xfrmPolicy(localIP, remoteIP, outSPIInfo.spi)); err != nil {
ipsec.log.Warnf("ipsec: xfrm policy del (%s, %s, 0x%x) failed: %s", localIP, remoteIP, outSPIInfo.spi, err)
}
} else {
ipsec.log.Debugf("ipsec: xfrm not my policy (%s, %s, 0x%x) got 0x%x ", localIP, remoteIP, outSPIInfo.spi, policy.Tmpls[0].Spi)
}
}
}
outSA := &netlink.XfrmState{
+3 -3
View File
@@ -55,9 +55,9 @@ func WithNetNSByPath(path string, work func() error) error {
}
func NSPathByPid(pid int) string {
return NSPathByPidWithRoot("/", pid)
return NSPathByPidWithProc("/proc", pid)
}
func NSPathByPidWithRoot(root string, pid int) string {
return filepath.Join(root, fmt.Sprintf("/proc/%d/ns/net", pid))
func NSPathByPidWithProc(procPath string, pid int) string {
return filepath.Join(procPath, fmt.Sprint(pid), "/ns/net")
}
+17 -8
View File
@@ -13,7 +13,7 @@ import (
)
// create and attach a veth to the Weave bridge
func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, keepTXOn bool, errIfLinkExist bool, init func(peer netlink.Link) error) (*netlink.Veth, error) {
func CreateAndAttachVeth(procPath, name, peerName, bridgeName string, mtu int, keepTXOn bool, errIfLinkExist bool, init func(peer netlink.Link) error) (*netlink.Veth, error) {
bridge, err := netlink.LinkByName(bridgeName)
if err != nil {
return nil, fmt.Errorf(`bridge "%s" not present; did you launch weave?`, bridgeName)
@@ -49,6 +49,13 @@ func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, keepTXOn bo
if err := bridgeType.attach(veth); err != nil {
return cleanup("attaching veth %q to %q: %s", name, bridgeName, err)
}
// No ipv6 router advertisments please
if err := sysctl(procPath, "net/ipv6/conf/"+name+"/accept_ra", "0"); err != nil {
return cleanup("setting accept_ra to 0: %s", err)
}
if err := sysctl(procPath, "net/ipv6/conf/"+peerName+"/accept_ra", "0"); err != nil {
return cleanup("setting accept_ra to 0: %s", err)
}
if !bridgeType.IsFastdp() && !keepTXOn {
if err := EthtoolTXOff(veth.PeerName); err != nil {
return cleanup(`unable to set tx off on %q: %s`, peerName, err)
@@ -112,6 +119,9 @@ func interfaceExistsInNamespace(netNSPath string, ifName string) bool {
}
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool, hairpinMode bool) error {
// AttachContainer expects to be called in host pid namespace
const procPath = "/proc"
ns, err := netns.GetFromPath(netNSPath)
if err != nil {
return err
@@ -124,12 +134,12 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
id = id[:maxIDLen] // trim passed ID if too long
}
name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id
veth, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, true, func(veth netlink.Link) error {
veth, err := CreateAndAttachVeth(procPath, name, peerName, bridgeName, mtu, keepTXOn, true, func(veth netlink.Link) error {
if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil {
return fmt.Errorf("failed to move veth to container netns: %s", err)
}
if err := WithNetNS(ns, func() error {
return setupIface(peerName, ifName)
return setupIface(procPath, peerName, ifName)
}); err != nil {
return fmt.Errorf("error setting up interface: %s", err)
}
@@ -206,7 +216,7 @@ func setupIfaceAddrs(veth netlink.Link, withMulticastRoute bool, cidrs []*net.IP
}
// setupIface expects to be called in the container's netns
func setupIface(ifaceName, newIfName string) error {
func setupIface(procPath, ifaceName, newIfName string) error {
ipt, err := iptables.New()
if err != nil {
return err
@@ -219,15 +229,14 @@ func setupIface(ifaceName, newIfName string) error {
if err := netlink.LinkSetName(link, newIfName); err != nil {
return err
}
// This is only called by AttachContainer which is only called in host pid namespace
if err := configureARPCache("/proc", newIfName); err != nil {
if err := configureARPCache(procPath, newIfName); err != nil {
return err
}
return ipt.Append("filter", "INPUT", "-i", newIfName, "-d", "224.0.0.0/4", "-j", "DROP")
}
// configureARP is a helper for the Docker plugin which doesn't set the addresses itself
func ConfigureARP(prefix, rootPath string) error {
func ConfigureARP(prefix, procPath string) error {
links, err := netlink.LinkList()
if err != nil {
return err
@@ -235,7 +244,7 @@ func ConfigureARP(prefix, rootPath string) error {
for _, link := range links {
ifName := link.Attrs().Name
if strings.HasPrefix(ifName, prefix) {
configureARPCache(rootPath+"/proc", ifName)
configureARPCache(procPath, ifName)
if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil {
for _, addr := range addrs {
arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName)
+60 -19
View File
@@ -12,12 +12,14 @@ import (
func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
rules map[string]*ruleSpec,
nsSelectors, podSelectors map[string]*selectorSpec,
nsSelectors, podSelectors, namespacedPodSelectors map[string]*selectorSpec,
ipBlocks map[string]*ipBlockSpec,
err error) {
nsSelectors = make(map[string]*selectorSpec)
podSelectors = make(map[string]*selectorSpec)
namespacedPodSelectors = make(map[string]*selectorSpec)
ipBlocks = make(map[string]*ipBlockSpec)
rules = make(map[string]*ruleSpec)
policyTypes := make([]policyType, 0)
@@ -31,9 +33,9 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
}
}
// If empty, matches all pods in a namespace
targetSelector, err := newSelectorSpec(&policy.Spec.PodSelector, policyTypes, ns.name, ipset.HashIP)
targetSelector, err := newSelectorSpec(&policy.Spec.PodSelector, nil, policyTypes, ns.name, ipset.HashIP)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
// To prevent targetSelector being overwritten by a subsequent selector with
@@ -50,6 +52,12 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
// If From is empty or missing, this rule matches all sources
allSources := ingressRule.From == nil || len(ingressRule.From) == 0
if !allPorts {
if err = checkForNamedPorts(ingressRule.Ports); err != nil {
return nil, nil, nil, nil, nil, fmt.Errorf("named ports in network policies is not supported yet. "+
"Rejecting network policy: %s from further processing. "+err.Error(), policy.Name)
}
}
if allSources {
if allPorts {
rule := newRuleSpec(policyTypeIngress, nil, nil, targetSelector, nil)
@@ -63,30 +71,42 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
} else {
for _, peer := range ingressRule.From {
var srcSelector *selectorSpec
var srcRuleHost ruleHost
// NetworkPolicyPeer describes a peer to allow traffic from.
// Exactly one of its fields must be specified.
if peer.PodSelector != nil {
srcSelector, err = newSelectorSpec(peer.PodSelector, nil, ns.name, ipset.HashIP)
if peer.PodSelector != nil && peer.NamespaceSelector != nil {
srcSelector, err = newSelectorSpec(peer.PodSelector, peer.NamespaceSelector, nil, "", ipset.HashIP)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
addIfNotExist(srcSelector, namespacedPodSelectors)
srcRuleHost = srcSelector
} else if peer.PodSelector != nil {
srcSelector, err = newSelectorSpec(peer.PodSelector, nil, nil, ns.name, ipset.HashIP)
if err != nil {
return nil, nil, nil, nil, nil, err
}
addIfNotExist(srcSelector, podSelectors)
srcRuleHost = srcSelector
} else if peer.NamespaceSelector != nil {
srcSelector, err = newSelectorSpec(peer.NamespaceSelector, nil, "", ipset.ListSet)
srcSelector, err = newSelectorSpec(nil, peer.NamespaceSelector, nil, "", ipset.ListSet)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
nsSelectors[srcSelector.key] = srcSelector
srcRuleHost = srcSelector
} else if peer.IPBlock != nil {
ipBlock := newIPBlockSpec(peer.IPBlock, ns.name)
ipBlocks[ipBlock.key] = ipBlock
srcRuleHost = ipBlock
}
if allPorts {
rule := newRuleSpec(policyTypeIngress, nil, srcSelector, targetSelector, nil)
rule := newRuleSpec(policyTypeIngress, nil, srcRuleHost, targetSelector, nil)
rules[rule.key] = rule
} else {
withNormalisedProtoAndPort(ingressRule.Ports, func(proto, port string) {
rule := newRuleSpec(policyTypeIngress, &proto, srcSelector, targetSelector, &port)
rule := newRuleSpec(policyTypeIngress, &proto, srcRuleHost, targetSelector, &port)
rules[rule.key] = rule
})
}
@@ -103,6 +123,12 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
// If To is empty or missing, this rule matches all destinations
allDestinations := egressRule.To == nil || len(egressRule.To) == 0
if !allPorts {
if err = checkForNamedPorts(egressRule.Ports); err != nil {
return nil, nil, nil, nil, nil, fmt.Errorf("named ports in network policies is not supported yet. "+
"Rejecting network policy: %s from further processing. "+err.Error(), policy.Name)
}
}
if allDestinations {
if allPorts {
rule := newRuleSpec(policyTypeEgress, nil, targetSelector, nil, nil)
@@ -119,19 +145,25 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
var dstRuleHost ruleHost
// NetworkPolicyPeer describes a peer to allow traffic to.
// Exactly one of its fields must be specified.
if peer.PodSelector != nil {
dstSelector, err = newSelectorSpec(peer.PodSelector, nil, ns.name, ipset.HashIP)
if peer.PodSelector != nil && peer.NamespaceSelector != nil {
dstSelector, err = newSelectorSpec(peer.PodSelector, peer.NamespaceSelector, nil, "", ipset.HashIP)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
addIfNotExist(dstSelector, namespacedPodSelectors)
dstRuleHost = dstSelector
} else if peer.PodSelector != nil {
dstSelector, err = newSelectorSpec(peer.PodSelector, nil, nil, ns.name, ipset.HashIP)
if err != nil {
return nil, nil, nil, nil, nil, err
}
addIfNotExist(dstSelector, podSelectors)
dstRuleHost = dstSelector
} else if peer.NamespaceSelector != nil {
dstSelector, err = newSelectorSpec(peer.NamespaceSelector, nil, "", ipset.ListSet)
dstSelector, err = newSelectorSpec(nil, peer.NamespaceSelector, nil, "", ipset.ListSet)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
nsSelectors[dstSelector.key] = dstSelector
dstRuleHost = dstSelector
@@ -155,7 +187,7 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
}
}
return rules, nsSelectors, podSelectors, ipBlocks, nil
return rules, nsSelectors, podSelectors, namespacedPodSelectors, ipBlocks, nil
}
func addIfNotExist(s *selectorSpec, ss map[string]*selectorSpec) {
@@ -195,3 +227,12 @@ func port(p *intstr.IntOrString) string {
return port
}
func checkForNamedPorts(ports []networkingv1.NetworkPolicyPort) error {
for _, npProtocolPort := range ports {
if npProtocolPort.Port != nil && npProtocolPort.Port.Type == intstr.String {
return fmt.Errorf("named port %s in network policy", port(npProtocolPort.Port))
}
}
return nil
}
+74 -14
View File
@@ -1,12 +1,15 @@
package npc
import (
"fmt"
"sync"
"github.com/pkg/errors"
coreapi "k8s.io/api/core/v1"
extnapi "k8s.io/api/extensions/v1beta1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/net/ipset"
@@ -32,30 +35,33 @@ type controller struct {
nodeName string // my node name
ipt iptables.Interface
ips ipset.Interface
nss map[string]*ns // ns name -> ns struct
nsSelectors *selectorSet // selector string -> nsSelector
ipt iptables.Interface
ips ipset.Interface
clientset kubernetes.Interface
nss map[string]*ns // ns name -> ns struct
nsSelectors *selectorSet // selector string -> nsSelector
namespacedPodSelectors *selectorSet
defaultEgressDrop bool // flag to track if base iptable rule to drop egress traffic is added or not
}
func New(nodeName string, ipt iptables.Interface, ips ipset.Interface) NetworkPolicyController {
func New(nodeName string, ipt iptables.Interface, ips ipset.Interface, clientset kubernetes.Interface) NetworkPolicyController {
c := &controller{
nodeName: nodeName,
ipt: ipt,
ips: ips,
nss: make(map[string]*ns)}
nodeName: nodeName,
ipt: ipt,
ips: ips,
clientset: clientset,
nss: make(map[string]*ns)}
doNothing := func(*selector, policyType) error { return nil }
c.nsSelectors = newSelectorSet(ips, c.onNewNsSelector, doNothing, doNothing)
c.namespacedPodSelectors = newSelectorSet(ips, c.onNewNamespacePodsSelector, doNothing, doNothing)
return c
}
func (npc *controller) onNewNsSelector(selector *selector) error {
for _, ns := range npc.nss {
if ns.namespace != nil {
if selector.matches(ns.namespace.ObjectMeta.Labels) {
if selector.matchesNamespaceSelector(ns.namespace.ObjectMeta.Labels) {
if err := selector.addEntry(ns.namespace.ObjectMeta.UID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil {
return err
}
@@ -65,10 +71,32 @@ func (npc *controller) onNewNsSelector(selector *selector) error {
return nil
}
func (npc *controller) onNewNamespacePodsSelector(selector *selector) error {
for _, ns := range npc.nss {
if ns.namespace != nil && len(ns.pods) > 0 {
for _, pod := range ns.pods {
if hasIP(pod) {
if selector.matchesNamespacedPodSelector(pod.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels) {
if err := selector.addEntry(pod.ObjectMeta.UID, pod.Status.PodIP, podComment(pod)); err != nil {
return err
}
}
}
}
}
}
return nil
}
func (npc *controller) withNS(name string, f func(ns *ns) error) error {
ns, found := npc.nss[name]
if !found {
newNs, err := newNS(name, npc.nodeName, npc.ipt, npc.ips, npc.nsSelectors)
namespace, err := npc.clientset.CoreV1().Namespaces().Get(name, metav1.GetOptions{})
if err != nil {
return err
}
newNs, err := newNS(name, npc.nodeName, npc.ipt, npc.ips, npc.nsSelectors, npc.namespacedPodSelectors, namespace)
if err != nil {
return err
}
@@ -121,11 +149,26 @@ func (npc *controller) AddNetworkPolicy(obj interface{}) error {
npc.Lock()
defer npc.Unlock()
// lazily add default rule to drop egress traffic only when network policies are applied
if !npc.defaultEgressDrop {
egressNetworkPolicy, err := isEgressNetworkPolicy(obj)
if err != nil {
return err
}
if egressNetworkPolicy {
npc.defaultEgressDrop = true
if err := npc.ipt.Append(TableFilter, EgressChain,
"-m", "mark", "!", "--mark", EgressMark, "-j", "DROP"); err != nil {
npc.defaultEgressDrop = false
return fmt.Errorf("Failed to add iptable rule to drop egress traffic from the pods by default due to %s", err.Error())
}
}
}
nsName, err := nsName(obj)
if err != nil {
return err
}
common.Log.Infof("EVENT AddNetworkPolicy %s", js(obj))
return npc.withNS(nsName, func(ns *ns) error {
return errors.Wrap(ns.addNetworkPolicy(obj), "add network policy")
@@ -202,3 +245,20 @@ func nsName(obj interface{}) (string, error) {
return "", errInvalidNetworkPolicyObjType
}
func isEgressNetworkPolicy(obj interface{}) (bool, error) {
if policy, ok := obj.(*networkingv1.NetworkPolicy); ok {
if len(policy.Spec.PolicyTypes) > 0 {
for _, policyType := range policy.Spec.PolicyTypes {
if policyType == networkingv1.PolicyTypeEgress {
return true, nil
}
}
}
if policy.Spec.Egress != nil {
return true, nil
}
return false, nil
}
return false, errInvalidNetworkPolicyObjType
}
+104 -6
View File
@@ -14,6 +14,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/kubernetes/fake"
)
type mockSet struct {
@@ -198,7 +199,10 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
// Namespaces first
m := newMockIPSet()
controller := New("foo", newMockIPTables(), &m)
client := fake.NewSimpleClientset()
controller := New("foo", newMockIPTables(), &m, client)
client.CoreV1().Namespaces().Create(sourceNamespace)
client.CoreV1().Namespaces().Create(destinationNamespace)
const (
selectorIPSetName = "weave-I239Zp%sCvoVt*D6u=A!2]YEk"
@@ -214,7 +218,7 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
// NetworkPolicy first
m = newMockIPSet()
controller = New("foo", newMockIPTables(), &m)
controller = New("foo", newMockIPTables(), &m, &fake.Clientset{})
controller.AddNetworkPolicy(networkPolicy)
@@ -235,7 +239,7 @@ func TestDefaultAllow(t *testing.T) {
)
m := newMockIPSet()
controller := New("bar", newMockIPTables(), &m)
controller := New("bar", newMockIPTables(), &m, &fake.Clientset{})
defaultNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
@@ -363,13 +367,15 @@ func TestOutOfOrderPodEvents(t *testing.T) {
)
m := newMockIPSet()
controller := New("qux", newMockIPTables(), &m)
client := fake.NewSimpleClientset()
controller := New("qux", newMockIPTables(), &m, client)
defaultNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
},
}
client.CoreV1().Namespaces().Create(defaultNamespace)
controller.AddNamespace(defaultNamespace)
podFoo := &coreapi.Pod{
@@ -445,13 +451,15 @@ func TestNewTargetSelector(t *testing.T) {
)
m := newMockIPSet()
controller := New("baz", newMockIPTables(), &m)
client := fake.NewSimpleClientset()
controller := New("baz", newMockIPTables(), &m, client)
defaultNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
},
}
client.CoreV1().Namespaces().Create(defaultNamespace)
controller.AddNamespace(defaultNamespace)
podFoo := &coreapi.Pod{
@@ -521,7 +529,21 @@ func TestEgressPolicyWithIPBlock(t *testing.T) {
m := newMockIPSet()
ipt := newMockIPTables()
controller := New("foo", ipt, &m)
client := fake.NewSimpleClientset()
controller := New("foo", ipt, &m, client)
defaultNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
},
}
nonDefaultNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "non-default",
},
}
client.CoreV1().Namespaces().Create(defaultNamespace)
client.CoreV1().Namespaces().Create(nonDefaultNamespace)
netpolFoo := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
@@ -592,3 +614,79 @@ func TestEgressPolicyWithIPBlock(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 2, len(m.sets[exceptIPSetNameInNonDefault].subSets))
}
// Test case for https://github.com/weaveworks/weave/issues/3653
func TestIngressPolicyWithIPBlockAndPortSpecified(t *testing.T) {
const (
barPodIP = "10.32.0.11"
runBarIPSetName = "weave-bZ~x=yBgzH)Ht()K*Uv3z{M]Y"
)
m := newMockIPSet()
ipt := newMockIPTables()
client := fake.NewSimpleClientset()
controller := New("any", ipt, &m, client)
defaultNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
},
}
client.CoreV1().Namespaces().Create(defaultNamespace)
podBar := &coreapi.Pod{
ObjectMeta: metav1.ObjectMeta{
UID: "bar",
Namespace: "default",
Name: "bar",
Labels: map[string]string{"run": "bar"}},
Status: coreapi.PodStatus{PodIP: barPodIP}}
controller.AddPod(podBar)
defer controller.DeletePod(podBar)
portProtocol := coreapi.ProtocolTCP
port := intstr.FromInt(80)
netpolicty := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
UID: "ipblock-bar",
Name: "allow-ipblock-to-bar",
Namespace: "default",
},
Spec: networkingv1.NetworkPolicySpec{
PolicyTypes: []networkingv1.PolicyType{
networkingv1.PolicyTypeIngress,
},
PodSelector: metav1.LabelSelector{MatchLabels: podBar.Labels},
Ingress: []networkingv1.NetworkPolicyIngressRule{
{
Ports: []networkingv1.NetworkPolicyPort{
{
Protocol: &portProtocol,
Port: &port,
},
},
From: []networkingv1.NetworkPolicyPeer{
{
IPBlock: &networkingv1.IPBlock{
CIDR: "192.168.48.4/32",
},
},
},
},
},
},
}
err := controller.AddNetworkPolicy(netpolicty)
require.NoError(t, err)
defer controller.DeleteNetworkPolicy(netpolicty)
require.Equal(t, 1, len(m.sets[runBarIPSetName].subSets))
require.True(t, m.entryExists(runBarIPSetName, barPodIP))
require.Equal(t, 1, len(ipt.rules[IngressChain]))
for rule := range ipt.rules[IngressChain] {
require.Contains(t, rule, "-s 192.168.48.4/32 -m set --match-set "+runBarIPSetName+" dst --dport 80")
}
}
+9
View File
@@ -22,6 +22,12 @@ var (
},
[]string{"protocol", "dport"},
)
PolicyEnforcementErrors = prometheus.NewCounter(
prometheus.CounterOpts{
Name: "weavenpc_policy_enforcement_errors",
Help: "Errors occured in enforcing the network policies.",
},
)
)
func gatherMetrics() {
@@ -95,6 +101,9 @@ func Start(addr string) error {
if err := prometheus.Register(blockedConnections); err != nil {
return err
}
if err := prometheus.Register(PolicyEnforcementErrors); err != nil {
return err
}
http.Handle("/metrics", promhttp.Handler())
+87 -53
View File
@@ -37,30 +37,33 @@ type ns struct {
ingressDefaultAllowIPSet ipset.Name
egressDefaultAllowIPSet ipset.Name
nsSelectors *selectorSet
podSelectors *selectorSet
ipBlocks *ipBlockSet
rules *ruleSet
nsSelectors *selectorSet // reference to global selectorSet that is shared across the `ns`. Used to represent all pods in the matching namespaces
podSelectors *selectorSet // used to represent the matching pods in namespace respresented by this `ns`
namespacedPodsSelectors *selectorSet // reference to global selectorSet that is shared across the `ns`. Used to represent matching pods in matching namespace
ipBlocks *ipBlockSet
rules *ruleSet
}
func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, nsSelectors *selectorSet) (*ns, error) {
allPods, err := newSelectorSpec(&metav1.LabelSelector{}, nil, name, ipset.HashIP)
func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, nsSelectors *selectorSet, namespacedPodsSelectors *selectorSet, namespaceObj *coreapi.Namespace) (*ns, error) {
allPods, err := newSelectorSpec(&metav1.LabelSelector{}, nil, nil, name, ipset.HashIP)
if err != nil {
return nil, err
}
ns := &ns{
ipt: ipt,
ips: ips,
name: name,
nodeName: nodeName,
pods: make(map[types.UID]*coreapi.Pod),
policies: make(map[types.UID]interface{}),
uid: uuid.NewUUID(),
allPods: allPods,
nsSelectors: nsSelectors,
ipBlocks: newIPBlockSet(ips),
rules: newRuleSet(ipt),
ipt: ipt,
ips: ips,
name: name,
namespace: namespaceObj,
nodeName: nodeName,
pods: make(map[types.UID]*coreapi.Pod),
policies: make(map[types.UID]interface{}),
uid: uuid.NewUUID(),
allPods: allPods,
nsSelectors: nsSelectors,
namespacedPodsSelectors: namespacedPodsSelectors,
ipBlocks: newIPBlockSet(ips),
rules: newRuleSet(ipt),
}
ns.podSelectors = newSelectorSet(ips, ns.onNewPodSelector, ns.onNewTargetPodSelector, ns.onDestroyTargetPodSelector)
@@ -95,7 +98,7 @@ func (ns *ns) destroy() error {
func (ns *ns) onNewPodSelector(selector *selector) error {
for _, pod := range ns.pods {
if hasIP(pod) {
if selector.matches(pod.ObjectMeta.Labels) {
if selector.matchesPodSelector(pod.ObjectMeta.Labels) {
if err := selector.addEntry(pod.ObjectMeta.UID, pod.Status.PodIP, podComment(pod)); err != nil {
return err
}
@@ -111,7 +114,7 @@ func (ns *ns) onNewTargetPodSelector(selector *selector, policyType policyType)
if hasIP(pod) {
// Remove the pod from default-allow if dst podselector matches the pod
ipset := ns.defaultAllowIPSetName(policyType)
if selector.matches(pod.ObjectMeta.Labels) {
if selector.matchesPodSelector(pod.ObjectMeta.Labels) {
if err := ns.ips.DelEntry(pod.ObjectMeta.UID, ipset, pod.Status.PodIP); err != nil {
return err
}
@@ -125,7 +128,7 @@ func (ns *ns) onNewTargetPodSelector(selector *selector, policyType policyType)
func (ns *ns) onDestroyTargetPodSelector(selector *selector, policyType policyType) error {
for _, pod := range ns.pods {
if hasIP(pod) {
if selector.matches(pod.ObjectMeta.Labels) {
if selector.matchesPodSelector(pod.ObjectMeta.Labels) {
if err := ns.addToDefaultAllowIfNoMatching(pod, policyType); err != nil {
return err
}
@@ -141,7 +144,7 @@ func (ns *ns) addToDefaultAllowIfNoMatching(pod *coreapi.Pod, policyType policyT
found := false
// TODO(mp) optimize (avoid iterating over selectors) by ref counting IP addrs.
for _, s := range ns.podSelectors.entries {
if ns.podSelectors.targetSelectorExist(s, policyType) && s.matches(pod.ObjectMeta.Labels) {
if ns.podSelectors.targetSelectorExist(s, policyType) && s.matchesPodSelector(pod.ObjectMeta.Labels) {
found = true
break
}
@@ -169,11 +172,7 @@ func (ns *ns) addPod(obj *coreapi.Pod) error {
return nil
}
if ns.checkLocalPod(obj) {
ns.ips.AddEntry(obj.ObjectMeta.UID, LocalIpset, obj.Status.PodIP, podComment(obj))
}
foundIngress, foundEgress, err := ns.podSelectors.addToMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
if err != nil {
return err
}
@@ -189,6 +188,11 @@ func (ns *ns) addPod(obj *coreapi.Pod) error {
}
}
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
if err != nil {
return err
}
return nil
}
@@ -201,25 +205,21 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
}
if hasIP(oldObj) && !hasIP(newObj) {
if ns.checkLocalPod(oldObj) {
ns.ips.DelEntry(oldObj.ObjectMeta.UID, LocalIpset, oldObj.Status.PodIP)
}
if err := ns.ips.DelEntry(oldObj.ObjectMeta.UID, ns.ingressDefaultAllowIPSet, oldObj.Status.PodIP); err != nil {
return err
}
if err := ns.ips.DelEntry(oldObj.ObjectMeta.UID, ns.egressDefaultAllowIPSet, oldObj.Status.PodIP); err != nil {
return err
}
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(oldObj.ObjectMeta.UID, oldObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, oldObj.Status.PodIP); err != nil {
return err
}
return ns.podSelectors.delFromMatching(oldObj.ObjectMeta.UID, oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
return ns.podSelectors.delFromMatchingPodSelector(oldObj.ObjectMeta.UID, oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
}
if !hasIP(oldObj) && hasIP(newObj) {
if ns.checkLocalPod(newObj) {
ns.ips.AddEntry(newObj.ObjectMeta.UID, LocalIpset, newObj.Status.PodIP, podComment(newObj))
}
foundIngress, foundEgress, err := ns.podSelectors.addToMatching(newObj.ObjectMeta.UID, newObj.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(newObj.ObjectMeta.UID, newObj.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
if err != nil {
return err
}
@@ -234,6 +234,10 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
return err
}
}
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(newObj.ObjectMeta.UID, newObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
if err != nil {
return err
}
return nil
}
@@ -251,8 +255,8 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
oldObj.Status.PodIP != newObj.Status.PodIP {
for _, ps := range ns.podSelectors.entries {
oldMatch := ps.matches(oldObj.ObjectMeta.Labels)
newMatch := ps.matches(newObj.ObjectMeta.Labels)
oldMatch := ps.matchesPodSelector(oldObj.ObjectMeta.Labels)
newMatch := ps.matchesPodSelector(newObj.ObjectMeta.Labels)
if oldMatch == newMatch && oldObj.Status.PodIP == newObj.Status.PodIP {
continue
}
@@ -274,6 +278,23 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
return err
}
}
for _, ps := range ns.namespacedPodsSelectors.entries {
oldMatch := ps.matchesNamespacedPodSelector(oldObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels)
newMatch := ps.matchesNamespacedPodSelector(newObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels)
if oldMatch == newMatch && oldObj.Status.PodIP == newObj.Status.PodIP {
continue
}
if oldMatch {
if err := ps.delEntry(oldObj.ObjectMeta.UID, oldObj.Status.PodIP); err != nil {
return err
}
}
if newMatch {
if err := ps.addEntry(newObj.ObjectMeta.UID, newObj.Status.PodIP, podComment(newObj)); err != nil {
return err
}
}
}
}
return nil
@@ -303,24 +324,25 @@ func (ns *ns) deletePod(obj *coreapi.Pod) error {
return nil
}
if ns.checkLocalPod(obj) {
ns.ips.DelEntry(obj.ObjectMeta.UID, LocalIpset, obj.Status.PodIP)
}
if err := ns.ips.DelEntry(obj.ObjectMeta.UID, ns.ingressDefaultAllowIPSet, obj.Status.PodIP); err != nil {
return err
}
if err := ns.ips.DelEntry(obj.ObjectMeta.UID, ns.egressDefaultAllowIPSet, obj.Status.PodIP); err != nil {
return err
}
return ns.podSelectors.delFromMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP)
if err := ns.podSelectors.delFromMatchingPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP); err != nil {
return err
}
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, obj.Status.PodIP); err != nil {
return err
}
return nil
}
func (ns *ns) addNetworkPolicy(obj interface{}) error {
// Analyse policy, determine which rules and ipsets are required
uid, rules, nsSelectors, podSelectors, ipBlocks, err := ns.analyse(obj)
uid, rules, nsSelectors, podSelectors, namespacedPodsSelectors, ipBlocks, err := ns.analyse(obj)
if err != nil {
return err
}
@@ -332,6 +354,9 @@ func (ns *ns) addNetworkPolicy(obj interface{}) error {
if err := ns.podSelectors.provision(uid, nil, podSelectors); err != nil {
return err
}
if err := ns.namespacedPodsSelectors.provision(uid, nil, namespacedPodsSelectors); err != nil {
return err
}
if err := ns.ipBlocks.provision(uid, nil, ipBlocks); err != nil {
return err
}
@@ -340,11 +365,11 @@ func (ns *ns) addNetworkPolicy(obj interface{}) error {
func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
// Analyse the old and the new policy so we can determine differences
oldUID, oldRules, oldNsSelectors, oldPodSelectors, oldIPBlocks, err := ns.analyse(oldObj)
oldUID, oldRules, oldNsSelectors, oldPodSelectors, oldNamespacedPodsSelectors, oldIPBlocks, err := ns.analyse(oldObj)
if err != nil {
return err
}
newUID, newRules, newNsSelectors, newPodSelectors, newIPBlocks, err := ns.analyse(newObj)
newUID, newRules, newNsSelectors, newPodSelectors, newNamespacedPodsSelectors, newIPBlocks, err := ns.analyse(newObj)
if err != nil {
return err
}
@@ -362,6 +387,9 @@ func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
if err := ns.podSelectors.deprovision(oldUID, oldPodSelectors, newPodSelectors); err != nil {
return err
}
if err := ns.namespacedPodsSelectors.deprovision(oldUID, oldNamespacedPodsSelectors, newNamespacedPodsSelectors); err != nil {
return err
}
if err := ns.ipBlocks.deprovision(oldUID, oldIPBlocks, newIPBlocks); err != nil {
return err
}
@@ -371,6 +399,9 @@ func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
if err := ns.podSelectors.provision(oldUID, oldPodSelectors, newPodSelectors); err != nil {
return err
}
if err := ns.namespacedPodsSelectors.provision(oldUID, oldNamespacedPodsSelectors, newNamespacedPodsSelectors); err != nil {
return err
}
if err := ns.ipBlocks.provision(oldUID, oldIPBlocks, newIPBlocks); err != nil {
return err
}
@@ -379,7 +410,7 @@ func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
func (ns *ns) deleteNetworkPolicy(obj interface{}) error {
// Analyse network policy to free resources
uid, rules, nsSelectors, podSelectors, ipBlocks, err := ns.analyse(obj)
uid, rules, nsSelectors, podSelectors, namespacedPodsSelectors, ipBlocks, err := ns.analyse(obj)
if err != nil {
return err
}
@@ -396,6 +427,9 @@ func (ns *ns) deleteNetworkPolicy(obj interface{}) error {
if err := ns.podSelectors.deprovision(uid, podSelectors, nil); err != nil {
return err
}
if err := ns.namespacedPodsSelectors.deprovision(uid, namespacedPodsSelectors, nil); err != nil {
return err
}
if err := ns.ipBlocks.deprovision(uid, ipBlocks, nil); err != nil {
return err
}
@@ -469,7 +503,7 @@ func (ns *ns) addNamespace(obj *coreapi.Namespace) error {
}
// Add namespace ipset to matching namespace selectors
_, _, err := ns.nsSelectors.addToMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName), namespaceComment(ns))
err := ns.nsSelectors.addToMatchingNamespaceSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName), namespaceComment(ns))
return err
}
@@ -479,8 +513,8 @@ func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
// Re-evaluate namespace selector membership if labels have changed
if !equals(oldObj.ObjectMeta.Labels, newObj.ObjectMeta.Labels) {
for _, selector := range ns.nsSelectors.entries {
oldMatch := selector.matches(oldObj.ObjectMeta.Labels)
newMatch := selector.matches(newObj.ObjectMeta.Labels)
oldMatch := selector.matchesNamespaceSelector(oldObj.ObjectMeta.Labels)
newMatch := selector.matchesNamespaceSelector(newObj.ObjectMeta.Labels)
if oldMatch == newMatch {
continue
}
@@ -509,7 +543,7 @@ func (ns *ns) deleteNamespace(obj *coreapi.Namespace) error {
}
// Remove namespace ipset from any matching namespace selectors
err := ns.nsSelectors.delFromMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
err := ns.nsSelectors.delFromMatchingNamespaceSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
if err != nil {
return err
}
@@ -561,7 +595,7 @@ func (ns *ns) defaultAllowIPSetName(pt policyType) ipset.Name {
func (ns *ns) analyse(obj interface{}) (
uid types.UID,
rules map[string]*ruleSpec,
nsSelectors, podSelectors map[string]*selectorSpec,
nsSelectors, podSelectors, namespacedPodsSelectors map[string]*selectorSpec,
ipBlocks map[string]*ipBlockSpec,
err error) {
@@ -577,7 +611,7 @@ func (ns *ns) analyse(obj interface{}) (
ns.policies[uid] = obj
// Analyse policy, determine which rules and ipsets are required
rules, nsSelectors, podSelectors, ipBlocks, err = ns.analysePolicy(obj.(*networkingv1.NetworkPolicy))
rules, nsSelectors, podSelectors, namespacedPodsSelectors, ipBlocks, err = ns.analysePolicy(obj.(*networkingv1.NetworkPolicy))
if err != nil {
return
}
+83 -17
View File
@@ -12,25 +12,39 @@ import (
)
type selectorSpec struct {
key string // string representation (for hash keying/equality comparison)
selector labels.Selector // k8s Selector object (for matching)
policyTypes []policyType // If non-empty, then selectorSpec is a target selector for given policyTypes.
key string // string representation (for hash keying/equality comparison)
podSelector labels.Selector // k8s Selector object (for matching pods)
namespaceSelector labels.Selector // k8s Selector object (for matching namespaces)
policyTypes []policyType // If non-empty, then selectorSpec is a target selector for given policyTypes.
ipsetType ipset.Type // type of ipset to provision
ipsetName ipset.Name // generated ipset name
nsName string // Namespace name
}
func newSelectorSpec(json *metav1.LabelSelector, policyType []policyType, nsName string, ipsetType ipset.Type) (*selectorSpec, error) {
selector, err := metav1.LabelSelectorAsSelector(json)
if err != nil {
return nil, err
func newSelectorSpec(podJSON *metav1.LabelSelector, namespaceJSON *metav1.LabelSelector, policyType []policyType, nsName string, ipsetType ipset.Type) (*selectorSpec, error) {
var podSelector, namespaceSelector labels.Selector
var err error
var key string
if namespaceJSON != nil {
namespaceSelector, err = metav1.LabelSelectorAsSelector(namespaceJSON)
if err != nil {
return nil, err
}
key = namespaceSelector.String()
}
if podJSON != nil {
podSelector, err = metav1.LabelSelectorAsSelector(podJSON)
if err != nil {
return nil, err
}
key = key + podSelector.String()
}
key := selector.String()
return &selectorSpec{
key: key,
selector: selector,
policyTypes: policyType,
key: key,
podSelector: podSelector,
namespaceSelector: namespaceSelector,
policyTypes: policyType,
// We prefix the selector string with the namespace name when generating
// the shortname because you can specify the same selector in multiple
// namespaces - we need those to map to distinct ipsets
@@ -61,8 +75,16 @@ type selector struct {
spec *selectorSpec
}
func (s *selector) matches(labelMap map[string]string) bool {
return s.spec.selector.Matches(labels.Set(labelMap))
func (s *selector) matchesPodSelector(podsLabelMap map[string]string) bool {
return s.spec.podSelector.Matches(labels.Set(podsLabelMap))
}
func (s *selector) matchesNamespaceSelector(namespaceLabelMap map[string]string) bool {
return s.spec.namespaceSelector.Matches(labels.Set(namespaceLabelMap))
}
func (s *selector) matchesNamespacedPodSelector(podsLabelMap, namespaceLabelMap map[string]string) bool {
return s.spec.podSelector.Matches(labels.Set(podsLabelMap)) && s.spec.namespaceSelector.Matches(labels.Set(namespaceLabelMap))
}
func (s *selector) addEntry(user types.UID, entry string, comment string) error {
@@ -105,11 +127,11 @@ func newSelectorSet(ips ipset.Interface, onNewSelector selectorFn, onNewTargetSe
targetSelectorsCount: make(map[string]map[policyType]int)}
}
func (ss *selectorSet) addToMatching(user types.UID, labelMap map[string]string, entry string, comment string) (bool, bool, error) {
func (ss *selectorSet) addToMatchingPodSelector(user types.UID, podLabelsMap map[string]string, entry string, comment string) (bool, bool, error) {
foundIngress := false
foundEgress := false
for _, s := range ss.entries {
if s.matches(labelMap) {
if s.matchesPodSelector(podLabelsMap) {
if ss.targetSelectorExist(s, policyTypeIngress) {
foundIngress = true
}
@@ -124,9 +146,53 @@ func (ss *selectorSet) addToMatching(user types.UID, labelMap map[string]string,
return foundIngress, foundEgress, nil
}
func (ss *selectorSet) delFromMatching(user types.UID, labelMap map[string]string, entry string) error {
func (ss *selectorSet) addToMatchingNamespaceSelector(user types.UID, namespaceLabelsMap map[string]string, entry string, comment string) error {
for _, s := range ss.entries {
if s.matches(labelMap) {
if s.matchesNamespaceSelector(namespaceLabelsMap) {
if err := s.addEntry(user, entry, comment); err != nil {
return err
}
}
}
return nil
}
func (ss *selectorSet) addToMatchingNamespacedPodSelector(user types.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string, comment string) error {
for _, s := range ss.entries {
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
if err := s.addEntry(user, entry, comment); err != nil {
return err
}
}
}
return nil
}
func (ss *selectorSet) delFromMatchingPodSelector(user types.UID, podLabelsMap map[string]string, entry string) error {
for _, s := range ss.entries {
if s.matchesPodSelector(podLabelsMap) {
if err := s.delEntry(user, entry); err != nil {
return err
}
}
}
return nil
}
func (ss *selectorSet) delFromMatchingNamespaceSelector(user types.UID, namespaceLabelsMap map[string]string, entry string) error {
for _, s := range ss.entries {
if s.matchesNamespaceSelector(namespaceLabelsMap) {
if err := s.delEntry(user, entry); err != nil {
return err
}
}
}
return nil
}
func (ss *selectorSet) delFromMatchingNamespacedPodSelector(user types.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string) error {
for _, s := range ss.entries {
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
if err := s.delEntry(user, entry); err != nil {
return err
}
+7
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"net"
"os"
"strings"
"github.com/containernetworking/cni/pkg/ipam"
"github.com/containernetworking/cni/pkg/skel"
@@ -206,7 +207,13 @@ func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
err = ipam.ExecDel(conf.IPAM.Type, args.StdinData)
}
if err != nil {
if strings.Contains(err.Error(), fmt.Sprintf("Delete: no addresses for %s", args.ContainerID)) {
// ignore the error in the case where there are no IP addresses associated with container
fmt.Fprintln(os.Stderr, "weave-cni:", fmt.Sprintf("Delete: no addresses for %s", args.ContainerID))
return nil
}
logOnStderr(fmt.Errorf("unable to release IP address: %s", err))
return err
}
return nil
}
+4 -2
View File
@@ -39,9 +39,10 @@ type driver struct {
// used only by plugin-v2
forceMulticast bool
networks map[string]network
procPath string
}
func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2, forceMulticast bool) (skel.Driver, error) {
func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2, forceMulticast bool, procPath string) (skel.Driver, error) {
driver := &driver{
name: name,
scope: scope,
@@ -51,6 +52,7 @@ func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns,
// make sure that it's used only by plugin-v2
forceMulticast: isPluginV2 && forceMulticast,
networks: make(map[string]network),
procPath: procPath,
}
// Do not start watcher in the case of plugin v2, which prevents us from
@@ -134,7 +136,7 @@ func (driver *driver) CreateEndpoint(create *api.CreateEndpointRequest) (*api.Cr
// create veths. note we assume endpoint IDs are unique in the first 9 chars
name, peerName := vethPair(create.EndpointID)
if _, err := weavenet.CreateAndAttachVeth(name, peerName, weavenet.WeaveBridgeName, 0, false, true, nil); err != nil {
if _, err := weavenet.CreateAndAttachVeth(driver.procPath, name, peerName, weavenet.WeaveBridgeName, 0, false, true, nil); err != nil {
return nil, driver.error("JoinEndpoint", "%s", err)
}
+2 -7
View File
@@ -43,14 +43,9 @@ func (w *watcher) ContainerStarted(id string) {
w.driver.warn("ContainerStarted", "unable to register %s with weaveDNS: %s", id, err)
}
}
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)
netNSPath := weavenet.NSPathByPidWithProc(w.driver.procPath, info.State.Pid)
if err := weavenet.WithNetNSByPath(netNSPath, func() error {
return weavenet.ConfigureARP(weavenet.VethName, rootDir)
return weavenet.ConfigureARP(weavenet.VethName, w.driver.procPath)
}); err != nil {
w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err)
}
+5 -4
View File
@@ -32,6 +32,7 @@ type Config struct {
EnableV2Multicast bool
DNS bool
DefaultSubnet string
ProcPath string // path to reach host /proc filesystem
}
type Plugin struct {
@@ -62,7 +63,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
endChan := make(chan error, 1)
if plugin.Socket != "" {
globalListener, err := listenAndServe(dockerClient, weave, plugin.Socket, endChan, "global", false, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
globalListener, err := listenAndServe(dockerClient, weave, plugin.Socket, endChan, "global", false, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast, plugin.ProcPath)
if err != nil {
return err
}
@@ -70,7 +71,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
defer globalListener.Close()
}
if plugin.MeshSocket != "" {
meshListener, err := listenAndServe(dockerClient, weave, plugin.MeshSocket, endChan, "local", true, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
meshListener, err := listenAndServe(dockerClient, weave, plugin.MeshSocket, endChan, "local", true, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast, plugin.ProcPath)
if err != nil {
return err
}
@@ -87,7 +88,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
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) {
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, dns bool, isPluginV2, forceMulticast bool, procPath string) (net.Listener, error) {
var name string
if isPluginV2 {
name = pluginV2Name
@@ -95,7 +96,7 @@ func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address
name = pluginNameFromAddress(address)
}
d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2, forceMulticast)
d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2, forceMulticast, procPath)
if err != nil {
return nil, err
}
+8 -64
View File
@@ -2,13 +2,10 @@
In order to keep track of active weave peers, we use annotations on the Kubernetes cluster.
Kubernetes uses etcd to distribute and synchronise these annotations so we don't have to.
This module deals with operations on the peerlist backed by Kubernetes' annotation mechanism.
*/
package main
import (
"encoding/json"
"log"
"time"
@@ -29,43 +26,11 @@ type configMapAnnotations struct {
cm *v1.ConfigMap
}
func newConfigMapAnnotations(ns string, configMapName string, clientset *kubernetes.Clientset) *configMapAnnotations {
func newConfigMapAnnotations(ns string, configMapName string, c kubernetes.Interface) *configMapAnnotations {
return &configMapAnnotations{
Namespace: ns,
ConfigMapName: configMapName,
Client: clientset.CoreV1(),
}
}
type peerList struct {
Peers []peerInfo
}
type peerInfo struct {
PeerName string // Weave internal unique ID
NodeName string // Kubernetes node name
}
func (pl peerList) contains(peerName string) bool {
for _, peer := range pl.Peers {
if peer.PeerName == peerName {
return true
}
}
return false
}
func (pl *peerList) add(peerName string, name string) {
pl.Peers = append(pl.Peers, peerInfo{PeerName: peerName, NodeName: name})
}
func (pl *peerList) remove(peerNameToRemove string) {
for i := 0; i < len(pl.Peers); {
if pl.Peers[i].PeerName == peerNameToRemove {
pl.Peers = append(pl.Peers[:i], pl.Peers[i+1:]...)
} else {
i++
}
Client: c.CoreV1(),
}
}
@@ -111,27 +76,6 @@ func (cml *configMapAnnotations) Init() error {
return nil
}
func (cml *configMapAnnotations) GetPeerList() (*peerList, error) {
var record peerList
if cml.cm == nil {
return nil, errors.New("endpoint not initialized, call Init first")
}
if recordBytes, found := cml.cm.Annotations[KubePeersAnnotationKey]; found {
if err := json.Unmarshal([]byte(recordBytes), &record); err != nil {
return nil, err
}
}
return &record, nil
}
func (cml *configMapAnnotations) UpdatePeerList(list peerList) error {
recordBytes, err := json.Marshal(list)
if err != nil {
return err
}
return cml.UpdateAnnotation(KubePeersAnnotationKey, string(recordBytes))
}
// Clean up a string so it meets the Kubernetes requiremements for Annotation keys:
// name part must consist of alphanumeric characters, '-', '_' or '.', and must
// start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or '123-abc')
@@ -152,33 +96,33 @@ func (cml *configMapAnnotations) GetAnnotation(key string) (string, bool) {
}
func (cml *configMapAnnotations) UpdateAnnotation(key, value string) (err error) {
if cml.cm == nil {
if cml.cm == nil || cml.cm.Annotations == nil {
return errors.New("endpoint not initialized, call Init first")
}
// speculatively change the state, then replace with whatever comes back
// from Update(), which will be the latest on the server whatever happened
// from Update(), which will be the latest on the server, or nil if error
cml.cm.Annotations[cleanKey(key)] = value
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm)
return err
}
func (cml *configMapAnnotations) RemoveAnnotation(key string) (err error) {
if cml.cm == nil {
if cml.cm == nil || cml.cm.Annotations == nil {
return errors.New("endpoint not initialized, call Init first")
}
// speculatively change the state, then replace with whatever comes back
// from Update(), which will be the latest on the server whatever happened
// from Update(), which will be the latest on the server, or nil if error
delete(cml.cm.Annotations, cleanKey(key))
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm)
return err
}
func (cml *configMapAnnotations) RemoveAnnotationsWithValue(valueToRemove string) (err error) {
if cml.cm == nil {
if cml.cm == nil || cml.cm.Annotations == nil {
return errors.New("endpoint not initialized, call Init first")
}
// speculatively change the state, then replace with whatever comes back
// from Update(), which will be the latest on the server whatever happened
// from Update(), which will be the latest on the server, or nil if error
for key, value := range cml.cm.Annotations {
if value == valueToRemove {
delete(cml.cm.Annotations, key) // don't need to clean this key as it came from the map
+30
View File
@@ -0,0 +1,30 @@
// Adapted from k8s.io/client-go/kubernetes/fake to use a modified ObjectTracker
package main
import (
"k8s.io/apimachinery/pkg/runtime"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/testing"
weavetracker "github.com/weaveworks/weave/testing/kubernetes/testing"
)
var scheme = runtime.NewScheme()
var codecs = serializer.NewCodecFactory(scheme)
func NewSimpleClientset(objects ...runtime.Object) *fake.Clientset {
o := weavetracker.NewObjectTracker(scheme, codecs.UniversalDecoder())
for _, obj := range objects {
if err := o.Add(obj); err != nil {
panic(err)
}
}
ret := fake.Clientset{}
ret.AddReactor("*", "*", weavetracker.ObjectReaction(o))
ret.AddWatchReactor("*", testing.DefaultWatchReactor(watch.NewFake(), nil))
return &ret
}
+231 -92
View File
@@ -8,12 +8,20 @@ package main
import (
"flag"
"fmt"
"math/rand"
"net"
"os"
"os/signal"
"syscall"
"time"
"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
api "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
weaveapi "github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
@@ -25,7 +33,7 @@ type nodeInfo struct {
}
// return the IP addresses of all nodes in the cluster
func getKubePeers(c *kubernetes.Clientset) ([]nodeInfo, error) {
func getKubePeers(c kubernetes.Interface, includeWithNoIPAddr bool) ([]nodeInfo, error) {
nodeList, err := c.CoreV1().Nodes().List(api.ListOptions{})
if err != nil {
return nil, err
@@ -48,71 +56,74 @@ func getKubePeers(c *kubernetes.Clientset) ([]nodeInfo, error) {
// Fallback for cases where a Node has an ExternalIP but no InternalIP
if internalIP != "" {
// exclude self from the list of peers this node will peer with
if isLocalNodeIP(internalIP) {
continue
}
addresses = append(addresses, nodeInfo{name: peer.Name, addr: internalIP})
} else if externalIP != "" {
addresses = append(addresses, nodeInfo{name: peer.Name, addr: externalIP})
} else if includeWithNoIPAddr {
addresses = append(addresses, nodeInfo{name: peer.Name, addr: ""})
}
}
return addresses, nil
}
const (
configMapName = "weave-net"
configMapNamespace = "kube-system"
)
// update the list of all peers that have gone through this code path
func addMyselfToPeerList(cml *configMapAnnotations, c *kubernetes.Clientset, peerName, name string) (*peerList, error) {
var list *peerList
err := cml.LoopUpdate(func() error {
var err error
list, err = cml.GetPeerList()
if err != nil {
return err
// returns true if given IP matches with one of the local IP's
func isLocalNodeIP(ip string) bool {
addrs, err := netlink.AddrList(nil, unix.AF_INET)
if err != nil {
return false
}
for _, addr := range addrs {
if addr.Peer.IP.String() == ip {
return true
}
if !list.contains(peerName) {
list.add(peerName, name)
err = cml.UpdatePeerList(*list)
if err != nil {
return err
}
}
return nil
})
return list, err
}
return false
}
func checkIamInPeerList(cml *configMapAnnotations, c *kubernetes.Clientset, peerName string) (bool, error) {
if err := cml.Init(); err != nil {
return false, err
}
list, err := cml.GetPeerList()
if err != nil {
return false, err
}
common.Log.Debugf("[kube-peers] Checking peer %q against list %v", peerName, list)
return list.contains(peerName), nil
// (minimal, incomplete) interface so weaver can be mocked for testing.
type weaveClient interface {
RmPeer(peerName string) (string, error)
}
// For each of those peers that is no longer listed as a node by
// Kubernetes, remove it from Weave IPAM
func reclaimRemovedPeers(weave *weaveapi.Client, cml *configMapAnnotations, nodes []nodeInfo, myPeerName string) error {
func reclaimRemovedPeers(kube kubernetes.Interface, cml *configMapAnnotations, myPeerName, myNodeName string) error {
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), common.Log)
for loopsWhenNothingChanged := 0; loopsWhenNothingChanged < 3; loopsWhenNothingChanged++ {
if err := cml.Init(); err != nil {
return err
}
// 1. Compare peers stored in the peerList against all peers reported by k8s now.
storedPeerList, err := cml.GetPeerList()
storedPeerList, err := getRefreshedPeerList(cml)
if err != nil {
return err
}
nodes, err := getKubePeers(kube, true)
if err != nil {
return err
}
nodeSet := make(map[string]struct{}, len(nodes))
for _, node := range nodes {
nodeSet[node.name] = struct{}{}
}
peerMap := make(map[string]peerInfo, len(storedPeerList.Peers))
for _, peer := range storedPeerList.Peers {
peerMap[peer.NodeName] = peer
if peer.PeerName != myPeerName {
peerMap[peer.PeerName] = peer
}
}
for _, node := range nodes {
delete(peerMap, node.name)
// remove entries from the peer map that are current nodes
for key, peer := range peerMap {
if _, found := nodeSet[peer.NodeName]; found {
// unless they have a duplicate of my NodeName but are not me
if peer.NodeName == myNodeName && peer.PeerName != myPeerName {
continue
}
delete(peerMap, key)
}
}
// so the remainder is everything we want to clean up
common.Log.Debugln("[kube-peers] Nodes that have disappeared:", peerMap)
if len(peerMap) == 0 {
break
@@ -123,63 +134,178 @@ func reclaimRemovedPeers(weave *weaveapi.Client, cml *configMapAnnotations, node
common.Log.Warnln("[kube-peers] not removing myself", peer)
continue
}
common.Log.Debugln("[kube-peers] Preparing to remove disappeared peer", peer)
okToRemove := false
// 3. Check if there is an existing annotation with key X
if existingAnnotation, found := cml.GetAnnotation(KubePeersPrefix + peer.PeerName); found {
common.Log.Debugln("[kube-peers] Existing annotation", existingAnnotation)
// 4. If annotation already contains my identity, ok;
if existingAnnotation == myPeerName {
okToRemove = true
}
} else {
// 5. If non-existent, write an annotation with key X and contents "my identity"
common.Log.Debugln("[kube-peers] Noting I plan to remove ", peer.PeerName)
if err := cml.UpdateAnnotation(KubePeersPrefix+peer.PeerName, myPeerName); err == nil {
okToRemove = true
} else {
common.Log.Debugln("[kube-peers] error from UpdateAnnotation: ", err)
}
changed, err := reclaimPeer(weave, cml, peer.PeerName, myPeerName)
if err != nil {
return err
}
if okToRemove {
// 6. If step 4 or 5 succeeded, rmpeer X
result, err := weave.RmPeer(peer.PeerName)
common.Log.Infof("[kube-peers] rmpeer of %s: %s", peer.PeerName, result)
if err != nil {
return err
}
if changed {
loopsWhenNothingChanged = 0
cml.LoopUpdate(func() error {
// 7aa. Remove any annotations Z* that have contents X
if err := cml.RemoveAnnotationsWithValue(peer.PeerName); err != nil {
return err
}
// 7a. Remove X from peerList
storedPeerList.remove(peer.PeerName)
if err := cml.UpdatePeerList(*storedPeerList); err != nil {
return err
}
// 7b. Remove annotation with key X
return cml.RemoveAnnotation(KubePeersPrefix + peer.PeerName)
})
}
// 8. If step 5 failed due to optimistic lock conflict, stop: someone else is handling X
// Step 3-5 is to protect against two simultaneous rmpeers of X
// Step 4 is to pick up again after a restart between step 5 and step 7b
// If the peer doing the reclaim disappears between steps 5 and 7a, then someone will clean it up in step 7aa
// If peer doing the reclaim disappears forever between 7a and 7b then we get a dangling annotation
// This should be sufficiently rare that we don't care.
}
// 9. Go back to step 1 until there is no difference between the two sets
// (or we hit the counter that says we've been round the loop 3 times and nothing happened)
}
return nil
}
// Attempt to reclaim the IP addresses owned by peerName, using the
// Kubernetes api-server as a point of consensus so that only one peer
// actions the reclaim.
// Return a bool to show whether we attempted to change anything,
// and an error if something went wrong.
func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string, myPeerName string) (changed bool, err error) {
common.Log.Debugln("[kube-peers] Preparing to remove disappeared peer", peerName)
okToRemove := false
nonExistentPeer := false
// Re-read status from Kubernetes; speculative updates may leave it un-set
if err := cml.Init(); err != nil {
return false, err
}
// 3. Check if there is an existing annotation with key X
existingAnnotation, found := cml.GetAnnotation(KubePeersPrefix + peerName)
if found {
common.Log.Debugln("[kube-peers] Existing annotation", existingAnnotation)
// 4. If annotation already contains my identity, ok;
if existingAnnotation == myPeerName {
okToRemove = true
} else {
storedPeerList, err := cml.GetPeerList()
if err != nil {
return false, err
}
// handle an edge case where peer claimed to own the action to reclaim but no longer
// exists hence lock persists foever
if !storedPeerList.contains(existingAnnotation) {
nonExistentPeer = true
common.Log.Debugln("[kube-peers] Existing annotation", existingAnnotation, " has a non-existent peer so owning the reclaim action")
}
}
}
if !found || nonExistentPeer {
// 5. If non-existent, write an annotation with key X and contents "my identity"
common.Log.Debugln("[kube-peers] Noting I plan to remove ", peerName)
if err := cml.UpdateAnnotation(KubePeersPrefix+peerName, myPeerName); err == nil {
okToRemove = true
} else {
common.Log.Errorln("[kube-peers] error from UpdateAnnotation: ", err)
}
}
if !okToRemove {
return false, nil
}
// 6. If step 4 or 5 succeeded, rmpeer X
// we will try once more to see if the peerName has been removed from the annotation
// by another weave pod
storedPeerList, err := getRefreshedPeerList(cml)
if storedPeerList.contains(peerName) {
result, err := weave.RmPeer(peerName)
common.Log.Infof("[kube-peers] rmpeer of %s: %s", peerName, result)
if err != nil {
return false, err
}
}
err = cml.LoopUpdate(func() error {
// 7aa. Remove any annotations Z* that have contents X
if err := cml.RemoveAnnotationsWithValue(peerName); err != nil {
return err
}
// 7a. Remove X from peerList
storedPeerList, err := cml.GetPeerList()
if err != nil {
return err
}
if storedPeerList.contains(peerName) {
storedPeerList.remove(peerName)
if err := cml.UpdatePeerList(*storedPeerList); err != nil {
return err
}
} else {
common.Log.Infof("[kube-peers] annotation was removed already for %s", peerName)
}
// 7b. Remove annotation with key X
return cml.RemoveAnnotation(KubePeersPrefix + peerName)
})
// 8. If step 5 failed due to optimistic lock conflict, stop: someone else is handling X
// Step 3-5 is to protect against two simultaneous rmpeers of X
// Step 4 is to pick up again after a restart between step 5 and step 7b
// If the peer doing the reclaim disappears between steps 5 and 7a, then someone will clean it up in step 7aa
// If peer doing the reclaim disappears forever between 7a and 7b then we get a dangling annotation
// This should be sufficiently rare that we don't care.
// Question: Should we narrow step 2 by checking against Weave Net IPAM?
// i.e. If peer X owns any address space and is marked unreachable, we want to rmpeer X
return true, err
}
// resetPeers replaces the peers list with current set of peers
func resetPeers(kube kubernetes.Interface) error {
nodes, err := getKubePeers(kube, false)
if err != nil {
return err
}
peerList := make([]string, 0)
for _, node := range nodes {
peerList = append(peerList, node.addr)
}
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), common.Log)
err = weave.ReplacePeers(peerList)
if err != nil {
return err
}
return nil
}
// regiesters with Kubernetes API server for node delete events. Node delete event handler
// invokes reclaimRemovedPeers to remove it from IPAM so that IP space is reclaimed
func registerForNodeUpdates(client *kubernetes.Clientset, stopCh <-chan struct{}, nodeName, peerName string) {
informerFactory := informers.NewSharedInformerFactory(client, 0)
nodeInformer := informerFactory.Core().V1().Nodes().Informer()
common.Log.Debugln("registering for updates for node delete events")
nodeInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
DeleteFunc: func(obj interface{}) {
var name string
if apiObj, ok := obj.(api.Object); ok {
name = apiObj.GetName()
} else {
name = fmt.Sprintf("%#v", obj)
}
common.Log.Debugln("Delete event for", name)
// add random delay to avoid all nodes acting on node delete event at the same
// time leading to contention to use `weave-net` configmap
r := rand.Intn(5000)
time.Sleep(time.Duration(r) * time.Millisecond)
cml := newConfigMapAnnotations(configMapNamespace, configMapName, client)
err := reclaimRemovedPeers(client, cml, peerName, nodeName)
if err != nil {
common.Log.Fatalf("[kube-peers] Error while reclaiming space: %v", err)
}
err = resetPeers(client)
if err != nil {
common.Log.Fatalf("[kube-peers] Error resetting peer list: %v", err)
}
},
})
informerFactory.WaitForCacheSync(stopCh)
informerFactory.Start(stopCh)
}
// getRefreshedPeerList will fetch the latest peer list from the config map annotation
func getRefreshedPeerList(cml *configMapAnnotations) (*peerList, error) {
if err := cml.Init(); err != nil {
return nil, err
}
storedPeerList, err := cml.GetPeerList()
if err != nil {
return nil, err
}
return storedPeerList, nil
}
func main() {
var (
justReclaim bool
@@ -188,8 +314,10 @@ func main() {
peerName string
nodeName string
logLevel string
runReclaimDaemon bool
)
flag.BoolVar(&justReclaim, "reclaim", false, "reclaim IP space from dead peers")
flag.BoolVar(&runReclaimDaemon, "run-reclaim-daemon", false, "run background process that reclaim IP space from dead peers ")
flag.BoolVar(&justCheck, "check-peer-new", false, "return success if peer name is not stored in annotation")
flag.BoolVar(&justSetNodeStatus, "set-node-status", false, "set NodeNetworkUnavailable to false")
flag.StringVar(&peerName, "peer-name", "unknown", "name of this Weave Net peer")
@@ -225,10 +353,6 @@ func main() {
}
return
}
peers, err := getKubePeers(c)
if err != nil {
common.Log.Fatalf("[kube-peers] Could not get peers: %v", err)
}
if justReclaim {
cml := newConfigMapAnnotations(configMapNamespace, configMapName, c)
@@ -238,13 +362,28 @@ func main() {
}
common.Log.Infoln("[kube-peers] Added myself to peer list", list)
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), common.Log)
err = reclaimRemovedPeers(weave, cml, peers, peerName)
err = reclaimRemovedPeers(c, cml, peerName, nodeName)
if err != nil {
common.Log.Fatalf("[kube-peers] Error while reclaiming space: %v", err)
}
return
}
if runReclaimDaemon {
// Handle SIGINT and SIGTERM
ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
stopCh := make(chan struct{})
rand.Seed(time.Now().UnixNano())
registerForNodeUpdates(c, stopCh, nodeName, peerName)
<-ch
close(stopCh)
return
}
peers, err := getKubePeers(c, false)
if err != nil {
common.Log.Fatalf("[kube-peers] Could not get peers: %v", err)
}
for _, node := range peers {
fmt.Println(node.addr)
}
+1 -1
View File
@@ -10,7 +10,7 @@ import (
)
// based on k8s.io/kubernetes/pkg/controller/nodeipam/ipam/adapter.go
func setNodeNetworkUnavailableFalse(c *kubernetes.Clientset, nodeName string) error {
func setNodeNetworkUnavailableFalse(c kubernetes.Interface, nodeName string) error {
condition := v1.NodeCondition{
Type: v1.NodeNetworkUnavailable,
Status: v1.ConditionFalse,
+104
View File
@@ -0,0 +1,104 @@
/*
This module deals with operations on the peerlist backed by Kubernetes' annotation mechanism.
*/
package main
import (
"encoding/json"
"github.com/pkg/errors"
"k8s.io/client-go/kubernetes"
"github.com/weaveworks/weave/common"
)
const (
configMapName = "weave-net"
configMapNamespace = "kube-system"
)
type peerList struct {
Peers []peerInfo
}
type peerInfo struct {
PeerName string // Weave internal unique ID
NodeName string // Kubernetes node name
}
func (pl *peerList) contains(peerName string) bool {
for _, peer := range pl.Peers {
if peer.PeerName == peerName {
return true
}
}
return false
}
func (pl *peerList) add(peerName string, name string) {
pl.Peers = append(pl.Peers, peerInfo{PeerName: peerName, NodeName: name})
}
func (pl *peerList) remove(peerNameToRemove string) {
for i := 0; i < len(pl.Peers); {
if pl.Peers[i].PeerName == peerNameToRemove {
pl.Peers = append(pl.Peers[:i], pl.Peers[i+1:]...)
} else {
i++
}
}
}
func (cml *configMapAnnotations) GetPeerList() (*peerList, error) {
var record peerList
if cml.cm == nil {
return nil, errors.New("endpoint not initialized, call Init first")
}
if recordBytes, found := cml.cm.Annotations[KubePeersAnnotationKey]; found {
if err := json.Unmarshal([]byte(recordBytes), &record); err != nil {
return nil, err
}
}
return &record, nil
}
func (cml *configMapAnnotations) UpdatePeerList(list peerList) error {
recordBytes, err := json.Marshal(list)
if err != nil {
return err
}
return cml.UpdateAnnotation(KubePeersAnnotationKey, string(recordBytes))
}
// update the list of all peers that have gone through this code path
func addMyselfToPeerList(cml *configMapAnnotations, c kubernetes.Interface, peerName, name string) (*peerList, error) {
var list *peerList
err := cml.LoopUpdate(func() error {
var err error
list, err = cml.GetPeerList()
if err != nil {
return err
}
if !list.contains(peerName) {
list.add(peerName, name)
err = cml.UpdatePeerList(*list)
if err != nil {
return err
}
}
return nil
})
return list, err
}
func checkIamInPeerList(cml *configMapAnnotations, c kubernetes.Interface, peerName string) (bool, error) {
if err := cml.Init(); err != nil {
return false, err
}
list, err := cml.GetPeerList()
if err != nil {
return false, err
}
common.Log.Debugf("[kube-peers] Checking peer %q against list %v", peerName, list)
return list.contains(peerName), nil
}
+184
View File
@@ -0,0 +1,184 @@
package main
import (
"fmt"
"math/rand"
"sync"
"testing"
"time"
"github.com/stretchr/testify/require"
)
const (
peerName1 = "01:00:00:00:00:00"
peerName2 = "02:00:00:00:00:00"
peerName3 = "03:00:00:00:00:00"
nodeName1 = "fake-node-1"
nodeName2 = "fake-node-2"
testIters = 1000
)
func TestPeerListBasic(t *testing.T) {
c := NewSimpleClientset()
cml := newConfigMapAnnotations(configMapNamespace, configMapName, c)
err := cml.Init()
require.NoError(t, err)
list1, err := addMyselfToPeerList(cml, c, peerName1, nodeName1)
require.NoError(t, err)
require.Equal(t, 1, len(list1.Peers))
list2, err := addMyselfToPeerList(cml, c, peerName2, nodeName2)
require.NoError(t, err)
require.Equal(t, 2, len(list2.Peers))
check1, err := checkIamInPeerList(cml, c, peerName1)
require.NoError(t, err)
require.Equal(t, true, check1)
check3, err := checkIamInPeerList(cml, c, peerName3)
require.NoError(t, err)
require.Equal(t, false, check3)
storedPeerList, err := cml.GetPeerList()
require.NoError(t, err)
storedPeerList.remove(peerName1)
require.Equal(t, 1, len(storedPeerList.Peers))
err = cml.UpdatePeerList(*storedPeerList)
require.NoError(t, err)
check1, err = checkIamInPeerList(cml, c, peerName1)
require.NoError(t, err)
require.Equal(t, false, check1)
}
// Run function _f_ _iterations_ times, in _concurrency_
// number of goroutines
func doConcurrentIterations(iterations, concurrency int, f func(int)) {
iterationsPerThread := iterations / concurrency
wg := sync.WaitGroup{}
for i := 0; i < concurrency; i++ {
wg.Add(1)
go func(j int) {
defer wg.Done()
for k := 0; k < iterationsPerThread; k++ {
f((j * iterationsPerThread) + k)
}
}(i)
}
wg.Wait()
}
func TestPeerListFuzz(t *testing.T) {
rand.Seed(time.Now().UnixNano())
const (
testIters = 1000
maxNodes = 100
concurrency = 5
)
peerName := func(i int) string { return fmt.Sprintf("%02d:00:00:02:00:00", i) }
nodeName := func(i int) string { return fmt.Sprintf("node%d", i) }
stateLock := sync.Mutex{}
nodes := []int{}
nodeMap := map[int]bool{} // true if an operation is pending
c := NewSimpleClientset()
addNode := func() {
i := rand.Intn(maxNodes)
// add to test state first, then to Kubernetes
stateLock.Lock()
pending, found := nodeMap[i]
if !found {
nodes = append(nodes, i)
}
nodeMap[i] = true
stateLock.Unlock()
if pending { // someone else is adding or deleting this node
return
}
cml := newConfigMapAnnotations(configMapNamespace, configMapName, c)
err := cml.Init()
require.NoError(t, err)
_, err = addMyselfToPeerList(cml, c, peerName(i), nodeName(i))
require.NoError(t, err)
stateLock.Lock()
nodeMap[i] = false
stateLock.Unlock()
}
removeNode := func() {
stateLock.Lock()
if len(nodes) == 0 { // can't remove if there aren't any nodes
stateLock.Unlock()
return
}
pos := rand.Intn(len(nodes))
i := nodes[pos]
if pending, found := nodeMap[i]; found {
if pending {
stateLock.Unlock()
return // someone else is adding or deleting this node
}
nodeMap[i] = true
} else {
t.Errorf("missing entry from node map: %d", i)
}
stateLock.Unlock()
// remove from Kubernetes first, then from test state
cml := newConfigMapAnnotations(configMapNamespace, configMapName, c)
require.NoError(t, cml.Init())
storedPeerList, err := cml.GetPeerList()
require.NoError(t, err)
found := storedPeerList.contains(peerName(i))
require.True(t, found, "peer %d not found in stored list", i)
_, err = reclaimPeer(mockWeave{}, cml, peerName(i), fmt.Sprintf("deleter-%d", i))
require.NoError(t, err)
require.NoError(t, cml.Init())
storedPeerList, err = cml.GetPeerList()
require.NoError(t, err)
stateLock.Lock()
delete(nodeMap, i)
for pos = 0; pos < len(nodes); pos++ {
if nodes[pos] == i {
// Remove item from list by swapping it with last and reducing slice length by 1
nodes[pos] = nodes[len(nodes)-1]
nodes = nodes[:len(nodes)-1]
break
}
}
stateLock.Unlock()
}
doConcurrentIterations(testIters, concurrency, func(iteration int) {
r := rand.Float32()
switch {
case 0.0 <= r && r < 0.4:
addNode()
case (0.4 <= r && r < 0.8):
removeNode()
}
})
cml := newConfigMapAnnotations(configMapNamespace, configMapName, c)
err := cml.Init()
require.NoError(t, err)
storedPeerList, err := cml.GetPeerList()
require.NoError(t, err)
require.Equal(t, len(storedPeerList.Peers), len(nodes))
}
type mockWeave struct{}
func (mockWeave) RmPeer(peerName string) (string, error) {
return "", nil
}
+34 -2
View File
@@ -6,6 +6,34 @@ modprobe_safe() {
modprobe $1 || echo "Ignore the error if \"$1\" is built-in in the kernel" >&2
}
# Setup iptables backend to be legacy or nftable
setup_iptables_backend() {
if [ -n "${IPTABLES_BACKEND}" ]; then
mode=$IPTABLES_BACKEND
else
# auto-detect if iptables backend mode to use if not specified explicitly
num_legacy_lines=$( (iptables-legacy-save || true) 2>/dev/null | grep '^-' | wc -l)
num_nft_lines=$( (iptables-nft-save || true) 2>/dev/null | grep '^-' | wc -l)
if [ "${num_legacy_lines}" -ge 10 ]; then
mode="legacy"
else
if [ "${num_legacy_lines}" -ge "${num_nft_lines}" ]; then
mode="legacy"
else
mode="nft"
fi
fi
fi
if [ $mode = "nft" ]; then
rm /sbin/iptables
rm /sbin/iptables-save
rm /sbin/iptables-restore
ln -s /sbin/iptables-nft /sbin/iptables
ln -s /sbin/iptables-nft-save /sbin/iptables-save
ln -s /sbin/iptables-nft-restore /sbin/iptables-restore
fi
}
# Check whether xt_set actually exists
xt_set_exists() {
# Clean everything up in advance, in case there's leftovers
@@ -24,12 +52,14 @@ xt_set_exists() {
[ -z "$NOT_EXIST" ] || (echo "\"xt_set\" does not exist" >&2 && return 1)
}
setup_iptables_backend
# 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}
METRICS_ADDR=${WEAVE_METRICS_ADDR:-0.0.0.0:6782}
HOST_ROOT=${HOST_ROOT:-/host}
CONN_LIMIT=${CONN_LIMIT:-100}
CONN_LIMIT=${CONN_LIMIT:-200}
DB_PREFIX=${DB_PREFIX:-/weavedb/weave-net}
# Check if the IP range overlaps anything existing on the host
@@ -85,7 +115,7 @@ router_bridge_opts() {
}
if [ -z "$KUBE_PEERS" ]; then
if ! KUBE_PEERS=$(/home/weave/kube-utils) || [ -z "$KUBE_PEERS" ]; then
if ! KUBE_PEERS=$(/home/weave/kube-utils); then
echo Failed to get peers >&2
exit 1
fi
@@ -151,6 +181,8 @@ post_start_actions() {
# Mark network as up
/home/weave/kube-utils -set-node-status -node-name="$HOSTNAME"
/home/weave/kube-utils -run-reclaim-daemon -node-name="$HOSTNAME" -peer-name="$PEERNAME" -log-level=debug&
}
post_start_actions &
@@ -0,0 +1,215 @@
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ServiceAccount
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1
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
- apiGroups:
- 'networking.k8s.io'
resources:
- networkpolicies
verbs:
- get
- list
- watch
- apiGroups:
- ''
resources:
- nodes/status
verbs:
- patch
- update
- apiVersion: rbac.authorization.k8s.io/v1
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: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: weave-net
namespace: kube-system
labels:
name: weave-net
rules:
- apiGroups:
- ''
resources:
- configmaps
resourceNames:
- weave-net
verbs:
- get
- update
- apiGroups:
- ''
resources:
- configmaps
verbs:
- create
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: weave-net
namespace: kube-system
labels:
name: weave-net
roleRef:
kind: Role
name: weave-net
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: weave-net
namespace: kube-system
- apiVersion: apps/v1
kind: DaemonSet
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
spec:
# Wait 5 seconds to let pod connect before rolling next pod
selector:
matchLabels:
name: weave-net
minReadySeconds: 5
template:
metadata:
labels:
name: weave-net
spec:
containers:
- name: weave
command:
- /home/weave/launch.sh
env:
- name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
readinessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
resources:
requests:
cpu: 50m
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: xtables-lock
mountPath: /run/xtables.lock
readOnly: false
- name: weave-npc
env:
- name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: 'weaveworks/weave-npc:latest'
imagePullPolicy: Always
#npc-args
resources:
requests:
cpu: 50m
securityContext:
privileged: true
volumeMounts:
- name: xtables-lock
mountPath: /run/xtables.lock
readOnly: false
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
hostPID: true
restartPolicy: Always
securityContext:
seLinuxOptions: {}
serviceAccountName: weave-net
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
volumes:
- name: weavedb
hostPath:
path: /var/lib/weave
- 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
- name: xtables-lock
hostPath:
path: /run/xtables.lock
type: FileOrCreate
priorityClassName: system-node-critical
updateStrategy:
type: RollingUpdate
+5 -4
View File
@@ -110,15 +110,14 @@ items:
fieldPath: spec.nodeName
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
livenessProbe:
readinessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
initialDelaySeconds: 30
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
volumeMounts:
@@ -145,7 +144,7 @@ items:
imagePullPolicy: Always
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
hostNetwork: true
@@ -157,6 +156,8 @@ items:
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
volumes:
- name: weavedb
hostPath:
+5 -4
View File
@@ -119,15 +119,14 @@ items:
fieldPath: spec.nodeName
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
livenessProbe:
readinessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
initialDelaySeconds: 30
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
volumeMounts:
@@ -157,7 +156,7 @@ items:
imagePullPolicy: Always
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
volumeMounts:
@@ -173,6 +172,8 @@ items:
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
volumes:
- name: weavedb
hostPath:
+9 -8
View File
@@ -8,7 +8,7 @@ items:
labels:
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: weave-net
@@ -48,7 +48,7 @@ items:
verbs:
- patch
- update
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: weave-net
@@ -62,7 +62,7 @@ items:
- kind: ServiceAccount
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: weave-net
@@ -85,7 +85,7 @@ items:
- configmaps
verbs:
- create
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: weave-net
@@ -127,15 +127,14 @@ items:
fieldPath: spec.nodeName
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
livenessProbe:
readinessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
initialDelaySeconds: 30
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
volumeMounts:
@@ -166,7 +165,7 @@ items:
#npc-args
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
volumeMounts:
@@ -182,6 +181,8 @@ items:
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
volumes:
- name: weavedb
hostPath:
@@ -0,0 +1,214 @@
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ServiceAccount
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1
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
- apiGroups:
- 'networking.k8s.io'
resources:
- networkpolicies
verbs:
- get
- list
- watch
- apiGroups:
- ''
resources:
- nodes/status
verbs:
- patch
- update
- apiVersion: rbac.authorization.k8s.io/v1
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: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: weave-net
namespace: kube-system
labels:
name: weave-net
rules:
- apiGroups:
- ''
resources:
- configmaps
resourceNames:
- weave-net
verbs:
- get
- update
- apiGroups:
- ''
resources:
- configmaps
verbs:
- create
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: weave-net
namespace: kube-system
labels:
name: weave-net
roleRef:
kind: Role
name: weave-net
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: weave-net
namespace: kube-system
- apiVersion: apps/v1
kind: DaemonSet
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
spec:
# Wait 5 seconds to let pod connect before rolling next pod
selector:
matchLabels:
name: weave-net
minReadySeconds: 5
template:
metadata:
labels:
name: weave-net
spec:
containers:
- name: weave
command:
- /home/weave/launch.sh
env:
- name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
readinessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
resources:
requests:
cpu: 50m
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: xtables-lock
mountPath: /run/xtables.lock
readOnly: false
- name: weave-npc
env:
- name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: 'weaveworks/weave-npc:latest'
imagePullPolicy: Always
#npc-args
resources:
requests:
cpu: 50m
securityContext:
privileged: true
volumeMounts:
- name: xtables-lock
mountPath: /run/xtables.lock
readOnly: false
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
hostPID: true
restartPolicy: Always
securityContext:
seLinuxOptions: {}
serviceAccountName: weave-net
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
volumes:
- name: weavedb
hostPath:
path: /var/lib/weave
- 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
- name: xtables-lock
hostPath:
path: /run/xtables.lock
type: FileOrCreate
updateStrategy:
type: RollingUpdate
-101
View File
@@ -1,101 +0,0 @@
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ServiceAccount
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
- apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
spec:
template:
metadata:
annotations:
scheduler.alpha.kubernetes.io/tolerations: >-
[{"key":"dedicated","operator":"Equal","value":"master","effect":"NoSchedule"}]
labels:
name: weave-net
spec:
containers:
- name: weave
command:
- /home/weave/launch.sh
env:
- name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
livenessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
initialDelaySeconds: 30
resources:
requests:
cpu: 10m
securityContext:
privileged: true
volumeMounts:
- name: weavedb
mountPath: /weavedb
- name: cni-bin
mountPath: /host/opt
- name: cni-bin2
mountPath: /host/home
- name: cni-conf
mountPath: /host/etc
- name: dbus
mountPath: /host/var/lib/dbus
- name: lib-modules
mountPath: /lib/modules
- name: weave-npc
env:
- name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: 'weaveworks/weave-npc:latest'
imagePullPolicy: Always
resources:
requests:
cpu: 10m
securityContext:
privileged: true
hostNetwork: true
hostPID: true
restartPolicy: Always
securityContext:
seLinuxOptions: {}
serviceAccountName: weave-net
volumes:
- name: weavedb
hostPath:
path: /var/lib/weave
- 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
+2 -1
View File
@@ -27,7 +27,8 @@ RUN apk add --update \
&& mknod /var/log/ulogd.pcap p
COPY ./weave-npc /usr/bin/weave-npc
COPY ./ulogd.conf /etc/ulogd.conf
ENTRYPOINT ["/usr/bin/weave-npc"]
COPY ./launch.sh /usr/bin/
ENTRYPOINT ["/usr/bin/launch.sh"]
# These labels will change for every build, and should therefore be the last layer of the image:
ARG revision
+36
View File
@@ -0,0 +1,36 @@
#!/bin/sh
set -e
# Setup iptables backend to be legacy or nftable
setup_iptables_backend() {
if [ -n "${IPTABLES_BACKEND}" ]; then
mode=$IPTABLES_BACKEND
else
# auto-detect if iptables backend mode to use if not specified explicitly
num_legacy_lines=$( (iptables-legacy-save || true) 2>/dev/null | grep '^-' | wc -l)
num_nft_lines=$( (iptables-nft-save || true) 2>/dev/null | grep '^-' | wc -l)
if [ "${num_legacy_lines}" -ge 10 ]; then
mode="legacy"
else
if [ "${num_legacy_lines}" -ge "${num_nft_lines}" ]; then
mode="legacy"
else
mode="nft"
fi
fi
fi
if [ $mode = "nft" ]; then
rm /sbin/iptables
rm /sbin/iptables-save
rm /sbin/iptables-restore
ln -s /sbin/iptables-nft /sbin/iptables
ln -s /sbin/iptables-nft-save /sbin/iptables-save
ln -s /sbin/iptables-nft-restore /sbin/iptables-restore
fi
}
setup_iptables_backend
# Start weave-npc with any flags specified in $EXTRA_ARGS as well as any flags passed to this container (for backwards compatibility)
exec /usr/bin/weave-npc $EXTRA_ARGS $@
+47 -34
View File
@@ -25,15 +25,23 @@ import (
)
var (
version = "unreleased"
metricsAddr string
logLevel string
allowMcast bool
nodeName string
maxList int
version = "unreleased"
metricsAddr string
logLevel string
allowMcast bool
nodeName string
maxList int
bridgePortName string
)
func handleError(err error) { common.CheckFatal(err) }
func handleError(err error) {
if err != nil {
metrics.PolicyEnforcementErrors.Inc()
common.Log.Error(err)
}
}
func handleFatal(err error) { common.CheckFatal(err) }
func makeController(getter cache.Getter, resource string,
objType runtime.Object, handlers cache.ResourceEventHandlerFuncs) cache.Controller {
@@ -125,6 +133,12 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
}
}
// If the destination address is not any of the local pods, let it through
if err := ipt.Append(npc.TableFilter, npc.MainChain,
"-m", "physdev", "--physdev-is-bridged", "--physdev-out="+bridgePortName, "-j", "ACCEPT"); err != nil {
return err
}
if err := ipt.Append(npc.TableFilter, npc.MainChain,
"-m", "state", "--state", "NEW", "-j", string(npc.DefaultChain)); err != nil {
return err
@@ -135,21 +149,6 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
return err
}
// If the destination address is not any of the local pods, let it through
found, err := ipsetExist(ips, npc.LocalIpset)
if err != nil {
return err
}
if !found {
if err := ips.Create(npc.LocalIpset, ipset.HashIP); err != nil {
return err
}
}
if err := ipt.Append(npc.TableFilter, npc.MainChain,
"-m", "set", "!", "--match-set", npc.LocalIpset, "dst", "-j", "ACCEPT"); err != nil {
return err
}
if err := ipt.Append(npc.TableFilter, npc.EgressMarkChain,
"-j", "MARK", "--set-xmark", npc.EgressMark); err != nil {
return err
@@ -158,8 +157,8 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
// Egress rules:
//
// -A WEAVE-NPC-EGRESS -m state --state RELATED,ESTABLISHED -j ACCEPT
// -A WEAVE-NPC-EGRESS -m set ! --match-set weave-local-pods src -j RETURN
// -A WEAVE-NPC-EGRESS -d 224.0.0.0/4 -j RETURN
// -A WEAVE-NPC-EGRESS -m physdev --physdev-in vethwe-bridge --physdev-is-bridged -j RETURN
// -A WEAVE-NPC-EGRESS -m addrtype --dst-type LOCAL -j RETURN
// -A WEAVE-NPC-EGRESS -m state --state NEW -j WEAVE-NPC-EGRESS-DEFAULT
// -A WEAVE-NPC-EGRESS -m state --state NEW -m mark ! --mark 0x40000/0x40000 -j WEAVE-NPC-EGRESS-CUSTOM
// -A WEAVE-NPC-EGRESS -m state --state NEW -m mark ! --mark 0x40000/0x40000 -j NFLOG --nflog-group 86
@@ -179,7 +178,10 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
ruleSpecs := [][]string{
{"-m", "state", "--state", "RELATED,ESTABLISHED", "-j", "ACCEPT"},
{"-m", "state", "--state", "NEW", "-m", "set", "!", "--match-set", npc.LocalIpset, "src", "-j", "RETURN"},
// skip running through egress network policies for the traffic not coming from local pods
{"-m", "physdev", "--physdev-is-bridged", "--physdev-in=" + bridgePortName, "-j", "RETURN"},
// skip running through egress network policies for the traffic bound for IP address assigned for the bridge
{"-m", "addrtype", "--dst-type", "LOCAL", "-j", "RETURN"},
}
if allowMcast {
ruleSpecs = append(ruleSpecs, []string{"-d", "224.0.0.0/4", "-j", "RETURN"})
@@ -188,12 +190,22 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
{"-m", "state", "--state", "NEW", "-j", string(npc.EgressDefaultChain)},
{"-m", "state", "--state", "NEW", "-m", "mark", "!", "--mark", npc.EgressMark, "-j", string(npc.EgressCustomChain)},
{"-m", "state", "--state", "NEW", "-m", "mark", "!", "--mark", npc.EgressMark, "-j", "NFLOG", "--nflog-group", "86"},
{"-m", "mark", "!", "--mark", npc.EgressMark, "-j", "DROP"},
}...)
if err := net.AddChainWithRules(ipt, npc.TableFilter, npc.EgressChain, ruleSpecs); err != nil {
return err
}
// delete `weave-local-pods` ipset which is no longer used by weave-npc
weaveLocalPodExist, err := ipsetExist(ips, npc.LocalIpset)
if err != nil {
common.Log.Errorf("Failed to look if ipset '%s' exists", npc.LocalIpset)
} else if weaveLocalPodExist {
common.Log.Debugf("Destroying ipset '%s'", npc.LocalIpset)
if err := ips.Destroy(npc.LocalIpset); err != nil {
common.Log.Errorf("Failed to destroy ipset '%s'", npc.LocalIpset)
}
}
return nil
}
@@ -235,21 +247,21 @@ func root(cmd *cobra.Command, args []string) {
}
config, err := rest.InClusterConfig()
handleError(err)
handleFatal(err)
client, err := kubernetes.NewForConfig(config)
handleError(err)
handleFatal(err)
ipt, err := iptables.New()
handleError(err)
handleFatal(err)
ips := ipset.New(common.LogLogger(), maxList)
handleError(resetIPTables(ipt))
handleError(resetIPSets(ips))
handleError(createBaseRules(ipt, ips))
handleFatal(resetIPTables(ipt))
handleFatal(resetIPSets(ips))
handleFatal(createBaseRules(ipt, ips))
npc := npc.New(nodeName, ipt, ips)
npc := npc.New(nodeName, ipt, ips, client)
nsController := makeController(client.Core().RESTClient(), "namespaces", &coreapi.Namespace{},
cache.ResourceEventHandlerFuncs{
@@ -332,6 +344,7 @@ func main() {
rootCmd.PersistentFlags().BoolVar(&allowMcast, "allow-mcast", true, "allow all multicast traffic")
rootCmd.PersistentFlags().StringVar(&nodeName, "node-name", "", "only generate rules that apply to this node")
rootCmd.PersistentFlags().IntVar(&maxList, "max-list-size", 1024, "maximum size of ipset list (for namespaces)")
rootCmd.PersistentFlags().StringVar(&bridgePortName, "bridge-port-name", "vethwe-bridge", "name of the brige port on which packets are received and sent")
handleError(rootCmd.Execute())
handleFatal(rootCmd.Execute())
}
+46 -3
View File
@@ -1,12 +1,17 @@
package main
import (
"fmt"
"os"
"sync/atomic"
"syscall"
"time"
"github.com/weaveworks/go-checkpoint"
checkpoint "github.com/weaveworks/go-checkpoint"
weave "github.com/weaveworks/weave/router"
api "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
var checker *checkpoint.Checker
@@ -14,10 +19,12 @@ var newVersion atomic.Value
var success atomic.Value
const (
updateCheckPeriod = 6 * time.Hour
updateCheckPeriod = 6 * time.Hour
configMapName = "weave-net"
configMapNamespace = "kube-system"
)
func checkForUpdates(dockerVersion string, router *weave.NetworkRouter) {
func checkForUpdates(dockerVersion string, router *weave.NetworkRouter, clusterSize uint) {
newVersion.Store("")
success.Store(true)
@@ -53,6 +60,8 @@ func checkForUpdates(dockerVersion string, router *weave.NetworkRouter) {
"kernel-version": kernelVersion,
}
checkpointKubernetes(flags, clusterSize)
// Start background version checking
params := checkpoint.CheckParams{
Product: "weave-net",
@@ -77,3 +86,37 @@ func checkpointFlags(router *weave.NetworkRouter) []checkpoint.Flag {
}
return flags
}
// checkpoint Kubernetes specific details
func checkpointKubernetes(flags map[string]string, clusterSize uint) {
// checks if weaver is running in Kubernetes
host := os.Getenv("KUBERNETES_SERVICE_HOST")
if len(host) == 0 {
return
}
config, err := rest.InClusterConfig()
if err != nil {
Log.Printf("Could not get Kubernetes in-cluster config: %v", err)
return
}
c, err := kubernetes.NewForConfig(config)
if err != nil {
Log.Printf("Could not make Kubernetes client: %v", err)
return
}
k8sVersion, err := c.Discovery().ServerVersion()
if err != nil {
Log.Printf("Could not get Kubernetes version: %v", err)
return
}
flags["kubernetes-version"] = k8sVersion.String()
// use UID of `weave-net` configmap as unique ID of the Kubenerets cluster
cm, err := c.CoreV1().ConfigMaps(configMapNamespace).Get(configMapName, api.GetOptions{})
if err != nil {
Log.Printf("Unable to fetch ConfigMap %s/%s to infer unique cluster ID", configMapNamespace, configMapName)
return
}
flags["kubernetes-cluster-uid"] = string(cm.ObjectMeta.UID)
flags["kubernetes-cluster-size"] = fmt.Sprint(clusterSize)
}
+9 -3
View File
@@ -188,7 +188,7 @@ func main() {
mflag.StringVar(&logLevel, []string{"-log-level"}, "info", "logging level (debug, info, warning, error)")
mflag.BoolVar(&pktdebug, []string{"-pkt-debug"}, false, "enable per-packet debug logging")
mflag.StringVar(&prof, []string{"-profile"}, "", "enable profiling and write profiles to given path")
mflag.IntVar(&config.ConnLimit, []string{"-conn-limit"}, 100, "connection limit (0 for unlimited)")
mflag.IntVar(&config.ConnLimit, []string{"-conn-limit"}, 200, "connection limit (0 for unlimited)")
mflag.BoolVar(&noDiscovery, []string{"-no-discovery"}, false, "disable peer discovery")
mflag.IntVar(&bufSzMB, []string{"-bufsz"}, 8, "capture buffer size in MB")
mflag.IntVar(&bridgeConfig.MTU, []string{"-mtu"}, 0, "MTU size")
@@ -307,6 +307,11 @@ func main() {
bridgeConfig.Mac = name.String()
bridgeConfig.Port = config.Port
if httpAddr != "" {
if _, port, err := net.SplitHostPort(httpAddr); err == nil {
bridgeConfig.ControlPort = port
}
}
ips := ipset.New(common.LogLogger(), 0)
bridgeType, err := weavenet.EnsureBridge(procPath, &bridgeConfig, Log, ips)
checkFatal(err)
@@ -385,7 +390,7 @@ func main() {
dockerVersion = dockerCli.DockerVersion()
}
checkForUpdates(dockerVersion, router)
checkForUpdates(dockerVersion, router, uint(len(peers)))
observeContainers := func(o docker.ContainerObserver) {
if dockerCli != nil {
@@ -453,6 +458,7 @@ func main() {
pluginConfig.DNS = !noDNS
pluginConfig.DefaultSubnet = defaultSubnet.String()
pluginConfig.ProcPath = procPath
plugin := plugin.NewPlugin(pluginConfig)
// The weave script always waits for a status call to succeed,
@@ -513,7 +519,7 @@ func exposeForAWSVPC(alloc *ipam.Allocator, subnet address.CIDR, bridgeName stri
addr, err := alloc.Allocate("weave:expose", subnet, false, func() bool { return false })
checkFatal(err)
cidr := address.MakeCIDR(subnet, addr)
err = weavenet.Expose(bridgeName, cidr.IPNet(), true, false)
err = weavenet.Expose(bridgeName, cidr.IPNet(), true, false, false)
checkFatal(err)
Log.Printf("Bridge %q exposed on address %v", bridgeName, cidr)
ready()
+24 -5
View File
@@ -89,8 +89,9 @@ func containerFQDN(args []string) error {
return nil
}
func runContainer(args []string) error {
func parseContainerArgs(args []string) docker.CreateContainerOptions {
env := []string{}
labels := map[string]string{}
name := ""
net := ""
pid := ""
@@ -109,6 +110,10 @@ func runContainer(args []string) error {
env = append(env, args[i+1])
}
args = append(args[:i], args[i+2:]...)
case "-l", "--label":
key, value := parseLabel(args[i+1])
labels[key] = value
args = append(args[:i], args[i+2:]...)
case "--name":
name = args[i+1]
args = append(args[:i], args[i+2:]...)
@@ -161,19 +166,25 @@ func runContainer(args []string) error {
image := args[0]
cmds := args[1:]
config := docker.Config{Image: image, Env: env, Cmd: cmds, Labels: labels}
hostConfig := docker.HostConfig{NetworkMode: net, PidMode: pid, Privileged: privileged, RestartPolicy: restart, Binds: volumes, VolumesFrom: volumesFrom}
return docker.CreateContainerOptions{Name: name, Config: &config, HostConfig: &hostConfig}
}
func runContainer(args []string) error {
containerOptions := parseContainerArgs(args)
c, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return fmt.Errorf("unable to connect to docker: %s", err)
}
config := docker.Config{Image: image, Env: env, Cmd: cmds}
hostConfig := docker.HostConfig{NetworkMode: net, PidMode: pid, Privileged: privileged, RestartPolicy: restart, Binds: volumes, VolumesFrom: volumesFrom}
container, err := c.CreateContainer(docker.CreateContainerOptions{Name: name, Config: &config, HostConfig: &hostConfig})
container, err := c.CreateContainer(containerOptions)
if err != nil {
return fmt.Errorf("unable to create container: %s", err)
}
err = c.StartContainer(container.ID, &hostConfig)
err = c.StartContainer(container.ID, containerOptions.HostConfig)
if err != nil {
return fmt.Errorf("unable to start container: %s", err)
}
@@ -182,6 +193,14 @@ func runContainer(args []string) error {
return nil
}
func parseLabel(s string) (key, value string) {
pos := strings.Index(s, "=")
if pos == -1 { // no value - set it to blank
return s, ""
}
return s[:pos], s[pos+1:]
}
func listContainers(args []string) error {
if len(args) > 1 {
cmdUsage("list-containers", "[<label>]")
+36
View File
@@ -0,0 +1,36 @@
package main
import (
"testing"
docker "github.com/fsouza/go-dockerclient"
"github.com/stretchr/testify/require"
)
func TestParseContainerArgs(t *testing.T) {
args := []string{"--name", "weave", "--privileged", "--net", "host",
"-l", "foo=bar", "-l", "foobar",
"-v", "/var/run/docker.sock:/var/run/docker.sock", "-v", "/etc:/host/etc",
"--restart", "always", "--pid", "host", "--volumes-from", "weavedb",
"-e", "WEAVE_DEBUG", "-e", "EXEC_IMAGE=weaveworks/weaveexec:latest",
"weaveworks/weave:latest", "cmd", "arg1", "arg2"}
expected := docker.CreateContainerOptions{
Name: "weave",
Config: &docker.Config{
Image: "weaveworks/weave:latest",
Env: []string{"WEAVE_DEBUG", "EXEC_IMAGE=weaveworks/weaveexec:latest"},
Cmd: []string{"cmd", "arg1", "arg2"},
Labels: map[string]string{"foo": "bar", "foobar": ""},
},
HostConfig: &docker.HostConfig{
NetworkMode: "host",
PidMode: "host",
Privileged: true,
RestartPolicy: docker.RestartPolicy{Name: "always"},
Binds: []string{"/var/run/docker.sock:/var/run/docker.sock", "/etc:/host/etc"},
VolumesFrom: []string{"weavedb"},
},
}
have := parseContainerArgs(args)
require.Equal(t, expected, have)
}
+1 -1
View File
@@ -225,7 +225,7 @@ func (proxy *Proxy) findVolume(v string) (string, error) {
}
func (proxy *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Log.Infof("%s %s", r.Method, r.URL)
Log.Debugf("%s %s", r.Method, r.URL)
path := r.URL.Path
var i interceptor
switch {
+66 -13
View File
@@ -482,7 +482,7 @@ func (fastdp *FastDatapath) getVxlanVportID(udpPort int) (odp.VportID, error) {
// The netdev interface is down, so most likely bringing it up
// has failed due to the UDP port being in use.
if err := fastdp.dp.DeleteVport(vxlanVportID); err != nil {
log.Warning("Unable to remove vxlan vport %d: %s", vxlanVportID, err)
log.Warningf("Unable to remove vxlan vport %d: %s", vxlanVportID, err)
}
return 0, odp.NetlinkError(syscall.EADDRINUSE)
}
@@ -582,9 +582,11 @@ type fastDatapathForwarder struct {
ackedHeartbeat bool
stopChan chan struct{}
stopped bool
establishedChan chan struct{}
errorChan chan error
healthy bool
established bool
establishedChan chan struct{}
errorChan chan error
healthChan chan bool
}
func (fastdp fastDatapathOverlay) PrepareConnection(params mesh.OverlayConnectionParams) (mesh.OverlayConnection, error) {
@@ -622,6 +624,7 @@ func (fastdp fastDatapathOverlay) PrepareConnection(params mesh.OverlayConnectio
connUID: params.ConnUID,
vxlanVportID: vxlanVportID,
sessionKey: params.SessionKey,
healthy: true,
remoteAddr: remoteAddr,
heartbeatInterval: FastHeartbeat,
@@ -629,6 +632,7 @@ func (fastdp fastDatapathOverlay) PrepareConnection(params mesh.OverlayConnectio
establishedChan: make(chan struct{}),
errorChan: make(chan error, 1),
healthChan: make(chan bool),
}
return fwd, nil
@@ -650,27 +654,26 @@ func (fwd *fastDatapathForwarder) logPrefix() string {
func (fwd *fastDatapathForwarder) Confirm() {
fwd.lock.Lock()
defer fwd.lock.Unlock()
if fwd.confirmed {
log.Fatal(fwd.logPrefix(), "already confirmed")
}
var controlMsg []byte
if fwd.fastdp.ipsec != nil && fwd.sessionKey != nil {
fwd.isEncrypted = true
log.Info("Setting up IPsec between ", fwd.fastdp.localPeer, " and ", fwd.remotePeer)
err := fwd.fastdp.ipsec.InitSALocal(
var err error
controlMsg, err = fwd.fastdp.ipsec.InitSALocal(
fwd.fastdp.localPeer.Name, fwd.remotePeer.Name, fwd.connUID,
net.IP(fwd.localIP[:]), fwd.remoteAddr.IP,
fwd.remoteAddr.Port,
fwd.sessionKey,
func(msg []byte) error {
return fwd.sendControlMsg(FastDatapathCryptoInitSARemote, msg)
},
)
if err != nil {
log.Error(fwd.logPrefix(), "ipsec init SA local failed: ", err)
fwd.handleError(err)
fwd.lock.Unlock()
return
}
}
@@ -688,6 +691,17 @@ func (fwd *fastDatapathForwarder) Confirm() {
}
fwd.heartbeatTimeout = time.NewTimer(HeartbeatTimeout)
fwd.lock.Unlock() // unlock before calling send() which may block
if len(controlMsg) > 0 {
if err := fwd.sendControlMsg(FastDatapathCryptoInitSARemote, controlMsg); err != nil {
log.Error(fwd.logPrefix(), "ipsec send InitSARemote failed: ", err)
fwd.handleError(err)
return
}
}
go fwd.doHeartbeats()
}
@@ -699,19 +713,40 @@ func (fwd *fastDatapathForwarder) ErrorChannel() <-chan error {
return fwd.errorChan
}
func (fwd *fastDatapathForwarder) HealthChannel() <-chan bool {
return fwd.healthChan
}
func (fwd *fastDatapathForwarder) doHeartbeats() {
var err error
for err == nil {
select {
case <-fwd.heartbeatTimer.C:
if fwd.confirmed {
log.Debug(fwd.logPrefix(), "sending Heartbeat to peer")
fwd.sendHeartbeat()
}
fwd.heartbeatTimer.Reset(fwd.heartbeatInterval)
case <-fwd.heartbeatTimeout.C:
err = fmt.Errorf("timed out waiting for vxlan heartbeat")
log.Debug(fwd.logPrefix(), "missed Heartbeat from peer, marking fastdp forwarder as un-healthy")
// treat missed heartbeat as transient error. Indicate to overlay forwarder
// that Forwarder is un-healthy so it can pick next best forwarder
fwd.healthChan <- false
// switch from fast-heartbeat to slow-heartbeat to avoid aggressive heartbeats
// when there is no estbalished session with peer yet
if fwd.heartbeatInterval != SlowHeartbeat {
fwd.heartbeatInterval = SlowHeartbeat
if fwd.heartbeatTimer != nil {
fwd.heartbeatTimer.Reset(fwd.heartbeatInterval)
}
}
if fwd.healthy {
fwd.healthy = false
}
case <-fwd.stopChan:
return
@@ -744,7 +779,6 @@ func (fwd *fastDatapathForwarder) handleError(err error) {
func (fwd *fastDatapathForwarder) sendHeartbeat() {
fwd.lock.RLock()
log.Debug(fwd.logPrefix(), "sendHeartbeat")
// the heartbeat payload consists of the 64-bit connection uid
// followed by the 16-bit packet size.
@@ -801,13 +835,23 @@ func (fwd *fastDatapathForwarder) handleVxlanSpecialPacket(frame []byte, sender
if !fwd.ackedHeartbeat {
fwd.ackedHeartbeat = true
log.Debug(fwd.logPrefix(), "Ack Heartbeat from peer")
fwd.handleError(fwd.sendControlMsg(FastDatapathHeartbeatAck, nil))
} else {
log.Debug(fwd.logPrefix(), "Got Heartbeat Ack from peer")
}
// we can receive a heartbeat before Confirm() has set up
// heartbeatTimeout
if fwd.heartbeatTimeout != nil {
fwd.heartbeatTimeout.Reset(HeartbeatTimeout)
if !fwd.healthy {
// If fastdp was marked as unhealthy earlier due to missed heartbeat then indicate to
// overlay forwarder that Forwarder is healthy now so it can pick next best forwarder
log.Debug(fwd.logPrefix(), "got Heartbeat from peer, marking fastdp forwarder as healthy")
fwd.healthy = true
fwd.healthChan <- true
}
}
}
@@ -833,8 +877,12 @@ func (fwd *fastDatapathForwarder) Attrs() map[string]interface{} {
func (fwd *fastDatapathForwarder) handleHeartbeatAck() {
log.Debug(fwd.logPrefix(), "handleHeartbeatAck")
if fwd.heartbeatInterval != SlowHeartbeat {
if !fwd.established {
close(fwd.establishedChan)
fwd.established = true
}
if fwd.heartbeatInterval != SlowHeartbeat {
fwd.heartbeatInterval = SlowHeartbeat
if fwd.heartbeatTimer != nil {
fwd.heartbeatTimer.Reset(fwd.heartbeatInterval)
@@ -843,6 +891,11 @@ func (fwd *fastDatapathForwarder) handleHeartbeatAck() {
}
func (fwd *fastDatapathForwarder) handleCryptoInitSARemote(msg []byte) {
if fwd.stopped {
log.Info(fwd.logPrefix(), "IPSec init SA remote failed: forwarder has already been stopped")
return
}
log.Info(fwd.logPrefix(), "IPSec init SA remote")
err := fwd.fastdp.ipsec.InitSARemote(
msg,
+9 -1
View File
@@ -3,6 +3,7 @@ package router
import (
"fmt"
"net/http"
"strconv"
"github.com/gorilla/mux"
@@ -37,7 +38,14 @@ func (router *NetworkRouter) HandleHTTP(muxRouter *mux.Router) {
return
}
if err = net.Expose(router.BridgeConfig.WeaveBridgeName, cidr.IPNet(), router.BridgeConfig.AWSVPC, router.BridgeConfig.NPC); err != nil {
var skipNAT bool
if r.FormValue("skipNAT") != "" {
if skipNAT, err = strconv.ParseBool(r.FormValue("skipNAT")); err != nil {
http.Error(w, fmt.Sprint("unable to parse skipNAT option: ", err.Error()), http.StatusBadRequest)
}
}
if err = net.Expose(router.BridgeConfig.WeaveBridgeName, cidr.IPNet(), router.BridgeConfig.AWSVPC, router.BridgeConfig.NPC, skipNAT); err != nil {
http.Error(w, fmt.Sprint("unable to expose: ", err.Error()), http.StatusInternalServerError)
return
}
+2
View File
@@ -31,6 +31,8 @@ type OverlayForwarder interface {
// Confirm(). The return value nil means the key could not be
// handled by this forwarder.
Forward(ForwardPacketKey) FlowOp
HealthChannel() <-chan bool
}
type NullNetworkOverlay struct{ mesh.NullOverlay }
+34 -1
View File
@@ -142,6 +142,7 @@ type overlaySwitchForwarder struct {
alreadyEstablished bool
establishedChan chan struct{}
errorChan chan error
healthChan chan bool
}
// A subsidiary forwarder
@@ -154,6 +155,9 @@ type subForwarder struct {
// closed to tell the forwarder monitor goroutine to stop
stopChan chan<- struct{}
// set to true to skip this forwarder in chooseBest()
onHold bool
}
// An event from a subsidiary forwarder
@@ -166,6 +170,9 @@ type subForwarderEvent struct {
// is this an error event?
err error
// event to indicate if forwarder is in healthy state to be considered for best forwarded
healthy *bool
}
func (osw *OverlaySwitch) PrepareConnection(params mesh.OverlayConnectionParams) (mesh.OverlayConnection, error) {
@@ -248,6 +255,9 @@ loop:
e.established = true
establishedChan = nil
case healthy := <-fwd.HealthChannel():
e.healthy = &healthy
case err := <-fwd.ErrorChannel():
e.err = err
@@ -282,6 +292,8 @@ loop:
fwd.established(e.index)
case e.err != nil:
fwd.error(e.index, e.err)
case e.healthy != nil:
fwd.healthCheck(e.index, *e.healthy)
}
}
}
@@ -318,6 +330,23 @@ func (fwd *overlaySwitchForwarder) error(index int, err error) {
fwd.chooseBest()
}
func (fwd *overlaySwitchForwarder) healthCheck(index int, healthy bool) {
fwd.lock.Lock()
defer fwd.lock.Unlock()
if healthy == true && fwd.forwarders[index].onHold {
log.Debug(fwd.logPrefix(), "Adding "+fwd.forwarders[index].overlayName+" to the list of forwarders")
fwd.forwarders[index].onHold = false
fwd.chooseBest()
}
if healthy == false && !fwd.forwarders[index].onHold {
log.Debug(fwd.logPrefix(), "Removing "+fwd.forwarders[index].overlayName+" from the list of forwarders")
fwd.forwarders[index].onHold = true
fwd.chooseBest()
}
}
func (fwd *overlaySwitchForwarder) stopFrom(index int) {
for index < len(fwd.forwarders) {
subFwd := &fwd.forwarders[index]
@@ -337,7 +366,7 @@ func (fwd *overlaySwitchForwarder) chooseBest() {
for i := range fwd.forwarders {
subFwd := &fwd.forwarders[i]
if subFwd.fwd == nil {
if subFwd.fwd == nil || subFwd.onHold {
continue
}
@@ -415,6 +444,10 @@ func (fwd *overlaySwitchForwarder) ErrorChannel() <-chan error {
return fwd.errorChan
}
func (fwd *overlaySwitchForwarder) HealthChannel() <-chan bool {
return fwd.healthChan
}
func (fwd *overlaySwitchForwarder) Stop() {
fwd.lock.Lock()
defer fwd.lock.Unlock()
+5 -1
View File
@@ -4,10 +4,14 @@ import (
"fmt"
"net"
"sync"
"time"
"github.com/google/gopacket/pcap"
)
// Must be less than 2^31 usec - see https://github.com/google/gopacket/issues/708
const longTimeout = time.Duration(30 * time.Minute)
type Pcap struct {
NonDiscardingFlowOp
@@ -77,7 +81,7 @@ func newPcapHandle(ifName string, promisc bool, snaplen int, bufSz int) (handle
if err = inactive.SetSnapLen(snaplen); err != nil {
return
}
if err = inactive.SetTimeout(MaxDuration); err != nil {
if err = inactive.SetTimeout(longTimeout); err != nil {
return
}
if err = inactive.SetImmediateMode(true); err != nil {
+6 -1
View File
@@ -326,6 +326,7 @@ type sleeveForwarder struct {
// listener channels
establishedChan chan struct{}
errorChan chan error
healthChan chan bool
// Explicitly locked state
lock sync.RWMutex
@@ -445,6 +446,10 @@ func (fwd *sleeveForwarder) ErrorChannel() <-chan error {
return fwd.errorChan
}
func (fwd *sleeveForwarder) HealthChannel() <-chan bool {
return fwd.healthChan
}
type curriedForward struct {
NonDiscardingFlowOp
fwd *sleeveForwarder
@@ -1087,7 +1092,7 @@ func (sender *udpSenderDF) send(msg []byte, raddr *net.UDPAddr) error {
}
defer f.Close()
log.Print("EMSGSIZE on send, expecting PMTU update (IP packet was ", len(packet), " bytes, payload was ", len(msg), " bytes)")
log.Debug("sleeve ->[", sender, "] expecting PMTU update (IP packet was ", len(packet), " bytes, payload was ", len(msg), " bytes)")
pmtu, err := syscall.GetsockoptInt(int(f.Fd()), syscall.IPPROTO_IP, syscall.IP_MTU)
if err != nil {
return err
+9
View File
@@ -142,6 +142,15 @@ is not reachable, then the packet is dropped. For most protocols
(for example, TCP), the transmission will be retried a short time later, by
which time the topology should have updated.
#### <a name="connection-limit"></a>Connection Limit
In a fully connected mesh of N peers, this would mean N^2 connections. To constrain the resource consumption and
communication between the peers and complexity of route calculation there is a configurable upper limit on the
maximum number of connections that a peer can make to the remote peers. There is safe default value (100) which works
for most deployment. However if you would like to increase the number of peers, you should be able to explicitly override the
default value by passing the value through `connlimit` flag for e.g.`weave launch --connlimit=100`. If you are using Weave with
Kubernetes using [Kubernetes Addon](/site/kubernetes/kube-addon.md) then you can set CONN_LIMIT environment variable to set
the connection limit.
**See Also**
-1
View File
@@ -31,7 +31,6 @@ Install Weave Net from the command line on its own or if you are using Docker, K
* [Integrating Kubernetes and Mesos via the CNI Plugin](https://www.weave.works/docs/net/latest/kubernetes/)
* [Integrating Kubernetes via the Addon](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/)
* [Installation](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/#install)
* [Upgrading Kubernetes to version 1.6](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/#kube-1.6-upgrade)
* [Upgrading the Daemon Sets](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/#daemon-sets)
* [CPU and Memory Requirements](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/#resources)
* [Pod Eviction](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/#eviction)
+2 -4
View File
@@ -48,10 +48,8 @@ To disable this check, run the following before launching Weave Net:
### Guides for Specific Platforms
CoreOS users see [here](/guides/networking-docker-containers-with-weave-on-coreos/) for an example of installing Weave using cloud-config.
Amazon ECS users see [here](https://github.com/weaveworks/integrations/blob/master/aws/ecs/README.md)
for the latest Weave AMIs and [here](https://www.weave.works/docs/tutorials/old-guides/ecs/) to get started with Weave Net on ECS.
Amazon ECS users see [here](https://www.weave.works/docs/scope/latest/ami/)
for the latest Weave AMIs.
If you're on Amazon EC2, the standard installation instructions at the
top of this page, provide the simplest setup and the most flexibility.
+3 -1
View File
@@ -30,6 +30,8 @@ Then run:
weave setup
Weave net depends on the *portmap* [standard](https://github.com/containernetworking/plugins) CNI plugin to support *hostport* functionality. Please ensure that *portmap* CNI plugin is installed in `/opt/cni/bin` directory.
#### Launching Weave Net
To create a network that spans multiple hosts, the Weave peers must be connected to each other.
@@ -45,7 +47,7 @@ for a discussion on peer connections.
All CNI plugins are configured by a JSON file in the directory
`/etc/cni/net.d/`. `weave setup` installs a minimal configuration
file named `10-weave.conf`, which you can alter to suit your needs.
file named `10-weave.conflist`, which you can alter to suit your needs.
See the [CNI Spec](https://github.com/appc/cni/blob/master/SPEC.md#network-configuration)
for details on the format and contents of this file.
+81 -44
View File
@@ -7,7 +7,8 @@ search_type: Documentation
The following topics are discussed:
* [Installation](#install)
* [Upgrading Kubernetes to version 1.6](#kube-1.6-upgrade)
* [Installing on GKE](#gke)
* [Installing on EKS](#eks)
* [Upgrading the Daemon Sets](#daemon-sets)
* [CPU and Memory Requirements](#resources)
* [Pod Eviction](#eviction)
@@ -19,6 +20,7 @@ The following topics are discussed:
* [Troubleshooting Blocked Connections](#blocked-connections)
* [Things to watch out for](#key-points)
* [Changing Configuration Options](#configuration-options)
* [Securing The Setup](#securing-the-setup)
## <a name="install"></a> Installation
@@ -34,6 +36,8 @@ with a single command:
$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
```
**Important:** this configuration won't enable encryption by default. If your data plane traffic isn't secured that could allow malicious actors to access your pod network. Read on to see the alternatives.
After a few seconds, a Weave Net pod should be running on each
Node and any further pods you create will be automatically attached to the Weave
network.
@@ -50,6 +54,11 @@ recommend your master node has at least two CPU cores.
> [kubeadm](http://kubernetes.io/docs/getting-started-guides/kubeadm/).
>
> Alternatively, you can [configure CNI yourself](http://kubernetes.io/docs/admin/network-plugins/#cni)
>
> Weave net depends on the *portmap* [standard](https://github.com/containernetworking/plugins) CNI plugin
> to support *hostport* functionality. Please ensure that *portmap* CNI plugin is installed
> (either by cluster installers like kubeadm or manually if you have configured CNI yourself) in `/opt/cni/bin` directory.
**Note:** If using the [Weave CNI
Plugin](/site/kubernetes.md) from a prior full install of Weave Net with your
@@ -64,38 +73,33 @@ Shut down Kubernetes, and _on all nodes_ perform the following:
Then relaunch Kubernetes and install the addon as described
above.
## <a name="kube-1.6-upgrade"></a> Upgrading Kubernetes to version 1.6
### <a name="gke"></a> Installing on GKE
Please note that you must grant the user the ability to create roles in Kubernetes before launching Weave Net.
This is a prerequisite to use use role-based access control on GKE. Please see the GKE [instructions](https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control).
In version 1.6, Kubernetes has increased security, so we need to
create a special service account to run Weave Net. This is done in
the file `weave-daemonset-k8s-1.6.yaml` attached to the [Weave Net
release](https://github.com/weaveworks/weave/releases/latest).
### <a name="gke"></a> Installing on EKS
Also, the
[toleration](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/taint-toleration-dedicated.md)
required to let Weave Net run on master nodes has moved from an
annotation to a field on the DaemonSet spec object.
EKS by default installs `amazon-vpc-cni-k8s` CNI. Please follow below steps to use Weave-net as CNI
- create EKS cluster in any of [prescribed](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html) way
- delete `amazon-vpc-cni-k8s` deamonset by running `kubectl delete ds aws-node -n kube-system` command
- delete `/etc/cni/net.d/10-aws.conflist` on each of the node
- edit instance security group to allow TCP 6783 and UDP 6783/6784 ports
- flush iptables nat, mangle, filter tables to clear any iptables configurations done by `amazon-vpc-cni-k8s`
- restart kube-proxy pods to reconfigure iptables
- apply weave-net daemoset by following above installation steps
- delete existing pods so they get recreated in Weave pod CIDR's address-space.
Please note that while pods can connect to the Kubernetes API server for your cluser, API server will not be able to connect to the pods as API server nodes are not connected to Weave Net (they run on network managed by EKS).
If you have edited the Weave Net DaemonSet from a previous release,
you will need to re-make your changes against the new version.
### <a name="daemon-sets"></a> Upgrading the Daemon Sets
For Kubernetes 1.6 and above the DaemonSet definition specifies
[Rolling Updates](https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/),
The DaemonSet definition specifies [Rolling
Updates](https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/),
so when you apply a new version Kubernetes will automatically restart
the Weave Net pods one by one.
Kubernetes v1.5 and below does not support rolling upgrades of daemon sets,
and so you will need to perform the procedure manually:
* Apply the updated addon manifest `kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"`
* Kill each Weave Net pod with `kubectl delete` and then wait for it to reboot before moving on to the next pod.
**Note:** In versions prior to Weave Net 2.0, deleting all Weave Net pods at the same time
will result in them losing track of IP address range ownership, possibly leading to
duplicate IP addresses if you then start a new copy of Weave Net.
## <a name="resources"></a>CPU and Memory Requirements
Kubernetes manages
@@ -103,23 +107,18 @@ Kubernetes manages
on each node, and only schedules pods to run on nodes that have enough
free resources.
The components of a typical Kubernetes installation (with the master
node running etcd, scheduler, api-server, etc.) take up about 95% of a
CPU, which leaves little room to run anything else. For all of Weave
Net's features to work, it must run on every node, including the
master.
In the example manifests we request 10% of a CPU, which will be enough
for small installations, but you should monitor how much it uses in
your production clusters and adjust the requests to suit.
The best way to resolve this issue is to use machines with at least
two CPU cores. However if you are installing Kubernetes and Weave Net
for the first time, you may not be aware of this requirement. For this
reason, Weave Net launches as a DaemonSet with a specification that
reserves at least 1% CPU for each container. This enables Weave Net to
start up seamlessly on a single-CPU node.
We do not recommend that you set a CPU or memory _limit_ unless you
are very experienced in such matters, because the implementation of
limits in the Linux kernel sometimes behaves in a surprising way.
Depending on the workload, Weave Net may need more than 1% of the
CPU. The percentage set in the DaemonSet is the minimum and not a
limit. This minimum setting allows Weave Net to take advantage of
available CPU and "burst" above that limit if it needs to.
On a 1-node single-CPU cluster you may find Weave Net does not install
at all, because other Kubernetes components already take 95% of the
CPU. The best way to resolve this issue is to use machines with at
least two CPU cores.
## <a name="eviction"></a>Pod Eviction
@@ -180,7 +179,7 @@ labels. For more information on configuring network policies in
Kubernetes see the
[walkthrough](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy/)
and the [NetworkPolicy API object
definition](https://v1-7.docs.kubernetes.io/docs/api-reference/v1.7/#networkpolicy-v1-networking)
definition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#networkpolicy-v1-networking-k8s-io)
**Note:** as of version 1.9 of Weave Net, the Network Policy
Controller allows all multicast traffic. Since a single multicast
@@ -189,6 +188,11 @@ definition](https://v1-7.docs.kubernetes.io/docs/api-reference/v1.7/#networkpoli
all multicast traffic) by adding `--allow-mcast=false` as an
argument to `weave-npc` in the YAML configuration.
**Note:** Since ingress traffic is masqueraded, it makes sense to use
`ipBlock` selector in an ingress rule only when limiting access to a Service
annotated with `externalTrafficPolicy=Local` or between Pods when `podIP` is used
to access a Pod.
## <a name="troubleshooting"></a> Troubleshooting
The first thing to check is whether Weave Net is up and
@@ -221,12 +225,26 @@ ask for the logs like this:
$ kubectl logs -n kube-system weave-net-1jkl6 weave
```
For easier viewing, pipe the output into a file , especially if
For easier viewing, pipe the output into a file, especially if
it is long.
By default log level of `weave` container is set to `info` level. If you wish to see more detailed logs you can set the desired log level for the `--log-level` flag through the `EXTRA_ARGS` environment variable for the `weave` container in the weave-net daemon set. Add environment variable as below.
```yaml
containers:
- command:
- /home/weave/launch.sh
name: weave
env:
- name: EXTRA_ARGS
value: --log-level=debug
```
You may also set the `--log-level` flag to `warning` or `error` if you
prefer to only log exceptional conditions.
Many Kubernetes network issues occur at a higher level than Weave Net.
The [Kubernetes Service Debugging Guide]
(https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/)
The [Kubernetes Service Debugging Guide](https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/)
has a detailed step-by-step guide.
Once it is up and running, the status of Weave Net can be checked by
@@ -336,6 +354,8 @@ UDP connection from 10.32.0.7:56648 to 10.32.0.11:80 blocked by Weave NPC.
### <a name="key-points"></a> Things to watch out for
- Weave Net does not work on hosts running iptables 1.8 or above, only with 1.6.
Track this via issue [#3465](https://github.com/weaveworks/weave/issues/3465)
- Don't turn on `--masquerade-all` on kube-proxy: this will change the
source address of every pod-to-pod conversation which will make it
impossible to correctly enforce network policies that restrict which
@@ -376,7 +396,7 @@ The list of variables you can set is:
* `CHECKPOINT_DISABLE` - if set to 1, disable checking for new Weave Net
versions (default is blank, i.e. check is enabled)
* `CONN_LIMIT` - soft limit on the number of connections between
peers. Defaults to 30.
peers. Defaults to 200.
* `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
@@ -404,6 +424,7 @@ The list of variables you can set is:
* `NO_MASQ_LOCAL` - set to 1 to preserve the client source IP address when
accessing Service annotated with `service.spec.externalTrafficPolicy=Local`.
The feature works only with Weave IPAM (default).
* `IPTABLES_BACKEND` - set to `nft` to use `nftables` backend for `iptables` (default is `iptables`)
Example:
```
@@ -442,3 +463,19 @@ For example,
- name: IPALLOC_RANGE
value: 10.0.0.0/16
```
## <a name="securing-the-setup"></a> Securing the Setup
You must pass the `password-secret` option as noted in the previous section to enable the data plane encryption; this is a recommended option in case you cannot be sure about the security of the fabric between your nodes.
A different option is to use `trusted-subnets` and whitelist only the subnets that host your k8s nodes. Mind that depending on your circumstances that might allow a malicious container running in your cluster to access the weave dataplane, still.
Read on the [Securing Connections Across Untrusted Networks](/site/tasks/manage/security-untrusted-networks/) document to see the alternatives.
To improve security drop `CAP_NET_RAW` from pod capabilities: by default pods can forge packets from anywhere on the network, which enables attacks such as DNS spoofing.
```
securityContext:
capabilities:
drop: ["NET_RAW"]
```
+3
View File
@@ -9,6 +9,9 @@ Weave Net creates a virtual network that connects Docker containers across multi
Services provided by application containers on the weave network can be exposed to the outside world, regardless of where they are running. Similarly, existing internal systems can be opened to accept connections from application containers irrespective of their location.
### How does it work?
Weave Net creates a new Layer 2 network using Linux kernel features; one daemon sets up that network and manages routing between machines and there are various ways to attach to that network (e.g. a CNI plugin which runs as a separate process). Also one more daemon if you are using Kubernetes Network Policy.
## Why Weave?
+16 -1
View File
@@ -13,7 +13,22 @@ Weave Net detects when a container has exited and releases its allocated address
See the [Automatic IP Address Management](/site/tasks/ipam/ipam.md) and also an explanation of [the basics of IP addressing](/site/concepts/ip-addresses.md) for further details.
Instead of allowing Weave Net to allocate IP addresses automatically (using IPAM), there may be instances where you need to control a particular container or a cluster by setting an IP address for it.
Instead of allowing Weave Net to allocate IP addresses automatically (using IPAM), there may be instances where you need to control a particular container or a cluster by setting an IP address for it. The way to do this varies according to how containers are attached to Weave Net.
## Manually specifying an IP address when using CNI
The software making a call to CNI has to specify an allocator that allows static IPs.
For instance the [static allocator](https://github.com/containernetworking/plugins/tree/master/plugins/ipam/static)
(At the time of writing there is no straightforward way to ask Kubernetes to do this.)
## Manually specifying an IP address when using the Weave Net Docker Plugin
Docker has a flag `--ip` to specify an address, e.g.:
$ docker run --network=mynetwork --ip=172.18.0.22 ...
## Manually specifying an IP address when using the Weave Net Docker Proxy
You can specify an IP address and a network explicitly, using Classless Inter-Domain Routing or [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing).
+1 -1
View File
@@ -332,6 +332,6 @@ and the container image versions as git hashes.
**See Also**
* [Troubleshooting the Kubernetes Addon](/site/kubernetes/kube-addon/#troubleshooting)
* [Troubleshooting the Kubernetes Addon](/site/kubernetes/kube-addon.md#troubleshooting)
* [Troubleshooting IPAM](/site/tasks/ipam/troubleshooting-ipam.md)
* [Troubleshooting the Proxy](/site/tasks/weave-docker-api/using-proxy.md)
+8
View File
@@ -26,10 +26,15 @@ start_container $HOST2 $C2/24 --name=c2
assert_raises "weave_on $HOST2 connect 10.2.2.1 10.2.2.2"
assert_peers $HOST2 "10.2.2.1\n10.2.2.2"
sleep 2 # Allow topology to propagate
# Replace bogus hosts with real hosts
assert_raises "exec_on $HOST1 c1 sh -c '! $PING $C2'"
assert_raises "weave_on $HOST2 connect --replace $HOST1 $HOST2"
assert_peers $HOST2 "$HOST1\n$HOST2"
sleep 2 # Allow topology to propagate
assert_raises "exec_on $HOST1 c1 $PING $C2"
# Forget everyone and disconnect
@@ -37,6 +42,9 @@ assert_raises "weave_on $HOST2 forget $HOST1 $HOST2"
assert_raises "stop_weave_on $HOST1"
assert_raises "weave_on $HOST1 launch"
assert_peers $HOST2 ""
sleep 2 # Allow topology to propagate
assert_raises "exec_on $HOST1 c1 sh -c '! $PING $C2'"
end_suite
+3 -1
View File
@@ -9,7 +9,7 @@ kill_weaver() {
run_on $HOST1 sudo ip link set weave down
WEAVER_PID=$(container_pid $HOST1 weave)
run_on $HOST1 sudo kill -9 $WEAVER_PID
sleep 3
sleep 5
}
start_suite "Re-create bridge after restart"
@@ -20,6 +20,7 @@ WEAVE_NO_FASTDP=1 weave_on $HOST2 launch $HOST1
start_container $HOST1 $C1/24 --name=c1
start_container $HOST2 $C2/24 --name=c2
sleep 2 # give topology gossip some time to propagate
assert_raises "exec_on $HOST1 c1 $PING $C2"
kill_weaver # should re-create the bridge
@@ -30,6 +31,7 @@ assert_raises "exec_on $HOST1 c1 $PING $C2"
weave_on $HOST1 reset
weave_on $HOST1 launch $HOST2
weave_on $HOST1 attach $C1/24 c1
sleep 2 # give topology gossip some time to propagate
assert_raises "exec_on $HOST1 c1 $PING $C2"
kill_weaver # should re-create the bridge
+2
View File
@@ -16,6 +16,8 @@ for host in $HOSTS; do
weave_on $host launch --ipalloc-range $UNIVERSE $HOSTS
done
sleep 2 # Allow topology updates to propagate
# Basic test
start_container $HOST2 $C2/24 --name=c2 -h $NAME2
start_container_with_dns $HOST1 $C1/24 --name=c1
+3 -1
View File
@@ -8,6 +8,8 @@ weave_on $HOST1 launch --no-discovery
weave_on $HOST2 launch --no-discovery $HOST1
weave_on $HOST3 launch --no-discovery $HOST2
sleep 2 # Allow topology updates to propagate
start_container $HOST1 --name=c1
C1=$(container_ip $HOST1 c1)
start_container_with_dns $HOST3 --name=c3
@@ -25,7 +27,7 @@ weave_on $HOST1 launch --no-discovery $HOST3
# Now re-enable gossip from host2 to host3
run_on $HOST3 "sudo iptables -D INPUT -s $HOST2 -j DROP"
sleep 1
sleep 2 # allow some time for connections to reform and updates to propagate
assert_no_dns_record $HOST3 c3 c1.weave.local
+1 -1
View File
@@ -66,7 +66,7 @@ weave_on $HOST1 launch --ipalloc-range $UNIVERSE $HOST2
# Start another container on host1. The starting should block, because host1 is
# not able to establish the ring due to host2 being offline.
CMD="proxy_start_container $HOST1 --name c4 -e WEAVE_CIDR=$C4/12"
assert_raises "timeout 5 cat <( $CMD )" 124
assert_raises "timeout --signal=9 5 cat <( $CMD )" 137
# However, allocation for an external subnet should not block.
assert_raises "proxy_start_container $HOST1 -e WEAVE_CIDR=10.3.0.1/12"
+3
View File
@@ -15,6 +15,9 @@ assert_raises "timeout 10 cat <( start_container $HOST2 --name c2)"
# Connect routers
weave_on $HOST2 connect $HOST1
# Allow topology to propagate
sleep 2
# Check connectivity
assert_raises "exec_on $HOST1 c1 $PING c2"
assert_raises "exec_on $HOST2 c2 $PING c1"
+3
View File
@@ -13,6 +13,9 @@ docker_py_test() {
# Work round https://github.com/docker/docker-py/issues/852
docker_on $HOST1 pull busybox:buildroot-2014.02 >/dev/null
# Work round https://github.com/weaveworks/weave/issues/3680 - pin busybox version to 1.28
docker_on $HOST1 pull busybox:1.28 >/dev/null
docker_on $HOST1 tag busybox:1.28 busybox:latest >/dev/null
# Get a list of the tests for use to shard
docker_on $HOST1 pull $IMAGE >/dev/null
CANDIDATES=$(docker_on $HOST1 run \
+2
View File
@@ -15,6 +15,8 @@ weave_on $HOST2 launch $HOST1
start_container_local_plugin $HOST1 --name=c1 --hostname=$C1_NAME --dns=$DNS_IP
start_container_local_plugin $HOST2 --name=c2 --hostname=$C2_NAME --dns=$DNS_IP
sleep 2 # Allow topology to propagate
assert_raises "exec_on $HOST1 c1 $PING $C2_NAME"
assert_raises "exec_on $HOST2 c2 $PING $C1_NAME"
+29 -2
View File
@@ -52,7 +52,7 @@ fi
# Ensure Kubernetes uses locally built container images and inject code coverage environment variable (or do nothing depending on $COVERAGE):
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
-e "s%env:%$WEAVE_ENV_VARS%" \
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.8.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.9.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
sleep 5
@@ -214,11 +214,17 @@ spec:
access: deny
EOF
# Allow some time for the policy change to take effect
sleep 2
assert_raises "$SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http://$DOMAIN:8080/status >/dev/null"
# remove the access for nettest-deny
run_on $HOST1 "$KUBECTL delete netpol allow-nettest-deny"
# Allow some time for the policy change to take effect
sleep 2
# nettest-deny should still not be able to reach nettest pods
assert_raises "! $SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http://$DOMAIN:8080/status >/dev/null"
@@ -249,6 +255,27 @@ assert_raises "$SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http
assert_raises "! $SSH $HOST1 curl -s -S -f -m 2 http://$VIRTUAL_IP/status >/dev/null"
assert_raises "! $SSH $HOST1 curl -s -S -f -m 2 http://$HOST2:31138/status >/dev/null"
# allow access only from weave bridge IP of host1 to test ipBlock
run_on $HOST1 "$KUBECTL apply -f -" <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-via-weave-bridge-of-host1
namespace: default
spec:
podSelector: {}
ingress:
- from:
- ipBlock:
cidr: $HOST1EXPIP/32
EOF
sleep 2
assert_raises "$SSH $HOST1 curl -s -S -f -m 2 http://$VIRTUAL_IP/status >/dev/null"
run_on $HOST1 "$KUBECTL delete netpol allow-via-weave-bridge-of-host1"
# allow access from anywhere
run_on $HOST1 "$KUBECTL apply -f -" <<EOF
apiVersion: networking.k8s.io/v1
@@ -330,7 +357,7 @@ WEAVE_ENV_VARS="${WEAVE_ENV_VARS}\\n - name: NO_MASQ_LOCAL\\n
$SSH $HOST1 "$KUBECTL delete ds weave-net -n=kube-system"
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
-e "s%env:%$WEAVE_ENV_VARS%" \
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.8.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.9.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
sleep 5
Loaded 100 of 1256 files, more files were not shown because too many files have changed in this diff. Show more