Appearance
Kubeadm部署K8S
节点准备
所有主机均需操作
主机名配置
bash
$ hostnamectl set-hostname xxxx主机名与IP地址的解析
bash
$ vi /etc/hosts
xxx.xxx.xxx.mm1 master1
xxx.xxx.xxx.nn1 node1
xxx.xxx.xxx.nn2 node2防火墙配置
bash
# 关闭防火墙
$ systemctl stop firewalld
$ systemctl disbale firewalld
# 或
$ systemctl disbale --now firewalld
# 查看状态
$ firewall-cmd --state
not runningSELINUX配置
bash
$ sed -i s#SELINUX=enforcing#SELINUX=disabled# /etc/selinux/config
$ sestatus时间同步
bash
# crontab -e
0 */1 * * * /usr/sbin/ntpdate time1.aliyun.com
# crontab -l升级内核操作
其他系统需要自行解决
建议更新,有些软件要求高版本的内核,才能完全使用其功能
Linux 内核分两种:官方内核(通常是内核开发人员用)和各大 Linux 发行版内核(一般用户常用)
关于Linux内核版本号
bash
$ uname -r如:
bash3.10.0-1127.19.1.el7.x86_64查询得到的版本号为:3.10.0-1127.19.1.el7.x86_64
第一个组数字:3, 主版本号
第二个组数字:10, 次版本号,当前为稳定版本,一般这个数字为偶数表示稳定,奇数表示在开发版本,通常这样的不做生产使用。
第三个组数字:0, 修订版本号
第四个组数字:1127.19.1,表示发型版本的补丁版本
el7:则表示我正在使用的内核是 RedHat / CentOS 系列发行版专用内核 ,centos7
x86_64:采用的是适用64位的CPU的操作系统
CentOS 允许使用 ELRepo,这是一个第三方仓库,可以将内核升级到最新版本
导入该源的秘钥
bash
$ rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org启用该源仓库
bash
$ rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm查看有哪些内核版本可供安装
bash
$ yum --disablerepo="*" --enablerepo="elrepo-kernel" list available安装主线版本,该版本比较激进,慎重选择
bash
$ yum --enablerepo=elrepo-kernel install kernel-ml -y安装长期稳定版本,稳定可靠
bash
$ yum --enablerepo=elrepo-kernel install kernel-lt -y设置 GRUB 默认的内核版本
设置grub2默认引导为0
bash
$ grub2-set-default 0重新生成grub2引导文件
bash
$ grub2-mkconfig -o /boot/grub2/grub.cfg更新后重启,使升级的内核生效
bash
$ reboot配置内核路由转发及网桥过滤
添加网桥过滤机内核转发配置文件
bash
$ 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
vm.swappiness = 0
net.bridge.bridge-nf-call-ip6tables = 1:这个参数设置为 1,表示在 Linux 内核中启用 IPv6 的网络地址转换 (NAT) 功能,允许 iptables 调用 ip6tables 进行 IPv6 数据包的处理。
net.bridge.bridge-nf-call-iptables = 1:这个参数设置为 1,表示在 Linux 内核中启用 iptables 的网络地址转换 (NAT) 功能,允许 iptables 进行网络数据包的处理和转发。
net.ipv4.ip_forward = 1:这个参数设置为 1,表示启用 Linux 内核的 IP 转发功能,允许 Linux 主机作为一个路由器来转发 IP 数据包。
vm.swappiness = 0:这个参数设置为 0,表示将内核对交换空间(swap)的使用降到最低。较低的 swappiness 值将更多的内存保留在物理内存中,而不是将其交换到磁盘上的交换空间
加载br_netfilter模块
此步如果直接让配置生效,会有报错,所以需要加载相关模块
bash
$ modprobe br_netfilter查看是否加载
bash
$ lsmod | grep br_netfilter
br_netfilter 22256 0
bridge 151336 1 br_netfilter配置生效
bash
$ sysctl -p /etc/sysctl.d/k8s.conf
# 或
$ sysctl --system安装ipset及ipvsadm
不是必须,1.18+建议安装
在k8s中Service有两种代理模型,一种是基于iptables的,一种是基于ipvs,两者对比ipvs的性能要高,如果想要使用ipvs模型,需要手动载入ipvs模块
安装ipset及ipvsadm
bash
$ yum -y install ipset ipvsadm配置ipvsadm模块加载方式
bash
$ cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack
EOF授权
bash
$ chmod 755 /etc/sysconfig/modules/ipvs.modules执行脚本
bash
$ /etc/sysconfig/modules/ipvs.modules验证ipvs模块
bash
$ lsmod | grep -e ip_vs -e nf_conntrack_ipv4关闭swap分区
k8s 1.28+可以开启,但是初始化可能有问题
建议关闭
bash
# 永远关闭,需重启
$ vi /etc/fstab
# 注释掉swap行
# 临时关闭
$ swapoff -a容器运行时准备
所有主机安装
k8s1.20+对容器运行时接口做了标准化,不管什么容器运行时都要能与k8s对接,docker通过
cri-dockerd方式来对接的
Docker-ce
在线安装
加yum源
bash
$ wget http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo安装docker
bash
$ yum install -y docker-ce离线安装
二进制安装
解压二进制包
bash
$ tar -xf docker-19.03.9.tgz
$ mv docker/* /usr/bin && rm -rf dockersystemd管理docker
bash
$ cat > /etc/systemd/system/docker.service << EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF离线yum源安装
通过yum install -y --downloadonly方式下载后上传到离线服务器
或自建本地yum源,直接yum进行安装,安装参考 在线安装,只不是添加yum换成了配置本地yum源
启动
bash
$ systemctl enable --now docker修改cgroup方式
创建或修改/etc/docker/daemod.json
bash
$ vi /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"]
}bash
$ systemctl restart dockercri-dockerd
yum安装
bash
$ wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.14/cri-dockerd-0.3.14-3.el7.x86_64.rpm
$ yum install -y cri-dockerd-0.3.14-3.el7.x86_64.rpm修改service文件
bash
$ vi /usr/lib/systemd/system/cri-docker.service
ExecStart=/usr/bin/cri-dockerd --pod-infra-container-image=registry.k8s.io/pause:3.9 --container-runtime-endpoint fd://
# ExecStart=/usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.k8s.io/pause:3.9启动
bash
$ systemctl start cri-docker
$ systemctl enable cri-docker启动后会产生socket:/var/run/cri-dockerd.sock,后续k8s集群就使用这个socket
Containerd 安装
containerd · Github:https://github.com/containerd/containerd/releases
下载cri-containerd包
bash
# amd
$ wget https://github.com/containerd/containerd/releases/download/v1.7.22/cri-containerd-1.7.22-linux-amd64.tar.gz
# arm
$ wget https://github.com/containerd/containerd/releases/download/v1.7.22/cri-containerd-1.7.22-linux-arm64.tar.gz解压
cri-containerd压缩包里所有相关资源都是按目录层级存放的,因此解压到/目录即可
bash
# amd
$ tar -xf cri-containerd-1.7.22-linux-amd64.tar.gz -C /
# arm
$ tar -xf cri-containerd-1.7.22-linux-arm64.tar.gz -C /配置文件生成及修改
bash
$ mkdir /etc/containerd
$ containerd config default > /etc/containerd/config.toml
$ vi /etc/containerd/config.toml
sandbox_image = "registry.k8s.io/pause:3.8" # pause:3.8修改为pause:3.9启动及设置开机自启
bash
$ systemctl enable --now containerd版本验证
bash
$ containerd --versionrunc准备
runc · GitHub:https://github.com/opencontainers/runc/releases
下载libseccomp
bash
$ wget https://github.com/opencontainers/runc/releases/download/v1.2.0-rc.3/libseccomp-2.5.5.tar.gz解压
bash
$ tar -xf libseccomp-2.5.5.tar.gz编译安装
bash
# 进入目录
$ cd libseccomp-2.5.5
# 安装编译依赖
$ yum install -y gperf
# 配置 编译安装
$ ./configure
$ make && make install
# 校验,一般会在/usr/local/lib/libseccomp.so
$ find / -name "libseccomp.so"查看原来runc的位置
bash
$ which runc
/usr/local/sbin/runc下载runc
bash
# amd
$ wget https://github.com/opencontainers/runc/releases/download/v1.2.0-rc.3/runc.amd64
# arm
$ wget https://github.com/opencontainers/runc/releases/download/v1.2.0-rc.3/runc.arm64替换
bash
# 给予执行权限
$ chmod +x runc.amd64 # chmod +x runc.arm64
# 删除原有的runc
$ rm -rf `which runc`
# 替换
$ mv runc.amd64 /usr/local/sbin/runc # mv runc.arm64 /usr/local/sbin/runc验证
bash
$ runc
# 会出现帮助信息
$ runc --version
# 会出现版本信息k8S安装
软件及版本说明
| 软件 | 版本 | 安装位置 | 作用 |
|---|---|---|---|
| kubeadm | 1.29.0 | 集群所有主机 | 初始化集群、管理集群等 |
| kubelet | 1.29.0 | 集群所有主机 | 接收api-server指令,对pod生命周期进行管理 |
| kubectl | 1.29.0 | 集群所有主机 | 集群应用命令行管理工具 |
yum安装
kubernetes yum源准备
使用k8s社区yum源
bash
$ vi/etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/repodata/repomd.xml.key
# exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni集群软件安装
所有节点均可以安装
bash
# 默认安装
$ yum install -y kubelet kubeadm kubectl
# 查看指定版本
$ yum list kubelet.x86_64 --showduplicates | sort -r
$ yum list kubeadm.x86_64 --showduplicates | sort -r
$ yum list kubectl.x86_64 --showduplicates | sort -r
# 安装指定版本
$ yum install -y kubelet-1.29.0-150500.1.1 kubeadm-1.29.0-150500.1.1 kubectl-1.29.0-150500.1.1配置kubelet
为了实线docker使用的cgroupdriver与kubelet使用的cgroup的一致性,建议修改如下内容
bash
$ vi /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"高版本,对于DEB类包管理系统位置可能在
/etc/default/kubelet
设置kubectl为开启自启即可,这里还没有生成配置文件,待集群初始化后再启动
bash
$ systemctl enable kubelet集群镜像准备
bash
$ kubeadm config images list
$ kubeadm config images list --kubernetes-version=v1.29.0
registry.k8s.io/kube-apiserver:v1.29.0
registry.k8s.io/kube-controller-manager:v1.29.0
registry.k8s.io/kube-scheduler:v1.29.0
registry.k8s.io/kube-proxy:v1.29.0
registry.k8s.io/pause:3.9
registry.k8s.io/etcd:3.5.10-0
registry.k8s.io/coredns/coredns:v1.11.1
# 下载镜像
$ kubeadm config images pull
# 如果是其他容器运行时 或 有多个容器运行时 时需要指定socket
$ kubeadm config images pull --cri-socket unix:///var/run/cri-dockerd.sock
# 指定源
$ kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers集群初始化
导出默认配置文件【这里作为记录,和下面的kubeadm init是两种方式】
bash$ kubeadm config print init-defaults > kubeadm-config.yaml $ vi kubeadm-config.yaml # 调整: # localAPIEndpoint: # advertiseAddress: master1节点IP # bindPort: 6443 # nodeRegistration: # criSocket: 容器运行时socket # name: master1节点名称 # taints: 是否增加污点,不增加忽略即可 # imageRepository: 仓库地址 # kubernetesVersion: k8s版本 # networking # dnsDomain: 默认的域名 # serviceSubnet: 10.96.0.0/12 默认的 # podSubnet: Pod所在网段,10.244.0.0/16 # cgroupDriver: systemd初始化
bash$ kubeadm init \ --config kubeadm-config.yaml \ --upload-certs \ --v=9建议
bash$ kubeadm init \ --config kubeadm-config.yaml \ --upload-certs
--config:这个参数指定了一个配置文件,该文件包含了kubeadm init所需的所有配置信息。这个文件可以定义 API 服务器的地址、Pod 网络插件的配置、使用的镜像仓库等。使用配置文件可以确保每次初始化集群时都使用相同的配置,从而更容易地复制和管理集群。
--upload-certs:这个参数告诉kubeadm在初始化过程中生成的证书将被上传到kubeadm-certsSecret 中,在集群的kube-system命名空间中。这允许在之后加入控制平面节点或工作节点时,自动下载并使用这些证书,而无需手动复制它们。这是一个方便的选项,因为它简化了添加新节点到集群的过程。
--v=9:这个参数设置了日志的详细级别。v=9表示非常详细的日志输出,包括大量的调试信息。这对于诊断问题或了解kubeadm在初始化过程中执行的具体操作非常有用。然而,在日常使用中,你可能不需要这么详细的日志,因为它会产生大量的输出。
containerd可忽略--cri-socket
bash
$ kubeadm init \
--kubernetes-version=v1.29.0 \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=192.168.10.160ontainerd写上--cri-socket
bash
$ kubeadm init \
--kubernetes-version=v1.29.0 \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=192.168.10.160 \
--cri-socket unix:///var/run/containerd/containerd.sock使用docker作为容器运行时,写上--cri-socket
bash
$ kubeadm init \
--kubernetes-version=v1.29.0 \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=192.168.10.160 \
--cri-socket unix:///var/run/cri-dockerd.sock
--pod-network-cidr=10.244.0.0/16:方便在部署网络插件的时候的网段与这里保持一致
其他参考
bash
$ kubeadm init \
--apiserver-advertise-address=192.168.10.160 \
--apiserver-bind-port=6443 \
--kubernetes-version=v1.29.0 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=192.168.3.0/24 \
--service-dns-domain=cluster.local \
--image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers \
--ignore-preflight-errors=swap \
--cri-socket=unix:///var/run/cri-dockerd.sock
--apiserver-advertise-address:这个参数指定了 Kubernetes API 服务器的地址,即 API 服务器对外暴露的地址。这个地址应该是集群中所有节点都能访问到的地址,通常是一个公网 IP 或者内网中的某个节点的 IP。
--apiserver-bind-port:这个参数指定了 Kubernetes API 服务器的绑定端口,默认是 6443。这个端口用于 API 服务器的内部通信和外部访问。
--kubernetes-version:这个参数指定了要安装的 Kubernetes 的版本,这里是 v1.29.0。请确保选择的版本与你的操作系统和其他组件兼容。
--pod-network-cidr:这个参数指定了 Pod 网络的 CIDR 范围。在 Kubernetes 集群中,Pod 之间的通信需要通过 Pod 网络进行,而这个参数就是用来定义 Pod 网络的 IP 地址范围。【注意此项需要与网络插件内的地址一致】
--service-cidr:这个参数指定了 Service 网络的 CIDR 范围。Service 是 Kubernetes 中的一个抽象,它定义了一个逻辑集合的 Pods 以及访问这些 Pods 的策略。这个范围用于分配 Service 的虚拟 IP 地址。
--service-dns-domain:这个参数指定了集群内 DNS 服务的域名后缀。Kubernetes 集群中的 Service 可以通过<service-name>.<namespace>.svc.<cluster-domain>的形式进行 DNS 解析。
--image-repository:这个参数指定了拉取 Kubernetes 镜像时使用的镜像仓库地址。由于 Google 的官方镜像仓库可能在国内访问较慢或不稳定,这里使用了阿里云提供的镜像仓库。
--ignore-preflight-errors:这个参数用于忽略初始化前的检查错误,忽略关于 swap 分区(交换空间)的检查。默认情况下,kubeadm会检查系统中是否启用了 swap,因为 Kubernetes 推荐禁用 swap 以提高集群的稳定性。如果确定需要启用 swap,可以使用这个参数来忽略这个检查。
--cri-socket:这个参数指定了容器运行时的 socket 路径。在 Kubernetes 中,容器运行时负责容器的创建和管理。请注意,从 Kubernetes 1.20 开始,kubeadm默认使用 containerd 作为容器运行时,因此如果使用的是 containerd不需要设置这个参数
输出样例
bash
...
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.10.160:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:abcdefghijklmnopqrstuvwxyz12345678901234567891234567891234567890参见输出内容,执行如下脚本,准备配置文件,有配置文件kubectl才能访问到k8s集群
bash
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config此时使用以下命令,就能看到节点了
bash
$ kubectl get nodes此时是NotReady的状态,部署网络插件后就会Ready
添加节点
添加Master节点
同步证书等
bash
$ scp -r /etc/kubernetes/pki/ root@master2:/etc/kubernetes/
$ scp -r /etc/kubernetes/pki/ root@master3:/etc/kubernetes/删除不需要的证书密钥
bash
$ cd /etc/kubernetes/pki/
$ rm -rf apiserver*
$ rm -rf etcd/peer.*
$ rm -rf etcd/server.*使用containerd容器运行时可以不指定socket
bash
$ kubeadm join 192.168.10.160:6443 \
--token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:abcdefghijklmnopqrstuvwxyz12345678901234567891234567891234567890 \
--control-plane使用非containerd容器运行时需要指定容器运行时的socket
bash
$ kubeadm join 192.168.10.160:6443 \
--token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:abcdefghijklmnopqrstuvwxyz12345678901234567891234567891234567890 \
--control-plane \
--cri-socket unix:///var/run/cri-dockerd.sock低一点的版本可能需要增加
--certificate-key配置,如果需要且初始化的时候没有输出/没有记录,可以考虑重新生成$ kubeadm join 192.168.10.160:6443 \ --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:abcdefghijklmnopqrstuvwxyz12345678901234567891234567891234567890 \ --control-plane \ --certificate-key 107397fb9f4b5ee3c6b2656282ced2b9846cff21738a89e29a9ef04a3c50652b \
添加Worker节点
使用containerd容器运行时可以不指定socket
bash
$ kubeadm join 192.168.10.160:6443 \
--token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:abcdefghijklmnopqrstuvwxyz12345678901234567891234567891234567890使用非containerd容器运行时需要指定容器运行时的socket
bash
$ kubeadm join 192.168.10.160:6443 \
--token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:abcdefghijklmnopqrstuvwxyz12345678901234567891234567891234567890 \
--cri-socket unix:///var/run/cri-dockerd.sock部署网络插件
calico
k8s节点超过10个推荐使用
Calico · GitHub:https://github.com/projectcalico/calico
Kubernetes 上的 Calico:https://docs.tigera.io/calico/latest/getting-started/kubernetes/quickstart
安装
bash
$ kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/tigera-operator.yaml查看是否成功
bash
$ kubectl get pods -n tigera-operator配置calico
bash
$ kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/custom-resources.yaml注意这个配置不要直接使用,调整custom-resources.yaml资源清单的
spec.calicoNetwork.blockSize.cidr与初始化时指定的--pod-network-cidr一致即可
yaml
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
calicoNetwork:
ipPools:
- blockSize: 26
cidr: 10.244.0.0/16
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()
---
apiVersion: operator.tigera.io/v1
kind: APIServer
metadata:
name: default
spec: {}bash
$ kubectl create -f custom-resources.yaml成功后会创建新的命名空间calico-system,相关容器运行好了之后,查看节点就正常了
bash
$ kubectl get nodes
$ kubectl get cs
$ kubectl get svc -n kube-system
# 根据查询的dns ip尝试域名解析
$ dig -t a www.baidu.com @xxx.xxx.xxx.xxxFlannel
Flannel · GitHub:https://github.com/flannel-io/flannel
适合小规模的k8s集群
安装
bash
$ kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml建议:
下载
bash$ wget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml调整ConfigMap:kube-flannel-cfg的net-conf.json的配置
jsonnet-conf.json: | { "Network": "10.244.0.0/16", "EnableNFTables": false, "Backend": { "Type": "vxlan" } }Network调整成初始化时指定的
--pod-network-cidr的值即可在应用
bash$ kubectl apply -f kube-flannel.yml
删除时网卡还在可以在每个节点:
bash
$ ip link delete flannel.1查看
bash
$ ip link show查看网络类型
bash
$ ethtool -i flannel.1Cilium
Cilium · GitHub:https://github.com/cilium/cilium
多集群推荐,需要关注他对系统的要求、内核的要求等:系统要求 · Cilium 1.16.1