Demo环境私有容器镜像仓库Harbor升级过程记录
Demo环境私有容器镜像仓库Harbor升级过程记录
在某朵月底即将随风飘散的云中,我搭建有一个Kubernetes环境,一个容器Demo环境。前段时间,看到VMware公司对其开源Docker镜像仓库实现Harbor做了许多升级,尤其增加了对镜像安全漏洞的扫描,因此就尝试着升了下级,现在整理下当时粗略记录的过程步骤。
因公司面向的主要客户目前对应用容器化还没有需求,对微服务的需求还集中于求业绩亮点,所以对容器及容器平台没有强烈需求,只做为技术探索及方案储备来源的Demo环境存在,因此下面描述的部署方案可能不够严谨,见谅!
Harbor简介
上面已经提到Harbor是开源的容器镜像仓库实现,它对Docker官方提供的Registry做了企业化功能扩展与增强,主要的特点包括 :
基于角色的访问控制 - 用户与Docker镜像仓库通过“项目”进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限。 镜像复制 - 镜像可以在多个Registry实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景。 图形化用户界面 - 用户可以通过浏览器来浏览,检索当前Docker镜像仓库,管理项目和命名空间。 AD/LDAP 支持 - Harbor可以集成企业内部已有的AD/LDAP,用于鉴权认证管理。 审计管理 - 所有针对镜像仓库的操作都可以被记录追溯,用于审计管理。 国际化 - 已拥有英文、中文、德文、日文和俄文的本地化版本。更多的语言将会添加进来。 RESTful API - RESTful API 提供给管理员对于Harbor更多的操控, 使得与其它管理软件集成变得更容易。 部署简单 - 提供在线和离线两种安装工具, 也可以安装到vSphere平台(OVA方式)虚拟设备。具体的请参见其在GitHub上的文档:here,它的架构组成如下图:
Proxy:反射代理,将请求路由到相应功能模块,由Nginx实现;Registry:存储镜像并处理docker pull/push命令,与token服务交互控制访问权限,由Docker官方Register实现;UI:核心服务组件,Harbor的主要组成部分;Database:存储有关项目、用户、角色、复制策略与镜像元数据;Job Servers:最初版本中完成镜像复制任务,后面又增加了镜像安全漏洞描述任务;Log collector:这个就不用细说了吧,日志模块,以syslog服务形式收取其他模块日志内容,落地持久化。
部署方案
在我原有的Demo环境中,在两只虚拟机上各布置了一套Harbor,从其中一个Harbor向另一个Harbor做镜像复制,以防虚拟机意外损毁丢失镜像,正因为是个Demo环境,也就根本没有考虑太多其他高可用,只是利用Harbor默认的docker-compose配置脚本在每只虚拟机上启动全套的组件。
当初布置的版本中,并不包含镜像安全漏洞描述功能,这次升级主要是想体验下这个功能。当正视此功能时,才发现需要联接互联网获取安全漏洞元数据。也就是Clair需要联网,Clair也是个开源实现,Harbor集成进来实现安全漏洞描述功能:
而在布置Demo环境的这朵云上,默认是不开启互联网,整个环境中,只有一只虚拟机开启了连接互联网的权限,但,不是布置Harbor的两只虚拟机之一。为解决这个问题,考虑将Clair组件单独部署到那只能连接互联网的虚拟机上,在整个部署尝试中采用了两种方式:
1. Docker Swarm方式
Harbor 1 与 Clair 节点 组成docker Swarm集群,指定Clair应用及数据库部署在能连接外网的节点,指定Harbor原有组件部署在原有节点;
2. 容器端口宿主机暴露方式
Clair应用及数据库端口暴露成主机端口,Harbor 2的组件,通过暴露的端口连接Clair,需要Clair应用与数据库地址以Harbor指定的主机名引入容器/etc/hosts文件。
部署操作步骤
升级Harbor
升级主要过程参照于Harbor官方文档:migration_guide。
在原部署Harbor的节点上,拖取已经在私有仓库里准备好的Harbor升级镜像work> docker pull oracle-1.udmp.git.com.cn/vmware/harbor-db-migrator:1.3
准备升级到哪一个版本,就准备那个版本的升级镜像,我准备升级到Harbor 1.3,就准备了harbor-db-migrator:1.3 。
停止并备份Harbor
work> cd harbor work> docker-compose down work> cd .. work> mv harbor harbor_bak
备份MySQL数据库数据
work> docker run -ti --rm -e DB_USR=root -e DB_PWD=root123 -v /data/database:/var/lib/mysql -v /home/work/harbor_bak/db_backup:/harbor-migration/backup oracle-1.udmp.git.com.cn/vmware/harbor-db-migrator:1.3 backup
其中:/home/work/harbor_bak/db_backup是宿主机上实际数据备份目录;
? /harbor-migration/backup是Docker容器内部目录,上面命令行将宿主机目录mount到了容器目录。
升级MySQL数据库Schema
work> docker run -ti --rm -e DB_USR=root -e DB_PWD=root123 -v /data/database:/var/lib/mysql oracle-1.udmp.git.com.cn/vmware/harbor-db-migrator:1.3 up head
其中:/data/database是原有Harbor部署时指定的MySQL数据存储目录
展开harbor离线安装包,并按照原有部署配置重新修改配置文件。离线安装包从here下载。
work> tar xvfz harbor-offline-installer-v1.3.0.tgz work> cd harbor work> vi harbor.cfg
以不带Clair功能模块方式,安装启动Harbor
work> sudo ./install.sh
在某只机器上启动时,发现容器内部解析hostname失败,通过docker info命令检视环境时,发现输出中有:
Registry: https://index.docker.io/v1/ WARNING: bridge-nf-call-iptables is disabled WARNING: bridge-nf-call-ip6tables is disabled
检查系统参数设置:
work> sysctl -a | grep bridge-nf-call-ip ... net.bridge.bridge-nf-call-ip6tables = 0 net.bridge.bridge-nf-call-iptables = 0 ....
修改/etc/sysctl.conf,增加以下内容:
net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1
使参数生效:
work> sudo sysctl -p
重启Harbor:
work> cd harbor work> docker-compose down work> docker-compose up -d
Swarm方式部署带Clair的Harbor
为以Swarm集群方式部署Harbor 1,需要docker-composef支持version 3.0,因此需要保证docker-compse版本>=1.10.0
生成相应配置文件
在Harbor 1节点上:
work> cd harbor work> docker-compose down work> vi harbor.cfg #修改clair_db_password work> sudo ./prepare --with-clair
?
建立Docker Swarm集群
在Harbor 1节点上,执行以下命令使其成为集群主节点:
work> docker swarm init --advertise-addr 10.210.33.60 Swarm initialized: current node (jrfpz1voltljdrg5rohoh3dfv) is now a manager. To add a worker to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-243dskrvdqo07gfbaqaj8afit0oymp451inllzt2thcyvl0bi0-6w8ob2me68t4miv0u6akte4c1 \ 10.210.33.60:2377
在能连接互联网的节点上,以上面命令输出中的token加入swarm集群:
work> docker swarm join \ --token SWMTKN-1-243dskrvdqo07gfbaqaj8afit0oymp451inllzt2thcyvl0bi0-6w8ob2me68t4miv0u6akte4c1 \ 10.210.33.60:2377
给Docker Swarm集群中两个节点分别打上角色标签,以便于在配置中以角色标签指定各组件在相应节点启动
在Harbor 1节点即Swarm主节点上,查看swarm集群节点列表:
work> docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS jrfpz1voltljdrg5rohoh3dfv * UDMP-RT-15 Ready Active Leader p32iiasin4pnhi9hvn0qe11dc UDMP-RT-13 Ready Active
将两个节点分别打上标签,标明角色:
work> docker node update --label-add harbor-role=registry UDMP-RT-15 work> docker node update --label-add harbor-role=clair UDMP-RT-13
编辑docker-compose.yml
修改version为3.2, 并在每个服务配置节后面增加指定部署节点的内容,指定Harbor主要组件运行在角色为registry的节点上,即原来已有的Harbor 1节点:
deploy: placement: constraints: - node.labels.harbor-role == registry
修改log collector、proxy容器端口输出为本机,以免其以swarm ingress方式同时输出到其他节点,影响其他节点本地已有使用这些端口的应用,类似于:
log: ... ports: - target: 10514 published: 1514 protocol: tcp mode: host
完整的配置文件内容如下:
version: '3.2' services: log: image: vmware/harbor-log:v1.3.0 container_name: harbor-log restart: always volumes: - /var/log/harbor/:/var/log/docker/ - ./common/config/log/:/etc/logrotate.d/ ports: - target: 10514 published: 1514 protocol: tcp mode: host networks: - harbor deploy: placement: constraints: - node.labels.harbor-role == registry registry: image: vmware/registry:2.6.2-photon container_name: registry restart: always volumes: - /data/registry:/storage - ./common/config/registry/:/etc/registry/ networks: - harbor environment: - GODEBUG=netdns=cgo command: ["serve", "/etc/registry/config.yml"] depends_on: - log logging: driver: "syslog" options: syslog-address: "tcp://127.0.0.1:1514" tag: "registry" deploy: placement: constraints: - node.labels.harbor-role == registry mysql: image: vmware/harbor-db:v1.3.0 container_name: harbor-db restart: always volumes: - /data/database:/var/lib/mysql networks: - harbor env_file: - ./common/config/db/env depends_on: - log logging: driver: "syslog" options: syslog-address: "tcp://127.0.0.1:1514" tag: "mysql" deploy: placement: constraints: - node.labels.harbor-role == registry adminserver: image: vmware/harbor-adminserver:v1.3.0 container_name: harbor-adminserver env_file: - ./common/config/adminserver/env restart: always volumes: - /data/config/:/etc/adminserver/config/ - /data/secretkey:/etc/adminserver/key - /data/:/data/ networks: - harbor depends_on: - log logging: driver: "syslog" options: syslog-address: "tcp://127.0.0.1:1514" tag: "adminserver" deploy: placement: constraints: - node.labels.harbor-role == registry ui: image: vmware/harbor-ui:v1.3.0 container_name: harbor-ui env_file: - ./common/config/ui/env restart: always volumes: - ./common/config/ui/app.conf:/etc/ui/app.conf - ./common/config/ui/private_key.pem:/etc/ui/private_key.pem - ./common/config/ui/certificates/:/etc/ui/certifates/ - /data/secretkey:/etc/ui/key - /data/ca_download/:/etc/ui/ca/ - /data/psc/:/etc/ui/token/ networks: - harbor depends_on: - log - adminserver - registry logging: driver: "syslog" options: syslog-address: "tcp://127.0.0.1:1514" tag: "ui" deploy: placement: constraints: - node.labels.harbor-role == registry jobservice: image: vmware/harbor-jobservice:v1.3.0 container_name: harbor-jobservice env_file: - ./common/config/jobservice/env restart: always volumes: - /data/job_logs:/var/log/jobs - ./common/config/jobservice/app.conf:/etc/jobservice/app.conf - /data/secretkey:/etc/jobservice/key networks: - harbor depends_on: - ui - adminserver logging: driver: "syslog" options: syslog-address: "tcp://127.0.0.1:1514" tag: "jobservice" deploy: placement: constraints: - node.labels.harbor-role == registry proxy: image: vmware/nginx-photon:1.11.13 container_name: nginx restart: always volumes: - ./common/config/nginx:/etc/nginx networks: - harbor ports: - target: 80 published: 80 protocol: tcp mode: host - target: 443 published: 443 protocol: tcp mode: host - target: 4443 published: 4443 protocol: tcp mode: host depends_on: - mysql - registry - ui - log logging: driver: "syslog" options: syslog-address: "tcp://127.0.0.1:1514" tag: "proxy" deploy: placement: constraints: - node.labels.harbor-role == registry networks: harbor: external: false
编辑docker-compose.clair.yml
修改version为3.2, 并在每个服务配置节后面增加指定部署节点的内容,指定Clair组件相关容器运行在角色标签为clair的节点上,即那台能连接互联网的机器:
deploy: placement: constraints: - node.labels.harbor-role == clair
先注释到cpu_quota,因为在V3.0里已经被resource.cpu配置替代,并且增加本地log日志服务,并修改其他服务依赖的服务名为log-clair,log端口为2514。(为什么既然限制了端口输出为节点,为什么使用1514时还会在启动时报冲突?【 Harbor 节点上的log在使用1514端口】)
修改postgres、clair容器配置,分别输出其端口到宿主机,以供Harbor 2引入
完整的配置文件内容如下:
version: '3.2' services: ui: networks: harbor-clair: aliases: - harbor-ui jobservice: networks: - harbor-clair registry: networks: - harbor-clair log-clair: image: vmware/harbor-log:v1.3.0 container_name: harbor-log restart: always volumes: - /var/log/harbor/:/var/log/docker/ - ./common/config/log/:/etc/logrotate.d/ ports: - target: 10514 published: 2514 protocol: tcp mode: host networks: - harbor-clair deploy: placement: constraints: - node.labels.harbor-role == clair postgres: networks: harbor-clair: aliases: - postgres container_name: clair-db image: vmware/postgresql:9.6.5-photon restart: always depends_on: - log-clair env_file: ./common/config/clair/postgres_env volumes: - ./common/config/clair/postgresql-init.d/:/docker-entrypoint-initdb.d - /data/clair-db:/var/lib/postgresql/data logging: driver: "syslog" options: syslog-address: "tcp://127.0.0.1:2514" tag: "clair-db" ports: - target: 5432 published: 5432 protocol: tcp mode: host deploy: placement: constraints: - node.labels.harbor-role == clair clair: networks: - harbor-clair container_name: clair image: vmware/clair:v2.0.1-photon restart: always #cpu_quota: 150000 depends_on: - postgres volumes: - ./common/config/clair:/config logging: driver: "syslog" options: syslog-address: "tcp://127.0.0.1:2514" tag: "clair" ports: - target: 6000 published: 6000 protocol: tcp mode: host deploy: placement: constraints: - node.labels.harbor-role == clair networks: harbor-clair: external: false
合并生成Docker Swarm部署配置文件
work> docker-compose -f docker-compose.yml -f docker-compose.clair.yml config > docker-with-clair.yml
将应用拷贝到能连接互联网的Clair节点,修改harbor.cfgj里的hostname,然后:
work> sudo ./install -with-clair work> docker-compose -f docker-compose.yml -f docker-compose.clair.yml down
以上命令的用意,以离线方式导入相应Docker镜像,并启动一次,建立相应目录,并初始化Clair数据库
在Swarm主节点,即Harbor 1节点上,启动应用:
work> docker stack deploy -c docker-with-clair.yml harbor
登录页面,检查确认部署成功
Harbor直接连接Clair暴露的端口
在Harbor 2节点上,以上面描述的方式,首先升级Harbor到新版本,然后修改harbor.cfg里clair_db_password,设置成与Harbor 1节点上相同的口令,再通过命令重新生成配置:
work> sudo ./prepare --with-clair
手工修改docker-compose.yml,在ui、adminserver、jobserver配置里增加对clair相关主机名与地址映射到/etc/hosts的配置:
extra_hosts: - "clair:10.210.33.58" - "postgres:10.210.33.58"
重启Harbor
work> docker-compose -f docker-compose.yaml
上一篇: centos7上安装docker教程