如何确保 kubernetes 中的优雅扩展?
How can I ensure graceful scaling in kubernetes?
作为在 kubernetes 中扩展 pods 的一部分,我想确保在关闭之前正常提供我的 http 连接。就此而言,我已经在 go 中实现了这段代码:
package main
import (
"fmt"
"io"
"net/http"
"os"
"os/signal"
"syscall"
"github.com/braintree/manners"
)
func main() {
shutdown := make(chan int)
//create a notification channel to shutdown
sigChan := make(chan os.Signal, 1)
//start the http server
http.HandleFunc("/", hello)
server := manners.NewWithServer(&http.Server{Addr: ":80", Handler: nil})
go func() {
server.ListenAndServe()
shutdown <- 1
}()
//register for interupt (Ctrl+C) and SIGTERM (docker)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigChan
fmt.Println("Shutting down...")
server.Close()
}()
<-shutdown
}
func hello(w http.ResponseWriter, r *http.Request) {
// time.Sleep(3000 * time.Millisecond)
io.WriteString(w, "Hello world!")
}
这会寻找 docker SIGTERM 并在处理完现有请求后正常关闭。当我 运行 kubernetes 中的这个容器有 10 个实例时,只要我不缩小到单个实例,我就可以毫无意外地向上和向下扩展。当我扩展到单个实例时,我看到一小部分 http 错误,然后一切看起来都很好。
我觉得这很奇怪,因为在缩放时我会假设首先更新代理,然后关闭容器,上面的代码将允许处理请求。
在我当前的设置中,我 运行 有 2 个节点,也许问题是当缩放比例低于节点数量时,etcd 更新存在某种计时问题?任何对这里发生的事情的洞察都会非常有用
在您收到 SIGTERM
后将 Pod 转换为 "not ready"
一旦发生这种情况,该服务将在删除之前从服务中移除 Pod。
(没有就绪检查,服务根本不知道 pod 不存在,直到它被实际删除)
您可能还想使用 PreStop 挂钩,将准备就绪设置为 false,然后耗尽所有现有请求。 PreStop 挂钩在 Pod 被删除之前被同步调用,它们在此处描述:
有一个小的 window 期间,正在删除但仍然存在的 pod 将成为负载平衡集的一部分。正如 Brendan 刚才所说(他比我快了几秒钟),准备检查应该可以为您解决此问题,完全在您的控制之下。
作为在 kubernetes 中扩展 pods 的一部分,我想确保在关闭之前正常提供我的 http 连接。就此而言,我已经在 go 中实现了这段代码:
package main
import (
"fmt"
"io"
"net/http"
"os"
"os/signal"
"syscall"
"github.com/braintree/manners"
)
func main() {
shutdown := make(chan int)
//create a notification channel to shutdown
sigChan := make(chan os.Signal, 1)
//start the http server
http.HandleFunc("/", hello)
server := manners.NewWithServer(&http.Server{Addr: ":80", Handler: nil})
go func() {
server.ListenAndServe()
shutdown <- 1
}()
//register for interupt (Ctrl+C) and SIGTERM (docker)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigChan
fmt.Println("Shutting down...")
server.Close()
}()
<-shutdown
}
func hello(w http.ResponseWriter, r *http.Request) {
// time.Sleep(3000 * time.Millisecond)
io.WriteString(w, "Hello world!")
}
这会寻找 docker SIGTERM 并在处理完现有请求后正常关闭。当我 运行 kubernetes 中的这个容器有 10 个实例时,只要我不缩小到单个实例,我就可以毫无意外地向上和向下扩展。当我扩展到单个实例时,我看到一小部分 http 错误,然后一切看起来都很好。
我觉得这很奇怪,因为在缩放时我会假设首先更新代理,然后关闭容器,上面的代码将允许处理请求。
在我当前的设置中,我 运行 有 2 个节点,也许问题是当缩放比例低于节点数量时,etcd 更新存在某种计时问题?任何对这里发生的事情的洞察都会非常有用
在您收到 SIGTERM
后将 Pod 转换为 "not ready"一旦发生这种情况,该服务将在删除之前从服务中移除 Pod。
(没有就绪检查,服务根本不知道 pod 不存在,直到它被实际删除)
您可能还想使用 PreStop 挂钩,将准备就绪设置为 false,然后耗尽所有现有请求。 PreStop 挂钩在 Pod 被删除之前被同步调用,它们在此处描述:
有一个小的 window 期间,正在删除但仍然存在的 pod 将成为负载平衡集的一部分。正如 Brendan 刚才所说(他比我快了几秒钟),准备检查应该可以为您解决此问题,完全在您的控制之下。