将kubectl cp转换为Kubernetes Python客户端代码时遇类型错误求助
Let's break down the issue and fix it step by step:
The Root Cause
In Python 3, tar_buffer.read() returns a binary bytes object, but the older version of Kubernetes Python Client (matching your Kubernetes 1.13 cluster) uses a websocket client that tries to concatenate a string (the channel identifier) with your binary data when writing to stdin. This causes the TypeError you're seeing.
Solution 1: Use Base64 Encoding (Recommended)
We'll modify the command running in the Pod to decode base64 input, then encode our tar data as base64 strings before sending. This avoids type mismatches while preserving the binary tar content.
Here's the updated code:
from kubernetes import client, config from kubernetes.stream import stream import tarfile from tempfile import TemporaryFile import base64 import os # Add this to handle file names # Load config and initialize API config.load_kube_config() api_instance = client.CoreV1Api() # Modified command: decode base64 input before passing to tar exec_command = ['sh', '-c', 'base64 -d | tar xvf - -C /'] resp = stream(api_instance.connect_get_namespaced_pod_exec, "nginx-deployment-6bb6554bf-9sdtr", 'default', command=exec_command, stderr=True, stdin=True, stdout=True, tty=False, _preload_content=False) source_file = '/tmp/abc.txt' with TemporaryFile() as tar_buffer: with tarfile.open(fileobj=tar_buffer, mode='w') as tar: # Use arcname to avoid creating /tmp/ in the Pod (optional but recommended) tar.add(source_file, arcname=os.path.basename(source_file)) tar_buffer.seek(0) # Encode binary tar data to base64 string tar_data = base64.b64encode(tar_buffer.read()).decode('utf-8') commands = [tar_data] while resp.is_open(): resp.update(timeout=1) if resp.peek_stdout(): print("STDOUT: %s" % resp.read_stdout()) if resp.peek_stderr(): print("STDERR: %s" % resp.read_stderr()) if commands: c = commands.pop(0) resp.write_stdin(c) else: break resp.close()
Key Changes:
- Updated Exec Command: We wrap the
tarcommand in a shell pipeline that decodes base64 input first. - Base64 Encoding: Convert the binary tar data to a UTF-8 encoded base64 string before sending to stdin.
- Arcname Fix: Added
arcname=os.path.basename(source_file)to ensure the file is placed directly in/of the Pod, instead of recreating the/tmp/directory structure from your local machine (adjust this if you want to preserve the original path).
Why This Works
By encoding the binary tar data as a base64 string, we're passing a valid UTF-8 string to write_stdin, which plays nicely with the client's websocket code that concatenates it with the channel identifier string. The Pod then decodes the string back to binary before passing it to tar.
内容的提问来源于stack exchange,提问作者Prafull Ladha

