Skip to main content

通过延长olcIdleTimeout以减少nslcd中的Can't contact LDAP server日志报错

· 7 min read
orange
programmer on jvm platform

客户用例执行失败, 其猜测可能是nslcd服务中的Can't contact LDAP server相关报错导致其生产用例执行失败.

nslcd日志如下:

[fastone@layout01 ~]$ sudo journalctl -t nslcd| tail --line 20
Mar 28 11:58:24 layout01 nslcd[25607]: [debc9e] <group="fsadmin"> connected to LDAP server ldap://172.20.3.126:389
Mar 28 11:59:17 layout01 nslcd[25607]: [fe8aa7] <passwd=2032> ldap_search_ext() failed: Can't contact LDAP server: Broken pipe
Mar 28 11:59:17 layout01 nslcd[25607]: [fe8aa7] <passwd=2032> no available LDAP server found, sleeping 1 seconds
Mar 28 11:59:18 layout01 nslcd[25607]: [fe8aa7] <passwd=2032> connected to LDAP server ldap://172.20.3.126:389
Mar 28 12:00:01 layout01 nslcd[25607]: [272b88] <group/member="root"> ldap_result() failed: Can't contact LDAP server
Mar 28 12:00:36 layout01 nslcd[25607]: [66b17f] <group=2001> ldap_search_ext() failed: Can't contact LDAP server: Broken pipe
Mar 28 12:00:36 layout01 nslcd[25607]: [66b17f] <group=2001> no available LDAP server found, sleeping 1 seconds
Mar 28 12:00:37 layout01 nslcd[25607]: [66b17f] <group=2001> connected to LDAP server ldap://172.20.3.126:389
Mar 28 12:00:38 layout01 nslcd[25607]: [a15030] <passwd=2004> ldap_search_ext() failed: Can't contact LDAP server: Broken pipe
Mar 28 12:00:38 layout01 nslcd[25607]: [a15030] <passwd=2004> no available LDAP server found, sleeping 1 seconds
Mar 28 12:00:39 layout01 nslcd[25607]: [a15030] <passwd=2004> connected to LDAP server ldap://172.20.3.126:389
Mar 28 12:00:39 layout01 nslcd[25607]: [9b7b93] <passwd=2001> ldap_result() failed: Can't contact LDAP server
Mar 28 12:00:54 layout01 nslcd[25607]: [97bb68] <passwd=2011> ldap_result() failed: Can't contact LDAP server
Mar 28 12:01:36 layout01 nslcd[25607]: [005d16] <group=2011> ldap_result() failed: Can't contact LDAP server
Mar 28 12:03:39 layout01 nslcd[25607]: [b9081a] <group="fsadmin"> ldap_search_ext() failed: Can't contact LDAP server: Broken pipe
Mar 28 12:03:39 layout01 nslcd[25607]: [b9081a] <group="fsadmin"> no available LDAP server found, sleeping 1 seconds
Mar 28 12:03:40 layout01 nslcd[25607]: [b9081a] <group="fsadmin"> connected to LDAP server ldap://172.20.3.126:389
Mar 28 12:03:47 layout01 nslcd[25607]: [0f614b] <group/member="root"> ldap_search_ext() failed: Can't contact LDAP server: Broken pipe
Mar 28 12:03:47 layout01 nslcd[25607]: [0f614b] <group/member="root"> no available LDAP server found, sleeping 1 seconds
Mar 28 12:03:48 layout01 nslcd[25607]: [0f614b] <group/member="root"> connected to LDAP server ldap://172.20.3.126:389

从日志中可以发现nslcd服务经常出现Can't contact LDAP server.

问题原因

触发了ldap-server的连接超时

这个问题的原因是因为触发了ldap-server的超时时间, 从而导致nslcd服务中的Can't contact LDAP server相关报错.
ldap-server的连接超时时间我们设置的默认为30s为了确保连接不会被一直占用从而导致服务端负载过高.
但是频繁出现这个错误会让客户认为是我们的ldap-server出现问题导致其用例失败, 我们需要延长超时时间来避免客户的误解.

解决方案

为了解决这个问题, 我们需要修改ldap-server的超时时间.
ldap-server中的超时时间是通过olcIdleTimeout来设置的.
通过修改此值可以延长ldap-server的连接超时时间.
需要注意的是, olcIdleTimeout的单位是秒.
另外的一个注意事项是修改此值需要通过ldap中的config数据库的admin用户来修改.
修改完成之后, 我们需要重启ldap-server服务.

创建change-timeout.ldif文件

先创建如下文件, 为了方便, 我们将超时时间设置为12h.

change-timeout.ldif
dn: cn=config
changetype: modify
replace: olcIdleTimeout
olcIdleTimeout: 43200

通过ldapmodify命令修改超时时间

我们需要连接ldap-server并执行ldapmodify命令来修改ldap连接超时时间.
然后执行如下命令

需要注意的是, 执行ldapmodify命令bind的用户为cn=admin,cn=config用户, 该用户是config数据库的admin用户.

ldapmodify -x -D cn=admin,cn=config -w <password-of-config-admin> -f change-timeout.ldif

该命令将会输出如下内容

modifying entry "cn=config"

当看到上面的输出时, 说明超时时间已经修改成功.

确认超时时间是否修改成功

执行如下命令

ldapsearch -x -D cn=admin,cn=config -w <password-of-config-admin> -b cn=config|grep olcIdleTimeout

该命令将会输出如下内容

olcIdleTimeout: 43200
olcAttributeTypes: ( OLcfgGlAt:18 NAME 'olcIdleTimeout' SYNTAX OMsInteger SING
PendingAuth $ olcDisallows $ olcGentleHUP $ olcIdleTimeout $ olcIndexSubstrIf

通过输出的内容可以看到olcIdleTimeout的值已经被修改为43200.

重启ldap-server

为了确保配置生效, 我们需要重启ldap服务.
不同的ldap服务的重启方式不同, 这里以ldap容器为例.

docker restart <ldap-container>

验证配置是否生效

在安装有nslcd服务的机器上执行如下命令.
两个命令中间间隔35s. 如果配置没生效那么30s后会再次出现Can't contact LDAP server的报错.
因为我们一开始默认的超时时间是30s, 所以我们需要间隔35s来验证配置是否生效.

getent passwd -s ldap && sleep 35s && getent passwd -s ldap

执行期间我们需要观察nslcd服务的日志.
最好开两个终端, 一个执行命令, 一个查看日志. 这样可以更加直观的看到日志.

journalctl -u nslcd -f

如果配置生效那么我们将不会看到Can't contact LDAP server的报错.

备注

默认超时时间的配置文件

change-timeout.ldif
dn: cn=config
changetype: modify
replace: olcIdleTimeout
olcIdleTimeout: 30

查看系统中的nslcd服务的配置文件

cat /etc/nslcd.conf

查看ldap-serverolcRoot用户的信息

olcRootldap-server的超级管理员, 通过该用户可以对ldap-server进行管理.

执行如下命令查看ldap-serverolcRoot用户的信息.

cd /etc/ldap/slapd.d/cn=config && grep -r 'olcRoot' *

该命令将会输出如下参考内容

olcDatabase={0}config.ldif:olcRootDN: cn=admin,cn=config
olcDatabase={0}config.ldif:olcRootPW:: xxxx
olcDatabase={1}mdb.ldif:olcRootDN: cn=admin,dc=demo,dc=com
olcDatabase={1}mdb.ldif:olcRootPW:: xxxx

通过上述输出可以看到有两个olcRoot用户, 一个是cn=admin,cn=config, 另一个是cn=admin,dc=demo,dc=com.
有这两个用户的原因是因为其是不同olcDatabaseolcRoot用户.
olcDatabase={0}config.ldifldap-server的配置数据库. 其主要存放了ldap-server的配置信息.
olcDatabase={1}mdb.ldifldap-server的数据数据库. 其主要存放了ldap-server的数据信息, 该数据是给我们使用的.

确保fd数量可用

因为上面修改了ldap-server的超时时间, 所以我们需要确保ldap-serverfd数量足够.

参考资料