首页 > 解决方案 > 运行 kubectl port-forward 时子进程意外死亡

问题描述

所以,我正在编写一个 CLI 来与 Elasticsearch 对话(因为我厌倦了冗长的 curl 命令)。一切都很好,除非我想与运行在 Kubernetes 中的集群通信,因为它没有暴露在互联网上。因此我必须手动运行kubectl port-forward第一个,我觉得它很烦人。

为了“解决”这个问题,我开始实现某种“预命令”,以便在我的 CLI 中的实际命令之前运行。在我的 CLI 配置文件中,我定义了如下内容:

my_cluster:
  servers: https://localhost:9200
  pre_commands:
  - command: "kubectl use-context ..."
    wait_for_exit: True
  - command: "kubectl port-forward svc/es 9200"
    wait_for_exit: False
    wait_for_output: "Forwarding from 127.0.0.1:9200"

此配置意味着在与名为“my_cluster”的集群通信时,我想预先运行两个 shell 命令:

我正在使用悬崖构建命令行,它在名为prepare_to_run_commandand的方法中公开了一些钩子(在此处clean_up定义):

def _run_shell_subcommand(self, command):
    command = command.split(" ")
    process = subprocess.Popen(command, stdout=subprocess.PIPE)

    return process

def prepare_to_run_command(self, cmd):
    for i in range(len(self.context.pre_commands)):
        command_block = self.context.pre_commands[i]
        process = self._run_shell_subcommand(command_block.get("command"))

        if command_block.get("wait_for_exit"):
            process.communicate()

        elif command_block.get("wait_for_output"):
            string_to_look_for = command_block.get("wait_for_output")
            pattern = re.compile(string_to_look_for)

            while True:
                line = process.stdout.readline()
                if not line:
                    break

                line = line.decode("utf-8").strip()

                match = re.search(pattern, line)

                if match is None:
                    pass
                else:
                    break

        self.context.pre_commands[i]["process"] = process

def clean_up(self, cmd, result, err):
    for pre_command in self.context.pre_commands:
        pre_command.get("process").terminate()

它似乎成功地等待了预期的输出,然后继续执行我想要针对我的 Elasticsearch 集群运行的实际操作。但这就是问题所在:我通常会遇到如下错误:

Traceback (most recent call last):
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/site-packages/urllib3/connectionpool.py", line 672, in urlopen
    chunked=chunked,
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/site-packages/urllib3/connectionpool.py", line 376, in _make_request
    self._validate_conn(conn)
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/site-packages/urllib3/connectionpool.py", line 994, in _validate_conn
    conn.connect()
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/site-packages/urllib3/connection.py", line 394, in connect
    ssl_context=context,
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/site-packages/urllib3/util/ssl_.py", line 370, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/ssl.py", line 407, in wrap_socket
    _context=self, _session=session)
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/ssl.py", line 817, in __init__
    self.do_handshake()
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/ssl.py", line 1077, in do_handshake
    self._sslobj.do_handshake()
  File "/Users/jeromepin/.asdf/installs/python/3.6.9/lib/python3.6/ssl.py", line 689, in do_handshake
    self._sslobj.do_handshake()
ConnectionResetError: [Errno 54] Connection reset by peer

我最好的猜测是在调用 Elasticsearch 期间端口转发被中断(虽然它不应该),意外终止连接。

如果我在另一个 shell 中手动运行端口转发并发出我的 CLI 命令(没有任何 pre_command),一切都会像魅力一样工作。

如果这不是运行 shell 命令的好方法,我也愿意接受建议。

标签: pythonlinuxnetworkingkubernetes

解决方案


推荐阅读