List from cloud and resync InMemoryPool.
This commit is contained in:
parent
ba26bcabf5
commit
8d59739bb1
9 changed files with 229 additions and 18 deletions
|
|
@ -20,6 +20,7 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
|
||||
|
|
@ -38,6 +39,10 @@ type Backends struct {
|
|||
healthChecker healthchecks.HealthChecker
|
||||
snapshotter storage.Snapshotter
|
||||
namer utils.Namer
|
||||
// ignoredPorts are a set of ports excluded from GC, even
|
||||
// after the Ingress has been deleted. Note that invoking
|
||||
// a Delete() on these ports will still delete the backend.
|
||||
ignoredPorts sets.String
|
||||
}
|
||||
|
||||
func portKey(port int64) string {
|
||||
|
|
@ -46,18 +51,46 @@ func portKey(port int64) string {
|
|||
|
||||
// NewBackendPool returns a new backend pool.
|
||||
// - cloud: implements BackendServices and syncs backends with a cloud provider
|
||||
// - healthChecker: is capable of producing health checks for backends.
|
||||
// - nodePool: implements NodePool, used to create/delete new instance groups.
|
||||
// - namer: procudes names for backends.
|
||||
// - ignorePorts: is a set of ports to avoid syncing/GCing.
|
||||
// - resyncWithCloud: if true, periodically syncs with cloud resources.
|
||||
func NewBackendPool(
|
||||
cloud BackendServices,
|
||||
healthChecker healthchecks.HealthChecker,
|
||||
nodePool instances.NodePool, namer utils.Namer) *Backends {
|
||||
return &Backends{
|
||||
nodePool instances.NodePool, namer utils.Namer, ignorePorts []int64, resyncWithCloud bool) *Backends {
|
||||
ignored := []string{}
|
||||
for _, p := range ignorePorts {
|
||||
ignored = append(ignored, portKey(p))
|
||||
}
|
||||
backendPool := &Backends{
|
||||
cloud: cloud,
|
||||
nodePool: nodePool,
|
||||
snapshotter: storage.NewInMemoryPool(),
|
||||
healthChecker: healthChecker,
|
||||
namer: namer,
|
||||
ignoredPorts: sets.NewString(ignored...),
|
||||
}
|
||||
if !resyncWithCloud {
|
||||
backendPool.snapshotter = storage.NewInMemoryPool()
|
||||
return backendPool
|
||||
}
|
||||
backendPool.snapshotter = storage.NewCloudListingPool(
|
||||
func(i interface{}) (string, error) {
|
||||
bs := i.(*compute.BackendService)
|
||||
if !namer.NameBelongsToCluster(bs.Name) {
|
||||
return "", fmt.Errorf("Unrecognized name %v", bs.Name)
|
||||
}
|
||||
port, err := namer.BePort(bs.Name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return port, nil
|
||||
},
|
||||
backendPool,
|
||||
30*time.Second,
|
||||
)
|
||||
return backendPool
|
||||
}
|
||||
|
||||
// Get returns a single backend.
|
||||
|
|
@ -150,10 +183,18 @@ func (b *Backends) Delete(port int64) (err error) {
|
|||
}
|
||||
|
||||
// List lists all backends.
|
||||
func (b *Backends) List() (*compute.BackendServiceList, error) {
|
||||
func (b *Backends) List() ([]interface{}, error) {
|
||||
// TODO: for consistency with the rest of this sub-package this method
|
||||
// should return a list of backend ports.
|
||||
return b.cloud.ListBackendServices()
|
||||
interList := []interface{}{}
|
||||
be, err := b.cloud.ListBackendServices()
|
||||
if err != nil {
|
||||
return interList, err
|
||||
}
|
||||
for i := range be.Items {
|
||||
interList = append(interList, be.Items[i])
|
||||
}
|
||||
return interList, nil
|
||||
}
|
||||
|
||||
// edgeHop checks the links of the given backend by executing an edge hop.
|
||||
|
|
@ -200,7 +241,7 @@ func (b *Backends) GC(svcNodePorts []int64) error {
|
|||
return err
|
||||
}
|
||||
nodePort := int64(p)
|
||||
if knownPorts.Has(portKey(nodePort)) {
|
||||
if knownPorts.Has(portKey(nodePort)) || b.ignoredPorts.Has(portKey(nodePort)) {
|
||||
continue
|
||||
}
|
||||
glog.V(3).Infof("GCing backend for port %v", p)
|
||||
|
|
|
|||
|
|
@ -19,24 +19,26 @@ package backends
|
|||
import (
|
||||
"testing"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
"k8s.io/contrib/ingress/controllers/gce/healthchecks"
|
||||
"k8s.io/contrib/ingress/controllers/gce/instances"
|
||||
"k8s.io/contrib/ingress/controllers/gce/storage"
|
||||
"k8s.io/contrib/ingress/controllers/gce/utils"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
|
||||
func newBackendPool(f BackendServices, fakeIGs instances.InstanceGroups) BackendPool {
|
||||
func newBackendPool(f BackendServices, fakeIGs instances.InstanceGroups, syncWithCloud bool) BackendPool {
|
||||
namer := utils.Namer{}
|
||||
return NewBackendPool(
|
||||
f,
|
||||
healthchecks.NewHealthChecker(healthchecks.NewFakeHealthChecks(), "/", namer),
|
||||
instances.NewNodePool(fakeIGs, "default-zone"), namer)
|
||||
instances.NewNodePool(fakeIGs, "default-zone"), namer, []int64{}, syncWithCloud)
|
||||
}
|
||||
|
||||
func TestBackendPoolAdd(t *testing.T) {
|
||||
f := NewFakeBackendServices()
|
||||
fakeIGs := instances.NewFakeInstanceGroups(sets.NewString())
|
||||
pool := newBackendPool(f, fakeIGs)
|
||||
pool := newBackendPool(f, fakeIGs, false)
|
||||
namer := utils.Namer{}
|
||||
|
||||
// Add a backend for a port, then re-add the same port and
|
||||
|
|
@ -89,13 +91,12 @@ func TestBackendPoolAdd(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBackendPoolSync(t *testing.T) {
|
||||
|
||||
// Call sync on a backend pool with a list of ports, make sure the pool
|
||||
// creates/deletes required ports.
|
||||
svcNodePorts := []int64{81, 82, 83}
|
||||
f := NewFakeBackendServices()
|
||||
fakeIGs := instances.NewFakeInstanceGroups(sets.NewString())
|
||||
pool := newBackendPool(f, fakeIGs)
|
||||
pool := newBackendPool(f, fakeIGs, true)
|
||||
pool.Add(81)
|
||||
pool.Add(90)
|
||||
pool.Sync(svcNodePorts)
|
||||
|
|
@ -109,12 +110,57 @@ func TestBackendPoolSync(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
svcNodePorts = []int64{81}
|
||||
deletedPorts := []int64{82, 83}
|
||||
pool.GC(svcNodePorts)
|
||||
for _, port := range deletedPorts {
|
||||
if _, err := pool.Get(port); err == nil {
|
||||
t.Fatalf("Pool contains %v after deletion", port)
|
||||
}
|
||||
}
|
||||
|
||||
// All these backends should be ignored because they don't belong to the cluster.
|
||||
// foo - non k8s managed backend
|
||||
// k8s-be-foo - foo is not a nodeport
|
||||
// k8s--bar--foo - too many cluster delimiters
|
||||
// k8s-be-3001--uid - another cluster tagged with uid
|
||||
unrelatedBackends := sets.NewString([]string{"foo", "k8s-be-foo", "k8s--bar--foo", "k8s-be-30001--uid"}...)
|
||||
for _, name := range unrelatedBackends.List() {
|
||||
f.CreateBackendService(&compute.BackendService{Name: name})
|
||||
}
|
||||
|
||||
namer := &utils.Namer{}
|
||||
// This backend should get deleted again since it is managed by this cluster.
|
||||
f.CreateBackendService(&compute.BackendService{Name: namer.BeName(deletedPorts[0])})
|
||||
|
||||
// TODO: Avoid casting.
|
||||
// Repopulate the pool with a cloud list, which now includes the 82 port
|
||||
// backend. This would happen if, say, an ingress backend is removed
|
||||
// while the controller is restarting.
|
||||
pool.(*Backends).snapshotter.(*storage.CloudListingPool).ReplinishPool()
|
||||
|
||||
pool.GC(svcNodePorts)
|
||||
|
||||
currBackends, _ := f.ListBackendServices()
|
||||
currSet := sets.NewString()
|
||||
for _, b := range currBackends.Items {
|
||||
currSet.Insert(b.Name)
|
||||
}
|
||||
// Port 81 still exists because it's an in-use service NodePort.
|
||||
knownBe := namer.BeName(81)
|
||||
if !currSet.Has(knownBe) {
|
||||
t.Fatalf("Expected %v to exist in backend pool", knownBe)
|
||||
}
|
||||
currSet.Delete(knownBe)
|
||||
if !currSet.Equal(unrelatedBackends) {
|
||||
t.Fatalf("Some unrelated backends were deleted. Expected %+v, got %+v", unrelatedBackends, currSet)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendPoolShutdown(t *testing.T) {
|
||||
f := NewFakeBackendServices()
|
||||
fakeIGs := instances.NewFakeInstanceGroups(sets.NewString())
|
||||
pool := newBackendPool(f, fakeIGs)
|
||||
pool := newBackendPool(f, fakeIGs, false)
|
||||
namer := utils.Namer{}
|
||||
|
||||
pool.Add(80)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ type BackendPool interface {
|
|||
GC(ports []int64) error
|
||||
Shutdown() error
|
||||
Status(name string) string
|
||||
List() (*compute.BackendServiceList, error)
|
||||
List() ([]interface{}, error)
|
||||
}
|
||||
|
||||
// BackendServices is an interface for managing gce backend services.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue