推荐
系统支持:centos7.6以上 ubuntu16.04以上 内核推荐4.14以上
推荐配置:centos7.7
环境信息

主机名 IP地址
s201 192.168.231.201
s202 192.168.231.202
s203 192.168.231.203

image.png

1、初始化安装 k8s 集群的实验环境

vi /etc/sysconfig/network-scripts/ifcfg-ens33

  1. TYPE=Ethernet
  2. PROXY_METHOD=none
  3. BROWSER_ONLY=no
  4. BOOTPROTO=static
  5. DEFROUTE=yes
  6. IPV4_FAILURE_FATAL=no
  7. IPV6INIT=yes
  8. IPV6_AUTOCONF=yes
  9. IPV6_DEFROUTE=yes
  10. IPV6_FAILURE_FATAL=no
  11. IPV6_ADDR_GEN_MODE=stable-privacy
  12. NAME=ens33
  13. UUID=7ab7d641-c2cb-4ba6-9d07-daba5a1f8c76
  14. DEVICE=ens33
  15. ONBOOT=yes
  16. IPADDR=192.168.231.201
  17. NETMASK=255.255.255.0
  18. GATEWAY=192.168.231.2

修改配置文件之后需要重启网络服务才能使配置生效,重启网络服务命令如下:
service network restart

2、配置主机名

在 192.168.231.201 上执行如下:
hostnamectl set-hostname s201 && bash
在 192.168.231.202 上执行如下:
hostnamectl set-hostname s202 && bash
在 192.168.231.203 上执行如下:
hostnamectl set-hostname s202 && bash

3、配置主机 hosts 文件,相互之间通过主机名互相访问修

改每台机器的/etc/hosts 文件,增加如下三行:

192.168.231.201 s201
192.168.231.202 s202
192.168.231.202 s203

4、配置主机之间无密码登录

ssh-keygen #一路回车,不输入密码把
本地生成的密钥文件和私钥文件拷贝到远程主机

ssh-copy-id s202
ssh-copy-id s203

5、闭交换分区 swap,提升性能[ s202 s203]

临时关闭
[root@s201 ~]# swapoff -a
#永久关闭:注释 swap 挂载,给 swap 这行开头加一下注释
[root@s201 ~]# vim/etc/fstab
#/dev/mapper/centos-swap swap swap defaults 0 0
问题 1:为什么要关闭 swap 交换分区?
Swap 是交换分区,如果机器内存不够,会使用 swap 分区,但是 swap 分区的性能较低,k8s 设计的时候为了能提升性能,默认是不允许使用交换分区的。Kubeadm 初始化的时候会检测 swap 是否关 闭,如果没关闭,那就初始化失败。如果不想要关闭交换分区,安装 k8s 的时候可以指定—ignore- preflight-errors=Swap 来解决。

6、修改机器内核参数

[root@s201 ~]# modprobe br_netfilter
[root@s201 ~]# 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 
[root@s201 ~]# 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
sysctl -p /etc/sysctl.d/k8s.conf 出现报错:
sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: No such file or directory
sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory
解决方法:
modprobe br_netfilter

问题 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
解决办法:
vim /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

问题 4:为什么要开启 net.ipv4.ip_forward = 1 参数?
kubeadm 初始化 k8s 如果报错:
image.png
就表示没有开启 ip_forward,需要开启。
net.ipv4.ip_forward 是数据包转发:
出于安全考虑,Linux系统默认是禁止数据包转发的。所谓转发即当主机拥有多于一块的网卡时, 其中一块收到数据包,根据数据包的目的 ip 地址将数据包发往本机另一块网卡,该网卡根据路由表继续发送数据包。这通常是路由器所要实现的功能。
要让 Linux 系统具有路由转发功能,需要配置一个 Linux 的内核参数 net.ipv4.ip_forward。这个参数指定了 Linux 系统当前对路由转发功能的支持情况;其值为 0 时表示禁止进行 IP 转发;如果是 1, 则说明 IP 转发功能已经打开。

7、关闭 firewalld 防火墙(所有机器)

systemctl stop firewalld ; systemctl disable firewalld

8、关闭 selinux (所有机器)

# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
#修改 selinux 配置文件之后,重启机器,selinux 配置才能永久生效
# getenforce
Disabled #显示 Disabled 说明 selinux 已经关闭

9、配置阿里云的 repo 源(所有机器)

配置国内安装 docker 和 containerd 的阿里云的 repo 源

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

10、配置安装 k8s 组件需要的阿里云的 repo 源 (所有机器)

vim /etc/yum.repos.d/kubernetes.repo

[kubernetes] 
name=Kubernetes 
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ 
enabled=1 
gpgcheck=0

scp /etc/yum.repos.d/kubernetes.repo s202:/etc/yum.repos.d/
scp /etc/yum.repos.d/kubernetes.repo s203:/etc/yum.repos.d/

11、配置时间同步(所有机器)

在 s201 上执行如下: 
#安装 ntpdate 命令 
[root@s201 ~]# yum install ntpdate -y 
#跟网络时间做同步 
[root@s201 ~]# ntpdate cn.pool.ntp.org 
#把时间同步做成计划任务
[root@s201 ~]# crontab -e 
* */1 * * * /usr/sbin/ntpdate cn.pool.ntp.org 
#重启 crond 服务 
[root@s201 ~]#service crond restart

12、 开启 ipvs (所有机器)

安装 k8s: 没有在内核加载 ipvs 模块,会自动适用 iptables 做代理,如果开启了 ipvs,那会使用ipvs 做规则
#把 ipvs.modules 上传到 xianchaomaster1 机器的/etc/sysconfig/modules/目录下
[root@s201]# chmod 755 /etc/sysconfig/modules/ipvs.modules && bash
/etc/sysconfig/modules/ipvs.modules && lsmod | grep ip_vs

ip_vs_ftp 13079 0  
nf_nat         26583  1 
ip_vs_ftp ip_vs_sed               12519    0 
ip_vs_nq                12516    0 
ip_vs_sh                12688    0 
ip_vs_dh 12688 0

问题 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 支持服务器健康检查和连接重试等功能

13 安装基础软件包(所有机器)

[root@s201 ~]# 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 ntp libaio-devel wget vim ncurses-devel autoconf automake zlib- devel python-devel epel-release openssh-server socat ipvsadm conntrack ntpdate telnet ipvsadm

14、安装containerd 服务(所有机器)

[root@s201]# yum install containerd -y 
[root@s201]# systemctl start containerd && systemctl enable containerd

创建 Containerd 配置文件(所有机器)

mkdir -p /etc/containerd 
containerd config default > /etc/containerd/config.toml 
#替换配置文件 
[root@s201]# sed -i "s#k8s.gcr.io#registry.cn- hangzhou.aliyuncs.com/google_containers#g" /etc/containerd/config.toml 
[root@s201]# sed -i '/containerd.runtimes.runc.options/a\ \ \ \ \ \ \ \ \ \ \ \ SystemdCgroup = true' /etc/containerd/config.toml 
[root@s201]# sed -i "s#https://registry-1.docker.io#https://registry.cn- hangzhou.aliyuncs.com#g" /etc/containerd/config.toml 
[root@s201 ~]# systemctl restart containerd

15、安装初始化 k8s 需要的软件包(所有机器)

[root@s201 ~]# yum install -y kubelet-1.23.3 kubeadm-1.23.3 kubectl-1.23.3 
[root@s202 ~]# systemctl enable kubelet 
[root@s203]# systemctl status kubelet

上面可以看到 kubelet 状态不是 running 状态,这个是正常的,不用管,等 k8s 组件起来这个kubelet 就正常了。
注:每个软件包的作用
Kubeadm: kubeadm 是一个工具,用来初始化 k8s 集群的
kubelet: 安装在集群所有节点上,用于启动 Pod 的
kubectl: 通过 kubectl 可以部署和管理应用,查看各种资源,创建、删除和更新各种组件

16kubeadm 初始化 k8s 集群

#设置容器运行时 
[root@s201 ~]# crictl config runtime-endpoint /run/containerd/containerd.sock 
[root@s202 ~]# crictl config runtime-endpoint /run/containerd/containerd.sock 
[root@s203 ~]# crictl config runtime-endpoint /run/containerd/containerd.sock 

#使用 kubeadm 初始化 k8s 集群 
[root@s201 ~]# kubeadm config print init-defaults > kubeadm.yaml

根据我们自己的需求修改配置,比如修改imageRepository的值,kube-proxy的模式为ipvs,需
要注意的是由于我们使用的containerd作为运行时,所以在初始化节点的时候需要指定cgroupDriver
为systemd

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.231.201#控制节点的 ip 
  bindPort: 6443 nodeRegistration: 
  criSocket: /run/containerd/containerd.sock  #用 containerd 作为容器运行时 
  imagePullPolicy: IfNotPresent 
  name: s201 #控制节点主机名 
  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.23.3 #k8s 版本networking: 
  dnsDomain: cluster.local 
  podSubnet: 10.244.0.0/16 #指定 pod 网段 
  serviceSubnet: 10.96.0.0/16 #指定 Service 网段scheduler: {} 
--- 
apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration 
mode: ipvs 
--- 
apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration 
cgroupDriver: systemd

基于 kubeadm.yaml 初始化 k8s 集群
[root@s201 ~]# kubeadm init —config=kubeadm.yaml
显示如下,说明安装完成:
image.png
#配置 kubectl 的配置文件 config,相当于对 kubectl 进行授权,这样 kubectl 命令可以使用这个证书对 k8s 集群进行管理
[root@s201~]# mkdir -p $HOME/.kube
[root@s201 ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@s201~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config
[root@s201 ~]# kubectl get nodes
此时集群状态还是NotReady状态,因为没有安装网络插件。

17 扩容 k8s 集群-添加第一个工作节点

在 s201上查看加入节点的命令:
[root@s201~]# kubeadm token create —print-join-command

显示如下:
kubeadm join 192.168.121.201:6443—tokenvulvta.9ns7da3saibv4pg1—— discovery-token-
ca-cert-hash sha256:72a0896e27521244850b8f1c3b600087292c2d10f2565adb56381f1f4ba7057a
把 s202加入 k8s 集群:
[root@s202~]# kubeadmjoin192.168.40.180:6443- tokenvulvta.9ns7da3saibv4pg1
—discovery-token-ca-cert-hash sha256:72a0896e27521244850b8f1c3b600087292c2d10f2565adb56381f1f4ba7057a
image.png
#看到上面说明 s202节点已经加入到集群了,充当工作节点

在 s201上查看集群节点状况:
[root@s201~]# kubectl get nodes

可以对 s202、s203打个标签,显示 work
[root@s202~]# kubectl label nodes xianchaonode1 node-role.kubernetes.io/work=work

[root@s201~]# kubectl get nodes

19 安装 kubernetes 网络组件-Calico

把安装calico需要的镜像calico.tar.gz传到s201和s202 s203节点,手动解
[root@s201~]# ctr images import calico.tar.gz
[root@s202~]# ctr images import calico.tar.gz
[root@s203~]# ctr images import calico.tar.gz
上传calico.yaml到s201上,使用yaml文件安装calico网络插件。
注:在线下载配置文件地址是: https://docs.projectcalico.org/manifests/calico.yaml
[root@s201~]# kubectl apply -f calico.yaml
[root@s201~]# kubectl get pod -n kube-system

再次查看集群状态。
[root@s201~]# kubectl get nodes