Merge pull request #2827 from weaveworks/issues/2799-peer-disco

Peer Discovery via cloud service
This commit is contained in:
Marc Carré authored and GitHub committed 2017-04-11 14:59:28 +01:00
commit bc47866880
11 files changed
+293 -15

No files matched your search

+6
View File
@@ -124,3 +124,9 @@
[submodule "vendor/github.com/containernetworking/cni"]
path = vendor/github.com/containernetworking/cni
url = https://github.com/containernetworking/cni
[submodule "vendor/golang.org/x/net"]
path = vendor/golang.org/x/net
url = https://go.googlesource.com/net
[submodule "vendor/google.golang.org/grpc"]
path = vendor/google.golang.org/grpc
url = https://github.com/grpc/grpc-go
-11
View File
@@ -198,17 +198,6 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
w.WriteHeader(204)
})
router.Methods("DELETE").Path("/peer").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
alloc.Shutdown()
w.WriteHeader(204)
})
router.Methods("DELETE").Path("/peer/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ident := mux.Vars(r)["id"]
transferred := alloc.AdminTakeoverRanges(ident)
fmt.Fprintf(w, "%d IPs taken over from %s\n", transferred, ident)
})
router.Methods("GET").Path("/ipinfo/tracker").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, tracker)
})
+22
View File
@@ -82,3 +82,25 @@ func findInterface(ifaceName string) (iface *net.Interface, err error) {
}
return
}
func LocalAddresses() ([]*net.IPNet, error) {
links, err := netlink.LinkList()
if err != nil {
return nil, err
}
retval := []*net.IPNet{}
for _, link := range links {
if _, isBridge := link.(*netlink.Bridge); isBridge || (link.Attrs().Flags&net.FlagLoopback) != 0 {
continue
}
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
if err != nil {
return nil, err
}
for _, addr := range addrs {
retval = append(retval, addr.IPNet)
}
}
return retval, nil
}
+104
View File
@@ -0,0 +1,104 @@
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/weaveworks/weave/ipam"
)
// TODO: move these definitions somewhere more shareable
type PeerUpdateRequest struct {
Name string `json:"peername"`
Nickname string `json:"nickname"` // optional
Addresses []string `json:"addresses"` // can be empty
}
type PeerUpdateResponse struct {
Addresses []string `json:"addresses"`
PeerCount int `json:"peercount"`
}
var httpClient = &http.Client{Timeout: 30 * time.Second}
func do(verb string, discoveryEndpoint, token string, request interface{}, response interface{}) error {
body := new(bytes.Buffer)
err := json.NewEncoder(body).Encode(request)
if err != nil {
return err
}
req, err := http.NewRequest(verb, discoveryEndpoint+"/peer", body)
if err != nil {
return err
}
req.Header.Set("Authorization", fmt.Sprintf("Scope-Probe token=%s", token))
req.Header.Set("X-Weave-Net-Version", version)
req.Header.Set("Content-Type", "application/json")
Log.Printf("Calling peer discovery %s with %s", req.URL, request)
resp, err := httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
rbody, _ := ioutil.ReadAll(resp.Body)
return errors.New(resp.Status + ": " + string(rbody))
}
if response == nil {
return nil
}
err = json.NewDecoder(resp.Body).Decode(response)
Log.Printf("peer discovery result: (%v) %v", err, response)
return err
}
func peerDiscoveryUpdate(discoveryEndpoint, token, peername, nickname string, addresses []string) ([]string, int, error) {
request := PeerUpdateRequest{
Name: peername,
Nickname: nickname,
Addresses: addresses,
}
var updateResponse PeerUpdateResponse
err := do("POST", discoveryEndpoint, token, request, &updateResponse)
return updateResponse.Addresses, updateResponse.PeerCount, err
}
func peerDiscoveryDelete(discoveryEndpoint, token, peername string) error {
request := PeerUpdateRequest{Name: peername}
return do("DELETE", discoveryEndpoint, token, request, nil)
}
func HandleHTTPPeer(router *mux.Router, alloc *ipam.Allocator, discoveryEndpoint, token, peername string) {
router.Methods("DELETE").Path("/peer").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if discoveryEndpoint != "" {
if err := peerDiscoveryDelete(discoveryEndpoint, token, peername); err != nil {
Log.Errorf("Error while deleting self from peer discovery: %s", err)
}
}
if alloc != nil {
alloc.Shutdown()
}
w.WriteHeader(204)
})
router.Methods("DELETE").Path("/peer/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ident := mux.Vars(r)["id"]
if discoveryEndpoint != "" {
// TODO: deal with this being either a peername or a nickname
if err := peerDiscoveryDelete(discoveryEndpoint, token, ident); err != nil {
Log.Errorf("Error while deleting self from peer discovery: %s", err)
}
}
if alloc != nil {
transferred := alloc.AdminTakeoverRanges(ident)
fmt.Fprintf(w, "%d IPs taken over from %s\n", transferred, ident)
}
})
}
+31 -3
View File
@@ -53,7 +53,7 @@ type dnsConfig struct {
func (c *ipamConfig) Enabled() bool {
var (
hasPeerCount = c.PeerCount > 0
hasMode = len(c.Mode) > 0
hasMode = c.HasMode()
hasRange = c.IPRangeCIDR != ""
hasSubnet = c.IPSubnetCIDR != ""
)
@@ -75,6 +75,10 @@ func (c *ipamConfig) Enabled() bool {
return true
}
func (c ipamConfig) HasMode() bool {
return len(c.Mode) > 0
}
func (c *ipamConfig) parseMode() error {
modeAndParam := strings.SplitN(c.Mode, "=", 2)
@@ -143,6 +147,9 @@ func main() {
trustedSubnetStr string
dbPrefix string
isAWSVPC bool
discoveryEndpoint string
token string
advertiseAddress string
defaultDockerHost = "unix:///var/run/docker.sock"
)
@@ -184,6 +191,9 @@ func main() {
mflag.StringVar(&trustedSubnetStr, []string{"-trusted-subnets"}, "", "comma-separated list of trusted subnets in CIDR notation")
mflag.StringVar(&dbPrefix, []string{"-db-prefix"}, "/weavedb/weave", "pathname/prefix of filename to store data")
mflag.BoolVar(&isAWSVPC, []string{"-awsvpc"}, false, "use AWS VPC for routing")
mflag.StringVar(&discoveryEndpoint, []string{"-peer-discovery-url"}, "https://cloud.weave.works/api/net", "url for peer discovery")
mflag.StringVar(&token, []string{"-token"}, "", "token for peer discovery")
mflag.StringVar(&advertiseAddress, []string{"-advertise-address"}, "", "address to advertise for peer discovery")
// crude way of detecting that we probably have been started in a
// container, with `weave launch` --> suppress misleading paths in
@@ -257,7 +267,24 @@ func main() {
router := weave.NewNetworkRouter(config, networkConfig, name, nickName, overlay, db)
Log.Println("Our name is", router.Ourself)
if peers, err = router.InitialPeers(resume, peers); err != nil {
if token != "" {
var addresses []string
if advertiseAddress == "" {
localAddrs, err := weavenet.LocalAddresses()
checkFatal(err)
for _, addr := range localAddrs {
addresses = append(addresses, addr.IP.String())
}
} else {
addresses = strings.Split(advertiseAddress, ",")
}
discoveredPeers, count, err := peerDiscoveryUpdate(discoveryEndpoint, token, name.String(), nickName, addresses)
checkFatal(err)
if !ipamConfig.HasMode() {
ipamConfig.PeerCount = len(peers) + count
}
peers = append(peers, discoveredPeers...)
} else if peers, err = router.InitialPeers(resume, peers); err != nil {
Log.Fatal("Unable to get initial peer set: ", err)
}
@@ -352,6 +379,7 @@ func main() {
}
router.HandleHTTP(muxRouter)
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver)
HandleHTTPPeer(muxRouter, allocator, discoveryEndpoint, token, name.String())
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver))
http.Handle("/", common.LoggingHTTPHandler(muxRouter))
Log.Println("Listening for HTTP control messages on", httpAddr)
@@ -376,7 +404,7 @@ func options() map[string]string {
mflag.Visit(func(f *mflag.Flag) {
value := f.Value.String()
name := canonicalName(f)
if name == "password" {
if name == "password" || name == "token" {
value = "<redacted>"
}
options[name] = value
+1
View File
@@ -135,5 +135,6 @@ Weave Net supports *any* protocol, and it doesn't have to be over TCP/IP. For ex
**See Also**
* [Installing Weave Net](/site/installing-weave.md)
* [Using Weave Cloud to get started with Weave Net](/site/using-weave/weave-cloud.md)
* [Using Fastdp With Weave Net](/site/using-weave/fastdp.md)
* [Using the Weave Net Docker Network Plugin](/site/plugin.md)
Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

+126
View File
@@ -0,0 +1,126 @@
---
title: Using Weave Cloud to get started with Weave Net
menu_order: 10
---
Weave Net provides a simple to deploy networking solution for containerized apps. Here, we describe how to manage a Weave container network using a sample application which consists of two simple `netcat` services deployed to containers on two separate hosts.
This section contains the following topics:
* [Signing in to Weave Cloud](#signing-in)
* [Launching Weave Net](#launching)
* [Launching on Additional Hosts](#peer-connections)
* [How Peer Discovery Works](#how-it-works)
### <a name="signing-in"></a>Signing in to Weave Cloud
Weave Cloud is a fast and simple way to visualize, manage and monitor
containers and microservices. In order to use Weave Cloud to set up
Weave Net, you must sign up to Weave Cloud and create an "Instance".
The instance will have a Service Token which is a 32-character string
used to uniquely identify it. Get hold of the Service Token for your
Instance, as shown below:
![UI to get a Service Token](weave-cloud-token.png)
For the purpose of these instructions we will use a dummy Service
Token `dk6hz1acdd58aea6b75migoy4axqasdf`.
### <a name="launching"></a>Launching Weave Net
Before launching Weave Net and deploying your apps, ensure that Docker
is [installed](https://docs.docker.com/engine/installation/) on both
hosts.
On `$HOST1` run:
host1$ weave launch --token=dk6hz1acdd58aea6b75migoy4axqasdf
host1$ eval $(weave env)
host1$ docker run --name a1 -ti weaveworks/ubuntu
Where,
* The first line runs Weave Net.
* The second line configures the Weave Net environment, so that containers launched via the Docker command line are automatically attached to the Weave network, and,
* The third line runs the [application container](/site/faq.md#own-image) using [a Docker command](https://docs.docker.com/engine/reference/run/).
> **Note** If the first command results in an error like
> ```
> Cannot connect to the Docker daemon. Is the docker daemon running on this host?
> ```
> then you likely need to be 'root' in order to connect to the Docker
> daemon. If so, run the above and all subsequent commands in a
> *single* root shell:
> ```
> host1$ sudo -s
> host1# weave launch --token=dk6hz1acdd58aea6b75migoy4axqasdf
> host1# eval $(weave env)
> host1# docker run --name a1 -ti weaveworks/ubuntu
> ```
> Do *not* prefix individual commands with `sudo`, since some commands
> modify environment entries and hence they all need to be executed from
> the same shell.
Weave Net must be launched once per host. The relevant container images will be pulled down from Docker Hub on demand during `weave launch`.
You can also preload the images by running `weave setup`. Preloaded images are useful for automated deployments, and ensure there are no delays during later operations.
If you are deploying an application that consists of more than one container to the same host, launch them one after another using `docker run`, as appropriate.
### <a name="peer-connections"></a>Launching on Additional Hosts
To launch Weave Net on an additional host and create a peer
connection, run exactly the same commands as on the first host:
host2$ weave launch --token=dk6hz1acdd58aea6b75migoy4axqasdf
host2$ eval $(weave env)
host2$ docker run --name a2 -ti weaveworks/ubuntu
Because you are using Weave Cloud, the second peer will discover the
first and automatically create a connection to it.
>**Note:** If there is a firewall between `$HOST1` and `$HOST2`, you must permit traffic to flow through TCP 6783 and UDP 6783/6784, which are Weave’s control and data ports.
Now you can proceed to [test container communications](site/using-weave#testing)
### <a name="how-it-works"></a>How Peer Discovery Works
The Weave Cloud back-end maintains a database of all the peers that
have registered in each instance. You can create as many instances as
you like in the Weave Cloud console: for different projects, or to
separate test and production.
As each peer starts up, it looks for all network instances that
another peer might be able to contact it on, and registers those with the back-end.
If you want to control which addresses are used, add the `--advertise-address` flag:
host1$ weave launch --token=dk6hz1acdd58aea6b75migoy4axqasdf --advertise-address=192.0.2.1,198.51.100.4
When the new peer registers itself, it also fetches a list of all
other peers in the instance, and begins to contact them.
If the peer cannot contact the Weave Cloud back-end it will print an
error message in its log and exit. To check the logs run:
host1$ docker logs weave
When a Weave Net instance is formed for the first time, the peers must
initialize the [IP Allocation Manager](site/ipam.md). This process,
and the configuration options available, are unchanged when using
Weave Cloud.
When you shut down a peer for good, use [the `weave reset`
command](site/ipam/stop-remove-peers-ipam.md) and it will be removed
from the Weave Cloud database so future peers will not attempt to
connect to it.
**See Also**
* [Installing Weave Net](/site/installing-weave.md)
* [Using Weave Net](/site/using-weave.md)
* [Using Fastdp With Weave Net](/site/using-weave/fastdp.md)
* [Using the Weave Net Docker Network Plugin](/site/plugin.md)
Generated Vendored Submodule
+1
Submodule vendor/golang.org/x/net added at d379faa25c.
Generated Vendored Submodule
+1