kubernetes集群部署
常见的 k8s 部署方式包括:二进制包、kubeadm 工具、云服务提供商、或通过一些开源的工具搭建,例如:sealos、kuboard、Runcher、kubeSphere。
本文使用kubeadm的部署方式,部署k8s1.28版本
我本地安装资源规划如下:
IP地址 | 主机名称 | 角色 | 操作系统 | 主机配置参考 |
---|---|---|---|---|
192.168.3.92 | master1 | master | rockylinux9.4(最小化安装) | 4核心CPU/4G内存/80G磁盘 |
192.168.3.93 | worker1 | worker | rockylinux9.4(最小化安装) | 4核心CPU/4G内存/80G磁盘 |
192.168.3.94 | worker2 | worker | rockylinux9.4(最小化安装) | 4核心CPU/4G内存/80G磁盘 |
初始化集群环境
**注意:**初始化集群环境,以下步骤在所有主机都需相应操作
修改相应主机的主机名称和host文件解析
bash
hostnamectl set-hostname master1 && bash
hostnamectl set-hostname worker1 && bash
hostnamectl set-hostname worker2 && bash
bash
cat <<EOF >> /etc/hosts
192.168.3.92 master1
192.168.3.93 worker1
192.168.3.94 worker2
EOF
配置相应主机的静态IP地址
bash
vim /etc/NetworkManager/system-connections/ens160.nmconnection
[connection]
id=ens160
uuid=8fa4f8df-0d4d-3993-a38d-4de4f1af2382
type=ethernet
autoconnect-priority=-999
interface-name=ens160
timestamp=1725741990
[ethernet]
[ipv4]
method=manual
dns=114.114.114.114
address1=192.168.3.92/24,192.168.3.2
[ipv6]
addr-gen-mode=eui64
method=auto
[proxy]
安装常用软件包
bash
yum install -y epel-release tree vim wget bash-completion lrzsz nfs-utils net-tools sysstat iotop unzip nc nmap telnet bc psmisc yum-utils ipvsadm git socat conntrack sshpass libseccomp device-mapper-persistent-data lvm2 gcc gcc-c++ make cmake libxml2-devel openssl-devel curl libaio-devel ncurses-devel autoconf automake zlib-devel epel-release telnet
关闭selinux和防火墙
bash
setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
systemctl stop firewalld.service && systemctl disable firewalld.service
关闭swap缓存
bash
swapoff -a && sed -ri 's/.*swap.*/#&/' /etc/fstab
配置免密登录
生成秘钥
bash
ssh-keygen
拷贝秘钥到相应主机
bash
ssh-copy-id 192.168.3.92
安装时间同步chrony软件
bash
yum install chrony -y
bash
systemctl enable chronyd.service --now
systemctl restart chronyd.service
bash
vim /etc/chrony.conf
#修改以下位置
#pool 2.rocky.pool.ntp.org iburst
pool ntp1.aliyun.com
修改内核参数
bash
#加载内核模块
modprobe br_netfilter
modprobe ip_conntrack
modprobe iptable_filter
modprobe iptable_nat
modprobe overlay
#查看是否加载
lsmod | grep -e ip_vs -e nf_conntrack
nf_conntrack 176128 1 nf_nat
nf_defrag_ipv6 20480 1 nf_conntrack
nf_defrag_ipv4 16384 1 nf_conntrack
libcrc32c 16384 3 nf_conntrack,nf_nat,xfs
lsmod | grep ip
iptable_nat 16384 0
nf_nat 49152 1 iptable_nat
iptable_filter 16384 0
ip_tables 28672 2 iptable_filter,iptable_nat
nf_defrag_ipv6 20480 1 nf_conntrack
nf_defrag_ipv4 16384 1 nf_conntrack
#修改内核参数
cat > /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 --system
#持久化加载内核模块
cat > /etc/modules-load.d/modules.conf << EOF
br_netfilter
ip_conntrack
iptable_filter
iptable_nat
overlay
EOF
systemctl restart systemd-modules-load.service
#解释:
#对网桥上的IPv6数据包通过iptables处理 net.bridge.bridge-nf-call-ip6tables = 1
#对网桥上的IPv4数据包通过iptables处理 net.bridge.bridge-nf-call-iptables = 1
#开启IPv4路由转发,来实现集群中的容器与外部网络的通信 net.ipv4.ip_forward = 1
安装docker
bash
yum install -y yum-utils
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#查看yum源中的docker版本
yum list docker-ce.x86_64 --showduplicates | sort -r
#安装指定版本
yum -y install docker-ce-26.1.1-1.el9.x86_64
安装好docker后containerd.io作为docker依赖也会被安装,在安装k8s前就无需再安装containerd.io了
shell
[root@master1 ~]# rpm -qa | grep containerd
containerd.io-1.6.32-3.1.el8.x86_64
启用Docker Cgroup控制组,用于限制进程的资源使用量,如CPU、内存。再配置镜像加速器,harbor地址,方便后期拉取镜像。
bash
mkdir /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"log-opts": {
"max-size": "5m",
"max-file":"3"
},
"exec-opts": ["native.cgroupdriver=systemd"],
"insecure-registries": ["192.168.137.35","harbor.cn"],
"registry-mirrors": [
"https://jockerhub.com",
"https://mirror.baidubce.com",
"https://dockerproxy.com",
"https://docker.laoex.link",
"https://docker.nju.edu.cn"
]
}
EOF
启动Docker服务并设置开机自启动
bash
systemctl enable docker --now
安装k8s
配置软件仓库和安装所需包
因上文安装好了docker所以在安装k8s前就无需再安装containerd.io了
**注意:**所有主机均需要操作
添加阿里云kubernetes仓库
bash
cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
新版k8s网络源地址 1.29+版本
bash
cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.29/rpm/
enabled=1
gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/repodata/repomd.xml.key
EOF
安装集群所需软件包
●kubeadm:用于初始化集群,并配置集群所需的组件并生成对应的安全证书和令牌;
●kubelet:负责与 Master 节点通信,并根据 Master 节点的调度决策来创建、更新和删除 Pod,同时维护 Node 节点上的容器状态;
●kubectl:用于管理k8集群的一个命令行工具;
安装 kubeadm kubelet kubectl
bash
dnf install -y kubeadm-1.28.2-0 kubelet-1.28.2-0 kubectl-1.28.2-0
设置kubelet开机自启,集群初始化时kubelet会随着集群启动
bash
systemctl enable kubelet
生成且修改containerd的配置文件(原有的配置文件不可使用)
bash
containerd config default > /etc/containerd/config.toml
#修改以下配置
vim /etc/containerd/config.toml
139 SystemdCgroup = true
67 sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
#拷贝到其它主机
scp /etc/containerd/config.toml 192.168.3.93:/etc/containerd/config.toml
scp /etc/containerd/config.toml 192.168.3.94:/etc/containerd/config.toml
启动containerd并设置开机自启动
bash
systemctl restart containerd
systemctl enable containerd
查看集群所需镜像文件(国外镜像我们无法下载的)
bash
kubeadm config images list --kubernetes-version=v1.28.13
I0907 22:45:30.944332 40619 version.go:256] remote version is much newer: v1.31.0; falling back to: stable-1.28
registry.k8s.io/kube-apiserver:v1.28.13
registry.k8s.io/kube-controller-manager:v1.28.13
registry.k8s.io/kube-scheduler:v1.28.13
registry.k8s.io/kube-proxy:v1.28.13
registry.k8s.io/pause:3.9
registry.k8s.io/etcd:3.5.9-0
registry.k8s.io/coredns/coredns:v1.10.1
kubernetes集群初始化
注:在master节点初始化集群
生成集群初始化配置文件
shell
kubeadm config print init-defaults > kubeadm.yaml
修改advertiseAddress,name,imageRepository,kubernetesVersion的值,
添加podSubnet字段,加入kube proxy模式为ipvs的配置字段
yaml
vim kubeadm.yaml
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: 192.168.3.92 #控制节点IP
bindPort: 6443
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
name: master1 #控制节点名称
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.cn-hangzhou.aliyuncs.com/google_containers #改为国内镜像
kind: ClusterConfiguration
kubernetesVersion: 1.28.13 #修改成1.28.13版本
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16 #添加这个字段 指定pod网段
serviceSubnet: 10.96.0.0/12
scheduler: {}
#加入以下配置使用ipvs转发规则
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
准备镜像
bash
kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers --kubernetes-version=v1.28.13
导出所有镜像到其它主机,防止网络原因导致集群初始化失败
bash
ctr -n=k8s.io images export all.tar.gz \
registry.aliyuncs.com/google_containers/coredns:v1.10.1 \
registry.aliyuncs.com/google_containers/etcd:3.5.9-0 \
registry.aliyuncs.com/google_containers/kube-apiserver:v1.28.13 \
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.28.13 \
registry.aliyuncs.com/google_containers/kube-proxy:v1.28.13 \
registry.aliyuncs.com/google_containers/kube-scheduler:v1.28.13 \
registry.aliyuncs.com/google_containers/pause:3.9
scp k8sall.tar.gz 192.168.3.93:/root/
scp k8sall.tar.gz 192.168.3.94:/root/
#[root@worker1 ~]
ctr -n=k8s.io images import k8sall.tar.gz
#[root@worker2 ~]
ctr -n=k8s.io images import k8sall.tar.gz
执行初始化命令(控制节点执行)
bash
kubeadm init --config=kubeadm.yaml --ignore-preflight-errors=SystemVerification
安装成功后会有以下提示信息
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join 192.168.3.199:16443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:d53d64de26fe12db3fc01de53b3f8c7f281f465215b2c3bb34be6747c3db9870 \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.3.199:16443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:d53d64de26fe12db3fc01de53b3f8c7f281f465215b2c3bb34be6747c3db9870
初始化成功后,按照提示准备集群管理员配置文件
bash
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
配置tab键命令补全
bash
yum install bash-completion
source /usr/share/bash-completion/bash_completion
echo 'source <(kubectl completion bash)' >>~/.bashrc
echo 'alias k=kubectl' >>~/.bashrc
echo 'complete -o default -F __start_kubectl k' >>~/.bashrc
source ~/.bashrc
查看集群状态
bash
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master NotReady control-plane 2m3s v1.28.2
此时集群状态还是NotReady 状态,因为网络组件没有启动。
部署Pod网络插件Calico
Calico 和 Flannel 是两种流行的 k8s 网络插件,它们都为集群中的 Pod 提供网络功能,然而,它们在实现方式和功能上有一些重要区别:
模型的区别:
●Calico 使用 BGP(边界网关协议)作为其底层网络模型。它利用 BGP 为每个 Pod 分配一个唯一的 IP 地址,并在集群内部进行路由。Calico 支持网络策略,可以对流量进行精细控制,允许或拒绝特定的通信。
●Flannel 则采用了一个简化的覆盖网络模型。它为每个节点分配一个 IP 地址子网,然后在这些子网之间建立覆盖网络。Flannel 将 Pod 的数据包封装到一个更大的网络数据包中,并在节点之间进行转发。Flannel 更注重简单和易用性,不提供与 Calico 类似的网络策略功能。
性能的区别:
●由于 Calico 使用 BGP 进行路由,其性能通常优于 Flannel。Calico 可以实现直接的 Pod 到 Pod 通信,而无需在节点之间进行额外的封装和解封装操作。这使得 Calico 在大型或高度动态的集群中具有更好的性能。
●Flannel 的覆盖网络模型会导致额外的封装和解封装开销,从而影响网络性能。对于较小的集群或对性能要求不高的场景,这可能并不是一个严重的问题。
**注:**在线下载配置文件地址是: https://calico-v3-25.netlify.app/archive/v3.25/manifests/calico.yaml
在master1节点下载calico.yaml文件
bash
wget https://docs.tigera.io/archive/v3.25/manifests/calico.yaml
vim calico.yaml
#修改pod网段ip ,把注释放开并修改vlaue值
...
- name: CALICO_IPV4POOL_CIDR
value: "10.244.0.0/16"
...
若机器有多个网卡,需要在calico.yaml配置文件里指定可以联网的网卡。(若机器只有一个网卡也可以不配置此步)
增加指定网卡配置:(4513 4514 行 不同版本的calico行号位置略有不同)
4508 name: calico-config
4509 key: calico_backend
4510 # Cluster type to identify the deployment type
4511 - name: CLUSTER_TYPE
4512 value: "k8s,bgp"
4513 - name: IP_AUTODETECTION_METHOD #加入这行
4514 value: "interface=ens160" #加入这行
4515 # Auto-detect the BGP IP address.
4516 - name: IP
4517 value: "autodetect"
提前下载calico.yaml中所需要的镜像文件并导出至所有主机,防止网络原因导致集群初始化失败
bash
docker pull docker.io/calico/kube-controllers:v3.25.0
docker pull docker.io/calico/node:v3.25.0
docker pull docker.io/calico/cni:v3.25.0
#这里我多下载一个nginx的镜像方便安装好后测试集群网络是否可用
docker pull docker.io/library/nginx:1.21
#导出所需要的镜像
docker save $(docker images | grep -v REPOSITORY | awk 'BEGIN{OFS=":";ORS=" "}{print $1,$2}') -o calicoimg.tar.gz
#所有主机都需要导入镜像
scp calicoimg.tar.gz 192.168.3.93:/root/
scp calicoimg.tar.gz 192.168.3.94:/root/
#[root@master1 ~]
ctr -n=k8s.io images import calicoimg.tar.gz
#[root@worker1 ~]
ctr -n=k8s.io images import calicoimg.tar.gz
#[root@worker2 ~]
ctr -n=k8s.io images import calicoimg.tar.gz
在master1节点创建Calico网络
bash
kubectl apply -f calico.yaml
等待Calico相关的Pod状态为Running即可
bash
[root@master ~]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-9d57d8f49-lk7sw 1/1 Running 0 10m
calico-node-drsmx 1/1 Running 0 10m
coredns-6554b8b87f-6rjtd 1/1 Running 0 39m
coredns-6554b8b87f-w5gzw 1/1 Running 0 39m
etcd-master 1/1 Running 0 39m
kube-apiserver-master 1/1 Running 0 39m
kube-controller-manager-master 1/1 Running 0 39m
kube-proxy-cj5v8 1/1 Running 0 39m
kube-scheduler-master 1/1 Running 0 39m
查看集群节点状态是否为Ready
bash
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane 39m v1.28.2
将工作节点加入集群
在master1主机上查看加入节点的命令:
bash
kubeadm token create --print-join-command
kubeadm join 192.168.3.92:6443 --token 27z1xd.143q77f4jqnt67r4 --discovery-token-ca-cert-hash sha256:48f4733f89787e74a07ac9a87d91782093a46190131ecfb20260a75968aa8166
其它节点(worker1 worker2)执行加入命令
bash
kubeadm join 192.168.3.92:6443 --token 27z1xd.143q77f4jqnt67r4 --discovery-token-ca-cert-hash sha256:48f4733f89787e74a07ac9a87d91782093a46190131ecfb20260a75968aa8166
创建nginx pod测试集群网络是否正常
yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080
浏览器访问 192.168.3.86:30080 nginx服务