如何将 CentOS 乔迁成 AlmaLinux ,且避免数据中心停机
Posted ~晨曦静竹~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何将 CentOS 乔迁成 AlmaLinux ,且避免数据中心停机相关的知识,希望对你有一定的参考价值。
CentOS 8 在线升级 AlmaLinux
众所周知,步入到2021年红帽已不在维护CentOS了,转而取代的是伪滚动发行版 CentOS Stream,但少有Centos的运维人员对其青睐,而许多第三方应用程序(如cPanel)均不支持Stream。为此,博主对红帽这一草率的决定感到惋惜,同时也对自己初学Linux时用过的Centos将逐渐淡出人们视野而表示同情。
不过,别担心,随后就有大佬们推出了Centos的替代分支Linux。第一个宣布的是 Rocky Linux,来自最初为我们带来 CentOS 的人。紧随其后的是 AlmaLinux 。两者都是当前 Red Hat Enterprise Linux 二进制兼容并得到社区支持的开源操作系统的替代品,并且已经在成为 CentOS 的事实上的替代品方面取得了长足的进步 。
博主在Github找到了AlmaLinux的工作人员提供的Centos在线升级更新AlmaLinux的方式,可以说为已在数据中心部署了大量CentOS的运维人员带来了福音,且过程很简便。
需求:
● CentOS 8 的运行实例
● 具有 sudo 运行权限的用户
如何将 CentOS 乔迁 AlmaLinux
首先是更新Centos服务器环境:
sudo dnf upgrade -y 很明显这是CentOS 8
不管是哪版本,当然也可用yum:
yum update && yum upgrade -y
创建升级更新时的脚本文件路径:
mkdir AlmaLinux
博主是在/root下创建的
进入新建目录:
cd AlmaLinux
从Github上下载升级脚本:
curl -O https://raw.githubusercontent.com/AlmaLinux/almalinux-deploy/master/almalinux-deploy.sh
若有读者在测试过程中如下图所示被墙了,可通过添加github的ip到hosts文件中来解决:
报错代码:
Failed to connect to raw.githubusercontent.com port 443: Connection refused
解决方法: 访问 https://www.ipaddress.com/ ,查询 raw.githubusercontent.com 的IP
添加到/etc/hosts文件中:
vim /etc/hosts
添加内容:
#Github
199.232.68.133 raw.githubusercontent.com
再次执行curl下载:
curl -O https://raw.githubusercontent.com/AlmaLinux/almalinux-deploy/master/almalinux-deploy.sh
而已下载好文件的朋友,授权执行即可:
给almalinux-deploy.sh脚本文件授权:
chmod u+x almalinux-deploy.sh
执行:
sudo ./almalinux-deploy.sh
等待,直到出现如下消息,即说明乔迁成功!
Complete!
Run dnf distro-sync -y OK
Restoring of alternatives is done OK
Generating grub configuration file ...
done
All Secure Boot related packages which were released by not AlmaLinux are reinstalledOK
Migration to AlmaLinux is completed
重启!
reboot
同时,我们发现新增了 AlmaLinux 8.4 的内核
重启后发现已乔迁成功!!
若有读者仍旧无法获取 almalinux-deploy.sh 升级脚本,也莫担心,博主提供脚本内容:
#!/bin/bash
# Description: EL to AlmaLinux migration script.
# License: GPLv3.
# Environment variables:
# ALMA_RELEASE_URL - almalinux-release package download URL.
# ALMA_PUBKEY_URL - RPM-GPG-KEY-AlmaLinux download URL.
set -euo pipefail
BASE_TMP_DIR='/root'
OS_RELEASE_PATH='/etc/os-release'
REDHAT_RELEASE_PATH='/etc/redhat-release'
STAGE_STATUSES_DIR='/var/run/almalinux-deploy-statuses'
ALT_ADM_DIR="/var/lib/alternatives"
BAK_DIR="/tmp/alternatives_backup"
ALT_DIR="/etc/alternatives"
# AlmaLinux OS 8.3
MINIMAL_SUPPORTED_VERSION='8.3'
VERSION='0.1.12'
BRANDING_PKGS=("centos-backgrounds" "centos-logos" "centos-indexhtml" \\
"centos-logos-ipa" "centos-logos-httpd" \\
"oracle-backgrounds" "oracle-logos" "oracle-indexhtml" \\
"oracle-logos-ipa" "oracle-logos-httpd" \\
"oracle-epel-release-el8" \\
"redhat-backgrounds" "redhat-logos" "redhat-indexhtml" \\
"redhat-logos-ipa" "redhat-logos-httpd" \\
"rocky-backgrounds" "rocky-logos" "rocky-indexhtml" \\
"rocky-logos-ipa" "rocky-logos-httpd")
REMOVE_PKGS=("centos-linux-release" "centos-gpg-keys" "centos-linux-repos" \\
"libreport-plugin-rhtsupport" "libreport-rhel" "insights-client" \\
"libreport-rhel-anaconda-bugzilla" "libreport-rhel-bugzilla" \\
"oraclelinux-release" "oraclelinux-release-el8" \\
"redhat-release" "redhat-release-eula" \\
"rocky-release" "rocky-gpg-keys" "rocky-repos" \\
"rocky-obsolete-packages")
setup_log_files() {
exec > >(tee /var/log/almalinux-deploy.log)
exec 5> /var/log/almalinux-deploy.debug.log
BASH_XTRACEFD=5
}
# Save the successful status of a stage for future continue of it
# $1 - name of a stage
save_status_of_stage() {
if [[ 0 != "$(id -u)" ]]; then
# the function is called in tests and should be skipped
return 0
fi
local -r stage_name="${1}"
if [[ ! -d "${STAGE_STATUSES_DIR}" ]]; then
mkdir -p "${STAGE_STATUSES_DIR}"
fi
touch "${STAGE_STATUSES_DIR}/${stage_name}"
}
# Get a status of a stage for continue of it
# $1 - name of a stage
# The function returns 1 if stage isn't completed and 0 if it's completed
get_status_of_stage() {
if [[ 0 != "$(id -u)" ]]; then
# the function is called in tests and should be skipped
return 1
fi
local -r stage_name="${1}"
if [[ ! -d "${STAGE_STATUSES_DIR}" ]]; then
return 1
fi
if [[ ! -f "${STAGE_STATUSES_DIR}/${stage_name}" ]]; then
return 1
fi
return 0
}
is_migration_completed() {
if get_status_of_stage "completed"; then
printf '\\n\\033[0;32mMigration to AlmaLinux was already completed\\033[0m\\n'
exit 0
fi
}
# Reports a completed step using a green color.
#
# $1 - Message to print.
report_step_done() {
local -r message="${1}"
printf '\\033[0;32m%-70sOK\\033[0m\\n' "${message}"
}
# Reports a failed step using a red color.
#
# $1 - Message to print.
# $2 - Additional information to show (optional).
report_step_error() {
local -r message="${1}"
local -r trace="${2:-}"
printf '\\033[0;31m%-70sERROR\\033[0m\\n' "${message}" 1>&2
if [[ -n "${trace}" ]]; then
echo "${trace}" | while read -r line; do
printf ' %s\\n' "${line}" 1>&2
done
fi
}
# Prints program usage information.
show_usage() {
echo -e 'Migrates an EL system to AlmaLinux\\n'
echo -e 'Usage: almalinux-deploy.sh [OPTION]...\\n'
echo ' -h, --help show this message and exit'
echo ' -v, --version print version information and exit'
}
# Terminates the program if it is not run with root privileges
assert_run_as_root() {
if [[ $(id -u) -ne 0 ]]; then
report_step_error 'Check root privileges' \\
'Migration tool must be run as root'
exit 2
fi
report_step_done 'Check root privileges'
}
# Terminates the program if UEFI Secure Boot is enabled
assert_secureboot_disabled() {
local -r message='Check Secure Boot disabled'
if LC_ALL='C' mokutil --sb-state 2>/dev/null | grep -P '^SecureBoot\\s+enabled' 1>/dev/null; then
report_step_error "${message}" 'Secure Boot is not supported yet'
exit 1
fi
report_step_done "${message}"
}
# Prints a system architecture.
get_system_arch() {
uname -i
}
# Reads a variable value from /etc/os-release.
#
# $1 - variable name.
#
# Returns the variable value.
get_os_release_var() {
local -r var="${1}"
local val
if ! val="$(grep -oP "^${var}=\\"\\K.*?(?=\\")" "${OS_RELEASE_PATH}")"; then
echo "Error: ${var} is not found in ${OS_RELEASE_PATH}" >&2
exit 1
fi
echo "${val}"
}
# Detects an operational system version.
#
# $1 - operational system type.
#
# Prints OS version.
get_os_version() {
local -r os_type="${1}"
local os_version
if [[ "${os_type}" == 'centos' ]]; then
if ! os_version="$(grep -oP 'CentOS\\s+Linux\\s+release\\s+\\K(\\d+\\.\\d+)' \\
"${REDHAT_RELEASE_PATH}" 2>/dev/null)"; then
report_step_error "Detect ${os_type} version"
fi
else
os_version="$(get_os_release_var 'VERSION_ID')"
fi
echo "${os_version}"
}
# Prints control type and version.
get_panel_info() {
local panel_type=''
local panel_version=''
local -r cpanel_file='/usr/local/cpanel/cpanel'
local -r plesk_file='/usr/local/psa/version'
if [[ -x "${cpanel_file}" ]]; then
panel_type='cpanel'
panel_version=$("${cpanel_file}" -V 2>/dev/null | grep -oP '^[\\d.]+')
elif [[ -f "${plesk_file}" ]]; then
panel_type='plesk'
panel_version=$(grep -oP '^[\\d.]+' "${plesk_file}" 2>/dev/null)
fi
echo "${panel_type} ${panel_version}"
}
# Terminates the program if a platform is not supported by AlmaLinux.
#
# $1 - Operational system id (ID).
# $2 - Operational system version (e.g. 8 or 8.3).
# $3 - System architecture (e.g. x86_64).
assert_supported_system() {
if get_status_of_stage "assert_supported_system"; then
return 0
fi
local -r os_type="${1}"
local -r os_version="${2:0:1}"
local -r arch="${3}"
case "${arch}" in
x86_64|aarch64)
;;
*)
report_step_error "Check ${arch} architecture is supported"
exit 1
;;
esac
if [[ ${os_version} -ne ${MINIMAL_SUPPORTED_VERSION:0:1} ]]; then
report_step_error "Check EL${os_version} is supported"
exit 1
fi
os_types=("centos" "almalinux" "ol" "rhel" "rocky")
if [[ ! " ${os_types[*]} " =~ ${os_type} ]]; then
report_step_error "Check ${os_type} operating system is supported"
exit 1
fi
report_step_done "Check ${os_type}-${os_version}.${arch} is supported"
save_status_of_stage "assert_supported_system"
return 0
}
# Terminates the program if a control panel is not supported by AlmaLinux.
#
# $1 - Control panel type.
# $2 - Control panel version.
assert_supported_panel() {
if get_status_of_stage "assert_supported_panel"; then
return 0
fi
local -r panel_type="${1}"
local -r panel_version="${2}"
local plesk_min_major=18
local plesk_min_minor=0
local plesk_min_micro=35
local major
local minor
local micro
local error_msg="${panel_type} version \\"${panel_version}\\" is not supported. Please update the control panel to version \\"${plesk_min_major}.${plesk_min_minor}.${plesk_min_micro}\\"."
if [[ "${panel_type}" == 'plesk' ]]; then
local IFS=.
read -r major minor micro << EOF
${panel_version}
EOF
if [[ -z ${micro} ]]; then
micro=0
fi
if [[ -z ${minor} ]]; then
minor=0
fi
if [[ ${major} -lt ${plesk_min_major} ]]; then
report_step_error "${error_msg}"
exit 1
elif [[ ${major} -eq ${plesk_min_major} && ${minor} -lt ${plesk_min_minor} ]]; then
report_step_error "${error_msg}"
exit 1
elif [[ ${major} -eq ${plesk_min_major} && ${minor} -eq ${plesk_min_minor} && ${micro} -lt ${plesk_min_micro} ]]; then
report_step_error "${error_msg}"
exit 1
fi
fi
save_status_of_stage "assert_supported_panel"
}
# Returns a latest almalinux-release RPM package download URL.
#
# $1 - AlmaLinux major version (e.g. 8).
# $2 - System architecture (e.g. x86_64).
#
# Prints almalinux-release RPM package download URL.
get_release_file_url() {
local -r os_version="${1:0:1}"
local -r arch="${2}"
echo "${ALMA_RELEASE_URL:-https://repo.almalinux.org/almalinux/almalinux-release-latest-${os_version}.${arch}.rpm}"
}
# Downloads and installs the AlmaLinux public PGP key.
#
# $1 - Temporary directory path.
install_rpm_pubkey() {
if get_status_of_stage "install_rpm_pubkey"; then
return 0
fi
local -r tmp_dir="${1}"
local -r pubkey_url="${ALMA_PUBKEY_URL:-https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux}"
local -r pubkey_path="${tmp_dir}/RPM-GPG-KEY-AlmaLinux"
local -r step='Download RPM-GPG-KEY-AlmaLinux'
local output
if ! output=$(curl -f -s -S -o "${pubkey_path}" "${pubkey_url}" 2>&1); then
report_step_error "${step}" "${output}"
exit 1
else
report_step_done "${step}"
fi
rpm --import "${pubkey_path}"
report_step_done 'Import RPM-GPG-KEY-AlmaLinux to RPM DB'
rm -f "${pubkey_path}"
save_status_of_stage "install_rpm_pubkey"
}
# Downloads almalinux-release package.
#
# $1 - almalinux-release package download URL.
# $2 - Temporary directory path.
#
# Prints downloaded file path.
download_release_file() {
local -r release_url="${1}"
local -r tmp_dir="${2}"
local -r release_path="${tmp_dir}/almalinux-release-latest.rpm"
local output
if ! output=$(curl -f -s -S -o "${release_path}" "${release_url}" 2>&1); then
report_step_error 'Download almalinux-release package' "${output}"
exit 1
fi
echo "${release_path}"
}
# Terminates the program if a given RPM package checksum/signature is invalid.
#
# $1 - RPM package path.
assert_valid_package() {
local -r pkg_path="${1}"
local output
if ! output=$(rpm -K "${pkg_path}" 2>&1); then
report_step_error "Verify $(basename "${pkg_path}") package" \\
"${output}"
exit 1
fi
report_step_done 'Verify almalinux-release package'
}
# Terminates the program if OS version doesn't match AlmaLinux version.
#
# $1 - OS version.
# $2 - almalinux-release package file path.
assert_compatible_os_version() {
if get_status_of_stage "assert_compatible_os_version"; then
return 0
fi
local -r os_version="${1}"
local -r release_path="${2}"
local alma_version
alma_version=$(rpm -qp --queryformat '%{version}' "${release_path}")
if [[ "${os_version:2:3}" -lt "${MINIMAL_SUPPORTED_VERSION:2:3}" ]]; then
report_step_error "Please upgrade your OS from ${os_version} to" \\
"at least ${MINIMAL_SUPPORTED_VERSION} and try again"
exit 1
fi
if [[ "${os_version:2:3}" -gt "${alma_version:2:3}" ]]; then
report_step_error "Version of you OS ${os_version} is not supported yet"
exit 1
fi
report_step_done 'Your OS is supported'
save_status_of_stage "assert_compatible_os_version"
}
# Backup /etc/issue* files
backup_issue() {
if get_status_of_stage "backup_issue"; then
return 0
fi
for file in $(rpm -Vf /etc/issue | cut -d' ' -f4); do
if [[ ${file} =~ "/etc/issue" ]]; then
cp "${file}" "${file}.bak"
fi
done
save_status_of_stage "backup_issue"
}
# Restore /etc/issue* files
restore_issue() {
if get_status_of_stage "restore_issue"; then
return 0
fi
for file in /etc/issue /etc/issue.net; do
[ ! -f "${file}.bak" ] || mv -f ${file}.bak ${file}
done
save_status_of_stage "restore_issue"
}
# Recursively removes a given directory.
#
# $1 - Directory path.
cleanup_tmp_dir() {
rm -fr "${1:?}"
}
# Remove OS specific packages
remove_os_specific_packages_before_migration() {
if get_status_of_stage "remove_os_specific_packages_before_migration"; then
return 0
fi
for i in "${!REMOVE_PKGS[@]}"; do
if ! rpm -q "${REMOVE_PKGS[i]}" &> /dev/null; then
# remove an erased package from the list if it isn't installed
unset "REMOVE_PKGS[i]"
fi
done
if [[ "${#REMOVE_PKGS[@]}" -ne 0 ]]; then
rpm -e --nodeps --allmatches "${REMOVE_PKGS[@]}"
fi
report_step_done 'Remove OS specific rpm packages'
save_status_of_stage "remove_os_specific_packages_before_migration"
}
# Remove not needed Red Hat directories
remove_not_needed_redhat_dirs() {
if get_status_of_stage "remove_not_needed_redhat_dirs"; then
return 0
fi
[ -d /usr/share/doc/redhat-release ] && rm -r /usr/share/doc/redhat-release
[ -d /usr/share/redhat-release ] && rm -r /usr/share/redhat-release
save_status_of_stage "remove_not_needed_redhat_dirs"
}
# Install package almalinux-release
install_almalinux_release_package() {
if get_status_of_stage "install_almalinux_release_package"; then
return 0
fi
local -r release_path="${1}"
rpm -Uvh "${release_path}"
report_step_done 'Install almalinux-release package'
save_status_of_stage "install_almalinux_release_package"
}
# Remove brand packages and install the same AlmaLinux packages
replace_brand_packages() {
if get_status_of_stage "replace_brand_packages"; then
return 0
fi
local alma_pkgs=()
local alma_pkg
local output
local pkg_name
# replace GUI packages
for i in "${!BRANDING_PKGS[@]}"; do
pkg_name="${BRANDING_PKGS[i]}"
if rpm -q "${pkg_name}" &>/dev/null; then
# shellcheck disable=SC2001
case "${pkg_name}" in
oracle-epel-release-el8)
alma_pkg="epel-release"
;;
*)
# shellcheck disable=SC2001
alma_pkg="$(echo "${pkg_name}" | sed 's#centos\\|oracle\\|redhat\\|rocky#almalinux#')"
;;
esac
alma_pkgs+=("${alma_pkg}")
else
unset "BRANDING_PKGS[i]"
fi
done
if [[ "${#BRANDING_PKGS[@]}" -ne 0 ]]; then
rpm -e --nodeps --allmatches "${BRANDING_PKGS[@]}"
report_step_done "Remove ${BRANDING_PKGS[*]} packages"
fi
if [[ "${#alma_pkgs[@]}" -ne 0 ]]; then
if ! output=$(dnf install -y "${alma_pkgs[@]}" 2>&1); then
report_step_error "Install ${alma_pkgs[*]} packages" "${output}"
fi
report_step_done "Install ${alma_pkgs[*]} packages"
fi
save_status_of_stage "replace_brand_packages"
}
# Converts a CentOS like system to AlmaLinux
#
# $1 - almalinux-release RPM package path.
migrate_from_centos() {
if get_status_of_stage "migrate_from_centos"; then
return 0
fi
local -r release_path="${1}"
# replace OS packages with almalinux-release
# and OS centos-specific packages
remove_os_specific_packages_before_migration
remove_not_needed_redhat_dirs
install_almalinux_release_package "${release_path}"
replace_brand_packages
save_status_of_stage "migrate_from_centos"
}
# Executes the 'dnf distro-sync -y' command.
#
distro_sync() {
if get_status_of_stage "distro_sync"; then
return 0
fi
local -r step='Run dnf distro-sync -y'
local ret_code=0
local dnf_repos="--enablerepo=powertools"
# create needed repo
if [ "${panel_type}" == "plesk" ]; then
plesk installer --select-release-current --show-components --skip-cleanup
dnf_repos+=",PLESK_*-dist"
fi
dnf check-update || {
ret_code=${?}
if [[ ${ret_code} -ne 0 ]] && [[ ${ret_code} -ne 100 ]]; then
report_step_error "${step}. Exit code: ${ret_code}"
exit ${ret_code}
fi
}
dnf distro-sync -y "${dnf_repos}" || {
ret_code=${?}
report_step_error "${step}. Exit code: ${ret_code}"
exit ${ret_code}
}
# remove unnecessary repo
if [ "${panel_type}" == "plesk" ]; then
plesk installer --select-release-current --show-components
fi
report_step_done "${step}"
save_status_of_stage "distro_sync"
}
install_kernel() {
if get_status_of_stage "install_kernel"; then
return 0
以上是关于如何将 CentOS 乔迁成 AlmaLinux ,且避免数据中心停机的主要内容,如果未能解决你的问题,请参考以下文章
CloudLinux将其CentOS衍生项目Lenix更名为AlmaLinux