Harbor共享存储高可用
主机拓扑
角色 | 主机名 | ip | 系统 | 资源最低要求 |
Harbor1 nginx Keepalived1 | harbor1 | 192.168.48.106 | OpenEuler22.03LTS | CPU:4核 内存:2G 硬盘:40G |
Harbor2 nginx Keepalived2 | harbor2 | 192.168.48.107 | OpenEuler22.03LTS | CPU:4核 内存:2G 硬盘:40G |
postgresql Redis NFS共享 | zujian | 192.168.48.108 | OpenEuler22.03LTS | CPU:4核 内存:2G 硬盘:40G |
高可用ip | 192.168.48.100 |
系统架构图
基本配置
操作节点:[harbor1,harbour2,zujian]
vi jichu_init.sh
将以下脚本内容添加进去
#!/bin/bash
if [ $# -eq 2 ];then
echo "设置主机名为:$1"
echo "ens160设置IP地址为:192.168.48.$2"
else
echo "使用方法:sh $0 主机名 主机位"
exit 2
fi
echo "--------------------------------------"
echo "1.正在设置主机名:$1"
hostnamectl set-hostname $1
echo "2.正在关闭firewalld、dnsmasq、selinux"
systemctl disable firewalld &> /dev/null
systemctl disable dnsmasq &> /dev/null
systemctl stop firewalld
systemctl stop dnsmasq
sed -i "s#SELINUX=enforcing#SELINUX=disabled#g" /etc/selinux/config
setenforce 0
echo "3.正在设置ens160:192.168.48.$2"
cat > /etc/sysconfig/network-scripts/ifcfg-ens160 <<EOF
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
NAME=ens160
UUID=53b402ff-5865-47dd-a853-7afcd6521738
DEVICE=ens160
ONBOOT=yes
IPADDR=192.168.48.$2
GATEWAY=192.168.48.2
PREFIX=24
DNS1=192.168.48.2
DNS2=114.114.114.114
nmcli c reload
nmcli c up ens 160
echo "4.优化ssh"
sed -i "s#\#UseDNS yes#UseDNS no#g" /etc/ssh/sshd_config
sed -i "s#GSSAPIAuthentication yes#GSSAPIAuthentication no#g" /etc/ssh/sshd_config
systemctl restart sshd
echo "5.更改欧拉源为华为云源,速度快一点"
sed -i 's/\$basearch/x86_64/g' /etc/yum.repos.d/openEuler.repo
sed -i 's/http\:\/\/repo.openeuler.org/https\:\/\/mirrors.huaweicloud.com\/openeuler/g' /etc/yum.repos.d/openEuler.repo
echo "6.更新yum源软件包缓存"
yum clean all && yum makecache
dnf update -y
echo "7.修改history格式及记录数"
sed -i "s#HISTSIZE=1000##g" /etc/profile
cat >> /etc/profile <<EOF
shopt -s histappend
USER_IP=`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'`
export HISTFILE=~/.commandline_warrior
export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S `whoami`@${USER_IP}: "
export HISTSIZE=200000
export HISTFILESIZE=1000000
export PROMPT_COMMAND="history -a"
EOF
source /etc/profile
echo "8.添加hosts解析"
cat > /etc/hosts <<EOF
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.48.106 harbor1
192.168.48.107 harbor2
192.168.48.108 zujian
EOF
echo "10.安装chrony服务,并同步时间"
dnf install chrony -y
systemctl start chronyd
systemctl enable chronyd
chronyc sources
chronyc sources
echo "11、安装依赖包"
dnf install -y cmake gcc gcc-c++ perl readline readline-devel openssl openssl-devel zlib zlib-devel ncurses-devel readline readline-devel zlib zlib-devel
reboot
执行脚本命令格式:sh jichu_init.sh 主机名 主机位
[harbor1] sh jichu_init.sh harbor1 106
[harbor2] sh jichu_init.sh harbor2 107
[zujian] sh jichu_init.sh zujian 108
配置ssh免密
操作节点:[harbor1,harbour2,zujian]
dnf install -y sshpass
cat > sshmianmi.sh << "EOF"
#!/bin/bash
# 目标主机列表
hosts=("harbor1" "harbor2" "zujian")
# 密码
password="Lj201840."
# 生成 SSH 密钥对
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
# 循环遍历目标主机
for host in "${hosts[@]}"
do
# 复制公钥到目标主机
sshpass -p "$password" ssh-copy-id -o StrictHostKeyChecking=no "$host"
# 验证免密登录
sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$host" "echo '免密登录成功'"
done
EOF
sh sshmianmi.sh
安装高可用组件
操作节点:[harbor1,harbour2]
dnf install -y keepalived nginx
安装nginx
操作节点:[harbor1,harbour2]
cat > /etc/nginx/nginx.conf <<"EOF"
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
stream {
log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
access_log /var/log/nginx/harbor-access.log main;
upstream harbor{
server 192.168.48.106:8081; #harbor1
server 192.168.48.107:8081; #harbor2
}
server {
listen 80;
proxy_pass harbor;
}
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 8888 default_server;
server_name _;
location / {
}
}
}
EOF
systemctl enable --now nginx
nginx -s reload
安装安装keepalived
操作节点:[harbor1]
cat >/etc/keepalived/keepalived.conf << "EOF"
! Configuration File for keepalived
global_defs {
notification_email {
qianyios@qq.com
}
router_id harbor1
}
vrrp_instance zh {
state MASTER
interface ens160
mcast_src_ip 192.168.48.106
virtual_router_id 107
priority 100
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.48.100/24
}
track_script {
chk_nginx
}
}
vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -20
}
EOF
操作节点:[harbor2]
cat >/etc/keepalived/keepalived.conf << "EOF"
! Configuration File for keepalived
global_defs {
notification_email {
qianyios@qq.com
}
router_id harbor2
}
vrrp_instance zh {
state BACKUP
interface ens160
mcast_src_ip 192.168.48.107
virtual_router_id 107
priority 99
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.48.100/24
}
track_script {
chk_nginx
}
}
vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -20
}
EOF
配置检查脚本
操作节点:[harbor1,harbour2]
cat >/etc/keepalived/check_nginx.sh <<"EOF"
#!/bin/bash
counter=`ps -C nginx --no-header | wc -l`
if [ $counter -eq 0 ]; then
systemctl start nginx
sleep 2
counter=`ps -C nginx --no-header | wc -l`
if [ $counter -eq 0 ]; then
systemctl stop keepalived
fi
fi
EOF
启动服务
systemctl enable --now nginx keepalived
nginx -s reload
查看VIP虚拟ip
[root@harbor1 ~]# ip a
.............
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:af:76:8c brd ff:ff:ff:ff:ff:ff
inet 192.168.48.106/24 brd 192.168.48.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet 192.168.48.100/24 scope global secondary ens160 ###192.168.48.100/24就是刚刚设置的高可用ip
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feaf:768c/64 scope link noprefixroute
valid_lft forever preferred_lft forever
安装postgresql
操作节点:[zujian]
安装
#创建postgres用户
useradd postgres
passwd postgres
#设置密码123456
#编译安装postgresql
wget https://ftp.postgresql.org/pub/source/v16.2/postgresql-16.2.tar.gz
tar zxvf postgresql-16.2.tar.gz -C /usr/local/bin/
cd /usr/local/bin/postgresql-16.2/
./configure --prefix=/usr/local/postgresql
make && make install
#建立数据目录
mkdir -p /data/postgresql/data
#创建日志目录
mkdir -p /data/postgresql/log
#创建socket目录
mkdir -p /data/postgresql/tmp
#授权
chown -R postgres:postgres /usr/local/postgresql/
chown -R postgres:postgres /data/postgresql
#设置postgres环境
su - postgres
cd
cat << "EOF" >> ~/.bash_profile
PGHOME=/usr/local/postgresql
export PGHOME
PGDATA=/data/postgresql/data
export PGDATA
PATH=$PATH:$HOME/bin:$HOME/.local/bin:$PGHOME/bin
export PATH
EOF
source ~/.bash_profile
psql -V
#初始化数据库
initdb --username=postgres -D /data/postgresql/data
#会有Success. You can now start the database server using: #表示初始化成功
#修改初始化的配置文件
cat > /data/postgresql/data/postgresql.conf << "EOF"
max_connections = 100 # 允许最大连接数
shared_buffers = 128MB # 内存大小
dynamic_shared_memory_type = posix # the default is usually the first option
max_wal_size = 1GB
min_wal_size = 80MB
log_timezone = 'Asia/Shanghai'
datestyle = 'iso, mdy'
timezone = 'Asia/Shanghai'
lc_messages = 'en_US.UTF-8' # locale for system error message
lc_monetary = 'en_US.UTF-8' # locale for monetary formatting
lc_numeric = 'en_US.UTF-8' # locale for number formatting
lc_time = 'en_US.UTF-8' # locale for time formatting
default_text_search_config = 'pg_catalog.english'
listen_addresses = '*' #监听所有地址
data_directory = '/data/postgresql/data' # 数据目录指定
port = 5432
unix_socket_directories = '/data/postgresql/tmp'
unix_socket_group = ''
unix_socket_permissions = 0777
logging_collector = on
log_directory = '/data/postgresql/log'
log_rotation_size = 1GB
log_timezone = 'Asia/Shanghai'
log_min_duration_statement = 100
EOF
#设置远程连接
cat >> /data/postgresql/data/pg_hba.conf << EOF
local all all trust
host all all 0.0.0.0/0 password
host all all ::1/128 password
host all postgres 0.0.0.0/0 trust
EOF
#启动PostgreSQL
pg_ctl -D /data/postgresql/data -l logfile start
进入数据库
psql -h 127.0.0.1 -p 5432 -U postgres
postgres=# \password
Enter new password for user "postgres":
Enter it again:
#输入密码123456
postgres=# exit
#重新启动
pg_ctl -D /data/postgresql/data -l /data/postgresql/data/postgresql.log restart
#提示一下信息成功(不是命令哈,不要去运行)
pg_ctl: old server process (PID: 25461) seems to be gone
starting server anyway
waiting for server to start.... done
server started
psql -h 127.0.0.1 -p 5432 -U postgres
#输入密码123456
CREATE DATABASE registry;
CREATE DATABASE notary_signer;
CREATE DATABASE notary_servers;
\l
create user server with password '123456';
create user signer with password '123456';
\du
GRANT ALL PRIVILEGES ON DATABASE registry to postgres;
GRANT ALL PRIVILEGES ON DATABASE notary_signer to postgres;
GRANT ALL PRIVILEGES ON DATABASE notary_servers to postgres;
exit
设置启动服务
操作节点[zujian]
#回到root用户下执行
su - root
cat >/etc/init.d/PG-start.sh<< "EOF"
sudo -u postgres /usr/local/postgresql/bin/pg_ctl -D /data/postgresql/data start
EOF
cat >/etc/init.d/PG-stop.sh<< "EOF"
sudo -u postgres /usr/local/postgresql/bin/pg_ctl -D /data/postgresql/data stop
EOF
cat >/etc/init.d/PG-restart.sh<<"EOF"
sudo -u postgres /usr/local/postgresql/bin/pg_ctl -D /data/postgresql/data restart
EOF
sudo chmod +x /etc/init.d/PG-start.sh
sudo chmod +x /etc/init.d/PG-stop.sh
sudo chmod +x /etc/init.d/PG-restart.sh
cat >/etc/systemd/system/postgresql.service << "EOF"
[Unit]
Description=postgresql Service
[Service]
Type=oneshot
user=root
RemainAfterExit=true
ExecStart=/usr/bin/sudo /etc/init.d/PG-start.sh
ExecStop=/usr/bin/sudo /etc/init.d/PG-stop.sh
ExecRestart=/usr/bin/sudo /etc/init.d/PG-restart.sh
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now postgresql
错误积累
#每次我启动pgsql的时候就有这个东西
2024-09-14 14:34:03.196 CST [17746] HINT: Is another postmaster (PID 16042) running in data directory "/data/postgresql/data"?
stopped waiting
pg_ctl: could not start server
#意思是有个pid进程在运行,杀掉它就行了
sudo kill -9 16042
安装redis
操作节点:[zujian]
安装redis
wget https://download.redis.io/releases/redis-7.2.4.tar.gz
tar zxvf redis-7.2.4.tar.gz
mv redis-7.2.4 /usr/local/bin/
cd /usr/local/bin/redis-7.2.4
make && make install
修改配置文件
vi /usr/local/bin/redis-7.2.4/redis.conf
#bind 127.0.0.1 -::1 #注释掉bind的行,允许任何主机连接;
daemonize yes #将no修改为yes,使redis可以使用守护进程方式启动;
requirepass 123456 #添加这行,设置redis连接的auth密码(123456)
protected-mode no #禁用保护模式
以下是一步到位将以上四个命令全部实现
sed -i 's/^bind 127.0.0.1 -::1/#bind 127.0.0.1 -::1/' /usr/local/bin/redis-7.2.4/redis.conf
sed -i 's/^daemonize no/daemonize yes/' /usr/local/bin/redis-7.2.4/redis.conf
echo -e "\nrequirepass 123456" >> /usr/local/bin/redis-7.2.4/redis.conf
sed -i 's/^protected-mode yes/protected-mode no/' /usr/local/bin/redis-7.2.4/redis.conf
启动服务
redis-server redis.conf
[root@zujian redis-7.2.4]# redis-server redis.conf
2226:C 20 Apr 2024 17:10:45.039 # WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
Redis在启动时可能会出现这样的日志:在分析这个问题之前, 首先要弄清楚什么是overcommit? Linux操作系统对大部分申请内存的请求都回复yes
, 以便能运行更多的程序
。 因为申请内存后, 并不会马上使用内存, 这种技术叫做overcommit
。如果Redis在启动时有上面的日志, 说明vm.overcommit_memory=0, Redis提示把它设置为1。
vm.overcommit_memory用来设置内存分配策略, 有三个可选值, 如表:可用内存代表物理内存与swap之和
解决办法:
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
sysctl vm.overcommit_memory=1
redis-server redis.conf
再重新启动就可以查看版本和端口号了
[root@zujian redis-7.2.4]# redis-cli -v
redis-cli 7.2.4
[root@zujian redis-7.2.4]# ps aux |grep 6379
root 2227 0.0 0.3 68412 10888 ? Ssl 17:10 0:00 redis-server *:6379
root 5427 0.0 0.0 22096 2300 pts/0 S+ 17:19 0:00 grep --color=auto 6379
#redis-server有这个就行
关闭服务(只是普及知识,测试可用,不要随意关闭)
redis-cli shutdown
客户端连接redis
操作节点:[zujian]
将redis-cli的工具复制到Harbor1,harbor2
查看redis-cli工具位置
[root@zujian]# which redis-cli
/usr/local/bin/redis-cli
复制
which redis-cli
scp /usr/local/bin/redis-cli harbor1:/usr/local/bin/
scp /usr/local/bin/redis-cli harbor2:/usr/local/bin/
操作节点:[harbor1,harbor2]
redis-cli -h 192.168.48.108 -p 6379 -a 123456
到此redis安装成功
设置启动服务
cat >/etc/init.d/redis-start.sh<< "EOF"
/usr/local/bin/redis-server /usr/local/bin/redis-7.2.4/redis.conf
EOF
cat >/etc/init.d/redis-stop.sh<< "EOF"
/usr/local/bin/redis-cli -a 123456 shutdown
EOF
sudo chmod +x /etc/init.d/redis-start.sh
sudo chmod +x /etc/init.d/redis-stop.sh
cat >/etc/systemd/system/redis.service << "EOF"
[Unit]
Description=redis Service
[Service]
Type=oneshot
user=root
RemainAfterExit=true
ExecStart=/usr/bin/sudo /etc/init.d/redis-start.sh
ExecStop=/usr/bin/sudo /etc/init.d/redis-stop.sh
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now redis
NFS共享存储安装
操作节点:[zujian]
dnf install -y nfs-utils
systemctl enable --now nfs
#创建远程共享目录
mkdir -p /data/harbor_data
cat >> /etc/exports << "EOF"
/data/harbor_data 192.168.48.0/24(rw,no_root_squash)
EOF
#使配置生效
exportfs -arv
#生效结果
[root@zujian ~]# showmount -e
Export list for zujian:
/data/harbor_data 192.168.48.0/24
操作节点:[harbor1,harbor2]
Harbor1、harbor2机器上安装nfs-utils客户端并挂载共享存储
dnf install -y nfs-utils
systemctl enable --now nfs
mkdir -p /data/harbor_data
cat >>/etc/fstab<<"EOF"
192.168.48.108:/data/harbor_data /data/harbor_data nfs defaults 0 0
EOF
mount -a
df -h | grep harbor
#以下是挂载成功
[root@harbor1 ~]# df -h | grep harbor
192.168.48.108:/data/harbor_data 63G 3.0G 57G 6% /data/harbor_data
[root@harbor2 ~]# df -h | grep harbor
192.168.48.108:/data/harbor_data 63G 3.0G 57G 6% /data/harbor_data
harbor仓库安装
操作节点:[harbor1,harbor2]
安装docker
wget https://download.docker.com/linux/static/stable/x86_64/docker-26.0.1.tgz
tar xf docker-*.tgz
cp docker/* /usr/bin/
#创建containerd的service文件,并且启动
cat >/etc/systemd/system/containerd.service <<EOF
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=1048576
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
EOF
systemctl enable --now containerd.service
#准备docker的service文件
cat > /etc/systemd/system/docker.service <<EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket containerd.service
[Service]
Type=notify
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
OOMScoreAdjust=-500
[Install]
WantedBy=multi-user.target
EOF
#准备docker的socket文件
cat > /etc/systemd/system/docker.socket <<EOF
[Unit]
Description=Docker Socket for the API
[Socket]
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
EOF
groupadd docker
systemctl enable --now docker.socket && systemctl enable --now docker.service
#验证
mkdir /etc/docker
cat >/etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com",
"https://pw860av8.mirror.aliyuncs.com"
],
"max-concurrent-downloads": 10,
"log-driver": "json-file",
"log-level": "warn",
"log-opts": {
"max-size": "500m",
"max-file": "3"
},
"data-root": "/var/lib/docker"
}
EOF
systemctl restart docker
docker -v
安装docker-compose
操作节点:[harbor1,harbor2]
wget https://github.com/docker/compose/releases/download/v2.26.1/docker-compose-linux-x86_64
mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose version
配置内核参数并使之生效
操作节点:[harbor1,harbor2]
modprobe br_netfilter
cat >> /etc/sysctl.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1 #路由转发
EOF
sysctl -p
下载harbor包并配置文件
操作节点:[harbor1,harbor2]
下载离线包offline字样
wget https://github.com/goharbor/harbor/releases/download/v2.9.4/harbor-offline-installer-v2.9.4.tgz
tar zxvf harbor-offline-installer-v2.9.4.tgz
mv harbor /var/
cd /var/harbor/
[root@harbor1 harbor]# ls
common.sh harbor.v2.9.4.tar.gz harbor.yml.tmpl install.sh LICENSE prepare
cp harbor.yml.tmpl harbor.yml
配置harbor文件
操作节点:[harbor1]
vi /var/harbor/harbor.yml
hostname: 192.168.48.106 #harbor1
http:
port: 8081
#https: #先注释https协议,后面再实现
# port: 443
# certificate: /your/certificate/path
# private_key: /your/private/key/path
## 启用外部代理,启用后hostname将不再使用
external_url: https://192.168.48.100
#harbor页面密码
harbor_admin_password: Harbor12345
#配置NFS共享存储
data_volume: /data/harbor_data
_version: 2.9.0
#配置数据库
external_database:
harbor:
host: 192.168.48.108 # 数据库主机地址
port: 5432 # 数据库端口
db_name: registry # 数据库名称
username: postgres # 连接该数据库的用户名
password: 123456 # 连接数据库的密码
ssl_mode: disable
max_idle_conns: 50
max_open_conns: 100
notary_server:
host: 192.168.48.108
port: 5432
db_name: notary_server
username: postgres
password: 123456
ssl_mode: disable
notary_signer:
host: 192.168.48.108
port: 5432
db_name: notary_signer
username: postgres
password: 123456
ssl_mode: disable
#配置redis
external_redis:
host: 192.168.48.108:6379 #redis服务IP地址和端口号
password: 123456 #连接外部redis服务的密码
registry_db_index: 1
jobservice_db_index: 2 #job服务的数据库索引
chartmuseum_db_index: 3 #chartmuseum插件的Redis索引
trivy_db_index: 5 #Trivy扫描器的数据索引
idle_timeout_seconds: 30 #超时时间
#启用metrics数据采集插件
metric:
enabled: false
port: 9090
path: /metrics
trivy:
ignore_unfixed: false
skip_update: false
skip_java_db_update: false
offline_scan: false
security_check: vuln
insecure: false
jobservice:
max_job_workers: 10
job_loggers:
- STD_OUTPUT
- FILE
logger_sweeper_duration: 1 #days
notification:
webhook_job_max_retry: 3
webhook_job_http_client_timeout: 3 #seconds
log:
level: info
local:
rotate_count: 50
rotate_size: 200M
location: /var/log/harbor
proxy:
http_proxy:
https_proxy:
no_proxy:
components:
- core
- jobservice
- trivy
upload_purging:
enabled: true
age: 168h
interval: 24h
dryrun: false
cache:
enabled: false
expire_hours: 24
操作节点:[harbor2]
vi /var/harbor/harbor.yml
hostname: 192.168.48.107 #harbor2
http:
port: 8081
#https: #先注释https协议,后面再实现
# port: 443
# certificate: /your/certificate/path
# private_key: /your/private/key/path
## 启用外部代理,启用后hostname将不再使用
external_url: https://192.168.48.100
#harbor页面密码
harbor_admin_password: Harbor12345
#配置NFS共享存储
data_volume: /data/harbor_data
_version: 2.9.0
#配置数据库
external_database:
harbor:
host: 192.168.48.108 # 数据库主机地址
port: 5432 # 数据库端口
db_name: registry # 数据库名称
username: postgres # 连接该数据库的用户名
password: 123456 # 连接数据库的密码
ssl_mode: disable
max_idle_conns: 2
max_open_conns: 0
notary_server:
host: 192.168.48.108
port: 5432
db_name: notary_server
username: postgres
password: 123456
ssl_mode: disable
notary_signer:
host: 192.168.48.108
port: 5432
db_name: notary_signer
username: postgres
password: 123456
ssl_mode: disable
#配置redis
external_redis:
host: 192.168.48.108:6379 #redis服务IP地址和端口号
password: 123456 #连接外部redis服务的密码
registry_db_index: 1
jobservice_db_index: 2 #job服务的数据库索引
chartmuseum_db_index: 3 #chartmuseum插件的Redis索引
trivy_db_index: 5 #Trivy扫描器的数据索引
idle_timeout_seconds: 30 #超时时间
#启用metrics数据采集插件
metric:
enabled: false
port: 9090
path: /metrics
trivy:
ignore_unfixed: false
skip_update: false
skip_java_db_update: false
offline_scan: false
security_check: vuln
insecure: false
jobservice:
max_job_workers: 10
job_loggers:
- STD_OUTPUT
- FILE
logger_sweeper_duration: 1 #days
notification:
webhook_job_max_retry: 3
webhook_job_http_client_timeout: 3 #seconds
log:
level: info
local:
rotate_count: 50
rotate_size: 200M
location: /var/log/harbor
proxy:
http_proxy:
https_proxy:
no_proxy:
components:
- core
- jobservice
- trivy
upload_purging:
enabled: true
age: 168h
interval: 24h
dryrun: false
cache:
enabled: false
expire_hours: 24
将配置文件注入到各级件中并安装
先提前下载镜像吧,这里用博主构建的镜像速度会快一点
docker pull registry.cn-hangzhou.aliyuncs.com/qianyios/prepare:v2.9.4
docker tag registry.cn-hangzhou.aliyuncs.com/qianyios/prepare:v2.9.4 goharbor/prepare:v2.9.4
开始注入
cd /var/harbor/
./prepare
开始安装
cd /var/harbor/
./install.sh
配置自启动
cat >/usr/lib/systemd/system/harbor.service << "EOF"
[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service nfs-server.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor
[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/local/bin/docker-compose -f /var/harbor/docker-compose.yml up
ExecStop=/usr/local/bin/docker-compose -f /var/harbor/docker-compose.yml down
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable harbor --now
大坑来了,之前找了两个星期都没解决的
到此,harbor安装完成,但是你在网页可能会出现不能用admin登入,会显示密码错误
你需要进行下一步安装证书
原因:首先pg数据库在安装harbor时创建的admin是用sha256协议加密的
而在我们harbor页面,我们并没有配置ssl证书,是http方式访问并没有sha256加密协议,意味着harbor再登入的时候,会出现密码错误,就是:网页登入验证===/===
pg数据库验证,配置openssl证书,可以解决此问题,openssl包含sha256协议,这样就可以登入了。
OpenSSL是一个强大的加密库
,广泛应用于互联网的各个角落,用于保护数据传输的安全。它实现了SSL和TLS协议,这些协议是现代网络安全的基石。
配置ssl证书
操作节点:[harbor1,harbor2]
生成ca证书
创建一个放置证书相关的目录,并使用cd进入该目录
mkdir /var/harbor/cert&& cd /var/harbor/cert
## 1. 生成CA证书私钥
openssl genrsa -out ca.key 4096
## 2. 生成CA证书,可调整 -subj 选项来表明域名名称等信息
openssl req -x509 -new -nodes -sha512 -days 3650 \
-subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=192.168.48.100" \
-key ca.key \
-out ca.crt
生成服务器证书
认证证书通常包含证书请求.csr
文件、签名证书.crt
文件及私钥.key
文件,我这里harbor配置的hostname是192.168.48.100,所以最终需要生成192.168.48.100.crt、192.168.48.100.csr、192.168.48.100.key
三个文件。
- key:证书私钥,一般利用rsa等算法生成
- csr:证书请求文件,利用证书私钥生成证书请求文件,该文件包含了服务器和地址等信息,申请人将该文件提交给CA机构,CA机构会根据该文件所携带的私钥信息来进行签名生成证书
- crt:证书文件
## 1. 生成私钥
openssl genrsa -out 192.168.48.100.key 4096
## 2. 生成csr文件
openssl req -sha512 -new \
-subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=192.168.48.100" \
-key 192.168.48.100.key \
-out 192.168.48.100.csr
## 3. 生成ssl匹配多域名文,例如既想使用域名又需要通过127.0.0.1本地地址登陆测试,可使用subjectAltName参数来进行配置
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=192.168.48.100
DNS.2=127.0.0.1
IP.1=192.168.48.100
EOF
## 4. 根据v3.ext及csr文件请求生成crt证书文件
openssl x509 -req -sha512 -days 3650 \
-extfile v3.ext \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-in 192.168.48.100.csr \
-out 192.168.48.100.crt
修改harbor配置文件
cat >> /var/harbor/harbor.yml << "EOF"
https:
port: 443
certificate: /var/harbor/cert/192.168.48.100.crt
private_key: /var/harbor/cert/192.168.48.100.key
EOF
重新启动
cd /var/harbor
docker-compose down -v
./prepare
docker-compose up -d
镜像上传及拉取测试
操作节点:[harbor1,harbor2,zujian,qianyios(测试客户端)]
找一台客户端装好docker
进行测试
[root@qianyios ~]# docker -v
Docker version 26.0.1, build d260a54
新建私有镜像仓库
客户端免https登陆
# 此时直接使用docker login登陆到harbor中,会报错,下面hostname和port是harbor的配置文件中设置的名称及端口
#以下是格式
[root@xxxx harbor]# docker login [hostname]:[port]
可能会出现以下情况
#192.168.48.100是高可用vip
[root@harbor1 ~]# docker login 192.168.48.100
Username: admin
Password:
Error response from daemon: Get "https://192.168.48.100/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority
[root@qianyios ~]# docker login 192.168.48.106:8081
Username: admin
Password:
Error response from daemon: Get "https://192.168.48.106:8081/v2/": http: server gave HTTP response to HTTPS client
[root@qianyios ~]#
# 客户端默认使用的是https协议,所以需要对docker做以下修改,在文件末尾添加insecure-registries
[root@qianyios ~]# vim /etc/docker/daemon.json
{
................
"registry-mirrors": [],#无关紧要,不用看,
"insecure-registries": [ "192.168.48.100" ],#重要加这行,别忘了如果他不是最后一行一定要在末尾加逗号
................
}
# 修改后,重启docker使其生效
systemctl daemon-reload
systemctl restart docker
# 利用docker info查看是否添加上
[root@qianyios ~]# docker info
Containers: 10
Running: 1
Paused: 0
Stopped: 9
Images: 37
...
Experimental: false
Insecure Registries:
192.168.48.100 ###要确保有这个才行
127.0.0.0/8
Registry Mirrors:
扩展知识-containerd私有仓库配置(可略过)
在今后的K8s版本可能也会用containerd做为k8s的容器运行时,那么配置私有仓库也是一个头疼的事情。
在/etc/containerd/config.toml会有以下两个信息,可以定位
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
要在以上两个信息下配置东西如下:(理解,我下面有一步到位命令,不用手动加)
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.48.100".tls]
insecure_skip_verify = true # 是否跳过安全认证
[plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.48.100".auth]
username = "admin"
password = "Harbor12345"
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://registry-1.docker.io"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.48.100"]
endpoint = ["http://192.168.48.100"]
添加Harbor信息
sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry.configs\]/a \
[plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.48.100".tls]\
insecure_skip_verify = true # 是否跳过安全认证\
[plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.48.100".auth]\
username = "admin"\
password = "Harbor12345"' /etc/containerd/config.toml
sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry.mirrors\]/a \
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]\
endpoint = ["https://registry-1.docker.io"]\
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.48.100"]\
endpoint = ["http://192.168.48.100"]' /etc/containerd/config.toml
最后尝试下载镜像
crictl pull 192.168.48.100/cicd/jenkins:latest
这个是我自己上传的镜像,已经在harbor仓库了,我现在在有containerd的客户端进行拉取看看能不能成功
显然已经成功
进行登入测试
docker login 192.168.48.100
[root@harbor1 ~]# docker login 192.168.48.100
Username: admin
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
[root@qianyios ~]# docker login 192.168.48.100
Username: admin
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
##经过测试,通过添加"insecure-registries": [ "192.168.48.100" ]可以免除https登入
上传镜像测试
#下载一个nginx镜像,然后tag,再上传
[root@qianyios ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete
a9edb18cadd1: Pull complete
589b7251471a: Pull complete
186b1aaa4aa6: Pull complete
b4df32aa5a72: Pull complete
a0bcbecc962e: Pull complete
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
#在此下载了最新版的nginx镜像tag为lastest
我们进入当刚刚创建的仓库,点推送指令
#推送镜像命令格式
#docker tag 源镜像名[:TAG] 192.168.48.100/qianyios/新镜像名[:TAG]
docker tag SOURCE_IMAGE[:TAG] 192.168.48.100/qianyios/REPOSITORY[:TAG]
#我们将nginx镜像打上tag
[root@qianyios ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 2 years ago 141MB
#605的意思是镜像id的前三位数字,我们指定为V1标签,相当于版本号。
[root@qianyios ~]# docker tag 605 192.168.48.100/qianyios/nginx:V1
[root@qianyios ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
192.168.48.100/qianyios/nginx V1 605c77e624dd 2 years ago 141MB
nginx latest 605c77e624dd 2 years ago 141MB
#开始上传
[root@qianyios ~]# docker push 192.168.48.100/qianyios/nginx:V1
The push refers to repository [192.168.48.100/qianyios/nginx]
d874fd2bc83b: Pushed
32ce5f6a5106: Pushed
f1db227348d0: Pushed
b8d6e692a25e: Pushed
e379e8aedd4d: Pushed
2edcec3590a4: Pushed
V1: digest: sha256:ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3 size: 1570
#去页面查看
我们去harbor1测试拉取镜像,会发现下载数变成了1
[root@harbor1 ~]# docker pull 192.168.48.100/qianyios/nginx:V1
V1: Pulling from qianyios/nginx
a2abf6c4d29d: Pull complete
a9edb18cadd1: Pull complete
589b7251471a: Pull complete
186b1aaa4aa6: Pull complete
b4df32aa5a72: Pull complete
a0bcbecc962e: Pull complete
Digest: sha256:ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
Status: Downloaded newer image for 192.168.48.100/qianyios/nginx:V1
192.168.48.100/qianyios/nginx:V1
[root@harbor1 ~]#
特别声明
千屹博客旗下的所有文章,是通过本人课堂学习和课外自学所精心整理的知识巨著
难免会有出错的地方
如果细心的你发现了小失误,可以在下方评论区告诉我,或者私信我!
非常感谢大家的热烈支持!