momo's Blog.

排查consul拿不到锁引出常用的nfs参数

字数统计: 639阅读时长: 2 min
2024/04/07 Share

前言

最近在排查consul拿不到锁的问题.报错信息failed to acquire lock: lock not available

我们consul跑在k8s当中, 数据持久化是用nfs做的,但是最近新部署的consul一直卡在拿锁卡主, 或者直接拿不到锁.

排查思路一直在为什么拿不到锁上。

拿不到锁的原因是:
通常没有启动rpc-statd

nfs的锁依赖于rpcbind服务,如果rpcbind服务不可用,那么nfs的锁也就不可用。 但是我们宿主机上的rpcbind服务是正常的. 通过执行命令rpcinfo -p可以看到rpcbind服务的进程. 发现缺少一个关键服务nlockmgr,这个服务是nfs的锁服务,如果这个服务不可用,那么nfs的锁也就不可用。

但是本地用过flock测试过nfs的锁是可以用的,所以这个问题就很奇怪了。
flock -e ./a.txt echo 1

问题

后来发现, 是两个问题重叠了.

问题一

内核机制导致rpcbind启动报错, 通过rpcinfo -p localhost查看rpcbind服务的进程,发现nlockmgr服务没有启动. 重启机器, 关闭selinux之后发现nlockmgr服务启动了.

问题二

consul拿不到锁, 但是此时不会报错了, 而是一直卡在拿锁的地方. 期间看了源码, 就是普通文件锁.

此时怀疑consul没有释放锁,导致重启后第二个进程也拿不到锁。 因为如果是本地文件, 假如锁没有释放内核会自动管理释放。但是nfs的锁是依赖于rpcbind服务的,所以如果没有释放锁,那么其他进程就拿不到锁。

解决方案

既然这样, 我们还是不要用nfs网络锁了. 用本地文件锁就好了.
通过修改nfs的挂载参数, 使其支持nolock参数, 这样就可以使用本地文件锁了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package main

import (
"context"
"flag"
"fmt"
"log"
"strings"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)

func main() {
kubeconfig := flag.String("kubeconfig", "/path/to/your/kubeconfig", "kubeconfig file")
flag.Parse()
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
log.Fatalln("init Cluster Config failed ", err)
}

clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatalln("init Cluster Config failed ", err)
}

pvList, _ := clientset.CoreV1().PersistentVolumes().List(context.TODO(), metav1.ListOptions{})
for _, pv := range pvList.Items {
if pv.Spec.ClaimRef != nil && strings.Contains(pv.Spec.ClaimRef.Name, "consul") {
if pv.Spec.MountOptions == nil {
pv.Spec.MountOptions = []string{"nolock,tcp,noresvport", "vers=3"}
_, err := clientset.CoreV1().PersistentVolumes().Update(context.TODO(), &pv, metav1.UpdateOptions{})
if err != nil {
panic(err.Error())
}
fmt.Printf("Updated PV: %s\n", pv.Name)
}
}
}
}
CATALOG
  1. 1. 前言
  2. 2. 问题
    1. 2.0.1. 问题一
    2. 2.0.2. 问题二
  • 3. 解决方案