Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1abdc3afcf | ||
|
|
b8f98a5387 | ||
|
|
cb3b858df6 | ||
|
|
afb0d5bd3d | ||
|
|
2d3e070288 | ||
|
|
138141ac9b | ||
|
|
fa56ad8bc3 | ||
|
|
9d29da8d27 | ||
|
|
68f2cb9caa | ||
|
|
d13c7ea7ee | ||
|
|
4c7c702b6d | ||
|
|
c05955d598 | ||
|
|
ca64ab54e7 | ||
|
|
e64442f6de | ||
|
|
987a1618e9 | ||
|
|
0ab95cdd27 | ||
|
|
b0d0c3d731 | ||
|
|
534dd8e16a | ||
|
|
79e703c8ac | ||
|
|
d4a98a58f4 | ||
|
|
72532324ed | ||
|
|
68106d804e | ||
|
|
efff6d6e63 | ||
|
|
6bbd8d7a4c | ||
|
|
9cbf0289d8 | ||
|
|
255d087416 | ||
|
|
8668f6bb1e | ||
|
|
95ee99d652 | ||
|
|
30583ec8f2 | ||
|
|
e370ef7007 | ||
|
|
42953faf70 | ||
|
|
6c29a1f648 | ||
|
|
fa29b18be7 | ||
|
|
40db885b3a | ||
|
|
ae0c16f375 | ||
|
|
909b751d6d | ||
|
|
9419ad16bf | ||
|
|
2c12c4f67e | ||
|
|
be11db45d8 | ||
|
|
30213bd71e | ||
|
|
b14501f358 | ||
|
|
e93a145bab | ||
|
|
8b245a442c | ||
|
|
109e249aa6 | ||
|
|
60c5e11871 |
No files matched your search
@@ -70,3 +70,6 @@ test/coverage.*
|
||||
*qemu-*-static
|
||||
terraform.tfstate
|
||||
terraform.tfstate.backup
|
||||
|
||||
# Website
|
||||
site-build
|
||||
@@ -0,0 +1 @@
|
||||
2.3.0
|
||||
@@ -1,3 +1,39 @@
|
||||
## Release 1.9.7
|
||||
|
||||
This is identical to 1.9.6 with one additional bug-fix:
|
||||
|
||||
* weave-npc would block everything if `kubectl --hostname-override` was used #2995,#2996
|
||||
|
||||
## Release 1.9.6
|
||||
|
||||
Bug fixes and minor improvements
|
||||
|
||||
* Ensure that Kubernetes pods can contact a service implemented within
|
||||
the same pod, by turning on "hairpin mode". This is required because
|
||||
of a quiet change between Kubernetes 1.5 and 1.6. #2993
|
||||
* Network Policy Controller (`weave-npc`) now checks local addresses
|
||||
only, so it doesn't interfere with cross-cluster traffic. It should
|
||||
be more efficient too #2622,#2973,#2979
|
||||
* Stop reporting back to Kubernetes any issues encountered when
|
||||
deleting a pod's network interface. This is required because
|
||||
of a quiet change between Kubernetes 1.5 and 1.6. #2921,#2928
|
||||
* Fixed an issue whereby `weave-npc` couldn't start because one
|
||||
`ipset` was referring to another one and could not be destroyed #2915,#2949
|
||||
* Improved the code which checks whether the kernel supports `ipset` #2934,#2935
|
||||
* `weave-npc` now creates ipsets with only valid xml characters in the
|
||||
name #2958,#2959
|
||||
|
||||
Build and Testing
|
||||
|
||||
* In build container use cross-compilers from debian package
|
||||
repository, so they match other components #2940
|
||||
* Pin the version of the linting tool `shfmt` so the set of things it
|
||||
checks is stable #2987
|
||||
* Fix lint error in script that runs smoke-tests #2962
|
||||
* Moved website publishing from Wordpress to Netlify #2986
|
||||
|
||||
[Full list of changes](https://github.com/weaveworks/weave/milestone/55?closed=1).
|
||||
|
||||
## Release 1.9.5
|
||||
|
||||
Bug fixes and minor improvements
|
||||
|
||||
@@ -378,3 +378,14 @@ integration-tests: all testrunner
|
||||
# integration-tests
|
||||
#
|
||||
RUNNER_ARGS="-parallel" ./test/run-integration-tests.sh
|
||||
|
||||
# This target is only intended for use in Netlify CI environment for generating preview pages on feature branches and pull requests.
|
||||
# We need to obtain website repository (checked out under `site-build`) and place `site` directory into the context (`site-build/_weave_net_docs`).
|
||||
# We then run make in `site-build` and Netlify will publish the output (`site-build/_site`).
|
||||
netlify-site-preview:
|
||||
@mkdir -p site-build
|
||||
@curl --user $(WEBSITE_GITHUB_USER) --silent 'https://codeload.github.com/weaveworks/website-next/tar.gz/$(WEBSITE_BRANCH)' \
|
||||
| tar --extract --gunzip --directory site-build --strip 1
|
||||
@cp -r site site-build/_weave_net_docs
|
||||
@$(MAKE) -C site-build netlify_ensure_install
|
||||
@$(MAKE) -C site-build BUILD_ENV=netlify
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
source "$STATE"
|
||||
|
||||
site_changes() {
|
||||
curl -s https://api.github.com/repos/weaveworks/weave/pulls/$1/files |
|
||||
jq -r '.[]|.status + " " + .filename' |
|
||||
grep -oP '^(added|modified|removed) site/.*(?=\.md$)'
|
||||
}
|
||||
|
||||
format_comment() {
|
||||
if [ ! -d .git ] || ! BRANCH=$(git symbolic-ref --short HEAD) || [ -z "$BRANCH" ] ; then
|
||||
echo "Could not determine branch" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "#### Documentation changes:"
|
||||
while read ACTION PAGE; do
|
||||
echo "$ACTION [${PAGE#site/}]($WP_DEV_URL/docs/net/${BRANCH#issues/}/${PAGE#site/}/)"
|
||||
done | sort
|
||||
}
|
||||
|
||||
post_comment() {
|
||||
jq -s -R '. | tostring | { body: . }' |
|
||||
curl -s -d @- \
|
||||
-H "Authorization: Bearer $WP_GH_COMMENT_TOKEN" \
|
||||
-H 'Content-Type: application/json' \
|
||||
https://api.github.com/repos/weaveworks/weave/issues/$GH_PR/comments > /dev/null
|
||||
}
|
||||
|
||||
cd $SRCDIR
|
||||
bin/install-wordepress v1.0.0
|
||||
bin/publish-site "$WP_DEV_URL" "$WP_DEV_USER" "$WP_DEV_PASSWORD"
|
||||
|
||||
if [ -n "$WP_GH_COMMENT_TOKEN" -a -n "$GH_PR" ] ; then
|
||||
echo ">>> Adding doc changelog to GitHub PR $GH_PR"
|
||||
if CHANGES=$(site_changes $GH_PR) && [ -n "$CHANGES" ] ; then
|
||||
echo "$CHANGES" | format_comment | post_comment
|
||||
fi
|
||||
fi
|
||||
@@ -11,7 +11,3 @@ if [ -n "$TEST_AND_PUBLISH" ] ; then
|
||||
# CircleCI doesn't let us install the qemu module to do ARM docker builds
|
||||
make publish ALL_ARCHITECTURES=amd64 UPDATE_LATEST=latest-only
|
||||
fi
|
||||
|
||||
cd $SRCDIR
|
||||
bin/install-wordepress v1.0.0
|
||||
bin/publish-site "$WP_DEV_URL" "$WP_DEV_USER" "$WP_DEV_PASSWORD"
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cd $SRCDIR
|
||||
bin/install-wordepress v1.0.0
|
||||
bin/publish-site "$WP_LIVE_URL" "$WP_LIVE_USER" "$WP_LIVE_PASSWORD"
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -ne 1 ] ; then
|
||||
echo USAGE: install-wordepress [COMMIT-ISH] >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
go get github.com/weaveworks/wordepress
|
||||
cd /home/ubuntu/src/github.com/weaveworks/wordepress
|
||||
git checkout $1
|
||||
cd cmd/wordepress
|
||||
go get
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
PRODUCT=net
|
||||
|
||||
fatal() {
|
||||
echo "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ ! -d .git ] ; then
|
||||
fatal "Current directory is not a git clone"
|
||||
fi
|
||||
|
||||
if ! BRANCH=$(git symbolic-ref --short HEAD) || [ -z "$BRANCH" ] ; then
|
||||
fatal "Could not determine branch"
|
||||
fi
|
||||
|
||||
case "$BRANCH" in
|
||||
issues/*)
|
||||
VERSION="${BRANCH#issues/}"
|
||||
TAGS="$VERSION"
|
||||
;;
|
||||
*)
|
||||
if echo "$BRANCH" | grep -qE '^[0-9]+\.[0-9]+' ; then
|
||||
DESCRIBE=$(git describe --match 'v*')
|
||||
if ! VERSION=$(echo "$DESCRIBE" | grep -oP '(?<=^v)[0-9]+\.[0-9]+\.[0-9]+') ; then
|
||||
fatal "Could not infer latest $BRANCH version from $DESCRIBE"
|
||||
fi
|
||||
TAGS="latest"
|
||||
else
|
||||
VERSION="$BRANCH"
|
||||
TAGS="$VERSION"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
for TAG in $TAGS ; do
|
||||
echo ">>> Publishing $PRODUCT $VERSION to $1/docs/$PRODUCT/$TAG"
|
||||
wordepress \
|
||||
--url "$1" --user "$2" --password "$3" \
|
||||
--product "$PRODUCT" --version "$VERSION" --tag "$TAG" \
|
||||
publish site
|
||||
done
|
||||
+8
-5
@@ -20,13 +20,12 @@ ENV GCC_CROSSCOMPILERS \
|
||||
|
||||
# Temporarily add the Ubuntu 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://archive.ubuntu.com/ubuntu xenial main universe" > /etc/apt/sources.list.d/cgocrosscompiling.list \
|
||||
&& apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 3B4FE6ACC0B21F32 \
|
||||
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 \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y build-essential \
|
||||
&& for platform in ${DEB_CROSSPLATFORMS}; do apt-get install -y crossbuild-essential-${platform}; done \
|
||||
&& rm /etc/apt/sources.list.d/cgocrosscompiling.list \
|
||||
&& apt-get update \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install some required packages
|
||||
@@ -41,11 +40,15 @@ RUN apt-get update \
|
||||
flex \
|
||||
bison
|
||||
|
||||
RUN curl -fsSLo shfmt https://github.com/mvdan/sh/releases/download/v1.3.0/shfmt_v1.3.0_linux_amd64 && \
|
||||
echo "b1925c2c405458811f0c227266402cf1868b4de529f114722c2e3a5af4ac7bb2 shfmt" | sha256sum -c && \
|
||||
chmod +x shfmt && \
|
||||
mv shfmt /usr/bin
|
||||
|
||||
# Install common Go tools
|
||||
RUN go get \
|
||||
github.com/golang/lint/golint \
|
||||
github.com/fzipp/gocyclo \
|
||||
gopkg.in/mvdan/sh.v1/cmd/shfmt \
|
||||
github.com/fatih/hclfmt \
|
||||
github.com/client9/misspell/cmd/misspell
|
||||
|
||||
|
||||
-10
@@ -59,18 +59,8 @@ teardown:
|
||||
parallel: true
|
||||
|
||||
deployment:
|
||||
release:
|
||||
branch: /[0-9]+\.[0-9]+/
|
||||
owner: weaveworks
|
||||
commands:
|
||||
- "$SRCDIR/bin/circle-deploy-release"
|
||||
master:
|
||||
branch: master
|
||||
owner: weaveworks
|
||||
commands:
|
||||
- "$SRCDIR/bin/circle-deploy-master"
|
||||
issues:
|
||||
branch: /.*/
|
||||
owner: weaveworks
|
||||
commands:
|
||||
- "$SRCDIR/bin/circle-deploy-issues"
|
||||
@@ -77,8 +77,10 @@ iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-INGRESS
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
Note this only affects traffic which egresses the bridge on a physical
|
||||
port which is not the Weave Net router - in other words, it is
|
||||
|
||||
+6
-2
@@ -113,7 +113,7 @@ func interfaceExistsInNamespace(netNSPath string, ifName string) bool {
|
||||
|
||||
// NB: This function can be used only by a process that terminates immediately
|
||||
// after calling the function as it changes netns via WithNetNSLinkUnsafe.
|
||||
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool) error {
|
||||
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool, hairpinMode bool) error {
|
||||
ns, err := netns.GetFromPath(netNSPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -131,7 +131,7 @@ 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
|
||||
_, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, func(veth netlink.Link) error {
|
||||
veth, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, 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)
|
||||
}
|
||||
@@ -143,6 +143,10 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = netlink.LinkSetHairpin(veth, hairpinMode); err != nil {
|
||||
return fmt.Errorf("unable to set hairpin mode to %t for bridge side of veth %s: %s", hairpinMode, name, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if err := WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error {
|
||||
|
||||
@@ -8,4 +8,6 @@ const (
|
||||
IngressChain = "WEAVE-NPC-INGRESS"
|
||||
|
||||
IpsetNamePrefix = "weave-"
|
||||
|
||||
LocalIpset = IpsetNamePrefix + "local-pods"
|
||||
)
|
||||
+25
-4
@@ -29,6 +29,8 @@ type NetworkPolicyController interface {
|
||||
type controller struct {
|
||||
sync.Mutex
|
||||
|
||||
nodeName string // my node name
|
||||
|
||||
ipt *iptables.IPTables
|
||||
ips ipset.Interface
|
||||
|
||||
@@ -36,11 +38,12 @@ type controller struct {
|
||||
nsSelectors *selectorSet // selector string -> nsSelector
|
||||
}
|
||||
|
||||
func New(ipt *iptables.IPTables, ips ipset.Interface) NetworkPolicyController {
|
||||
func New(nodeName string, ipt *iptables.IPTables, ips ipset.Interface) NetworkPolicyController {
|
||||
c := &controller{
|
||||
ipt: ipt,
|
||||
ips: ips,
|
||||
nss: make(map[string]*ns)}
|
||||
nodeName: nodeName,
|
||||
ipt: ipt,
|
||||
ips: ips,
|
||||
nss: make(map[string]*ns)}
|
||||
|
||||
c.nsSelectors = newSelectorSet(ips, c.onNewNsSelector)
|
||||
|
||||
@@ -82,10 +85,21 @@ func (npc *controller) withNS(name string, f func(ns *ns) error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (npc *controller) checkLocalPod(obj *coreapi.Pod, event string) bool {
|
||||
if obj.Spec.NodeName != npc.nodeName {
|
||||
common.Log.Debugf("%s ignored for pod %s/%s on node %s", event, obj.ObjectMeta.Namespace, obj.ObjectMeta.Name, obj.Spec.NodeName)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (npc *controller) AddPod(obj *coreapi.Pod) error {
|
||||
npc.Lock()
|
||||
defer npc.Unlock()
|
||||
|
||||
if !npc.checkLocalPod(obj, "AddPod") {
|
||||
return nil
|
||||
}
|
||||
common.Log.Debugf("EVENT AddPod %s", js(obj))
|
||||
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||
return errors.Wrap(ns.addPod(obj), "add pod")
|
||||
@@ -96,6 +110,10 @@ func (npc *controller) UpdatePod(oldObj, newObj *coreapi.Pod) error {
|
||||
npc.Lock()
|
||||
defer npc.Unlock()
|
||||
|
||||
// Pods don't move across nodes so we only check the new version
|
||||
if !npc.checkLocalPod(newObj, "UpdatePod") {
|
||||
return nil
|
||||
}
|
||||
common.Log.Debugf("EVENT UpdatePod %s %s", js(oldObj), js(newObj))
|
||||
return npc.withNS(oldObj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||
return errors.Wrap(ns.updatePod(oldObj, newObj), "update pod")
|
||||
@@ -106,6 +124,9 @@ func (npc *controller) DeletePod(obj *coreapi.Pod) error {
|
||||
npc.Lock()
|
||||
defer npc.Unlock()
|
||||
|
||||
if !npc.checkLocalPod(obj, "DeletePod") {
|
||||
return nil
|
||||
}
|
||||
common.Log.Debugf("EVENT DeletePod %s", js(obj))
|
||||
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||
return errors.Wrap(ns.deletePod(obj), "delete pod")
|
||||
|
||||
+6
-2
@@ -1,6 +1,7 @@
|
||||
package ipset
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
@@ -31,10 +32,11 @@ type Interface interface {
|
||||
|
||||
type ipset struct {
|
||||
refCount
|
||||
*log.Logger
|
||||
}
|
||||
|
||||
func New() Interface {
|
||||
return &ipset{refCount: newRefCount()}
|
||||
func New(logger *log.Logger) Interface {
|
||||
return &ipset{refCount: newRefCount(), Logger: logger}
|
||||
}
|
||||
|
||||
func (i *ipset) Create(ipsetName Name, ipsetType Type) error {
|
||||
@@ -42,6 +44,7 @@ func (i *ipset) Create(ipsetName Name, ipsetType Type) error {
|
||||
}
|
||||
|
||||
func (i *ipset) AddEntry(ipsetName Name, entry string) error {
|
||||
i.Logger.Printf("adding entry %s to %s", entry, ipsetName)
|
||||
if i.inc(ipsetName, entry) > 1 { // already in the set
|
||||
return nil
|
||||
}
|
||||
@@ -49,6 +52,7 @@ func (i *ipset) AddEntry(ipsetName Name, entry string) error {
|
||||
}
|
||||
|
||||
func (i *ipset) DelEntry(ipsetName Name, entry string) error {
|
||||
i.Logger.Printf("deleting entry %s from %s", entry, ipsetName)
|
||||
if i.dec(ipsetName, entry) > 0 { // still needed
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ func (ns *ns) addPod(obj *coreapi.Pod) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
ns.ips.AddEntry(LocalIpset, obj.Status.PodIP)
|
||||
return ns.podSelectors.addToMatching(obj.ObjectMeta.Labels, obj.Status.PodIP)
|
||||
}
|
||||
|
||||
@@ -100,10 +101,12 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
||||
}
|
||||
|
||||
if hasIP(oldObj) && !hasIP(newObj) {
|
||||
ns.ips.DelEntry(LocalIpset, oldObj.Status.PodIP)
|
||||
return ns.podSelectors.delFromMatching(oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
|
||||
}
|
||||
|
||||
if !hasIP(oldObj) && hasIP(newObj) {
|
||||
ns.ips.AddEntry(LocalIpset, newObj.Status.PodIP)
|
||||
return ns.podSelectors.addToMatching(newObj.ObjectMeta.Labels, newObj.Status.PodIP)
|
||||
}
|
||||
|
||||
@@ -139,6 +142,7 @@ func (ns *ns) deletePod(obj *coreapi.Pod) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
ns.ips.DelEntry(LocalIpset, obj.Status.PodIP)
|
||||
return ns.podSelectors.delFromMatching(obj.ObjectMeta.Labels, obj.Status.PodIP)
|
||||
}
|
||||
|
||||
|
||||
@@ -43,12 +43,10 @@ func (s *selector) matches(labelMap map[string]string) bool {
|
||||
}
|
||||
|
||||
func (s *selector) addEntry(entry string) error {
|
||||
common.Log.Infof("adding entry %s to %s", entry, s.spec.ipsetName)
|
||||
return s.ips.AddEntry(s.spec.ipsetName, entry)
|
||||
}
|
||||
|
||||
func (s *selector) delEntry(entry string) error {
|
||||
common.Log.Infof("deleting entry %s from %s", entry, s.spec.ipsetName)
|
||||
return s.ips.DelEntry(s.spec.ipsetName, entry)
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -7,12 +7,13 @@ import (
|
||||
|
||||
const (
|
||||
// This array:
|
||||
// * Must include only printable UTF8 characters that are represented with a single byte
|
||||
// * Must include only printable UTF8 characters that are represented with a single byte (http://www.utf8-chartable.de/)
|
||||
// * Must be at least of length 85 (`len("weave-") + l(2^160)/l(85)` equals 31, the maximum ipset name length)
|
||||
// * Must not include commas as those are treated specially by `ipset add` when adding a named set to a list:set
|
||||
// * Should not include space for readability
|
||||
// * Should not include invalid chars for XML `<>&"'`
|
||||
// * Should not include single quote or backslash to be nice to shell users
|
||||
ShortNameSymbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789(){}[]<>_$%^&*|/?.;:@#~"
|
||||
ShortNameSymbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789(){}[]+=_$%^!*|/?.;:@#~"
|
||||
)
|
||||
|
||||
// sha1 hash an arbitrary string and represent it using the full range of
|
||||
|
||||
+22
-16
@@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/ipam"
|
||||
@@ -35,7 +34,8 @@ func NewCNIPlugin(weave *weaveapi.Client) *CNIPlugin {
|
||||
|
||||
func loadNetConf(bytes []byte) (*NetConf, error) {
|
||||
n := &NetConf{
|
||||
BrName: weavenet.WeaveBridgeName,
|
||||
BrName: weavenet.WeaveBridgeName,
|
||||
HairpinMode: true,
|
||||
}
|
||||
if err := json.Unmarshal(bytes, n); err != nil {
|
||||
return nil, fmt.Errorf("failed to load netconf: %v", err)
|
||||
@@ -129,7 +129,7 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
|
||||
id = fmt.Sprintf("%x", data)
|
||||
}
|
||||
|
||||
if err := weavenet.AttachContainer(args.Netns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&ip.Address}, false); err != nil {
|
||||
if err := weavenet.AttachContainer(args.Netns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&ip.Address}, false, conf.HairpinMode); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := weavenet.WithNetNSLinkUnsafe(ns, args.IfName, func(link netlink.Link) error {
|
||||
@@ -183,16 +183,21 @@ func assignBridgeIP(bridgeName string, ipnet net.IPNet) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// As of CNI 0.5 spec:
|
||||
// "Plugins should generally complete a DEL action without error even if some resources are missing"
|
||||
// this method should therefore return nil in most, if not all, cases.
|
||||
func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
|
||||
conf, err := loadNetConf(args.StdinData)
|
||||
if err != nil {
|
||||
return err
|
||||
logOnStderr(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// As of CNI 0.3 spec, runtimes can send blank if they just want the address deallocated
|
||||
if args.Netns != "" {
|
||||
if _, err = weavenet.WithNetNS(args.Netns, "del-iface", args.IfName); err != nil {
|
||||
return fmt.Errorf("error removing interface %q: %s", args.IfName, err)
|
||||
// We log the error and carry on instead of returning nil, as there may still be resources to free in IPAM.
|
||||
logOnStderr(fmt.Errorf("error removing interface %q: %s", args.IfName, err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,20 +207,21 @@ func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
|
||||
} else {
|
||||
err = ipam.ExecDel(conf.IPAM.Type, args.StdinData)
|
||||
}
|
||||
// Hack - don't know how we should detect this situation properly
|
||||
if args.Netns == "" && strings.Contains(err.Error(), "no addresses") {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to release IP address: %s", err)
|
||||
}
|
||||
logOnStderr(fmt.Errorf("unable to release IP address: %s", err))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Standard error is inherited from the caller (e.g. Kubelet, when running Weave Net's CNI plugin
|
||||
// under Kubernetes) hence provided errors should eventually appear in the caller's log files.
|
||||
func logOnStderr(err error) {
|
||||
fmt.Fprintln(os.Stderr, "weave-cni:", err)
|
||||
}
|
||||
|
||||
type NetConf struct {
|
||||
types.NetConf
|
||||
BrName string `json:"bridge"`
|
||||
IsGW bool `json:"isGateway"`
|
||||
IPMasq bool `json:"ipMasq"`
|
||||
MTU int `json:"mtu"`
|
||||
BrName string `json:"bridge"`
|
||||
IsGW bool `json:"isGateway"`
|
||||
IPMasq bool `json:"ipMasq"`
|
||||
MTU int `json:"mtu"`
|
||||
HairpinMode bool `json:"hairpinMode"`
|
||||
}
|
||||
@@ -8,6 +8,11 @@ modprobe_safe() {
|
||||
|
||||
# Check whether xt_set actually exists
|
||||
xt_set_exists() {
|
||||
# Clean everything up in advance, in case there's leftovers
|
||||
iptables -F WEAVE-KUBE-TEST 2>/dev/null || true
|
||||
iptables -X WEAVE-KUBE-TEST 2>/dev/null || true
|
||||
ipset destroy weave-kube-test 2>/dev/null || true
|
||||
|
||||
ipset create weave-kube-test hash:ip
|
||||
iptables -t filter -N WEAVE-KUBE-TEST
|
||||
if ! iptables -A WEAVE-KUBE-TEST -m set --match-set weave-kube-test src -j DROP; then
|
||||
|
||||
@@ -92,6 +92,12 @@ spec:
|
||||
cpu: 10m
|
||||
securityContext:
|
||||
privileged: true
|
||||
env:
|
||||
- name: HOSTNAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: spec.nodeName
|
||||
restartPolicy: Always
|
||||
tolerations:
|
||||
- key: node-role.kubernetes.io/master
|
||||
|
||||
@@ -59,6 +59,12 @@ spec:
|
||||
cpu: 10m
|
||||
securityContext:
|
||||
privileged: true
|
||||
env:
|
||||
- name: HOSTNAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: spec.nodeName
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: weavedb
|
||||
|
||||
+54
-21
@@ -28,6 +28,7 @@ var (
|
||||
metricsAddr string
|
||||
logLevel string
|
||||
allowMcast bool
|
||||
nodeName string
|
||||
)
|
||||
|
||||
func handleError(err error) { common.CheckFatal(err) }
|
||||
@@ -53,6 +54,41 @@ func resetIPTables(ipt *iptables.IPTables) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resetIPSets(ips ipset.Interface) error {
|
||||
// Remove ipsets prefixed `weave-` only
|
||||
|
||||
sets, err := ips.List(npc.IpsetNamePrefix)
|
||||
if err != nil {
|
||||
common.Log.Errorf("Failed to retrieve list of ipsets")
|
||||
return err
|
||||
}
|
||||
|
||||
common.Log.Debugf("Got list of ipsets: %v", sets)
|
||||
|
||||
// Must remove references to ipsets by other ipsets before they're destroyed
|
||||
for _, s := range sets {
|
||||
common.Log.Debugf("Flushing ipset '%s'", string(s))
|
||||
if err := ips.Flush(s); err != nil {
|
||||
common.Log.Errorf("Failed to flush ipset '%s'", string(s))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range sets {
|
||||
common.Log.Debugf("Destroying ipset '%s'", string(s))
|
||||
if err := ips.Destroy(s); err != nil {
|
||||
common.Log.Errorf("Failed to destroy ipset '%s'", string(s))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
|
||||
// Configure main chain static rules
|
||||
if err := ipt.Append(npc.TableFilter, npc.MainChain,
|
||||
"-m", "state", "--state", "RELATED,ESTABLISHED", "-j", "ACCEPT"); err != nil {
|
||||
@@ -76,26 +112,14 @@ func resetIPTables(ipt *iptables.IPTables) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resetIPSets(ips ipset.Interface) error {
|
||||
// Remove ipsets prefixed `weave-` only
|
||||
|
||||
sets, err := ips.List(npc.IpsetNamePrefix)
|
||||
if err != nil {
|
||||
common.Log.Errorf("Failed to retrieve list of ipsets")
|
||||
// If the destination address is not any of the local pods, let it through
|
||||
if err := ips.Create(npc.LocalIpset, ipset.HashIP); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
common.Log.Debugf("Got list of ipsets: %v", sets)
|
||||
|
||||
for _, s := range sets {
|
||||
common.Log.Debugf("Destroying ipsets '%s'", string(s))
|
||||
if err := ips.Destroy(s); err != nil {
|
||||
common.Log.Errorf("Failed to destroy ipset '%s'", string(s))
|
||||
return err
|
||||
}
|
||||
if err := ipt.Append(npc.TableFilter, npc.MainChain,
|
||||
"-m", "set", "--match-set", npc.LocalIpset, "src",
|
||||
"-m", "set", "!", "--match-set", npc.LocalIpset, "dst", "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -103,7 +127,14 @@ func resetIPSets(ips ipset.Interface) error {
|
||||
|
||||
func root(cmd *cobra.Command, args []string) {
|
||||
common.SetLogLevel(logLevel)
|
||||
common.Log.Infof("Starting Weaveworks NPC %s", version)
|
||||
if nodeName == "" {
|
||||
// HOSTNAME is set by Kubernetes for pods in the host network namespace
|
||||
nodeName = os.Getenv("HOSTNAME")
|
||||
}
|
||||
if nodeName == "" {
|
||||
common.Log.Fatalf("Must set node name via --node-name or $HOSTNAME")
|
||||
}
|
||||
common.Log.Infof("Starting Weaveworks NPC %s; node name %q", version, nodeName)
|
||||
|
||||
if err := metrics.Start(metricsAddr); err != nil {
|
||||
common.Log.Fatalf("Failed to start metrics: %v", err)
|
||||
@@ -122,12 +153,13 @@ func root(cmd *cobra.Command, args []string) {
|
||||
ipt, err := iptables.New()
|
||||
handleError(err)
|
||||
|
||||
ips := ipset.New()
|
||||
ips := ipset.New(common.LogLogger())
|
||||
|
||||
handleError(resetIPTables(ipt))
|
||||
handleError(resetIPSets(ips))
|
||||
handleError(createBaseRules(ipt, ips))
|
||||
|
||||
npc := npc.New(ipt, ips)
|
||||
npc := npc.New(nodeName, ipt, ips)
|
||||
|
||||
nsController := makeController(client.Core().RESTClient(), "namespaces", &coreapi.Namespace{},
|
||||
cache.ResourceEventHandlerFuncs{
|
||||
@@ -207,6 +239,7 @@ func main() {
|
||||
rootCmd.PersistentFlags().StringVar(&metricsAddr, "metrics-addr", ":6781", "metrics server bind address")
|
||||
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "debug", "logging level (debug, info, warning, error)")
|
||||
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")
|
||||
|
||||
handleError(rootCmd.Execute())
|
||||
}
|
||||
@@ -14,11 +14,12 @@ import (
|
||||
|
||||
func attach(args []string) error {
|
||||
if len(args) < 4 {
|
||||
cmdUsage("attach-container", "[--no-multicast-route] [--keep-tx-on] <container-id> <bridge-name> <mtu> <cidr>...")
|
||||
cmdUsage("attach-container", "[--no-multicast-route] [--keep-tx-on] [--hairpin-mode=true|false] <container-id> <bridge-name> <mtu> <cidr>...")
|
||||
}
|
||||
|
||||
keepTXOn := false
|
||||
withMulticastRoute := true
|
||||
hairpinMode := true
|
||||
for i := 0; i < len(args); {
|
||||
switch args[i] {
|
||||
case "--no-multicast-route":
|
||||
@@ -27,6 +28,9 @@ func attach(args []string) error {
|
||||
case "--keep-tx-on":
|
||||
keepTXOn = true
|
||||
args = append(args[:i], args[i+1:]...)
|
||||
case "--hairpin-mode=false":
|
||||
hairpinMode = false
|
||||
args = append(args[:i], args[i+1:]...)
|
||||
default:
|
||||
i++
|
||||
}
|
||||
@@ -55,7 +59,7 @@ func attach(args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, args[1], mtu, withMulticastRoute, cidrs, keepTXOn)
|
||||
err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, args[1], mtu, withMulticastRoute, cidrs, keepTXOn, hairpinMode)
|
||||
// If we detected an error but the container has died, tell the user that instead.
|
||||
if err != nil && !processExists(pid) {
|
||||
err = fmt.Errorf("Container %s died", args[0])
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ search_type: Documentation
|
||||
CNI, the [_Container Network Interface_](https://github.com/containernetworking/cni),
|
||||
is a proposed standard for configuring network interfaces for Linux
|
||||
application containers. CNI is supported by
|
||||
[Kubernetes](http://kubernetes.io/), [Apache Mesos](mesos.apache.org)
|
||||
[Kubernetes](http://kubernetes.io/), [Apache Mesos](http://mesos.apache.org)
|
||||
and
|
||||
[others](https://github.com/containernetworking/cni#who-is-using-cni).
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ To disable this check, run the following before launching Weave Net:
|
||||
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](http://weave.works/guides/service-discovery-with-weave-aws-ecs.html) to get started with Weave Net on ECS.
|
||||
for the latest Weave AMIs and [here](https://www.weave.works/docs/tutorials/old-guides/ecs/) to get started with Weave Net on ECS.
|
||||
|
||||
If you're on Amazon EC2, the standard installation instructions at the
|
||||
top of this page, provide the simplest setup and the most flexibility.
|
||||
|
||||
+66
-1
@@ -9,6 +9,8 @@ The following topics are discussed:
|
||||
* [Installation](#install)
|
||||
* [Upgrading Kubernetes to version 1.6](#kube-1.6-upgrade)
|
||||
* [Upgrading the Daemon Sets](#daemon-sets)
|
||||
* [CPU and Memory Requirements](#resources)
|
||||
* [Pod Eviction](#eviction)
|
||||
* [Network Policy Controller](#npc)
|
||||
* [Troubleshooting Blocked Connections](#blocked-connections)
|
||||
* [Changing Configuration Options](#configuration-options)
|
||||
@@ -35,7 +37,8 @@ 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.
|
||||
|
||||
**Note:** This command requires Kubernetes 1.4 or later.
|
||||
**Note:** This command requires Kubernetes 1.4 or later, and we
|
||||
recommend your master node has at least two CPU cores.
|
||||
|
||||
> CNI, the [_Container Network Interface_](https://github.com/containernetworking/cni),
|
||||
> is a proposed standard for configuring network interfaces for Linux
|
||||
@@ -92,6 +95,64 @@ and so you will need to perform the procedure manually:
|
||||
lose 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
|
||||
[resources](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/)
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## <a name="eviction"></a>Pod Eviction
|
||||
|
||||
If a node runs out of CPU, memory or disk, Kubernetes may [decide to
|
||||
evict](https://kubernetes.io/docs/concepts/cluster-administration/out-of-resource/)
|
||||
one or more pods. It may choose to evict the Weave Net pod, which will
|
||||
disrupt pod network operations.
|
||||
|
||||
You can reduce the chance of eviction by changing the DaemonSet to
|
||||
have a much bigger request, and a limit of the same value.
|
||||
|
||||
This causes Kubernetes to apply a ["guaranteed" rather than a
|
||||
"burstable" policy](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/resource-qos.md).
|
||||
However a similar request for disk space can not
|
||||
be made, and so please be aware of this issue and monitor your
|
||||
resources to ensure that they stay below 100%.
|
||||
|
||||
You can see when pods have been evicted via the `kubectl get events` command
|
||||
|
||||
```
|
||||
LASTSEEN COUNT NAME KIND TYPE REASON SOURCE MESSAGE
|
||||
1m 1 mypod-09vkd Pod Warning Evicted kubelet, node-1 The node was low on resource: memory.
|
||||
```
|
||||
|
||||
or `kubectl get pods`
|
||||
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE IP NODE
|
||||
mypod-09vkd 0/1 Evicted 0 1h <none> node-1
|
||||
```
|
||||
|
||||
If you see this in your cluster, consider some of the above steps to
|
||||
reduce disruption.
|
||||
|
||||
## <a name="npc"></a>Network Policy Controller
|
||||
|
||||
The addon also supports the [Kubernetes policy
|
||||
@@ -180,3 +241,7 @@ The list of variables you can set is:
|
||||
a larger size for better performance if your network supports jumbo
|
||||
frames - see [here](/site/using-weave/fastdp.md#mtu) for more
|
||||
details.
|
||||
* `HAIRPIN_MODE` - Weave Net defaults to enabling hairpin on the bridge side of
|
||||
the `veth` pair for containers attached. If you need to disable hairpin, e.g. your
|
||||
kernel is one of those that can panic if hairpin is enabled, then you can disable it
|
||||
by setting `HAIRPIN_MODE=false`.
|
||||
@@ -44,7 +44,7 @@ or possible:
|
||||
In some cases you may already be aware of the problem, as you were
|
||||
unable to execute `weave reset` successfully or because you know
|
||||
through other channels that the host has died. In these cases you can
|
||||
proceed straight to [Manually Reclaiming Lost Address Space](#reclaim-address-space).
|
||||
proceed straight to [Manually Reclaiming Lost Address Space](#manually-reclaim-address-space).
|
||||
|
||||
However in some scenarios it may not be obvious that space has been
|
||||
lost, in which case you can check for it periodically with the
|
||||
|
||||
@@ -6,7 +6,6 @@ search_type: Documentation
|
||||
|
||||
* [Launching Weave Net and Running Containers Using the Plugin](#launching)
|
||||
* [Restarting the Plugin](#restarting)
|
||||
* [Configuring the Plugin](#configuring)
|
||||
|
||||
Docker versions 1.9 and later have a plugin mechanism for adding
|
||||
different network providers. Weave Net installs itself as a network
|
||||
|
||||
@@ -49,7 +49,7 @@ WeaveDNS removes the addresses of any container that dies. This offers
|
||||
a simple way to implement redundancy. E.g. if in our example we stop
|
||||
one of the `pingme` containers and re-run the ping tests, eventually
|
||||
(within ~30s at most, since that is the weaveDNS
|
||||
[cache expiry time](#ttl)) we will only be hitting the address of the
|
||||
[cache expiry time](/site/weavedns/managing-entries-weavedns.md#ttl)) we will only be hitting the address of the
|
||||
container that is still alive.
|
||||
|
||||
**See Also**
|
||||
|
||||
@@ -4,17 +4,13 @@ menu_order: 40
|
||||
search_type: Documentation
|
||||
---
|
||||
|
||||
|
||||
The following topics are discussed:
|
||||
|
||||
* [Adding and removing extra DNS entries](#add-remove)
|
||||
* [Resolving WeaveDNS entries from the Host](#resolve-weavedns-entries-from-host)
|
||||
* [Hot-swapping Service Containers](#hot-swapping)
|
||||
* [Retaining DNS Entries When Containers Stop](#retain-stopped)
|
||||
* [Configuring a Custom TTL](#ttl)
|
||||
|
||||
|
||||
|
||||
### <a name="add-remove"></a>Adding and Removing Extra DNS Entries
|
||||
|
||||
If you want to give the container a name in DNS *other* than its
|
||||
@@ -82,6 +78,6 @@ weaveDNS instance will receive.
|
||||
|
||||
**See Also**
|
||||
|
||||
* [How Weave Finds Containers](/site/how-works-weavedns.md)
|
||||
* [How Weave Finds Containers](/site/weavedns/how-works-weavedns.md)
|
||||
* [Load Balancing and Fault Resilience with WeaveDNS](/site/weavedns/load-balance-fault-weavedns.md)
|
||||
* [Managing Domains](/site/weavedns/managing-domains-weavedns.md)
|
||||
@@ -8,7 +8,7 @@ cni_connect() {
|
||||
pid=$(container_pid $1 $2)
|
||||
id=$(docker_on $1 inspect -f '{{.Id}}' $2)
|
||||
run_on $1 sudo CNI_COMMAND=ADD CNI_CONTAINERID=$id CNI_IFNAME=eth0 \
|
||||
CNI_NETNS=/proc/$pid/ns/net CNI_PATH=/opt/cni/bin /opt/cni/bin/weave-net
|
||||
CNI_NETNS=/proc/$pid/ns/net CNI_PATH=/opt/cni/bin /opt/cni/bin/weave-net
|
||||
}
|
||||
|
||||
run_on $HOST1 sudo mkdir -p /opt/cni/bin
|
||||
@@ -19,6 +19,11 @@ weave_on $HOST1 launch
|
||||
C0=$(docker_on $HOST1 run --net=none --name=c0 -dt $SMALL_IMAGE /bin/sh)
|
||||
C1=$(docker_on $HOST1 run --net=none --privileged --name=c1 -dt $SMALL_IMAGE /bin/sh)
|
||||
C2=$(docker_on $HOST1 run --net=none --name=c2 -dt $SMALL_IMAGE /bin/sh)
|
||||
CH0=$(docker_on $HOST1 run --net=none --name=ch0 -dt $SMALL_IMAGE /bin/sh)
|
||||
CH1=$(docker_on $HOST1 run --net=none --name=ch1 -dt $SMALL_IMAGE /bin/sh)
|
||||
CH2=$(docker_on $HOST1 run --net=none --name=ch2 -dt $SMALL_IMAGE /bin/sh)
|
||||
|
||||
|
||||
# Enable unsolicited ARPs so that ping after the address reuse does not time out
|
||||
exec_on $HOST1 c1 sysctl -w net.ipv4.conf.all.arp_accept=1
|
||||
|
||||
@@ -52,6 +57,29 @@ cni_connect $HOST1 c2 <<EOF
|
||||
}
|
||||
EOF
|
||||
|
||||
# examples to test hairpin
|
||||
cni_connect $HOST1 ch0 <<EOF
|
||||
{
|
||||
"name": "weave",
|
||||
"type": "weave-net",
|
||||
"hairpinMode": true
|
||||
}
|
||||
EOF
|
||||
cni_connect $HOST1 ch1 <<EOF
|
||||
{
|
||||
"name": "weave",
|
||||
"type": "weave-net",
|
||||
"hairpinMode": false
|
||||
}
|
||||
EOF
|
||||
cni_connect $HOST1 ch2 <<EOF
|
||||
{
|
||||
"name": "weave",
|
||||
"type": "weave-net"
|
||||
}
|
||||
EOF
|
||||
|
||||
|
||||
C0IP=$(container_ip $HOST1 c0)
|
||||
C1IP=$(container_ip $HOST1 c1)
|
||||
C2IP=$(container_ip $HOST1 c2)
|
||||
@@ -85,6 +113,29 @@ assert_raises "[ $C2IP != $C3IP ]"
|
||||
assert_raises "[ $BRIP != $C3IP ]"
|
||||
assert_raises "exec_on $HOST1 c1 $PING $C3IP"
|
||||
|
||||
#####
|
||||
#
|
||||
# Hairpin mode tests
|
||||
#
|
||||
# here we check that the bridge side of the veth is set to hairpin mode (true or false) correctly
|
||||
# check for each of
|
||||
# - ch0 explicitly true
|
||||
# - ch1 explicitly false
|
||||
# - ch2 unset, which should default to true
|
||||
#
|
||||
# we take advantage of the veth name being constructed from the container ID)
|
||||
#
|
||||
# should this reliance ever fail and we need to get it from the system, do the following for each:
|
||||
# CH0_PEER_ID=$(exec_on $HOST1 ch0 cat /sys/class/net/eth0/iflink)
|
||||
# CH0_PEER=$($SSH $HOST1 ip link show | awk "/^${CH0_PEER_ID}:/"' {print $2}' | sed 's/@.*$//g' )
|
||||
# CH0_HAIRPIN=$($SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/$CH0_PEER/hairpin_mode)
|
||||
# assert_raises "[ $CH0_HAIRPIN == 1 ]"
|
||||
#
|
||||
assert "$SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/vethwepl${CH0:0:7}/hairpin_mode" "1"
|
||||
assert "$SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/vethwepl${CH1:0:7}/hairpin_mode" "0"
|
||||
assert "$SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/vethwepl${CH2:0:7}/hairpin_mode" "1"
|
||||
|
||||
|
||||
|
||||
# Ensure existing containers can reclaim their IP addresses after CNI has been used -- see #2548
|
||||
stop_weave_on $HOST1
|
||||
|
||||
@@ -284,7 +284,7 @@ function configure() {
|
||||
local inventory_file=$(mktemp /tmp/ansible_inventory_XXXXX)
|
||||
echo "[all]" >"$inventory_file"
|
||||
# shellcheck disable=SC2001
|
||||
echo "$2" | sed "s/$/:$3/" >>"$inventory_file"
|
||||
echo "$2" | sed "s/\$/:$3/" >>"$inventory_file"
|
||||
|
||||
# Configure the provisioned machines using Ansible, allowing up to 3 retries upon failure (e.g. APT connectivity issues, etc.):
|
||||
for i in $(seq 3); do
|
||||
|
||||
@@ -1070,17 +1070,20 @@ create_cni_config() {
|
||||
cat >"$1" <<EOF
|
||||
{
|
||||
"name": "weave",
|
||||
"type": "weave-net"
|
||||
"type": "weave-net",
|
||||
"hairpinMode": $2
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
setup_cni() {
|
||||
# if env var HAIRPIN_MODE is not set, default it to true
|
||||
HAIRPIN_MODE=${HAIRPIN_MODE:-true}
|
||||
if install_cni_plugin $CNI_PLUGIN_DIR ; then
|
||||
upgrade_cni_plugin $CNI_PLUGIN_DIR
|
||||
fi
|
||||
if [ -d $HOST_ROOT/etc/cni/net.d -a ! -f $HOST_ROOT/etc/cni/net.d/10-weave.conf ] ; then
|
||||
create_cni_config $HOST_ROOT/etc/cni/net.d/10-weave.conf
|
||||
create_cni_config $HOST_ROOT/etc/cni/net.d/10-weave.conf $HAIRPIN_MODE
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user