Harbor高可用(nginx和keepalived)
Harbor高可用(nginx和keepalived)
文章目录
- Harbor高可用(nginx和keepalived)
- 1.Harbor高可用集群部署架构
- 1.1 主机初始化
- 1.1.1 设置网卡名和ip地址
- 1.1.2 设置主机名
- 1.1.3 配置镜像源
- 1.1.4 关闭防火墙
- 1.1.5 禁用SELinux
- 1.1.6 设置时区
- 1.2 安装 Nginx
- 1.3 安装 Keepalived
- 1.4 安装harbor
- 1.5 创建harbor仓库
- 1.6 在docker客户端验证
1.Harbor高可用集群部署架构
本示例中的Harbor高可用集群部署将基于以下环境进行。

图1-1 Harbor高可用架构
表1-1 高可用Harbor集群规划
| 角色 | 机器名 | 机器配置 | ip地址 | 安装软件 |
|---|---|---|---|---|
| 提供高可用及负载均衡 | ha01.example.local | 2C2G | 172.31.3.104 | nginx、keepalived |
| 提供高可用及负载均衡 | ha02.example.local | 2C2G | 172.31.3.105 | nginx、keepalived |
| 容器镜像仓库1 | harbor01.example.local | 2C2G | 172.31.3.106 | docker、docker-compose、harbor |
| 容器镜像仓库2 | harbor02.example.local | 2C2G | 172.31.3.107 | docker、docker-compose、harbor |
| docker客户端 | client.example.local | 2C2G | 172.31.0.8 | docker |
| VIP,在ha01和ha02主机实现 | 172.31.3.188 |
1.1 主机初始化
1.1.1 设置网卡名和ip地址
Rocky 9和CentOS Stream 9:
# Rocky 9和CentOS Stream 9默认支持修改网卡名。
[root@rocky9 ~]# grep 'plugins' /etc/NetworkManager/NetworkManager.conf
#plugins=keyfile,ifcfg-rh
# 因为网卡命名方式默认是keyfile,默认不支持修改网卡名,既然官方已经默认是keyfile那这里就不去更改网卡名了。[root@rocky9 ~]# ETHNAME=`ip addr | awk -F"[ :]" '/^2/{print $3}'`[root@rocky9 ~]# nmcli con delete ${ETHNAME} && nmcli connection add type ethernet con-name ${ETHNAME} ifname ${ETHNAME} ipv4.method manual ipv4.address "172.31.0.9/21" ipv4.gateway "172.31.0.2" ipv4.dns "223.5.5.5,180.76.76.76" autoconnect yes && nmcli con reload && nmcli con up ${ETHNAME}
# 172.31.0.9/21中172.31.0.9是ip地址,21是子网位数;172.31.0.2是网关地址;223.5.5.5, 180.76.76.76都是DNS,根据自己的需求修改。[root@rocky9 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000link/ether 00:0c:29:37:62:95 brd ff:ff:ff:ff:ff:ffaltname enp3s0inet 172.31.0.9/21 brd 172.31.7.255 scope global noprefixroute ens160valid_lft forever preferred_lft foreverinet6 fe80::51ca:fd5d:3552:677d/64 scope link noprefixroute valid_lft forever preferred_lft forever
# 可以看到ip地址已修改。
Rocky 8、CentOS Stream 8和CentOS 7:
# Rocky 8、CentOS Stream 8和CentOS 7支持修改网卡名。
[root@rocky8 ~]# grep 'plugins' /etc/NetworkManager/NetworkManager.conf
#plugins=ifcfg-rh
# 因为网卡命名方式默认是ifcfg-rh,支持修改网卡名。# 修改网卡名称配置文件
[root@rocky8 ~]# sed -ri.bak '/^GRUB_CMDLINE_LINUX=/s@"$@ net.ifnames=0 biosdevname=0"@' /etc/default/grub
[root@rocky8 ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
done# 修改网卡文件名
[root@rocky8 ~]# ETHNAME=`ip addr | awk -F"[ :]" '/^2/{print $3}'`
[root@rocky8 ~]# mv /etc/sysconfig/network-scripts/ifcfg-${ETHNAME} /etc/sysconfig/network-scripts/ifcfg-eth0[root@rocky8 ~]# shutdown -r now[root@rocky8 ~]# nmcli dev
DEVICE TYPE STATE CONNECTION
eth0 ethernet connected Wired connection 1
lo loopback unmanaged --
# 可以看到CONNECTION的名字是Wired connection 1,要改名才可以下面设置。[root@rocky8 ~]# ETHNAME=`ip addr | awk -F"[ :]" '/^2/{print $3}'`[root@rocky8 ~]# nmcli connection modify "Wired connection 1" con-name ${ETHNAME}
[root@rocky8 ~]# nmcli dev
DEVICE TYPE STATE CONNECTION
eth0 ethernet connected eth0
lo loopback unmanaged -- # 修改ip地址
[root@rocky8 ~]# nmcli con delete ${ETHNAME} && nmcli connection add type ethernet con-name ${ETHNAME} ifname ${ETHNAME} ipv4.method manual ipv4.address "172.31.0.8/21" ipv4.gateway "172.31.0.2" ipv4.dns "223.5.5.5,180.76.76.76" autoconnect yes && nmcli con reload && nmcli dev up eth0
# 172.31.0.8/21中172.31.0.8是ip地址,21是子网位数;172.31.0.2是网关地址;223.5.5.5, 180.76.76.76都是DNS,根据自己的需求修改。[root@rocky8 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000link/ether 00:0c:29:6f:65:d3 brd ff:ff:ff:ff:ff:ffaltname enp3s0altname ens160inet 172.31.0.8/21 brd 172.31.7.255 scope global noprefixroute eth0valid_lft forever preferred_lft foreverinet6 fe80::e9c9:aa93:4a58:2cc2/64 scope link noprefixroute valid_lft forever preferred_lft forever
# 重启系统后可以看到网卡名已经修改成eth0,ip地址也已修改。
Ubuntu:
# Ubuntu先启用root用户,并设置密码
raymond@ubuntu2204:~$ cat set_root_login.sh
#!/bin/bashread -p "请输入密码: " PASSWORD
echo ${PASSWORD} |sudo -S sed -ri 's@#(PermitRootLogin )prohibit-password@\1yes@' /etc/ssh/sshd_config
sudo systemctl restart sshd
sudo -S passwd root <<-EOF
${PASSWORD}
${PASSWORD}
EOFraymond@ubuntu2204:~$ bash set_root_login.sh
请输入密码: 123456
[sudo] password for raymond: New password: Retype new password: passwd: password updated successfullyraymond@ubuntu2204:~$ rm -rf set_root_login.sh# 使用root登陆,修改网卡名
root@ubuntu2204:~# sed -ri.bak '/^GRUB_CMDLINE_LINUX=/s@"$@net.ifnames=0 biosdevname=0"@' /etc/default/grub
root@ubuntu2204:~# grub-mkconfig -o /boot/grub/grub.cfg
Sourcing file `/etc/default/grub'
Sourcing file `/etc/default/grub.d/init-select.cfg'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.15.0-88-generic
Found initrd image: /boot/initrd.img-5.15.0-88-generic
Warning: os-prober will not be executed to detect other bootable partitions.
Systems on them will not be added to the GRUB boot configuration.
Check GRUB_DISABLE_OS_PROBER documentation entry.
done# Ubuntu 20.04设置ip地址
root@ubuntu2004:~# cat > /etc/netplan/00-installer-config.yaml <<-EOF
network:version: 2renderer: networkdethernets:eth0:dhcp4: nodhcp6: noaddresses: [172.31.0.20/21] gateway4: 172.31.0.2nameservers:addresses: [223.5.5.5, 180.76.76.76]
EOF
# 说明:Ubuntu20.04网卡配置文件是00-installer-config.yaml;172.31.0.20/21中172.31.0.20是ip地址,21是子网位数;172.31.0.2是网关地址;223.5.5.5, 180.76.76.76都是DNS,根据自己的需求修改。# Ubuntu 18.04设置ip地址
root@ubuntu1804:~# cat > /etc/netplan/01-netcfg.yaml <<-EOF
network:version: 2renderer: networkdethernets:eth0:dhcp4: nodhcp6: noaddresses: [172.31.0.18/21] gateway4: 172.31.0.2nameservers:addresses: [223.5.5.5, 180.76.76.76]
EOF
# 说明:Ubuntu18.04网卡配置文件是01-netcfg.yaml;172.31.0.18/21中172.31.0.18是ip地址,21是子网位数;172.31.0.2是网关地址;223.5.5.5, 180.76.76.76都是DNS,根据自己的需求修改。root@ubuntu2004:~# shutdown -r nowroot@ubuntu2004:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000link/ether 00:0c:29:e5:98:6f brd ff:ff:ff:ff:ff:ffinet 172.31.0.20/21 brd 172.31.7.255 scope global eth0valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:fee5:986f/64 scope link valid_lft forever preferred_lft forever
# 重启系统后可以看到网卡名已经修改成eth0,ip地址也已修改。# Ubuntu 22.04设置ip地址
root@ubuntu2204:~# cat > /etc/netplan/00-installer-config.yaml <<-EOF
network:version: 2renderer: networkdethernets:eth0:dhcp4: nodhcp6: noaddresses: [172.31.0.22/21]routes:- to: defaultvia: 172.31.0.2nameservers:addresses: [223.5.5.5, 180.76.76.76]
EOF
# 说明:Ubuntu 22.04网卡配置文件是00-installer-config.yaml;172.31.0.22/21中172.31.0.22是ip地址,21是子网位数;172.31.0.2是网关地址,Ubuntu 22.04设置网关地址的方法发生了改变,参考上面的方法;223.5.5.5, 180.76.76.76都是DNS,根据自己的需求修改。root@ubuntu2204:~# shutdown -r now# 重启后使用新设置的ip登陆
root@ubuntu2204:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000link/ether 00:0c:29:a7:be:f2 brd ff:ff:ff:ff:ff:ffaltname enp2s1altname ens33inet 172.31.0.22/21 brd 172.31.7.255 scope global eth0valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:fea7:bef2/64 scope link valid_lft forever preferred_lft forever
# 重启系统后可以看到网卡名已经修改成eth0,ip地址也已修改。
1.1.2 设置主机名
hostnamectl set-hostname ha01.example.local
hostnamectl set-hostname ha02.example.local
hostnamectl set-hostname harbor01.example.local
hostnamectl set-hostname harbor02.example.local
hostnamectl set-hostname client.example.local
1.1.3 配置镜像源
Rocky 8和9:
MIRROR=mirrors.sjtug.sjtu.edu.cn
sed -i.bak -e 's|^mirrorlist=|#mirrorlist=|g' -e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://'${MIRROR}'/rocky|g' /etc/yum.repos.d/[Rr]ocky*.repodnf clean all && dnf makecache
CentOS Stream 9:
cat update_mirror.pl
#!/usr/bin/perluse strict;
use warnings;
use autodie;# 要修改镜像源,请去修改url变量!
my $url = 'mirrors.aliyun.com';
my $mirrors = "https://$url/centos-stream";if (@ARGV < 1) {die "Usage: $0 <filename1> <filename2> ...\n";
}while (my $filename = shift @ARGV) {my $backup_filename = $filename . '.bak';rename $filename, $backup_filename;open my $input, "<", $backup_filename;open my $output, ">", $filename;while (<$input>) {s/^metalink/# metalink/;if (m/^name/) {my (undef, $repo, $arch) = split /-/;$repo =~ s/^\s+|\s+$//g;($arch = defined $arch ? lc($arch) : '') =~ s/^\s+|\s+$//g;if ($repo =~ /^Extras/) {$_ .= "baseurl=${mirrors}/SIGs/\$releasever-stream/extras" . ($arch eq 'source' ? "/${arch}/" : "/\$basearch/") . "extras-common\n";} else {$_ .= "baseurl=${mirrors}/\$releasever-stream/$repo" . ($arch eq 'source' ? "/" : "/\$basearch/") . ($arch ne '' ? "${arch}/tree/" : "os") . "\n";}}print $output $_;}
}rpm -q perl &> /dev/null || { echo -e "\\033[01;31m "安装perl工具,请稍等..."\033[0m";yum -y install perl ; }perl ./update_mirror.pl /etc/yum.repos.d/centos*.repodnf clean all && dnf makecache
CentOS Stream 8:
MIRROR=mirrors.aliyun.com
sed -i.bak -e 's|^mirrorlist=|#mirrorlist=|g' -e 's|^#baseurl=http://mirror.centos.org/$contentdir|baseurl=https://'${MIRROR}'/centos|g' /etc/yum.repos.d/CentOS-*.repodnf clean all && dnf makecache
CentOS 7:
MIRROR=mirrors.aliyun.com
sed -i.bak -e 's|^mirrorlist=|#mirrorlist=|g' -e 's|^#baseurl=http://mirror.centos.org|baseurl=https://'${MIRROR}'|g' /etc/yum.repos.d/CentOS-*.repoyum clean all && yum makecache
Ubuntu 22.04和20.04:
MIRROR=mirrors.aliyun.com
OLD_MIRROR=`sed -rn "s@^deb http(.*)://(.*)/ubuntu/? $(lsb_release -cs) main.*@\2@p" /etc/apt/sources.list`sed -i.bak 's/'${OLD_MIRROR}'/'${MIRROR}'/g' /etc/apt/sources.listapt update
Ubuntu 18.04:
MIRROR=mirrors.aliyun.com
OLD_MIRROR=`sed -rn "s@^deb http(.*)://(.*)/ubuntu/? $(lsb_release -cs) main.*@\2@p" /etc/apt/sources.list`sed -i.bak 's/'${OLD_MIRROR}'/'${MIRROR}'/g' /etc/apt/sources.listSECURITY_MIRROR=`sed -rn "s@^deb http(.*)://(.*)/ubuntu $(lsb_release -cs)-security main.*@\2@p" /etc/apt/sources.list`sed -i.bak 's/'${SECURITY_MIRROR}'/'${MIRROR}'/g' /etc/apt/sources.listapt update
1.1.4 关闭防火墙
# Rocky和CentOS
systemctl disable --now firewalld# CentOS 7
systemctl disable --now NetworkManager# Ubuntu
systemctl disable --now ufw
1.1.5 禁用SELinux
#CentOS
setenforce 0
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config#Ubuntu
Ubuntu没有安装SELinux,不用设置
1.1.6 设置时区
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo 'Asia/Shanghai' >/etc/timezone#Ubuntu还要设置下面内容
cat >> /etc/default/locale <<-EOF
LC_TIME=en_DK.UTF-8
EOF
1.2 安装 Nginx
这里使用"一键编译安装nginx脚本"安装nginx,nginx的具体安装方法请参考博客“https://raymond.blog.csdn.net/article/details/135960659”。
[root@ha01 ~]# cat install_nginx.sh
#!/bin/bash
#
#************************************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2024-01-31
#FileName: install_nginx.sh
#URL: raymond.blog.csdn.net
#Description: install_haproxy for CentOS 7 & CentOS Stream 8/9 & Ubuntu 18.04/20.04/22.04 & Rocky 8/9
#Copyright (C): 2024 All rights reserved
#************************************************************************************************************
SRC_DIR=/usr/local/src
COLOR="echo -e \\033[01;31m"
END='\033[0m'NGINX_URL=https://nginx.org/download/
NGINX_FILE=nginx-1.24.0.tar.gz
NGINX_INSTALL_DIR=/apps/nginx
CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`
HARBOR01=172.31.3.106
HARBOR02=172.31.3.107os(){OS_ID=`sed -rn '/^NAME=/s@.*="([[:alpha:]]+).*"$@\1@p' /etc/os-release`
}check_file (){cd ${SRC_DIR}if [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;thenrpm -q wget &> /dev/null || { ${COLOR}"安装wget工具,请稍等..."${END};yum -y install wget &> /dev/null; }fiif [ ! -e ${NGINX_FILE} ];then${COLOR}"缺少${NGINX_FILE}文件"${END}${COLOR}'开始下载Nginx源码包'${END}wget ${NGINX_URL}${NGINX_FILE} || { ${COLOR}"Nginx源码包下载失败"${END}; exit; }else${COLOR}"${NGINX_FILE}文件已准备好"${END} fi
} install_nginx(){[ -d ${NGINX_INSTALL_DIR} ] && { ${COLOR}"Nginx已存在,安装失败"${END};exit; }${COLOR}"开始安装Nginx"${END}${COLOR}"开始安装Nginx依赖包,请稍等..."${END}if [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;thenyum -y install make gcc pcre-devel openssl-devel zlib-devel &> /dev/nullelseapt update &> /dev/null;apt -y install make gcc libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev &> /dev/nullfiid nginx &> /dev/null || { useradd -s /sbin/nologin -r nginx; ${COLOR}"创建Nginx用户"${END}; }tar xf ${NGINX_FILE}NGINX_DIR=`echo ${NGINX_FILE}| sed -nr 's/^(.*[0-9]).*/\1/p'`cd ${NGINX_DIR}./configure --prefix=${NGINX_INSTALL_DIR} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module make -j ${CPUS} && make install [ $? -eq 0 ] && ${COLOR}"Nginx编译安装成功"${END} || { ${COLOR}"Nginx编译安装失败,退出!"${END};exit; }chown -R nginx.nginx /apps/nginxecho "PATH=${NGINX_INSTALL_DIR}/sbin:${PATH}" > /etc/profile.d/nginx.shcat > ${NGINX_INSTALL_DIR}/conf/nginx.conf <<EOF
user nginx;
worker_processes 1;
error_log logs/error.log;
pid logs/nginx.pid;
events {worker_connections 1024;
}
stream {log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';access_log logs/access.log main;upstream harbor_server {hash \$remote_addr consistent;server ${HARBOR01}:80 max_fails=3 fail_timeout=30s;server ${HARBOR02}:80 max_fails=3 fail_timeout=30s;}server {listen 80;proxy_connect_timeout 1s;proxy_timeout 3s;proxy_pass harbor_server;}
}
EOFcat > /lib/systemd/system/nginx.service <<EOF
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target[Service]
Type=forking
PIDFile=${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStart=${NGINX_INSTALL_DIR}/sbin/nginx -c ${NGINX_INSTALL_DIR}/conf/nginx.conf
ExecReload=/bin/kill -s HUP \$MAINPID
ExecStop=/bin/kill -s TERM \$MAINPID
LimitNOFILE=100000[Install]
WantedBy=multi-user.target
EOFsystemctl daemon-reloadsystemctl enable --now nginx &> /dev/null systemctl is-active nginx &> /dev/null || { ${COLOR}"Nginx 启动失败,退出!"${END} ; exit; }${COLOR}"Nginx安装完成"${END}
}main(){oscheck_fileinstall_nginx
}main# 分别在ha01和ha02执行安装
[root@ha01 ~]# bash install_nginx.sh[root@ha02 ~]# bash install_nginx.sh
nginx.conf文件详解
[root@ha01 ~]#
user nginx; # 指定Nginx进程的运行用户
worker_processes 1; # 表示启动一个worker进程用于处理流量
error_log logs/error.log; # 错误日志路径
pid logs/nginx.pid; # pid路径
events {worker_connections 1024; # 表示每个worker进程可以同时处理最多1024个连接。
}# 四层负载均衡,为两台harbor提供负载均衡
stream {log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent'; # 日志格式access_log logs/access.log main; # 访问日志路径upstream harbor_server { # 在stream块里面,定义了一个名为`harbor_server`的upstream,用于负载均衡和故障转移。hash $remote_addr consistent;server 172.31.3.106:80 max_fails=3 fail_timeout=30s; # `server`指令用于定义后端的服务器,每个服务器都有一个IP地址和端口号,以及一些可选的参数;`max_fails=3`表示当一个服务器连续失败3次时将其标记为不可用;fail_timeout=30s`表示如果一个服务器被标记为不可用,nginx将在30秒后重新尝试。server 172.31.3.107:80 max_fails=3 fail_timeout=30s;}server {listen 80; # 在server块内部,定义了一个监听地址为80的服务器proxy_connect_timeout 1s; # 表示与后端服务器建立连接的超时时间为1秒。proxy_timeout 3s; # 表示与后端服务器建立连接的转发超时时间为2秒proxy_pass harbor_server; # 表示将流量代理到名为harbor_server的上游服务器组}
}
1.3 安装 Keepalived
这里使用"一键编译安装keepalived脚本"安装keepalived,keepalived的具体安装方法请参考博客“https://raymond.blog.csdn.net/article/details/135876134”。
# "check_nginx.sh"文件是nginx健康检查文件。
[root@ha01 ~]# cat check_nginx.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2022-01-09
#FileName: check_nginx.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2022 All rights reserved
#*********************************************************************************************
err=0
for k in $(seq 1 3);docheck_code=$(pgrep nginx)if [[ $check_code == "" ]]; thenerr=$(expr $err + 1)sleep 1continueelseerr=0breakfi
doneif [[ $err != "0" ]]; thenecho "systemctl stop keepalived"/usr/bin/systemctl stop keepalivedexit 1
elseexit 0
fi[root@ha01 ~]# cat install_keepalived_v2.sh
#!/bin/bash
#
#************************************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2024-01-26
#FileName: install_keepalived_v2.sh
#URL: raymond.blog.csdn.net
#Description: install_keepalived for CentOS 7 & CentOS Stream 8/9 & Ubuntu 18.04/20.04/22.04 & Rocky 8/9
#Copyright (C): 2024 All rights reserved
#************************************************************************************************************
SRC_DIR=/usr/local/src
COLOR="echo -e \\033[01;31m"
END='\033[0m'
KEEPALIVED_URL=https://keepalived.org/software/
KEEPALIVED_FILE=keepalived-2.2.8.tar.gz
KEEPALIVED_INSTALL_DIR=/apps/keepalived
CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`
NET_NAME=`ip a |awk -F"[: ]" '/^2/{print $3}'`
VIP=172.31.3.188os(){OS_ID=`sed -rn '/^NAME=/s@.*="([[:alpha:]]+).*"$@\1@p' /etc/os-release`OS_RELEASE_VERSION=`sed -rn '/^VERSION_ID=/s@.*="?([0-9]+)\.?.*"?@\1@p' /etc/os-release`
}check_file (){cd ${SRC_DIR}if [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;thenrpm -q wget &> /dev/null || { ${COLOR}"安装wget工具,请稍等..."${END};yum -y install wget &> /dev/null; }fiif [ ! -e ${KEEPALIVED_FILE} ];then${COLOR}"缺少${KEEPALIVED_FILE}文件,如果是离线包,请放到${SRC_DIR}目录下"${END}${COLOR}'开始下载Keepalived源码包'${END}wget ${KEEPALIVED_URL}${KEEPALIVED_FILE} || { ${COLOR}"Keepalived源码包下载失败"${END}; exit; }elif [ ! -e check_nginx.sh ];then${COLOR}"缺少check_nginx.sh文件,请把文件放到${SRC_DIR}目录下"${END}exitelse${COLOR}"相关文件已准备好"${END}fi
}install_keepalived(){${COLOR}"开始安装Keepalived,请稍等..."${END}${COLOR}"开始安装Keepalived依赖包,请稍等..."${END}if [ ${OS_ID} == "Rocky" -a ${OS_RELEASE_VERSION} == 8 ];thenMIRROR=mirrors.sjtug.sjtu.edu.cnif [ `grep -R "\[powertools\]" /etc/yum.repos.d/*.repo` ];thendnf config-manager --set-enabled powertoolselsecat > /etc/yum.repos.d/PowerTools.repo <<-EOF
[PowerTools]
name=PowerTools
baseurl=https://${MIRROR}/rocky/\$releasever/PowerTools/\$basearch/os/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial
EOFfifiif [ ${OS_ID} == "CentOS" -a ${OS_RELEASE_VERSION} == 8 ];thenMIRROR=mirrors.aliyun.comif [ `grep -R "\[powertools\]" /etc/yum.repos.d/*.repo` ];thendnf config-manager --set-enabled powertoolselsecat > /etc/yum.repos.d/PowerTools.repo <<-EOF
[PowerTools]
name=PowerTools
baseurl=https://${MIRROR}/centos/\$stream/PowerTools/\$basearch/os/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
EOFfifiif [ ${OS_RELEASE_VERSION} == 9 ];thenyum -y install make gcc ipvsadm autoconf automake openssl-devel libnl3-devel iptables-devel ipset file net-snmp-devel glib2-devel pcre2-devel libnftnl libmnl systemd-devel &> /dev/nullelif [ ${OS_RELEASE_VERSION} == 8 ];then yum -y install make gcc ipvsadm autoconf automake openssl-devel libnl3-devel iptables-devel ipset-devel file-devel net-snmp-devel glib2-devel pcre2-devel libnftnl-devel libmnl-devel systemd-devel &> /dev/nullelif [ ${OS_RELEASE_VERSION} == 7 ];thenyum -y install make gcc libnfnetlink-devel libnfnetlink ipvsadm libnl libnl-devel libnl3 libnl3-devel lm_sensors-libs net-snmp-agent-libs net-snmp-libs openssh-server openssh-clients openssl openssl-devel automake iproute &> /dev/nullelif [ ${OS_RELEASE_VERSION} == "20" -o ${OS_RELEASE_VERSION} == "22" ];thenapt update &> /dev/null;apt -y install make gcc ipvsadm build-essential pkg-config automake autoconf libipset-dev libnl-3-dev libnl-genl-3-dev libssl-dev libxtables-dev libip4tc-dev libip6tc-dev libipset-dev libmagic-dev libsnmp-dev libglib2.0-dev libpcre2-dev libnftnl-dev libmnl-dev libsystemd-develseapt update &> /dev/null;apt -y install make gcc ipvsadm build-essential pkg-config automake autoconf iptables-dev libipset-dev libnl-3-dev libnl-genl-3-dev libssl-dev libxtables-dev libip4tc-dev libip6tc-dev libipset-dev libmagic-dev libsnmp-dev libglib2.0-dev libpcre2-dev libnftnl-dev libmnl-dev libsystemd-dev &> /dev/nullfitar xf ${KEEPALIVED_FILE}KEEPALIVED_DIR=`echo ${KEEPALIVED_FILE} | sed -nr 's/^(.*[0-9]).*/\1/p'`cd ${KEEPALIVED_DIR}./configure --prefix=${KEEPALIVED_INSTALL_DIR} --disable-fwmarkmake -j $CPUS && make install[ $? -eq 0 ] && $COLOR"Keepalived编译安装成功"$END || { $COLOR"Keepalived编译安装失败,退出!"$END;exit; }[ -d /etc/keepalived ] || mkdir -p /etc/keepalived &> /dev/nullread -p "请输入是主服务断或备用服务端,例如(MASTER或BACKUP): " STATEread -p "请输入优先级,例如(100或80): " PRIORITYcat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalivedglobal_defs {router_id LVS_DEVELscript_user rootenable_script_security
}vrrp_script check_nginx {script "/etc/keepalived/check_nginx.sh"interval 5weight -5fall 2 rise 1
}vrrp_instance VI_1 {state ${STATE}interface ${NET_NAME}virtual_router_id 51priority ${PRIORITY}advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {${VIP} dev ${NET_NAME} label ${NET_NAME}:1 }track_script {check_nginx}
}
EOFcp ./keepalived/keepalived.service /lib/systemd/system/cd ${SRC_DIR}mv check_nginx.sh /etc/keepalived/check_nginx.shchmod +x /etc/keepalived/check_nginx.shecho "PATH=${KEEPALIVED_INSTALL_DIR}/sbin:${PATH}" > /etc/profile.d/keepalived.shsystemctl daemon-reloadsystemctl enable --now keepalived &> /dev/null systemctl is-active keepalived &> /dev/null || { ${COLOR}"Keepalived 启动失败,退出!"${END} ; exit; }${COLOR}"Keepalived安装完成"${END}
}main(){oscheck_fileinstall_keepalived
}main# 分别在ha01和ha02执行安装
[root@ha01 ~]# bash install_keepalived_v2.sh
...
请输入是主服务断或备用服务端,例如(MASTER或BACKUP): MASTER
请输入优先级,例如(100或80): 100[root@ha02 ~]# bash install_keepalived_v2.sh
...
请输入是主服务断或备用服务端,例如(MASTER或BACKUP): BACKUP
请输入优先级,例如(100或80): 80
1.4 安装harbor
这里使用"基于docker二进制包一键安装Harbor脚本"安装harbor,harbor的具体安装方法请参考博客“https://raymond.blog.csdn.net/article/details/135882947”。
[root@harbor01 ~]# cat install_harbor_http_v2_2.sh
#!/bin/bash
#
#******************************************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2024-01-26
#FileName: install_harbor_http_v2_2.sh
#URL: raymond.blog.csdn.net
#Description: install_harbor_http for CentOS 7 & CentOS Stream 8/9 & Ubuntu 18.04/20.04/22.04 & Rocky 8/9
#Copyright (C): 2024 All rights reserved
#******************************************************************************************************************
SRC_DIR=/usr/local/src
COLOR="echo -e \\033[01;31m"
END='\033[0m'DOCKER_VERSION=24.0.7
DOCKER_MAIN_VERSION=`echo ${DOCKER_VERSION} | awk -F'.' '{print $1}'`
URL='mirrors.aliyun.com'# Docker Compose下载地址:“https://github.com/docker/compose/releases/download/v2.23.3/docker-compose-linux-x86_64”,请提前下载。
DOCKER_COMPOSE_FILE=docker-compose-linux-x86_64# Harbor下载地址:“https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz”,请提前下载。
HARBOR_FILE=harbor-offline-installer-v
HARBOR_VERSION=2.10.0
TAR=.tgz
HARBOR_INSTALL_DIR=/apps
HARBOR_DOMAIN=harbor.raymonds.cc
NET_NAME=`ip addr |awk -F"[: ]" '/^2: e.*/{print $3}'`
IP=`ip addr show ${NET_NAME}| awk -F" +|/" '/global/{print $3}'`
HARBOR_ADMIN_PASSWORD=123456os(){OS_ID=`sed -rn '/^NAME=/s@.*="([[:alpha:]]+).*"$@\1@p' /etc/os-release`OS_RELEASE_VERSION=`sed -rn '/^VERSION_ID=/s@.*="?([0-9]+)\.?.*"?@\1@p' /etc/os-release`
}check_file (){cd ${SRC_DIR}if [ ! -e ${DOCKER_COMPOSE_FILE} ];then${COLOR}"缺少${DOCKER_COMPOSE_FILE}文件,请把文件放到${SRC_DIR}目录下"${END}exitelif [ ! -e ${HARBOR_FILE}${HARBOR_VERSION}${TAR} ];then${COLOR}"缺少${HARBOR_FILE}${HARBOR_VERSION}${TAR}文件,请把文件放到${SRC_DIR}目录下"${END}exitelse${COLOR}"相关文件已准备好"${END}fi
}ubuntu_install_docker(){${COLOR}"开始安装Docker依赖包,请稍等..."${END}apt update &> /dev/nullapt -y install apt-transport-https ca-certificates curl software-properties-common &> /dev/nullcurl -fsSL https://${URL}/docker-ce/linux/ubuntu/gpg | sudo apt-key add - &> /dev/nulladd-apt-repository -y "deb [arch=amd64] https://${URL}/docker-ce/linux/ubuntu $(lsb_release -cs) stable" &> /dev/null apt update &> /dev/null${COLOR}"Docker有以下版本"${END}apt-cache madison docker-ce${COLOR}"10秒后即将安装:Docker-"${DOCKER_VERSION}"版本......"${END}${COLOR}"如果想安装其它Docker版本,请按Ctrl+c键退出,修改版本再执行"${END}sleep 10${COLOR}"开始安装Docker,请稍等..."${END}if [ ${DOCKER_MAIN_VERSION} == "18" -o ${DOCKER_MAIN_VERSION} == "19" -o ${DOCKER_MAIN_VERSION} == "20" ];thenapt -y install docker-ce=5:${DOCKER_VERSION}~3-0~ubuntu-$(lsb_release -cs) docker-ce-cli=5:${DOCKER_VERSION}~3-0~ubuntu-$(lsb_release -cs) &> /dev/null || { ${COLOR}"apt源失败,请检查apt配置"${END};exit; }elseapt -y install docker-ce=5:${DOCKER_VERSION}-1~ubuntu.$(lsb_release -rs)~$(lsb_release -cs) docker-ce-cli=5:${DOCKER_VERSION}-1~ubuntu.$(lsb_release -rs)~$(lsb_release -cs) &> /dev/null || { ${COLOR}"apt源失败,请检查apt配置"${END};exit; }fi
}centos_install_docker(){${COLOR}"开始安装Docker依赖包,请稍等..."${END}yum -y install yum-utils &> /dev/nullyum-config-manager --add-repo https://${URL}/docker-ce/linux/centos/docker-ce.repo &> /dev/nullyum clean all &> /dev/nullyum makecache &> /dev/null${COLOR}"Docker有以下版本"${END}yum list docker-ce.x86_64 --showduplicates${COLOR}"10秒后即将安装:Docker-"${DOCKER_VERSION}"版本......"${END}${COLOR}"如果想安装其它Docker版本,请按Ctrl+c键退出,修改版本再执行"${END}sleep 10${COLOR}"开始安装Docker,请稍等..."${END}yum -y install docker-ce-${DOCKER_VERSION} docker-ce-cli-${DOCKER_VERSION} &> /dev/null || { ${COLOR}"yum源失败,请检查yum配置"${END};exit; }
}mirror_accelerator(){mkdir -p /etc/dockercat > /etc/docker/daemon.json <<-EOF
{"registry-mirrors": ["https://registry.docker-cn.com","https://hub-mirror.c.163.com","https://docker.mirrors.ustc.edu.cn"],"insecure-registries": ["${HARBOR_DOMAIN}"],"data-root": "/data/docker","exec-opts": ["native.cgroupdriver=systemd"],"max-concurrent-downloads": 10,"max-concurrent-uploads": 5,"log-opts": {"max-size": "300m","max-file": "2" },"live-restore": true
}
EOFsystemctl daemon-reloadsystemctl enable --now dockersystemctl is-active docker &> /dev/null && ${COLOR}"Docker 服务启动成功"${END} || { ${COLOR}"Docker 启动失败"${END};exit; }docker version && ${COLOR}"Docker 安装成功"${END} || ${COLOR}"Docker 安装失败"${END}
}set_alias(){echo 'alias rmi="docker images -qa|xargs docker rmi -f"' >> ~/.bashrcecho 'alias rmc="docker ps -qa|xargs docker rm -f"' >> ~/.bashrc
}install_docker_compose(){${COLOR}"开始安装Docker Compose,请稍等..."${END}mv ${SRC_DIR}/${DOCKER_COMPOSE_FILE} /usr/bin/docker-composechmod +x /usr/bin/docker-composedocker-compose --version && ${COLOR}"Docker Compose 安装完成"${END} || ${COLOR}"Docker compose 安装失败"${END}
}install_harbor(){${COLOR}"开始安装Harbor,请稍等..."${END}[ -d ${HARBOR_INSTALL_DIR} ] || mkdir ${HARBOR_INSTALL_DIR}tar xf ${SRC_DIR}/${HARBOR_FILE}${HARBOR_VERSION}${TAR} -C ${HARBOR_INSTALL_DIR}/mv ${HARBOR_INSTALL_DIR}/harbor/harbor.yml.tmpl ${HARBOR_INSTALL_DIR}/harbor/harbor.ymlsed -ri.bak -e 's/^(hostname:) .*/\1 '${IP}'/' -e 's/^(https:)/#\1/' -e 's/ (port: 443)/# \1/' -e 's@ (certificate: .*)@# \1@' -e 's@ (private_key: .*)@# \1@' -e 's/^(harbor_admin_password:) .*/\1 '${HARBOR_ADMIN_PASSWORD}'/' ${HARBOR_INSTALL_DIR}/harbor/harbor.ymlif [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;thenrpm -q python3 &> /dev/null || { ${COLOR}"安装python3,请稍等..."${END};yum -y install python3 &> /dev/null; }elsedpkg -s python3 &>/dev/null || { ${COLOR}"安装python3,请稍等..."${END};apt -y install python3 &> /dev/null; }fi${HARBOR_INSTALL_DIR}/harbor/install.sh --with-trivy && ${COLOR}"Harbor 安装完成"${END} || ${COLOR}"Harbor 安装失败"${END}cat > /lib/systemd/system/harbor.service <<-EOF
[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/bin/docker-compose -f ${HARBOR_INSTALL_DIR}/harbor/docker-compose.yml up
ExecStop=/usr/bin/docker-compose -f ${HARBOR_INSTALL_DIR}/harbor/docker-compose.yml down[Install]
WantedBy=multi-user.target
EOFsystemctl daemon-reload systemctl enable harbor &>/dev/null && ${COLOR}"Harbor已配置为开机自动启动"${END}
}set_swap_limit(){if [ ${OS_RELEASE_VERSION} == "18" -o ${OS_RELEASE_VERSION} == "20" ];thengrep -q "swapaccount=1" /etc/default/grub && { ${COLOR}'"WARNING: No swap limit support"警告,已设置'${END};exit; }${COLOR}'设置Docker的"WARNING: No swap limit support"警告'${END}sed -ri '/^GRUB_CMDLINE_LINUX=/s@"$@ swapaccount=1"@' /etc/default/grubupdate-grub &> /dev/null${COLOR}"10秒后,机器会自动重启"${END}sleep 10rebootfi
}main(){oscheck_fileif [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;thenrpm -q docker-ce &> /dev/null && ${COLOR}"Docker已安装"${END} || centos_install_dockerelsedpkg -s docker-ce &>/dev/null && ${COLOR}"Docker已安装"${END} || ubuntu_install_dockerfi[ -f /etc/docker/daemon.json ] &>/dev/null && ${COLOR}"Docker镜像加速器已设置"${END} || mirror_acceleratorgrep -Eqoi "(.*rmi=|.*rmc=)" ~/.bashrc && ${COLOR}"Docker别名已设置"${END} || set_alias[ -f /usr/bin/docker-compose ] && ${COLOR}"Docker Compose已安装"${END} || install_docker_composesystemctl is-active harbor &> /dev/null && ${COLOR}"Harbor已安装"${END} || install_harborset_swap_limit
}main# 分别在harbor01和harbor02执行安装
[root@harbor01 ~]# bash install_harbor_http_v2_2.sh[root@harbor02 ~]# bash install_harbor_http_v2_2.sh
1.5 创建harbor仓库
在harbor01新建项目google_containers。
http://172.31.3.106/
用户名:admin 密码:123456

图1-2 登录harbor01
登录后,在“项目”下面选择“新建项目”。

图1-3 在harbor01上新建项目
项目名称设置为“google_containers”,访问级别后面勾选“公开”,然后选“确认”。

图1-4 在harbor01上创建google_containers项目
在harbor02新建项目google_containers
http://172.31.3.107/
用户名:admin 密码:123456

图1-5 登录harbor02
登录后,在“项目”下面选择“新建项目”。

图1-6 在harbor02上新建项目
项目名称设置为“google_containers”,访问级别后面勾选“公开”,然后选“确认”。

图1-7 在harbor01上创建google_containers项目
在harbor02上新建目标
在“系统管理”下面的“仓库管理”里面选择“新建目标”。

图1-8 在harbor02上新建目标
提供者设置为“Harbor”,目标名设置为“google_containers”,目标URL设置为harbor01的地址“http://172.31.3.106”,访问ID设置为harbor01的用户名“admin”,访问密码设置为harbor01的密码“123456”,然后“测试连接”,测试成功后选择“确定”。

图1-9 在harbor02上新建目标
在harbor02上新建规则
在“系统管理”下面的“复制管理”里面选择“新建规则”。

图1-10 在harbor02上新建规则
名称设置为“google_containers”,目标仓库选择“google_containers-http://172.31.0.106”,触发模式设置为“事件驱动”,勾选“删除本地资源时同时也删除远程的资源 ”,然后选择“保存”。

图1-11 在harbor02上新建规则
在harbor01上新建目标
在“系统管理”下面的“仓库管理”里面选择“新建目标”。

图1-12 在harbor01上新建目标
提供者设置为“Harbor”,目标名设置为“google_containers”,目标URL设置为harbor01的地址“http://172.31.3.107”,访问ID设置为harbor01的用户名“admin”,访问密码设置为harbor01的密码“123456”,然后“测试连接”,测试成功后选择“确定”。

图1-13 在harbor01上新建目标
在harbor01上新建规则
在“系统管理”下面的“复制管理”里面选择“新建规则”。

图1-14 在harbor01上新建规则
名称设置为“google_containers”,目标仓库选择“google_containers-http://172.31.0.107”,触发模式设置为“事件驱动”,勾选“删除本地资源时同时也删除远程的资源 ”,然后选择“保存”。

图1-15 在harbor01上新建规则
1.6 在docker客户端验证
在172.31.0.8的Rocky 8的主机上无需登录,即可下载镜像
首先要主机初始化和安装docker
[root@client ~]# cat >> /etc/hosts <<-EOF
172.31.3.188 harbor.raymonds.cc
EOF[root@client ~]# docker login harbor.raymonds.cc
Username: admin
Password:
Error response from daemon: Get "https://harbor.raymonds.cc/v2/": dial tcp 172.31.3.188:443: connect: connection refuse
# 登录失败[root@client ~]# cat /etc/docker/daemon.json
{"registry-mirrors": ["https://registry.docker-cn.com","https://hub-mirror.c.163.com","https://docker.mirrors.ustc.edu.cn"],"insecure-registries": ["harbor.raymonds.cc"], # 设置非安全的镜像仓库"data-root": "/data/docker","exec-opts": ["native.cgroupdriver=systemd"],"max-concurrent-downloads": 10,"max-concurrent-uploads": 5,"log-opts": {"max-size": "300m","max-file": "2" },"live-restore": true
}[root@client ~]# systemctl daemon-reload && systemctl restart docker[root@client ~]# docker login harbor.raymonds.cc
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-storeLogin Succeeded
# 现在登录成功了[root@client ~]# docker pull alpine[root@client ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 05455a08881e 3 days ago 7.38MB[root@client ~]# docker tag alpine harbor.raymonds.cc/google_containers/alpine[root@client ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 05455a08881e 3 days ago 7.38MB
harbor.raymonds.cc/google_containers/alpine latest 05455a08881e 3 days ago 7.38MB[root@client ~]# docker push harbor.raymonds.cc/google_containers/alpine
Using default tag: latest
The push refers to repository [harbor.raymonds.cc/google_containers/alpine]
d4fc045c9e3a: Pushed
latest: digest: sha256:6457d53fb065d6f250e1504b9bc42d5b6c65941d57532c072d929dd0628977d0 size: 528
在harbor01上查看镜像已经上传。

图1-16 在harbor01上查看镜像上传情况
在harbor02上查看镜像已经上传。

图1-17 在harbor02上查看镜像上传情况
从上面可以看出harbor01和harbor02镜像仓库是高可用的。
# 删除所有镜像
[root@client ~]# docker images -qa|xargs docker rmi -f[root@client ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE# 从harbor仓库拉取镜像
[root@client ~]# docker pull harbor.raymonds.cc/google_containers/alpine
Using default tag: latest
latest: Pulling from google_containers/alpine
4abcf2066143: Pull complete
Digest: sha256:6457d53fb065d6f250e1504b9bc42d5b6c65941d57532c072d929dd0628977d0
Status: Downloaded newer image for harbor.raymonds.cc/google_containers/alpine:latest
harbor.raymonds.cc/google_containers/alpine:latest[root@client ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
harbor.raymonds.cc/google_containers/alpine latest 05455a08881e 3 days ago 7.38MB
# 可以看到harbor仓库的镜像也是可以拉取到本地的
相关文章:
Harbor高可用(nginx和keepalived)
Harbor高可用(nginx和keepalived) 文章目录 Harbor高可用(nginx和keepalived)1.Harbor高可用集群部署架构1.1 主机初始化1.1.1 设置网卡名和ip地址1.1.2 设置主机名1.1.3 配置镜像源1.1.4 关闭防火墙1.1.5 禁用SELinux1.1.6 设置时…...
[数据集][目标检测]牛羊检测数据集VOC+YOLO格式3393张2类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):3393 标注数量(xml文件个数):3393 标注数量(txt文件个数):3393 标注…...
命令提示符——CMD基础操作介绍
💞💞 前言 hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页&#x…...
vue2 自定义 v-model (model选项的使用)
效果预览 model 选项的语法 每个组件上只能有一个 v-model。v-model 默认会占用名为 value 的 prop 和名为 input 的事件,即 model 选项的默认值为 model: {prop: "value",event: "input",},通过修改 model 选项,即可自定义v-model …...
智慧城市中的智慧生活:便捷、舒适与高效
目录 一、智慧城市中的智慧生活概述 二、智慧生活带来的便捷性 1、智慧交通的便捷出行 2、智慧购物的轻松体验 3、智慧政务的一站式服务 三、智慧生活带来的舒适性 1、智慧环境的绿色宜居 2、智慧医疗的健康保障 3、智慧教育的均衡发展 四、智慧生活带来的高效性 1、…...
时代教育期刊投稿发表
《时代教育》是由成都传媒集团主管主办,中华人民共和国新闻出版总署批准国内公开出版发行的专业教育类期刊,主要刊登各类高等院校、职业技术学校、中小学教师及研究生、教育科研工作者的教育实践研究成果;教育教学行业的最新动态;…...
每日OJ题_子数组子串dp⑥_力扣978. 最长湍流子数组
目录 力扣978. 最长湍流子数组 解析代码 力扣978. 最长湍流子数组 978. 最长湍流子数组 难度 中等 给定一个整数数组 arr ,返回 arr 的 最大湍流子数组的长度 。 如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是 湍流子数组 。 更正…...
蓝桥练习题总结(一)字母图形、完美的代价、01串、序列求和
目录 一、字母图形 二、完美的代价 三、01字串 四、序列求和 一、字母图形 问题描述 利用字母可以组成一些美丽的图形,下面给出了一个例子: ABCDEFG BABCDEF CBABCDE DCBABCD EDCBABC 这是一个5行7列的图形,请找出这个图形的规律ÿ…...
Android 静默安装二(无障碍服务版)
近期开发上线一个常驻app,项目已上线,今天随笔记录一下静默安装相关内容。我分三篇静默安装(root版)、静默安装(无障碍版)、监听系统更新、卸载、安装。 先说说我的项目需求:要求app一直运行&am…...
蓝桥杯 EDA 组 2023模拟+真题原理图解析
本文解析了标题内的原理图蓝桥杯EDA组真题,2021-2022 省赛真题/模拟题在上一篇文中。本文中重复或者是简单的电路节约篇幅不在赘述。 其中需要补充和计算原理图的题目解析都放在最下面 一、2023 年第十四届省赛模拟题1 1.1 Type-C 接口电路 通过 CH340N 将数据转化为…...
聊聊功率器件(氮化镓,碳化硅)
氮化镓和碳化硅是两种具有独特性质和广泛应用的无机物。下面将尽可能详细地解释它们的定义、应用、研究热点以及对我们的价值。 1,氮化镓 氮化镓(GaN)是一种由氮和镓元素组成的化合物,具有直接能隙的半导体特性。其结构类似于纤…...
计算地球圆盘负荷产生的位移
1.研究背景 计算受表面载荷影响的弹性体变形问题有着悠久的历史,涉及到许多著名的数学家和物理学家(Boussinesq 1885;Lamb 1901;Love 1911,1929;Shida 1912;Terazawa 1916;Munk &…...
Harbor介绍
1.什么是Harbor Harbor是一个开源的企业级Docker Registry管理项目,由VMware公司开源。 Harbor提供了比Docker官方公共镜像仓库更为丰富和安全的功能,尤其适合企业环境使用。以下是Harbor的一些关键特性: 权限管理(RBAC&#x…...
解决jenkins运行磁盘满的问题
参考:https://blog.csdn.net/ouyang_peng/article/details/79225993 分配磁盘空间相关操作: https://cloud.tencent.com/developer/article/2230624 登录jenkins相对应的服务或容器中查看磁盘情况: df -h在102挂载服务器上看到是这两个文件…...
使用echart绘制拓扑图,树类型,自定义tooltip和label样式,可收缩
效果如图: 鼠标移上显示 vue3 - ts文件 “echarts”: “^5.4.3”, import { EChartsOption } from echarts import * as echarts from echarts/core import { TooltipComponent } from echarts/components import { TreeChart } from echarts/charts import { C…...
常用的6个的ChatGPT网站,国内可用!
GPTGod 🌐 链接: GPTGod 🏷️ 标签: GPT-4 免费体验 支持API 支持绘图 付费选项 📝 简介:GPTGod 是一个功能全面的平台,提供GPT-4的强大功能,包括API接入和绘图支持。用户可以选择免…...
Linux课程____Samba文件共享服务
一、 Samba服务基础 SMB协议,服务消息块 CIFS协议,通用互联网文件系统 1.Samba 服务器的主要程序 smbd:提供对服务器中文件、打印资源的共享访问 nmbd:提供基于 NetBlOS 主机名称的解析 2.目录文件 /etc/samba/smb.conf 检查工具:test…...
Java学习day1
打开命令提示符(cmd)窗口: 按下winR键,输入cmd 按回车或点击确定,打开cmd窗口 常用cmd命令 盘符名称冒号(D:):盘符切换,示例表示由C盘切换到D盘 dir:查看当前路径下的内…...
ByteTrack多目标跟踪——YOLOX详解
文章目录 1 before train1.1 dataset1.2 model 2 train2.1 Backbone2.2 PAFPN2.3 Head2.3.1 Decoupled Head2.3.2 anchor-free2.3.3 标签分配① 初步筛选② simOTA 2.3.4 Loss计算 项目地址: ByteTrack ByteTrack使用的检测器是YOLOX,是一个目前非常流行…...
Linux 常见驱动框架
一、V4L2驱动框架 v4l2驱动框架主要对象: (1)video_device:一个字符设备,为用户空间提供设备节点(/dev/videox),提供系统调用的相关操作(open、ioctl…) (2)v4l2_device:…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
