一、环境规划
角色 | IP | 主机名 | 操作系统 | 配置 |
---|---|---|---|---|
控制节点 | 192.168.50.10 | k8s-master | centos9 | 4vCPU/8Gib |
工作节点 | 192.168.50.11 | k8s-node1 | centos9 | 4vCPU/8Gib |
工作节点 | 192.168.50.12 | k8s-node2 | centos9 | 4vCPU/8Gib |
控制节点需要安装的组件:
apiserver、controller-manager、scheduler、kubelet、etcd、docker、kube-proxy、keepalived、nginx、calico
工作节点需要安装的组件:
kubelet、kube-proxy、docker、calico、coredns
二、初始化实验环境
1、修改机器IP,变成静态IP
1.1 查看网卡信息
nmcli con show
1.2 编辑配置文件
vi /etc/NetworkManager/system-connections/ens18.nmconnection
[ipv4]
# mehod=auto # 可以注释掉也可以直接改
method=manual # 改成manual(意思是设置手动模式)
address1=192.168.50.10/24,192.168.50.1 # 地址1 = ip 子网掩码 网关
dns=192.168.50.1 # dns地址,用,隔开
修改配置文件之后需要重启网络服务才能使配置生效
1.3 重启网络
nmcli c reload ens18
注意:这里的ens18是你网卡的名称,可以在第一步查看或者ip addr查看
:::info
按照步骤,在控制节点和工作节点做同样的操作
:::
nmcli命令用法:
# 查看所有网络连接
# 长格式
nmcli connection show
# 短格式,缩写
nmcli con show
# 查看活动的网络连接
nmcli con show -active
# 查看指定网卡的详细信息
nmcli con show eth0
# 显示设备的连接状态
nmcli status
# 显示所有设备网络设备详情信息
nmcli device show
# 显示指定网络设备的详细信息
nmcli device show eth0
网卡状态修改命令:
# 启用网络连接
nmcli con up eth0
# 停用网络连接(可以被自动激活)
nmcli con down eth0
# 禁用网卡,防止自动被激活
nmcli device disconnect eth0
# 删除网络连接的配置文件
nmcli con delete eth0
# 重新加载网络配置文件
nmcli con reload
2、配置机器主机名
在 192.168.50.10上执行:
hostnamectl set-hostname k8s-master && bash
在 192.168.50.11上执行:
hostnamectl set-hostname k8s-node1 && bash
在 192.168.50.12上执行:
hostnamectl set-hostname k8s-node2 && bash
3、配置主机hosts
修改每台机器的/etc/hosts 文件,增加如下三行:
192.168.50.10 k8s-master
192.168.50.11 k8s-node1
192.168.50.12 k8s-node2
4、配置主机之间无密码登录
[root@k8s-master ~]# ssh-keygen #一路回车,不输入密码把本地生成的密钥文件和私钥文件拷贝到远程主机
[root@k8s-master ~]# ssh-copy-id k8s-master
[root@k8s-master ~]# ssh-copy-id k8s-node1
[root@k8s-master ~]# ssh-copy-id k8s-node2
:::info
💡:分别在不同的主机执行此操作
:::
5、关闭交换分区swap
5.1 临时关闭
[root@k8s-master ~]# swapoff -a
[root@k8s-node1 ~]# swapoff -a
[root@k8s-node2 ~]# swapoff -a
5.2 永久关闭
注释 swap 挂载,给 swap 这行开头加一下注释
[root@k8s-master ~]# vim /etc/fstab
#/dev/mapper/centos-swap swap swap defaults 0 0
重启系统使配置生效
如果是克隆的虚拟机,需要删除 UUID
为什么要关闭 swap 交换分区?
Swap 是交换分区,如果机器内存不够,会使用 swap 分区,但是 swap 分区的性能较低,k8s 设计的
时候为了能提升性能,默认是不允许使用交换分区的。Kubeadm 初始化的时候会检测 swap 是否关
闭,如果没关闭,那就初始化失败。如果不想要关闭交换分区,安装 k8s 的时候可以指定--ignore
preflight-errors=Swap 来解决。
使用free -h查看操作是否成功
6、修改机器内核参数
[root@k8s-master ~]# modprobe br_netfilter
[root@k8s-master ~]# vi /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
使配置生效:
sysctl -p /etc/sysctl.d/k8s.conf
问题 1:sysctl 是做什么的?
在运行时配置内核参数
-p 从指定的文件加载系统参数,如不指定即从/etc/sysctl.conf 中加载
问题 2:为什么要执行 modprobe br_netfilter?
修改/etc/sysctl.d/k8s.conf 文件,增加如下三行参数:
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
问题 3:为什么开启 net.bridge.bridge-nf-call-iptables 内核参数?
在 centos 下安装 docker,执行 docker info 出现如下警告:
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
net.ipv4.ip_forward 是数据包转发:
出于安全考虑,Linux 系统默认是禁止数据包转发的。所谓转发即当主机拥有多于一块的网卡时,
其中一块收到数据包,根据数据包的目的 ip 地址将数据包发往本机另一块网卡,该网卡根据路由表继
续发送数据包。这通常是路由器所要实现的功能。
要让 Linux 系统具有路由转发功能,需要配置一个 Linux 的内核参数 net.ipv4.ip_forward。这个
参数指定了 Linux 系统当前对路由转发功能的支持情况;其值为 0 时表示禁止进行 IP 转发;如果是 1,
则说明 IP 转发功能已经打开。
7、关闭firewalld防火墙
[root@k8s-master ~]# systemctl stop firewalld ; systemctl disable firewalld
[root@k8s-node1 ~]# systemctl stop firewalld ; systemctl disable firewalld
[root@k8s-node2 ~]# systemctl stop firewalld ; systemctl disable firewalld
8、关闭selinux
[root@k8s-master ~]# vi /etc/selinux/config
将SELINUX=enforcing 修改为SELINUX=disabled
重启系统
验证:getenforce
显示 Disabled 说明 selinux 已经关闭
9、配置国内yum的repo源
CentOS Stream 9 默认启用了包管理工具 dnf,其是 yum 包管理工具的替代品。dnf 与 yum 大部分的命令都是通用的,dnf 也使用 /etc/yum.repos.d/
进行镜像配置。
CentOS Stream 9 中源被整合入两个文件 centos.repo
和 centos-addons.repo
,由于文件中不包含 baseurl
字段,需要手动插入,通过文本替换修改源的方法较为复杂,也可以选择直接复制最后的替换结果覆盖源文件。
1、备份基础 repo 源
[root@k8s-master ~]# mkdir /root/repo.bak
[root@k8s-master ~]# cd /etc/yum.repos.d/
[root@k8s-master ~]# cp * /root/repo.bak
2、安装perl:
# 使用 dnf
dnf install perl
# 使用 yum
yum install perl
3、update_mirror.pl
将以下段代码保存为一个文件,例如 update_mirror.pl
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
my $mirrors = 'https://mirrors.tuna.tsinghua.edu.cn/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 $_;
}
}
4、修改repo:
然后,在命令行中使用以下命令来执行它:
perl ./update_mirror.pl /etc/yum.repos.d/centos*.repo
5、更新软件包缓存
最后,更新软件包缓存:
# 使用 dnf
dnf clean all && dnf makecache
# 使用 yum
yum clean all && yum makecache
10、配置国内Docker的repo源安装containerd
如果你之前安装过 docker,请先删掉
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
安装依赖,下载 repo 文件,并把软件仓库地址替换为镜像站:
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sed -i 's+https://download.docker.com+https://mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
11、配置K8s组件需要的repo源
新建 /etc/yum.repos.d/kubernetes.repo
,内容为:
[kubernetes]
name=kubernetes
baseurl=https://mirrors.tuna.tsinghua.edu.cn/kubernetes/yum/repos/kubernetes-el7-$basearch
name=Kubernetes
baseurl=https://mirrors.tuna.tsinghua.edu.cn/kubernetes/core:/stable:/v1.28/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/repodata/repomd.xml.key
12、配置时间同步
CentOS9系统中,原有的时间同步服务 ntp/ntpdate服务已经无法使用
- 在CentOS9中,已使用chrony替代ntp,首先安装chrony
#使用dnf安装
dnf install -y chrony
# 也可以用yum安装
yum install -y chrony
- 修改配置文件
vim /etc/chrony.conf
修改配置文件,将第三行注释后添加如下内容
#pool 2.centos.pool.ntp.org iburst
pool ntp1.aliyun.com iburst
pool ntp2.aliyun.com iburst
pool ntp3.aliyun.com iburst
pool ntp4.aliyun.com iburst
pool ntp5.aliyun.com iburst
pool ntp6.aliyun.com iburst
- 重启chronyd服务
systemctl restart chronyd
#设置时间同步服务开机启动
systemctl enable chronyd
- 查看同步情况
chronyc sources
13、开启 ipvs
在k8s-master机器的/etc/modules-load.d/目录下新建ipvs.modules文件,将以下内容拷贝到文件中:
#!/bin/bash
ipvs_modules="ip_vs ip_vs_lc ip_vs_wlc ip_vs_rr ip_vs_wrr ip_vs_lblc ip_vs_lblcr ip_vs_dh ip_vs_sh ip_vs_nq ip_vs_sed ip_vs_ftp nf_conntrack"
for kernel_module in ${ipvs_modules}; do
/sbin/modinfo -F filename ${kernel_module} > /dev/null 2>&1
if [ 0 -eq 0 ]; then
/sbin/modprobe ${kernel_module}
fi
done
然后执行命令:
root@k8s-master ~]# chmod 755 /etc/modules-load.d/ipvs.modules && bash
/etc/modules-load.d/ipvs.modules && lsmod | grep ip_vs
拷贝ipvs.modules到k8s-node1和k8s-node2机器上
[root@k8s-master ~]# scp /etc/modules-load.d/ipvs.modules
k8s-node1:/etc/modules-load.d/
[root@k8s-master ~]# scp /etc/modules-load.d/ipvs.modules
k8s-node2:/etc/modules-load.d/
然后执行命令:
[root@k8s-node1 ~]# chmod 755 /etc/modules-load.d/ipvs.modules && bash
/etc/modules-load.d/ipvs.modules && lsmod | grep ip_vs
[root@k8s-node2 ~]# chmod 755 /etc/modules-load.d/ipvs.modules && bash
/etc/modules-load.d/ipvs.modules && lsmod | grep ip_vs
问题1:ipvs是什么?
ipvs (IP Virtual Server)实现了传输层负载均衡,也就是我们常说的4层LAN交换,作为Linux内核的一部分。ipvs运行在主机上,在真实服务器集群前充当负载均衡器。ipvs可以将基于TCP和UDP的服务请求转发到真实服务器上,并使真实服务器的服务在单个IP地址上显示为虚拟服务。
问题2:ipvs和iptable对比分析
kube-proxy 支持 iptables 和 ipvs 两种模式, 在 kubernetes v1.8 中引入了 ipvs 模式,在v1.9 中处于 beta 阶段,在 v1.11 中已经正式可用了。iptables 模式在 v1.1 中就添加支持了,从v1.2 版本开始 iptables 就是 kube-proxy 默认的操作模式,ipvs 和 iptables 都是基于 netfilter的,但是 ipvs 采用的是 hash 表,因此当 service 数量达到一定规模时,hash 查表的速度优势就会显现
出来,从而提高 service 的服务性能。那么 ipvs 模式和 iptables 模式之间有哪些差异呢?
- 1、ipvs 为大型集群提供了更好的可扩展性和性能
- 2、ipvs 支持比 iptables 更复杂的复制均衡算法(最小负载、最少连接、加权等等)
- 3、ipvs 支持服务器健康检查和连接重试等功能
14、安装基础软件包
每台机器都要安装:
[root@k8s-master ~]# yum install -y yum-utils 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 zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack telnet ipvsadm
[root@k8s-node1 ~]# yum install -y yum-utils 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 zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack telnet ipvsadm
[root@k8s-node2 ~]# yum install -y yum-utils 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 zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack telnet ipvsadm
15、安装iptables(可选)
如果用firewalld不习惯,可以安装iptables,在k8s-master、k8s-node1、k8s-node2上操作:
# 安装iptables
yum install iptables-services -y
# 禁用iptables
systemctl stop iptables && systemctl disable iptables
# 清空防火墙规则
iptables -F
三、安装Containerd服务
安装containerd
分别在三台服务器上安装containerd
$ sudo dnf update
$ sudo dnf install -y containerd
$ sudo mkdir -p /etc/containerd
$ sudo containerd config default | sudo tee /etc/containerd/config.toml
# 修改containerd配置
$ sudo vi /etc/containerd/config.toml
# 1、找到[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]并将值更改SystemdCgroup为true
# 2、找到sandbox_image = "k8s.gcr.io/pause:3.6"并改为sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
# 重启以应用更改
$ sudo systemctl restart containerd
# 加入开机启动
$ sudo systemctl enable containerd
四、安装k8s软件包
[root@k8s-master ~]# yum install -y kubelet kubeadm kubectl
[root@k8s-master ~]# systemctl enable kubelet && systemctl start kubelet
[root@k8s-master ~]# systemctl status kubelet
[root@k8s-node1 ~]# yum install -y kubelet kubeadm kubectl
[root@k8s-node1 ~]# systemctl enable kubelet && systemctl start kubelet
[root@k8s-node1 ~]# systemctl status kubelet
[root@k8s-node2 ~]# yum install -y kubelet kubeadm kubectl
[root@k8s-node2 ~]# systemctl enable kubelet && systemctl start kubelet
[root@k8s-node2 ~]# systemctl status kubelet
注:上面可以看到 kubelet 状态不是 running 状态,这个是正常的,不用管,等 k8s 组件起来这个kubelet 就正常了。
注:每个软件包的作用 :
Kubeadm: kubeadm 是一个工具,用来初始化 k8s 集群的
kubelet: 安装在集群所有节点上,用于启动 Pod 的
kubectl: 通过 kubectl 可以部署和管理应用,查看各种资源,创建、删除和更新各种组件
五、kubeadm 初始化 k8s 集群
所有节点执行:
sudo yum install -y kubelet kubeadm kubectl
使用 kubeadm 创建集群
kubeadm config images list
主节点初始化 (以下操作只在主节点执行)
生成默认配置文件
kubeadm config print init-defaults > kubeadm.conf
输出内容如下:
apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 1.2.3.4
bindPort: 6443
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
name: node
taints: null
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.k8s.io
kind: ClusterConfiguration
kubernetesVersion: 1.29.0
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
scheduler: {}
修改配置文件内容
主要修改以下几个地方
1、advertiseAddress:改为当前主机的ip地址
2、nodeRegistration.name:改为当前主机的hostname
3、imageRepository:我这里改成自己的私人仓库地址了,如果自己有的话可以改成自己的,没有的话可以改成阿里云的镜像源地址:registry.aliyuncs.com/google_containers
4、新添加KubeletConfiguration,指定驱动类型。内容如下:
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
5、serviceSubnet:这个看情况,如果自己想改的话也可以改,我这里用的默认的
6、podSubnet:指定容器的ip段
7、kubernetesVersion:改为当前对应的版本
开始初始化
kubeadm.conf:自定义的配置文件的名称
kubeadm init --config kubeadm.conf
创建配置文件
按照初始化成功的提示开始创建配置文件
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
获取集群token方法(备用)
在 Kubernetes 中,获取集群的 token 通常用于集群扩容,将新的节点加入到现有的集群中。以下是如何生成和获取 Kubernetes 集群 token 的详细步骤。
方法一:通过 kubeadm 生成新 token
可以使用 kubeadm token create 命令来生成一个新的 token。该命令可以在集群控制的任意一个master主节点上运行。
kubeadm token create --print-join-command
这个命令将生成一个新的 token 并输出 kubeadm join 命令的完整语法,包括生成的 token 和 discovery-token-ca-cert-hash,直接复制并在工作节点上运行这个命令来加入当前集群。
方法二:查看现有的 token
查看当前已有的 token,可以使用以下命令:
kubeadm token list
该命令可以在集群控制的任意一个master主节点上运行。同时列出当前所有有效的 token 及其相关信息。
方法三:通过手动生成 token
kubeadm token create <your-token> --ttl <duration>
这里, 是你想要生成的 token, duration是 token 的有效期,例如 24h 表示 24 小时。
安装网络插件
这里安装的网络插件是Calico
下载并执行配置文件
文件下载后要使用kubectl create 命令去执行,不要使用kubectl apply ,官方文档对这个有特别说明
wget https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/tigera-operator.yaml
kubectl create -f tigera-operator.yaml
wget https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/custom-resources.yaml
修改custom-resources.yaml
vim custom-resources.yaml
修改cidr的值
calicoNetwork:
ipPools:
- name: default-ipv4-ippool
blockSize: 26
cidr: 192.168.110.0/24 # 修改为kubeadm.conf中podSubnet的值
执行 custom-resources.yaml
kubectl create -f custom-resources.yaml
节点加入
在k8s-node1上执行以下命令
kubeadm join 192.168.50.10:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:5383f1be9920a38c34a0b0eba61ed113311f27f55e2748bd7b566584b7b2eca9
在k8s-node2上执行以下命令
kubeadm join 192.168.50.10:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:5383f1be9920a38c34a0b0eba61ed113311f27f55e2748bd7b566584b7b2eca9