1. 程式人生 > 其它 >Kubeadm搭建高可用(k8s)Kubernetes v1.24.0叢集

Kubeadm搭建高可用(k8s)Kubernetes v1.24.0叢集

文章轉載自:https://i4t.com/5451.html

背景

Kubernetes 1.24新特性

從kubelet中移除dockershim,自1.20版本被棄用之後,dockershim元件終於在1.24的kubelet中被刪除。從1.24開始,大家需要使用其他受到支援的執行時選項(例如containerd或CRI-O);如果您選擇Docker Engine作為執行時,則需要使用cri-dockerd。

對於kubelet和containerd重要提示

在升級至1.24之前,請確認containerd版本

#以下容器執行時已經或即將全面相容Kubernetes 1.24:
containerd v1.6.4及更高,v1.5.11及更高
CRI-O 1.24及更高

若CNI外掛尚未升級且/或CNI配置檔案中未宣告CNI配置版本時,則containerd v1.6.0-v1.6.3版本將導致Pod CNI網路setup及tear down發生問題。containerd團隊報告稱,這些問題已經在containerd v1.6.4中得到解決。
在containerd v1.6.0-v1.6.3時,如果你未升級CNI外掛且/或宣告CNI配置版本,則可能遇到CNI版本不相容或無法為沙箱刪除網路等錯誤。

Kubernetes 1.24新特性

  • 各beta API預設關閉
    在預設情況下,新的各beta API不會在叢集內得到啟用。但全部原有beta API及其新版本將在1.24中繼續預設啟用

  • OpenAPI v3
    Kubernetes 1.24開始為API的OpenAPI v3釋出格式提供beta支援。

  • 儲存容量與儲存卷擴充套件雙雙迎來通用版本
    儲存容量跟蹤通過CSIStorageCapacity物件公開當前可用的儲存容量,並對使用後續繫結的CSI儲存卷的pod進行排程增強。
    儲存卷擴充套件則新增對現有持久卷的重新調整功能。

  • NonPreemptingPriority迎來穩定版
    此功能為PriorityClasses添加了新的選項,可開啟或關閉Pod搶佔機制

  • 儲存外掛遷移
    目前Kubernetes開發團隊正在遷移樹記憶體儲外掛,希望在實現CSI外掛的同時、保持原有API的正常起效。Azure Disk與OpenStack Cinder等外掛已經完成了遷移。

  • gRPC探針升級至beta版
    在1.24版本中,gRPC探針功能已經進入beta階段且預設啟用。現在,大家可以在Kubernetes中為自己的gRPC應用程式原生配置啟動、活動與就緒探測,而且無需公開HTTP商戰或者使用額外的可執行檔案。

  • Kubelet證書提供程序升級至beta版
    最初在Kubernetes 1.20版本中以alpha版亮相的kubelet映象證書提供程式現已升級至beta版。現在,kubelet將使用exec外掛動態檢索容器映象登錄檔的憑證,而不再將憑證儲存在節點檔案系統之上。

  • 避免為服務分配IP時發生衝突
    Kubernetes 1.24引入了一項新的選擇性功能,允許使用者為服務的靜態IP分配地址保留一個軟範圍。通過手動啟用此項功能,叢集將從您指定的服務IP池中自動獲取地址,從而降低衝突風險。

也就是說,服務的ClusterIP能夠以下列方式分配:
動態分配,即叢集將在配置的服務IP範圍內自動選擇一個空閒IP。
靜態分配,意味著使用者需要在已配置的服務IP範圍內指定一個IP。

服務ClusterIP是唯一的;因此若嘗試使用已被分配的ClusterIP進行服務建立,則會返回錯誤結果。

環境準備

本地已有kubernetes 1.18環境,接下來對環境進行初始化

#目前kubernetes版本
[root@k8s-01 ~]# kubectl  get node
NAME     STATUS   ROLES    AGE    VERSION
k8s-01   Ready    master   243d   v1.18.3
k8s-02   Ready    master   243d   v1.18.3
k8s-03   Ready    master   243d   v1.18.3
k8s-04   Ready    <none>   243d   v1.18.3
k8s-05   Ready    <none>   243d   v1.18.3

解除安裝叢集命令

#建議所有伺服器都執行
#!/bin/bash
kubeadm reset -f
modprobe -r ipip
lsmod
rm -rf ~/.kube/
rm -rf /etc/kubernetes/
rm -rf /etc/systemd/system/kubelet.service.d
rm -rf /etc/systemd/system/kubelet.service
rm -rf /usr/bin/kube*
rm -rf /etc/cni
rm -rf /opt/cni
rm -rf /var/lib/etcd
rm -rf /var/etcd
yum -y remove kubeadm* kubectl* kubelet* docker*
reboot

基礎環境配置

VIP: 192.168.31.111
域名: apiserver.frps.cn

  • apiserver.frps.cn:6443 為VIP
  • kube-apiserver 三臺節點
  • kube-schedulet 三臺節點
  • kube-controller-manager 三臺節點
  • ETCD 三臺節點

服務版本

初始化環境

初始化環境需要全部節點都執行

批量修改主機名,以及免密

hostnamectl set-hostname k8s01  #所有機器按照要求修改
bash        #重新整理主機名
#配置host
cat >> /etc/hosts <<EOF
192.168.31.100  k8s-01
192.168.31.101  k8s-02
192.168.31.102  k8s-03
192.168.31.103  k8s-04
192.168.31.104  k8s-05
EOF
#設定k8s-01為分發機 (只需要在k8s-01伺服器操作即可)
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum install -y expect
#分發公鑰
ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa
for i in k8s-01 k8s-02 k8s-03 k8s-04 k8s-05;do
expect -c "
spawn ssh-copy-id -i /root/.ssh/id_rsa.pub root@$i
        expect {
                "*yes/no*" {send "yesr"; exp_continue}
                "*password*" {send "123456r"; exp_continue}
                "*Password*" {send "123456r";}
        } "
done 

我這裡密碼為123456,請根據需求自行更改

所有節點關閉Selinux、iptables、swap分割槽

systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat
iptables -P FORWARD ACCEPT
swapoff -a
sed -i '/ swap / s/^(.*)$/#1/g' /etc/fstab
setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

所有節點配置yum源

curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum clean all
yum makecache

新安裝的伺服器可以安裝下面的軟體包,可以解決99%的依賴問題

yum -y install gcc gcc-c++ make autoconf libtool-ltdl-devel gd-devel freetype-devel libxml2-devel libjpeg-devel libpng-devel openssh-clients openssl-devel curl-devel bison patch libmcrypt-devel libmhash-devel ncurses-devel binutils compat-libstdc++-33 elfutils-libelf elfutils-libelf-devel glibc glibc-common glibc-devel libgcj libtiff pam-devel libicu libicu-devel gettext-devel libaio-devel libaio libgcc libstdc++ libstdc++-devel unixODBC unixODBC-devel numactl-devel glibc-headers sudo bzip2 mlocate flex lrzsz sysstat lsof setuptool system-config-network-tui system-config-firewall-tui ntsysv ntp pv lz4 dos2unix unix2dos rsync dstat iotop innotop mytop telnet iftop expect cmake nc gnuplot screen xorg-x11-utils xorg-x11-xinit rdate bc expat-devel compat-expat1 tcpdump sysstat man nmap curl lrzsz elinks finger bind-utils traceroute mtr ntpdate zip unzip vim wget net-tools

由於開啟核心 ipv4 轉發需要載入 br_netfilter 模組,所以載入下該模組:

#每臺節點
modprobe br_netfilter
modprobe ip_conntrack

將上面的命令設定成開機啟動,因為重啟後模組失效,下面是開機自動載入模組的方式。首先新建 /etc/rc.sysinit 檔案,內容如下所示:

cat >>/etc/rc.sysinit<<EOF
#!/bin/bash
for file in /etc/sysconfig/modules/*.modules ; do
[ -x $file ] && $file
done
EOF

然後在/etc/sysconfig/modules/目錄下新建如下檔案:

echo "modprobe br_netfilter" >/etc/sysconfig/modules/br_netfilter.modules
echo "modprobe ip_conntrack" >/etc/sysconfig/modules/ip_conntrack.modules

增加許可權

chmod 755 /etc/sysconfig/modules/br_netfilter.modules
chmod 755 /etc/sysconfig/modules/ip_conntrack.modules

然後重啟後,模組就可以自動載入了

優化核心引數

cat > kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
vm.swappiness=0 # 禁止使用 swap 空間,只有當系統 OOM 時才允許使用它
vm.overcommit_memory=1 # 不檢查實體記憶體是否夠用
vm.panic_on_oom=0 # 開啟 OOM
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=2310720
EOF
cp kubernetes.conf  /etc/sysctl.d/kubernetes.conf
sysctl -p /etc/sysctl.d/kubernetes.conf
#分發到所有節點
for i in k8s-02 k8s-03 k8s-04 k8s-05
do
    scp kubernetes.conf root@$i:/etc/sysctl.d/
    ssh root@$i sysctl -p /etc/sysctl.d/kubernetes.conf
    ssh root@$i echo '1' >> /proc/sys/net/ipv4/ip_forward
done
#for後面節點根據需求修改

bridge-nf 使得netfilter可以對Linux網橋上的 IPv4/ARP/IPv6 包過濾。比如,設定net.bridge.bridge-nf-call-iptables=1後,二層的網橋在轉發包時也會被 iptables的 FORWARD 規則所過濾。常用的選項包括:
- net.bridge.bridge-nf-call-arptables:是否在 arptables 的 FORWARD 中過濾網橋的 ARP 包
- net.bridge.bridge-nf-call-ip6tables:是否在 ip6tables 鏈中過濾 IPv6 包
- net.bridge.bridge-nf-call-iptables:是否在 iptables 鏈中過濾 IPv4 包
- net.bridge.bridge-nf-filter-vlan-tagged:是否在 iptables/arptables 中過濾打了 vlan 標籤的包。

所有節點安裝ipvs

為什麼要使用IPVS,從k8s的1.8版本開始,kube-proxy引入了IPVS模式,IPVS模式與iptables同樣基於Netfilter,但是採用的hash表,因此當service數量達到一定規模時,hash查表的速度優勢就會顯現出來,從而提高service的服務效能。
ipvs依賴於nf_conntrack_ipv4核心模組,4.19包括之後核心裡改名為nf_conntrack,1.13.1之前的kube-proxy的程式碼裡沒有加判斷一直用的nf_conntrack_ipv4,好像是1.13.1後的kube-proxy程式碼裡增加了判斷,我測試了是會去load nf_conntrack使用ipvs正常
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

chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack
#檢視是否已經正確載入所需的核心模組

所有節點安裝ipset

yum install ipset -y

ipset介紹
iptables是Linux伺服器上進行網路隔離的核心技術,核心在處理網路請求時會對iptables中的策略進行逐條解析,因此當策略較多時效率較低;而是用IPSet技術可以將策略中的五元組(協議,源地址,源埠,目的地址,目的埠)合併到有限的集合中,可以大大減少iptables策略條目從而提高效率。測試結果顯示IPSet方式效率將比iptables提高100倍

為了方面ipvs管理,這裡安裝一下ipvsadm。

yum install ipvsadm -y

所有節點設定系統時區

timedatectl set-timezone Asia/Shanghai
 #將當前的 UTC 時間寫入硬體時鐘
timedatectl set-local-rtc 0
 #重啟依賴於系統時間的服務
systemctl restart rsyslog 
systemctl restart crond

升級核心 (可選方案)

rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
#預設安裝為最新核心
yum --enablerepo=elrepo-kernel install kernel-ml
#修改核心順序
grub2-set-default  0 && grub2-mkconfig -o /etc/grub2.cfg
#使用下面命令看看確認下是否啟動預設核心指向上面安裝的核心
grubby --default-kernel
#這裡的輸出結果應該為我們升級後的核心資訊
reboot
#可以等所有初始化步驟結束進行reboot操作

接下來更新一下軟體包版本

yum update -y

Containerd 安裝

在安裝containerd前,我們需要優先升級libseccomp,在centos7中yum下載libseccomp的版本是2.3的,版本不滿足我們最新containerd的需求,需要下載2.4以上的

Containerd需要在所有節點升級安裝

#解除安裝原來的
[i4t@web01 ~]# rpm -qa | grep libseccomp
libseccomp-devel-2.3.1-4.el7.x86_64
libseccomp-2.3.1-4.el7.x86_64
[i4t@web01 ~]# rpm -e libseccomp-devel-2.3.1-4.el7.x86_64 --nodeps
[i4t@web01 ~]# rpm -e libseccomp-2.3.1-4.el7.x86_64 --nodeps
#下載高於2.4以上的包
[i4t@web01 ~]# wget http://rpmfind.net/linux/centos/8-stream/BaseOS/x86_64/os/Packages/libseccomp-2.5.1-1.el8.x86_64.rpm
#安裝
[i4t@web01 ~]# rpm -ivh libseccomp-2.5.1-1.el8.x86_64.rpm 
warning: libseccomp-2.5.1-1.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 8483c65d: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:libseccomp-2.5.1-1.el8           ################################# [100%]
#檢視當前版本
[root@web01 ~]# rpm -qa | grep libseccomp
libseccomp-2.5.1-1.el8.x86_64

下載安裝containerd

github地址:https://containerd.io/downloads/

Containerd安裝我們使用1.6.1版本號

containerd-1.6.1-linux-amd64.tar.gz 只包含containerd
cri-containerd-cni-1.6.4-linux-amd64.tar.gz 包含containerd以及cri runc等相關工具包,建議下載本包

#下載tar.gz包
#containerd工具包,包含cri runc等
wget https://github.com/containerd/containerd/releases/download/v1.6.4/cri-containerd-cni-1.6.4-linux-amd64.tar.gz
#備用下載地址
wget https://d.frps.cn/file/kubernetes/containerd/cri-containerd-cni-1.6.4-linux-amd64.tar.gz

工具包檔案如下

#cri-containerd-cni會將我們整個containerd相關的依賴都進行下載下來
[root@k8s-01 containerd]# tar zxvf cri-containerd-cni-1.6.4-linux-amd64.tar.gz -C /   #我們直接讓它給我們對應的目錄給替換掉
etc/
etc/systemd/
etc/systemd/system/
etc/systemd/system/containerd.service
etc/crictl.yaml
etc/cni/
etc/cni/net.d/
etc/cni/net.d/10-containerd-net.conflist
usr/
usr/local/
usr/local/sbin/
usr/local/sbin/runc
usr/local/bin/
usr/local/bin/crictl
usr/local/bin/ctd-decoder
usr/local/bin/ctr
usr/local/bin/containerd-shim
usr/local/bin/containerd
usr/local/bin/containerd-shim-runc-v1
usr/local/bin/critest
usr/local/bin/containerd-shim-runc-v2
usr/local/bin/containerd-stress
opt/
opt/containerd/
opt/containerd/cluster/
opt/containerd/cluster/version
opt/containerd/cluster/gce/
opt/containerd/cluster/gce/cni.template
opt/containerd/cluster/gce/env
opt/containerd/cluster/gce/configure.sh
opt/containerd/cluster/gce/cloud-init/
opt/containerd/cluster/gce/cloud-init/node.yaml
opt/containerd/cluster/gce/cloud-init/master.yaml
opt/cni/
opt/cni/bin/
opt/cni/bin/firewall
opt/cni/bin/portmap
opt/cni/bin/host-local
opt/cni/bin/ipvlan
opt/cni/bin/host-device
opt/cni/bin/sbr
opt/cni/bin/vrf
opt/cni/bin/static
opt/cni/bin/tuning
opt/cni/bin/bridge
opt/cni/bin/macvlan
opt/cni/bin/bandwidth
opt/cni/bin/vlan
opt/cni/bin/dhcp
opt/cni/bin/loopback
opt/cni/bin/ptp

上面的檔案都是二進位制檔案,直接移動到對應的目錄並配置好環境變數就可以進行使用了。

如果我們機器上通過yum安裝docker了,可以用下面的命令進行解除安裝

sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine

接下來我們為每臺伺服器配置Containerd

#建立配置檔案目錄
[root@k8s-01 ~]# mkdir /etc/containerd -p
#生成預設配置檔案
[root@k8s-01 ~]# containerd config default > /etc/containerd/config.toml
#--config,-c可以在啟動守護程式時更改此路徑
#配置檔案的預設路徑位於/etc/containerd/config.toml

替換預設pause映象地址

預設情況下k8s.gcr.io無法訪問,所以使用我提供的阿里雲映象倉庫地址即可

sed -i 's/k8s.gcr.io/registry.cn-beijing.aliyuncs.com/abcdocker/' /etc/containerd/config.toml 
#所有節點更換預設映象地址
#我這裡使用阿里雲地址

配置systemd作為容器的cgroup driver

sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

Containerd官方操作手冊

預設cri-containerd-cni包中會有containerd啟動指令碼,我們已經解壓到對應的目錄,可以直接呼叫啟動

    [root@k8s-01 ~]# systemctl enable containerd --now   
    Created symlink from /etc/systemd/system/multi-user.target.wants/containerd.service to /etc/systemd/system/containerd.service.
    [root@k8s-01 ~]# systemctl status containerd   #檢視containerd啟動狀態
    ● containerd.service - containerd container runtime
       Loaded: loaded (/etc/systemd/system/containerd.service; enabled; vendor preset: disabled)
       Active: active (running) since Thu 2022-05-12 22:59:19 EDT; 3s ago
         Docs: https://containerd.io
      Process: 30048 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
     Main PID: 30050 (containerd)
       Memory: 24.5M
       CGroup: /system.slice/containerd.service
               └─30050 /usr/local/bin/containerd
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.153514446-04:00" level=info msg="Get image filesystem path "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs""
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154085898-04:00" level=info msg="Start subscribing containerd event"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154137039-04:00" level=info msg="Start recovering state"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154230615-04:00" level=info msg="Start event monitor"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154276701-04:00" level=info msg="Start snapshots syncer"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154299287-04:00" level=info msg="Start cni network conf syncer for default"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154316094-04:00" level=info msg="Start streaming server"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154675632-04:00" level=info msg=serving... address=/run/containerd/containerd.sock.ttrpc
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154755704-04:00" level=info msg=serving... address=/run/containerd/containerd.sock
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.155220379-04:00" level=info msg="containerd successfully booted in 0.027654s"

ctr在我們解壓包中已經附帶了,直接可以使用

    [root@k8s-01 ~]# ctr version
    Client:     #ctr版本號
      Version:  v1.6.4
      Revision: 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16
      Go version: go1.17.9
    Server:
      Version:  v1.6.4     #containerd版本號
      Revision: 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16
      UUID: b376d7b6-c97e-4b39-8144-9624ade3ba84
    #可以使用下面命令檢視containerd版本號
    [root@k8s-01 ~]# containerd --version
    containerd github.com/containerd/containerd v1.6.4 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16

api-server 高可用部署 (單master可跳過)

nginx代理後端3臺apiserver,所以需要在每臺apiserver中安裝nginx。keeplived起到vip的作用

需要在master節點安裝

#首先我們在原有的基礎上新增一個host,只需要在master節點上執行即可
cat >>/etc/hosts<< EOF
192.168.31.10  k8s-master-01
192.168.31.11  k8s-master-02
192.168.31.12  k8s-master-03
192.168.31.111  apiserver.frps.cn
EOF

安裝nginx

為了方便後面擴充套件外掛,我這裡使用編譯安裝nginx

    #編譯安裝nginx
    #安裝依賴
    yum install pcre pcre-devel openssl openssl-devel gcc gcc-c++ automake autoconf libtool make wget vim lrzsz -y
    wget https://nginx.org/download/nginx-1.20.2.tar.gz
    tar xf nginx-1.20.2.tar.gz
    cd nginx-1.20.2/
    useradd nginx -s /sbin/nologin -M
    ./configure --prefix=/opt/nginx/ --with-pcre --with-http_ssl_module --with-http_stub_status_module --with-stream --with-http_stub_status_module --with-http_gzip_static_module
    make  &&  make install  
    #使用systemctl管理,並設定開機啟動
    cat >/usr/lib/systemd/system/nginx.service<<EOF
    # /usr/lib/systemd/system/nginx.service
    [Unit]
    Description=The nginx HTTP and reverse proxy server
    After=network.target sshd-keygen.service
    [Service]
    Type=forking
    EnvironmentFile=/etc/sysconfig/sshd
    ExecStartPre=/opt/nginx/sbin/nginx -t -c /opt/nginx/conf/nginx.conf
    ExecStart=/opt/nginx/sbin/nginx -c /opt/nginx/conf/nginx.conf
    ExecReload=/opt/nginx/sbin/nginx -s reload
    ExecStop=/opt/nginx/sbin/nginx -s stop
    Restart=on-failure
    RestartSec=42s
    [Install]
    WantedBy=multi-user.target
    EOF
    #開機啟動
    [root@k8s-01 nginx-1.20.2]# systemctl enable nginx --now
    Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
    # yum安裝nginx
    yum install nginx -y
    #yum安裝nginx需要注意下面的配置檔案路徑就是/etc/nginx/conf/nginx.conf

檢查服務是否啟動

[root@k8s-01 nginx-1.20.2]# ps -ef|grep nginx
root      84040      1  0 20:15 ?        00:00:00 nginx: master process /opt/nginx/sbin/nginx -c /opt/nginx/conf/nginx.conf
nobody    84041  84040  0 20:15 ?        00:00:00 nginx: worker process
root      84044  51752  0 20:16 pts/0    00:00:00 grep --color=auto nginx

修改nginx配置檔案

    vim nginx.conf 
    user nginx nginx;
    worker_processes auto;
    events {
        worker_connections  20240;
        use epoll;
    }
    error_log /var/log/nginx_error.log info;
    stream {
        upstream kube-servers {
            hash $remote_addr consistent;
            server k8s-master-01:6443 weight=5 max_fails=1 fail_timeout=3s;  #這裡可以寫IP
            server k8s-master-02:6443 weight=5 max_fails=1 fail_timeout=3s;
            server k8s-master-03:6443 weight=5 max_fails=1 fail_timeout=3s;
        }
        server {
            listen 8443 reuseport;
            proxy_connect_timeout 3s;
            # 加大timeout
            proxy_timeout 3000s;
            proxy_pass kube-servers;
        }
    }
    #分發到其它master節點
    for i in k8s-02 k8s-03
    do
        scp nginx.conf root@$i:/opt/nginx/conf/
        ssh root@$i systemctl restart nginx
    done

配置Keeplived

前面我們也說了,高可用方案需要一個VIP,供叢集內部訪問

yum  install -y keepalived
#在所有master節點安裝

修改配置檔案

  • router_id 節點IP
  • mcast_src_ip 節點IP
  • virtual_ipaddress VIP

請根據自己IP實際上情況修改

    cat > /etc/keepalived/keepalived.conf <<EOF
    ! Configuration File for keepalived
    global_defs {
       router_id 192.168.31.10     #節點ip,master每個節點配置自己的IP
    }
    vrrp_script chk_nginx {
        script "/etc/keepalived/check_port.sh 8443"
        interval 2
        weight -20
    }
    vrrp_instance VI_1 {
        state MASTER
        interface eth0
        virtual_router_id 251
        priority 100
        advert_int 1
        mcast_src_ip 192.168.31.10    #節點IP
        nopreempt
        authentication {
            auth_type PASS
            auth_pass 11111111
        }
        track_script {
             chk_nginx
        }
        virtual_ipaddress {
            192.168.31.111   #VIP
        }
    }
    EOF

    #編寫健康檢查指令碼
    vim  /etc/keepalived/check_port.sh 
    CHK_PORT=$1
     if [ -n "$CHK_PORT" ];then
            PORT_PROCESS=`ss -lt|grep $CHK_PORT|wc -l`
            if [ $PORT_PROCESS -eq 0 ];then
                    echo "Port $CHK_PORT Is Not Used,End."
                    exit 1
            fi
     else
            echo "Check Port Cant Be Empty!"
     fi

啟動keepalived

systemctl enable --now keepalived

測試vip是否正常

ping vip
ping apiserver.frps.cn #我們的域名

Kubeadm 安裝配置

首先我們需要在k8s-01配置kubeadm源

下面kubeadm操作只需要在k8s-01上即可

國內源

packages.cloud.google.com這裡懂的都懂,下面改成阿里雲源

    cat <<EOF > /etc/yum.repos.d/kubernetes.repo
    [kubernetes]
    name=Kubernetes
    baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
    enabled=1
    gpgcheck=0
    repo_gpgcheck=0
    gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
            http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
    EOF

官方文件推薦源

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

k8s-01節點安裝kubeadm和master相關依賴組建

yum install -y kubelet-1.24.0 kubeadm-1.24.0 kubectl-1.24.0 --disableexcludes=kubernetes

將k8s-01節點的kubelet設定成開機啟動:

systemctl enable --now kubelet

配置kubeadm檔案

這裡我們在k8s-01上配置列印init預設配置資訊

kubeadm config print init-defaults >kubeadm-init.yaml

雖然kubeadm作為etcd節點的管理工具,但請注意kubeadm不打算支援此類節點的證書輪換或升級。長期計劃是使用etcdadm來工具來進行管理。

因為我這裡要做叢集,請根據我這裡的配置按需修改

    [root@k8s-01 ~]# cat kubeadm-init.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.31.10               #k8s-01 ip地址
      bindPort: 6443
    nodeRegistration:
      criSocket: unix:///var/run/containerd/containerd.sock
      imagePullPolicy: IfNotPresent
      name: k8s-01
      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: k8s.gcr.io
    kind: ClusterConfiguration
    kubernetesVersion: 1.24.0
    controlPlaneEndpoint: apiserver.frps.cn:8443        #高可用地址,我這裡填寫vip
    networking:
      dnsDomain: cluster.local
      serviceSubnet: 10.96.0.0/12
      podSubnet: 10.244.0.0/16
    scheduler: {}
    ---
    apiVersion: kubeproxy.config.k8s.io/v1alpha1
    kind: KubeProxyConfiguration
    mode: ipvs                                            # kube-proxy 模式
    ---
    apiVersion: kubelet.config.k8s.io/v1beta1
    authentication:
      anonymous:
        enabled: false
      webhook:
        cacheTTL: 0s
        enabled: true
      x509:
        clientCAFile: /etc/kubernetes/pki/ca.crt
    authorization:
      mode: Webhook
      webhook:
        cacheAuthorizedTTL: 0s
        cacheUnauthorizedTTL: 0s
    clusterDNS:
    - 10.96.0.10
    clusterDomain: cluster.local
    cpuManagerReconcilePeriod: 0s
    evictionPressureTransitionPeriod: 0s
    fileCheckFrequency: 0s
    healthzBindAddress: 127.0.0.1
    healthzPort: 10248
    httpCheckFrequency: 0s
    imageMinimumGCAge: 0s
    kind: KubeletConfiguration
    cgroupDriver: systemd                   # 配置 cgroup driver
    logging: {}
    memorySwap: {}
    nodeStatusReportFrequency: 0s
    nodeStatusUpdateFrequency: 0s
    rotateCertificates: true
    runtimeRequestTimeout: 0s
    shutdownGracePeriod: 0s
    shutdownGracePeriodCriticalPods: 0s
    staticPodPath: /etc/kubernetes/manifests
    streamingConnectionIdleTimeout: 0s
    syncFrequency: 0s
    volumeStatsAggPeriod: 0s

檢查配置檔案是否有錯誤

[root@k8s-01 ~]# kubeadm init --config kubeadm-init.yaml --dry-run

正確如下

預先拉取映象

[root@k8s-01 ~]# kubeadm config images list --config kubeadm-init.yaml 
k8s.gcr.io/kube-apiserver:v1.24.0
k8s.gcr.io/kube-controller-manager:v1.24.0
k8s.gcr.io/kube-scheduler:v1.24.0
k8s.gcr.io/kube-proxy:v1.24.0
k8s.gcr.io/pause:3.7
k8s.gcr.io/etcd:3.5.3-0
k8s.gcr.io/coredns/coredns:v1.8.6

提前下載映象匯入,預設情況使用的是k8s.gcr.io,這個映象地址我們無法pull,所以使用匯入的方式

    wget https://d.frps.cn/file/kubernetes/image/k8s_all_1.24.tar
    #拷貝到其它節點
    for i in k8s-02 k8s-03 k8s-04 k8s-05;do
        scp k8s_all_1.24.tar root@$i:/root/
        ssh root@$i ctr -n k8s.io i import k8s_all_1.24.tar
    done

檢查

[root@k8s-01 ~]# ctr -n k8s.io i ls -q
k8s.gcr.io/coredns/coredns:v1.8.6
k8s.gcr.io/etcd:3.5.3-0
k8s.gcr.io/kube-apiserver:v1.24.0
k8s.gcr.io/kube-controller-manager:v1.24.0
k8s.gcr.io/kube-proxy:v1.24.0
k8s.gcr.io/kube-scheduler:v1.24.0
k8s.gcr.io/pause:3.7

Kubectl 安裝

這一步可以省略,可以通過後續yum安裝,這一步可以忽略

kubeadm不會安裝或管理kubelet,kubectl因此需要確保它們kubeadm和Kubernetes版本相匹配。如果不這樣,則存在版本偏差的風險。但是,支援kubelet和k8s之間的一個小版本偏差,但kubelet版本可能永遠不會超過API Server版本

    #下載1.24.0 kubectl工具
    [root@k8s-01 ~]# curl -LO https://dl.k8s.io/release/v1.24.0/bin/linux/amd64/kubectl
    [root@k8s-01 ~]# chmod +x kubectl && mv kubectl /usr/local/bin/
    #檢查kubectl工具版本號
    [root@k8s-01 ~]# kubectl version --client --output=yaml
    clientVersion:
      buildDate: "2022-05-03T13:46:05Z"
      compiler: gc
      gitCommit: 4ce5a8954017644c5420bae81d72b09b735c21f0
      gitTreeState: clean
      gitVersion: v1.24.0
      goVersion: go1.18.1
      major: "1"
      minor: "24"
      platform: linux/amd64
    kustomizeVersion: v4.5.4
    #拷貝kubectl到其它master節點
    for i in k8s-02 k8s-03;do
        scp /usr/local/bin/kubectl root@$i:/usr/local/bin/kubectl
        ssh root@$i chmod +x /usr/local/bin/kubectl
    done

接下來開始初始化

[root@k8s-01 ~]#  kubeadm init --config kubeadm-init.yaml  --upload-certs

初始化過程

初始化完成

記住init後列印的token,複製kubectl的kubeconfig,kubectl的kubeconfig路徑預設是~/.kube/config

mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

初始化的配置檔案為儲存在configmap裡面

kubectl -n kube-system get cm kubeadm-config -o yaml

接下來執行kubectl就可以看到node了

[root@k8s-01 ~]# kubectl get node
NAME     STATUS   ROLES           AGE     VERSION
k8s-01   Ready    control-plane   4m18s   v1.24.0

Master節點配置

前面我們已經為所有master節點配置了一下服務

  • nginx
  • keeplived
  • containerd

接下來只需要給其它master節點安裝k8s元件

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
        http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

安裝相關元件

yum install -y kubelet-1.24.0 kubeadm-1.24.0 kubectl-1.24.0 --disableexcludes=kubernetes

啟動kubelet

systemctl enable --now kubelet

master執行新增節點

kubeadm join apiserver.frps.cn:8443 --token abcdef.0123456789abcdef 
        --discovery-token-ca-cert-hash sha256:a54c17e514edba57226f969268227b749d8bfb8802ae99112e08cbcabcd22ae0 
        --control-plane --certificate-key f7b0eb9c7e0aac2c95eef083c591950109434250a6df9cc0dc1ec9fb04461250

設定kubectl config檔案

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

目前我們3臺master節點已經新增完畢

[root@k8s-02 ~]# kubectl get node
NAME     STATUS   ROLES           AGE     VERSION
k8s-01   Ready    control-plane   15m     v1.24.0
k8s-02   Ready    control-plane   6m25s   v1.24.0
k8s-03   Ready    control-plane   14m     v1.24.0

Node節點配置

node節點安裝kubeadm

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
        http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

安裝相關元件

yum install -y kubeadm-1.24.0 --disableexcludes=kubernetes

新增join命令

kubeadm join apiserver.frps.cn:8443 --token abcdef.0123456789abcdef 
        --discovery-token-ca-cert-hash sha256:a54c17e514edba57226f969268227b749d8bfb8802ae99112e08cbcabcd22ae0

如果我們後續需要新增node節點時,可以到k8s-01節點執行下面的命令獲取token相關資訊

[root@k8s-01 ~]# kubeadm token create --print-join-command
kubeadm join apiserver.frps.cn:8443 --token sgvcen.qf87ykht9gopqe0d --discovery-token-ca-cert-hash sha256:f535fdf0af19022a30760fd5069c648019a3f4b4828bfb2eb566224d76d21647

如果我們新增某臺節點異常了,修改後可以執行下面的命令,然後在重新join加入叢集: kubeadm reset

驗證所有伺服器是否新增到叢集中

[root@k8s-01 ~]# kubectl get node -o wide
NAME     STATUS   ROLES           AGE    VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION                CONTAINER-RUNTIME
k8s-01   Ready    control-plane   22m    v1.24.0   192.168.31.10   <none>        CentOS Linux 7 (Core)   5.17.8-1.el7.elrepo.x86_64    containerd://1.6.4
k8s-02   Ready    control-plane   13m    v1.24.0   192.168.31.11   <none>        CentOS Linux 7 (Core)   5.17.8-1.el7.elrepo.x86_64    containerd://1.6.4
k8s-03   Ready    control-plane   21m    v1.24.0   192.168.31.12   <none>        CentOS Linux 7 (Core)   5.17.8-1.el7.elrepo.x86_64    containerd://1.6.4
k8s-04   Ready    <none>          107s   v1.24.0   192.168.31.13   <none>        CentOS Linux 7 (Core)   5.17.8-1.el7.elrepo.x86_64    containerd://1.6.4
k8s-05   Ready    <none>          6m6s   v1.24.0   192.168.31.14   <none>        CentOS Linux 7 (Core)   3.10.0-1160.62.1.el7.x86_64   containerd://1.6.4

網路配置

這個時候其實叢集還不能正常使用,因為還沒有安裝網路外掛,接下來安裝網路外掛,可以在文件 https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/ 中選擇我們自己的網路外掛,這裡我們安裝 flannel

wget http://down.i4t.com/k8s1.24/kube-flannel.yml

根據需求修改網絡卡配置,我這裡以eth0為主

          containers:
          - name: kube-flannel
            image: quay.io/coreos/flannel:v0.12.0-amd64
            command:
            - /opt/bin/flanneld
            args:
            - --ip-masq
            - --kube-subnet-mgr
            - --iface=eth0  # 如果是多網絡卡的話,指定內網網絡卡的名稱

溫馨提示: 在kubeadm.yaml檔案中設定了podSubnet網段,同時在flannel中網段也要設定相同的。 (我這裡預設就是相同的配置)

執行

[root@k8s-01 ~]# kubectl apply -f kube-flannel.yml 

CNI外掛問題

預設情況下containerd也會有一個cni外掛,但是我們已經安裝Flannel了,我們需要使用Flannel的cni外掛,需要將containerd裡面的cni配置檔案進行註釋,否則2個配置會產生衝突

因為如果這個目錄中有多個 cni 配置檔案,kubelet 將會使用按檔名的字典順序排列的第一個作為配置檔案,所以前面預設選擇使用的是 containerd-net 這個外掛。

mv /etc/cni/net.d/10-containerd-net.conflist /etc/cni/net.d/10-containerd-net.conflist.bak
ifconfig cni0 down && ip link delete cni0
systemctl daemon-reload
systemctl restart containerd kubelet

接下來我們所有的pod都可以正常運行了

驗證叢集

等kube-system名稱空間下的Pod都為Running,這裡先測試一下dns是否正常

cat<<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:alpine
        name: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30001
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - name: busybox
    image: abcdocker9/centos:v1
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always
EOF

建立後Pod我們進行檢查

使用nslookup檢視是否能返回地址

[root@k8s-01 ~]# kubectl exec -ti busybox -- nslookup kubernetes
Server:         10.96.0.10
Address:        10.96.0.10#53
Name:   kubernetes.default.svc.cluster.local
Address: 10.96.0.1

測試nginx svc以及Pod內部網路通訊是否正常

for i in k8s-01 k8s-02 k8s-03 k8s-04 k8s-05
do
   ssh root@$i curl -s 10.99.209.220   #nginx svc ip
   ssh root@$i curl -s 10.244.3.4   #pod ip
done

訪問宿主機nodePort埠