[root@k8s-worker ~]# ps -ef | grep harbor
10000 218032 217960 0 15:46 ? 00:00:03 /home/harbor/harbor_registryctl -c /etc/registryctl/config.yml
10000 218334 218314 2 15:46 ? 00:00:21 /harbor/harbor_core
10000 218835 218806 2 15:46 ? 00:00:27 /harbor/harbor_jobservice -c /etc/jobservice/config.yml
root 232919 93404 0 16:02 pts/0 00:00:00 grep --color=auto harbor
vi/etc/hosts[root@k8s-worker ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.0.68 k8s-master
192.168.0.69 k8s-worker harbor.test.comfind / -name "*harbor.yml*"[root@k8s-worker ~]# netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 775/sshd
tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 823/kubelet
tcp 0 0 127.0.0.1:10249 0.0.0.0:* LISTEN 1355/kube-proxy
tcp 0 0 127.0.0.1:1514 0.0.0.0:* LISTEN 217653/docker-proxy
tcp 0 0 127.0.0.1:39243 0.0.0.0:* LISTEN 216752/containerd
tcp 0 0 127.0.0.1:9099 0.0.0.0:* LISTEN 2059/calico-node
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1/systemd
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 218487/docker-proxy
tcp 0 0 0.0.0.0:179 0.0.0.0:* LISTEN 2384/bird
tcp6 0 0 :::22 :::* LISTEN 775/sshd
tcp6 0 0 :::10250 :::* LISTEN 823/kubelet
tcp6 0 0 :::111 :::* LISTEN 1/systemd
tcp6 0 0 :::80 :::* LISTEN 218502/docker-proxy
tcp6 0 0 :::10256 :::* LISTEN 1355/kube-proxy 포트확인을 해야 docker login이 될수있음./etc/docker/daemon.json에 등록하지 않았을경우, 해당파일을 확인하는것도 방법임)

ctr --debug images pull <레지스트리 도메인 / 프로젝트 / 이미지명:태그> [root@k8s-worker certs]# ctr --debug images pull harbor.test.com/jupiter/nginx:250702
DEBU[0000] fetching image="harbor.test.com/jupiter/nginx:250702"
DEBU[0000] resolving host=harbor.test.com
DEBU[0000] do request host=harbor.test.com request.header.accept="application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, */*" request.header.user-agent=containerd/v1.7.13 request.method=HEAD url="https://harbor.test.com/v2/jupiter/nginx/manifests/250702"
INFO[0000] trying next host error="failed to do request: Head \"https://harbor.test.com/v2/jupiter/nginx/manifests/250702\": tls: failed to verify certificate: x509: certificate signed by unknown authority" host=harbor.test.com
ctr: failed to resolve reference "harbor.test.com/jupiter/nginx:250702": failed to do request: Head "https://harbor.test.com/v2/jupiter/nginx/manifests/250702": tls: failed to verify certificate: x509: certificate signed by unknown authority

tls: failed to verify certificate: x509: certificate signed by unknown authority
요청 과정
- harbor.test.com 이게 누구냐? → DNS로 IP를 찾음
- https://harbor.test.com/... 로 요청을 보냄 (HTTPS)
- 서버(Harbor)가 인증서를 줌 → harbor.test.com.crt 같은 거
- containerd가 인증서를 확인함 → "이거 누가 발급했는지 신뢰할 수 있어?"
- "신뢰 못해. 이미지 못 받아옴!"
즉 현재 에러는 harbor에 인증서는 잘 적용되어있으나 containerd쪽에는 인증서가 등록 및 적용이 되어있지 않아 발생한 에러
Harbor의 자체 서명 인증서를 신뢰하게 하려면 harbor, containerd 두곳에는 최소한 인증서가 적용되어야 한다.
| 위치 | 의미 |
|---|---|
/etc/harbor/ssl/harbor.test.com.crt | Harbor HTTPS 서버 인증서 (서버에 보여주는 증명서) |
/etc/harbor/ssl/harbor.test.com.key | Harbor 서버 개인 키 |
/etc/harbor/ssl/ca.crt | (선택) 클라이언트 인증서 체인을 보여줄 때 포함될 CA |

Kubernetes 노드에서 containerd가 Harbor 인증서를 신뢰하게 하려면 여기에 등록해야 함
| 위치 | 설명 |
|---|---|
/etc/containerd/certs.d/harbor.test.com:443/ca.crt | containerd가 Harbor 서버 인증서를 신뢰하도록 등록하는 위치 |
containerd의 /etc/containerd/certs.d/ 하위 디렉토리 이름은 반드시 <레지스트리 주소(dns):포트> 형식으로 정확히 일치해야 한다.
/etc/containerd/certs.d/<레지스터리> 하위에 인증서가 있어야 하는데 ca.crt 방식 , hosts.toml 방식 두가지 방식으로 인증서를 처리할 수 있다.
# 디렉토리 생성 (정확한 도메인:포트)
sudo mkdir -p /etc/containerd/certs.d/harbor.test.com:443/
# 인증서 복사
sudo cp /etc/harbor/ssl/ca.crt /etc/containerd/certs.d/harbor.test.com:443/ca.crt
# containerd 재시작
sudo systemctl restart containerd
[root@k8s-worker ~]# sudo mkdir -p /etc/containerd/certs.d/harbor.test.com/
[root@k8s-worker ~]# cat <<EOF | sudo tee /etc/containerd/certs.d/harbor.test.com/hosts.toml
> server = "https://harbor.test.com"
>
> [host."https://harbor.test.com"]
> capabilities = ["pull", "resolve", "push"]
> skip_verify = true
> EOF
/etc/containerd/config.toml 수정 vi /etc/containerd/config.toml
154 [plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime.options]
155
156 [plugins."io.containerd.grpc.v1.cri".image_decryption]
157 key_model = "node"
158
159 [plugins."io.containerd.grpc.v1.cri".registry]
160 config_path = "/etc/containerd/certs.d"
161
grep -A 5 "registry\]" /etc/containerd/config.toml
적용후 에러
[host."https://harbor.test.com"]
capabilities = ["pull", "resolve", "push"]
skip_verify = true
[root@k8s-worker ~]# sudo systemctl restart containerd
[root@k8s-worker ~]# ctr images pull harbor.test.com/jupiter/nginx:250702
harbor.test.com/jupiter/nginx:250702: resolving |--------------------------------------|
elapsed: 0.3 s total: 0.0 B (0.0 B/s)
harbor.test.com/jupiter/nginx:250702: resolving |--------------------------------------|
elapsed: 0.5 s total: 0.0 B (0.0 B/s)
ctr: failed to resolve reference "harbor.test.com/jupiter/nginx:250702": failed to do request: Head "https://harbor.test.com/v2/jupiter/nginx/manifests/250702": tls: failed to verify certificate: x509: certificate signed by unknown authority

[root@k8s-worker harbor.test.com]# cat hosts.toml
server = "https://harbor.test.com"
[host."https://harbor.test.com"]
capabilities = ["pull", "resolve", "push"]
skip_verify = true
override_path = true ## containerd 1.7.x에서 중요
containerd버전 문제인지 host.toml skip_verify를 인식하지 못해 결국 시스템에 인증서를 적용시킴
cp /etc/harbor/ssl/ca.crt /etc/pki/ca-trust/source/anchors/harbor-ca.crtcp /etc/harbor/ssl/ca-chain.crt /etc/pki/ca-trust/source/anchors/harbor-ca-chain.crupdate-ca-trust
https로 pull 성공
[root@k8s-master containerd]# sed -i 's/config_path = ""/config_path = "\/etc\/containerd\/certs.d"/' /etc/containerd/config.toml
[root@k8s-master containerd]# grep config_path /etc/containerd/config.toml
config_path = "/etc/containerd/certs.d"
plugin_config_path = "/etc/nri/conf.d"
config_path = "/etc/containerd/certs.d"
[root@k8s-master containerd]#
[root@k8s-master containerd]# mkdir -p /etc/containerd/certs.d/harbor.test.com
[root@k8s-master containerd]#
[root@k8s-master containerd]# cat > /etc/containerd/certs.d/harbor.test.com/hosts.toml << 'EOF'
> server = "https://harbor.test.com"
>
> [host."https://harbor.test.com"]
> capabilities = ["pull", "resolve", "push"]
> skip_verify = true
> EOF
[root@k8s-master containerd]# systemctl restart containerd
[root@k8s-master containerd]# sleep 5
[root@k8s-master containerd]# nerdctl pull harbor.test.com/jupiter/nginx:250702
harbor.test.com/jupiter/nginx:250702: resolved |++++++++++++++++++++++++++++++++++++++|
manifest-sha256:ccde53834eab53e85b35526a647cdb714ea4521b1ddf5a07b5c8787298d13087: exists |++++++++++++++++++++++++++++++++++++++|
config-sha256:9592f5595f2b12c2ede5d2ce9ec936b33fc328225a00b3901b96019e3dd83528: exists |++++++++++++++++++++++++++++++++++++++|
elapsed: 0.9 s total: 0.0 B (0.0 B/s)
[root@k8s-master containerd]# vi /etc/con
conntrackd/ containerd/
[root@k8s-master containerd]# vi /etc/containerd/config.toml c
2 files to edit
nerdctl로 pull 성공

만약 ctr로 pull이 안될경우:
# ctr에 hosts-dir 명시적으로 지정
ctr --debug images pull --hosts-dir /etc/containerd/certs.d harbor.test.com/jupiter/nginx:250702
