- 所有节点执行
[root@localhost ~]# hostnamectl --static set-hostname k8s-master1
[root@localhost ~]# hostnamectl --static set-hostname k8s-master2
[root@localhost ~]# hostnamectl --static set-hostname k8s-master3
[root@localhost ~]# hostnamectl --static set-hostname k8s-worker1
[root@localhost ~]# hostnamectl --static set-hostname k8s-worker2
[root@localhost ~]# hostnamectl --static set-hostname k8s-worker3
- 先配置主机名称解析,在master1节点执行
[root@k8s-master1 ~]# cat >> /etc/hosts <<EOF
192.168.66.62 k8s-master1
192.168.66.63 k8s-master2
192.168.66.64 k8s-master3
192.168.66.65 k8s-worker1
192.168.66.66 k8s-worker2
192.168.66.67 k8s-worker3
EOF
- K8S-master1实现ssh免密登入其他节点
[root@k8s-master1 ~]# ssh-keygen -t rsa
[root@k8s-master1 ~]# ssh-copy-id [email protected]
[root@k8s-master1 ~]# ssh-copy-id [email protected]
[root@k8s-master1 ~]# ssh-copy-id [email protected]
[root@k8s-master1 ~]# ssh-copy-id [email protected]
[root@k8s-master1 ~]# ssh-copy-id [email protected]
[root@k8s-master1 ~]# ssh-copy-id [email protected]
- 传给各节点,实现免密认证
[root@k8s-master1 ~]# for i in 192.168.66.{62..67}; do echo ">>> $i";scp /etc/hosts root@$i:/etc/; done
- 配置K8S-Master1节点通过主机名实现免密登入认证
[root@k8s-master1 ~]# ssh-copy-id root@k8s-master1
[root@k8s-master1 ~]# ssh-copy-id root@k8s-master2
[root@k8s-master1 ~]# ssh-copy-id root@k8s-master3
[root@k8s-master1 ~]# ssh-copy-id root@k8s-worker1
[root@k8s-master1 ~]# ssh-copy-id root@k8s-worker2
[root@k8s-master1 ~]# ssh-copy-id root@k8s-worker3
- 所有节点关闭DNS反向查询,加快SSH连接速度
[root@k8s-master1 ~]# for i in 192.168.66.{62..67}; do echo ">>> $i";ssh root@$i "sed -ri '/#UseDNS yes/a\UseDNS no' /etc/ssh/sshd_config && systemctl restart sshd"; done
[root@k8s-master1 ~]# for i in 192.168.66.{62..67}; do echo ">>> $i";ssh root@$i "grep UseDNS /etc/ssh/sshd_config"; done
-
在所有节点上的
profile
文件的最后都需要添加下面的参数;注意集群IP和主机名更改为自己的服务器地址和主机名 -
定义集群节点变量
[root@k8s-master1 ~]# export master01=192.168.66.62
[root@k8s-master1 ~]# export master02=192.168.66.63
[root@k8s-master1 ~]# export master03=192.168.66.64
[root@k8s-master1 ~]# export worker01=192.168.66.65
[root@k8s-master1 ~]# export worker02=192.168.66.66
[root@k8s-master1 ~]# export worker03=192.168.66.67
[root@k8s-master1 ~]# export etcd01=192.168.66.62
[root@k8s-master1 ~]# export etcd02=192.168.66.63
[root@k8s-master1 ~]# export etcd03=192.168.66.64
- 定义集群环境变量配置
[root@k8s-master1 ~]# cat >> /etc/profile <<EOF
#----------------------------K8S-----------------------------#
# 生成 EncryptionConfig 所需的加密 key
export ENCRYPTION_KEY=\$(head -c 32 /dev/urandom | base64)
#各机器 IP 数组包含Master与Node节点
export NODE_IPS=(${master01} ${master02} ${master03} ${worker01} ${worker02} ${worker03})
#各机器IP 对应的主机名数组包含Master与Node节点
export NODE_NAMES=(k8s-master1 k8s-master2 k8s-master3 k8s-worker1 k8s-worker2 k8s-worker3)
# Master集群节点IP
export MASTER_IPS=(${master01} ${master02} ${master03})
# Master集群IP对应主机名数组
export MASTER_NAMES=(k8s-master1 k8s-master2 k8s-master3)
# WORK集群数组IP
export WORK_IPS=(${worker01} ${worker02} ${worker03})
# WORK集群IP对应主机名数组
export WORK_NAMES=(k8s-worker1 k8s-worker2 k8s-worker3)
#ETCD集群IP数组
export ETCD_IPS=(${etcd01} ${etcd02} ${etcd03})
# ETCD集群节点IP对应主机名数组
export ETCD_NAMES=(k8s-master1 k8s-master2 k8s-master3)
# etcd 集群服务地址列表;注意IP地址根据自己的ETCD集群服务器地址填写
export ETCD_ENDPOINTS="https://${etcd01}:2379,https://${etcd02}:2379,https://${etcd03}:2379"
# etcd 集群间通信的 IP 和端口;注意此处改为自己的实际ETCD所在服务器主机名
export ETCD_NODES="k8s-master1=https://${etcd01}:2380,k8s-master2=https://${etcd02}:2380,k8s-master3=https://${etcd03}:2380"
# kube-apiserver 的反向代理(kube-nginx)地址端口
export KUBE_APISERVER="https://127.0.0.1:8443"
# 节点间互联网络接口名称;根据自己服务器网卡实际名称进行修改
export IFACE="ens33"
# etcd 数据目录
export ETCD_DATA_DIR="/data/k8s/etcd/data"
# etcd WAL 目录,建议是 SSD 磁盘分区,或者和 ETCD_DATA_DIR 不同的磁盘分区
export ETCD_WAL_DIR="/data/k8s/etcd/wal"
# k8s 各组件数据目录
export K8S_DIR="/data/k8s/k8s"
## DOCKER_DIR 和 CONTAINERD_DIR 二选一
# docker 数据目录
export DOCKER_DIR="/data/k8s/docker"
# containerd 数据目录
export CONTAINERD_DIR="/data/k8s/containerd"
## 以下参数一般不需要修改
# TLS Bootstrapping 使用的 Token,可以使用命令 head -c 16 /dev/urandom | od -An -t x | tr -d ' ' 生成
export BOOTSTRAP_TOKEN="41f7e4ba8b7be874fcff18bf5cf41a7c"
# 最好使用 当前未用的网段 来定义服务网段和 Pod 网段
# 服务网段,部署前路由不可达,部署后集群内路由可达(kube-proxy 保证)
export SERVICE_CIDR="10.254.0.0/16"
# Pod 网段,建议 /16 段地址,部署前路由不可达,部署后集群内路由可达(flanneld 保证)
export CLUSTER_CIDR="10.68.0.0/16"
# 服务端口范围 (NodePort Range),默认范围是30000-32767
export NODE_PORT_RANGE="30000-32767"
# kubernetes 服务 IP (一般是 SERVICE_CIDR 中第一个IP)
export CLUSTER_KUBERNETES_SVC_IP="10.254.0.1"
# 集群 DNS 服务 IP (从 SERVICE_CIDR 中预分配)
export CLUSTER_DNS_SVC_IP="10.254.0.2"
# 集群 DNS 域名(末尾不带点号)
export CLUSTER_DNS_DOMAIN="cluster.local"
# 将二进制目录 /opt/k8s/bin 加到 PATH 中
export PATH=/opt/k8s/bin:\$PATH
EOF
- 将配置传给各Master集群节点和ETCD集群和worker节点服务器
[root@k8s-master1 ~]# source /etc/profile
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo $i;scp /etc/profile root@$i:/etc/;done
- 环境变量生效
[root@k8s-master1 ~]# source /etc/profile
for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "source /etc/profile";done
- 所有节点执行
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]}; do echo ">>> $i";ssh root@$i "systemctl stop firewalld && systemctl disable firewalld && systemctl status firewalld"; done
- 所有节点执行
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]}; do echo ">>> $i";ssh root@$i "sed -ri 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config"; done
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]}; do echo ">>> $i";ssh root@$i "setenforce 0 && getenforce"; done
注意 :
(1)许多 Linux 发行版都包含 NetworkManager。 默认情况下,NetworkManager 不允许 Calico 管理接口。所以需要禁用
(2)NetworkManager启动会导致已经修改了 /etc/resolv.conf 的配置重启网卡或者服务器恢复至默认的
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]}; do echo ">>> $i";ssh root@$i "systemctl stop NetworkManager && systemctl disable NetworkManager && systemctl status NetworkManager"; done
- 所有节点执行,使用ipvs实现负载
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "yum install -y epel-release";done
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "yum install -y chrony conntrack ipvsadm ipset jq iptables curl sysstat libseccomp wget socat git";done
- master1节点去同步互联网时间,其他节点与master1节点进行时间同步
[root@k8s-master1 ~]# vim /etc/chrony.conf
allow 192.168.66.0/24
[root@k8s-master1 ~]# ntpd -gq
[root@k8s-master1 ~]# systemctl restart chronyd.service
[root@k8s-master1 ~]# systemctl enable chronyd.service
[root@k8s-master1 ~]# systemctl status chronyd.service
- 其他节点修改chrony服务配置,同步master1时钟
vim /etc/chrony.conf
server 192.168.66.62 iburst
- 启动服务
[root@k8s-master1 ~]# for i in 192.168.66.{63..67};do echo ">>> $i";ssh root@$i "systemctl restart chronyd.service && systemctl enable chronyd.service && systemctl status chronyd.service";done
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "swapoff -a && free -h|grep Swap";done
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "sed -ri 's@/dev/mapper/centos-swap@#/dev/mapper/centos-swap@g' /etc/fstab && grep /dev/mapper/centos-swap /etc/fstab";done
- 必须关闭 tcp_tw_recycle,否则和 NAT 冲突,会导致服务不通;关闭 IPV6,防止触发 docker BUG;
- 注意: 我这里内核使用5.10,所以tcp_tw_recycle参数在linux内核4.12版本之后已经移除了tcp_tw_recycle参数;如果你还是使用3.10的内核那么就必须关闭该参数;3.10内核的话,在下面的配置文件中添加参数:net.ipv4.tcp_tw_recycle=0
- 注意: ip_forward必须要打开,不打开的话有可能会出现跨主机不通的情况
[root@k8s-master1 ~]# cat > /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
net.ipv4.neigh.default.gc_thresh1=1024
net.ipv4.neigh.default.gc_thresh2=2048
net.ipv4.neigh.default.gc_thresh3=4096
vm.swappiness=0
vm.overcommit_memory=1
vm.panic_on_oom=0
vm.max_map_count=262144
fs.inotify.max_user_instances=8192
fs.inotify.max_user_watches=1048576
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=1048576
net.nf_conntrack_max=1048576
net.ipv4.tcp_max_syn_backlog=8096
net.core.netdev_max_backlog=10000
net.core.somaxconn=32768
kernel.pid_max=4194304
EOF
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "modprobe ip_conntrack && modprobe br_netfilter && sysctl -p /etc/sysctl.d/kubernetes.conf && sysctl -p /etc/sysctl.conf";done
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "echo 'PATH=/opt/k8s/bin:$PATH' >>/root/.bashrc && source /root/.bashrc";done
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "mkdir -p /opt/k8s/{bin,work} /etc/{kubernetes,etcd}/cert && ls /opt/k8s/";done
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "systemctl stop postfix && systemctl disable postfix";done
CentOS 7.x 系统自带的 3.10.x 内核存在一些 Bugs,导致运行的 Docker、Kubernetes 不稳定
1、 高版本的 docker(1.13 以后) 启用了 3.10 kernel 实验支持的 kernel memory account 功能(无法关闭),当节点压力大如频繁启动和停止容器时会导致 cgroup memory leak
2、 网络设备引用计数泄漏,会导致类似于报错:"kernel:unregister_netdevice: waiting for eth0 to become free. Usage count = 1"
3、 kernel v5.9以下版本会出现内核 ipvs 连接复用引发导致持续丢包
# 载入公钥,安装eprepo源
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org";done
# 接着,按照你的系统版本,如果是RHEL-7, SL-7 或者 CentOS-7运行下面命令
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "yum -y install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm";done
# 安装主线最新版本(v5.9+版本修复了ipvs连接复用导致性能的问题)
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "yum install --enablerepo=elrepo-kernel -y kernel-ml kernel-ml-headers kernel-ml-doc kernel-ml-devel kernel-ml-tools kernel-ml-tools-libs kernel-ml-tools-libs-devel";done
#查看当前使用的内核版本
[root@k8s-master1 ~]# grub2-editenv list
#查看当前可用的内核版本
[root@k8s-master1 ~]# awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
#所有节点设置启动新内核
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "grub2-set-default 0";done
#运行grub2-mkconfig命令来重新创建内核配置
[root@k8s-master1 ~]# for i in ${NODE_IPS[@]};do echo ">>> $i";ssh root@$i "grub2-mkconfig -o /boot/grub2/grub.cfg";done
reboot