curl 命令常见用法

环境信息

  • Centos 7 3.10.0-1062

curl 命令示例

常见选项

选项 说明 示例
-v 输出详细信息
-0 内容输出到指定文件或设备 curl -o /dev/null
-s 不输出任何信息(http 响应内容除外)
-w 自定义输出内容 curl -s -o /dev/null -w %{http_code} https://csms.tech
-I 只获取响应头部信息 curl -I https://csms.tech
--resolve yourdomain.com:443:source_ip domain:port 解析为指定的 IP 使用方法参考
curl -v -H "Host: admin.test.com" --resolve admin.test.com:443:52.52.2.9 https://admin.test.com
-H, --header 自定义 http 请求头部 -H "Host: admin.test.com"

输出响应状态码

curl -s -o /dev/null -w %{http_code} https://csms.tech

只获取响应头部

curl -I csms.tech

常见用法示例

使用 curl 定位多层跨域问题

线上域名前面使用了 Nginx 反向代理和 CDN,Nginx 上面配置了允许跨域,在域名使用过程中前段页面报跨域错误,错误信息如下图

主要报错:The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.,这个问题原因是域名请求的响应中包含了多层跨域配置,使用 curl 请求响应信息如下

# curl -I api.mydomain.com
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: api.mydomain.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html
< Content-Length: 137
< Last-Modified: Wed, 01 Nov 2023 02:20:00 GMT
< ETag: "6541b5d0-89"
< Accept-Ranges: bytes
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS
< Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization
< Access-Control-Max-Age: 1728000
< Date: Thu, 16 Nov 2023 03:04:52 GMT
< Connection: keep-alive
< Access-Control-Allow-Headers: *
< Access-Control-Allow-Methods: 'GET, POST, OPTIONS'
< Access-Control-Allow-Origin: *
<

以上请求的响应中,跨域相关配置 Access-Control-Allow-* 有 2 个,形成了多层跨域配置。这种情况是因为请求响应经过的多个节点都配置了跨域相关参数,可能配置跨域参数的地方一般包括服务端(代码),反代,CDN 等。本示例中已知 Nginx 反代配置了跨域选项。为了定位到另一个跨域配置的来源,可以参考以下思路及命令

  1. 确定跨越配置是否来自服务端(代码框架)。为了实现此目的,可以在服务端直接请求响应,使响应不经过反代及 CDN。参考命令如下
    # curl -v -I "Host: api.mydomain.com" --resolve api.mydomain.com:80:127.0.0.1 http://api.mydomain.com
    * Expire in 0 ms for 6 (transfer 0x55c2a4a1a0f0)
    * Added api.mydomain.com:80:127.0.0.1 to DNS cache
    * Closing connection -1
    curl: (3) URL using bad/illegal format or missing URL
    * Expire in 0 ms for 6 (transfer 0x55c2a4a1a0f0)
    * RESOLVE api.mydomain.com:80 is - old addresses discarded!
    * Added api.mydomain.com:80:127.0.0.1 to DNS cache
    * Hostname api.mydomain.com was found in DNS cache
    * Trying 127.0.0.1...
    * TCP_NODELAY set
    * Expire in 200 ms for 4 (transfer 0x55c2a4a1a0f0)
    * Connected to api.mydomain.com (127.0.0.1) port 80 (#0)
    > HEAD / HTTP/1.1
    > Host: api.mydomain.com
    > User-Agent: curl/7.64.0
    > Accept: */*
    >
    < HTTP/1.1 200 OK
    HTTP/1.1 200 OK
    < Server: nginx/1.21.6
    Server: nginx/1.21.6
    < Date: Thu, 16 Nov 2023 03:34:46 GMT
    Date: Thu, 16 Nov 2023 03:34:46 GMT
    < Content-Type: text/html
    Content-Type: text/html
    < Content-Length: 137
    Content-Length: 137
    < Last-Modified: Wed, 01 Nov 2023 02:20:50 GMT
    Last-Modified: Wed, 01 Nov 2023 02:20:50 GMT
    < Connection: keep-alive
    Connection: keep-alive
    < ETag: "6541b602-89"
    ETag: "6541b602-89"
    < Accept-Ranges: bytes
    Accept-Ranges: bytes

    <
    以上命令使用 curl 将域名直接解析为本地服务器并发送请求,获得的响应为服务器直接返回,不经过上层的反代服务器及 CDN。从响应结果中可以看到服务器响应中未包含跨域配置,说明服务端未配置跨域。
  2. 确定跨越配置是否来自反代服务器。参考以下命令,将域名直接解析到反代服务器,绕过 CDN 获得响应
    # curl -v -I -H "Host: api.mydomain.com" --resolve api.mydomain.com:443:13.1.1.9 https://api.mydomain.com
    * Added api.mydomain.com:443:13.1.1.9 to DNS cache
    * About to connect() to api.mydomain.com port 443 (#0)
    * Trying 13.1.1.9...
    * Connected to api.mydomain.com (13.1.1.9) port 443 (#0)
    * Initializing NSS with certpath: sql:/etc/pki/nssdb
    * CAfile: /etc/pki/tls/certs/ca-bundle.crt
    CApath: none
    * SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    * Server certificate:
    * subject: CN=aapp.b3b5b07.com
    * start date: Sep 08 00:00:00 2023 GMT
    * expire date: Sep 07 23:59:59 2024 GMT
    * common name: aapp.b3b5b07.com
    * issuer: CN=Sectigo RSA Domain Validation Secure Server CA,O=Sectigo Limited,L=Salford,ST=Greater Manchester,C=GB
    > HEAD / HTTP/1.1
    > User-Agent: curl/7.29.0
    > Accept: */*
    > Host: api.mydomain.com
    >
    < HTTP/1.1 200 OK
    HTTP/1.1 200 OK
    < Date: Thu, 16 Nov 2023 03:40:54 GMT
    Date: Thu, 16 Nov 2023 03:40:54 GMT
    < Content-Type: text/html
    Content-Type: text/html
    < Content-Length: 137
    Content-Length: 137
    < Connection: keep-alive
    Connection: keep-alive
    < Last-Modified: Wed, 01 Nov 2023 02:20:00 GMT
    Last-Modified: Wed, 01 Nov 2023 02:20:00 GMT
    < ETag: "6541b5d0-89"
    ETag: "6541b5d0-89"
    < Accept-Ranges: bytes
    Accept-Ranges: bytes
    < Strict-Transport-Security: max-age=15724800; includeSubDomains
    Strict-Transport-Security: max-age=15724800; includeSubDomains
    < Access-Control-Allow-Origin: *
    Access-Control-Allow-Origin: *
    < Access-Control-Allow-Credentials: true
    Access-Control-Allow-Credentials: true
    < Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS
    Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS
    < Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization
    Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization
    < Access-Control-Max-Age: 1728000
    Access-Control-Max-Age: 1728000
    从以上输出的响应中,可以看到,已经有了跨域的配置,这个配置来自反代服务器。
  3. 直接请求域名,因为域名配置了 CDN 加速,直接请求获得的响应是经过 CDN 返回
    # curl -v api.mydomain.com
    * About to connect() to api.mydomain.com port 80 (#0)
    * Trying 23.192.228.90...
    * Connected to api.mydomain.com (23.192.228.90) port 80 (#0)
    > GET / HTTP/1.1
    > User-Agent: curl/7.29.0
    > Host: api.mydomain.com
    > Accept: */*
    >
    < HTTP/1.1 200 OK
    < Content-Type: text/html
    < Content-Length: 137
    < Last-Modified: Wed, 01 Nov 2023 02:20:00 GMT
    < ETag: "6541b5d0-89"
    < Accept-Ranges: bytes
    < Access-Control-Allow-Origin: *
    < Access-Control-Allow-Credentials: true
    < Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS
    < Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization
    < Access-Control-Max-Age: 1728000
    < Date: Thu, 16 Nov 2023 03:04:52 GMT
    < Connection: keep-alive
    < Access-Control-Allow-Headers: *
    < Access-Control-Allow-Methods: 'GET, POST, OPTIONS'
    < Access-Control-Allow-Origin: *
    以上直接请求 CDN 域名的响应结果中,包含了两层跨域。

经过以上步骤,基本可以判断,本示例中的两层跨域配置分别来自于反代服务器和 CDN 配置。要解决此问题,只需要 在反代服务器或者 CDN 上取消跨域,只保持一个节点有跨域配置即可

常见错误

SSL_ERROR_BAD_CERT_DOMAIN

环境信息

  • Centos7 5.4.225-1
  • curl 7.29.0
$ curl --version
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.53.1 zlib/1.2.7 libidn/1.28 libssh2/1.8.0
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz unix-sockets

使用以下 curl 命令直接访问服务器来验证域名证书

$ curl -v -H "Host: admin.test.com" https://52.52.2.9
* About to connect() to 52.52.2.9 port 443 (#0)
* Trying 52.52.2.9...
* Connected to 52.52.2.9 (52.52.2.9) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* Server certificate:
* subject: CN=admin.test.com
* start date: Mar 14 00:00:00 2023 GMT
* expire date: Mar 13 23:59:59 2024 GMT
* common name: admin.test.com
* issuer: CN=Sectigo RSA Domain Validation Secure Server CA,O=Sectigo Limited,L=Salford,ST=Greater Manchester,C=GB
* NSS error -12276 (SSL_ERROR_BAD_CERT_DOMAIN)
* Unable to communicate securely with peer: requested domain name does not match the server's certificate.
* Closing connection 0
curl: (51) Unable to communicate securely with peer: requested domain name does not match the server's certificate.

结果显示,请求的域名和服务器中的域名证书不匹配(requested domain name does not match the server's certificate.),通过浏览器直接访问域名(可以将域名和其对应 IP 写入系统 hosts 文件),显示证书正常,使用 openssl s_client 命令验证证书,结果也显示正常

$ echo | openssl s_client -servername  admin.test.com -connect 52.52.2.9:443
CONNECTED(00000003)
depth=3 C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services
verify return:1
depth=2 C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
verify return:1
depth=1 C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
verify return:1
depth=0 CN = admin.test.com
verify return:1
---
Certificate chain
0 s:/CN=admin.test.com
i:/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Domain Validation Secure Server CA
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Domain Validation Secure Server CA
i:/C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
2 s:/C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
i:/C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGQTCCBSmgAwIBAgIRAMrTCHWnCEPDYFZcToXLKC8wDQYJKoZIhvcNAQELBQAw
gY8xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE3MDUGA1UE
AxMuU2VjdGlnbyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD
...
Srqh+IFfIKzcHX1eyPxluInUGxxHhVVPeLdzBGL2owLJ/u7YxMkmaiCaCZc9Tugt
1aX61uQWmAUM1I4IhPCj1qKNWt94
-----END CERTIFICATE-----
subject=/CN=admin.test.com
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Domain Validation Secure Server CA
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 5278 bytes and written 441 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: 40CFB3F53E5143F85E260CE777CEB6885A184401654EE71CB386FD5D3679D822
Session-ID-ctx:
Master-Key: 4FBB5C03A77D33AD14326C272F6D7A61528DA39763067EC27D21FFF13B16CDC71CEBCCF3E8443E5961AC7887F272D3CC
Key-Arg : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
0000 - c1 a5 66 e3 d5 68 a7 c5-02 29 03 60 12 7d 74 bf ..f..h...).`.}t.
0010 - fe 85 25 0f 76 8a 63 59-9c c7 f2 d4 15 5c 95 fb ..%.v.cY.....\..
0020 - 37 5b 48 d2 74 45 e5 c5-8b af 09 8a 19 14 69 ea 7[H.tE........i.
0030 - cd 23 52 9b a9 e2 2c cb-0d ab 31 9e a9 b4 5f fd .#R...,...1..._.
0040 - f9 ce bd b3 f8 68 0e 76-56 f8 76 a0 6b b2 85 93 .....h.vV.v.k...
0050 - 49 1e a6 61 16 17 73 b5-2c c9 69 53 a1 b3 b2 bf I..a..s.,.iS....
0060 - 2c 74 7d 4d a5 c2 8d 00-1f 59 ce a5 c3 13 22 0a ,t}M.....Y....".
0070 - eb 85 33 33 a3 26 32 eb-38 1a 0c 16 c6 74 cb 16 ..33.&2.8....t..
0080 - 34 2d 57 5c b7 3b 3b 68-22 23 4f 6f 52 d3 4f 3f 4-W\.;;h"#OoR.O?
0090 - e9 6b 87 3b 2a da 2f 8f-4d 21 32 e2 c9 d4 3c 01 .k.;*./.M!2...<.
00a0 - f7 96 36 1f 73 39 8c 80-b9 86 aa 01 b6 7b 57 40 ..6.s9.......{W@
00b0 - 49 c1 ec 17 96 18 3c 65-2e 10 18 b5 3a 14 5d c9 I.....<e....:.].

Start Time: 1683609320
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
DONE

由以上判断可得出结论,域名配置的证书没问题,应该是 curl 的问题。正确命令如下

$ curl -v -H "Host: admin.test.com" --resolve admin.test.com:443:52.52.2.9 https://admin.test.com
* Added admin.test.com:443:52.52.2.9 to DNS cache
* About to connect() to admin.test.com port 443 (#0)
* Trying 52.52.2.9...
* Connected to admin.test.com (52.52.2.9) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=admin.test.com
* start date: Mar 14 00:00:00 2023 GMT
* expire date: Mar 13 23:59:59 2024 GMT
* common name: admin.test.com
* issuer: CN=Sectigo RSA Domain Validation Secure Server CA,O=Sectigo Limited,L=Salford,ST=Greater Manchester,C=GB
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> Host: admin.test.com
>
< HTTP/1.1 404 Not Found
< Server: nginx
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Vary: Accept-Encoding
< X-Powered-By: PHP/7.4.13
< Cache-Control: no-cache, private
< date: Tue, 09 May 2023 06:01:16 GMT
<
* Connection #0 to host admin.test.com left intact

Bad Request: chat_id is empty

在执行以下命令向 telegram 发送消息时,返回了错误消息 : {"ok":false,"error_code":400,"description":"Bad Request: chat_id is empty"}

$ curl -v https://api.telegram.org/bot568321111:AAHza111111111111Xcs2I/sendMessage?text=hello&chat_id=-10018411111777

> GET /bot568321111:AAHza111111111111Xcs2I/sendMessage?text=hello HTTP/1.1
> User-Agent: curl/7.29.0
> Host: api.telegram.org
> Accept: */*
>
< HTTP/1.1 400 Bad Request
< Server: nginx/1.18.0
< Date: Fri, 02 Jun 2023 02:17:27 GMT
< Content-Type: application/json
< Content-Length: 75
< Connection: keep-alive
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
< Access-Control-Allow-Origin: *
< Access-Control-Expose-Headers: Content-Length,Content-Type,Date,Server,Connection
<
* Connection #0 to host api.telegram.org left intact
{"ok":false,"error_code":400,"description":"Bad Request: chat_id is empty"}

根据 curl 打印的详细的请求和响应头部信息,可以看到发送的 url 存在问题,ulr 中的 chat_id=-10018411111777 实际并未被发送,url 变成了 /bot5683237521:AAHzaGf0oRg8A3RiYeM_QOxwW8yUyEXcs2I/sendMessage?text=hello。这可能是因为 curl 未正确处理 URL 导致,可以将 url 放置在 "" 中。

$ curl -v "https://api.telegram.org/bot568321111:AAHza111111111111Xcs2I/sendMessage?text=hello&chat_id=-10018411111777"

> GET /bot568321111:AAHza111111111111Xcs2I/sendMessage?text=hello&chat_id=-10018411111777 HTTP/1.1
> User-Agent: curl/7.29.0
> Host: api.telegram.org
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.18.0
< Date: Fri, 02 Jun 2023 02:29:54 GMT
< Content-Type: application/json
< Content-Length: 273
< Connection: keep-alive
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET, POST, OPTIONS
< Access-Control-Expose-Headers: Content-Length,Content-Type,Date,Server,Connection
<
* Connection #0 to host api.telegram.org left intact
{"ok":true,"result":{"message_id":5,"sender_chat":{"id":-10018411111777,"title":"Alert Manager Test","username":"ttydddrrr","type":"channel"},"chat":{"id":-10018411111777,"title":"Alert Manager Test","username":"ttydddrrr","type":"channel"},"date":1685672994,"text":"hello"}}

SSL_ERROR_RX_RECORD_TOO_LONG

命令及输出如下

# curl -v -u elastic1:XhScf5JqwVsSQwHe= -XGET 'https://172.31.25.229:9200/_cluster/health'
* About to connect() to 172.31.25.229 port 9200 (#0)
* Trying 172.31.25.229...
* Connected to 172.31.25.229 (172.31.25.229) port 9200 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* NSS error -12263 (SSL_ERROR_RX_RECORD_TOO_LONG)
* SSL received a record that exceeded the maximum permissible length.
* Closing connection 0
curl: (35) SSL received a record that exceeded the maximum permissible length.

以上报错原因可能为 在没有启用 SSL/TLS 的端口上尝试使用 HTTPS

SEC_ERROR_UNKNOWN_ISSUER

Docker 私有镜像仓库 Harbor 的证书到期后,使用云平台申请的证书更换,部署到服务器后,浏览器访问 HTTPS 正常,使用 `curl` 命令访问失败,使用 `docker` 拉取镜像失败,Kubernetes 中拉取镜像失败,相关命令及输出如下
# curl -v -I https://harbor1.mydomain.com/
* About to connect() to harbor1.mydomain.com port 443 (#0)
* Trying 172.31.93.6...
* Connected to harbor1.mydomain.com (172.31.93.6) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* Server certificate:
* subject: CN=harbor1.mydomain.com
* start date: Nov 15 00:00:00 2023 GMT
* expire date: Nov 14 23:59:59 2024 GMT
* common name: harbor1.mydomain.com
* issuer: CN=RapidSSL TLS RSA CA G1,OU=www.digicert.com,O=DigiCert Inc,C=US
* NSS error -8179 (SEC_ERROR_UNKNOWN_ISSUER)
* Peer's Certificate issuer is not recognized.
* Closing connection 0
curl: (60) Peer's Certificate issuer is not recognized.
More details here: http://curl.haxx.se/docs/sslcerts.html

# docker pull harbor1.mydomain.com/ops/all/cloud-server:master-0.0-20230207143540
Error response from daemon: Get "https://harbor1.mydomain.com/v2/": x509: certificate signed by unknown authority

# kubectl describe pod -n ops get-cloud-cdn-pjfsc-hwnpp
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 22s default-scheduler Successfully assigned ops/get-cloud-cdn-pjfsc-hwnpp to fm-k8s-c1-worker1
Normal BackOff 21s kubelet Back-off pulling image "harbor1.mydomain.com/ops/all/cloud-server-cdn-statistics-code:master-0.0-20230207143540"
Warning Failed 21s kubelet Error: ImagePullBackOff
Normal Pulling 6s (x2 over 21s) kubelet Pulling image "harbor1.mydomain.com/ops/all/cloud-server-cdn-statistics-code:master-0.0-20230207143540"
Warning Failed 6s (x2 over 21s) kubelet Failed to pull image "harbor1.mydomain.com/ops/all/cloud-server-cdn-statistics-code:master-0.0-20230207143540": rpc error: code = Unknown desc = failed to pull and unpack image "harbor1.mydomain.com/ops/all/cloud-server-cdn-statistics-code:master-0.0-20230207143540": failed to resolve reference "harbor1.mydomain.com/ops/all/cloud-server-cdn-statistics-code:master-0.0-20230207143540": failed to do request: Head "https://harbor1.mydomain.com/v2/ops/all/cloud-server-cdn-statistics-code/manifests/master-0.0-20230207143540": x509: certificate signed by unknown authority
Warning Failed 6s (x2 over 21s) kubelet Error: ErrImagePull

此问题的主要原因为操作系统层面没有所使用证书的 CA 信息,因此无法验证此证书的合法性。解决办法为刷新操作系统 CA 证书列表,添加异常域名的 CA 信息。操作步骤参考以下过程(本示例基于 Centos7,不同操作系统步骤存储 CA 的位置可能不同),此操作 需要在所有使用此域名的主机系统上进行更新(比如所有的 Kubernetes 节点上)

  1. 将异常域名的证书(如 domain.crt此处的证书一定要确保是 PEM 格式的证书,如果不是 PEM 格式的证书,需要将其转换为 PEM 格式)复制到 /etc/pki/ca-trust/source/anchors/ 目录下,如果不存在此目录,可以手动创建
  2. 更新操作系统证书存储信息,执行命令 update-ca-trust
  3. 重启 Docker 或其他容器运行时,执行命令 systemctl restart docker
  4. 重新执行命令,验证证书。