配置pod拉取harbor容器映象倉庫私有映象:secret儲存賬號密碼

人生的哲理發表於2024-06-24

目錄
  • 一.系統環境
  • 二.前言
  • 三.Docker-Registry型別的Secret簡介
  • 四.映象倉庫簡介
  • 五.搭建Harbor容器映象倉庫
    • 5.1 安裝Harbor
    • 5.2 建立專案
    • 5.3 推送映象到harbor映象倉庫
  • 六.使用secret儲存harbor賬號密碼拉取私有倉庫的映象
  • 七.總結

一.系統環境

本文主要基於Kubernetes1.22.2和Linux作業系統Ubuntu 18.04。

伺服器版本 docker軟體版本 Kubernetes(k8s)叢集版本 CPU架構
Ubuntu 18.04.5 LTS Docker version 20.10.14 v1.22.2 x86_64

Kubernetes叢集架構:k8scludes1作為master節點,k8scludes2,k8scludes3作為worker節點。

伺服器 作業系統版本 CPU架構 程序 功能描述
k8scludes1/192.168.110.128 Ubuntu 18.04.5 LTS x86_64 docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico k8s master節點
k8scludes2/192.168.110.129 Ubuntu 18.04.5 LTS x86_64 docker,kubelet,kube-proxy,calico k8s worker節點
k8scludes3/192.168.110.130 Ubuntu 18.04.5 LTS x86_64 docker,kubelet,kube-proxy,calico k8s worker節點

二.前言

在Kubernetes叢集中,為了方便管理和使用Harbor映象倉庫中的私有映象,我們可以透過配置Pod使用Secret來儲存Harbor倉庫的賬號密碼。本文將為您介紹如何配置Pod以拉取Harbor映象倉庫中的私有映象。

Harbor是一個開源的企業級Docker映象倉庫,它為Docker映象提供了一個安全的儲存和管理環境。Harbor支援私有映象倉庫和公有映象倉庫,可以透過Pod配置來使用私有映象倉庫中的映象。

使用secret儲存harbor賬號密碼拉取私有倉庫的映象的前提是已經有一套可以正常執行的Kubernetes叢集,關於Kubernetes(k8s)叢集的安裝部署,可以檢視部落格《Ubuntu 安裝部署Kubernetes(k8s)叢集》https://www.cnblogs.com/renshengdezheli/p/17632858.html。

三.Docker-Registry型別的Secret簡介

在Kubernetes中,Secret用於儲存敏感資訊,如密碼、令牌等。Docker-Registry型別的Secret用於儲存Docker映象倉庫的認證資訊,包括使用者名稱和密碼。透過使用Docker-Registry型別的Secret,我們可以將認證資訊與Pod配置關聯,使Pod能夠訪問私有映象倉庫。

Secret有很多型別,比如kubernetes.io/service-account-token型別,Opaque型別,關於secret的更多用法,請檢視部落格《Kubernetes(k8s)密碼管理:Secret》。

四.映象倉庫簡介

Harbor是一個基於Go語言開發的Docker映象倉庫,它提供了使用者管理、映象倉庫管理、映象構建等功能。Harbor映象倉庫可以透過HTTP或HTTPS協議進行訪問,使用者可以透過Docker客戶端上傳和下載映象。Harbor官網為:https://goharbor.io/ ,Harbor在GitHub的網址為:https://github.com/goharbor/harbor/ ,Harbor安裝包下載地址為:https://github.com/goharbor/harbor/releases

映象倉庫除了可以使用Harbor搭建,還可以使用registry搭建,詳情請檢視部落格《搭建docker映象倉庫(一):使用registry搭建本地映象倉庫》。

五.搭建Harbor容器映象倉庫

5.1 安裝Harbor

當我們使用harbor搭建映象倉庫,建立專案的時候,如果專案選擇公開,則人們可以使用匿名使用者拉取映象,如果專案不選擇公開,則必須要docker login登入才能拉取映象 。

下面在etcd2機器上,使用harbor搭建一個映象倉庫。

由於harbor依賴於docker-compose,所以需要先安裝docker-compose。

[root@etcd2 ~]# yum -y install docker-compose docker-ce

去網上https://github.com/goharbor/harbor/releases/tag/v2.4.1 ,下載好harbor離線包:harbor-offline-installer-v2.4.1.tgz 。

[root@etcd2 ~]# ll -th harbor-offline-installer-v2.4.1.tgz 
-rw-r--r-- 1 root root 585M 1月   5 11:39 harbor-offline-installer-v2.4.1.tgz

解壓軟體包。

[root@etcd2 ~]# tar xf harbor-offline-installer-v2.4.1.tgz

[root@etcd2 ~]# rm -rf harbor-offline-installer-v2.4.1.tgz

[root@etcd2 ~]# cd harbor

[root@etcd2 harbor]# ls
common.sh  harbor.v2.4.1.tar.gz  harbor.yml.tmpl  install.sh  LICENSE  prepare

harbor.v2.4.1.tar.gz是安裝harbor所需的映象,docker load -i 載入映象。

[root@etcd2 harbor]# docker load -i harbor.v2.4.1.tar.gz

[root@etcd2 harbor]# docker images | grep harbor
goharbor/harbor-exporter        v2.4.1     0ee361b5454a   6 months ago   82.7MB
goharbor/chartmuseum-photon     v2.4.1     337a9d03b197   6 months ago   174MB
goharbor/redis-photon           v2.4.1     2bbe19b8cc5d   6 months ago   156MB
goharbor/trivy-adapter-photon   v2.4.1     d39fd42c93f0   6 months ago   151MB
goharbor/notary-server-photon   v2.4.1     e75c68b6638b   6 months ago   111MB
goharbor/notary-signer-photon   v2.4.1     17a627caf6dd   6 months ago   108MB
goharbor/harbor-registryctl     v2.4.1     bff3d2665456   6 months ago   137MB
goharbor/registry-photon        v2.4.1     b46e45c49d6f   6 months ago   79.2MB
goharbor/nginx-photon           v2.4.1     78aad8c8ef41   6 months ago   45.7MB
goharbor/harbor-log             v2.4.1     c86562daee64   6 months ago   160MB
goharbor/harbor-jobservice      v2.4.1     d8baceb5f1f6   6 months ago   220MB
goharbor/harbor-core            v2.4.1     80a4e3e60403   6 months ago   198MB
goharbor/harbor-portal          v2.4.1     1c9ed1cc3cb9   6 months ago   54.7MB
goharbor/harbor-db              v2.4.1     417d0a840247   6 months ago   222MB
goharbor/prepare                v2.4.1     e9158d34970b   6 months ago   257MB

harbor.yml.tmpl是harbor配置檔案的模版,複製模版。

[root@etcd2 harbor]# ls
common.sh  harbor.v2.4.1.tar.gz  harbor.yml.tmpl  install.sh  LICENSE  prepare

[root@etcd2 harbor]# cp harbor.yml.tmpl harbor.yml

修改harbor配置檔案harbor.yml。

harbor配置檔案harbor.yml修改內容如下:hostname修改為harbor私有倉庫所在的主機名:hostname: etcd2 ;harbor的賬號密碼為:harbor_admin_password: Harbor12345 。

[root@etcd2 harbor]# vim harbor.yml

[root@etcd2 harbor]# egrep 'hostname|harbor_admin_password' harbor.yml
# The IP address or hostname to access admin UI and registry service.
hostname: etcd2
# And when it enabled the hostname will no longer used
harbor_admin_password: Harbor12345
#   #   endpoint: http://hostname:14268/api/traces
#   #   agent_host: hostname
#   #   endpoint: hostname:4318

這裡不配置https,https的配置直接刪除或者註釋掉:# https related config#https:# # https port for harbor, default is 443# port: 443# # The path of cert and key files for nginx# certificate: /your/certificate/path# private_key: /your/private/key/path 。

image-20230809155825713

執行harbor安裝指令碼。

[root@etcd2 harbor]# ./prepare 
prepare base dir is set to /root/harbor
WARNING:root:WARNING: HTTP protocol is insecure. Harbor will deprecate http protocol in the future. Please make sure to upgrade to https
Generated configuration file: /config/portal/nginx.conf
......
Generated configuration file: /config/jobservice/config.yml
Generated and saved secret to file: /data/secret/keys/secretkey
Successfully called func: create_root_cert
Generated configuration file: /compose_location/docker-compose.yml
Clean up the input dir

#安裝harbor
[root@etcd2 harbor]# ./install.sh 

[Step 0]: checking if docker is installed ...

Note: docker version: 20.10.12
......
Creating harbor-db ... 
Creating harbor-core ... 
Creating harbor-jobservice ... 
Creating nginx ... 
✔ ----Harbor has been installed and started successfully.----

此時harbor映象倉庫就安裝成功了。

5.2 建立專案

直接在瀏覽器輸入harbor所在機器IP地址:http://192.168.110.131/,開啟主頁輸入賬號admin,密碼:Harbor12345進行登入。

image-20230809160056429

建立一個使用者:點選使用者管理-->建立使用者。

image-20230809160139391

建立一個test使用者。

image-20230809160209602

現在test使用者就建立好了。

image-20230809160238439

接著建立一個專案:點選專案-->新建專案。

image-20230809160308980

新建專案test,如果沒勾選“公開”,則專案是私有專案,使用者必須登入才能拉取映象,如果勾選了“公開”,則專案是公開專案,使用者可以匿名使用者拉取映象,"儲存容量"為-1,表示容量無上限。

image-20230809160330796

test私有專案就建立好了。

image-20230809160410943

點選進入test專案,點選成員-->使用者,把test使用者新增進來。

image-20230809160445752

把剛才建立的test使用者新增進去。

image-20230809160511951

現在test使用者就新增到test專案裡來了。

image-20230809160540945

現在test專案裡還沒有任何映象。

image-20230809160606064

5.3 推送映象到harbor映象倉庫

下面需要配置客戶端推送映象到harbor映象倉庫的test專案裡。

etcd2機器先拉取一個映象。

[root@etcd2 harbor]# docker pull busybox:latest

[root@etcd2 harbor]# docker images | grep busybox
busybox                         latest     ec3f0931a6e6   4 months ago   1.24MB

映象重新命名,命名格式:映象倉庫IP:埠/專案名/映象名.

[root@etcd2 harbor]# docker tag busybox:latest 192.168.110.131/test/busybox:latest

因為harbor映象倉庫沒有配置https,使用的是http,需要修改下配置,不然拉取映象會報錯,有兩種修改方法:

  • 方法一:修改/lib/systemd/system/docker.service的dockerd啟動引數,ExecStart=/usr/bin/dockerd --insecure-registry 192.168.110.131:80 -H fd:// --containerd=/run/containerd/containerd.sock ,--insecure-registry用於指定不安全的映象倉庫;
  • 方法二:修改 /etc/docker/daemon.json,新增引數"insecure-registries":["192.168.110.131:80"],insecure-registries 用於指定不安全的映象倉庫。

這次我們使用這第一種修改方法:

[root@etcd2 harbor]# vim /usr/lib/systemd/system/docker.service

#--insecure-registry 192.168.110.131 指定harbor映象倉庫
[root@etcd2 harbor]# grep ExecStart /usr/lib/systemd/system/docker.service
#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecStart=/usr/bin/dockerd --insecure-registry 192.168.110.131 -H fd:// --containerd=/run/containerd/containerd.sock

重新載入配置檔案,重啟docker使配置生效。

[root@etcd2 harbor]# systemctl daemon-reload ;systemctl restart docker

現在使用docker login登入harbor倉庫,輸入剛才建立的test使用者和密碼。

[root@etcd2 harbor]# docker login 192.168.110.131
Username: test
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

登入harbor倉庫之後,會多了一個/root/.docker/config.json檔案。

[root@etcd2 harbor]# ls /root/.docker/config.json
/root/.docker/config.json

Docker 會將 token 儲存在 ~/.docker/config.json 檔案中,從而作為拉取私有映象的憑證。

[root@etcd2 harbor]# cat /root/.docker/config.json
{
        "auths": {
                "192.168.110.131": {
                        "auth": "dGVzdDpIYXJib3IxMjM0NQ=="
                }
        }
}

現在推送映象到harbor映象倉庫的test專案裡。

[root@etcd2 harbor]# docker push 192.168.110.131/test/busybox:latest
The push refers to repository [192.168.110.131/test/busybox]
d31505fd5050: Pushed 
latest: digest: sha256:b69959407d21e8a062e0416bf13405bb2b71ed7a84dde4158ebafacfa06f5578 size: 527

檢視harbor web頁面。可以看到映象推送成功了。

image-20230809160920244

下面測試拉取映象到etcd2機器。

刪除本地的192.168.110.131/test/busybox:latest映象。

[root@etcd2 harbor]# docker rmi 192.168.110.131/test/busybox:latest
Untagged: 192.168.110.131/test/busybox:latest
Untagged: 192.168.110.131/test/busybox@sha256:b69959407d21e8a062e0416bf13405bb2b71ed7a84dde4158ebafacfa06f5578

[root@etcd2 harbor]# docker images | grep busy
busybox                         latest     ec3f0931a6e6   4 months ago   1.24MB

現在從harbor映象倉庫拉取映象,映象拉取成功。

[root@etcd2 harbor]# docker pull 192.168.110.131/test/busybox:latest
latest: Pulling from test/busybox
Digest: sha256:b69959407d21e8a062e0416bf13405bb2b71ed7a84dde4158ebafacfa06f5578
Status: Downloaded newer image for 192.168.110.131/test/busybox:latest
192.168.110.131/test/busybox:latest

刪除憑證。

[root@etcd2 harbor]# rm -rf /root/.docker/config.json

退出登入映象倉庫。

[root@etcd2 harbor]# docker logout 
Removing login credentials for https://index.docker.io/v1/

現在是拉取不了映象的,192.168.110.131/test/busybox:latest是私有倉庫的映象,不登入是沒方法拉取映象的,因為專案是私有的,必須登入才能拉取映象。

[root@etcd2 harbor]# docker pull 192.168.110.131/test/busybox:latest
Error response from daemon: unauthorized: unauthorized to access repository: test/busybox, action: pull: unauthorized to access repository: test/busybox, action: pull

六.使用secret儲存harbor賬號密碼拉取私有倉庫的映象

本次在k8s叢集的k8scludes3節點測試拉取私有映象。

來到k8s叢集的k8scludes3節點,編輯/lib/systemd/system/docker.service檔案,--insecure-registry 192.168.110.131 指定harbor映象倉庫。

root@k8scludes3:~# vim /lib/systemd/system/docker.service

root@k8scludes3:~# grep ExecStart /lib/systemd/system/docker.service
#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecStart=/usr/bin/dockerd --insecure-registry 192.168.110.131 -H fd:// --containerd=/run/containerd/containerd.sock

重啟docker使配置檔案生效。

root@k8scludes3:~# systemctl daemon-reload ; systemctl restart docker

拉取映象,但是報錯了,根據報錯可知,是域名解析出問題了,需要配置/etc/hosts。

root@k8scludes3:~# docker pull 192.168.110.131/test/busybox:latest
Error response from daemon: Head "http://192.168.110.131/v2/test/busybox/manifests/latest": Get "http://etcd2/service/token?scope=repository%3Atest%2Fbusybox%3Apull&service=harbor-registry": dial tcp: lookup etcd2: Temporary failure in name resolution

新增harbor倉庫所在機器的IP主機名對映:192.168.110.131 etcd2 。

root@k8scludes3:~# vim /etc/hosts

root@k8scludes3:~# cat /etc/hosts
127.0.0.1	localhost
127.0.1.1	tom
192.168.110.139 ubuntuk8sclient
192.168.110.128 k8scludes1
192.168.110.129 k8scludes2
192.168.110.130 k8scludes3
192.168.110.131 etcd2

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

重新拉取私有映象。192.168.110.131/test/busybox:latest是私有倉庫映象,不登入是沒方法拉取映象的,必須登入才能拉取映象

root@k8scludes3:~# docker pull 192.168.110.131/test/busybox:latest
Error response from daemon: unauthorized: unauthorized to access repository: test/busybox, action: pull: unauthorized to access repository: test/busybox, action: pull

下面使用私有倉庫的映象建立一個pod。

編輯pod配置檔案,表示使用私有倉庫的映象192.168.110.131/test/busybox:latest建立pod。

root@k8scludes1:~# vim pod.yaml 

root@k8scludes1:~# cat pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: podtest
  name: podtest
spec:
  #當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
  terminationGracePeriodSeconds: 0
  #nodeName: k8scludes3 表示使pod執行在k8scludes3節點
  nodeName: k8scludes3
  containers:
  - image: 192.168.110.131/test/busybox:latest
    #imagePullPolicy: IfNotPresent:表示如果本地已經存在該映象,則不重新下載;否則從遠端 Docker Hub 下載該映象
    imagePullPolicy: IfNotPresent
    #讓容器執行sleep程序,一直處於睡眠狀態
    command: ["sh","-c","sleep 100000"]
    name: podtest
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod。

root@k8scludes1:~# kubectl apply -f pod.yaml 
pod/podtest created

pod建立失敗。

root@k8scludes1:~# kubectl get pod 
NAME      READY   STATUS             RESTARTS   AGE
podtest   0/1     ImagePullBackOff   0          6s

檢視podtest描述,報錯為:unauthorized to access repository: test/busybox,因為192.168.110.131/test/busybox:latest映象是私有倉庫裡的,需要docker login登入,才能拉取映象,現在不登入,肯定拉取映象失敗。

root@k8scludes1:~# kubectl describe pod podtest 
Name:         podtest
Namespace:    admissioncontr
Priority:     0
Node:         k8scludes3/192.168.110.130
。。。。。。
Events:
  Type     Reason       Age                 From     Message
  ----     ------       ----                ----     -------
  Warning  FailedMount  2m9s                kubelet  MountVolume.SetUp failed for volume "kube-api-access-vtptj" : failed to sync configmap cache: timed out waiting for the condition
  Normal   Pulling      46s (x4 over 2m7s)  kubelet  Pulling image "192.168.110.131/test/busybox:latest"
  Warning  Failed       46s (x4 over 2m6s)  kubelet  Failed to pull image "192.168.110.131/test/busybox:latest": rpc error: code = Unknown desc = Error response from daemon: unauthorized: unauthorized to access repository: test/busybox, action: pull: unauthorized to access repository: test/busybox, action: pull
  Warning  Failed       46s (x4 over 2m6s)  kubelet  Error: ErrImagePull
  Normal   BackOff      31s (x6 over 2m6s)  kubelet  Back-off pulling image "192.168.110.131/test/busybox:latest"
  Warning  Failed       31s (x6 over 2m6s)  kubelet  Error: ImagePullBackOff

刪除pod。

root@k8scludes1:~# kubectl delete pod podtest 
pod "podtest" deleted

檢視docker-registry型別的secret幫助。

root@k8scludes1:~# kubectl create secret docker-registry --help

root@k8scludes1:~# kubectl create secret docker-registry --help | grep server
  kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
      --docker-server='https://index.docker.io/v1/': Server location for Docker registry
      --dry-run='none': Must be "none", "server", or "client". If client strategy, only print the object that would be sent, without sending it. If server strategy, submit server-side request without persisting the resource.
  kubectl create secret docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-file=[key=]source] [--dry-run=server|client|none] [options]

建立一個docker-registry型別的secret,--docker-server指定映象倉庫地址,--docker-username指定倉庫使用者名稱,--docker-password指定倉庫密碼。

root@k8scludes1:~# kubectl create secret docker-registry mysecret --docker-server=192.168.110.131 --docker-username=test --docker-password=Harbor12345
secret/mysecret created

檢視secret,這個secret包含了登入harbor映象倉庫的密碼。

root@k8scludes1:~# kubectl get secrets -o wide
NAME                  TYPE                                  DATA   AGE
default-token-lqfqc   kubernetes.io/service-account-token   3      6d9h
mysecret              kubernetes.io/dockerconfigjson        1      16s

再次編輯pod配置檔案,imagePullSecrets 指定儲存著映象倉庫密碼的secret。

root@k8scludes1:~# vim pod.yaml 

root@k8scludes1:~# cat pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: podtest
  name: podtest
spec:
  terminationGracePeriodSeconds: 0
  imagePullSecrets:
  - name: mysecret
  nodeName: k8scludes3
  containers:
  - image: 192.168.110.131/test/busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 100000"]
    name: podtest
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod。

root@k8scludes1:~# kubectl apply -f pod.yaml 
pod/podtest created

pod建立成功。

root@k8scludes1:~# kubectl get pod -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
podtest   1/1     Running   0          7s    10.244.1.68   k8scludes3   <none>           <none>

k8scludes3節點上也成功拉取了映象。

root@k8scludes3:~# docker images | grep busybox
192.168.110.131/test/busybox                         latest    ec3f0931a6e6   4 months ago    1.24MB
yauritux/busybox-curl                                latest    69894251bd3c   5 years ago     21.3MB

刪除pod。

root@k8scludes1:~# kubectl delete pod podtest 
pod "podtest" deleted

root@k8scludes1:~# kubectl get pod -o wide
No resources found in admissioncontr namespace.

七.總結

透過配置Docker-Registry型別的Secret和Pod,我們可以使Pod能夠拉取Harbor映象倉庫中的私有映象。這種方式既安全又方便,可以幫助我們在Kubernetes叢集中更好地管理和使用Harbor映象倉庫。

相關文章