Send signal SIGQUIT instead of SIGTERM to nginx
This commit is contained in:
parent
a8bfdc2427
commit
9b2013ac56
2 changed files with 56 additions and 30 deletions
|
@ -23,6 +23,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
"k8s.io/ingress/core/pkg/ingress/controller"
|
"k8s.io/ingress/core/pkg/ingress/controller"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,29 +32,32 @@ func main() {
|
||||||
ngx := newNGINXController()
|
ngx := newNGINXController()
|
||||||
// create a custom Ingress controller using NGINX as backend
|
// create a custom Ingress controller using NGINX as backend
|
||||||
ic := controller.NewIngressController(ngx)
|
ic := controller.NewIngressController(ngx)
|
||||||
go handleSigterm(ic)
|
|
||||||
// start the controller
|
|
||||||
ic.Start()
|
|
||||||
// wait
|
|
||||||
glog.Infof("shutting down Ingress controller...")
|
|
||||||
for {
|
|
||||||
glog.Infof("Handled quit, awaiting pod deletion")
|
|
||||||
time.Sleep(30 * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleSigterm(ic *controller.GenericController) {
|
// start the controller
|
||||||
|
go ic.Start()
|
||||||
|
|
||||||
signalChan := make(chan os.Signal, 1)
|
signalChan := make(chan os.Signal, 1)
|
||||||
signal.Notify(signalChan, syscall.SIGTERM)
|
signal.Notify(signalChan, syscall.SIGTERM)
|
||||||
<-signalChan
|
<-signalChan
|
||||||
|
|
||||||
glog.Infof("Received SIGTERM, shutting down")
|
glog.Infof("Received SIGTERM, shutting down")
|
||||||
|
|
||||||
exitCode := 0
|
|
||||||
if err := ic.Stop(); err != nil {
|
if err := ic.Stop(); err != nil {
|
||||||
glog.Infof("Error during shutdown %v", err)
|
glog.Errorf("unexpected error shutting down the ingress controller: %v", err)
|
||||||
exitCode = 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.Infof("Exiting with %v", exitCode)
|
glog.Infof("stopping nginx gracefully...")
|
||||||
os.Exit(exitCode)
|
ngx.Stop()
|
||||||
|
|
||||||
|
timer := time.NewTicker(time.Second * 1)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
if !isNginxRunning(ngx.ports.Status) {
|
||||||
|
glog.Infof("nginx stopped...")
|
||||||
|
glog.Infof("Exiting with code 0")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ var (
|
||||||
// newNGINXController creates a new NGINX Ingress controller.
|
// newNGINXController creates a new NGINX Ingress controller.
|
||||||
// If the environment variable NGINX_BINARY exists it will be used
|
// If the environment variable NGINX_BINARY exists it will be used
|
||||||
// as source for nginx commands
|
// as source for nginx commands
|
||||||
func newNGINXController() ingress.Controller {
|
func newNGINXController() *NGINXController {
|
||||||
ngx := os.Getenv("NGINX_BINARY")
|
ngx := os.Getenv("NGINX_BINARY")
|
||||||
if ngx == "" {
|
if ngx == "" {
|
||||||
ngx = binary
|
ngx = binary
|
||||||
|
@ -88,6 +88,7 @@ func newNGINXController() ingress.Controller {
|
||||||
isIPV6Enabled: isIPv6Enabled(),
|
isIPV6Enabled: isIPv6Enabled(),
|
||||||
resolver: h,
|
resolver: h,
|
||||||
ports: &config.ListenPorts{},
|
ports: &config.ListenPorts{},
|
||||||
|
done: make(chan error),
|
||||||
}
|
}
|
||||||
|
|
||||||
fcgiListener, err := net.Listen("unix", fastCGISocket)
|
fcgiListener, err := net.Listen("unix", fastCGISocket)
|
||||||
|
@ -134,11 +135,13 @@ Error loading new template : %v
|
||||||
|
|
||||||
go n.Start()
|
go n.Start()
|
||||||
|
|
||||||
return ingress.Controller(n)
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// NGINXController ...
|
// NGINXController ...
|
||||||
type NGINXController struct {
|
type NGINXController struct {
|
||||||
|
done chan error
|
||||||
|
|
||||||
t *ngx_template.Template
|
t *ngx_template.Template
|
||||||
|
|
||||||
configmap *api_v1.ConfigMap
|
configmap *api_v1.ConfigMap
|
||||||
|
@ -166,15 +169,16 @@ type NGINXController struct {
|
||||||
ports *config.ListenPorts
|
ports *config.ListenPorts
|
||||||
|
|
||||||
backendDefaults defaults.Backend
|
backendDefaults defaults.Backend
|
||||||
|
|
||||||
|
isShuttingDown bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start start a new NGINX master process running in foreground.
|
// Start start a new NGINX master process running in foreground.
|
||||||
func (n *NGINXController) Start() {
|
func (n *NGINXController) Start() {
|
||||||
glog.Info("starting NGINX process...")
|
glog.Info("starting NGINX process...")
|
||||||
|
|
||||||
done := make(chan error, 1)
|
|
||||||
cmd := exec.Command(n.binary, "-c", cfgPath)
|
cmd := exec.Command(n.binary, "-c", cfgPath)
|
||||||
n.start(cmd, done)
|
start(cmd, n.done)
|
||||||
|
|
||||||
// if the nginx master process dies the workers continue to process requests,
|
// if the nginx master process dies the workers continue to process requests,
|
||||||
// passing checks but in case of updates in ingress no updates will be
|
// passing checks but in case of updates in ingress no updates will be
|
||||||
|
@ -182,7 +186,12 @@ func (n *NGINXController) Start() {
|
||||||
// issues because of this behavior.
|
// issues because of this behavior.
|
||||||
// To avoid this issue we restart nginx in case of errors.
|
// To avoid this issue we restart nginx in case of errors.
|
||||||
for {
|
for {
|
||||||
err := <-done
|
err := <-n.done
|
||||||
|
|
||||||
|
if n.isShuttingDown {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
if exitError, ok := err.(*exec.ExitError); ok {
|
if exitError, ok := err.(*exec.ExitError); ok {
|
||||||
waitStatus := exitError.Sys().(syscall.WaitStatus)
|
waitStatus := exitError.Sys().(syscall.WaitStatus)
|
||||||
glog.Warningf(`
|
glog.Warningf(`
|
||||||
|
@ -195,19 +204,25 @@ NGINX master process died (%v): %v
|
||||||
cmd = exec.Command(n.binary, "-c", cfgPath)
|
cmd = exec.Command(n.binary, "-c", cfgPath)
|
||||||
// we wait until the workers are killed
|
// we wait until the workers are killed
|
||||||
for {
|
for {
|
||||||
conn, err := net.DialTimeout("tcp", "127.0.0.1:80", 1*time.Second)
|
if !isNginxRunning(n.ports.Status) {
|
||||||
if err != nil {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
conn.Close()
|
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
}
|
}
|
||||||
// start a new nginx master process
|
// start a new nginx master process
|
||||||
n.start(cmd, done)
|
start(cmd, n.done)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *NGINXController) start(cmd *exec.Cmd, done chan error) {
|
func (n *NGINXController) Stop() error {
|
||||||
|
n.isShuttingDown = true
|
||||||
|
cmd := exec.Command(n.binary, "-c", cfgPath, "-s", "quit")
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func start(cmd *exec.Cmd, done chan error) {
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
|
@ -216,8 +231,6 @@ func (n *NGINXController) start(cmd *exec.Cmd, done chan error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
n.cmdArgs = cmd.Args
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
done <- cmd.Wait()
|
done <- cmd.Wait()
|
||||||
}()
|
}()
|
||||||
|
@ -230,7 +243,7 @@ func (n NGINXController) BackendDefaults() defaults.Backend {
|
||||||
|
|
||||||
// printDiff returns the difference between the running configuration
|
// printDiff returns the difference between the running configuration
|
||||||
// and the new one
|
// and the new one
|
||||||
func (n NGINXController) printDiff(data []byte) {
|
func printDiff(data []byte) {
|
||||||
if !glog.V(2) {
|
if !glog.V(2) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -655,7 +668,7 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
n.printDiff(content)
|
printDiff(content)
|
||||||
|
|
||||||
err = ioutil.WriteFile(cfgPath, content, 0644)
|
err = ioutil.WriteFile(cfgPath, content, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -716,3 +729,12 @@ func isIPv6Enabled() bool {
|
||||||
cmd := exec.Command("test", "-f", "/proc/net/if_inet6")
|
cmd := exec.Command("test", "-f", "/proc/net/if_inet6")
|
||||||
return cmd.Run() == nil
|
return cmd.Run() == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isNginxRunning(port int) bool {
|
||||||
|
conn, err := net.DialTimeout("tcp", fmt.Sprintf("127.0.0.1:%v", port), 1*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
conn.Close()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue