首页 > 解决方案 > Kubernetes Python Client Watch 停止返回结果,不会失败

问题描述

使用 Kubernetes 的 Python 客户端,我创建了一个小型服务来监视新 Pod 并将数据发送到外部服务,以收集指标。我发现它完全可以工作,但几天后手表似乎停止接收新的变化。它不报告任何错误或抛出任何异常;它只是表现得好像没有更多的变化。如果我开始一个新的手表,我可以看到新的变化,如果我重新启动容器,进程会恢复,但似乎我不能让一个进程连续运行。

我在 GKE 上运行,我想知道 Kubernetes API 端点是否不可用。但我只想在它再次可用时恢复。在这种情况下,我对吊舱崩溃并不得不重新启动感到满意,但我根本没有收到来自 Watch 的报告,所以我无法尝试处理任何情况。

这是我的代码的相关部分:

def main():
    log = app.logger.get()
    kube_api = get_kubernetes_config()

    resource_version = get_resource_version(kube_api)

    watch_params = {
        'resource_version': resource_version
    }

    log.debug(f'Watching from resource version {resource_version}')
    w = watch.Watch()

    stream = w.stream(kube_api.list_pod_for_all_namespaces, **watch_params)
    log.info('Started watching for new pods')

    for message in stream:
        process_pod_change(message['object'], log)

def process_pod_change(pod, log):
    if not pod.metadata.deletion_timestamp is None or pod.status.container_statuses is None or not all(status.ready for status in pod.status.container_statuses):
        return
    pod_name = f'{pod.metadata.namespace}/{pod.metadata.name}'
    for status in pod.status.container_statuses:
        docker_image_sha = status.image_id.split('@')[-1]
        report_deployment(docker_image_sha, pod_name, status.name, log)
    with open(RESOURCE_VERSION_FILE, 'w') as f:
        f.write(str(pod.metadata.resource_version))

def report_deployment(sha, pod_name, container_name, log):
    log.info(f'Seen new deployment of {pod_name} container {container_name}: {sha}')
    authorised_session = app.auth.get_authorised_session()
    jsonbody = {
        'artefact_type': 'docker',
        'artefact_id': sha,
        'client': os.environ['CLIENT'],
        'environment': os.environ['ENVIRONMENT'],
        'product': os.environ['PRODUCT']
    }
    r = authorised_session.post(os.environ['NOTIFICATION_URL'], json=jsonbody)
    r.raise_for_status()

生成的日志显示连续的已处理消息流,直到它们停止进入。没有迹象表明日志中发生了任何奇怪的事情。我也相信这与 Kubernetes Watch 有关,而不是我正在做的任何下游处理,因为这是我编写的第二个应用程序,它表现出 Watch 似乎睡着了并且什么都不做的行为。

我用对了吗?我在网上找不到很多例子,而且似乎没有其他人有这个问题,所以我没有看到任何解决方法。

我的集群版本是 1.14.10-gke.27,我使用的是 Python 3.6-alpine 容器,我的 Python 依赖项仅来自过去几周。但我在六个月前再次尝试使用 Watch 时也看到了同样的问题。

标签: pythonkubernetesgoogle-kubernetes-engine

解决方案


你可以参考这个链接:https ://medium.com/programming-kubernetes/building-stuff-with-the-kubernetes-api-part-3-using-python-aea5ab16f627

它谈到设置 timeout_seconds=0 以避免超时。这可能会解决您的问题。

   for item in w.stream(kube_api.list_pod_for_all_namespaces,
                         **watch_params, timeout_seconds=0):

推荐阅读