python - Python kubernetes 客户端请求因“无法获取本地颁发者证书”而失败
问题描述
我正在使用受支持的 python Kubernetes 库(pip install kubernetes
,v12.0.1)。当我向我的集群请求任何选项(例如创建一个Namespace
)时,它会失败并出现以下错误:
import kubernetes.client
def create_namespace(self, namespace_key):
with kubernetes.client.ApiClient(self.configuration) as client:
api = kubernetes.client.CoreV1Api(client)
api.create_namespace(
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"name": namespace_key,
},
}
)
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='<url of my cluster>', port=443): Max retries exceeded with url: /api/v1/namespaces (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer
certificate (_ssl.c:1123)')))
如果我在客户端中使用关闭 SSL 配置self.configuration.verify_ssl = False
,请求会起作用,但它会给我一个警告,告诉我强烈建议不要禁用 SSL。
我的设置:
- Ubuntu 20.04.1 LTS(在 mac OSX 上的虚拟机中运行)
- Python 3.8.5(虚拟环境,没有 pyenv 或 pipenv)
- virtualenv 已
certifiy==2020.11.8
安装(不确定这是否会影响 SSL 交互)
我需要在本地和/或最终将在生产中运行这些请求的 docker 容器在系统范围内执行什么操作吗?
编辑 更多信息:
>>> import ssl
>>> print(ssl.OPENSSL_VERSION)
OpenSSL 1.1.1f 31 Mar 2020
解决方案
这最终是我的错误:我的托管 Kubernetes 提供商(Digital Ocean)提供了一个带有 Kubernetes 凭据的自定义 TLS 证书,并且需要用作 k8s python 客户端的证书。
通常,如果您的客户端中使用的证书与 k8s API 的预期不匹配,那么无论托管服务提供商如何,您都可能会看到这一点。
具体来说,这就是我解决 Digital Ocean 问题的方法:
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {DIGITAL_OCEAN_ACCESS_TOKEN}",
}
url = (
f"https://api.digitalocean.com/v2/kubernetes/clusters/{cluster_id}/credentials"
)
response = requests.get(url, headers=headers)
data = json.loads(response.content.decode("utf-8"))
if response.status_code != 200:
raise Exception(f"Unable to authenticate to cluster {cluster_id}")
my_clusters_host_url = data["server"]
my_new_api_key = data["token"]
# Decode and save certificate
decoded_certificate = base64.b64decode(data["certificate_authority_data"])
certificate_authority_data = str(decoded_certificate, "utf-8")
据我所知,客户端不允许您直接设置证书数据;它需要保存到文件中。所以我在下面创建了一个 tmp 文件:
filepath = f"/tmp/cluster_{cluster.id}.crt"
with open(filepath, "w+") as f:
f.write(certificate_authority_data)
configuration = kubernetes.client.Configuration(
host=host_url,
api_key={
"authorization": f"Bearer {api_key}",
},
)
configuration.ssl_ca_cert = filepath
然后可以在其他 API 请求中使用该配置对象。例如:
with kubernetes.client.ApiClient(configuration) as client:
api = kubernetes.client.CoreV1Api(client)
api.create_namespace(payload)
推荐阅读
- c# - 如何在仅使用 3 个 for 循环时优化此问题?
- python - 如何在不获取 ValueError 的情况下访问类的根属性
- ado - 如何禁用 ODBC 连接向导
- r - 从 r 数据帧生成加权矩阵
- sql - 如何在只有所有子查询都为真的情况下返回匹配的列值
- java - 将给定数组的所有子数组存储在 ArrayList 的 ArrayList 中,并显示 ArrayList 的内容
- filtering - 电机对 IMU 的影响
- ios - 使用 ios-charts 为 LineChartData 标签设置背景颜色和空间/填充
- python - Python: How can I get lower 95% confidence interval using Kaplan-Meier estimate for survival curve estimate
- http - 如何获取整个 http 请求行?