侧边栏壁纸
博主头像
路小飞博主等级

行动起来,活在当下

  • 累计撰写 72 篇文章
  • 累计创建 12 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

03- 部署高可用 Kubernetes 集群1 Kubeadm

路小飞
2024-07-09 / 0 评论 / 0 点赞 / 31 阅读 / 21670 字

1.1 Kubeadm 简介

为了简化 Kubernetes 的部署工作,让它能够更“接地气”,社区里就出现了一个专门用来在集群中安装 Kubernetes 的工具,名字就叫“kubeadm”,意思就是“Kubernetes 管理员”。

Kubeadm 是用容器和镜像来封装 Kubernetes 的各种组件,但它的目标不是单机部署,而是要能够轻松地在集群环境里部署 Kubernetes,并且让这个集群接近甚至达到生产级质量。

1.2 基本环境配置

本实验需要准备 5 台 2C4G 或以上的服务器,系统为 CentOS 7.x。

集群采用的服务器 IP 规划如下:

主机名IP 地址角色
master01 -03192.168.17.210-212Master 节点 × 3
VIP192.168.17.240Keepalived 虚拟 IP
node01-02192.168.17.213-214Node 节点 × 2

安装配置信息:

配置信息备注
系统版本CentOS 7.9
Docker 版本20.10.x
Pod 网段172.16.0.0/12
Service 网段192.168.0.0/16
1. 配置 hosts
hostnamectl set-hostname master-01
……
cat >>/etc/hosts << EOF
192.168.17.210 master-01
192.168.17.211 master-02
192.168.17.212 master-03
192.168.17.213 node-01
192.168.17.214 node-02
EOF
2. 关闭 SElinux
setenforce 0
sed -i --follow-symlinks 's/^SELUNUX=enforcing/SELINUX=disabled/' /etc/selinux/config
3. 关闭 防火墙
systemctl disable firewalld && systemctl stop firewalld
4. 关闭 Swap 分区
swapoff -a && sed -i '/swap/d' /etc/fstab
5. 确保时间同步

方案一:机器可以联网,使用ntpdate命令同步网络时间服务器

yum -y install ntpdate
ntpdate -u ntp1.aliyun.com
clock -w

方案二:机器无法联网,安装 chrony 服务,搭建时间同步服务器

#chrony 服务器端
yum -y install chrony
vim /ec/chrony.conf
---
#注释掉所有的时间同步server,指定从自己机器上同步
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst

#配置允许同步客户机
allow 192.168.17.0/24

#设置同步级别
local stratum 10
----
systemctl start chronyd
systemctl enable chronyd
ss -antup | grep chrony
clock -w

6. 配置 limit
cat  >> /etc/security/limits.conf << EOF
* soft nofiles 65535 
* hard  nofiles 65535
* soft  nproc 65535
* hard  nproc 65535
* soft  memlock unlimited
* hard  memlock unlimited
EOF
7. 修改内核参数
cat >>/etc/sysctl.d/kubernetes.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
8. 安装常用工具
yum -y install wget vim ipvsadm psmisc telnet

所有节点进行完以上配置后,重启服务器。

1.3 K8s 组件和 Runtime 安装

1. 安装 Docker

注意事项:如果计划安装的 Kubernets 版本高于 1.24(含1.24),默认选择 Containerd 作为 Runtime。

yum -y install yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install -y docker-ce-20.10.24-3.el7.x86_64 docker-ce-cli-20.10.24-3.el7.x86_64 containerd.io docker-buildx-plugin-0.10.5-1.el7.x86_64.rpm   docker-compose-plugin
docker version
docker compose version
systemctl status docker

由于新版Kubelet 建议使用 systemd,因此把 Docker 的 CgroupDriver 也改成 systemd

mkdir -p /etc/docker
cat > /etc/docker/daemon.json << EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF

所有节点设置重启 Docker 并设置成开机自启动

systemctl daemon-reload
systemctl stop docker
systemctl start docker
systemctl enable docker
2. 安装 Kubernetes 组件

生产环境建议安装第三个版本号大于5的版本,本文采用1.23.15。

cat > /etc/yum.repos.d/kubernetes.repo << EOF
[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.23.15-0 kubelet-1.23.15-0 kubectl-1.23.15-0
  • kubeadm 是 Kubernetes 提供的一个工具,用于快速部署 Kubernetes 集群。

  • kubelet 是 Kubernetes 集群中每个节点上运行的代理,负责与 Master 节点通信,接收集群管理的指令并在节点上执行这些指令。

    kubelet 进程同时也会监视特定目录(默认为 /etc/kubernetes/manifests)中的静态 Pod (控制面的四个组件,即apiserver、etcd、scheduler、controller-manager。有需求,也可以自定义一些静态pod)配置文件,并根据这些配置文件来创建和维护静态 Pod。

  • kubectl 是 Kubernetes 的命令行工具,用于与 Kubernetes 集群进行交互操作。通过 kubectl 可以管理集群中的资源对象,如 Pod、Service、Deployment 等。

    该组件可以按需安装,以哪台机器作为console机在哪里安装即可。

systemctl enable  kubelet
systemctl start kubelet

1.4 高可用组件安装

本实验采用 Keepalived 和 HAproxy 实现高可用。Keeaplived 和 HAproxy 的节点可以和 master 在同一节点,也可以在不同节点。

若在公有云环境搭建高可用集群,也可以采用公有云的负载均衡代替 Keepalived 和 HAproxy。

所有Masster节点安装 Keepalived 和 HAproxy。

1. 安装 HAproxy
yum -y install haproxy
mkdir /etc/haproxy
vim /etc/haproxy/haproxy.cfg
systemctl start haproxy
systemctl enable haproxy
global
    log /dev/log  local0 warning
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon
    stats socket /var/lib/haproxy/stats

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

frontend kube-apiserver
  bind *:16443
  mode tcp
  option tcplog
  default_backend kube-apiserver

backend kube-apiserver
    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 kube-apiserver-1 192.168.17.210:6443 check	#配置后端服务器地址
    server kube-apiserver-2 192.168.17.211:6443 check 
    server kube-apiserver-3 192.168.17.212:6443 check 

所有节点的 HAproxy 配置相同。

2. 安装 Keepalived
yum -y install keepalived
mkdir /etc/keepalived
vim /etc/keepalived/keepalived.conf
vim /etc/keepalived/check_haproxy.sh
chmod +x /etc/keepalived/check_haproxy.sh
systemctl start keepalived
systemctl enable keepalived

由于Keepalived 需要配置自身的 IP 地址和网卡名称,因此节点的配置文件不尽相同。

global_defs {               
    router_id haproxy_01			#每个实例都是不同的(master01是01,master02是02,master03是03)
}
vrrp_script check_haproxy {
    script "/etc/keepalived/check_haproxy.sh"
    interval 5
    weight -20
    fall 3
    rise 2
}
vrrp_instance VI_1 {
    state MASTER
    interface ens33                #设置实例绑定的网卡
    mcast_src_ip 192.168.17.210    #广播的原地址(master01是210,master02是211,master03是212)
    virtual_router_id 51           #同一实例下virtual_router_id必须相同
    priority 110                   #设置优先级,优先级高的会被竞选为Master(三台分别设置为110、100、90)
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {            #设置VIP
     192.168.17.240
    }
    track_script {                 #设置追踪脚本
    	check_haproxy
    }
}


/etc/keepalived/check_haproxy.sh

#!/bin/bash
counter=$(ps -C haproxy --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
    systemctl restart haproxy
    sleep 2
    counter=$(ps -C haproxy --no-heading|wc -l)
    if [ "${counter}" = "0" ]; then
        systemctl stop keepalived
        exit 1
    fi
fi
3. 测试 VIP 是否正常
[root@master-01 ~]# ping -c 4 192.168.17.240
PING 192.168.17.240 (192.168.17.240) 56(84) bytes of data.
64 bytes from 192.168.17.240: icmp_seq=1 ttl=64 time=0.033 ms
64 bytes from 192.168.17.240: icmp_seq=2 ttl=64 time=0.046 ms
64 bytes from 192.168.17.240: icmp_seq=3 ttl=64 time=0.060 ms
64 bytes from 192.168.17.240: icmp_seq=4 ttl=64 time=0.044 ms

--- 192.168.17.240 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.033/0.045/0.060/0.012 ms

[root@master-01 ~]# telnet 192.168.17.240 16443
Trying 192.168.17.240...
Connected to 192.168.17.240.
Escape character is '^]'.
Connection closed by foreign host.
[root@master-01 ~]# 

如果 ping 不通且 telnet 没有出现,则认为 VIP 不可用,需要进一步排查问题原因,比如防火墙、SElinux、进程状态、端口监听情况等。

1.5 集群初始化

使用 Kubeadm 安装集群时,需要一个 Master 节点初始化集群,然后其他节点加入到集群中。初始化集群可以直接使用 Kubeadm 命令行进行初始化,也可以使用一个配置文件进行初始化,由于使用命令行初始化需要配置的字段比较多,因此本实验采用配置文件进行初始化。

1. 创建初始化文件并修改配置
kubeadm config print init-defaults > kubeadm-config.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.17.210
  bindPort: 6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
 #criSocket: /var/containerd/containerd.sock		#如果是Containerd作为Runtime,配置此项
  imagePullPolicy: IfNotPresent
  name: master-01
  taints: null
---
apiServer:
  certSANs:
  - 192.168.17.240
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: 192.168.17.240:16443			
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.23.15
networking:
  dnsDomain: cluster.local
  podSubnet: 172.16.0.0/12
  serviceSubnet: 192.168.0.0/16	
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs

如果不是高可用集群,controlPlaneEndpoint 需要改为 Master 节点的 IP 和 6443 端口;certSANs 也需要改为 Master 节点的 IP。

2. 初始化集群
kubeadm init --config=kubeadm-config.yaml --upload-certs

--upload-certs 选项的引入是为了简化高可用集群中多控制平面节点的证书管理。使用该命令时,Kubeadm 会将控制平面节点所需的证书加密并上传到 kube-apiserver。后续的控制平面节点可以通过 kubeadm join 命令并带上 --control-plane 选项,自动从 kube-apiserver 中下载并解密证书,而不需要手动复制证书。

输出信息类似如下:

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.17.240:6443 --token abcdef.0123456789abcdef \
	--discovery-token-ca-cert-hash sha256:0879e13064c2b5b37e521d00317633890abba8e37ccbb334ba6e5d0b58adc93c 

初始化成功后,会产生 Token 值,用于其他节点加入时使用,因此要记录一下 Token。

如果初始化失败,需要检查各项配置是否正确,之后再次初始化,清理命令如下:

kubeadm reset -f ; ipvsadm --clear ; rm -rf ~/.kube

设置 Kubernetes 集群管理员的 kubeconfig 文件,以便让 kubectl 命令能够访问和管理集群。

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

默认情况下,新建的集群 Token 有效期是 24h ,如果过期,需要重新生成 Token。

kubeadm token create --print-join-command

如果需要添加 Master,certigicate-key 也需要重新打印

kubeadm init phase upload-certs --upload-certs
4. 其他节点加入集群

Node节点:

#初始化节点打印token
[root@master-01 ~]# kubeadm token create --print-join-command
kubeadm join 192.168.17.240:6443 --token vzvhkw.zatqzkknr17bv9m3 --discovery-token-ca-cert-hash sha256:0879e13064c2b5b37e521d00317633890abba8e37ccbb334ba6e5d0b58adc93c 

[root@master-01 ~]# kubeadm join 192.168.17.240:6443 --token vzvhkw.zatqzkknr17bv9m3 --discovery-token-ca-cert-hash sha256:0879e13064c2b5b37e521d00317633890abba8e37ccbb334ba6e5d0b58adc93c 
[preflight] Running pre-flight checks
	[WARNING Hostname]: hostname "master-01" could not be reached
	[WARNING Hostname]: hostname "master-01": lookup master-01 on 114.114.114.114:53: no such host
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

Master节点:

Master节点加入集群和 Node节点是一致的,只不过加入集群时候需要指定--control-plane--certificate-key 参数

#初始化节点打印token
[root@master-01 ~]# kubeadm token create --print-join-command
kubeadm join 192.168.17.240:16443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:19996901d553cb3c56a974eeb8ecf857f3f115d4b82c0f303f024613c9ef9026 
[root@master-01 ~]# kubeadm init phase upload-certs --upload-certs
I0920 00:14:05.105749   16440 version.go:255] remote version is much newer: v1.31.0; falling back to: stable-1.23
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
f47baf8a2d8a358ecd2342fb0df376df3b74cc9f09f6d5cf4945bd1512634bbc
[root@master-01 ~]# 

#master节点加入
[root@master-01 ~]# kubeadm join 192.168.17.240:16443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:19996901d553cb3c56a974eeb8ecf857f3f115d4b82c0f303f024613c9ef9026  --control-plane --certificate-key f47baf8a2d8a358ecd2342fb0df376df3b74cc9f09f6d5cf4945bd1512634bbc

5.集群状态查看
[root@master-01 ~]# kubectl get node
NAME        STATUS     ROLES                  AGE     VERSION
master-01   NotReady   control-plane,master   8m51s   v1.23.15
master-02   NotReady   control-plane,master   95s     v1.23.15
master-03   NotReady   control-plane,master   11s     v1.23.15
node-01     NotReady   <none>                 4m1s    v1.23.15
[root@master-01 ~]# kubectl label node node-01 node-role.kubernetes.io/node=
node/node-01 labeled
[root@master-01 ~]# kubectl get node
NAME        STATUS     ROLES                  AGE     VERSION
master-01   NotReady   control-plane,master   9m47s   v1.23.15
master-02   NotReady   control-plane,master   2m31s   v1.23.15
master-03   NotReady   control-plane,master   67s     v1.23.15
node-01     NotReady   node                   4m57s   v1.23.15
  • 所有节点加入后,节点的 STATUS 字段为 NotReady,安装完 CNI 即可变成 Ready。
  • 干加入的node节点 ROLES 字段是 none, 可以使用 label 添加标签。

采用初始化安装方式,所有的系统组件均以容器的方式运且在 kube-system 命名空间内:

[root@master-01 ~]# kubectl -n kube-system get pod
NAME                                READY   STATUS    RESTARTS         AGE
coredns-6d8c4cb4d-w5ks6             0/1     Pending   0                12m
coredns-6d8c4cb4d-zdj8k             0/1     Pending   0                12m
etcd-master-01                      1/1     Running   13               12m
etcd-master-02                      1/1     Running   0                5m26s
etcd-master-03                      1/1     Running   0                4m2s
kube-apiserver-master-01            1/1     Running   1                12m
kube-apiserver-master-02            1/1     Running   0                5m31s
kube-apiserver-master-03            1/1     Running   0                4m7s
kube-controller-manager-master-01   1/1     Running   2 (5m14s ago)    12m
kube-controller-manager-master-02   1/1     Running   0                5m30s
kube-controller-manager-master-03   1/1     Running   0                4m6s
kube-proxy-8w7p5                    1/1     Running   0                7m57s
kube-proxy-lsb8r                    1/1     Running   0                12m
kube-proxy-tcdfb                    1/1     Running   0                4m7s
kube-proxy-z6x4x                    1/1     Running   0                5m31s
kube-scheduler-master-01            1/1     Running   14 (5m16s ago)   12m
kube-scheduler-master-02            1/1     Running   0                5m30s
kube-scheduler-master-03            1/1     Running   0                4m6s

1.6 Calico安装

接下来安装CNI插件,CNI插件可以选择Calico、Flannel、Cilium等,本文安装的是 Calico。

curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/calico-typha.yaml -o calico.yaml

#下载需要科学上网

修改模式为BGP模式:

# 修改为 BGP 模式
# Enable IPIP
- name: CALICO_IPV4POOL_IPIP
  value: "Always"  #改成Off
kubectl apply -f calico.yaml

Ref:Install Calico networking and network policy for on-premises deployments | Calico Documentation (tigera.io)

1.7 Metrics 安装

Metrics 作为集群中资源指标的默认聚合组件,用于采集和提供节点和 Pod 的资源使用情况(如 CPU 和内存)的监控数据。

wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/high-availability-1.21+.yaml

#下载需要科学上网

#修改点1	
# 145行添加--kubelet-insecure-tls(Metric 需要和kubelet通信。默认和kubelet通信需要证书,为了简单,令其不适用证书通信)
143       containers:
144       - args:
145         - --kubelet-insecure-tls		
146         - --cert-dir=/tmp

	
kubectl apply -f high-availability-1.21+.yaml

安装metrics server后才会有top命令,此命令也是K8S中常用命令之一。

所以使用K8S一般都会安装Metrics Server。

1.8 Kubectl 优化

实现kubectl的命令补全功能

yum -y install bash-completion 
echo "source <(kubectl completion bash)" >> ~/.bashrc     
source  ~/.bashrc

1.9 注意事项

1. 配置方面

和二进制安装方式不同的是,使用 Kubeadm 安装的 K8S 集群,大部分组件都是以容器的方式运行的;

Master 节点的组件apiserver、scheduler、controller-manager、etcd 的配置和启动文件默认都放在/etc/kubernetes/mainfests,以静态 Pod 方式启动。比如 apiserver 的 kube-apiserver.yaml,该 yaml 文件更改后,kubelet 会自动刷新配置,也就是重启 Pod。

kube-proxy 是以 Daemonset 的方式在每个节点都部署一个,其配置文件使用 Kubernetes 的 ConfigMap 进行管理,需要更改该 cm 后,再对 kube-proxy 及性能滚动更新才会生效。

比如将 kube-proxy 的代理模式改写为 ipvs 模式

kubectl edit cm kube-proxy -n kube-system
……
mode:
ipvs
……

验证 kube-proxy 的模式:

curl 127.0.0.1:10249/proxyMode
2. 污点方面

Kubeadm 安装后,会自动在 Master 节点添加 NoSchedule 的污点,可以通过删除污点的方式允许部署:
查看污点:

kubectl describe node -l node-role.kubernetes.io/master| grep -i taints -B 3
kubectl taint node <node-name> node-role.kubernetes.io/master-

3. 证书有效期问题

虽然 Kubeadm 安装方式比较简单,但是这种方式安装的证书有效期默认是一年,到期后需要进行升级或者更新证书。

查看证书有效期(两种方式均可)

openssl x509 -enddate -noout -in /etc/kubernetes/pki/apiserver.crt
kubeadm certs check-expiration

更新证书有效期

kubeadm certs renew all
docker ps | grep -v pause | grep -E "etcd|scheduler|controller|apiserver" | awk '{print $1}' | xargs -I {} docker restart {}
0

评论区