github.com/jfrazelle/docker@v1.1.2-0.20210712172922-bf78e25fe508/libnetwork/drivers/overlay/overlay.go (about)

     1  // +build linux
     2  
     3  package overlay
     4  
     5  //go:generate protoc -I.:../../Godeps/_workspace/src/github.com/gogo/protobuf  --gogo_out=import_path=github.com/docker/docker/libnetwork/drivers/overlay,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto:. overlay.proto
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  	"net"
    11  	"sync"
    12  
    13  	"github.com/docker/docker/libnetwork/datastore"
    14  	"github.com/docker/docker/libnetwork/discoverapi"
    15  	"github.com/docker/docker/libnetwork/driverapi"
    16  	"github.com/docker/docker/libnetwork/idm"
    17  	"github.com/docker/docker/libnetwork/netlabel"
    18  	"github.com/docker/docker/libnetwork/osl"
    19  	"github.com/docker/docker/libnetwork/types"
    20  	"github.com/hashicorp/serf/serf"
    21  	"github.com/sirupsen/logrus"
    22  )
    23  
    24  const (
    25  	networkType  = "overlay"
    26  	vethPrefix   = "veth"
    27  	vethLen      = 7
    28  	vxlanIDStart = 256
    29  	vxlanIDEnd   = (1 << 24) - 1
    30  	vxlanEncap   = 50
    31  	secureOption = "encrypted"
    32  )
    33  
    34  var initVxlanIdm = make(chan (bool), 1)
    35  
    36  type driver struct {
    37  	eventCh          chan serf.Event
    38  	notifyCh         chan ovNotify
    39  	exitCh           chan chan struct{}
    40  	bindAddress      string
    41  	advertiseAddress string
    42  	neighIP          string
    43  	config           map[string]interface{}
    44  	peerDb           peerNetworkMap
    45  	secMap           *encrMap
    46  	serfInstance     *serf.Serf
    47  	networks         networkTable
    48  	store            datastore.DataStore
    49  	localStore       datastore.DataStore
    50  	vxlanIdm         *idm.Idm
    51  	initOS           sync.Once
    52  	joinOnce         sync.Once
    53  	localJoinOnce    sync.Once
    54  	keys             []*key
    55  	peerOpCh         chan *peerOperation
    56  	peerOpCancel     context.CancelFunc
    57  	sync.Mutex
    58  }
    59  
    60  // Init registers a new instance of overlay driver
    61  func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
    62  	c := driverapi.Capability{
    63  		DataScope:         datastore.GlobalScope,
    64  		ConnectivityScope: datastore.GlobalScope,
    65  	}
    66  	d := &driver{
    67  		networks: networkTable{},
    68  		peerDb: peerNetworkMap{
    69  			mp: map[string]*peerMap{},
    70  		},
    71  		secMap:   &encrMap{nodes: map[string][]*spi{}},
    72  		config:   config,
    73  		peerOpCh: make(chan *peerOperation),
    74  	}
    75  
    76  	// Launch the go routine for processing peer operations
    77  	ctx, cancel := context.WithCancel(context.Background())
    78  	d.peerOpCancel = cancel
    79  	go d.peerOpRoutine(ctx, d.peerOpCh)
    80  
    81  	if data, ok := config[netlabel.GlobalKVClient]; ok {
    82  		var err error
    83  		dsc, ok := data.(discoverapi.DatastoreConfigData)
    84  		if !ok {
    85  			return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
    86  		}
    87  		d.store, err = datastore.NewDataStoreFromConfig(dsc)
    88  		if err != nil {
    89  			return types.InternalErrorf("failed to initialize data store: %v", err)
    90  		}
    91  	}
    92  
    93  	if data, ok := config[netlabel.LocalKVClient]; ok {
    94  		var err error
    95  		dsc, ok := data.(discoverapi.DatastoreConfigData)
    96  		if !ok {
    97  			return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
    98  		}
    99  		d.localStore, err = datastore.NewDataStoreFromConfig(dsc)
   100  		if err != nil {
   101  			return types.InternalErrorf("failed to initialize local data store: %v", err)
   102  		}
   103  	}
   104  
   105  	if err := d.restoreEndpoints(); err != nil {
   106  		logrus.Warnf("Failure during overlay endpoints restore: %v", err)
   107  	}
   108  
   109  	return dc.RegisterDriver(networkType, d, c)
   110  }
   111  
   112  // Endpoints are stored in the local store. Restore them and reconstruct the overlay sandbox
   113  func (d *driver) restoreEndpoints() error {
   114  	if d.localStore == nil {
   115  		logrus.Warn("Cannot restore overlay endpoints because local datastore is missing")
   116  		return nil
   117  	}
   118  	kvol, err := d.localStore.List(datastore.Key(overlayEndpointPrefix), &endpoint{})
   119  	if err != nil && err != datastore.ErrKeyNotFound {
   120  		return fmt.Errorf("failed to read overlay endpoint from store: %v", err)
   121  	}
   122  
   123  	if err == datastore.ErrKeyNotFound {
   124  		return nil
   125  	}
   126  	for _, kvo := range kvol {
   127  		ep := kvo.(*endpoint)
   128  		n := d.network(ep.nid)
   129  		if n == nil {
   130  			logrus.Debugf("Network (%.7s) not found for restored endpoint (%.7s)", ep.nid, ep.id)
   131  			logrus.Debugf("Deleting stale overlay endpoint (%.7s) from store", ep.id)
   132  			if err := d.deleteEndpointFromStore(ep); err != nil {
   133  				logrus.Debugf("Failed to delete stale overlay endpoint (%.7s) from store", ep.id)
   134  			}
   135  			continue
   136  		}
   137  		n.addEndpoint(ep)
   138  
   139  		s := n.getSubnetforIP(ep.addr)
   140  		if s == nil {
   141  			return fmt.Errorf("could not find subnet for endpoint %s", ep.id)
   142  		}
   143  
   144  		if err := n.joinSandbox(s, true, true); err != nil {
   145  			return fmt.Errorf("restore network sandbox failed: %v", err)
   146  		}
   147  
   148  		Ifaces := make(map[string][]osl.IfaceOption)
   149  		vethIfaceOption := make([]osl.IfaceOption, 1)
   150  		vethIfaceOption = append(vethIfaceOption, n.sbox.InterfaceOptions().Master(s.brName))
   151  		Ifaces["veth+veth"] = vethIfaceOption
   152  
   153  		err := n.sbox.Restore(Ifaces, nil, nil, nil)
   154  		if err != nil {
   155  			n.leaveSandbox()
   156  			return fmt.Errorf("failed to restore overlay sandbox: %v", err)
   157  		}
   158  
   159  		d.peerAdd(ep.nid, ep.id, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), false, false, true)
   160  	}
   161  	return nil
   162  }
   163  
   164  // Fini cleans up the driver resources
   165  func Fini(drv driverapi.Driver) {
   166  	d := drv.(*driver)
   167  
   168  	// Notify the peer go routine to return
   169  	if d.peerOpCancel != nil {
   170  		d.peerOpCancel()
   171  	}
   172  
   173  	if d.exitCh != nil {
   174  		waitCh := make(chan struct{})
   175  
   176  		d.exitCh <- waitCh
   177  
   178  		<-waitCh
   179  	}
   180  }
   181  
   182  func (d *driver) configure() error {
   183  
   184  	// Apply OS specific kernel configs if needed
   185  	d.initOS.Do(applyOStweaks)
   186  
   187  	if d.store == nil {
   188  		return nil
   189  	}
   190  
   191  	if d.vxlanIdm == nil {
   192  		return d.initializeVxlanIdm()
   193  	}
   194  
   195  	return nil
   196  }
   197  
   198  func (d *driver) initializeVxlanIdm() error {
   199  	var err error
   200  
   201  	initVxlanIdm <- true
   202  	defer func() { <-initVxlanIdm }()
   203  
   204  	if d.vxlanIdm != nil {
   205  		return nil
   206  	}
   207  
   208  	d.vxlanIdm, err = idm.New(d.store, "vxlan-id", vxlanIDStart, vxlanIDEnd)
   209  	if err != nil {
   210  		return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
   211  	}
   212  
   213  	return nil
   214  }
   215  
   216  func (d *driver) Type() string {
   217  	return networkType
   218  }
   219  
   220  func (d *driver) IsBuiltIn() bool {
   221  	return true
   222  }
   223  
   224  func validateSelf(node string) error {
   225  	advIP := net.ParseIP(node)
   226  	if advIP == nil {
   227  		return fmt.Errorf("invalid self address (%s)", node)
   228  	}
   229  
   230  	addrs, err := net.InterfaceAddrs()
   231  	if err != nil {
   232  		return fmt.Errorf("Unable to get interface addresses %v", err)
   233  	}
   234  	for _, addr := range addrs {
   235  		ip, _, err := net.ParseCIDR(addr.String())
   236  		if err == nil && ip.Equal(advIP) {
   237  			return nil
   238  		}
   239  	}
   240  	return fmt.Errorf("Multi-Host overlay networking requires cluster-advertise(%s) to be configured with a local ip-address that is reachable within the cluster", advIP.String())
   241  }
   242  
   243  func (d *driver) nodeJoin(advertiseAddress, bindAddress string, self bool) {
   244  	if self && !d.isSerfAlive() {
   245  		d.Lock()
   246  		d.advertiseAddress = advertiseAddress
   247  		d.bindAddress = bindAddress
   248  		d.Unlock()
   249  
   250  		// If containers are already running on this network update the
   251  		// advertise address in the peerDB
   252  		d.localJoinOnce.Do(func() {
   253  			d.peerDBUpdateSelf()
   254  		})
   255  
   256  		// If there is no cluster store there is no need to start serf.
   257  		if d.store != nil {
   258  			if err := validateSelf(advertiseAddress); err != nil {
   259  				logrus.Warn(err.Error())
   260  			}
   261  			err := d.serfInit()
   262  			if err != nil {
   263  				logrus.Errorf("initializing serf instance failed: %v", err)
   264  				d.Lock()
   265  				d.advertiseAddress = ""
   266  				d.bindAddress = ""
   267  				d.Unlock()
   268  				return
   269  			}
   270  		}
   271  	}
   272  
   273  	d.Lock()
   274  	if !self {
   275  		d.neighIP = advertiseAddress
   276  	}
   277  	neighIP := d.neighIP
   278  	d.Unlock()
   279  
   280  	if d.serfInstance != nil && neighIP != "" {
   281  		var err error
   282  		d.joinOnce.Do(func() {
   283  			err = d.serfJoin(neighIP)
   284  			if err == nil {
   285  				d.pushLocalDb()
   286  			}
   287  		})
   288  		if err != nil {
   289  			logrus.Errorf("joining serf neighbor %s failed: %v", advertiseAddress, err)
   290  			d.Lock()
   291  			d.joinOnce = sync.Once{}
   292  			d.Unlock()
   293  			return
   294  		}
   295  	}
   296  }
   297  
   298  func (d *driver) pushLocalEndpointEvent(action, nid, eid string) {
   299  	n := d.network(nid)
   300  	if n == nil {
   301  		logrus.Debugf("Error pushing local endpoint event for network %s", nid)
   302  		return
   303  	}
   304  	ep := n.endpoint(eid)
   305  	if ep == nil {
   306  		logrus.Debugf("Error pushing local endpoint event for ep %s / %s", nid, eid)
   307  		return
   308  	}
   309  
   310  	if !d.isSerfAlive() {
   311  		return
   312  	}
   313  	d.notifyCh <- ovNotify{
   314  		action: "join",
   315  		nw:     n,
   316  		ep:     ep,
   317  	}
   318  }
   319  
   320  // DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
   321  func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
   322  	var err error
   323  	switch dType {
   324  	case discoverapi.NodeDiscovery:
   325  		nodeData, ok := data.(discoverapi.NodeDiscoveryData)
   326  		if !ok || nodeData.Address == "" {
   327  			return fmt.Errorf("invalid discovery data")
   328  		}
   329  		d.nodeJoin(nodeData.Address, nodeData.BindAddress, nodeData.Self)
   330  	case discoverapi.DatastoreConfig:
   331  		if d.store != nil {
   332  			return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")
   333  		}
   334  		dsc, ok := data.(discoverapi.DatastoreConfigData)
   335  		if !ok {
   336  			return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
   337  		}
   338  		d.store, err = datastore.NewDataStoreFromConfig(dsc)
   339  		if err != nil {
   340  			return types.InternalErrorf("failed to initialize data store: %v", err)
   341  		}
   342  	case discoverapi.EncryptionKeysConfig:
   343  		encrData, ok := data.(discoverapi.DriverEncryptionConfig)
   344  		if !ok {
   345  			return fmt.Errorf("invalid encryption key notification data")
   346  		}
   347  		keys := make([]*key, 0, len(encrData.Keys))
   348  		for i := 0; i < len(encrData.Keys); i++ {
   349  			k := &key{
   350  				value: encrData.Keys[i],
   351  				tag:   uint32(encrData.Tags[i]),
   352  			}
   353  			keys = append(keys, k)
   354  		}
   355  		if err := d.setKeys(keys); err != nil {
   356  			logrus.Warn(err)
   357  		}
   358  	case discoverapi.EncryptionKeysUpdate:
   359  		var newKey, delKey, priKey *key
   360  		encrData, ok := data.(discoverapi.DriverEncryptionUpdate)
   361  		if !ok {
   362  			return fmt.Errorf("invalid encryption key notification data")
   363  		}
   364  		if encrData.Key != nil {
   365  			newKey = &key{
   366  				value: encrData.Key,
   367  				tag:   uint32(encrData.Tag),
   368  			}
   369  		}
   370  		if encrData.Primary != nil {
   371  			priKey = &key{
   372  				value: encrData.Primary,
   373  				tag:   uint32(encrData.PrimaryTag),
   374  			}
   375  		}
   376  		if encrData.Prune != nil {
   377  			delKey = &key{
   378  				value: encrData.Prune,
   379  				tag:   uint32(encrData.PruneTag),
   380  			}
   381  		}
   382  		if err := d.updateKeys(newKey, priKey, delKey); err != nil {
   383  			return err
   384  		}
   385  	default:
   386  	}
   387  	return nil
   388  }
   389  
   390  // DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
   391  func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
   392  	return nil
   393  }