kubeadm部署k8s高可用集群

kubeadm部署k8s高可用集群

一. 环境准备及集群规划

 
准备四台机器(均为2C1.5G配置):
192.168.10.11 master1
192.168.10.12 master2
192.168.10.13 master3
192.168.10.14 node
 
3台master共用一个vip: 192.168.10.100
 
所有机器配置好如下环境:
• 关闭防火墙,selinux
• 做好解析
• 配置好时间同步
• 禁用swap分区
• 配置内核参数
[root@master1 ~]# vim /etc/sysctl.d/kubernetes.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_nonlocal_bind = 1
net.ipv4.ip_forward = 1
vm.swappiness=0
[root@master1 ~]# sysctl --system
• 加载ipvs模块:
[root@master1 ~]# yum install ipset ipvsadm -y #安装相关管理工具
[root@master1 ~]# vim /etc/sysconfig/modules/ipvs.modules
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
[root@master1 ~]# chmod +x /etc/sysconfig/modules/ipvs.modules
[root@master1 ~]# /etc/sysconfig/modules/ipvs.modules
•升级内核(版本较新的不需要此步)
[root@master1 ~]# yum -y update kernel
[root@master1 ~]# shutdown -r now
 

二、部署过程

1. 安装配置docker             # 所有节点
2. 安装软件                   # 所有节点
3. 安装负载均衡及高可用   # 所有 Master节点
4. 初台化Master1          # Master1节点
5. 配置kubectl              # 所有需要的节点
6. 部署网络插件      # Master1节点
7. 加入Master节点              # 其它 Master节点
8. 加入Worker节点       # 所有 Node节点

2.1 安装配置docker 

在所有节点安装
vim docker_install.sh
#/bin/bash
curl http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo
yum -y install docker-ce-18.06.0.ce
[ ! -d /etc/docker ] && mkdir /etc/docker
cat >> /etc/docker/daemon.json <<- EOF
{
"registry-mirrors": ["https://pf5f57i3.mirror.aliyuncs.com"]
}
EOF
systemctl enable docker
systemctl start docker
yum -y install ansible
cat >> /etc/ansible/hosts << EOF
[k8s]
192.168.10.11
192.168.10.12
192.168.10.13
192.168.10.14
EOF
ansible k8s -m script -a 'creates=/root/docker_install.sh /root/docker_install.sh'

 

2.2 安装软件

在所有节点安装
vim k8s_repo.sh
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
cat >> /etc/ansible/host << EOF
[cluster]
192.168.10.12
192.168.10.13
192.168.10.14
EOF
ansible cluster -m copy -a "src=/etc/yum.repos.d/kubernetes.repo dest=/etc/yum.repos.d/ force=no"
yum install -y kubeadm-1.18.10-0 kubelet-1.18.10-0 kubectl-1.18.10-0 ipvsadm
可用 yum list --showduplicates|egrep kubeadm 查看有哪些可用版本
设置开机启动kubelet
# systemctl enable kubelet

2.3 安装负载均衡

在所有Master节点操作
Kubernetes master 节点运行如下组件:
- kube-apiserver
- kube-scheduler
- kube-controller-manager
kube-scheduler 和 kube-controller-manager 可以以集群模式运行,通过 leader 选举产生一个工作进程,其它进程处于阻塞模式。kube-apiserver可以运行多个实例,但对其它组件需要提供统一的访问地址,该地址需要高可用。
本次部署使用 keepalived+haproxy 实现 kube-apiserver 的VIP 高可用和负载均衡。keepalived 提供 kube-apiserver 对外服务的 VIP高可用。haproxy 监听 VIP,后端连接所有 kube-apiserver 实例,提供健康检查和负载均衡功能。kube-apiserver的端口为6443, 为避免冲突, haproxy 监听的端口要与之不同,此实验中为6444。
keepalived 周期性检查本机的 haproxy 进程状态,如果检测到 haproxy 进程异常,则触发VIP 飘移。 所有组件都通过 VIP 监听的6444端口访问 kube-apiserver 服务。
 
在此我们使用睿云智合相关镜像,具体使用方法请访问: https://github.com/wise2c-devops 。当然也可以手动配置haproxy以实现apiserver负载均衡,keepalived实现haproxy高可用。
创建 haproxy和 keepalived的启动脚本
[root@master1 ~]# vim haproxy_keepalived.sh
#!/bin/bash
MasterIP1=192.168.10.11
MasterIP2=192.168.10.12
MasterIP3=192.168.10.13
MasterPort=6443                   # apiserver端口
 
 
docker run -d --restart=always --name haproxy-k8s -p 6444:6444 \
           -e MasterIP1=$MasterIP1 \
           -e MasterIP2=$MasterIP2 \
           -e MasterIP3=$MasterIP3 \
           -e MasterPort=$MasterPort  wise2c/haproxy-k8s
 
VIRTUAL_IP=192.168.10.100         # VIP
INTERFACE=ens33                   # 网卡名称
NETMASK_BIT=24
CHECK_PORT=6444                   # Haproxy端口
RID=10
VRID=160
MCAST_GROUP=224.0.0.18
docker run -itd --restart=always --name=keepalived-k8s \
           --net=host --cap-add=NET_ADMIN \
           -e VIRTUAL_IP=$VIRTUAL_IP \
           -e INTERFACE=$INTERFACE \
           -e NETMASK_BIT=$NETMASK_BIT \
           -e CHECK_PORT=$CHECK_PORT \
           -e RID=$RID -e VRID=$VRID \
           -e MCAST_GROUP=$MCAST_GROUP  wise2c/keepalived-k8s
在所有Master节点执行脚本运行这两个容器
[root@master1 ~]# sh haproxy_keepalived.sh
[root@master1 ~]# ansible 192.168.10.12 -m script -a 'creates=/root/haproxy_keepalived.sh /root/haproxy_keepalived.sh'
[root@master1 ~]# ansible 192.168.10.13 -m script -a 'creates=/root/haproxy_keepalived.sh /root/haproxy_keepalived.sh'
测试
1).在每台机器上查看容器(haproxy, keepalived)是否都正常运行
2).在每台机器上查看6444端口是否监听
3).在有VIP的机器关闭haproxy容器或keepalived容器看看VIP能否正常飘移
 

2.4 初始化Master1

仅在 Master1节点操作
初始化参考:
在 Master1上创建初始化配置文件
[root@master1 ~]# mkdir k8s
[root@master1 ~]# cd k8s/
[root@master1 k8s]# kubeadm config print init-defaults > init.yml
根据实际环境修改初始化配置文件
[root@master1 k8s]# vim init.yml
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.10.11         # 此处改为本机IP(修改)
  bindPort: 6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  name: master1 #修改为master1
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: "192.168.10.100:6444"   # VIP:PORT(增加)
controllerManager: {}
dns:
  type: CoreDNS
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers  # 使用国内镜像仓库(增加)
kind: ClusterConfiguration
kubernetesVersion: v1.18.10    # 版本号(修改)
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
  podSubnet: 10.244.0.0/16    # pod子网,和Flannel中要一致(增加)
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
初始化 Master1
之前版本:
[root@master1 k8s]# kubeadm init --config=init.yml --experimental-upload-certs | tee kubeadm-init.log
v1.18.10版本:
[root@master1 k8s]# kubeadm init --config=init.yml --upload-certs |tee kubeadm-init.log
  • 该命令指定了初始化时需要使用的配置文件,其中添加–experimental-upload-certs参数可以在后续执行加入节点时自动分发证书文件。
  • 这里追加tee命令将初始化日志输出到kubeadm-init.log中以备用(可选)。
  • 由于需要拉取镜像,各种原因,这里可能要等十几分钟,一定耐心耐心,只要没有error等待即可
初始化成功后可以看到类似于下图提示:
*如果中途失败, 再次初始化前先执行 kubeadm reset 命令清理, 然后再执行init或join操作
 
[root@node2 ~]# kubeadm reset
[reset] WARNING: Changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.
[reset] Are you sure you want to proceed? [y/N]: y
[preflight] Running pre-flight checks
W0321 22:54:01.292739    7918 removeetcdmember.go:79] [reset] No kubeadm config, using etcd pod spec to get data directory
[reset] No etcd config found. Assuming external etcd
[reset] Please, manually reset etcd to prevent further issues
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Deleting contents of config directories: [/etc/kubernetes/manifests /etc/kubernetes/pki]
[reset] Deleting files: [/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/bootstrap-kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf]
[reset] Deleting contents of stateful directories: [/var/lib/kubelet /var/lib/dockershim /var/run/kubernetes /var/lib/cni]
 
# reset进程没有清理CNI配置
The reset process does not clean CNI configuration. To do so, you must remove /etc/cni/net.d
 
# reset进程没有清理iptables或IPVS表
The reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually by using the "iptables" command.
 
If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.
 
# reset进程没有清理kubeconfig文件
The reset process does not clean your kubeconfig files and you must remove them manually.
Please, check the contents of the $HOME/.kube/config file.
 
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
 

2.5 配置kubectl

无论在master节点或node节点,要能够执行kubectl命令必须进行配置,有两种配置方式
方式一,通过配置文件
我用的是root用户,所以执行下面两步即可
[root@master k8s]# mkdir -p $HOME/.kube
[root@master k8s]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
 
[root@master k8s]# sudo chown $(id -u):$(id -g) $HOME/.kube/config
方式二,通过环境变量
# echo 'export KUBECONFIG=/etc/kubernetes/admin.conf' >> ~/.bashrc
# source ~/.bashrc
配置好kubectl后,就可以使用kubectl命令了
[root@master1 k8s]# kubectl get cs
NAME                 STATUS    MESSAGE             ERROR
controller-manager   Healthy   ok                  
etcd-0               Healthy   {"health":"true"}   
scheduler            Healthy   ok  
 
[root@master1 k8s]# kubectl get no
NAME      STATUS     ROLES    AGE     VERSION
master1   NotReady   master   2m32s   v1.18.0
 
[root@master1 k8s]# kubectl get po -n kube-system
NAME                              READY   STATUS    RESTARTS   AGE
coredns-7ff77c879f-965nt          0/1     Pending   0          2m24s
coredns-7ff77c879f-qmsb2          0/1     Pending   0          2m24s
etcd-master1                      1/1     Running   1          2m38s
kube-apiserver-master1            1/1     Running   1          2m38s
kube-controller-manager-master1   1/1     Running   1          2m38s
kube-proxy-q847x                  1/1     Running   1          2m24s
kube-scheduler-master1            1/1     Running   1          2m38s

 

由于未安装网络插件,coredns处于pending状态,node处于NotReady 状态
在更高版本的k8s集群中,可能会出现 scheduler、controller-manager 两个组件健康状况不正常的情况,如下:
[root@master-1 k8s]# kubectl get cs
NAME                 STATUS      MESSAGE                                                                                     ERROR
controller-manager   Unhealthy   Get http://127.0.0.1:10252/healthz: dial tcp 127.0.0.1:10252: connect: connection refused
scheduler            Unhealthy   Get http://127.0.0.1:10251/healthz: dial tcp 127.0.0.1:10251: connect: connection refused
etcd-0               Healthy     {"health":"true"}

 

解决方法:修改以下两个文件:
/etc/kubernetes/manifests/kube-controller-manager.yaml
/etc/kubernetes/manifests/kube-scheduler.yaml
!!!注释掉: - --port=0 ,等一会即可

2.6 部署网络插件flannel

仅在Master1节点操作
kubernetes支持多种网络方案,这里简单介绍常用的 flannel 方案.
下载kube-flannel.yml文件
[root@master k8s]# curl -O https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
由于kube-flannel.yml文件指定的镜像从coreos镜像仓库拉取,可能拉取失败,我们替换掉它
# 查看
[root@master k8s]# grep -i "flannel:" kube-flannel.yml
        image: quay.io/coreos/flannel:v0.12.0-amd64
        image: quay.io/coreos/flannel:v0.12.0-amd64
 
# 替换(注:因文件版本不同,替换命令可能有所不同)
[root@master k8s]# sed -i 's#quay.io/coreos/flannel:v0.13.0#registry.cn-shenzhen.aliyuncs.com/leedon/flannel:v0.11.0-amd64#' kube-flannel.yml
 
由于国内网络原因,下载不下来的,多下载几次。
执行安装
[root@master1 k8s]# kubectl apply -f kube-flannel.yml
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds-amd64 created
再次查看node和 Pod状态,全部OK, 所有的核心组件都起来了
[root@master1 k8s]# kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-7ff77c879f-965nt 1/1 Running 0 24m
coredns-7ff77c879f-qmsb2 1/1 Running 0 24m
etcd-master1 1/1 Running 1 25m
kube-apiserver-master1 1/1 Running 1 25m
kube-controller-manager-master1 1/1 Running 1 25m
kube-flannel-ds-amd64-vvj65 1/1 Running 0 48s
kube-proxy-q847x 1/1 Running 1 24m
kube-scheduler-master1 1/1 Running 1 25m
 
[root@master1 k8s]# kubectl get no
 
 

2.7 加入master节点

从初始化输出或kubeadm-init.log中获取命令将master2和master3加入到集群中来
[root@master1 k8s]# cat kubeadm-init.log
 
在另外两个节点执行
[root@master2 ~]# kubeadm join 192.168.10.100:6444 --token abcdef.0123456789abcdef \
>     --discovery-token-ca-cert-hash sha256:fae84690ed5edbf2189f9c7c6db193e09a543c9abe3e16a54c5ddaf5c558b1d2 \
>     --control-plane --certificate-key 598ebb9877f3b981316a21879988e6cfe0eb64708c2aef689128604e5267a767
[root@master3 ~]# kubeadm join 192.168.10.100:6444 --token abcdef.0123456789abcdef \
>     --discovery-token-ca-cert-hash sha256:fae84690ed5edbf2189f9c7c6db193e09a543c9abe3e16a54c5ddaf5c558b1d2 \
>     --control-plane --certificate-key 598ebb9877f3b981316a21879988e6cfe0eb64708c2aef689128604e5267a767
稍等一会,加入成功后会有如下提示:        (耐心等待)
 
再查看集群信息
 
[root@master1 k8s]# kubectl get no
NAME STATUS ROLES AGE VERSION
master1 Ready master 12m v1.18.0
master2 Ready master 10m v1.18.0
master3 Ready master 3m3s v1.18.0

 

 
[root@master1 k8s]# kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-7ff77c879f-r4mqp 1/1 Running 0 12m
coredns-7ff77c879f-w9nsh 1/1 Running 0 12m
etcd-master1 1/1 Running 0 13m
etcd-master2 1/1 Running 0 9m39s
etcd-master3 1/1 Running 0 3m51s
kube-apiserver-master1 1/1 Running 0 13m
kube-apiserver-master2 1/1 Running 0 11m
kube-apiserver-master3 1/1 Running 0 3m50s
kube-controller-manager-master1 1/1 Running 1 13m
kube-controller-manager-master2 1/1 Running 1 9m43s
kube-controller-manager-master3 1/1 Running 0 3m50s
kube-flannel-ds-amd64-9wn57 1/1 Running 1 11m
kube-flannel-ds-amd64-ktxpl 1/1 Running 0 12m
kube-flannel-ds-amd64-qhttx 1/1 Running 0 8m59s
kube-proxy-6hlql 1/1 Running 0 11m
kube-proxy-jbx8r 1/1 Running 0 12m
kube-proxy-l9782 1/1 Running 0 8m59s
kube-scheduler-master1 1/1 Running 2 13m
kube-scheduler-master2 1/1 Running 2 9m43s
kube-scheduler-master3 1/1 Running 0 3m49s

 

 
分别在master2和master3上配置好命令行工具kubectl
就可以正常使用了
也可以

2.8 加入worker节点

Kubernetes 的 Worker 节点跟 Master 节点几乎是相同的,它们运行着的都是一个 kubelet 组件。
唯一的区别在于,Master 节点上还会自动运行 kube-apiserver、kube-scheduler、kube-controller-manger 这三个系统 Pod
 
从init的输出或kubeadm-init.log文件中获取命令将node节点加入到集群中来
[root@master1 k8s]# cat kubeadm-init.log
 
在所有worker节点执行
 
过一段时间再看集群信息
可以在任意master节点上查看加入是否成功:
[root@master1 k8s]# kubectl get no
NAME      STATUS   ROLES    AGE     VERSION
master1   Ready    master   22m     v1.18.0
master2   Ready    master   20m     v1.18.0
master3   Ready    master   13m     v1.18.0
node1     Ready    <none>   4m46s   v1.18.0

 

至此,集群部署完毕。
 

2.9 查看集群信息

 
查看service
[root@master3 ~]# kubectl get svc -n kube-system
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   91m
 
查看代理规则
[root@master3 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.96.0.1:443 rr
  -> 192.168.10.11:6443           Masq    1      0          0
  -> 192.168.10.12:6443           Masq    1      0          0
  -> 192.168.10.13:6443           Masq    1      1          0
TCP  10.96.0.10:53 rr
  -> 10.244.0.2:53                Masq    1      0          0
  -> 10.244.0.3:53                Masq    1      0          0
TCP  10.96.0.10:9153 rr
  -> 10.244.0.2:9153              Masq    1      0          0
  -> 10.244.0.3:9153              Masq    1      0          0
UDP  10.96.0.10:53 rr
  -> 10.244.0.2:53                Masq    1      0          0
  -> 10.244.0.3:53                Masq    1      0          0

 

 
查看etcd集群状态:
[root@master2 ~]# kubectl -n kube-system exec etcd-master1 -- etcdctl \
--endpoints=https://192.168.10.11:2379 \
--ca-file=/etc/kubernetes/pki/etcd/ca.crt \
--cert-file=/etc/kubernetes/pki/etcd/server.crt \
--key-file=/etc/kubernetes/pki/etcd/server.key cluster-health
posted @ 2020-10-30 19:02  梦里花落知多少sl  阅读(652)  评论(1编辑  收藏  举报