1.1 Kubeadm 简介
为了简化 Kubernetes 的部署工作,让它能够更“接地气”,社区里就出现了一个专门用来在集群中安装 Kubernetes 的工具,名字就叫“kubeadm”,意思就是“Kubernetes 管理员”。
Kubeadm 是用容器和镜像来封装 Kubernetes 的各种组件,但它的目标不是单机部署,而是要能够轻松地在集群环境里部署 Kubernetes,并且让这个集群接近甚至达到生产级质量。
1.2 基本环境配置
本实验需要准备 5 台 2C4G 或以上的服务器,系统为 CentOS 7.x。
集群采用的服务器 IP 规划如下:
| 主机名 | IP 地址 | 角色 |
|---|---|---|
| master01 -03 | 192.168.17.210-212 | Master 节点 × 3 |
| VIP | 192.168.17.240 | Keepalived 虚拟 IP |
| node01-02 | 192.168.17.213-214 | Node 节点 × 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
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 {}
评论区