Avoid nginx reloads

This commit is contained in:
Manuel de Brito Fontes 2016-11-23 21:14:14 -03:00
parent 5a8e090736
commit 42b58e957c
4 changed files with 20 additions and 26 deletions

View file

@ -105,22 +105,18 @@ func (n NGINXController) Start() {
// Reload checks if the running configuration file is different // Reload checks if the running configuration file is different
// to the specified and reload nginx if required // to the specified and reload nginx if required
func (n NGINXController) Reload(data []byte) ([]byte, error) { func (n NGINXController) Reload(data []byte) ([]byte, bool, error) {
if !n.isReloadRequired(data) { if !n.isReloadRequired(data) {
return nil, fmt.Errorf("Reload not required") return []byte("Reload not required"), false, nil
} }
err := ioutil.WriteFile(cfgPath, data, 0644) err := ioutil.WriteFile(cfgPath, data, 0644)
if err != nil { if err != nil {
return nil, err return nil, false, err
} }
return exec.Command(n.binary, "-s", "reload").CombinedOutput() o, e := exec.Command(n.binary, "-s", "reload").CombinedOutput()
} return o, true, e
// Test checks is a file contains a valid NGINX configuration
func (n NGINXController) Test(file string) *exec.Cmd {
return exec.Command(n.binary, "-t", "-c", file)
} }
// BackendDefaults returns the nginx defaults // BackendDefaults returns the nginx defaults
@ -188,7 +184,7 @@ func (n NGINXController) testTemplate(cfg []byte) error {
} }
defer tmpfile.Close() defer tmpfile.Close()
ioutil.WriteFile(tmpfile.Name(), cfg, 0644) ioutil.WriteFile(tmpfile.Name(), cfg, 0644)
out, err := n.Test(tmpfile.Name()).CombinedOutput() out, err := exec.Command(n.binary, "-t", "-c", tmpfile.Name()).CombinedOutput()
if err != nil { if err != nil {
// this error is different from the rest because it must be clear why nginx is not working // this error is different from the rest because it must be clear why nginx is not working
oe := fmt.Sprintf(` oe := fmt.Sprintf(`

View file

@ -89,9 +89,11 @@ func (ic *GenericController) syncSecret(k interface{}) error {
// create certificates and add or update the item in the store // create certificates and add or update the item in the store
_, exists = ic.sslCertTracker.Get(key) _, exists = ic.sslCertTracker.Get(key)
if exists { if exists {
glog.V(3).Infof("updating secret %v/%v in the store ", sec.Namespace, sec.Name)
ic.sslCertTracker.Update(key, cert) ic.sslCertTracker.Update(key, cert)
return nil return nil
} }
glog.V(3).Infof("adding secret %v/%v to the store ", sec.Namespace, sec.Name)
ic.sslCertTracker.Add(key, cert) ic.sslCertTracker.Add(key, cert)
return nil return nil
} }
@ -99,7 +101,7 @@ func (ic *GenericController) syncSecret(k interface{}) error {
func (ic *GenericController) getPemCertificate(secretName string) (*ingress.SSLCert, error) { func (ic *GenericController) getPemCertificate(secretName string) (*ingress.SSLCert, error) {
secretInterface, exists, err := ic.secrLister.Store.GetByKey(secretName) secretInterface, exists, err := ic.secrLister.Store.GetByKey(secretName)
if err != nil { if err != nil {
return nil, fmt.Errorf("Error retriveing secret %v: %v", secretName, err) return nil, fmt.Errorf("error retriveing secret %v: %v", secretName, err)
} }
if !exists { if !exists {
return nil, fmt.Errorf("secret named %v does not exists", secretName) return nil, fmt.Errorf("secret named %v does not exists", secretName)

View file

@ -386,14 +386,16 @@ func (ic *GenericController) sync(key interface{}) error {
return err return err
} }
out, err := ic.cfg.Backend.Reload(data) out, reloaded, err := ic.cfg.Backend.Reload(data)
if err != nil { if err != nil {
incReloadErrorCount() incReloadErrorCount()
glog.Errorf("unexpected failure restarting the backend: \n%v", string(out)) glog.Errorf("unexpected failure restarting the backend: \n%v", string(out))
return err return err
} }
if reloaded {
glog.Infof("ingress backend successfully reloaded...") glog.Infof("ingress backend successfully reloaded...")
incReloadCount() incReloadCount()
}
return nil return nil
} }
@ -686,7 +688,6 @@ func (ic *GenericController) getBackendServers() ([]*ingress.Backend, []*ingress
loc.BasicDigestAuth = *nginxAuth loc.BasicDigestAuth = *nginxAuth
loc.RateLimit = *rl loc.RateLimit = *rl
loc.Redirect = *locRew loc.Redirect = *locRew
//loc.SecureUpstream = secUpstream
loc.Whitelist = *wl loc.Whitelist = *wl
loc.Backend = ups.Name loc.Backend = ups.Name
loc.EnableCORS = eCORS loc.EnableCORS = eCORS
@ -706,7 +707,6 @@ func (ic *GenericController) getBackendServers() ([]*ingress.Backend, []*ingress
BasicDigestAuth: *nginxAuth, BasicDigestAuth: *nginxAuth,
RateLimit: *rl, RateLimit: *rl,
Redirect: *locRew, Redirect: *locRew,
//SecureUpstream: secUpstream,
Whitelist: *wl, Whitelist: *wl,
EnableCORS: eCORS, EnableCORS: eCORS,
ExternalAuth: ra, ExternalAuth: ra,
@ -921,7 +921,7 @@ func (ic *GenericController) createServers(data []interface{}, upstreams map[str
host = defServerName host = defServerName
} }
// only add certificate if the server does not have one previously configured // only add a certificate if the server does not have one previously configured
if len(ing.Spec.TLS) > 0 && servers[host].SSLCertificate != "" { if len(ing.Spec.TLS) > 0 && servers[host].SSLCertificate != "" {
key := fmt.Sprintf("%v/%v", ing.Namespace, ing.Spec.TLS[0].SecretName) key := fmt.Sprintf("%v/%v", ing.Namespace, ing.Spec.TLS[0].SecretName)
bc, exists := ic.sslCertTracker.Get(key) bc, exists := ic.sslCertTracker.Get(key)
@ -1048,8 +1048,8 @@ func (ic GenericController) Start() {
go ic.secrController.Run(ic.stopCh) go ic.secrController.Run(ic.stopCh)
go ic.mapController.Run(ic.stopCh) go ic.mapController.Run(ic.stopCh)
go ic.secretQueue.Run(time.Second, ic.stopCh) go ic.secretQueue.Run(5*time.Second, ic.stopCh)
go ic.syncQueue.Run(time.Second, ic.stopCh) go ic.syncQueue.Run(5*time.Second, ic.stopCh)
go ic.syncStatus.Run(ic.stopCh) go ic.syncStatus.Run(ic.stopCh)

View file

@ -17,8 +17,6 @@ limitations under the License.
package ingress package ingress
import ( import (
"os/exec"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/ingress/core/pkg/ingress/annotations/auth" "k8s.io/ingress/core/pkg/ingress/annotations/auth"
@ -43,15 +41,13 @@ var (
// TODO (#18): Make sure this is sufficiently supportive of other backends. // TODO (#18): Make sure this is sufficiently supportive of other backends.
type Controller interface { type Controller interface {
// Reload takes a byte array representing the new loadbalancer configuration, // Reload takes a byte array representing the new loadbalancer configuration,
// and returns a byte array containing any output/errors from the backend. // and returns a byte array containing any output/errors from the backend and
// if a reload was required.
// Before returning the backend must load the configuration in the given array // Before returning the backend must load the configuration in the given array
// into the loadbalancer and restart it, or fail with an error and message string. // into the loadbalancer and restart it, or fail with an error and message string.
// If reloading fails, there should be not change in the running configuration or // If reloading fails, there should be not change in the running configuration or
// the given byte array. // the given byte array.
Reload(data []byte) ([]byte, error) Reload(data []byte) ([]byte, bool, error)
// Tests returns the commands to execute that verifies if the configuration file is valid
// Example: nginx -t -c <file>
Test(file string) *exec.Cmd
// OnUpdate callback invoked from the sync queue https://k8s.io/ingress/core/blob/master/pkg/ingress/controller/controller.go#L387 // OnUpdate callback invoked from the sync queue https://k8s.io/ingress/core/blob/master/pkg/ingress/controller/controller.go#L387
// when an update occurs. This is executed frequently because Ingress // when an update occurs. This is executed frequently because Ingress
// controllers watches changes in: // controllers watches changes in: