promethues升级的时候报错:“opening storage failed: lock DB directory: resource temporarily unavailable”
从报错看是TSDB 数据库打开失败了。进入prometheus存储TSDB数据的目录/prometheus可以看到:
这个lock 文件如下所示
我们是通过Deployment方式部署promethues的,Deployment默认的滚动策略是先启动一个新的pod,等新的pod启动成功后,再删除老的pod,由于两个prometheus挂载同一块存储,共用同一个lock文件,所以新的pod等待老的pod结束服务(给lock文件解锁)才能给lock文件加锁然后开始提供服务,而kubernetes等待新的pod启动完成开始服务了才能停止并删除老的pod,这样就产生了一个“死锁”。
查看promethues关于加锁的代码如下:
func Flock(fileName string) (r Releaser, existed bool, err error) {
if err = os.MkdirAll(filepath.Dir(fileName), 0755); err != nil {
return nil, false, err
}
_, err = os.Stat(fileName)
existed = err == nil
r, err = newLock(fileName)
return r, existed, err
}
可以看出该方法中创建了lock文件并且在该文件上调用了newLock()方法,进一步查看newLock()方法:
func newLock(fileName string) (Releaser, error) {
f, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0666)
if err != nil {
return nil, err
}
l := &unixLock{f}
err = l.set(true)
if err != nil {
f.Close()
return nil, err
}
return l, nil
}
func (l *unixLock) set(lock bool) error {
how := syscall.LOCK_UN
if lock {
how = syscall.LOCK_EX
}
return syscall.Flock(int(l.f.Fd()), how|syscall.LOCK_NB)
}
就是通过Flock系统调用对上面的 lock 文件加锁实现多个promethues写数据互斥。
那么解决这个问题就简单了,方式一是直接把老的pod删除,方法二是采用statefulset 部署,statefulset 会先干掉老的pod 然后再启动新Pod。方法三比较hack就是直接将maxSurge设置成0,那么这样也会先杀死老的pod,然后再启动新Pod。
strategy:
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
页面更新:2024-03-18
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号