、迁移背景说明
本次服务器硬件为 LGA‑775 架构老旧台式主机,双核处理器性能有限,整机内存 7.72GB,内存资源充裕。
最开始部署 Harbor 镜像仓库时,存储目录使用程序默认路径/var/lib/harbor,该目录归属系统盘分区。随着容器镜像、项目版本不断增加,镜像文件体积会持续上涨,系统盘存储空间较小,长期运行极易出现磁盘占满、服务器系统崩溃的问题。
服务器大容量数据分区路径为/opt/mirror,该目录原本用于存放 apt‑mirror 内网 APT 软件安装包镜像源。为充分利用该分区富余磁盘空间,决定将整套 Harbor 镜像仓库迁移至此目录下。
目录隔离设计思路
/opt/mirror 需要承载两套独立存储业务:
apt‑mirror:deb 格式系统安装包内网镜像源
Harbor:Docker 容器镜像仓库
为防止日常管理 APT 软件源的时候误删、混淆镜像仓库目录,Harbor 的数据目录、日志目录采用 Linux 隐藏文件夹进行隔离:
/opt/mirror/.harbor_data:容器镜像持久化存储目录/opt/mirror/.harbor_log:Harbor 服务运行日志目录
普通可见目录专门管理 APT 软件源资源,隐藏目录存放容器仓库,两项业务互不干扰
为什么需要依托 Docker 容器运行 Harbor
Harbor 本身是由数据库、缓存、存储服务、反向网关等多个组件组成的容器化项目,所有服务依靠 Docker 容器启动运行;
磁盘文件夹只负责静态存放镜像文件、日志、数据库数据;容器才是真正读取、加载、运行仓库程序的载体;
迁移全程逻辑:容器生成完整仓库目录结构 → 备份原有全部数据 → 迁移文件至新分区 → 修改配置指向新路径 → 重启容器加载新路径内的镜像资源。
老旧 775 平台服务器额外优化要点
本机为双核 LGA‑775 处理器,CPU 性能偏弱,rsync 批量文件拷贝、apt‑mirror 软件源同步均会大量消耗 CPU 资源;
大批量文件拷贝任务可添加传输限速,降低 CPU 与磁盘 IO 负载:
bash
rsync -av --bwlimit=30 源路径 目标路径
两个 IO 密集型业务错峰运行,不要同时开启 APT 源同步与仓库迁移;
本机内存充足,硬件瓶颈仅为双核处理器,后续可以选购 65W 低功耗四核 Xeon L3360 进行硬件升级。
六、迁移最终收益
将容器镜像仓库脱离系统盘,规避镜像文件膨胀塞满系统分区的风险;
利用隐藏文件夹隔离 APT 软件源与 Docker 镜像仓库,避免日常操作误删;
数据独立存放至大容量磁盘分区,服务器后续重装系统不会丢失容器镜像资源,方便后期备份与维护查看,harbor 镜像仓库,存储
du -lh --max-depth=1 /var/harbor_data.bak | sort -hr
shitou@shitou:~$ sudo du -lh --max-depth=1 /var | sort -hr
[sudo] password for shitou:
du: cannot access '/var/lib/docker/overlay2/27764b807de140f75d0d41362cda8711161ae08606cea879058166bf4a29aeff': No such file or directory
36G /var
29G /var/harbor_data.bak
5.5G /var/lib
772M /var/log
709M /var/cache
3.6M /var/crash
3.0M /var/backups
64K /var/tmp
32K /var/spool
24K /var/www
4.0K /var/snap
4.0K /var/opt
4.0K /var/mail
4.0K /var/local
镜像仓库
apt-mirror ca_download database iso job_logs mirrors redis registry secret
表格
目录 用途说明
registry 核心,存放所有 docker 镜像文件,一般占用磁盘最大
database Harbor 数据库,存储项目、账号、配置元数据
redis 缓存、会话数据
job_logs 仓库任务运行日志
iso、mirrors 同步镜像、离线镜像资源进入配置目录,查看有哪些配置文件,
cd harbor
root@shitou:/home/shitou/harbor# ls
common common.sh docker-compose.yml harbor-offline-installer-v2.13.1.tgz harbor-offline-installer-v2.13.1.tgz.1 harbor.v2.13.1.tar.gz harbor.yml harbor.yml.tmpl install.sh LICENSE prepare
root@shitou:/home/shitou/harbor#
root@shitou:/home/shitou/harbor# cat harbor.yml
# Configuration file of Harbor
# 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 改为目标IP 192.168.31.19
hostname: 192.168.31.19
# http related config
http:
# port for http, default is 80. If https enabled, this port will redirect to https port
port: 80
# https related config
https:
# https port for harbor, default is 443
port: 443
# The path of cert and key files for nginx
# 👇 已修改:证书路径匹配你生成的 IP 证书位置
certificate: /etc/harbor/ssl/harbor.crt
private_key: /etc/harbor/ssl/harbor.key
# enable strong ssl ciphers (default: false)
# strong_ssl_ciphers: false
# # Harbor will set ipv4 enabled only by default if this block is not configured
# # Otherwise, please uncomment this block to configure your own ip_family stacks
# ip_family:
# # ipv6Enabled set to true if ipv6 is enabled in docker network, currently it affected the nginx related component
# ipv6:
# enabled: false
# # ipv4Enabled set to true by default, currently it affected the nginx related component
# ipv4:
# enabled: true
# # Uncomment following will enable tls communication between all harbor components
# internal_tls:
# # set enabled to true means internal tls is enabled
# enabled: true
# # put your cert and key files on dir
# dir: /etc/harbor/tls/internal
# Uncomment external_url if you want to enable external proxy
# And when it enabled the hostname will no longer used
# external_url: https://reg.mydomain.com:8433
# The initial password of Harbor admin
# It only works in first time to install harbor
# Remember Change the admin password from UI after launching Harbor.
harbor_admin_password: Harbor12345
# Harbor DB configuration
database:
# The password for the user('postgres' by default) of Harbor DB. Change this before any production use.
password: root123
# The maximum number of connections in the idle connection pool. If it <=0, no idle connections are retained.
max_idle_conns: 100
# The maximum number of open connections to the database. If it <= 0, then there is no limit on the number of open connections.
# Note: the default number of connections is 1024 for postgres of harbor.
max_open_conns: 900
# The maximum amount of time a connection may be reused. Expired connections may be closed lazily before reuse. If it <= 0, connections are not closed due to a connection's age.
# The value is a duration string. A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
conn_max_lifetime: 5m
# The maximum amount of time a connection may be idle. Expired connections may be closed lazily before reuse. If it <= 0, connections are not closed due to a connection's idle time.
# The value is a duration string. A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
conn_max_idle_time: 0
# The default data volume
data_volume: /var/harbor_data
# Harbor Storage settings by default is using /data dir on local filesystem
# Uncomment storage_service setting If you want to using external storage
# storage_service:
# # ca_bundle is the path to the custom root ca certificate, which will be injected into the truststore
# # of registry's containers. This is usually needed when the user hosts a internal storage with self signed certificate.
# ca_bundle:
# # storage backend, default is filesystem, options include filesystem, azure, gcs, s3, swift and oss
# # for more info about this configuration please refer https://distribution.github.io/distribution/about/configuration/
# # and https://distribution.github.io/distribution/storage-drivers/
# filesystem:
# maxthreads: 100
# # set disable to true when you want to disable registry redirect
# redirect:
# disable: false
# Trivy configuration
#
# Trivy DB contains vulnerability information from NVD, Red Hat, and many other upstream vulnerability databases.
# It is downloaded by Trivy from the GitHub release page https://github.com/aquasecurity/trivy-db/releases and cached
# in the local file system. In addition, the database contains the update timestamp so Trivy can detect whether it
# should download a newer version from the Internet or use the cached one. Currently, the database is updated every
# 12 hours and published as a new release to GitHub.
trivy:
# ignoreUnfixed The flag to display only fixed vulnerabilities
ignore_unfixed: false
# skipUpdate The flag to enable or disable Trivy DB downloads from GitHub
#
# You might want to enable this flag in test or CI/CD environments to avoid GitHub rate limiting issues.
# If the flag is enabled you have to download the `trivy-offline.tar.gz` archive manually, extract `trivy.db` and
# `metadata.json` files and mount them in the `/home/scanner/.cache/trivy/db` path.
skip_update: false
#
# skipJavaDBUpdate If the flag is enabled you have to manually download the `trivy-java.db` file and mount it in the
# `/home/scanner/.cache/trivy/java-db/trivy-java.db` path
skip_java_db_update: false
#
# The offline_scan option prevents Trivy from sending API requests to identify dependencies.
# Scanning JAR files and pom.xml may require Internet access for better detection, but this option tries to avoid it.
# For example, the offline mode will not try to resolve transitive dependencies in pom.xml when the dependency doesn't
# exist in the local repositories. It means a number of detected vulnerabilities might be fewer in offline mode.
# It would work if all the dependencies are in local.
# This option doesn't affect DB download. You need to specify "skip-update" as well as "offline-scan" in an air-gapped environment.
offline_scan: false
#
# Comma-separated list of what security issues to detect. Possible values are `vuln`, `config` and `secret`. Defaults to `vuln`.
security_check: vuln
#
# insecure The flag to skip verifying registry certificate
insecure: false
#
# timeout The duration to wait for scan completion.
# There is upper bound of 30 minutes defined in scan job. So if this `timeout` is larger than 30m0s, it will also timeout at 30m0s.
timeout: 5m0s
#
# github_token The GitHub access token to download Trivy DB
#
# Anonymous downloads from GitHub are subject to the limit of 60 requests per hour. Normally such rate limit is enough
# for production operations. If, for any reason, it's not enough, you could increase the rate limit to 5000
# requests per hour by specifying the GitHub access token. For more details on GitHub rate limiting please consult
# https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting
#
# You can create a GitHub token by following the instructions in
# https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
#
# github_token: xxx
# 👇 保留原有完整的 jobservice 配置(已包含必要参数,避免 KeyError)
jobservice:
# Maximum number of job workers in job service
max_job_workers: 10
# Maximum hours of task duration in job service, default 24
max_job_duration_hours: 24
# The jobLoggers backend name, only support "STD_OUTPUT", "FILE" and/or "DB"
job_loggers:
- STD_OUTPUT
- FILE
# - DB
# The jobLogger sweeper duration (ignored if `jobLogger` is `stdout`)
logger_sweeper_duration: 1 #days
notification:
# Maximum retry count for webhook job
webhook_job_max_retry: 3
# HTTP client timeout for webhook job
webhook_job_http_client_timeout: 3 #seconds
# Log configurations
log:
# options are debug, info, warning, error, fatal
level: info
# configs for logs in local storage
local:
# Log files are rotated log_rotate_count times before being removed. If count is 0, old versions are removed rather than rotated.
rotate_count: 50
# Log files are rotated only if they grow bigger than log_rotate_size bytes. If size is followed by k, the size is assumed to be in kilobytes.
# If the M is used, the size is in megabytes, and if G is used, the size is in gigabytes. So size 100, size 100k, size 100M and size 100G
# are all valid.
rotate_size: 200M
# The directory on your host that store log
location: /var/log/harbor
# Uncomment following lines to enable external syslog endpoint.
# external_endpoint:
# # protocol used to transmit log to external endpoint, options is tcp or udp
# protocol: tcp
# # The host of external endpoint
# host: localhost
# # Port of external endpoint
# port: 5140
#This attribute is for migrator to detect the version of the .cfg file, DO NOT MODIFY!
_version: 2.13.0
# Uncomment external_database if using external database.
# external_database:
# harbor:
# host: harbor_db_host
# port: harbor_db_port
# db_name: harbor_db_name
# username: harbor_db_username
# password: harbor_db_password
# ssl_mode: disable
# max_idle_conns: 2
# max_open_conns: 0
# Uncomment redis if need to customize redis db
# redis:
# # db_index 0 is for core, it's unchangeable
# # registry_db_index: 1
# # jobservice_db_index: 2
# # trivy_db_index: 5
# # it's optional, the db for harbor business misc, by default is 0, uncomment it if you want to change it.
# # harbor_db_index: 6
# # it's optional, the db for harbor cache layer, by default is 0, uncomment it if you want to change it.
# # cache_layer_db_index: 7
# Uncomment external_redis if using external Redis server
# external_redis:
# # support redis, redis+sentinel
# # host for redis: <host_redis>:<port_redis>
# # host for redis+sentinel:
# # <host_sentinel1>:<port_sentinel1>,<host_sentinel2>:<port_sentinel2>,<host_sentinel3>:<port_sentinel3>
# host: redis:6379
# password:
# # Redis AUTH command was extended in Redis 6, it is possible to use it in the two-arguments AUTH <username> <password> form.
# # there's a known issue when using external redis username ref:https://github.com/goharbor/harbor/issues/18892
# # if you care about the image pull/push performance, please refer to this https://github.com/goharbor/harbor/wiki/Harbor-FAQs#external-redis-username-password-usage
# # username:
# # sentinel_master_set must be set to support redis+sentinel
# #sentinel_master_set:
# # tls configuration for redis connection
# # only server-authentication is supported
# # mtls for redis connection is not supported
# # tls connection will be disable by default
# tlsOptions:
# enable: false
# # if it is a self-signed ca, please set the ca path specifically.
# rootCA:
# # db_index 0 is for core, it's unchangeable
# registry_db_index: 1
# jobservice_db_index: 2
# trivy_db_index: 5
# idle_timeout_seconds: 30
# # it's optional, the db for harbor business misc, by default is 0, uncomment it if you want to change it.
# # harbor_db_index: 6
# # it's optional, the db for harbor cache layer, by default is 0, uncomment it if you want to change it.
# # cache_layer_db_index: 7
# Uncomment uaa for trusting the certificate of uaa instance that is hosted via self-signed cert.
# uaa:
# ca_file: /path/to/ca
# Global proxy
# Config http proxy for components, e.g. http://my.proxy.com:3128
# Components doesn't need to connect to each others via http proxy.
# Remove component from `components` array if want disable proxy
# for it. If you want use proxy for replication, MUST enable proxy
# for core and jobservice, and set `http_proxy` and `https_proxy`.
# Add domain to the `no_proxy` field, when you want disable proxy
# for some special registry.
proxy:
http_proxy:
https_proxy:
no_proxy:
components:
- core
- jobservice
- trivy
# metric:
# enabled: false
# port: 9090
# path: /metrics
# Trace related config
# only can enable one trace provider(jaeger or otel) at the same time,
# and when using jaeger as provider, can only enable it with agent mode or collector mode.
# if using jaeger collector mode, uncomment endpoint and uncomment username, password if needed
# if using jaeger agetn mode uncomment agent_host and agent_port
# trace:
# enabled: true
# # set sample_rate to 1 if you wanna sampling 100% of trace data; set 0.5 if you wanna sampling 50% of trace data, and so forth
# sample_rate: 1
# # # namespace used to differentiate different harbor services
# # namespace:
# # # attributes is a key value dict contains user defined attributes used to initialize trace provider
# # attributes:
# # application: harbor
# # # jaeger should be 1.26 or newer.
# # jaeger:
# # endpoint: http://hostname:14268/api/traces
# # username:
# # password:
# # agent_host: hostname
# # # export trace data by jaeger.thrift in compact mode
# # agent_port: 6831
# # otel:
# # endpoint: hostname:4318
# # url_path: /v1/traces
# # compression: false
# # insecure: true
# # # timeout is in seconds
# # timeout: 10
# Enable purge _upload directories
upload_purging:
enabled: true
# remove files in _upload directories which exist for a period of time, default is one week.
age: 168h
# the interval of the purge operations
interval: 24h
dryrun: false
# Cache layer configurations
# If this feature enabled, harbor will cache the resource
# `project/project_metadata/repository/artifact/manifest` in the redis
# which can especially help to improve the performance of high concurrent
# manifest pulling.
# NOTICE
# If you are deploying Harbor in HA mode, make sure that all the harbor
# instances have the same behaviour, all with caching enabled or disabled,
# otherwise it can lead to potential data inconsistency.
cache:
# not enabled by default
enabled: false
# keep cache for one day by default
expire_hours: 24
# Harbor core configurations
# Uncomment to enable the following harbor core related configuration items.
# core:
# # The provider for updating project quota(usage), there are 2 options, redis or db,
# # by default is implemented by db but you can switch the updation via redis which
# # can improve the performance of high concurrent pushing to the same project,
# # and reduce the database connections spike and occupies.
# # By redis will bring up some delay for quota usage updation for display, so only
# # suggest switch provider to redis if you were ran into the db connections spike around
# # the scenario of high concurrent pushing to same project, no improvement for other scenes.
# quota_update_provider: redis # Or db
配置文件释义
因为,/空间磁盘不够
du -lh --max-depth=1 /var/ | sort -hr
du: cannot access '/var/lib/docker/overlay2/a920e2552e19e4a565f2b7d37477ba585a1c83bc8ae7bb8a8327bc80aa30c263': No such file or directory
36G /var/
29G /var/harbor_data.bak
5.8G /var/lib
773M /var/log
717M /var/cache
3.6M /var/crash
3.0M /var/backups
64K /var/tmp
32K /var/spool
24K /var/www
4.0K /var/snap
4.0K /var/opt
4.0K /var/mail
4.0K /var/local
报错原因
plaintext
du: cannot access ... overlay2 ... No such file or directory
docker 容器临时文件已经被销毁、目录残留失效,只是一条无关紧要的警告,不会影响最终统计结果,直接忽略即可。
2、重点数据
/var整体占用 36G/var/harbor_data.bak就占了 29G这就是你系统盘空间压力巨大的元凶,54G 的系统盘光是这一份镜像备份就吃掉 29GB。
3、目录占用排行
表格
cp: cannot overwrite non‑directory '/var/harbor_data' with directory
最开始
/var/harbor_data是普通文件,不是文件夹cp -r文件夹,不能直接覆盖一个普通文件,直接报错rm -f只能删除文件,无法删除文件夹,就算它之前是目录,‑f 参数也处理不掉,目录依旧残留在系统内,所以拷贝一直失败
2、中途按下 Ctrl+C 强制终止拷贝
执行拷贝指令之后,根目录磁盘占用已经达到 95%
系统盘空间快要耗尽,你手动快捷键中断了 cp 复制进程,防止硬盘直接爆满卡死服务器。
3、之后敲入正确删除指令
bash
sudo rm -rf /var/harbor_data
-r:递归,可以删除文件夹-f:强制清除,忽略权限这条命令才真正把残留的旧目录 / 文件彻底删掉
最核心问题
/var 属于 54G 系统本地硬盘,空间马上塞满
harbor_data.bak 镜像备份体积很大,在系统盘内部复制文件夹,会瞬间占满剩余磁盘,引发系统卡死、docker 崩溃。
hitou@shitou:~$ df -h 查看容量大小
Filesystem Size Used Avail Use% Mounted on
tmpfs 791M 5.7M 786M 1% /run
/dev/mapper/ubuntu--vg-lv--0 54G 45G 6.1G 89% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 3.9G 0 3.9G 0% /run/qemu
/dev/sdb2 2.0G 200M 1.6G 11% /boot
/dev/sda2 1.4T 501G 773G 40% /opt/mirror
/dev/sda1 492G 8.8G 458G 2% /home
tmpfs 791M 16K 791M 1% /run/user/1000
shitou@shitou:~$ ls /opt/ 进入这个挂载镜像的文件夹
cni/ containerd/ harbor_backup/ mirror/
这个先不管了,
shitou@shitou:~$ cd /opt/harbor_backup/
shitou@shitou:/opt/harbor_backup$ ls
common docker-compose.yml harbor.yml harbor.yml.tmpl install.sh
sudo:使用管理员最高权限运行
mkdir:新建文件夹
-p:上级目录不存在也不会报错
/opt/mirror/.harbor_bak
文件夹建在1.4T 大盘里面
开头小数点 . = Linux 隐藏文件夹,网页浏览不会展示出来,不会干扰你文件同步
shitou@shitou:/opt/harbor_backup$ sudo mkdir -p /opt/mirror/.harbor_bak
[sudo] password for shitou:
Sorry, try again.
[sudo] password for shitou:
shitou@shitou:/opt/harbor_backup$ ls
common docker-compose.yml harbor.yml harbor.yml.tmpl install.sh
shitou@shitou:/opt/harbor_backup$ pwd
/opt/harbor_backup
shitou@shitou:/opt/harbor_backup$ sudo rsync -av /var/harbor_data.bak /opt/mirror/.harbor_bak/
很长时间的复制。
正确操作思路
不要再在
/var内部复制这份大容量备份使用
rsync把备份传到你的 1.4T 大盘隐藏目录
bash
rsync -av /var/harbor_data.bak /opt/mirror/.harbor_bak/
大盘存放好备份之后,需要还原的时候再拷贝回系统盘即可
简单区分 rm 参数
rm -f:仅删除单个文件,删不掉文件夹rm -rf:强制删除文件、文件夹、嵌套目录,清理 harbor 数据必须用这条
后续复制完了的话,、在操作。,
先确认 rsync 数据同步全部结束
等待终端命令跑完、光标回到命令行,代表 Ubuntu 软件源镜像文件已经完整备份至
/opt/mirror/.harbor_bak检查备份目录文件是否齐全
bash
ls /opt/mirror/.harbor_bak/
已关停正在运行的 tunasync 同步服务(防止抢占磁盘、文件冲突)
bash
# 停止工作节点
sudo systemctl stop tunasync-worker
# 停止管理节点
sudo systemctl stop tunasync-manager
# 杀掉后台残留进程
pkill tunasync
、已停止 Harbor 容器
bash
cd /home/shitou/harbor
sudo docker compose down
查看有哪些服务需要关停,查看所有活跃 systemd 服务
bash
systemctl list-units --type=service --state=runningshitou@shitou:~$ sudo systemctl stop tunasync-worker
[sudo] password for shitou:
shitou@shitou:~$ sudo systemctl stop tunasync-manager
shitou@shitou:~$ systemctl status tunasync-worker
○ tunasync-worker.service - Tunasync Worker Sync Node
Loaded: loaded (/etc/systemd/system/tunasync-worker.service; disabled; preset: enabled)
Active: inactive (dead)
Aug 08 02:22:19 shitou tunasync[6238]: [26-08-07 18:22:13][NOTICE] Stopping all the jobs
Aug 08 02:22:19 shitou tunasync[6238]: [26-08-07 18:22:15][WARNIN] SIGTERM failed to kill the job in 2s. SIGKILL sent
Aug 08 02:22:19 shitou tunasync[6238]: [26-08-07 18:22:15][WARNIN] failed syncing ubuntu-cdimage: killed by manager
Aug 08 02:22:19 shitou tunasync[6238]: [26-08-07 18:22:15][WARNIN] SIGTERM failed to kill the job in 2s. SIGKILL sent
Aug 08 02:22:19 shitou tunasync[6238]: [26-08-07 18:22:15][WARNIN] failed syncing ubuntu: killed by manager
Aug 08 02:22:19 shitou tunasync[6238]: [26-08-07 18:22:17][NOTICE] All the jobs are stopped
Aug 08 02:22:13 shitou systemd[1]: Stopping tunasync-worker.service - Tunasync Worker Sync Node...
Aug 08 02:22:22 shitou systemd[1]: tunasync-worker.service: Deactivated successfully.
Aug 08 02:22:22 shitou systemd[1]: Stopped tunasync-worker.service - Tunasync Worker Sync Node.
Aug 08 02:22:22 shitou systemd[1]: tunasync-worker.service: Consumed 1h 13min 43.383s CPU time, 159.3M memory peak, 0B memory swap peak.
shitou@shitou:~$ sudo systemctl stop docker
Stopping 'docker.service', but its triggering units are still active:
docker.socket
shitou@shitou:~$ sudo systemctl stop docker.socket
shitou@shitou:~$ systemctl list-units --type=service --state=running
UNIT LOAD ACTIVE SUB DESCRIPTION
containerd.service loaded active running containerd container runtime
cri-docker.service loaded active running CRI Interface for Docker Application Container Engine
cron.service loaded active running Regular background program processing daemon
dbus.service loaded active running D-Bus System Message Bus
fwupd.service loaded active running Firmware update daemon
getty@tty1.service loaded active running Getty on tty1
kubelet.service loaded active running kubelet: The Kubernetes Node Agent
ModemManager.service loaded active running Modem Manager
multipathd.service loaded active running Device-Mapper Multipath Device Controller
netdata.service loaded active running Netdata, X-Ray Vision for your infrastructure!
NetworkManager.service loaded active running Network Manager
nginx.service loaded active running A high performance web server and a reverse proxy server
nmbd.service loaded active running Samba NMB Daemon
polkit.service loaded active running Authorization Manager
rsyslog.service loaded active running System Logging Service
smbd.service loaded active running Samba SMB Daemon
ssh.service loaded active running OpenBSD Secure Shell server
systemd-journald.service loaded active running Journal Service
systemd-journald@netdata.service loaded active running Journal Service for Namespace netdata
systemd-logind.service loaded active running User Login Management
systemd-machined.service loaded active running Virtual Machine and Container Registration Service
systemd-networkd.service loaded active running Network Configuration
systemd-timesyncd.service loaded active running Network Time Synchronization
systemd-udevd.service loaded active running Rule-based Manager for Device Events and Files
udisks2.service loaded active running Disk Manager
unattended-upgrades.service loaded active running Unattended Upgrades Shutdown
upower.service loaded active running Daemon for power management
user@1000.service loaded active running User Manager for UID 1000
virtlockd.service loaded active running libvirt locking daemon
virtlogd.service loaded active running libvirt logging daemon
wpa_supplicant.service loaded active running WPA supplicant
Legend: LOAD → Reflects whether the unit definition was properly loaded.
ACTIVE → The high-level unit activation state, i.e. generalization of SUB.
SUB → The low-level unit activation state, values depend on unit type.
31 loaded units listed.
shitou@shitou:~$ top
top - 02:28:01 up 4:34, 4 users, load average: 5.97, 7.26, 10.29
Tasks: 187 total, 1 running, 186 sleeping, 0 stopped, 0 zombie
%Cpu(s): 7.2 us, 27.1 sy, 0.0 ni, 12.5 id, 51.2 wa, 0.0 hi, 2.1 si, 0.0 st
MiB Mem : 7907.6 total, 152.9 free, 938.2 used, 7127.9 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 6969.4 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
286046 root 20 0 16256 9712 7032 D 17.9 0.1 2:02.37 rsync
286048 root 20 0 188544 7124 1916 S 16.6 0.1 2:03.68 rsync
51 root 0 -20 0 0 0 I 10.3 0.0 8:08.36 kworker/1:1H-kblockd
35 root 20 0 0 0 0 S 4.3 0.0 0:10.88 kcompactd0
40124 netdata 20 0 875156 220288 24428 S 3.7 2.7 13:30.73 netdata
193321 root 20 0 0 0 0 D 3.7 0.0 1:01.67 kworker/u4:8+flush-8:0
40904 netdata 20 0 183532 11148 5880 S 2.7 0.1 8:45.76 apps.plugin
52 root 20 0 0 0 0 S 2.3 0.0 4:12.78 kswapd0
2884 root 20 0 1636188 59864 28000 S 2.3 0.7 7:43.95 kubelet
233030 root 20 0 0 0 0 I 1.0 0.0 0:05.15 kworker/u4:0-flush-252:0
288255 root 20 0 0 0 0 I 1.0 0.0 0:03.50 kworker/u4:2-ext4-rsv-conversion
40964 netdata 20 0 1420924 108912 77436 S 0.7 1.3 4:18.43 go.d.plugin
17 root 20 0 0 0 0 I 0.3 0.0 0:50.08 rcu_preempt
36 root 25 5 0 0 0 S 0.3 0.0 1:15.98 ksmd
84 root 0 -20 0 0 0 I 0.3 0.0 0:38.05 kworker/0:1H-kblockd
347 root 19 -1 99788 51908 50500 S 0.3 0.6 5:57.22 systemd-journal
815 message+ 20 0 10464 6136 4600 S 0.3 0.1 0:58.29 dbus-daemon
827 root 20 0 18076 8920 7796 S 0.3 0.1 0:20.11 systemd-logind
39003 root 20 0 33996 12280 11192 S 0.3 0.2 0:03.16 systemd-journal
40943 netdata 20 0 203992 7116 5876 S 0.3 0.1 0:17.96 sd-jrnl.plugin
40981 netdata 20 0 15896 2408 1608 S 0.3 0.0 0:01.17 spawn-setns
348224 netdata 20 0 4588 3500 2996 S 0.3 0.0 0:00.71 bash
1 root 20 0 23156 14280 9496 S 0.0 0.2 0:49.00 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:01.45 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.00 pool_workqueue_release
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-rcu_g
5 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-rcu_p
6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-slub_
7 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-netns
10 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H-kblockd
12 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-mm_pe
13 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_tasks_kthread
14 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_tasks_rude_kthread
15 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_tasks_trace_kthread
16 root 20 0 0 0 0 S 0.0 0.0 0:37.98 ksoftirqd/0
18 root rt 0 0 0 0 S 0.0 0.0 0:00.38 migration/0
19 root -51 0 0 0 0 S 0.0 0.0 0:00.00 idle_inject/0
20 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/0
21 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/1
22 root -51 0 0 0 0 S 0.0 0.0 0:00.00 idle_inject/1
23 root rt 0 0 0 0 S 0.0 0.0 0:00.72 migration/1
24 root 20 0 0 0 0 S 0.0 0.0 0:08.53 ksoftirqd/1
26 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/1:0H-events_highpri
27 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs
28 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-inet_
29 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kauditd
30 root 20 0 0 0 0 S 0.0 0.0 0:00.01 khungtaskd
32 root 20 0 0 0 0 S 0.0 0.0 0:00.00 oom_reaper
34 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/R-write
38 root 39 19 0 0 0 S 0.0 0.0 0:00.12 khugepaged
然后关停,
先识别列表里所有会读写硬盘、干扰 rsync 迁移的服务
🔴 最高优先级,必须关闭(容器、文件共享、实时监控)
containerd.service:容器运行时底层服务,docker/k8s 依靠它读写磁盘cri‑docker.service:k8s 对接 docker 的接口kubelet.service:kubernetes 节点代理,会持续读写容器磁盘smbd.service、nmbd.service:Samba 网盘服务,随时读写/opt/mirror硬盘netdata.service:实时资源监控,不停写入磁盘日志、采集磁盘 IO
🟡 次要后台读写服务,迁移期间临时关停
cron.service:定时任务,防止中途触发备份、自动脚本读写硬盘nginx.service:网页服务,避免站点缓存写入磁盘fwupd.service:固件自动更新服务
# 1.关闭k8s容器相关整套服务
sudo systemctl stop kubelet
sudo systemctl stop cri-docker
sudo systemctl stop containerd
# 2.关闭samba网盘(最容易占用你的/opt/mirror磁盘)
sudo systemctl stop smbd nmbd
# 3.关闭监控、定时任务、web服务
sudo systemctl stop netdata
sudo systemctl stop cron
sudo systemctl stop nginx
sudo systemctl stop fwupd、修改 Harbor 配置,把存储路径更换到大容量硬盘
编辑主配置文件
bash
nano harbor.yml
找到
data_volume参数
yaml
#旧路径
data_volume: /var/harbor_data
#修改为你的大盘路径
data_volume: /opt/mirror/harbor_data
保存退出编辑器
把刚刚 rsync 备份好的数据迁移到新工作目录
bash
#新建harbor‑data文件夹
sudo mkdir -p /opt/mirror/harbor_data
#把备份内全部镜像数据复制过来
sudo rsync -av /opt/mirror/.harbor_bak/ /opt/mirror/harbor_data/
从新,修改镜像仓库存储地址,
/opt/mirror 为内网 APT 软件包镜像站根目录,用来存放系统 deb 安装包资源。
为充分利用该分区磁盘空间,将 Docker‑Harbor 容器镜像仓库部署在此目录内;
为防止 APT 镜像目录与容器仓库目录发生混淆、误删,Harbor 的数据目录、日志目录采用 Linux 隐藏文件夹进行隔离,日常浏览目录时仅展示 APT 镜像业务文件夹,隐藏目录不会被直接列出,两类业务互不干扰。
完整执行步骤
bash
# 清理之前创建的普通仓库数据目录
sudo rm -rf /opt/mirror/harbor_data
# 创建隐藏格式的仓库数据目录、日志目录
sudo mkdir -p /opt/mirror/.harbor_data
sudo mkdir -p /opt/mirror/.harbor_log
# 迁移原有容器镜像备份数据
sudo rsync -av /opt/mirror/.harbor_bak/ /opt/mirror/.harbor_data/
# 迁移旧日志文件
sudo rsync -av /opt/mirror/harbor_log/ /opt/mirror/.harbor_log/
# 删除已经迁移完毕的旧日志文件夹
sudo rm -rf /opt/mirror/harbor_log
# 赋予目录读写权限,保证容器正常读写文件
sudo chmod -R 777 /opt/mirror/.harbor_data
sudo chmod -R 777 /opt/mirror/.harbor_log
# 使用管理员权限编辑配置文件
sudo nano ~/harbor/harbor.yml
配置文件关键参数
yaml
data_volume: /opt/mirror/.harbor_data
log:
level: info
local:
rotate_count: 50
rotate_size: 200M
location: /opt/mirror/.harbor_log
编辑完成后保存退出,重载配置并启动服务
bash
sudo ./install.sh
docker compose up -d
/opt/mirror:内网 APT 软件包镜像站,存放 apt‑mirror、iso、mirrors 等可见业务目录/opt/mirror/.harbor_data:Docker 容器镜像仓库存储目录(隐藏)/opt/mirror/.harbor_log:Harbor 服务运行日志目录(隐藏)
将备份镜像数据完整还原至新隐藏目录
sudo rsync -av /opt/mirror/.harbor_bak/ /opt/mirror/.harbor_data/
停止了很多服务,
sudo systemctl stop tunasync-worker
141 sudo systemctl stop tunasync-manager
142 systemctl status tunasync-worker
143 sudo systemctl stop docker
144 sudo systemctl stop docker.socket
145 systemctl list-units --type=service --state=running
146 top
147 sudo systemctl stop kubelet
148 sudo systemctl stop cri-docker
149 sudo systemctl stop containerd
150 sudo systemctl stop netdata
151 sudo systemctl stop cron
152 sudo systemctl stop nginx
153 sudo systemctl stop fwupd
154 lsof +D /opt/mirror
155 history
故障移步其他文章,
重载 Harbor 配置、启动容器
bash
#执行安装脚本加载新配置
sudo ./install.sh
#后台启动整套harbor服务
docker compose up -d
校验服务是否正常运行
bash
#查看启动的docker容器
docker ps
#查看harbor日志排查报错
docker logs -f harbor-core
镜像仓库迁移完成之后,重启软件源同步服务
bash
sudo systemctl start tunasync-manager
sudo systemctl start tunasync-worker
💡整体流程总结
等待 rsync 同步完成 → 关闭源同步服务 → 关停 Harbor → 修改存储路径配置 → 迁移镜像数据 → 重载配置启动 Harbor → 重启 tunasync 同步
硬盘分区后:本地迁移docker 镜像harbor仓库
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法