企业级Kubernetes集群版离线在线部署

企业级Kubernetes集群版

本文使用kubeadm部署Kubernetes集群,kubeadm是官方社区推出的一个用于快速部署kubernetes集群的开源工具。

一、资源需求

在开始部署Kubernetes集群之前,机器需要满足以下几个条件:

  • 一台或多台机器,Linux操作系统

  • 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多

  • 需要访问公网,拉取镜像及安装包,如果服务器不能上网,需要准备一台同环境的机器下载需要的软件包并上传至K8S节点

  • 禁止swap分区

二、资源规划

本文示例以3台master机器作为高可用冗余管控节点,搭建K8S集群,worker节点可以根据业务需求随时增加。通过keepalived和haproxy实现APIserver服务的高可用。

服务 部署节点IP 主机名
master 10.43.86.186 k8s-master01
master 10.43.86.185 k8s-master02
master 10.43.86.180 k8s-master03
worker 10.43.86.187 k8s-worker001
高可用VIP(云平台可以使用负载均衡地址或者HAVIP产品) 10.43.86.188 k8s-vip
keepalived(云平台使用负载均衡产品时无需部署keepalived,配置代理到haproxy端口即可) 10.43.86.186、10.43.86.185、10.43.86.180
haproxy 10.43.86.186、10.43.86.185、10.43.86.180

2.1 离线安装软件及依赖包

注意:如果部署的K8S环境可以访问公网,下面的离线安装步骤不需要操作。

#######准备一台环境一致可以访问公网的机器,下载所需软件包并打包上传至所有K8S集群节点。
mkdir -p /opt/package/{
   base_package,kubernetes_package,keepalived_package,haproxy_package}
#######可以访问公网的机器准备yum源,注意根据不同的操作系统及CPU架构配置对应的yum源地址,下方以CentOS7操作系统x86架构作为示例配置阿里云的CentOS、kubernetes的镜像源地址。
#1.CentOS7和K8S镜像源配置示例,根据现场机器实际环境修改配置
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo 
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
#清理并重新生成缓存
yum clean all && yum makecache
#2.下载基础常用软件包、IPVS插件及依赖包
yum install --downloadonly --downloaddir=/opt/package/base_package/ wget expect vim net-tools ntp bash-completion jq iptables ipvsadm ipset conntrack-tools conntrack sysstat libseccomp libtool-ltdl device-mapper-persistent-data lvm2 yum-utils ntpdate -y
#3.下载keepalived
yum install -y --downloadonly --downloaddir=/opt/package/keepalived_package/ keepalived
#4.下载haproxy
yum install -y --downloadonly --downloaddir=/opt/package/haproxy_package/ haproxy
#5.查看镜像源中所有kubelet、kubeadm、kubectl的版本,选择需求版本下载,本次示例安装kubernetes1.27.6版本。
yum list kubelet kubeadm kubectl --showduplicates -y
yum install -y --downloadonly --downloaddir=/opt/package/kubernetes_package/ kubelet-1.27.6 kubeadm-1.27.6 kubectl-1.27.6
#6.打包所有安装包上传至K8S节点
cd /opt/ && tar zcvf package.tar.gz package
#7.上传到所有K8S集群节点,解压并安装rpm包,并开启kubelet开机自启配置。
tar xvf package.tar.gz
yum localinstall -y package/base_package/*.rpm package/kubernetes_package/*.rpm package/keepalived_package/*.rpm package/haproxy_package/*.rpm
systemctl enable kubelet

2.2 前置环境准备操作

注意:

  • 所有K8S节点都需要操作。
  • 如果K8S集群可以访问公网,上述2.1所有离线安装操作不需要执行,下面方案中包含yum安装。
  • 如果K8S集群不能访问公网,需先执行上述2.1所有离线安装操作,下面方案中yum安装不需要执行。
########下述步骤K8S集群所有节点所有机器全做
# 关闭selinux
setenforce 0
sed -ri 's/(SELINUX=)enforcing/\1disabled/' /etc/selinux/config
# 关闭防火墙
systemctl disable --now firewalld
# 关闭swap分区
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
# 根据规划设置主机名
hostnamectl set-hostname <hostname>
# 在master添加hosts
cat >> /etc/hosts << EOF
10.43.86.188 k8s-vip
10.43.86.186 k8s-master01
10.43.86.185 k8s-master02
10.43.86.180 k8s-master03
EOF

# 配置镜像源,离线安装时不需要配置
curl-o /etc/yum.repos.d/CentOS-Base.repo https://repo.huaweicloud.com/repository/conf/CentOS-7-reg.repo
yum clean all && yum makecache
# 同步集群时间(根据现场环境时间同步服务器设置)
yum install ntpdate -y
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo 'Asia/Shanghai' > /etc/timezone
ntpdate time2.aliyun.com
crontab -e
*/1 * * * * /usr/sbin/ntpdate time2.aliyun.com &> /dev/null
# 安装基础常用软件
yum install wget expect vim net-tools ntp bash-completion ipvsadm ipset jq iptables conntrack sysstat libseccomp -y
# 安装IPVS插件
yum install -y conntrack-tools ipvsadm ipset conntrack libseccomp libtool-ltdl
# 加载IPVS模块
cat > /etc/sysconfig/modules/ipvs.modules << EOF
#!/bin/bash
# netfilter 模块 允许 iptables 检查桥接流量
modprobe -- br_netfilter
# containerd
modprobe -- overlay
# nf_conntrack
modprobe -- nf_conntrack
# ipvs
modprobe -- ip_vs
modprobe -- ip_vs_lc
modprobe -- ip_vs_lblc
modprobe -- ip_vs_lblcr
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- ip_vs_dh
modprobe -- ip_vs_fo
modprobe -- ip_vs_nq
modprobe -- ip_vs_sed
modprobe -- ip_vs_ftp
modprobe -- ip_tables
modprobe -- ip_set
modprobe -- ipt_set
modprobe -- ipt_rpfilter
modprobe -- ipt_REJECT
modprobe -- ipip
modprobe -- xt_set
EOF
# 权限设置、并加载到系统之中
chmod 755 /etc/sysconfig/modules/ipvs.modules
source /etc/sysconfig/modules/ipvs.modules
lsmod | grep ip_vs

# 修改内核启动参数
cat > /etc/sysctl.d/k8s.conf << EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
fs.may_detach_mounts = 1
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
fs.file-max=52706963
fs.nr_open=52706963
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp.keepaliv.probes = 3
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp.max_tw_buckets = 36000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp.max_orphans = 327680
net.ipv4.tcp_orphan_retries = 3
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.ip_conntrack_max = 65536
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.top_timestamps = 0
net.core.somaxconn = 16384
EOF

# 立即生效
sysctl --system

三、部署keepalived

传统物理或者虚拟化服务器直接部署keepalied即可,但在云平台上,因云上网络环境需使用虚拟化技术构建,虚拟服务器IP地址由云平台底层的虚拟化平台分配和管理。无法像传统方式一样修改主机IP地址,且整个虚拟网络是基于3层的隧道技术,ARP被终结在发送端,主机无法声明IP地址。可以使用云产品的HaVip功能,高可用虚拟IP+部署keepalived服务方式+haproxy服务,或者采用SLB负载均衡+部署haproxy服务方式

注意:只需要在规划的master节点部署

3.1 安装keepalived

在线yum安装keepalived,如果K8S节点无法访问公网,根据《2.1离线安装软件及依赖包》手动离线安装过的机器忽略yum步骤。

yum install -y keepalived

3.2 master节点keepalived配置

注意:virtual_ipaddress配置为规划的VIP,interface配置为本机网卡名,根据现场实际情况修改

master01节点配置

cat > /etc/keepalived/keepalived.conf <<EOF 
! Configuration File for keepalived

global_defs {
   router_id k8s-master01
}

vrrp_script check_haproxy {
    script "killall -0 haproxy"
    interval 3
    weight -2
    fall 10
    rise 2
}

vrrp_instance VI_1 {
    #设置节点为非抢占式
    state BACKUP
    nopreempt
    interface eth0     #设置网卡名,本示例配置为eth0  
    virtual_router_id 51
    priority 150       #设置优先级,数字越大,优先级越高
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ceb1b3ec013d66163d6ab
    }
    unicast_src_ip 10.43.86.186   #设置本节点的私网IP地址
    unicast_peer {
        #对端节点的私网IP地址
        10.43.86.185
        10.43.86.180 
    }
    virtual_ipaddress {
        #设置HaVip的IP地址
        10.43.86.188
    }
    track_script {
        check_haproxy
    }

}
EOF

master02节点配置

cat > /etc/keepalived/keepalived.conf <<EOF 
! Configuration File for keepalived

global_defs {
   router_id k8s-master02
}

vrrp_script check_haproxy {
    script "killall -0 haproxy"
    interval 3
    weight -2
    fall 10
    rise 2
}

vrrp_instance VI_1 {
    #设置节点为非抢占式
    state BACKUP
    nopreempt
    interface eth0     #设置网卡名,本示例配置为eth0  
    virtual_router_id 51
    priority 100       #设置优先级,数字越大,优先级越高
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ceb1b3ec013d66163d6ab
    }
    unicast_src_ip 10.43.86.185   #设置本节点的私网IP地址
    unicast_peer {
        #对端节点的私网IP地址
        10.43.86.186
        10.43.86.180 
    }
    virtual_ipaddress {
        #设置HaVip的IP地址
        10.43.86.188
    }
    track_script {
        check_haproxy
    }

}
EOF

master03节点配置

cat > /etc/keepalived/keepalived.conf <<EOF 
! Configuration File for keepalived

global_defs {
   router_id k8s-master03
}

vrrp_script check_haproxy {
    script "killall -0 haproxy"
    interval 3
    weight -2
    fall 10
    rise 2
}

vrrp_instance VI_1 {
    #设置节点为非抢占式
    state BACKUP
    nopreempt
    interface eth0     #设置网卡名,本示例配置为eth0  
    virtual_router_id 51
    priority 50       #设置优先级,数字越大,优先级越高
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ceb1b3ec013d66163d6ab
    }
    unicast_src_ip 10.43.86.180   #设置本节点的私网IP地址
    unicast_peer {
        #对端节点的私网IP地址
        10.43.86.186
        10.43.86.185 
    }
    virtual_ipaddress {
        #设置HaVip的IP地址
        10.43.86.188
    }
    track_script {
        check_haproxy
    }

}
EOF

四、部署haproxy

注意:只需要在规划的master节点部署

4.1 安装haproxy

在线yum安装haproxy,如果K8S节点无法访问公网,根据《2.1 离线安装软件依赖包》手动离线安装的机器忽略yum步骤。

yum install -y haproxy

4.2 配置haproxy

所有master节点的配置均相同,配置中声明了后端代理的三个master节点服务器,指定了haproxy运行的端口为16443等,因此16443端口为K8S集群的API server入口

cat > /etc/haproxy/haproxy.cfg << EOF
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    #
    log         127.0.0.1 local2
    
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon 
       
    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------  
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
#---------------------------------------------------------------------
# kubernetes apiserver frontend which proxys to the backends
#--------------------------------------------------------------------- 
frontend kubernetes-apiserver
    mode                 tcp
    #haproxy监听端口,因为 haproxy 是和 k8s apiserver是部署在同一台服务器上,都用 6443 会冲突。
    bind                 *:16443
    option               tcplog
    default_backend      kubernetes-apiserver    
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend kubernetes-apiserver
    mode        tcp
    balance     roundrobin
    
    # master节点IP和hosts解析里的域名,端口是apiserver 监听端口。
    server      k8s-master01   10.43.86.186:6443 check
    server      k8s-master02   10.43.86.185:6443 check
    server      k8s-master03   10.43.86.180:6443 check
#---------------------------------------------------------------------
# collection haproxy statistics message
#---------------------------------------------------------------------
listen stats
    bind                 *:1080
    stats auth           admin:awesomePassword
    stats refresh        5s
    stats realm          HAProxy\ Statistics
    stats uri            /admin?stats
EOF

4.3 启动检查服务

所有master节点启动keepalived和haproxy服务,先启动haproxy,因keepalived配置了haproxy检测。

###haproxy启动
systemctl enable --now haproxy
systemctl status haproxy

###keepalived启动,注意因为配置的是非抢占式,按顺序启动
systemctl enable --now keepalived
systemctl status keepalived.service 

#检查keepalived虚拟IP
ip a |grep eth0

检查haproxy端口

netstat -lntup|grep haproxy

五、安装K8S组件和containerd运行时

Kubernetes 从 1.20 版本开始,推荐使用 Containerd 作为默认的容器运行时,弃用了对 Docker 的直接支持( 不是完全不支持!),所以下面以containerd作为K8S容器运行时。

5.1 安装containerd

注意:所有K8S集群节点都需要安装containerd

二进制containerd安装

containerd说明:
containerd有两种安装包
	- containerd-xxx:
		这种安装包用于单机测试没问题,不包含runC,不建议使用。		
	- cri-containerd-cni-xxx:
		包含runc及符合K8S的CNI接口的相关软件包。虽然包含runC,但是依赖系统中的Seccomp(用于系统资源调用的相关模块)来配合使用,且不同runc对seccomp版本要求不尽相同,会导致安装后无法使用runc的情况,下面步骤会手动下载安装runc。
###containerd包、runc下载地址,根据系统和CPU架构选择,X86_64对应amd64,arm对应arm64版本
wget https://github.com/containerd/containerd/releases/download/v1.7.13/cri-containerd-cni-1.7.13-linux-amd64.tar.gz
wget https://github.com/opencontainers/runc/releases/download/v1.1.12/runc.amd64
#上传至所有节点解压
#找到下载的runc.amd64文件并授权
mv runc.amd64 /usr/sbin/runc
chmod +x /usr/sbin/runc
#查看验证runc版本
runc -v
#创建containerd目录解压后配置containerd、ctr、crictl、containerd-shim-runc-v2可执行文件到环境变量目录下。
mkdir -p /usr/local/containerd
tar xvf cri-containerd-cni-1.7.13-linux-amd64.tar.gz -C /usr/local/containerd
cp /usr/local/containerd/usr/local/bin/containerd /usr/local/bin/
cp /usr/local/containerd/etc/systemd/system/containerd.service  /usr/lib/systemd/system/
cp /usr/local/containerd/usr/local/bin/ctr /usr/bin/
cp /usr/local/containerd/usr/local/bin/containerd-shim-runc-v2 /usr/bin/
cp /usr/local/containerd/usr/local/bin/crictl /usr/local/bin
#检测containerd安装版本
containerd --version
#创建containerd配置文件目录
mkdir -p /etc/containerd
#生成默认的containerd配置文件
containerd config default > /etc/containerd/config.toml
#修改Cgroup的管理者为systemd组件
grep SystemdCgroup /etc/containerd/config.toml
sed -ri 's#(SystemdCgroup = )false#\1true#' /etc/containerd/config.toml 
grep SystemdCgroup /etc/containerd/config.toml
#修改pause的基础镜像名称替换成阿里云镜像仓库地址
grep sandbox_image /etc/containerd/config.toml
#替换注意版本
sed -i 's#registry.k8s.io/pause:3.8#registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9#' /etc/containerd/config.toml
grep sandbox_image /etc/containerd/config.toml
#配置containerd服务启动
systemctl daemon-reload && systemctl enable --now containerd
systemctl status containerd.service
#使用ctr工具检查验证
ctr version

5.2 ctr工具帮助

我们知道 Docker CLI 工具提供了需要增强用户体验的功能;ctr 是 Containerd 的命令行客户端工具,同样提供了与 Containerd 交互的多种命令。

###########使用ctr工具操作containerd镜像常用命令############
#查看所有命名空间
ctr namespace ls
#创建k8s.io命名空间
ctr ns create k8s.io
#查看k8s.io命名空间下的镜像
ctr -n=k8s.io image ls
或者
ctr -n=k8s.io i ls
ctr -n k8s.io i ls -q
#拉取镜像
ctr i pull 
#导入导出镜像,指定导入导出导K8S命名空间
ctr -n k8s.io i import 镜像地址  #导出镜像
ctr -n k8s.io i export 镜像包.tar 镜像地址 #导出镜像
###注意:docker导出的镜像无法使用ctr直接导入,需要转换成OCI格式。

5.3 crictl工具使用

crictl是一个CRI(Container Runtime Interface)兼容的命令行工具,主要用于与Kubernetes节点上的容器运行时进行交互

###按照《5.1 安装containerd》步骤已按照crictl工具,生成配置文件即可。
#配置文件(所有K8S节点执行) 
cat > /etc/crictl.yaml << EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
EOF
#查看版本
crictl -v
#配置完即可使用crictl命令,crictl默认工作在k8s.io命名空间下,无需指定命名空间。
crictl pull 镜像名 #拉取镜像
crictl images  #查看镜像
crictl ps -a #查看所有容器
crictl exec -i -t #进入容器
crictl start #启动容器

5.4 安装kubeadm、kubelet、kubectl

注意:所有节点都需要安装

在线yum安装kubernetes组件,如果K8S节点无法访问公网,通过《2.1 离线安装软件及依赖包》手动离线安装的机器忽略下述步骤。

# 配置kebernetes yum 源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 查看需要的版本,指定版本下载。
yum list kubelet kubeadm kubectl --showduplicates -y
#yum install -y kubelet-1.27.6 kubeadm-1.27.6 kubectl-1.27.6
# 设置kubelet服务开机自启动,注意:不要直接执行 systemctl start kubelet,初始化集群完成后kubelet服务会自动拉起。
systemctl enable kubelet

六、初始化Kubernetes集群

6.1 创建kubeadm初始化配置文件

注意:在keepalived VIP当前所在节点上操作,本示例的VIP在master01节点

# 在有vip的master主机上操作,这里为master01
mkdir /etc/kubernetes/manifests/ -p
cd /etc/kubernetes/manifests/
######注意:使用kubeadm config print init-defaults > kubeadm-init.yaml 打印出默认配置,然后在根据自己的环境修改配置,需要修改 advertiseAddress、controlPlaneEndpoint、imageRepository、podSubnet、serviceSubnet配置。
配置说明:
###advertiseAddress 为当前节点的ip。
###controlPlaneEndpoint 为规划的VIP+16443 端口。
###imageRepository 修改为国内阿里云镜像地址。
###podSubnet 需规划一个私有网端用来分配给K8S pod
###serviceSubnet 需规划一个私有网端用来分配给K8S service ip。

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

###########下方是示例yaml配置,通过上述命令打印出初始化默认配置的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:
  # 当前节点的ip及默认的apiserver端口
  advertiseAddress: 10.43.86.186
  bindPort: 6443
nodeRegistration:
  #指定containerd为运行时,一般1.23之后版本的K8S默认是该运行时。
  criSocket: unix:///var/run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  # 此处修改为当前节点主机名
  name: k8s-master01
  # 打污点,master节点不调度pod工作。
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  # 此处添加,证书中心包含的SANs列表一般包含VIP与各master节点的主机名称
  certSANs:
  - k8s-vip
  - k8s-master01
  - k8s-master02
  - k8s-master03
  - localhost
  - 10.43.86.188
  - 10.43.86.186
  - 10.43.86.185
  - 10.43.86.180
  - 127.0.0.1
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
# 规划的VIP+haproxy的监听端口
controlPlaneEndpoint: "10.43.86.188:16443"
controllerManager: {
   }
# 修改DNS类型使用CoreDNS
dns: 
  type: CoreDNS
etcd:
  local:
    # etcd 数据目录
    dataDir: /var/lib/etcd
# 更换集群所需镜像仓库源为阿里源,加速拉取
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
kind: ClusterConfiguration
#设置集群证书有效期为10年(87600小时)
certificates:
  duration: 87600h
kubernetesVersion: 1.27.0
networking:
  #集群dns根域默认cluster.local,可以根据需求修改
  dnsDomain: cluster.local
  # k8s集群pod网段,需规划一个私网
  podSubnet: 10.244.0.0/16
  # k8s集群service网段,需规划一个私网
  serviceSubnet: 192.168.0.0/20
scheduler: {
   }

############################yaml配置结束分隔符##############################

6.2 K8S管控组件镜像预下载

方式一:访问公网预下载镜像

#查看所需镜像版本
kubeadm config images list --config kubeadm-init.yaml

###特别注意:查看registry.cn-hangzhou.aliyuncs.com/google_containers/pause的镜像版本需要跟containerd服务的/etc/containerd/config.toml配置文件sandbox_image配置指定的镜像地址版本一致,如果不一致,修改所有节点的/etc/containerd/config.toml配置文件,更换为K8S指定的版本,重启containerd。

#预下载镜像
kubeadm config images pull --config kubeadm-init.yaml

方式二:无法连接公网,通过公网服务器下载镜像打包导入到所有节点

#查看所需镜像及版本输出到文件中
kubeadm config images list --config kubeadm-init.yaml > /tmp/kubeadm-init-images.txt

###特别注意:查看registry.cn-hangzhou.aliyuncs.com/google_containers/pause的镜像版本需要跟containerd服务的/etc/containerd/config.toml配置文件sandbox_image配置指定的镜像地址版本一致,如果不一致,修改所有节点的/etc/containerd/config.toml配置文件,更换为K8S指定的版本,重启containerd。

#把镜像版本文件/tmp/kubeadm-init-images.txt上传至公网服务器上,批量下载镜像。
for y in `cat kubeadm-init-images.txt`;do ctr i pull $y;done && ctr i ls -q name~=registry.cn-hangzhou.aliyuncs.com/google_containers

#批量导出所需镜像为tar文件
for x in `ctr i ls -q name~=registry.cn-hangzhou.aliyuncs.com/google_containers`;do ctr i export `echo $x|awk -F "[/:]+" '{print $3}'`.tar $x;done

#打包镜像文件。
tar zcvf images_tar.gz pause.tar kube-scheduler.tar kube-proxy.tar kube-controller-manager.tar kube-apiserver.tar etcd.tar coredns.tar

#把images_tar.gz镜像压缩包上传至【K8S所有节点】解压(images_tar.gz镜像压缩包包含所有管控容器镜像tar文件,ctr镜像格式。)
mkdir -p /tmp/images_tar && tar xvf images_tar.gz -C /tmp/images_tar

#【K8S所有节点】批量导入镜像到k8s.io命名空间下
ctr ns create k8s.io;for x in `ls /tmp/images_tar/`;do ctr -n k8s.io i import /tmp/images_tar/$x;done

6.3 初始化K8S集群

注意:只需要在vip所在节点的master上操作,本文示例:master01

cd /etc/kubernetes/manifests/
kubeadm init --config kubeadm-init.yaml --v=5

######如果出现报错:
[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables does not exist
解决:
modprobe br_netfilter
echo 1 > /proc/sys/net/ipv4/ip_forward
######初始化失败重置:
kubeadm reset -f
重新打印初始化配置并修改:
cd /etc/kubernetes/manifests/
kubeadm config print init-defaults > kubeadm-init.yaml

# kubeadm init主要执行了以下操作:
[init]:指定版本进行初始化操作
[preflight] :初始化前的检查和下载所需要的 Docker 镜像文件
[kubelet-start] :生成 kubelet 的配置文件 ”/var/lib/kubelet/config.yaml”,没有这个文件 kubelet 无法启动,所以初始化之前的 kubelet 实际上启动失败。
[certificates]:生成Kubernetes使用的证书,存放在 /etc/kubernetes/pki 目录中。
[kubeconfig] :生成 KubeConfig 文件,存放在 /etc/kubernetes目录中,组件之间通信需要使用对应文件。
[control-plane]:使用 /etc/kubernetes/manifest 目录下的 YAML 文件,安装 Master 组件。
[etcd]:使用 /etc/kubernetes/manifest/etcd.yaml 安装 Etcd 服务。
[wait-control-plane]:等待 control-plan 部署的 Master 组件启动。
[apiclient]:检查 Master 组件服务状态。
[uploadconfig]:更新配置。
[kubelet]:使用 configMap 配置 kubelet。
[patchnode]:更新 CNI 信息到 Node上,通过注释的方式记录。
[mark-control-plane]:为当前节点打标签,打了角色 Master,和不可调度标签,这样默认就不会使用 Master 节点来运行 Pod。
[bootstrap-token]:生成 token 记录下来,后边使用 kubeadm join 往集群中添加节点时会用到。
[addons]:安装附加组件 CoreDNS 和 kube-proxy

按照提示配置kubectl凭据:

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

# 检查组件状态
[root@k8s-master01 manifests]# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS    MESSAGE                         ERROR
scheduler            Healthy   ok                              
controller-manager   Healthy   ok                              
etcd-0               Healthy   {
   "health":"true","reason":""}

########如果出现scheduler和controller-manager状态异常:
原因:出现这种情况,是老版本的/etc/kubernetes/manifests/下的kube-controller-manager.yaml和kube-scheduler.yaml设置的默认端口是0导致的,解决方式是注释掉对应的port即可,操作如下:
kube-controller-manager.yaml文件修改:注释掉27行,- --port=0
kube-scheduler.yaml配置修改:注释掉19行,- --port=0
然后在节点上重启kubelet服务,systemctl restart kubelet.service 重新查看是否正常。
########检查kube-controller-manager.yaml文件是否存在下方配置,老版本需要配置下方参数,新版本默认配置#############
vim /etc/kubernetes/manifests/kube-controller-manager.yaml
。。。 。。。
    - --allocate-node-cidrs=true
    #注意网段是规划的pod子网,同时要和后续安装的flannel插件里配置的网段保持一致。
    - --cluster-cidr=10.244.0.0/16
。。。 。。。
#查看节点状态
kubectl get nodes
NAME           STATUS     ROLES                  AGE     VERSION
k8s-master01   NotReady   control-plane,master   8m22s   v1.21.0
#目前只有一个节点,角色是 Master,状态是 NotReady,状态是 NotReady 状态是因为还没有安装网络插件。

加入集群命令帮助

#如果加入集群token过期,重新生成
kubeadm token create --print-join-command
#worker节点加入方式(下方token为示例,根据上面命令实际生成的结果使用。):
kubeadm join k8s-vip:16443 --token qma4tc.6rlctzhicmuctv50 --discovery-token-ca-cert-hash sha256:1ed5f80a1c40cdfbafb7544f550a7a5464f6cdfde515fe8be0185ebe63418d13 
#master节点加入方式(添加 --control-plane参数):
kubeadm join k8s-vip:16443 --token hmq7nh.r8wm1dwpnij4169q --discovery-token-ca-cert-hash sha256:1ed5f80a1c40cdfbafb7544f550a7a5464f6cdfde515fe8be0185ebe63418d13 --control-plane

6.4 kube-proxy切换为ipvs模式

#1.修改kube-proxy的configmap,把mode配置改为ipvs
kubectl edit configmaps kube-proxy -n kube-system
    ... ...
    mode: "ipvs"
    ... ...
#2.重启kube-proxy pod节点
kubectl delete pods -n kube-system -l k8s-app=kube-proxy
#3.查看kube-proxy pod启动状态
kubectl get pods -n kube-system -l k8s-app=kube-proxy
#4.查看kube-proxy日志是否更换为IPVS模式
kubectl logs --tail 100 kube-proxy-xxxxxx  -n kube-system
......
Using ipvs Proxier #使用IPVS代理。
......
"IPVS scheduler not specified, use rr by default"	#IPVS默认算法rr轮询。
......

6.5 修改集群service节点主机端口默认端口范围

##### k8s集群service节点主机端口默认范围是30000-32767,修改kube-apiserver.yaml配置文件中的端口范围(自动会重启)。
#编辑/etc/kubernetes/manifests/kube-apiserver.yaml,在- --service-cluster-ip-range 同级增加下方参数
    - --service-node-port-range=1-65535

6.6 将集群证书文件拷贝至其他master节点

注意:根据现场实际情况,在初始化集群配置完成的节点上操作,本文示例:master01

###注意:在做完集群初始化后的master节点上操作,本文示例中master01做完集群初始化,复制K8S集群证书文件至其它master节点。
# 拷贝正式至 master02 节点
ssh root@k8s-master02 mkdir -p /etc/kubernetes/pki/etcd
scp /etc/kubernetes/admin.conf root@k8s-master02:/etc/kubernetes/
scp /etc/kubernetes/pki/{
   ca.*,sa.*,front-proxy-ca.*} root@k8s-master02:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/etcd/ca.* root@k8s-master02:/etc/kubernetes/pki/etcd/

# 拷贝正式至 master03 节点
ssh root@k8s-master03 mkdir -p /etc/kubernetes/pki/etcd
scp /etc/kubernetes/admin.conf root@k8s-master03:/etc/kubernetes/
scp /etc/kubernetes/pki/{
   ca.*,sa.*,front-proxy-ca.*} root@k8s-master03:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/etcd/ca.* root@k8s-master03:/etc/kubernetes/pki/etcd/

七、部署flannel集群网络

7.1 公网安装flannel网络插件

# 在做完集群初始化后的master节点上操作,本文示例master01。
mkdir -p /etc/kubernetes/flannel
cd /etc/kubernetes/flannel

#如果节点可以访问公网,直接执行下方步骤
wget -c https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml

7.2 离线安装flannel网络插件

######如果节点不能访问公网,在公网机器上下载kube-flannel.yml并上传至做完集群初始化后的master节点上,本示例:master01。
###公网服务器上操作:
#1.下载kube-flannel.yml,如果无法下载kube-flannel.yml文件,可以复制使用下方kube-flannel.yml模板使用
wget -c https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
#2.把文件中image配置的flannel-cni-plugin和flannel镜像替换成下方离线镜像地址。
grep "image:" kube-flannel.yml
        image: registry.cn-hangzhou.aliyuncs.com/google_containers/flannel-cni-plugin:v1.1.2
        image: registry.cn-hangzhou.aliyuncs.com/google_containers/flannel:v0.21.5
        image: registry.cn-hangzhou.aliyuncs.com/google_containers/flannel:v0.21.5
        
###做完集群初始化后的master节点上,本示例:master01
#1.上传kube-flannel.yml文件至做完集群初始化后的master01节点上。
mkdir -p /etc/kubernetes/flannel
cd /etc/kubernetes/flannel
#2.上传离线镜像包至 [所有K8S集群节点上] 并解压导入到k8s.io命名空间下(附件包:flannel_package.tar.gz中包含flannel镜像tar包,ctr格式的镜像)。
tar xvf flannel_package.tar.gz
ctr -n k8s.io i import flannel-cni-plugin.tar 
ctr -n k8s.io i import flannel.tar
#3.做完集群初始化后的master节点上操作,本示例:master01上执行apply部署flannel。
kubectl apply -f kube-flannel.yml 

7.3 kube-flannel.yml 模板

如果无法下载kube-flannel.yml文件,可以复制使用下方模板,但注意修改network的网段。

特别注意:修改net-conf.json配置中"Network": “10.244.0.0/16”,和集群初始化配置文件kubeadm-init.yaml中的podSubnet配置pod网段一致。

---
kind: Namespace
apiVersion: v1
metadata:
  name: kube-flannel
  labels:
    k8s-app: flannel
    pod-security.kubernetes.io/enforce: privileged
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: flannel
  name: flannel
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes/status
  verbs:
  - patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: flannel
  name: flannel
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: flannel
subjects:
- kind: ServiceAccount
  name: flannel
  namespace: kube-flannel
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: flannel
  name: flannel
  namespace: kube-flannel
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-flannel-cfg
  namespace: kube-flannel
  labels:
    tier: node
    k8s-app: flannel
    app: flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "EnableNFTables": false,
      "Backend": {
        "Type": "vxlan"
      }
    }
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds
  namespace: kube-flannel
  labels:
    tier: node
    app: flannel
    k8s-app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/os
                operator: In
                values:
                - linux
      hostNetwork: true
      priorityClassName: system-node-critical
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni-plugin
        image: registry.cn-hangzhou.aliyuncs.com/google_containers/flannel-cni-plugin:v1.1.2
        command:
        - cp
        args:
        - -f
        - /flannel
        - /opt/cni/bin/flannel
        volumeMounts:
        - name: cni-plugin
          mountPath: /opt/cni/bin
      - name: install-cni
        image: registry.cn-hangzhou.aliyuncs.com/google_containers/flannel:v0.21.5
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: registry.cn-hangzhou.aliyuncs.com/google_containers/flannel:v0.21.5
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
            add: ["NET_ADMIN", "NET_RAW"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: EVENT_QUEUE_DEPTH
          value: "5000"
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
        - name: xtables-lock
          mountPath: /run/xtables.lock
      volumes:
      - name: run
        hostPath:
          path: /run/flannel
      - name: cni-plugin
        hostPath:
          path: /opt/cni/bin
      - name: cni
        hostPath:
          path: /etc/cni/net.d
      - name: flannel-cfg
        configMap:
          name: kube-flannel-cfg
      - name: xtables-lock
        hostPath:
          path: /run/xtables.lock
          type: FileOrCreate

八、节点加入Kubernetes集群

8.1 master02加入集群

执行在master01上init后输出的join命令,需要带上参数--control-plane表示把master02控制节点加入集群

#如果加入集群token过期,重新生成
kubeadm token create --print-join-command

#master节点加入方式(注意下方token为示例,通过上面命令生成获取,并添加 --control-plane参数):
kubeadm join 10.43.86.188:16443 --token hmq7nh.r8wm1dwpnij4169q --discovery-token-ca-cert-hash sha256:1ed5f80a1c40cdfbafb7544f550a7a5464f6cdfde515fe8be0185ebe63418d13 --control-plane

#配置kubectl工具凭据
	mkdir -p $HOME/.kube
	sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
	sudo chown $(id -u):$(id -g) $HOME/.kube/config

8.2 master03加入集群

#如果加入集群token过期,重新生成
kubeadm token create --print-join-command

#master节点加入方式(注意下方token为示例,通过上面命令生成获取,并添加 --control-plane参数):
kubeadm join 10.43.86.188:16443 --token hmq7nh.r8wm1dwpnij4169q --discovery-token-ca-cert-hash sha256:1ed5f80a1c40cdfbafb7544f550a7a5464f6cdfde515fe8be0185ebe63418d13 --control-plane

#配置kubectl工具凭据
	mkdir -p $HOME/.kube
	sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
	sudo chown $(id -u):$(id -g) $HOME/.kube/config

8.3 worker节点加入集群

#如果加入集群token过期,重新生成
kubeadm token create --print-join-command

#worker节点加入方式(注意下方token为示例,通过上面命令生成获取):
kubeadm join 10.43.86.188:16443 --token fggzmm.25w77cix3c5giybz --discovery-token-ca-cert-hash sha256:05bff7926bf65a977dda54b1227c9158b3f24c6c99ef9a4c5a874be82c9ec1e8

8.4 设置集群角色

# 设置master节点的集群角色为master(所有master节点执行,注意替换节点主机名称)
kubectl label nodes k8s-master01 node-role.kubernetes.io/master=
kubectl label nodes k8s-master02 node-role.kubernetes.io/master=
kubectl label nodes k8s-master03 node-role.kubernetes.io/master=

8.5 检查集群状态

kubectl get node
kubectl get cs
kubectl get pods --all-namespaces

8.6 kubectl优化

添加命令自动补齐补全功能

#所有master节点上执行
# yum install -y bash-completion
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

九、etcd状态检查

###1.检查etcd pod状态
kubectl get pods -A|grep etcd
###2.进入etcd容器中执行命令
# 查看etcd 集群的成员节点
etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --endpoints="https://10.43.86.185:2379,https://10.43.86.186:2379,https://10.43.86.180:2379" member list -w table
# 查看集群状态和主节点信息
etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --endpoints="https://10.43.86.185:2379,https://10.43.86.186:2379,https://10.43.86.180:2379"  endpoint status -w table

十、重置节点重新加入集群

################重置master节点##################
systemctl restart keepalived.service 
kubeadm reset -f
sudo rm -rf $HOME/.kube
# 重新拷贝证书至master节点
ssh root@k8s-master02 mkdir -p /etc/kubernetes/pki/etcd
scp /etc/kubernetes/admin.conf root@k8s-master02:/etc/kubernetes/
scp /etc/kubernetes/pki/{
   ca.*,sa.*,front-proxy-ca.*} root@k8s-master02:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/etcd/ca.* root@k8s-master02:/etc/kubernetes/pki/etcd/
#master节点重新生成集群token
kubeadm token create --print-join-command
#master节点加入方式(注意下方token为示例,通过上面命令生成获取,并添加 --control-plane参数):
kubeadm join 10.43.86.188:16443 --token hmq7nh.r8wm1dwpnij4169q --discovery-token-ca-cert-hash sha256:1ed5f80a1c40cdfbafb7544f550a7a5464f6cdfde515fe8be0185ebe63418d13 --control-plane
#配置kubectl工具凭据
	mkdir -p $HOME/.kube
	sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
	sudo chown $(id -u):$(

你可能感兴趣的:(kubernetes,容器,云原生,docker,运维)