活久见,Pod日志也能做探针?

在这里插入图片描述

最近遇到一个有趣的场景,当业务方有一个只运行异步任务的容器,这意味着它逻辑简单,即从上游服务中获取内容进行数据处理,但应用本身不提供任何方式判断当前服务状态。当服务运行出现阻塞时,我们该如何在Kubernetes中来实现探针管理呢?很多同学都使用过存活探针就绪探针启动探针,不过它们有一个共同的属性就是需要应用本身提供一个Http/TCP接口或一个Command来评估服务当前是否健康。在不具备上述条件的情况下,我们就只能通过捕获容器的控制台日志输出来判断容器运行是否健康了

不要问我业务应用阻塞的原因,总之一言难尽。
也不要问我靠容器打印的日志来判断是否健康是否不太可靠。但凡研发要求应用稳定会不写探针?

虽然作为平台接锅侠的我们,在应用出现阻塞时,大部分情况下都是在K8S中将出问题的应用杀掉重启。久而久之,具备丰富delete容器的经验驱使我们应该且需要将这类任务交给K8S自行处理。

首先,要解决的是如何在容器内捕获自己的控制台日志

当一个K8S集群部署完成后,在default命名空间内有一个叫kubernetes的默认service。它的主要作用就是供集群内容器调取k8s api使用的地址。我们可以在容器内通过https://kubernetes.default.svc.cluster.local访问k8s api。那我们调取容器自身控制台的日志,就可以用如下接口:

https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/pods/$HOSTNAME/log

这里我们就需要将容器的namespace元数据传入到环境变量,方式如下:

containers:
- env:
  - name: NAMESPACE
    valueFrom:
      fieldRef:
        apiVersion: v1
        fieldPath: metadata.namespace

先来请求看下情况:
在这里插入图片描述

forbidden: User system:anonymous看来还得加上RABC相关的权限设置。我们可以为应用单独创建一个ServiceAccount,如下:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: log-capture
  labels:
    app.kubernetes.io/name: app
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/name: app
  name: log-capture
rules:
- apiGroups: [""]
  resources: ["pods","pods/log"]
  verbs: ["get","list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/name: app
  name: log-capture
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: log-capture
subjects:
- kind: ServiceAccount
  name: log-capture

再将该SA引进至Workerload下,如例:

spec:
  containers: {}
  serviceAccount: log-capture
  serviceAccountName: log-capture

如果你天性不羁,也一些可以将RoleBinding做在default上

除此之外,我还需要在请求里带上自己的认证信息。默认情况下容器内的SA Token放在/var/run/secrets/kubernetes.io/serviceaccount/token路径下。我们再来请求看看
在这里插入图片描述

ok,现在我们在容器内能捕获到自己的日志了。

其次,建立K8S探针与控制台日志的关系

明眼的小伙伴可能看出问题了,只通过调取日志接口的方式并不能判断应用是否出现阻塞,因为容器的控制台日志是持久化到node节点的,通过判断日志是否有输出的话,那结果永远会是为真

我们应该给日志接口加上?sinceSeconds=参数,这样我们就能捕获最近一段时间的日志了。

接下来我们只需要把以上逻辑用shell实现并放在镜像或者configmap里面用liveness探针去执行即可。这里小白在探测脚本里面加了个探针失败的计数器,来递增扩大捕获日志的时间,可以参考如下:

#!/bin/bash

if [[ -f /tmp/ProbeFailedTimes ]]; then
    COUNT=$(cat /tmp/ProbeFailedTimes)
    let Probe_Seconds=(1+${COUNT})*${COUNT}/2*60
else
    COUNT="0"
    Probe_Seconds="60"
fi

STDOUT=`timeout 10 curl -s https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/pods/$HOSTNAME/log?sinceSeconds=${Probe_Seconds} -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"`

if [[ "$STDOUT" == "" ]]; then
    let COUNT=${COUNT}+1
    echo "$COUNT" > /tmp/ProbeFailedTimes
    echo "Now $(cat /tmp/ProbeFailedTimes)"
    exit 1
else
    rm -rf /tmp/ProbeFailedTimes
    echo "Now 0"
    exit 0
fi

然后我们再将workerload中添加liveness探针:

containers:
  livenessProbe:
    exec:
      command:
      - /bin/bash
      - -c
      - /probe.sh
    failureThreshold: 15
    initialDelaySeconds: 120
    periodSeconds: 60
    successThreshold: 1
    timeoutSeconds: 10

这样,liveness检查容器日志的逻辑就变成每60s检查输出,如果没有下次检查180s内,在下次就是360s日志,直到第15次检查2小时前的日志,刨除探针本身15分钟的时间,最终满足的容器再过去105分钟内无日志输出便任务失败,k8s重启pod。探针检测中途一旦有日志打印,则计数器重置。
在这里插入图片描述

为什么要用计数器?灵活调整容器内请求日志的时间范围,避免探针出现在两次打印的中间,出现探测失败

最后不要问如果我的应用连容器日志也没打印该怎么办,我只能说那自求多福吧😂


关注「云原生小白」,进入Loki学习群
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!对于 `CrashLoopBackOff` 状态的 Pod,这通常表示该 Pod 在启动过程中遇到了问题,并且一直处于重启循环中。这个状态意味着 Pod 启动后立即崩溃,然后 Kubernetes 尝试重新启动它,但又崩溃了,如此循环。 要解决这个问题,你可以按照以下步骤进行排查: 1. 查看 Pod日志:使用 `kubectl logs <pod-name>` 命令来查看 Pod日志,尝试找出何处发生了错误。可能会有一些错误消息或异常堆栈跟踪可供参考。 2. 检查 Pod 的配置:确保你的 Pod 配置正确无误,包括容器镜像、资源限制、环境变量等。一个常见的问题是容器启动所需的依赖项未正确配置或缺失。 3. 检查相关的服务和资源:如果你的应用程序依赖于其他服务或资源(例如数据库),请确保这些服务和资源都正常可用。如果依赖的服务不可用,可能会导致容器启动失败并进入 `CrashLoopBackOff` 状态。 4. 检查 Pod 的健康检查设置:你的应用程序可能配置了健康检查,例如使用 Kubernetes 的 liveness 或 readiness 探针。确保这些探针正确配置,以便检测到应用程序是否健康。如果探针失败,则 Pod 可能会被 Kubernetes 认为是不可用的,从而导致重启循环。 5. 更新容器镜像:如果你的应用程序使用的容器镜像存在已知的 bug 或问题,尝试更新镜像到最新版本或使用一个稳定版本。 通过排查以上问题,你应该能够找到导致 `CrashLoopBackOff` 状态的原因,并采取相应的措施解决问题。希望对你有所帮助!如果你还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值