Harbor私有镜像仓库无坑搭建

一、介绍

Docker容器应用的开发和运行路不开可靠的镜像管理,虽然Docker官方也提供了公共的镜像仓库,但是从安全和效率等方面考虑,部署我们私有环境的Registry也是非常必要的。 Harbor是由VMware公司开源的企业级的Docker Registry管理项目,它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。

二、组件

用于部署 Harbor 的 Docker Compose 模板位于 /Deployer/docker-compose.yml. 打开这个模板文件,会发现 Harbor 由 5 个容器组成:

proxy:由 Nginx 服务器构成的反向代理。
registry:由 Docker 官方的开源 registry 镜像构成的容器实例。
ui:即架构中的 core services, 构成此容器的代码是 Harbor 项目的主体。
mysql:由官方 MySql 镜像构成的数据库容器。
log: 运行着 rsyslogd 的容器,通过 log-driver 的形式收集其他容器的日志。
这几个容器通过 Docker link 的形式连接在一起,这样,在容器之间可以通过容器名字互相访问。对终端用户而言,只需要暴露 proxy (即 Nginx)的服务端口。

三、工作原理

假设我们将 Harbor 部署在主机名为 registry.abcdocker.com 的虚机上。用户通过 docker login 命令向这个 Harbor 服务发起登录请求:docker login registry.abcdocker.com当用户输入所需信息并点击回车后,Docker 客户端会向地址“registry.abcdocker.com/v2/” 发出 HTTP GET 请求。

Harbor 的各个容器会通过以下步骤处理:

(1)Docker login
(a) 首先,这个请求会由监听 80 端口的 proxy 容器接收到。根据预先设置的匹配规则,容器中的 Nginx会将请求转发给后端的 registry 容器;

(b) 在 registry 容器一方,由于配置了基于 token 的认证,registry 会返回错误代码 401,提示 Docker客户端访问 token 服务绑定的 URL。在 Harbor 中,这个 URL 指向 Core Services;

(c) Docker 客户端在接到这个错误代码后,会向token服务的URL发出请求,并根据HTTP协议的BasicAuthentication 规范,将用户名密码组合并编码,放在请求头部(header);

(d)类似地,这个请求通过 80 端口发到 proxy 容器后,Nginx 会根据规则把请求转发给 ui 容器,ui 容器监听 token 服务网址的处理程序接收到请求后,会将请求头解码,得到用户名、密码;

(e) 在得到用户名、密码后,ui 容器中的代码会查询数据库,将用户名、密码与 mysql 容器中的数据进行比对(注:ui 容器还支持 LDAP 的认证方式,在那种情况下 ui 会试图和外部 LDAP 服务进行通信并校验用户名/密码)。比对成功,ui 容器会返回表示成功的状态码, 并用密钥生成 token,放在响应体中返回给 Docker 客户端。这个过程中组件间的交互过程如下图所示

三、安装

Harbor 2种安装方式1.离线安装

$ wget https://storage.googleapis.com/harbor-releases/harbor-offline-installer-v1.5.0.tgz
$ tar xf harbor-online-installer-v1.5.0.tgz

2.在线安装
$ wget https://storage.googleapis.com/harbor-releases/harbor-online-installer-v1.5.2.tgz
$ tar xf harbor-online-installer-v1.5.2.tgz

重点:下载那个823M的安装
复制代码配置Harbor解压之后,配置文件名称harbor.cfg,该文件就是Harbor的配置文件编辑harbor.cfg实际上我们只需要修改Hostname字段[root@harbor harbor]# head harbor.cfg

## Configuration file of Harbor

#This attribute is for migrator to detect the version of the .cfg file, DO NOT MODIFY!
_version = 1.5.0
#The IP address or hostname to access admin UI and registry service.
#DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
hostname = 192.168.1.197

本次我们使用离线安装,安装包在上面

tar xf harbor-offline-installer-v1.5.0.tgz


./install

默认端口为80,需要修改端口请修改docker-compose.yaml对应服务的映射

四、访问Harbor

访问:192.168.1.197

docker push 需要项目路径,需要Harbor 创建项目 test

五、客户端配置免https

[root@localhost ~]# echo '{ "insecure-registries":["192.168.252.213:80"] }' > /etc/docker/daemon.json
 [root@localhost ~]# cat /etc/docker/daemon.json
{ "insecure-registries":["192.168.252.213:80"] }
[root@localhost ~]# service docker restart

如果不配置,客户端使用时候会报错: Error response from daemon: Get https:// 172.16.1.146:5000/v1/_ping: http: server gave
HTTP response to HTTPS client

客户端登陆
[root@localhost harbor]# docker login 192.168.252.213:80
Username (admin): admin
Password: 
Login Succeeded

五、管理镜像

下拉镜像

docker pull nginx

打标签

docekr tag 镜像名称:标签 你的IP:端口/harbor项目名称/镜像名称:标签 

docker tag nginx:latest 192.168.252.213:80/test/nginx:latest

上传

docker push 你的IP:端口/harbor项目名称/镜像名称:标签
docker push 192.168.252.213:80/test/nginx:latest

下拉

docker pull  192.168.252.213:80/test/nginx:latest

六、k8s配置harbor

在k8s中使用harbor仓库

k8s 默认https访问harbor,访问http,需要修改整个集群节点 /etc/docker/daemon.json 文件

# 配置两个镜像源文件
# 1.harbor 源/etc/docker/daemon.json 2. 国内源/etc/docker/daemon.conf
# 配置国内镜像源/etc/docker/daemon.conf 文件
cat > /etc/docker/daemon.conf <<EOF

{
    "registry-mirrors": [
        "https://kfwkfulq.mirror.aliyuncs.com",
        "https://registry.docker-cn.com",
        "http://hub-mirror.c.163.com"
    ],
    { "insecure-registries":["192.168.252.213:80"] }, # harbor ip地址

    "dns": ["8.8.8.8","8.8.4.4"]
}
EOF

最后重启docker

service docker restart

创建认证secret

  由于harbor采用了用户名密码认证,所以在镜像下载时需要配置sercet

#创建
kubectl create secret docker-registry registry-secret --namespace=default  \
--docker-server=10.1.210.33 \
--docker-username=admin \
--docker-password=Harbor12345 


#查看secret
[root@master demo]# kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-gdwgn   kubernetes.io/service-account-token   3      2d18h
registry-secret       kubernetes.io/dockerconfigjson        1      116s

#删除
kubectl delete secret registry-secret

部署示例

以一个部署一个nginx为例子,其中需要把containers中的images镜像指定为harbor仓库镜像地址

# kubectl create -f nginx.test.yml
root@k8s-master-2:~# vim /k8s/nginx.test.yml 

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment-harbor
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: 192.168.252.213:80/test/nginx:latest # harbor仓库镜像地址
        imagePullPolicy: Always
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  sessionAffinity: ClientIP
  selector:
    app: nginx
  ports:
    - port: 80
      nodePort: 30080

访问nginx

root@k8s-master-2:~# kubectl get svc
NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
nginx-service   NodePort    10.68.153.43   <none>        80:30080/TCP   19
root@k8s-master-2:~# curl 10.68.153.43