Promethues升级死锁

Promethues升级死锁

promethues升级的时候报错:“opening storage failed: lock DB directory: resource temporarily unavailable”

从报错看是TSDB 数据库打开失败了。进入prometheus存储TSDB数据的目录/prometheus可以看到:

这个lock 文件如下所示

Promethues升级死锁

我们是通过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

标签:死锁   解锁   加锁   策略   两个   结束   代码   简单   方式   数据库   文件   目录   方法   数据   系统   科技

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top