ingress: nginx controller watches referenced tls secrets
* reload certificates on change
This commit is contained in:
parent
74b66beda9
commit
00b2180a8f
2 changed files with 82 additions and 4 deletions
|
@ -90,10 +90,12 @@ type loadBalancerController struct {
|
||||||
ingController *framework.Controller
|
ingController *framework.Controller
|
||||||
endpController *framework.Controller
|
endpController *framework.Controller
|
||||||
svcController *framework.Controller
|
svcController *framework.Controller
|
||||||
|
secrController *framework.Controller
|
||||||
mapController *framework.Controller
|
mapController *framework.Controller
|
||||||
ingLister StoreToIngressLister
|
ingLister StoreToIngressLister
|
||||||
svcLister cache.StoreToServiceLister
|
svcLister cache.StoreToServiceLister
|
||||||
endpLister cache.StoreToEndpointsLister
|
endpLister cache.StoreToEndpointsLister
|
||||||
|
secrLister StoreToSecretsLister
|
||||||
mapLister StoreToConfigmapLister
|
mapLister StoreToConfigmapLister
|
||||||
nginx *nginx.Manager
|
nginx *nginx.Manager
|
||||||
podInfo *podInfo
|
podInfo *podInfo
|
||||||
|
@ -165,6 +167,32 @@ func newLoadBalancerController(kubeClient *client.Client, resyncPeriod time.Dura
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secrEventHandler := framework.ResourceEventHandlerFuncs{
|
||||||
|
AddFunc: func(obj interface{}) {
|
||||||
|
addSecr := obj.(*api.Secret)
|
||||||
|
if lbc.secrReferenced(addSecr.Namespace, addSecr.Name) {
|
||||||
|
lbc.recorder.Eventf(addSecr, api.EventTypeNormal, "CREATE", fmt.Sprintf("%s/%s", addSecr.Namespace, addSecr.Name))
|
||||||
|
lbc.syncQueue.enqueue(obj)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DeleteFunc: func(obj interface{}) {
|
||||||
|
delSecr := obj.(*api.Secret)
|
||||||
|
if lbc.secrReferenced(delSecr.Namespace, delSecr.Name) {
|
||||||
|
lbc.recorder.Eventf(delSecr, api.EventTypeNormal, "DELETE", fmt.Sprintf("%s/%s", delSecr.Namespace, delSecr.Name))
|
||||||
|
lbc.syncQueue.enqueue(obj)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpdateFunc: func(old, cur interface{}) {
|
||||||
|
if !reflect.DeepEqual(old, cur) {
|
||||||
|
upSecr := cur.(*api.Secret)
|
||||||
|
if lbc.secrReferenced(upSecr.Namespace, upSecr.Name) {
|
||||||
|
lbc.recorder.Eventf(upSecr, api.EventTypeNormal, "UPDATE", fmt.Sprintf("%s/%s", upSecr.Namespace, upSecr.Name))
|
||||||
|
lbc.syncQueue.enqueue(cur)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
eventHandler := framework.ResourceEventHandlerFuncs{
|
eventHandler := framework.ResourceEventHandlerFuncs{
|
||||||
AddFunc: func(obj interface{}) {
|
AddFunc: func(obj interface{}) {
|
||||||
lbc.syncQueue.enqueue(obj)
|
lbc.syncQueue.enqueue(obj)
|
||||||
|
@ -214,6 +242,13 @@ func newLoadBalancerController(kubeClient *client.Client, resyncPeriod time.Dura
|
||||||
},
|
},
|
||||||
&api.Service{}, resyncPeriod, framework.ResourceEventHandlerFuncs{})
|
&api.Service{}, resyncPeriod, framework.ResourceEventHandlerFuncs{})
|
||||||
|
|
||||||
|
lbc.secrLister.Store, lbc.secrController = framework.NewInformer(
|
||||||
|
&cache.ListWatch{
|
||||||
|
ListFunc: secretsListFunc(lbc.client, namespace),
|
||||||
|
WatchFunc: secretsWatchFunc(lbc.client, namespace),
|
||||||
|
},
|
||||||
|
&api.Secret{}, resyncPeriod, secrEventHandler)
|
||||||
|
|
||||||
lbc.mapLister.Store, lbc.mapController = framework.NewInformer(
|
lbc.mapLister.Store, lbc.mapController = framework.NewInformer(
|
||||||
&cache.ListWatch{
|
&cache.ListWatch{
|
||||||
ListFunc: mapListFunc(lbc.client, namespace),
|
ListFunc: mapListFunc(lbc.client, namespace),
|
||||||
|
@ -260,6 +295,18 @@ func endpointsWatchFunc(c *client.Client, ns string) func(options api.ListOption
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func secretsListFunc(c *client.Client, ns string) func(api.ListOptions) (runtime.Object, error) {
|
||||||
|
return func(opts api.ListOptions) (runtime.Object, error) {
|
||||||
|
return c.Secrets(ns).List(opts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func secretsWatchFunc(c *client.Client, ns string) func(options api.ListOptions) (watch.Interface, error) {
|
||||||
|
return func(options api.ListOptions) (watch.Interface, error) {
|
||||||
|
return c.Secrets(ns).Watch(options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func mapListFunc(c *client.Client, ns string) func(api.ListOptions) (runtime.Object, error) {
|
func mapListFunc(c *client.Client, ns string) func(api.ListOptions) (runtime.Object, error) {
|
||||||
return func(opts api.ListOptions) (runtime.Object, error) {
|
return func(opts api.ListOptions) (runtime.Object, error) {
|
||||||
return c.ConfigMaps(ns).List(opts)
|
return c.ConfigMaps(ns).List(opts)
|
||||||
|
@ -273,8 +320,11 @@ func mapWatchFunc(c *client.Client, ns string) func(options api.ListOptions) (wa
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lbc *loadBalancerController) controllersInSync() bool {
|
func (lbc *loadBalancerController) controllersInSync() bool {
|
||||||
return lbc.ingController.HasSynced() && lbc.svcController.HasSynced() &&
|
return lbc.ingController.HasSynced() &&
|
||||||
lbc.endpController.HasSynced() && lbc.mapController.HasSynced()
|
lbc.svcController.HasSynced() &&
|
||||||
|
lbc.endpController.HasSynced() &&
|
||||||
|
lbc.secrController.HasSynced() &&
|
||||||
|
lbc.mapController.HasSynced()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lbc *loadBalancerController) getConfigMap(ns, name string) (*api.ConfigMap, error) {
|
func (lbc *loadBalancerController) getConfigMap(ns, name string) (*api.ConfigMap, error) {
|
||||||
|
@ -759,6 +809,7 @@ func (lbc *loadBalancerController) createUpstreams(ngxCfg nginx.Configuration, d
|
||||||
|
|
||||||
svcKey := fmt.Sprintf("%v/%v", ing.GetNamespace(), path.Backend.ServiceName)
|
svcKey := fmt.Sprintf("%v/%v", ing.GetNamespace(), path.Backend.ServiceName)
|
||||||
svcObj, svcExists, err := lbc.svcLister.Store.GetByKey(svcKey)
|
svcObj, svcExists, err := lbc.svcLister.Store.GetByKey(svcKey)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Infof("error getting service %v from the cache: %v", svcKey, err)
|
glog.Infof("error getting service %v from the cache: %v", svcKey, err)
|
||||||
continue
|
continue
|
||||||
|
@ -833,14 +884,19 @@ func (lbc *loadBalancerController) getPemsFromIngress(data []interface{}) map[st
|
||||||
|
|
||||||
for _, ingIf := range data {
|
for _, ingIf := range data {
|
||||||
ing := ingIf.(*extensions.Ingress)
|
ing := ingIf.(*extensions.Ingress)
|
||||||
|
|
||||||
for _, tls := range ing.Spec.TLS {
|
for _, tls := range ing.Spec.TLS {
|
||||||
secretName := tls.SecretName
|
secretName := tls.SecretName
|
||||||
secret, err := lbc.client.Secrets(ing.Namespace).Get(secretName)
|
secretKey := fmt.Sprintf("%s/%s", ing.Namespace, secretName)
|
||||||
|
secretInterface, exists, err := lbc.secrLister.Store.GetByKey(secretKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Warningf("Error retriveing secret %v for ing %v: %v", secretName, ing.Name, err)
|
glog.Warningf("Error retriveing secret %v for ing %v: %v", secretName, ing.Name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if !exists {
|
||||||
|
glog.Warningf("Secret %v is not existing", secretKey)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
secret := secretInterface.(*api.Secret)
|
||||||
cert, ok := secret.Data[api.TLSCertKey]
|
cert, ok := secret.Data[api.TLSCertKey]
|
||||||
if !ok {
|
if !ok {
|
||||||
glog.Warningf("Secret %v has no private key", secretName)
|
glog.Warningf("Secret %v has no private key", secretName)
|
||||||
|
@ -882,6 +938,22 @@ func (lbc *loadBalancerController) getPemsFromIngress(data []interface{}) map[st
|
||||||
return pems
|
return pems
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if secret is referenced in this controller's config
|
||||||
|
func (lbc *loadBalancerController) secrReferenced(namespace string, name string) bool {
|
||||||
|
for _, ingIf := range lbc.ingLister.Store.List() {
|
||||||
|
ing := ingIf.(*extensions.Ingress)
|
||||||
|
if ing.Namespace != namespace {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, tls := range ing.Spec.TLS {
|
||||||
|
if tls.SecretName == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// getEndpoints returns a list of <endpoint ip>:<port> for a given service/target port combination.
|
// getEndpoints returns a list of <endpoint ip>:<port> for a given service/target port combination.
|
||||||
func (lbc *loadBalancerController) getEndpoints(s *api.Service, servicePort intstr.IntOrString, proto api.Protocol, hz *healthcheck.Upstream) []nginx.UpstreamServer {
|
func (lbc *loadBalancerController) getEndpoints(s *api.Service, servicePort intstr.IntOrString, proto api.Protocol, hz *healthcheck.Upstream) []nginx.UpstreamServer {
|
||||||
glog.V(3).Infof("getting endpoints for service %v/%v and port %v", s.Namespace, s.Name, servicePort.String())
|
glog.V(3).Infof("getting endpoints for service %v/%v and port %v", s.Namespace, s.Name, servicePort.String())
|
||||||
|
@ -1026,6 +1098,7 @@ func (lbc *loadBalancerController) Run() {
|
||||||
go lbc.ingController.Run(lbc.stopCh)
|
go lbc.ingController.Run(lbc.stopCh)
|
||||||
go lbc.endpController.Run(lbc.stopCh)
|
go lbc.endpController.Run(lbc.stopCh)
|
||||||
go lbc.svcController.Run(lbc.stopCh)
|
go lbc.svcController.Run(lbc.stopCh)
|
||||||
|
go lbc.secrController.Run(lbc.stopCh)
|
||||||
go lbc.mapController.Run(lbc.stopCh)
|
go lbc.mapController.Run(lbc.stopCh)
|
||||||
|
|
||||||
go lbc.syncQueue.run(time.Second, lbc.stopCh)
|
go lbc.syncQueue.run(time.Second, lbc.stopCh)
|
||||||
|
|
|
@ -37,6 +37,11 @@ type StoreToIngressLister struct {
|
||||||
cache.Store
|
cache.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StoreToSecretsLister makes a Store that lists Secrets.
|
||||||
|
type StoreToSecretsLister struct {
|
||||||
|
cache.Store
|
||||||
|
}
|
||||||
|
|
||||||
// StoreToConfigmapLister makes a Store that lists Configmap.
|
// StoreToConfigmapLister makes a Store that lists Configmap.
|
||||||
type StoreToConfigmapLister struct {
|
type StoreToConfigmapLister struct {
|
||||||
cache.Store
|
cache.Store
|
||||||
|
|
Loading…
Reference in a new issue