CentOS停更之后替换方案
Rocky Linux
-
Rocky Linux是一个社区化的企业级操作系统,位于Red Hat Enterprise Linux(RHEL)下游。Rocky Linux与CentOS一样,提供了适用于服务器的稳定版本,旨在作为CentOS的完全兼容替代版本。
-
rocky linux自带cockpit UI面板,开启方法:
yum list installed | grep cockpit
systemctl enable cockpit
systemctl start cockpit
ss -antulp | grep cockpit
#浏览器访问IP:9090端口
国产操作系统介绍
-
银河麒麟操作系统 (Kylin OS):(有免费的社区版)
-
开发者:国防科技大学
-
特点:主要面向政府、国防、教育等领域,具有较高的安全性和稳定性。Kylin OS 有多种版本,如桌面版和服务器版。
-
中标麒麟 (NeoKylin):(有免费的社区版)
- 开发者:银河麒麟与中标普华合作开发
-
特点:基于Linux内核,提供稳定和安全的操作环境,广泛应用于政府和企业。
-
深度操作系统 (Deepin OS):(有免费的社区版)
- 开发者:武汉深之度科技有限公司特点:用户界面美观,使用方便,针对普通用户和开发者,基于Debian。
-
Deepin OS 以其深度定制的桌面环境(DDE)和丰富的软件生态而闻名。
-
UOS (统信操作系统):(有免费的社区版)
- 开发者:统信软件技术有限公司
- 特点:面向企业级市场,整合了深度和中标麒麟的技术,提供统一的操作系统平台。
- 欧拉:
- 华为开发的基于Linux内核的操作系统,主要用于企业服务器和云计算环境(有免费的)
- 鸿蒙操作系统 (HarmonyOS):(不是基于Linux内核,而是基于LiteOS微内核和其他技术)
- 开发者:华为
- 特点:不仅是一个手机操作系统,还适用于各种智能设备,如物联网设备、智能家居、汽车等。鸿蒙操作系统强调分布式架构和多设备协同
- OpenHarmony:这是HarmonyOS的开源版本
环境准备
实验环境规划
- 操作系统:rockylinux8
- 网络:NAT模式,可以确保机器在任何网络都能ssh连接
| K8S集群角色 | IP | 主机名 |
|---|---|---|
| 控制节点 | 172.16.183.100 | rm1 |
| 工作节点 | 172.16.183.101 | rn1 |
安装前准备
- 软件包安装
yum install -y device-mapper-persistent-data lvm2 wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo libaio-devel wget vim ncurses-devel autoconf automake epel-release openssh-server telnet vim
yum update -y
- 配置网络
#查看网卡名
ip addr
#编辑网卡配置文件
vim /etc/sysconfig/network-scripts/ifcfg-ens160
#修改成如下内容:
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
IPADDR=172.16.183.100
NETMASK=255.255.255.0
GATEWAY=172.16.183.2
DNS1=172.16.183.2
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens160
DEVICE=ens160
ONBOOT=yes
nmcli connection reload
nmcli c up ens160
也可以用nmcli来修改(rockylinux上不太好用,改配置文件好用)
nmcli connection modify ens160 ipv4.method manual connection.autoconnect yes #修改IP地址为手动配置,并且设置开机启动
nmcli connection modify ens160 ipv4.addresses 172.16.183.100/24 #修改IP地址和掩码
nmcli connection modify ens160 ipv4.gateway 172.16.183.2 #修改网关
nmcli connection modify ens160 ipv4.dns 172.16.183.2 #修改DNS,多个DNS以逗号分隔
nmcli connection down ens160
nmcli connection up ens160
- 关闭selinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
reboot
- 配置主机名
hostnamectl set-hostname rm1 && bash
- 配置hosts
tee -a /etc/hosts <<'EOF'
172.16.183.100 rm1
172.16.183.101 rn1
EOF
- 配置ssh互信
ssh-keygen
ssh-copy-id rn1
- 关闭swap,并把swap的lv重新分配到/
swapoff -a
vim /etc/fstab
#/dev/mapper/centos-swap swap swap defaults 0 0
lvs
#看到swap占用了3.91G的LVM
#root rl -wi-ao---- 35.08g
#swap rl -wi-a----- 3.91g
lvdisplay
#获取到LV Path /dev/rl/swap
#删除这个lv
lvremove /dev/rl/swap
#获取vg剩余空间
vgs
#VFree = 3.91G
#扩容lv
lvextend -L +3.91G /dev/rl/root
#扩容文件系统(xfs系统)
xfs_growfs /
#检查根分区
df -h
删除交换分区后必须重新配置 grub、BLS 引导条目、dracut 和 initramfs,否则重启会卡住或报 "找不到 swap" 错误:
# 1. 查看当前 GRUB_CMDLINE_LINUX 的完整内容(确认要删的参数)
grep GRUB_CMDLINE_LINUX /etc/default/grub
# 典型输出(VG 名可能含主机名,如 rl_rm1,也可能是 rl):
# GRUB_CMDLINE_LINUX="crashkernel=... resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap rhgb quiet"
# 2. 修改 /etc/default/grub,删除 swap 相关参数(影响未来新装内核的默认参数)
# 删除 resume= 参数(指向 swap 设备,用于休眠恢复)
sed -i 's/ resume=[^ "]*//' /etc/default/grub
# 删除 rd.lvm.lv=.../swap 参数(告诉 dracut 激活 swap LV)
sed -i 's/ rd\.lvm\.lv=[^ "]*swap//' /etc/default/grub
# 3. 验证 /etc/default/grub 修改结果
grep GRUB_CMDLINE_LINUX /etc/default/grub
# 4.【关键】使用 grubby 更新已有的 BLS 引导条目
# Rocky Linux 使用 BLS(Boot Loader Specification),内核启动参数存储在
# /boot/loader/entries/*.conf 中。仅修改 /etc/default/grub 不会更新已有的 BLS 条目!
# 必须用 grubby 删除所有已有内核条目中的 swap 相关参数:
grubby --update-kernel=ALL --remove-args="resume rd.lvm.lv=rl/swap"
# 注意:rd.lvm.lv=rl/swap 中的 rl 替换为实际 VG 名(通过 vgs 查看)
# 验证 BLS 条目已更新(确认 resume 和 swap 参数已消失)
grubby --info=ALL | grep -E "resume|swap" || echo "BLS 条目已清理干净"
# 5. 清除 dracut 的 resume 模块配置
# dracut 有独立的 resume 配置,仅清理引导参数不够!
# dracut -f 时 resume 模块仍会自动将已删除的 swap 设备写入 initramfs,
# 导致启动时 initramfs 尝试激活不存在的 swap LV 用于休眠恢复,系统卡住。
rm -f /etc/dracut.conf.d/resume.conf
# 显式禁用 resume 模块,防止 dracut 自动探测残留的 swap 引用
echo 'omit_dracutmodules+=" resume "' > /etc/dracut.conf.d/noresume.conf
# 如果存在 systemd-hibernate-resume 服务也一并禁用
systemctl disable systemd-hibernate-resume@*.service 2>/dev/null || true
# 6. 重新生成 initramfs(此步不可跳过,必须在上一步清除 resume 配置之后执行)
dracut -f
# 7. 重新生成 grub 配置(无论 UEFI 还是 Legacy BIOS 统一用此命令)
grub2-mkconfig -o /boot/grub2/grub.cfg
# 8. 重启验证
init 6
如果有扩盘需求,关机后在VMWare中扩盘,进系统扩容LVM:
#lsblk看到nvme0n1盘容量已经扩容了,现在新建分区,扩容到LVM
fdisk /dev/nvme0n1
#新建一个nvme0n1p3分区,type为8e
#w保存
partprobe /dev/nvme0n1
pvcreate /dev/nvme0n1p3
vgextend rl /dev/nvme0n1p3
lvextend -L +40G /dev/rl/root
xfs_growfs /dev/rl/root
- 修改内核参数
#将br_netfilter模块添加到 Linux 内核中。这是Linux网桥的核心模块,提供网络包转发和过滤。Kubernetes需要网络插件(如 Flannel、Calico)实现容器间通信,而这些网络插件通常会用Linux网桥来进行数据包转发和过滤。
modprobe br_netfilter
echo "modprobe br_netfilter" >> /etc/profile
#开启包过滤
tee /etc/sysctl.d/k8s.conf <<'EOF'
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl -p /etc/sysctl.d/k8s.conf
- 关闭防火墙
systemctl stop firewalld && systemctl disable firewalld
- 配置时间同步
yum -y install chrony
systemctl enable chronyd --now
tee -a /etc/chrony.conf <<'EOF'
server ntp1.aliyun.com iburst
server ntp2.aliyun.com iburst
server ntp1.tencent.com iburst
server ntp2.tencent.com iburst
EOF
#Iburst: 如果设置该选项,前四轮询之间的间隔将是2秒,而不是minpoll。 这对于在chronyd启动后快速获得时钟的第一次更新非常有用。即:重启chronyd后,2秒后,直接同步一次时间。
crontab -e
* * * * * /usr/bin/systemctl restart chronyd
systemctl restart crond
- 配置aliyun docker repo源
#配置国内安装docker和containerd的阿里云在线源
yum install yum-utils -y
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum clean all && yum makecache
组件安装
docker
#docker也要安装,docker跟containerd不冲突,安装docker是为了能基于dockerfile构建镜像
yum install docker-ce -y
systemctl enable docker --now
#配置docker镜像加速器,k8s所有节点均按照以下配置
tee /etc/docker/daemon.json <<'EOF'
{
"registry-mirrors":["https://docker.m.daocloud.io"]
}
EOF
#重启docker:
systemctl daemon-reload && systemctl restart docker && systemctl status docker
containerd
yum install containerd.io-1.6.22* -y
cd /etc/containerd
#rm -rf *
- 如果有harbor环境,修改config.toml为以下。(将\
替换为安装harbor机器的IP)
tee /etc/containerd/config.toml <<'EOF'
disabled_plugins = []
imports = []
oom_score = 0
plugin_dir = ""
required_plugins = []
root = "/var/lib/containerd"
state = "/run/containerd"
temp = ""
version = 2
[cgroup]
path = ""
[debug]
address = ""
format = ""
gid = 0
level = ""
uid = 0
[grpc]
address = "/run/containerd/containerd.sock"
gid = 0
max_recv_message_size = 16777216
max_send_message_size = 16777216
tcp_address = ""
tcp_tls_ca = ""
tcp_tls_cert = ""
tcp_tls_key = ""
uid = 0
[metrics]
address = ""
grpc_histogram = false
[plugins]
[plugins."io.containerd.gc.v1.scheduler"]
deletion_threshold = 0
mutation_threshold = 100
pause_threshold = 0.02
schedule_delay = "0s"
startup_delay = "100ms"
[plugins."io.containerd.grpc.v1.cri"]
device_ownership_from_security_context = false
disable_apparmor = false
disable_cgroup = false
disable_hugetlb_controller = true
disable_proc_mount = false
disable_tcp_service = true
enable_selinux = false
enable_tls_streaming = false
enable_unprivileged_icmp = false
enable_unprivileged_ports = false
ignore_image_defined_volumes = false
max_concurrent_downloads = 3
max_container_log_line_size = 16384
netns_mounts_under_state_dir = false
restrict_oom_score_adj = false
sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.7"
selinux_category_range = 1024
stats_collect_period = 10
stream_idle_timeout = "4h0m0s"
stream_server_address = "127.0.0.1"
stream_server_port = "0"
systemd_cgroup = false
tolerate_missing_hugetlb_controller = true
unset_seccomp_profile = ""
[plugins."io.containerd.grpc.v1.cri".cni]
bin_dir = "/opt/cni/bin"
conf_dir = "/etc/cni/net.d"
conf_template = ""
ip_pref = ""
max_conf_num = 1
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
disable_snapshot_annotations = true
discard_unpacked_layers = false
ignore_rdt_not_enabled_errors = false
no_pivot = false
snapshotter = "overlayfs"
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
base_runtime_spec = ""
cni_conf_dir = ""
cni_max_conf_num = 0
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_path = ""
runtime_root = ""
runtime_type = ""
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
base_runtime_spec = ""
cni_conf_dir = ""
cni_max_conf_num = 0
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_path = ""
runtime_root = ""
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
BinaryName = ""
CriuImagePath = ""
CriuPath = ""
CriuWorkPath = ""
IoGid = 0
IoUid = 0
NoNewKeyring = false
NoPivotRoot = false
Root = ""
ShimCgroup = ""
SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]
base_runtime_spec = ""
cni_conf_dir = ""
cni_max_conf_num = 0
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_path = ""
runtime_root = ""
runtime_type = ""
[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime.options]
[plugins."io.containerd.grpc.v1.cri".image_decryption]
key_model = "node"
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = ""
[plugins."io.containerd.grpc.v1.cri".registry.auths]
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.configs."172.16.183.100:32002".tls]
insecure_skip_verify = true
ca_file = ""
cert_file = ""
key_file = ""
[plugins."io.containerd.grpc.v1.cri".registry.configs."172.16.183.100:32002".auth]
username = "admin"
password = "Harbor12345"
[plugins."io.containerd.grpc.v1.cri".registry.headers]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."172.16.183.100:32002"]
endpoint = ["http://172.16.183.100:32002"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://docker.m.daocloud.io"]
[plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
tls_cert_file = ""
tls_key_file = ""
[plugins."io.containerd.internal.v1.opt"]
path = "/opt/containerd"
[plugins."io.containerd.internal.v1.restart"]
interval = "10s"
[plugins."io.containerd.internal.v1.tracing"]
sampling_ratio = 1.0
service_name = "containerd"
[plugins."io.containerd.metadata.v1.bolt"]
content_sharing_policy = "shared"
[plugins."io.containerd.monitor.v1.cgroups"]
no_prometheus = false
[plugins."io.containerd.runtime.v1.linux"]
no_shim = false
runtime = "runc"
runtime_root = ""
shim = "containerd-shim"
shim_debug = false
[plugins."io.containerd.runtime.v2.task"]
platforms = ["linux/amd64"]
sched_core = false
[plugins."io.containerd.service.v1.diff-service"]
default = ["walking"]
[plugins."io.containerd.service.v1.tasks-service"]
rdt_config_file = ""
[plugins."io.containerd.snapshotter.v1.aufs"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.btrfs"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.devmapper"]
async_remove = false
base_image_size = ""
discard_blocks = false
fs_options = ""
fs_type = ""
pool_name = ""
root_path = ""
[plugins."io.containerd.snapshotter.v1.native"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.overlayfs"]
root_path = ""
upperdir_label = false
[plugins."io.containerd.snapshotter.v1.zfs"]
root_path = ""
[plugins."io.containerd.tracing.processor.v1.otlp"]
endpoint = ""
insecure = false
protocol = ""
[proxy_plugins]
[stream_processors]
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
path = "ctd-decoder"
returns = "application/vnd.oci.image.layer.v1.tar"
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
path = "ctd-decoder"
returns = "application/vnd.oci.image.layer.v1.tar+gzip"
[timeouts]
"io.containerd.timeout.bolt.open" = "0s"
"io.containerd.timeout.shim.cleanup" = "5s"
"io.containerd.timeout.shim.load" = "5s"
"io.containerd.timeout.shim.shutdown" = "3s"
"io.containerd.timeout.task.state" = "2s"
[ttrpc]
address = ""
gid = 0
uid = 0
EOF
systemctl daemon-reload && systemctl start containerd && systemctl enable containerd
#修改/etc/crictl.yaml文件,指定k8s的运行时和拉取镜像都使用containerd
#这个文件是 crictl 工具的配置文件,用于指定与 containerd 交互的相关设置:
#指定unix:///run/containerd/containerd.sock 是为了告诉 crictl 使用 Unix 域套接字的方式来连接 containerd 的 API。containerd 提供了一个 socket 文件 /run/containerd/containerd.sock,crictl 通过连接该 socket 文件,可以与 containerd 进行通信,管理容器和镜像等操作。
#runtime-endpoint:指定 containerd 的运行时接口地址:crictl 可以与 containerd 通信来管理容器生命周期和资源隔离。
#image-endpoint:指定 containerd 的镜像接口地址:以便 crictl 可以与 containerd 通信来管理镜像的拉取和推送。
#timeout:指定 crictl 等待 containerd 响应的最大时间,避免出现无响应的情况。
#debug:开启或关闭 crictl 的调试模式,方便排查问题。
cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
systemctl restart containerd
k8s-1.30
#配置安装k8s组件需要的阿里云的repo源
cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/rpm/repodata/repomd.xml.key
EOF
#其中baseurl是指定仓库的URL地址。这个仓库是Kubernetes针对CentOS 7 x86_64架构的yum仓库,yum会从这个指定的URL地址获取Kubernetes的安装包和依赖包,从而进行安装。使用阿里云镜像站可以提高安装速度和稳定性。
yum clean all && yum makecache
yum install -y kubelet-1.30.0 kubeadm-1.30.0 kubectl-1.30.0
systemctl enable kubelet
kubeadm初始化k8s集群
初始化集群
kubeadm config print init-defaults > kubeadm.yaml
tee kubeadm.yaml <<'EOF'
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 172.16.183.100 #控制节点的ip
bindPort: 6443
nodeRegistration:
criSocket: unix:///run/containerd/containerd.sock #指定containerd容器运行时
imagePullPolicy: IfNotPresent
name: rm1 #控制节点主机名
taints: null
---
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.30.0
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/12
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
EOF
kubeadm init --config=kubeadm.yaml --ignore-preflight-errors=SystemVerification
配置kubeconfig
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
#1. 设置kubectl的alias为k:
whereis kubectl ## kubectl: /usr/bin/kubectl
echo "alias k=/usr/bin/kubectl">>/etc/profile
source /etc/profile
#2. 设置alias的自动补全:
source <(kubectl completion bash | sed 's/kubectl/k/g')
#3. 解决每次启动k都会失效,要重新刷新环境变量(source /etc/profile)的问题:在~/.bashrc文件中添加以下代码:source /etc/profile
echo "source /etc/profile" >> ~/.bashrc
#4. 给alias k也配置补全
tee -a ~/.bashrc <<'EOF'
alias k='kubectl'
complete -o default -F __start_kubectl k
source <(kubectl completion bash)
EOF
##使命令生效
source ~/.bashrc
扩容工作节点
#master上
kubeadm token create --print-join-command
#把rnode1加入k8s集群,加上参数:--ignore-preflight-errors=SystemVerification
#打工作节点label
kubectl label nodes rn1 node-role.kubernetes.io/work=worker
安装calico
#上传calico镜像包和yaml文件,解压
##在线下载地址为:https://docs.projectcalico.org/manifests/calico.yaml
ctr -n=k8s.io images import calico.tar.gz
#修改calico.yaml中网卡名称
#- name: CLUSTER_TYPE
# value: "k8s,bgp"
# 上面这一段的下面添加:(指定calico从ens33跨节点通信,不指定的话,会走lo的IP,没办法跨节点通信,也就没办法给pod划分IP)
- name: IP_AUTODETECTION_METHOD
value: "interface=ens160"
kubectl apply -f calico.yaml
#测试网络访问
kubectl run busybox --image busybox:1.28 --image-pull-policy=IfNotPresent --restart=Never --rm -it busybox -- sh
# ping www.baidu.com
# nslookup kubernetes.default.svc.cluster.local