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 }