二进制安装高可用k8s 1.27.x

本篇文章参考杜宽的《云原生Kubernetes全栈架构师》,视频、资料文档等,大家可以多多支持!

1. 高可用架构

1.1 架构图

二进制安装高可用k8s 1.27.x_k8s安装

Kubernetes是属于主从设备模型(Master-Slave架构),即有Master节点负责核心的调度、管理和运维,Slave节点则执行用户的程序。在Kubernetes中,主节点一般被称为Master Node 或者 Head Node,而从节点则被称为Worker Node 或者 Node。

Tips:Master节点通常包括API Server、Scheduler、Controller Manager等组件,Node节点通常包括Kubelet、Kube-Proxy等组件!


看到蓝色框内的Control Plane,这个是整个集群的控制平面,相当于是master进程的加强版。k8s中的Control Plane一般都会运行在Master节点上面。在默认情况下,Master节点并不会运行应用工作负载,所有的应用工作负载都交由Node节点负责。

控制平面中的Master节点主要运行控制平面的各种组件,它们主要的作用就是维持整个k8s集群的正常工作、存储集群的相关信息,同时为集群提供故障转移、负载均衡、任务调度和高可用等功能。对于Master节点一般有多个用于保证高可用,而控制平面中的各个组件均以容器的Pod形式运行在Master节点中,大部分的组件需要在每个Master节点上都运行,少数如DNS服务等组件则只需要保证足够数量的高可用即可。


1.1.1 ectd

ETCD:它是兼具一致性和高可用性的键值key-value数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库,负责保存Kubernetes Cluster的配置信息和各种资源的状态信息,当数据发生变化时,etcd 会快速地通知Kubernetes相关组件。

Kubernetes 集群的 etcd 数据库通常需要有个备份计划。此外还有一种k8s集群部署的高可用方案是将etcd数据库从容器中抽离出来,单独作为一个高可用数据库部署,从而为k8s提供稳定可靠的高可用数据库存储。

Tips:生成环境如果机器配置够高,安装etcd与master安装在一起也OK,也可以单独分离。


1.1.2 kube-apiserver

k8s集群的控制平面的核心是API服务器,而API服务器主要就是由kube-apiserver组件实现的,它被设计为可水平扩展,即通过部署不同数量的实例来进行缩放从而适应不同的流量。API服务器作为整个k8s控制平面的前端,负责提供 HTTP API,以供用户、集群中的不同部分组件和集群外部组件相互通信。(可以通过kubeadm或者kubectl这类的CLI工具来操控API从而控制整个k8s集群,也可以通过其他的Web UI来进行操控)

Tips:工具在背后也是调用 API,包括Web操作。


1.1.3 kube-scheduler

主节点上的组件,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点让 Pod 在上面运行。

调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。


1.1.4 kube-controller-manager

K8S所有Worker Node的监控器。Controller Manager作为集群内部的管理控制中心,运行在Master节点上,是一个永不休止的循环。它实质上是群内的Node、Pod、服务(Server)、端点(Endpoint)、命名空间(Namespace)、服务账号(ServiceAccount)、资源定额(ResourceQuota)的监视与守护进程的合集,每个资源的Controller通过API Server提供的接口实时监控每个资源对象的当前状态,当某个Node意外宕机时,Controller Manager会及时发现并执行自动化修复流程,确保集群始终处于预期的工作状态。

其中控制器包括:

  • 节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应。
  • 副本控制器(Replication Controller): 负责为系统中的每个副本控制器对象维护正确数量的 Pod。
  • 端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入 Service 与 Pod)。
  • 服务帐户和令牌控制器(Service Account & Token Controllers): 为新的命名空间创建默认帐户和 API 访问令牌。


1.1.5 kubelet

K8S中Master节点在每个Worker Node节点上运行的主要“节点代理”,也可以说是Master 的“眼线”。它会定期向Master Node汇报自己Node上运行服务的状态,并接受来自Master Node的指示采取调整措施。负责控制由 K8S 创建的容器的启动停止,保证节点工作正常。


1.1.6 kube-proxy

kube-proxy是集群中每个节点上运行的网络代理,负责Node在K8S的网络通讯、以及对外网络流量的负载均衡。 kube-proxy通过维护主机上的网络规则并执行连接转发,实现了Kubernetes服务抽象。

service在逻辑上代表了后端的多个Pod,外界通过service访问Pod。service接收到的请求就是通过kube-proxy转发到Pod上的,kube-proxy服务负责将访问service的TCP/UDP数据流转发到后端的容器。如果有多个副本,kube-proxy会实现负载均衡。

由于性能问题,目前大部分企业用K8S进行实际生产时,都不会直接使用Kube-proxy作为服务代理,而是通过Ingress Controller来集成HAProxy, Nginx来代替Kube-proxy。


1.2 高可用分析

所有从集群(或所运行的 Pods)发出的 API 调用都终止于 API server,而API Server直接与ETCD数据库通讯。若仅部署单一的API server ,当API server所在的 VM 关机或者 API 服务器崩溃将导致不能停止、更新或者启动新的 Pod、服务或副本控制器;而ETCD存储若发生丢失,API 服务器将不能启动。


所以如下几个方面需要做到:

  1. **集群状态维持:**K8S集群状态信息存储在ETCD集群中,该集群非常可靠,且可以分布在多个节点上。需要注意的是,在ETCD群集中至少应该有3个节点,且为了防止2网络分裂,节点的数量必须为奇数。
  2. **API服务器冗余灾备:**K8S的API server服务器是无状态的,从ETCD集群中能获取所有必要的数据。这意味着K8S集群中可以轻松地运行多个API服务器,而无需要进行协调,因此我们可以把负载均衡器(LB)放在这些服务器之前,使其对用户、Worker Node均透明。
  3. **Master选举:**一些主组件(Scheduler和Controller Manager)不能同时具有多个实例,可以想象多个Scheduler同时进行节点调度会导致多大的混乱。由于Controller Manager等组件通常扮演着一个守护进程的角色,当它自己失败时,K8S将没有更多的手段重新启动它自己,因此必须准备已经启动的组件随时准备取代它。高度可扩展的Kubernetes集群可以让这些组件在领导者选举模式下运行。这意味着虽然多个实例在运行,但是每次只有一个实例是活动的,如果它失败,则另一个实例被选为领导者并代替它。
  4. **K8S高可用:**只要K8S集群关键结点均高可用,则部署在K8S集群中的Pod、Service的高可用性就可以由K8S自行保证。


负载均衡节点设计

负载均衡节点承担着Worker Node集群和Master集群通讯的职责,同时Load Balance没有部署在K8S集群中,不受Controller Manager的监控,倘若Load Balance发生故障,将导致Node与Master的通讯全部中断,因此需要对负载均衡做高可用配置。Load Balance同样不能同时有多个实例在服务,因此使用Keepalived对部署了Load Balance的服务器进行监控,当发生失败时将虚拟IP(VIP)飘移至备份节点,确保集群继续可用。


2. 前期规划及准备

2.1 高可用Kubernetes集群规划

主机规划

主机名

IP地址

说明

k8s-master01 ~ 03

10.0.0.104 ~ 106

master节点 * 3

k8s-master-lb

10.0.0.236

keepalived虚拟IP(不占用机器)

k8s-node01 ~ 02

10.0.0.107 ~ 108

worker节点 * 2


网络规划及版本说明

配置信息

备注

系统版本

CentOS 7.9

Docker版本 (containerd)

20.10.x

Pod网段

172.16.0.0/16

Service网段

192.168.0.0/16

Tips:宿主机网段、K8s Service网段、Pod网段不能重复!


本方案负载均衡(VIP)在Master上,没有单独做负载均衡双机热备。

IP

角色

Hostname

说明

10.0.0.104

Master

k8s-master01

keepalived、haproxy、kube-apiserver、kube-scheduler、kube-controller-manager

10.0.0.105

Master

k8s-master02

keepalived、haproxy、kube-apiserver、kube-scheduler、kube-controller-manager

10.0.0.106

Master

k8s-master03

keepalived、haproxy、kube-apiserver、kube-scheduler、kube-controller-manager

10.0.0.107

Node

k8s-node01

kubelet、kube-proxy

10.0.0.108

Node

k8s-node02

kubelet、kube-proxy

10.0.0.236

Virtual IP(VIP)

k8s-master-lb

各主机hosts解析需要对应加上这一条10.0.0.36 k8s-master-lb


2.2 基本环境配置

centos通过单独安装,非克隆。安装完后进行基本环境的配置,配置一下几个方面:

  1. 设置主机名
  2. 关闭NetworkManager、firewalld、dnsmasq、selinux
  3. 设置eth0
  4. 优化ssh
  5. 设置时区为Asia/Shanghai
  6. 备份并新增清华yum源、epel源、docker-ce源、k8s源
  7. 更新yum源软件包缓存
  8. 修改history格式及记录数
  9. 添加hosts解析
  10. 关闭swap分区
  11. 安装ntpdate服务,并同步时间
  12. 配置limits.conf
  13. 安装必备工具
  14. 升级系统并重启


在/root目录下创建k8s_system_init.sh,复制以下内容。然后sh /root/k8s_system_init.sh进行基本环境的配置。

此步骤Master及Node节点都需进行!

#!/bin/bash
if [ $# -eq 2 ];then
  echo "设置主机名为:$1"
  echo "eth0设置IP地址为:10.0.0.$2"
else
  echo  "使用方法:sh $0 主机名 主机位"
  exit 2
fi

echo "--------------------------------------"
echo "1.正在设置主机名:$1"
hostnamectl set-hostname $1


echo "2.正在关闭NetworkManager、firewalld、dnsmasq、selinux"
systemctl disable firewalld &> /dev/null
systemctl disable NetworkManager &> /dev/null
systemctl disable dnsmasq &> /dev/null
systemctl stop firewalld
systemctl stop NetworkManager
systemctl stop dnsmasq
sed -i "s#SELINUX=enforcing#SELINUX=disabled#g" /etc/selinux/config
setenforce 0


echo "3.正在设置eth0:10.0.0.$2"
cat > /etc/sysconfig/network-scripts/ifcfg-eth0 <<EOF
TYPE=Ethernet
BOOTPROTO=static
DEFROUTE=yes
NAME=eth0
DEVICE=eth0
ONBOOT=yes
IPADDR=10.0.0.$2
NETMASK=255.255.255.0
GATEWAY=10.0.0.2
DNS1=114.114.114.114
EOF
systemctl restart network


echo "4.优化ssh"
sed -i "s#\#UseDNS yes#UseDNS no#g" /etc/ssh/sshd_config
sed -i "s#GSSAPIAuthentication yes#GSSAPIAuthentication no#g" /etc/ssh/sshd_config
systemctl restart sshd


echo "5.设置时区为Asia/Shanghai"
timedatectl set-timezone Asia/Shanghai


echo "6.备份并新增清华yum源、epel源、docker-ce源、k8s源"
cd /etc/yum.repos.d/
mkdir bak ; mv *.repo bak
cat > /etc/yum.repos.d/Centos-Base.repo <<EOF
[base]
name=CentOS-$releasever - Base
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/\$releasever/os/\$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

[updates]
name=CentOS-$releasever - Updates
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/\$releasever/updates/\$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

[extras]
name=CentOS-$releasever - Extras
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/\$releasever/extras/\$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

[centosplus]
name=CentOS-$releasever - Plus
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/\$releasever/centosplus/\$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
EOF

cat > /etc/yum.repos.d/epel.repo <<EOF
[epel]
name=Extra Packages for Enterprise Linux 7 - \$basearch
baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/7/\$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7

[epel-debuginfo]
name=Extra Packages for Enterprise Linux 7 - \$basearch - Debug
baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/7/\$basearch/debug
failovermethod=priority
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
gpgcheck=1

[epel-source]
name=Extra Packages for Enterprise Linux 7 - \$basearch - Source
baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/7/SRPMS
failovermethod=priority
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
gpgcheck=1
EOF

cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[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-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo  &> /dev/null
sed -i 's+https://download.docker.com+https://mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo

echo "7.更新yum源软件包缓存"
yum makecache


echo "8.修改history格式及记录数"
sed -i "s#HISTSIZE=1000##g" /etc/profile
cat >> /etc/profile <<EOF
shopt -s histappend
USER_IP=`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'`
export HISTFILE=~/.commandline_warrior
export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S  `whoami`@${USER_IP}: "
export HISTSIZE=200000
export HISTFILESIZE=1000000
export PROMPT_COMMAND="history -a"
EOF
source /etc/profile


echo "9.添加hosts解析"
cat >> /etc/hosts <<EOF
10.0.0.104 k8s-master01
10.0.0.105 k8s-master02
10.0.0.106 k8s-master03
10.0.0.236 k8s-master-lb
10.0.0.107 k8s-node01
10.0.0.108 k8s-node02
EOF


echo "10.关闭swap分区"
swapoff -a && sysctl -w vm.swappiness=0 &> /dev/null
sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab


echo "11.安装ntpdate服务,并同步时间"
yum install ntpdate -y &> /dev/null
systemctl enabled ntpdate &> /dev/null
systemctl start ntpdate
echo "*/10 * * * * root /usr/sbin/ntpdate ntp1.aliyun.com >/dev/null 2>&1" > /etc/cron.d/ntp_sync


echo "12.配置limits.conf"
ulimit -SHn 65535
cat >> /etc/security/limits.conf <<EOF
* soft nofile 65536
* hard nofile 131072
* soft nproc 65535
* hard nproc 655350
* soft memlock unlimited
* hard memlock unlimited
EOF


echo "13.必备工具安装"
yum install wget jq psmisc vim net-tools telnet yum-utils device-mapper-persistent-data lvm2 git -y &> /dev/null


echo "14.升级系统并重启"
yum update -y --exclude=kernel* && reboot


2.3 内核及ipvs模块配置

此步骤是升级内核、配置ipvs模块,开启一些k8s集群中必须的内核参数。配置一下几个方面:

  1. 下载安装包到/server/soft
  2. 安装kernel
  3. 更改内核启动顺序
  4. 安装ipvsadm
  5. 配置ipvs模块
  6. 开启k8s集群必须的内核参数
  7. 配置完内核,重启服务器


在/root目录下创建kernel_update.sh,复制以下内容。然后sh /root/kernel_update.sh进行基本环境的配置。

此步骤Master及Node节点都需进行!

#!/bin/bash
echo "1.下载安装包到/server/soft"
mkdir -p /server/soft ; cd /server/soft
wget http://193.49.22.109/elrepo/kernel/el7/x86_64/RPMS/kernel-ml-devel-4.19.12-1.el7.elrepo.x86_64.rpm
wget http://193.49.22.109/elrepo/kernel/el7/x86_64/RPMS/kernel-ml-4.19.12-1.el7.elrepo.x86_64.rpm


echo "2.正在安装kernel"
yum localinstall -y kernel-ml*


echo "3.更改内核启动顺序"
grub2-set-default  0 && grub2-mkconfig -o /etc/grub2.cfg
grubby --args="user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"


echo "4.输出现在内核版本信息"
grubby --default-kernel


echo "5.安装ipvsadm"
yum install ipvsadm ipset sysstat conntrack libseccomp -y &> /dev/null


echo "6.配置ipvs模块"
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack

cat >> /etc/modules-load.d/ipvs.conf <<EOF
ip_vs
ip_vs_lc
ip_vs_wlc
ip_vs_rr
ip_vs_wrr
ip_vs_lblc
ip_vs_lblcr
ip_vs_dh
ip_vs_sh
ip_vs_fo
ip_vs_nq
ip_vs_sed
ip_vs_ftp
ip_vs_sh
nf_conntrack
ip_tables
ip_set
xt_set
ipt_set
ipt_rpfilter
ipt_REJECT
ipip
EOF
systemctl enable --now systemd-modules-load.service &> /dev/null


echo "7.开启k8s集群必须的内核参数"
cat <<EOF > /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
fs.may_detach_mounts = 1
net.ipv4.conf.all.route_localnet = 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.netfilter.nf_conntrack_max=2310720

net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_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.tcp_timestamps = 0
net.core.somaxconn = 16384
EOF
sysctl --system


echo "8.配置完内核,重启服务器!"
reboot


2.4 检查ipvs加载、内核版本验证

lsmod | grep --color=auto -e ip_vs -e nf_conntrack

二进制安装高可用k8s 1.27.x_二进制安装k8s_02


uname -a

二进制安装高可用k8s 1.27.x_k8s安装_03


2.5 高可用组件安装
2.5.1 HAproxy配置

所有Master节点安装Keepalived、HAproxy

yum install keepalived haproxy -y


所有Master节点配置HAProxy,所有Master节点的HAProxy配置相同。

# cat /etc/haproxy/haproxy.cfg
global
  maxconn  2000
  ulimit-n  16384
  log  127.0.0.1 local0 err
  stats timeout 30s

defaults
  log global
  mode  http
  option  httplog
  timeout connect 5000
  timeout client  50000
  timeout server  50000
  timeout http-request 15s
  timeout http-keep-alive 15s

frontend monitor-in
  bind *:33305
  mode http
  option httplog
  monitor-uri /monitor

frontend k8s-master
  bind 0.0.0.0:16443
  bind 127.0.0.1:16443
  mode tcp
  option tcplog
  tcp-request inspect-delay 5s
  default_backend k8s-master

backend k8s-master
  mode tcp
  option tcplog
  option tcp-check
  balance roundrobin
  default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
  server k8s-master01   10.0.0.104:6443  check
  server k8s-master02   10.0.0.105:6443  check
  server k8s-master03   10.0.0.106:6443  check


2.5.2 Keepalived配置

所有Master节点配置Keepalived,以下三个Master节点配置注意ip和网卡。

Master01配置

[root@k8s-master01 ~]# vim /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
global_defs {
    router_id LVS_DEVEL
script_user root
    enable_script_security
}
vrrp_script chk_apiserver {
    script "/etc/keepalived/check_apiserver.sh"
    interval 5
    weight -5
    fall 2  
rise 1
}
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    mcast_src_ip 10.0.0.104
    virtual_router_id 51
    priority 101
    advert_int 2
    authentication {
        auth_type PASS
        auth_pass K8SHA_KA_AUTH
    }
    virtual_ipaddress {
        10.0.0.236
    }
    track_script {
       chk_apiserver
    }
}


Master02配置

[root@k8s-master02 ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
    router_id LVS_DEVEL
script_user root
    enable_script_security
}
vrrp_script chk_apiserver {
    script "/etc/keepalived/check_apiserver.sh"
   interval 5
    weight -5
    fall 2
rise 1
}
vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    mcast_src_ip 10.0.0.105
    virtual_router_id 51
    priority 100
    advert_int 2
    authentication {
        auth_type PASS
        auth_pass K8SHA_KA_AUTH
    }
    virtual_ipaddress {
        10.0.0.236
    }
    track_script {
       chk_apiserver
    }
}


Master03配置

[root@k8s-master03 ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
    router_id LVS_DEVEL
script_user root
    enable_script_security
}
vrrp_script chk_apiserver {
    script "/etc/keepalived/check_apiserver.sh"
 interval 5
    weight -5
    fall 2
rise 1
}
vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    mcast_src_ip 10.0.0.106
    virtual_router_id 51
    priority 100
    advert_int 2
    authentication {
        auth_type PASS
        auth_pass K8SHA_KA_AUTH
    }
    virtual_ipaddress {
        10.0.0.236
    }
    track_script {
       chk_apiserver
    }
}


所有Master节点配置Keepalived健康检查文件

#cat /etc/keepalived/check_apiserver.sh

#!/bin/bash

err=0
for k in $(seq 1 3)
do
    check_code=$(pgrep haproxy)
    if [[ $check_code == "" ]]; then
        err=$(expr $err + 1)
        sleep 1
        continue
    else
        err=0
        break
    fi
done

if [[ $err != "0" ]]; then
    echo "systemctl stop keepalived"
    /usr/bin/systemctl stop keepalived
    exit 1
else
    exit 0
fi


赋予执行权限

chmod +x /etc/keepalived/check_apiserver.sh


所有Master节点启动haproxy和keepalived,并设置开机自启动。

systemctl daemon-reload
systemctl enable --now haproxy
systemctl enable --now keepalived


2.5.3 测试VIP及HAproxy端口

所有节点测试VIP

#ping 10.0.0.236 -c 2
PING 10.0.0.236 (10.0.0.236) 56(84) bytes of data.
64 bytes from 10.0.0.236: icmp_seq=1 ttl=64 time=0.067 ms
64 bytes from 10.0.0.236: icmp_seq=2 ttl=64 time=0.061 ms


随便一台telnet VIP 16443端口,显示^]就说明端口开放的。

[root@k8s-master01 ~]# telnet 10.0.0.236 16443
Trying 10.0.0.236...
Connected to 10.0.0.236.
Escape character is '^]'.
Connection closed by foreign host.


2.5.4 故障解决
  1. 所有节点查看防火墙状态必须为disable和inactive:systemctl status firewalld
  2. 所有节点查看selinux状态,必须为disable:getenforce
  3. 如果ping不通且telnet没有出现 ] ,VIP没起来,不可在继续往下执行,需要排查keepalived的问题,比如防火墙和selinux,haproxy和keepalived的状态,监听端口等。

master节点查看haproxy和keepalived状态:systemctl status keepalived haproxy

master节点查看监听端口:netstat -lntp


3. k8s集群安装

Master01节点进行拉取k8s-ha-install仓库文件,切换到1.27.x分支(其他版本可以切换到其他分支,.x即可,不需要更改为具体的小版本)

cd /root/ ; git clone https://gitee.com/dukuan/k8s-ha-install.git
cd /root/k8s-ha-install && git checkout manual-installation-v1.27.x


配置免密,安装sshpass

yum install sshpass -y


新建一个fenfa_pub.sh,内容如下:

#!/bin/bash
#desc:一键自动化创建和分发密钥
#ip_list填写除了Master01的其余所有节点
ip_list="10.0.0.105 10.0.0.106 10.0.0.107 10.0.0.108"
ssh_root_pass="123456"
echo '-----------------------------------'
echo '1.创建key'
echo '-----------------------------------'

ssh-keygen -f ~/.ssh/id_rsa -P ''

echo '-----------------------------------'
echo '2.分发pub key'


for ip in $ip_list
do
  sshpass -p$ssh_root_pass ssh-copy-id -i ~/.ssh/id_rsa.pub -o StrictHostKeyChecking=no root@$ip
done

echo '-----------------------------------'
echo '3.已完成分发!'


运行脚本即可

[root@k8s-master01 ~]# sh fenfa_pub.sh


3.1 安装Containerd并配置

如果k8s安装的版本低于1.24,选择Docker和Containerd均可,高于1.24选择Containerd作为Runtime。(所有节点均需安装)

#此处直接安装docker-ce是因为docker会自带把Containerd装好,因为可能后续还会用到docker,再重新安装docker可能会出现问题,影响集群。
yum install docker-ce-20.10.* docker-ce-cli-20.10.* -y

#如果确定不安装Docker那就直接
yum install containerd.io -y

Tips:可以无需启动Docker,只需要配置和启动Containerd即可。


配置Containerd所需的模块**(所有节点均需配置)**

cat <<EOF | tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF


加载模块**(所有节点均需配置)**

modprobe -- overlay
modprobe -- br_netfilter


配置Containerd所需的内核**(所有节点均需配置)**

cat <<EOF | tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF


加载内核**(所有节点均需配置)**

sysctl --system


配置Containerd的配置文件**(所有节点均需配置)**

#从 containerd 的默认配置中获取配置信息,并将其复制到 /etc/containerd/config.toml 文件中
containerd config default | tee /etc/containerd/config.toml


将Containerd的Cgroup改为Systemd**(所有节点均需配置)**

找到containerd.runtimes.runc.options,添加或修改SystemdCgroup = true**(如果已存在直接修改,否则会报错)**

二进制安装高可用k8s 1.27.x_二进制安装k8s_04


将sandbox_image的Pause镜像改成符合自己版本的地址registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6**(所有节点均需配置)**

二进制安装高可用k8s 1.27.x_kubernetes_05


启动Containerd,并配置开机自启动**(所有节点均需配置)**

systemctl daemon-reload
systemctl enable --now containerd


配置crictl客户端连接的运行时位置**(所有节点均需配置)**

crictl 是一个用于与容器运行时通信的命令行工具,可以使用它管理和操作容器运行时中的容器。为了与容器运行时进行交互,crictl需要知道容器运行时的位置。

通过配置运行时位置,可以灵活地切换和管理不同的容器运行时。你可以使用不同的容器运行时(如 containerd、Docker、cri-o等)来满足不同的环境需求和偏好,同时仍然能够使用统一的 crictl客户端进行管理。

cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF


3.2 k8s及etcd安装

Master01节点下载kubernetes安装包

wget https://dl.k8s.io/v1.27.3/kubernetes-server-linux-amd64.tar.gz


下载etcd安装包

[root@k8s-master01 ~]# wget https://github.com/etcd-io/etcd/releases/download/v3.5.7/etcd-v3.5.7-linux-amd64.tar.gz


解压kubernetes安装文件

[root@k8s-master01 ~]# tar -xf kubernetes-server-linux-amd64.tar.gz --strip-components=3 -C /usr/local/bin kubernetes/server/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy}


解压etcd安装文件

[root@k8s-master01 ~]# tar -zxvf etcd-v3.5.7-linux-amd64.tar.gz --strip-components=1 -C /usr/local/bin etcd-v3.5.7-linux-amd64/etcd{,ctl}


版本查看

[root@k8s-master01 ~]# kubelet --version
Kubernetes v1.27.3

[root@k8s-master01 ~]# etcdctl version
etcdctl version: 3.5.7
API version: 3.5


将组件发送到其他节点

MasterNodes='k8s-master02 k8s-master03'
WorkNodes='k8s-node01 k8s-node02'

for NODE in $MasterNodes;
do echo $NODE;
scp /usr/local/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy} $NODE:/usr/local/bin/;
scp /usr/local/bin/etcd* $NODE:/usr/local/bin/;
done

for NODE in $WorkNodes;
do
scp /usr/local/bin/kube{let,-proxy} $NODE:/usr/local/bin/;
done


3.3 生成证书

Master01下载生成证书工具(wget不下来的话就得自行下载并移至相关目录)

wget "https://pkg.cfssl.org/R1.2/cfssl_linux-amd64" -O /usr/local/bin/cfssl
wget "https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64" -O /usr/local/bin/cfssljson
chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson


3.3.1 生成etcd证书

etcd集群内部通讯、api server连接etcd需要证书。(Node节点无etcd,不需要在Node节点上进行)

所有Master节点创建etcd证书目录

mkdir -p /etc/etcd/ssl


所有节点创建kubernetes相关目录

mkdir -p /etc/kubernetes/pki


Master01节点生成etcd证书,生成证书的CSR文件:证书签名请求文件,配置了一些域名、公司、单位

cd /root/k8s-ha-install/pki

#生成etcd CA证书和CA证书的key
cfssl gencert -initca etcd-ca-csr.json | cfssljson -bare /etc/etcd/ssl/etcd-ca

cfssl gencert \
   -ca=/etc/etcd/ssl/etcd-ca.pem \
   -ca-key=/etc/etcd/ssl/etcd-ca-key.pem \
   -config=ca-config.json \
   -hostname=127.0.0.1,k8s-master01,k8s-master02,k8s-master03,10.0.0.104,10.0.0.105,10.0.0.106 \
   -profile=kubernetes \
   etcd-csr.json | cfssljson -bare /etc/etcd/ssl/etcd

二进制安装高可用k8s 1.27.x_kubernetes_06


将证书复制到其他Master节点

MasterNodes='k8s-master02 k8s-master03'
for NODE in $MasterNodes; do
     ssh $NODE "mkdir -p /etc/etcd/ssl"
     for FILE in etcd-ca-key.pem  etcd-ca.pem  etcd-key.pem  etcd.pem; do
       scp /etc/etcd/ssl/${FILE} $NODE:/etc/etcd/ssl/${FILE}
     done
 done


3.3.2 生成k8s组件证书

生成k8s的CA证书

cd /root/k8s-ha-install/pki
cfssl gencert -initca ca-csr.json | cfssljson -bare /etc/kubernetes/pki/ca


生成apiserver的证书**(192.168.0.1是service网段的第一个IP地址)**

cfssl gencert   -ca=/etc/kubernetes/pki/ca.pem   -ca-key=/etc/kubernetes/pki/ca-key.pem   -config=ca-config.json   -hostname=192.168.0.1,10.0.0.236,127.0.0.1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster,kubernetes.default.svc.cluster.local,10.0.0.104,10.0.0.105,10.0.0.106   -profile=kubernetes   apiserver-csr.json | cfssljson -bare /etc/kubernetes/pki/apiserver


生成apiserver的聚合证书

cfssl gencert   -initca front-proxy-ca-csr.json | cfssljson -bare /etc/kubernetes/pki/front-proxy-ca 

cfssl gencert   -ca=/etc/kubernetes/pki/front-proxy-ca.pem   -ca-key=/etc/kubernetes/pki/front-proxy-ca-key.pem   -config=ca-config.json   -profile=kubernetes   front-proxy-client-csr.json | cfssljson -bare /etc/kubernetes/pki/front-proxy-client


生成controller-manager的证书

cfssl gencert \
   -ca=/etc/kubernetes/pki/ca.pem \
   -ca-key=/etc/kubernetes/pki/ca-key.pem \
   -config=ca-config.json \
   -profile=kubernetes \
   manager-csr.json | cfssljson -bare /etc/kubernetes/pki/controller-manager


配置 Kubernetes 集群的连接信息

# set-cluster:设置一个集群项,

kubectl config set-cluster kubernetes \
     --certificate-authority=/etc/kubernetes/pki/ca.pem \
     --embed-certs=true \
     --server=https://10.0.0.236:16443 \
     --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig

# 设置一个环境项,一个上下文
kubectl config set-context system:kube-controller-manager@kubernetes \
    --cluster=kubernetes \
    --user=system:kube-controller-manager \
    --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig

# set-credentials 设置一个用户项

kubectl config set-credentials system:kube-controller-manager \
     --client-certificate=/etc/kubernetes/pki/controller-manager.pem \
     --client-key=/etc/kubernetes/pki/controller-manager-key.pem \
     --embed-certs=true \
     --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig


# 使用某个环境当做默认环境

kubectl config use-context system:kube-controller-manager@kubernetes \
     --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig


生成scheduler的证书

cfssl gencert \
   -ca=/etc/kubernetes/pki/ca.pem \
   -ca-key=/etc/kubernetes/pki/ca-key.pem \
   -config=ca-config.json \
   -profile=kubernetes \
   scheduler-csr.json | cfssljson -bare /etc/kubernetes/pki/scheduler


配置 Kubernetes 调度器(scheduler)的连接信息

kubectl config set-cluster kubernetes \
     --certificate-authority=/etc/kubernetes/pki/ca.pem \
     --embed-certs=true \
     --server=https://10.0.0.236:16443 \
     --kubeconfig=/etc/kubernetes/scheduler.kubeconfig


kubectl config set-credentials system:kube-scheduler \
     --client-certificate=/etc/kubernetes/pki/scheduler.pem \
     --client-key=/etc/kubernetes/pki/scheduler-key.pem \
     --embed-certs=true \
     --kubeconfig=/etc/kubernetes/scheduler.kubeconfig

kubectl config set-context system:kube-scheduler@kubernetes \
     --cluster=kubernetes \
     --user=system:kube-scheduler \
     --kubeconfig=/etc/kubernetes/scheduler.kubeconfig


kubectl config use-context system:kube-scheduler@kubernetes \
     --kubeconfig=/etc/kubernetes/scheduler.kubeconfig


生成一个用于管理员的证书和私钥

cfssl gencert \
   -ca=/etc/kubernetes/pki/ca.pem \
   -ca-key=/etc/kubernetes/pki/ca-key.pem \
   -config=ca-config.json \
   -profile=kubernetes \
   admin-csr.json | cfssljson -bare /etc/kubernetes/pki/admin


配置Kubernetes集群的身份验证和访问信息

kubectl config set-cluster kubernetes  \
--certificate-authority=/etc/kubernetes/pki/ca.pem \
--embed-certs=true  \
--server=https://10.0.0.236:16443  \
--kubeconfig=/etc/kubernetes/admin.kubeconfig

kubectl config set-credentials kubernetes-admin  \
--client-certificate=/etc/kubernetes/pki/admin.pem  \
--client-key=/etc/kubernetes/pki/admin-key.pem  \
--embed-certs=true  \
--kubeconfig=/etc/kubernetes/admin.kubeconfig

kubectl config set-context kubernetes-admin@kubernetes \
--cluster=kubernetes  \
--user=kubernetes-admin  \
--kubeconfig=/etc/kubernetes/admin.kubeconfig

kubectl config use-context kubernetes-admin@kubernetes \
--kubeconfig=/etc/kubernetes/admin.kubeconfig


创建ServiceAccount Key --> secret

openssl genrsa -out /etc/kubernetes/pki/sa.key 2048

openssl rsa -in /etc/kubernetes/pki/sa.key -pubout -out /etc/kubernetes/pki/sa.pub


查看证书文件,要有23个。

二进制安装高可用k8s 1.27.x_k8s安装_07


将证书复制到其他Master节点

for NODE in k8s-master02 k8s-master03; do 
  for FILE in $(ls /etc/kubernetes/pki | grep -v etcd); do 
    scp /etc/kubernetes/pki/${FILE} $NODE:/etc/kubernetes/pki/${FILE};
  done; 
  for FILE in admin.kubeconfig controller-manager.kubeconfig scheduler.kubeconfig; do 
    scp /etc/kubernetes/${FILE} $NODE:/etc/kubernetes/${FILE};
  done;
done


3.4 etcd、k8s高可用集群部署
3.4.1 etcd配置

etcd配置大致相同,注意修改每个Master节点的etcd配置的主机名和IP地址。


3.4.1.1 修改配置文件

Master01节点

[root@k8s-master01 pki]# cat /etc/etcd/etcd.config.yml
name: 'k8s-master01'
data-dir: /var/lib/etcd
wal-dir: /var/lib/etcd/wal
snapshot-count: 5000
heartbeat-interval: 100
election-timeout: 1000
quota-backend-bytes: 0
listen-peer-urls: 'https://10.0.0.104:2380'
listen-client-urls: 'https://10.0.0.104:2379,http://127.0.0.1:2379'
max-snapshots: 3
max-wals: 5
cors:
initial-advertise-peer-urls: 'https://10.0.0.104:2380'
advertise-client-urls: 'https://10.0.0.104:2379'
discovery:
discovery-fallback: 'proxy'
discovery-proxy:
discovery-srv:
initial-cluster: 'k8s-master01=https://10.0.0.104:2380,k8s-master02=https://10.0.0.105:2380,k8s-master03=https://10.0.0.106:2380'
initial-cluster-token: 'etcd-k8s-cluster'
initial-cluster-state: 'new'
strict-reconfig-check: false
enable-v2: true
enable-pprof: true
proxy: 'off'
proxy-failure-wait: 5000
proxy-refresh-interval: 30000
proxy-dial-timeout: 1000
proxy-write-timeout: 5000
proxy-read-timeout: 0
client-transport-security:
  cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  client-cert-auth: true
  trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  auto-tls: true
peer-transport-security:
  cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  peer-client-cert-auth: true
  trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  auto-tls: true
debug: false
log-package-levels:
log-outputs: [default]
force-new-cluster: false


Master02节点

[root@k8s-master02 ~]# cat /etc/etcd/etcd.config.yml
name: 'k8s-master02'
data-dir: /var/lib/etcd
wal-dir: /var/lib/etcd/wal
snapshot-count: 5000
heartbeat-interval: 100
election-timeout: 1000
quota-backend-bytes: 0
listen-peer-urls: 'https://10.0.0.105:2380'
listen-client-urls: 'https://10.0.0.105:2379,http://127.0.0.1:2379'
max-snapshots: 3
max-wals: 5
cors:
initial-advertise-peer-urls: 'https://10.0.0.105:2380'
advertise-client-urls: 'https://10.0.0.105:2379'
discovery:
discovery-fallback: 'proxy'
discovery-proxy:
discovery-srv:
initial-cluster: 'k8s-master01=https://10.0.0.104:2380,k8s-master02=https://10.0.0.105:2380,k8s-master03=https://10.0.0.106:2380'
initial-cluster-token: 'etcd-k8s-cluster'
initial-cluster-state: 'new'
strict-reconfig-check: false
enable-v2: true
enable-pprof: true
proxy: 'off'
proxy-failure-wait: 5000
proxy-refresh-interval: 30000
proxy-dial-timeout: 1000
proxy-write-timeout: 5000
proxy-read-timeout: 0
client-transport-security:
  cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  client-cert-auth: true
  trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  auto-tls: true
peer-transport-security:
  cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  peer-client-cert-auth: true
  trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  auto-tls: true
debug: false
log-package-levels:
log-outputs: [default]
force-new-cluster: false


Master03节点

[root@k8s-master03 ~]# cat /etc/etcd/etcd.config.yml
name: 'k8s-master03'
data-dir: /var/lib/etcd
wal-dir: /var/lib/etcd/wal
snapshot-count: 5000
heartbeat-interval: 100
election-timeout: 1000
quota-backend-bytes: 0
listen-peer-urls: 'https://10.0.0.106:2380'
listen-client-urls: 'https://10.0.0.106:2379,http://127.0.0.1:2379'
max-snapshots: 3
max-wals: 5
cors:
initial-advertise-peer-urls: 'https://10.0.0.106:2380'
advertise-client-urls: 'https://10.0.0.106:2379'
discovery:
discovery-fallback: 'proxy'
discovery-proxy:
discovery-srv:
initial-cluster: 'k8s-master01=https://10.0.0.104:2380,k8s-master02=https://10.0.0.105:2380,k8s-master03=https://10.0.0.106:2380'
initial-cluster-token: 'etcd-k8s-cluster'
initial-cluster-state: 'new'
strict-reconfig-check: false
enable-v2: true
enable-pprof: true
proxy: 'off'
proxy-failure-wait: 5000
proxy-refresh-interval: 30000
proxy-dial-timeout: 1000
proxy-write-timeout: 5000
proxy-read-timeout: 0
client-transport-security:
  cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  client-cert-auth: true
  trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  auto-tls: true
peer-transport-security:
  cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  peer-client-cert-auth: true
  trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  auto-tls: true
debug: false
log-package-levels:
log-outputs: [default]
force-new-cluster: false


3.4.1.2 创建systemd管理文件

所有Master节点创建etcd.service并启动

# cat /usr/lib/systemd/system/etcd.service
[Unit]
Description=Etcd Service
Documentation=https://coreos.com/etcd/docs/latest/
After=network.target

[Service]
Type=notify
ExecStart=/usr/local/bin/etcd --config-file=/etc/etcd/etcd.config.yml
Restart=on-failure
RestartSec=10
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
Alias=etcd3.service


3.4.1.3 创建证书目录并启动

所有Master节点创建etcd的证书目录

mkdir /etc/kubernetes/pki/etcd
ln -s /etc/etcd/ssl/* /etc/kubernetes/pki/etcd/

systemctl daemon-reload
systemctl enable --now etcd


查看etcd状态,没问题!

export ETCDCTL_API=3
etcdctl --endpoints="10.0.0.106:2379,10.0.0.105:2379,10.0.0.104:2379" --cacert=/etc/kubernetes/pki/etcd/etcd-ca.pem --cert=/etc/kubernetes/pki/etcd/etcd.pem --key=/etc/kubernetes/pki/etcd/etcd-key.pem  endpoint status --write-out=table

二进制安装高可用k8s 1.27.x_k8s安装_08

Tips:如果没出现上图一样的情况,请排查 tail -f /var/log/messages


3.4.2 apiserver配置

所有Master节点创建kube-apiserver service


Master01节点

[root@k8s-master01 pki]# cat /usr/lib/systemd/system/kube-apiserver.service                                       [Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-apiserver \
      --v=2  \
      --allow-privileged=true  \
      --bind-address=0.0.0.0  \
      --secure-port=6443  \
      --advertise-address=10.0.0.104 \
      --service-cluster-ip-range=192.168.0.0/16  \
      --service-node-port-range=30000-32767  \
      --etcd-servers=https://10.0.0.104:2379,https://10.0.0.105:2379,https://10.0.0.106:2379 \
      --etcd-cafile=/etc/etcd/ssl/etcd-ca.pem  \
      --etcd-certfile=/etc/etcd/ssl/etcd.pem  \
      --etcd-keyfile=/etc/etcd/ssl/etcd-key.pem  \
      --client-ca-file=/etc/kubernetes/pki/ca.pem  \
      --tls-cert-file=/etc/kubernetes/pki/apiserver.pem  \
      --tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem  \
      --kubelet-client-certificate=/etc/kubernetes/pki/apiserver.pem  \
      --kubelet-client-key=/etc/kubernetes/pki/apiserver-key.pem  \
      --service-account-key-file=/etc/kubernetes/pki/sa.pub  \
      --service-account-signing-key-file=/etc/kubernetes/pki/sa.key  \
      --service-account-issuer=https://kubernetes.default.svc.cluster.local \
      --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname  \
      --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota  \
      --authorization-mode=Node,RBAC  \
      --enable-bootstrap-token-auth=true  \
      --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem  \
      --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.pem  \
      --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client-key.pem  \
      --requestheader-allowed-names=aggregator  \
      --requestheader-group-headers=X-Remote-Group  \
      --requestheader-extra-headers-prefix=X-Remote-Extra-  \
      --requestheader-username-headers=X-Remote-User
      # --token-auth-file=/etc/kubernetes/token.csv

Restart=on-failure
RestartSec=10s
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target


Master02节点

[root@k8s-master02 ~]# cat /usr/lib/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-apiserver \
      --v=2  \
      --allow-privileged=true  \
      --bind-address=0.0.0.0  \
      --secure-port=6443  \
      --advertise-address=10.0.0.105 \
      --service-cluster-ip-range=192.168.0.0/16  \
      --service-node-port-range=30000-32767  \
      --etcd-servers=https://10.0.0.104:2379,https://10.0.0.105:2379,https://10.0.0.106:2379 \
      --etcd-cafile=/etc/etcd/ssl/etcd-ca.pem  \
      --etcd-certfile=/etc/etcd/ssl/etcd.pem  \
      --etcd-keyfile=/etc/etcd/ssl/etcd-key.pem  \
      --client-ca-file=/etc/kubernetes/pki/ca.pem  \
      --tls-cert-file=/etc/kubernetes/pki/apiserver.pem  \
      --tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem  \
      --kubelet-client-certificate=/etc/kubernetes/pki/apiserver.pem  \
      --kubelet-client-key=/etc/kubernetes/pki/apiserver-key.pem  \
      --service-account-key-file=/etc/kubernetes/pki/sa.pub  \
      --service-account-signing-key-file=/etc/kubernetes/pki/sa.key  \
      --service-account-issuer=https://kubernetes.default.svc.cluster.local \
      --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname  \
      --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota  \
      --authorization-mode=Node,RBAC  \
      --enable-bootstrap-token-auth=true  \
      --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem  \
      --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.pem  \
      --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client-key.pem  \
      --requestheader-allowed-names=aggregator  \
      --requestheader-group-headers=X-Remote-Group  \
      --requestheader-extra-headers-prefix=X-Remote-Extra-  \
      --requestheader-username-headers=X-Remote-User

Restart=on-failure
RestartSec=10s
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target


Master03节点

[root@k8s-master03 ~]# cat /usr/lib/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-apiserver \
      --v=2  \
      --allow-privileged=true  \
      --bind-address=0.0.0.0  \
      --secure-port=6443  \
      --advertise-address=10.0.0.106 \
      --service-cluster-ip-range=192.168.0.0/16  \
      --service-node-port-range=30000-32767  \
      --etcd-servers=https://10.0.0.104:2379,https://10.0.0.105:2379,https://10.0.0.106:2379 \
      --etcd-cafile=/etc/etcd/ssl/etcd-ca.pem  \
      --etcd-certfile=/etc/etcd/ssl/etcd.pem  \
      --etcd-keyfile=/etc/etcd/ssl/etcd-key.pem  \
      --client-ca-file=/etc/kubernetes/pki/ca.pem  \
      --tls-cert-file=/etc/kubernetes/pki/apiserver.pem  \
      --tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem  \
      --kubelet-client-certificate=/etc/kubernetes/pki/apiserver.pem  \
      --kubelet-client-key=/etc/kubernetes/pki/apiserver-key.pem  \
      --service-account-key-file=/etc/kubernetes/pki/sa.pub  \
      --service-account-signing-key-file=/etc/kubernetes/pki/sa.key  \
      --service-account-issuer=https://kubernetes.default.svc.cluster.local \
      --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname  \
      --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota  \
      --authorization-mode=Node,RBAC  \
      --enable-bootstrap-token-auth=true  \
      --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem  \
      --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.pem  \
      --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client-key.pem  \
      --requestheader-allowed-names=aggregator  \
      --requestheader-group-headers=X-Remote-Group  \
      --requestheader-extra-headers-prefix=X-Remote-Extra-  \
      --requestheader-username-headers=X-Remote-User
      # --token-auth-file=/etc/kubernetes/token.csv

Restart=on-failure
RestartSec=10s
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target


启动apiserver,所有Master节点开启kube-apiserver

systemctl daemon-reload && systemctl enable --now kube-apiserver


检测kube-apiserver状态

systemctl status kube-apiserver


3.4.3 Controller Manager配置

所有Master节点配置kube-controller-manager service**(所有Master节点配置一样)**

# vim /usr/lib/systemd/system/kube-controller-manager.service

[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-controller-manager \
      --v=2 \
      --root-ca-file=/etc/kubernetes/pki/ca.pem \
      --cluster-signing-cert-file=/etc/kubernetes/pki/ca.pem \
      --cluster-signing-key-file=/etc/kubernetes/pki/ca-key.pem \
      --service-account-private-key-file=/etc/kubernetes/pki/sa.key \
      --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig \
      --authentication-kubeconfig=/etc/kubernetes/controller-manager.kubeconfig \
      --authorization-kubeconfig=/etc/kubernetes/controller-manager.kubeconfig \
      --leader-elect=true \
      --use-service-account-credentials=true \
      --node-monitor-grace-period=40s \
      --node-monitor-period=5s \
      --controllers=*,bootstrapsigner,tokencleaner \
      --allocate-node-cidrs=true \
      --cluster-cidr=172.16.0.0/16 \
      --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem \
      --node-cidr-mask-size=24
      
Restart=always
RestartSec=10s

[Install]
WantedBy=multi-user.target


所有Master节点启动kube-controller-manager

systemctl daemon-reload
systemctl enable --now kube-controller-manager


查看启动状态

systemctl  status kube-controller-manager


3.4.4 Scheduler配置

所有Master节点配置kube-scheduler service**(所有Master节点配置一样)**

# vim /usr/lib/systemd/system/kube-scheduler.service

[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-scheduler \
      --v=2 \
      --leader-elect=true \
      --authentication-kubeconfig=/etc/kubernetes/scheduler.kubeconfig \
      --authorization-kubeconfig=/etc/kubernetes/scheduler.kubeconfig \
      --kubeconfig=/etc/kubernetes/scheduler.kubeconfig

Restart=always
RestartSec=10s

[Install]
WantedBy=multi-user.target


所有Master节点启动kube-scheduler

systemctl daemon-reload
systemctl enable --now kube-scheduler


查看启动状态

systemctl  status kube-scheduler


3.4.5 自动颁发证书TLS Bootstrapping配置

只需要在Master01创建bootstrap

cd /root/k8s-ha-install/bootstrap

kubectl config set-cluster kubernetes     --certificate-authority=/etc/kubernetes/pki/ca.pem     --embed-certs=true     --server=https://10.0.0.236:16443     --kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig
kubectl config set-credentials tls-bootstrap-token-user     --token=c8ad9c.2e4d610cf3e7426e --kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig
kubectl config set-context tls-bootstrap-token-user@kubernetes     --cluster=kubernetes     --user=tls-bootstrap-token-user     --kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig
kubectl config use-context tls-bootstrap-token-user@kubernetes     --kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig

mkdir -p /root/.kube ; cp /etc/kubernetes/admin.kubeconfig /root/.kube/config


可以正常查询集群状态,才可以继续往下,否则不行,需要排查k8s组件是否有故障。

二进制安装高可用k8s 1.27.x_kubernetes_09


最后创建一下

kubectl create -f bootstrap.secret.yaml


3.4.6 Node节点配置
3.4.6.1 复制证书

Master01上进行

cd /etc/kubernetes/

for NODE in k8s-master02 k8s-master03 k8s-node01 k8s-node02; do
     ssh $NODE mkdir -p /etc/kubernetes/pki
     for FILE in pki/ca.pem pki/ca-key.pem pki/front-proxy-ca.pem bootstrap-kubelet.kubeconfig; do
       scp /etc/kubernetes/$FILE $NODE:/etc/kubernetes/${FILE}
     done
done


3.4.6.2 kubelet配置

所有节点创建相关目录

mkdir -p /var/lib/kubelet /var/log/kubernetes /etc/systemd/system/kubelet.service.d /etc/kubernetes/manifests/


所有节点配置kubelet service

# cat /usr/lib/systemd/system/kubelet.service

[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kubelet

Restart=always
StartLimitInterval=0
RestartSec=10

[Install]
WantedBy=multi-user.target


所有节点配置kubelet service的配置文件(也可以写到kubelet.service)

# Runtime为Containerd
# vim /etc/systemd/system/kubelet.service.d/10-kubelet.conf
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig --kubeconfig=/etc/kubernetes/kubelet.kubeconfig"
Environment="KUBELET_SYSTEM_ARGS=--container-runtime-endpoint=unix:///run/containerd/containerd.sock"
Environment="KUBELET_CONFIG_ARGS=--config=/etc/kubernetes/kubelet-conf.yml"
Environment="KUBELET_EXTRA_ARGS=--node-labels=node.kubernetes.io/node='' "
ExecStart=
ExecStart=/usr/local/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_SYSTEM_ARGS $KUBELET_EXTRA_ARGS


所有节点创建kubelet的配置文件

注意:如果更改了k8s的service网段,需要更改kubelet-conf.yml 的clusterDNS:配置,改成k8s Service网段的第十个地址,比如192.168.0.10

# vim /etc/kubernetes/kubelet-conf.yml

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
address: 0.0.0.0
port: 10250
readOnlyPort: 10255
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 2m0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.pem
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 5m0s
    cacheUnauthorizedTTL: 30s
cgroupDriver: systemd
cgroupsPerQOS: true
clusterDNS:
- 192.168.0.10
clusterDomain: cluster.local
containerLogMaxFiles: 5
containerLogMaxSize: 10Mi
contentType: application/vnd.kubernetes.protobuf
cpuCFSQuota: true
cpuManagerPolicy: none
cpuManagerReconcilePeriod: 10s
enableControllerAttachDetach: true
enableDebuggingHandlers: true
enforceNodeAllocatable:
- pods
eventBurst: 10
eventRecordQPS: 5
evictionHard:
  imagefs.available: 15%
  memory.available: 100Mi
  nodefs.available: 10%
  nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 5m0s
failSwapOn: true
fileCheckFrequency: 20s
hairpinMode: promiscuous-bridge
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 20s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
imageMinimumGCAge: 2m0s
iptablesDropBit: 15
iptablesMasqueradeBit: 14
kubeAPIBurst: 10
kubeAPIQPS: 5
makeIPTablesUtilChains: true
maxOpenFiles: 1000000
maxPods: 110
nodeStatusUpdateFrequency: 10s
oomScoreAdj: -999
podPidsLimit: -1
registryBurst: 10
registryPullQPS: 5
resolvConf: /etc/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 2m0s
serializeImagePulls: true
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
volumeStatsAggPeriod: 1m0s


启动所有节点kubelet

systemctl daemon-reload
systemctl enable --now kubelet


查看集群状态**(此时Ready或NotReady都正常,还没安装Calico)**

二进制安装高可用k8s 1.27.x_二进制安装k8s_10


3.4.6.3 kube-proxy配置

以下操作只在Master01执行

cd /root/k8s-ha-install/pki

cfssl gencert \
   -ca=/etc/kubernetes/pki/ca.pem \
   -ca-key=/etc/kubernetes/pki/ca-key.pem \
   -config=ca-config.json \
   -profile=kubernetes \
   kube-proxy-csr.json | cfssljson -bare /etc/kubernetes/pki/kube-proxy

kubectl config set-cluster kubernetes \
     --certificate-authority=/etc/kubernetes/pki/ca.pem \
     --embed-certs=true \
     --server=https://10.0.0.236:16443 \
     --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig

kubectl config set-credentials system:kube-proxy \
     --client-certificate=/etc/kubernetes/pki/kube-proxy.pem \
     --client-key=/etc/kubernetes/pki/kube-proxy-key.pem \
     --embed-certs=true \
     --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig

kubectl config set-context system:kube-proxy@kubernetes \
     --cluster=kubernetes \
     --user=system:kube-proxy \
     --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig


kubectl config use-context system:kube-proxy@kubernetes \
     --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig


将kubeconfig发送至其他节点

for NODE in k8s-master02 k8s-master03; do
     scp /etc/kubernetes/kube-proxy.kubeconfig  $NODE:/etc/kubernetes/kube-proxy.kubeconfig
 done

for NODE in k8s-node01 k8s-node02; do
     scp /etc/kubernetes/kube-proxy.kubeconfig $NODE:/etc/kubernetes/kube-proxy.kubeconfig
 done


所有节点添加kube-proxy的配置和service文件

# vim /usr/lib/systemd/system/kube-proxy.service

[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-proxy \
  --config=/etc/kubernetes/kube-proxy.yaml \
  --v=2

Restart=always
RestartSec=10s

[Install]
WantedBy=multi-user.target


如果更改了集群Pod的网段,需要更改kube-proxy.yaml的clusterCIDR为自己的Pod网段

# vim /etc/kubernetes/kube-proxy.yaml

apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
clientConnection:
  acceptContentTypes: ""
  burst: 10
  contentType: application/vnd.kubernetes.protobuf
  kubeconfig: /etc/kubernetes/kube-proxy.kubeconfig
  qps: 5
clusterCIDR: 172.16.0.0/16 
configSyncPeriod: 15m0s
conntrack:
  max: null
  maxPerCore: 32768
  min: 131072
  tcpCloseWaitTimeout: 1h0m0s
  tcpEstablishedTimeout: 24h0m0s
enableProfiling: false
healthzBindAddress: 0.0.0.0:10256
hostnameOverride: ""
iptables:
  masqueradeAll: false
  masqueradeBit: 14
  minSyncPeriod: 0s
  syncPeriod: 30s
ipvs:
  masqueradeAll: true
  minSyncPeriod: 5s
  scheduler: "rr"
  syncPeriod: 30s
kind: KubeProxyConfiguration
metricsBindAddress: 127.0.0.1:10249
mode: "ipvs"
nodePortAddresses: null
oomScoreAdj: -999
portRange: ""
udpIdleTimeout: 250ms


所有节点启动kube-proxy

systemctl daemon-reload
systemctl enable --now kube-proxy


3.4.7 安装Calico网络插件

以下步骤只在Master01执行,注意更改Pod网段。

cd /root/k8s-ha-install/calico/

sed -i "s#POD_CIDR#172.16.0.0/16#g" calico.yaml

二进制安装高可用k8s 1.27.x_kubernetes_11


安装calico

kubectl apply -f calico.yaml


查看容器状态,下图都running就OK。

kubectl get pod -n kube-system

二进制安装高可用k8s 1.27.x_k8s安装_12

如果容器状态异常可以使用kubectl describe 或者kubectl logs查看容器的日志

  1. kubectl logs -f POD_NAME -n kube-system
  2. kubectl logs -f POD_NAME -c upgrade-ipam -n kube-system


3.4.8 安装CoreDNS

以下步骤只在Master01执行

cd /root/k8s-ha-install/

#如果更改了k8s service的网段需要将coredns的serviceIP改成k8s service网段的第十个IP
COREDNS_SERVICE_IP=`kubectl get svc | grep kubernetes | awk '{print $3}'`0

sed -i "s#KUBEDNS_SERVICE_IP#${COREDNS_SERVICE_IP}#g" CoreDNS/coredns.yaml


安装CoreDNS

kubectl  create -f CoreDNS/coredns.yaml


查看容器状态,running就OK。

二进制安装高可用k8s 1.27.x_k8s安装_13


3.4.9 安装Metrics Server

在新版(1.8版本开始)的Kubernetes中系统资源的采集均使用Metrics-server,可以通过Metrics采集节点和Pod的内存、磁盘、CPU和网络的使用率。


以下步骤只在Master01执行

cd /root/k8s-ha-install/metrics-server

kubectl  create -f .


等待metrics server启动然后查看状态,并执行kubectl top node

二进制安装高可用k8s 1.27.x_二进制安装k8s_14


3.4.10 安装Dashboard

Dashboard用于展示集群中的各类资源,同时也可以通过Dashboard实时查看Pod的日志和在容器中执行一些命令等。


在Master01下执行

cd /root/k8s-ha-install/dashboard/
kubectl  create -f .


kubectl get all -n kubernetes-dashboard 用于获取在 kubernetes-dashboard 命名空间中的所有资源的详细信息。

二进制安装高可用k8s 1.27.x_kubernetes_15


查看端口号kubectl get svc kubernetes-dashboard -n kubernetes-dashboard

二进制安装高可用k8s 1.27.x_kubernetes_16


根据自己的实例端口号,通过任意安装了kube-proxy的宿主机的IP+端口即可访问到dashboard,或者直接VIP+端口也可访问到dashboard。

二进制安装高可用k8s 1.27.x_二进制安装k8s_17


创建登录Token

kubectl create token admin-user -n kube-system


将token值输入到令牌后,单击登录即可访问Dashboard。

二进制安装高可用k8s 1.27.x_二进制安装k8s_18


4. 集群可用性验证

节点需均正常

kubectl get node

二进制安装高可用k8s 1.27.x_二进制安装k8s_19


Pod均需正常

kubectl get pod -A

二进制安装高可用k8s 1.27.x_kubernetes_20


检查集群网段无任何冲突

kubectl get svc
kubectl get pod -A -owide


能够正常创建资源

kubectl create deploy cluster-test --image=registry.cn-beijing.aliyuncs.com/dotbalo/debug-tools -- sleep 3600

二进制安装高可用k8s 1.27.x_二进制安装k8s_21


Pod 必须能够解析 Service(同 namespace 和跨 namespace)

#取上面的NAME进入pod
kubectl exec -it cluster-test-84dfc9c68b-lbkhd -- bash

#解析两个域名,能够对应到.1和.10即可
nslookup kubernetes
nslookup kube-dns.kube-system

二进制安装高可用k8s 1.27.x_k8s安装_22


每个节点都必须要能访问 Kubernetes 的 kubernetes svc 443 和 kube-dns 的 service 53

curl https://192.168.0.1:443
curl 192.168.0.10:53

每个节点均需出现以下返回信息说明已通

二进制安装高可用k8s 1.27.x_kubernetes_23


Pod 和 Pod 之间要能够正常通讯(同 namespace 和跨 namespace)

#刚刚创建的一个测试Pod,看看IP也放在哪个节点上
[root@k8s-master01 ~]# kubectl get pod -owide
NAME                            READY   STATUS    RESTARTS   AGE     IP               NODE           NOMINATED NODE   READINESS GATES
cluster-test-84dfc9c68b-lbkhd   1/1     Running   0          4m50s   172.16.122.130   k8s-master02   <none>           <none>


#找出不在node02上的Pod IP,然后两个Pod之间不在同一机器上进ping
kubectl get pod -n kube-system -owide

二进制安装高可用k8s 1.27.x_二进制安装k8s_24


Pod 和 Pod 之间要能够正常通讯(同机器和跨机器)

#找刚从创建的测试Pod IP,全主机进行ping测试,都ping通即可。
[root@k8s-master01 ~]# kubectl get pod -owide
NAME                            READY   STATUS    RESTARTS   AGE     IP               NODE           NOMINATED NODE   READINESS GATES
cluster-test-84dfc9c68b-lbkhd   1/1     Running   0          8m27s   172.16.122.130   k8s-master02   <none>           <none>

二进制安装高可用k8s 1.27.x_k8s安装_25