Myluzh Blog

K8S环境下的Nacos应用优雅下线

发布时间: 2024-8-9 文章作者: myluzh 分类名称: Kubernetes 朗读文章


0x01 Nacos心跳时间
Nacos心跳检测时间 Nacos 目前支持临时实例使用心跳上报方式维持活性,发送心跳的周期默认是 5 秒,Nacos 服务端会在 15 秒没收到心跳后将实例设置为不健康,  在 30 秒没收到心跳时将这个临时实例摘除(这里要注意30秒这个时间)。
0x02 Nacos下线应用接口 
在Nacos OpenAPI:(https://nacos.io/zh-cn/docs/open-api.html )中有写明,可以通过/nacos/v1/ns/instance修改实例来完成应用下线,例如:
curl -X PUT "http://172.30.233.87:8848/nacos/v1/ns/instance?serviceName=xfshcloud-dxp&clusterName=DEFAULT&groupName=DEFAULT_GROUP&ip=10.42.1.89&port=9208&ephemeral=true&weight=1&enabled=false&namespaceId=a9076f8c-a1c7-474c-9ea4-1112677d9af7"
ok

# 说明:
# 172.30.233.87:8848 nacos注册地址
# serviceName=xfshcloud-dxp nacos中注册的应用名称
# ip=10.42.1.89 应用所在主机地址(也就是K8S中的PODIP)
# port=9208 注册的应用名称使用的端口号
# enabled=false 下线,enabled=true 上线
# namespaceId=xxx 命令空间(如果使用public命名空间则不需要这个)
0x03 在K8S中的优雅下线
1、编写nacos_unreg.sh
#!/bin/sh

echo "######## NACOS取消注册 ########"

# 获取POD的IP地址,定义NACOS服务器地址、服务名和端口
POD_IP=$(hostname -i)  # 使用 hostname -i 来获取 POD IP 可能不适用所有环境,建议使用 hostname -f 或通过环境变量来获取 POD IP 地址。
if [ -z "$POD_IP" ]; then
  echo "无法获取POD IP地址"
  exit 1
fi

NACOS_SERVER_ADDR=$1 # '172.30.233.87:8848'
SERVICE_NAME=$2 # "xfshcloud-dxp"
SERVICE_PORT=$3 #"9208"

[ -z "$NACOS_SERVER_ADDR" ] && { echo "错误: 未传入参数 NACOS_SERVER_ADDR 为空"; exit 1; }
[ -z "$SERVICE_NAME" ] && { echo "错误: 未传入参数 SERVICE_NAME 为空"; exit 1; }
[ -z "$SERVICE_PORT" ] && { echo "错误: 未传入参数  SERVICE_PORT 为空"; exit 1; }


# 构建取消注册的URL
UNREGISTER_URL="http://${NACOS_SERVER_ADDR}/nacos/v1/ns/instance?serviceName=${SERVICE_NAME}&clusterName=DEFAULT&groupName=DEFAULT_GROUP&ip=${POD_IP}&port=${SERVICE_PORT}&ephemeral=true&weight=1&enabled=false"

# 打印URL
echo "NACOS_取消注册URL: ${UNREGISTER_URL}"

# 执行取消注册请求并获取结果
result=$(curl -s -X PUT ${UNREGISTER_URL})

# 打印结果
echo "NACOS_取消注册结果: ${result}"

# 检查结果并处理
if [ "${result}" = "ok" ]; then
  echo "NACOS_执行成功"
  sleep 45
  exit 0
else
  echo "NACOS_执行失败"
  sleep 45
  exit 1
fi
2、在应用Dockerfile中把脚本放进去
# Dockerfile文件,增加这个nacos_unreg.sh脚本,设置可执行权限
ADD nacos_unreg.sh /usr/local/bin/nacos_unreg.sh
RUN chmod +x /usr/local/bin/nacos_unreg.sh
3、在应用yaml文件中增加prestop与terminationGracePeriodSeconds参数
Pod灭亡有个优雅终止宽限期terminationGracePeriod默认是30秒,Nacos中应用超过30秒则摘除,主要围绕这俩时间来进行处理。
apiVersion: v1
kind: Pod
metadata:
  name: your-pod-name
spec:
  terminationGracePeriodSeconds: 60  # 允许 Pod 优雅关闭的时间
  containers:
  - name: your-container-name
    image: your-image
    lifecycle:
      preStop:
        exec:
          command: ["/bin/sh", "-c", "/usr/local/bin/nacos_unreg.sh 172.30.233.87:8848 xfshcloud-dxp 9208"] 
4、验证
同时更新应用使用的docker镜像,待镜像启动后,增加副本数,由1增加到3,同时观察nacos中注册的应用数,确认显示有3个。
然后缩减一个副本数,副本数由3变成2,注意观察nacos中的应用是否有一个ip状态的变成"上线"(显示这个表示应用是下线状态),等待30秒后就看不到这个ip应用了。
然后观察k8s中pod的消失,等了60秒后才开始取消一个pod,最后查看事件events,发现并没有FailedPreStopHook,这是正常的,因为只有报错的情况下才会出现FailedPreStopHook,正常情况下不会出现这个。
Hook调用的日志没有暴露给Pod的Event,所以只能到通过describe命令来获取,如果是正常的操作是不会有event,如果有错误可以看到FailedPostStartHook和FailedPreStopHook这种event。并且如果Hook调用出现错误,则Pod状态不会是Running


参考链接:
Nacos 文档 Open API 指南 https://nacos.io/zh-cn/docs/open-api.html
使用Kubernetes Pod Hook 优雅的停止Pod:https://www.cnblogs.com/fengjian2016/p/15205477.html

标签: k8s PreStop nacos

发表评论