github action推送-构建准备步骤获取私有dockerhub镜像仓库镜像的一系列错误尝试
注意:
这篇文章算是经验贴吧!一系列操作后最终选择放弃,有点无奈也有点不甘心。
计划在github action 执行构建准备任务时,从我自己搭建的私有dockerhub镜像仓库拉取buildkit镜像。
最后没有解决的问题是私有镜像仓库的证书问题,改来改去,最终停留在域名certificate signed by unknown authority
,所以还是搞个域名最好。但我既不想花钱也不想出力,有现成的就先用现成的了。
构建准备获取私有镜像仓库镜像错误
私有镜像仓库搭建好了之后就可以开始应用了。项目demo推送后,构建准备步骤获取私有镜像仓库里的镜像报错。
报错:
经过查看,发现服务器上的80和443端口被nginx服务占用,也存在使用caddy配置的代理。为了确保不影响上面两者的正常运行,决定使用docker安装caddy镜像,运行caddy容器代理一个自定义域名。
拉取 Caddy 镜像
通过 Docker Hub 拉取 Caddy 镜像:docker pull caddy:latest
创建自签名证书
mkdir ssl
openssl req -x509 -newkey rsa:4096 -keyout /root/k8s/ssl/registry.key -out /root/k8s/ssl/registry.crt -days 365 -nodes -subj "/CN=my-registry.xxx.com"
创建 Caddy 配置文件
# myCaddy文件内容
{auto_https off
}https://my-registry.xxx.com:1443 {reverse_proxy <your-server-ip>:5000encode gziptls /etc/caddy/ssl/registry.crt /etc/caddy/ssl/registry.key
}
运行 Caddy 容器
docker run -d --name my-caddy \-p 1443:1443 \-v /root/k8s/myCaddy:/etc/caddy/Caddyfile \-v /root/k8s/ssl:/etc/caddy/ssl \caddy:latest
查看日志:docker logs my-caddy
查看docker容器:docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
895449bb9b2b caddy:latest "caddy run --config …" About a minute ago Up About a minute 80/tcp, 443/tcp, 2019/tcp, 443/udp, 0.0.0.0:1443->1443/tcp, :::1443->1443/tcp my-caddy
...
配置 Docker 客户端
在 GitHub 自托管 Runner 所在的内网服务器上,配置 Docker 客户端使用 HTTPS 访问 Caddy 提供的地址:
- 编辑
/etc/docker/daemon.json
文件 - 添加
{ "insecure-registries": ["my-registry.xxx.com:1443"] }
内容 - 保存文件后,重启 Docker 服务:
systemctl daemon-reload && systemctl restart docker
修改pod 配置文件
完成以上步骤后,运行了一下action任务。任务报错:Error: ERROR: Error response from daemon: Get "https://my-registry.xxx.com:1443/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
。截图如下:
这个错误表明 GitHub Action Runner 在尝试连接到我的自定义 Docker 私有镜像库时遇到了超时问题。在 Pod 中运行curl -v https://my-registry.xxx.com:1443/v2/_catalog
命令输出:... Failed to connect to my-registry.xxx.com port 1443: No route to host ...
在pod的etc文件中运行:sudo sh -c 'echo "192.168.xx.xxx my-registry.xxx.com" >> /etc/hosts'
可临时解决访问不到的问题。
为了不必每次新建pod都手写配置,在deploy-web-dev-runner.yaml文件中的.spec
部分新增hostAliases
字段,指定需要添加到 /etc/hosts 文件的 IP 和主机名。
...
hostAliases:- ip: "192.168.xxx.xxx"hostnames:- "my-registry.xxx.com"
...
创建 Secret:
kubectl create secret generic my-registry-certs --from-file=/root/k8s/ssl/registry.crt --from-file=/root/k8s/ssl/registry.key -n actions-runner-system
修改pod 配置文件
在 Pod 的配置文件(YAML)中,添加 volumes 和 volumeMounts 配置,以挂载之前创建的 Secret。
...volumeMounts:...- name: my-registry-certsmountPath: /etc/ssl/registryreadOnly: truevolumes:...- name: my-registry-certssecret:secretName: my-registry-certs
(测试步骤,可跳过)添加自签名证书到受信任的 CA 证书列表中
完成以上配置后,在服务器和pod运行curl --cacert /root/k8s/ssl/registry.crt -v https://my-registry.xxx.com:1443/v2/_catalog
都可以正常输出。但是直接curl -v https://...
仍然会提示证书“SSL certificate problem: self signed certificate”。为了能正确的拉取到docker镜像,需要将证书签名添加到受信任的 CA 证书列表中。
- 获取自签名证书:你可以使用以下命令获取自签名证书:
这个命令会将证书保存到 my-registry.crt 文件中。openssl s_client -showcerts -connect my-registry.xxx.com:1443 </dev/null 2>/dev/null|openssl x509 -outform PEM > my-registry-dockhub.crt
- 添加到受信任的证书列表:将证书文件复制到系统受信任的 CA 证书目录中,并更新证书数据库:
这个命令会将证书添加到系统的受信任证书列表中,并更新证书数据库。cp my-registry.crt /usr/local/share/ca-certificates/ update-ca-certificates
- 重新运行 curl 命令:现在你可以重新运行你的 curl 命令,不需要 -k 参数:
curl https://my-registry.xxx.com:1443/v2/_catalog
经过以上操作,已经可以直接在服务器中访问docker私有镜像库了。但是在k8s的pod中,curl https://my-registry.xxx.com:1443/v2/_catalog
命令仍然会输出:
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.htmlcurl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
添加自签名证书到自定义镜像
在K8s上运行GitHub Actions的自托管运行器里面使用了自定义镜像runner执行任务,为了使任务顺利执行,需要将自定义证书放到容器里面。
在自定义镜像的dockfile文件中(self-runner-image)增加:
...
# 自定义证书
COPY registry.crt /usr/local/share/ca-certificates/registry.crt
RUN sudo update-ca-certificates
...
打包镜像,执行action任务,不再报超时问题。
安装包含SANs扩展的证书
-
检查证书链完整性:
openssl verify -CAfile /root/k8s/ssl/sans_registry.crt /root/k8s/ssl/sans_registry.crt
-
确认证书确实包含SANs扩展:
openssl x509 -in /root/k8s/ssl/sans_registry.crt -text -noout | grep -A1 "Subject Alternative Name" # 或 openssl x509 -in /root/k8s/ssl/sans_registry.crt -text -noout | grep -A 10 "X509v3 extensions"
如果没有包含SANs扩展,action执行任务时就会报错:ERROR: Error response from daemon: Get "https://my-registry.xxx.com:1443/v2/": tls: failed to verify certificate: x509: certificate relies on legacy Common Name field, use SANs instead
,截图如下:
配置文件openssl.cnf:
[req]
default_bits = 4096
default_md = sha256
prompt = no
default_days = 365
req_extensions = req_ext
distinguished_name = dn[dn]
C = CN
ST = Shanghai
L = Shanghai
CN = my-registry.xxx.com[req_ext]
subjectAltName = @alt_names[v3_req]
subjectAltName = @alt_names[alt_names]
DNS.1 = my-registry.xxx.com
DNS.2 = *.my-registry.xxx.com
IP.1 = 192.168.xx.xxx
生成证书命令:
openssl req -x509 -newkey rsa:4096 \-keyout /root/k8s/ssl/sans_registry.key \-out /root/k8s/ssl/sans_registry.crt \-days 365 -nodes \-extensions v3_req \-config /root/k8s/ssl/openssl.cnf
最后还是报错:ERROR: Error response from daemon: Get "https://my-registry.xxx.com:1443/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority
。截图如下:
certificate signed by unknown authority
这个错误是真没招了,直接改用同事搭建好的公司的私有dockerhub镜像库,成功执行。