kubeadm HA master(v1.12.1)集群搭建指南(离线包 + 自动化脚本 + ipvs + keepalived + calico + helm) For Centos/Fedora

0x00 文章楔子

本文旨在通过最简易的方式指导读者搭建HA kubernetes 1.12.1集群

通过部署脚本驱动kubeadm工具进行自动化部署,自动启动keepalived负载均衡,calico网络插件,并且开启kube-proxy的IPVS模式。

本文中的自动化部署脚本可以在Lentil1016/kubeadm-ha找到,欢迎Star/Fork/提issue和PR。

在我的环境上进行示例自动化部署的录像可以在该链接查看

0x01 Kubernetes集群搭建

集群结构摘要

集群结构摘要

Master是集群的管理者,负责监控应用运行状态,维护应用运行,如发布工作任务、重启应用、部署升级应用等

Worker(节点),也被称为Minion,即从属主机,是Kubernetes集群中的一台工作机器。每一个节点都包含了Pod运行所需的必要服务,例如docker/kubelet/kube-proxy。

Kubernetes集群的基本部署步骤:

  1. 所有节点安装docker
  2. harbor节点安装harbor
  3. 所有master和minion节点安装kubelet kubeadm kubectl
  4. 初始化master节点,并启动Calico容器
  5. 将worker节点join到集群中

各个机器的主机信息以及IP分布如下:

  • Distribute: CentOS 7
  • Docker: 17.03.2-ce
  • Kernel: 4.18.12-1.el7.elrepo.x86_64
  • Kubernetes: 1.12.1
  • NetPlugin: Calico
  • Proxy-Mode: IPVS
  • Master-Mode: HA Master
  • DNS: CoreDNS
Host Name Role IP
harbor image registry 10.130.38.80
centos-7-x86-64-29-80 master-1 10.130.29.80
centos-7-x86-64-29-81 master-2 10.130.29.81
centos-7-x86-64-29-82 master-3 10.130.29.82
Virtual IP 10.130.29.83
node1 worker 10.130.38.105
node2 worker 10.130.38.106
node3 worker 10.130.38.107

进行系统配置

在所有机器上下载内核rpm包,并且执行下面的脚本,配置注记:

  • 关闭防火墙、selinux
  • 关闭系统的Swap,Kubernetes 1.8开始要求。
  • 关闭linux swap空间的swappiness
  • 配置L2网桥在转发包时会被iptables的FORWARD规则所过滤,该配置被CNI插件需要,更多信息请参考Network Plugin Requirements
  • 开启IPVS
# 所有主机:基本系统配置

# 关闭Selinux/firewalld
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
 
# 关闭交换分区
swapoff -a
yes | cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab
 
# 设置网桥包经IPTables,core文件生成路径
echo """
vm.swappiness = 0
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
""" > /etc/sysctl.conf
sysctl -p
 
# 同步时间
yum install -y ntpdate
ntpdate -u ntp.api.bz
 
# 安装4.18版本内核
# 由于最新稳定版4.19内核将nf_conntrack_ipv4更名为nf_conntrack,目前的kube-proxy不支持在4.19版本内核下开启ipvs
# 详情可以查看:https://github.com/kubernetes/kubernetes/issues/70304
# 对于该问题的修复10月30日刚刚合并到代码主干,所以目前还没有包含此修复的kubernetes版本发出
# 读者可以选择安装我提供的4.18版本内核,或者不开启IPVS
# 4.18版本内核RPM下载链接:https://pan.baidu.com/s/1dCeozuMRQ96MBBjGpf0cjA 提取码:3nqg
cd /path/to/kernel-ml.tgz/
tar -xzvf kernel-ml.tgz
rpm -Uvh kernel-ml/*
 
# 检查默认内核版本是否为4.18,否则请调整默认启动参数
grub2-editenv list
 
#重启以更换内核
reboot
 
# 确认内核版本
uname -a
 
# 确认内核版本为4.18后,开启IPVS
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
 
#!/bin/bash
ipvs_modules="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 nf_conntrack_ipv4"
for kernel_module in \${ipvs_modules}; do
 /sbin/modinfo -F filename \${kernel_module} > /dev/null 2>&1
 if [ $? -eq 0 ]; then
 /sbin/modprobe \${kernel_module}
 fi
done
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep ip_vs

执行sysctl -p报错请参考centos7添加bridge-nf-call-ip6tables出现No such file or directory

Kubernetes要求集群中所有机器具有不同的Mac地址、产品uuid、Hostname。可以使用如下命令查看Mac和uuid

# 所有主机:检查UUID和Mac

cat /sys/class/dmi/id/product_uuid
ip link

安装配置Docker

Docker从1.13版本开始调整了默认的防火墙规则,禁用了iptables filter表中FOWARD链,这样会引起Kubernetes集群中跨Node的Pod无法通信,因此docker安装完成后,还需要手动修改iptables规则。

安装私有镜像库

如果不能翻墙,需要使用本文提供的私有镜像源,则还需要为docker做如下配置,将K8s官方镜像库的几个域名设置为insecure-registry,然后设置hosts使它们指向私有源。

# 所有主机:http私有源配置

# 为Docker配置一下私有源
mkdir -p /etc/docker
echo -e '{\n"insecure-registries":["k8s.gcr.io", "gcr.io", "quay.io"]\n}' > /etc/docker/daemon.json
systemctl restart docker
 
# 此处应当修改为harbor所在机器的IP
HARBOR_HOST="10.130.38.80"
# 设置Hosts
yes | cp /etc/hosts /etc/hosts_bak
cat /etc/hosts_bak|grep -vE '(gcr.io|harbor.io|quay.io)' > /etc/hosts
echo """
$HARBOR_HOST gcr.io harbor.io k8s.gcr.io quay.io """ >> /etc/hosts

下载链接:链接:https://pan.baidu.com/s/10qwKtvVCeCRHccLrN-zQHg 提取码:ip4z,随后将该文件放置到harbor机器上,并在harbor主机上加载、启动该镜像

# harbor:启动私有镜像库

docker load -i /path/to/k8s-repo-1.12.1
docker run --restart=always -d -p 80:5000 --name repo harbor.io:1180/system/k8s-repo:v1.12.1

该镜像库中包含如下镜像,全部来源于官方镜像站。

1.12.1版本镜像列表

安装配置kubernetes

基本安装

首先下载链接:链接:https://pan.baidu.com/s/1ETQoH6RmcZ34n5IscR9RLQ 提取码:ntc6,并放置在k8s各个master和worker主机上

# master & worker:安装kubernetes

yum install -y socat keepalived ipvsadm
cd /path/to/downloaded/file
tar -xzvf k8s-v1.12.1-rpms.tgz
cd k8s-v1.12.1
rpm -Uvh *
systemctl enable kubelet
kubeadm version -o short

配置免密码登陆

# master-1:生成ssh密钥对

ssh-keygen
# 三次回车后,密钥生成完成
cat ~/.ssh/id_rsa.pub
# 得到该机器的公钥如下图

将该公钥复制,并分别登陆到master-1 master-2 master-3的root用户,将它令起一行粘贴到 ~/.ssh/authorized_keys 文件中,包括master-1自己

复制完成后,从master-1上分别登陆master-1 master-2 master-3测试是否可以免密码登陆(请不要跳过这一步),可以的话便可以继续执行下一步

部署HA Master

HA Master的部署过程已经自动化,请在master-1上执行如下命令,并注意修改IP和Hostname

# 部署HA master

cd ~/
 
# 创建集群信息文件
echo """
CP0_IP=10.130.29.80
CP0_HOSTNAME=centos-7-x86-64-29-80
CP1_IP=10.130.29.81
CP1_HOSTNAME=centos-7-x86-64-29-81
CP2_IP=10.130.29.82
CP2_HOSTNAME=centos-7-x86-64-29-82
VIP=10.130.29.83
NET_IF=eth0
CIDR=10.244.0.0/16
""" > ./cluster-info
 
bash -c "$(curl -fsSL https://raw.githubusercontent.com/Lentil1016/kubeadm-ha/1.12.1/kubeha-gen.sh)"
# 该步骤将可能持续2到10分钟,在该脚本进行安装部署前,将有一次对安装信息进行检查确认的机会

可以在该链接查看我在自己的环境上安装全过程的录像,安装结束后会打印出如下的信息,最后一行为加入集群的命令,其中加入集群的IP已经被更换为了高可用的VIP。

访问dashboard

如果需要访问kubernetes dashboard或traefik dashboard,只需要在浏览器所在机器上配置到任意master的hosts解析,然后访问对应域名即可。

echo """
10.130.29.80 dashboard.multi.io ingress.multi.io""" >> /etc/hosts

测试发现有时kubernetes dashboard容器会不响应请求,如果出现该情况请尝试删除dashboard的pod以重新启动该pod,即可解决该问题。

安装helm

如果需要安装helm,请先下载离线包链接:https://pan.baidu.com/s/1RZ8WOHQHQ951h2qlna85ig 提取码:02ni

cd /path/to/helm-v2.11.0-linux-amd64.tar/
tar -xzvf helm-v2.11.0-linux-amd64.tar
cd linux-amd64
cp helm /usr/local/bin
helm init --service-account=kubernetes-dashboard-admin --skip-refresh --upgrade
helm version

加入work node

现在可以将各节点入编到集群中。join command是由kubeadm动态生成的,其基本形式如下

# worker:将worker编入集群
kubeadm join 10.130.29.83:6443 --token 4n3hvt.sb8qjmno6l47tsww --discovery-token-ca-cert-hash sha256:a7f1de577bd8677a5d7fe4d765993645ae25d8b52a63a1133b74a595a7bb2e0f

其中包含了节点入编集群所需要携带的验证token,以防止外部恶意的节点进入集群。每个token自生成起24小时后过期。届时如果需要加入新的节点,则需要重新生成新的join token,请使用下面的命令生成,注意改写IP:

# master-1:生成指向VIP的Join Command
kubeadm token create --print-join-command|sed 's/${LOCAL_IP}/${VIP}/g'

随后到worker节点执行刚刚生成的join command即可将该节点编入集群。

至此,HA master Kubernetes 集群搭建完毕


Lentil Sun
Channelsoft Software Engineer
Mail: lentil1016@gmail.com
Site: https://lentil1016.cn
Github: https://github.com/Lentil1016

 

K8S中文社区微信公众号

评论 31

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #10

    问一问,Hyperkube 组件是用在哪里? 1.12.1对比以前1.11.0的大版本有哪里不一样?

    译风4周前 (10-26)回复
    • hyperkube是Prometheus部署会用到
      kubeadm的配置文件api版本变成v1alpha3了,结构和以前大不一样了,目前影响到我的只有这个。证书轮换功能以前我挺需要的,现在不用了,所以。。。
      其他都是些小变化,大多数在我的能力和视野之外。

      lentil10164周前 (10-26)回复
  2. #9

    vip可以绑定域名吗

    13周前 (10-29)回复
    • 不太可能,VIP这一配置主要是给keepalived用的,首先我没找到这样配置keepalived的文档。其次keepalived要拿这个IP在多个机器间争抢,如果经过一层DNS,keepalived很难知道这个过程中有没有做过DNS负载均衡,导致两次拿的IP不同。所以keepalived不太可能支持配置hostanem为VIP。

      lentil10163周前 (10-29)回复
  3. #8

    [root@localhost ~]# /sbin/modinfo -F filename nf_conntrack_ipv4
    modinfo: ERROR: Module nf_conntrack_ipv4 not found.
    [root@localhost ~]#

    bhj_dysf2周前 (11-04)回复
    • 我也遇到了这个问题 内核更新到 4.19 没有 nf_conntrack_ipv4

      annda2周前 (11-07)回复
      • 我写这篇的时候kernel-ml分支还在4.18版本,可能是4.19已经把nf_conntrack_ipv4.ko这个模块内置到内核里了,应该把最后那项去掉就可以了,我一会试一下,如果可以的话我会更新一下文章。

        lentil10162周前 (11-08)回复
      • 由于4.19版本内核将nf_conntrack_ipv4更名为nf_conntrack,目前的kube-proxy不支持在4.19版本内核下开启ipvs,详情可以查看:https://github.com/kubernetes/kubernetes/issues/70304
        对于该问题,由于修复9天前刚刚合并,所以还没有包含此修复的版本
        目前读者可以选择安装4.18版本内核,或者不开启IPVS

        lentil10162周前 (11-08)回复
  4. #7

    nf_conntrack_ipv4这个模块没有 ,怎么办啊

    bhj_dysf2周前 (11-04)回复
    • 我不清楚你遇到的是什么问题
      ls /lib/modules/$(uname -r)/kernel/net/ipv4/netfilter/nf_conntrack_ipv4.ko
      建议先执行这个命令查看那个内核模块存不存在,这个文件通常是直接包含在内核的本体RPM包中,例如kernel-ml-4.18.12-1.el7.elrepo.x86_64.rpm。所以它会和内核一起安装,不存在漏装或安装失败的情况,如果没有的话可能说明你的rpm源有问题。

      lentil10162周前 (11-06)回复
      • 就是按照文档添加的源啊

        annda2周前 (11-07)回复
      • 我试了一下 kernel-ml-4.18.12-1.el7.elrepo.x86_64.rpm 这个版本,确实是有 nf_conntrack_ipv4 的。现在 elrepo 源提供的 kernel-ml-4.19.1-1.el7.elrepo.x86_64 确实没有 nf_conntrack_ipv4,谷歌了以下 coreos 那边用了 4.19 内核好像也存在类似问题

        annda2周前 (11-07)回复
        • 由于4.19版本内核将nf_conntrack_ipv4更名为nf_conntrack,目前的kube-proxy不支持在4.19版本内核下开启ipvs,详情可以查看:https://github.com/kubernetes/kubernetes/issues/70304
          对于该问题,由于修复9天前刚刚合并,所以还没有包含此修复的版本
          目前读者可以选择安装4.18版本内核,或者不开启IPVS

          lentil10162周前 (11-08)回复
        • 你是怎么把内核版本升特定到4.28的,貌似有点复杂啊

          雾非雾1周前 (11-12)回复
        • 4.18

          雾非雾1周前 (11-12)回复
          • 您好,我在“进行系统配置”章节给了包,请注意看注释

  5. #6

    4.19.1-1.el7这个内核版本确实没有nf_conntrack_ipv4

    雾非雾2周前 (11-08)回复
    • 由于4.19版本内核将nf_conntrack_ipv4更名为nf_conntrack,目前的kube-proxy不支持在4.19版本内核下开启ipvs,详情可以查看:https://github.com/kubernetes/kubernetes/issues/70304
      对于该问题,由于修复9天前刚刚合并,所以还没有包含此修复的版本
      目前读者可以选择安装4.18版本内核,或者不开启IPVS

      lentil10162周前 (11-08)回复
  6. #5

    centos-7-x86-64-29-80 master-1 10.130.29.80
    centos-7-x86-64-29-81 master-2 10.130.29.81
    centos-7-x86-64-29-82 master-3 10.130.29.82
    – Virtual IP 10.130.29.83
    这几个IP地址在29段,其他在38段,这是有意要做成这样吗?29段和38段怎么互通呢?

    laozhang2周前 (11-09)回复
    • 这是无意的,公司的内网网段是10.130.0.0/16,这几个38网段的只是恰巧开在了这个网段而已。Kubernetes对网络的要求是不太高的,只要两台机器之间的网络是平整的,不经过NAT就可以路由就可以。具体使用哪个网段,可以由读者个人的网络环境决定。

      lentil10162周前 (11-09)回复
      • 非常感谢。

        laozhang2周前 (11-09)回复
  7. #4

    使用脚本是出现如下错误:
    [init] this might take a minute or longer if the control plane images have to be pulled

    Unfortunately, an error has occurred:
    timed out waiting for the condition

    This error is likely caused by:
    – The kubelet is not running
    – The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)

    If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
    – ‘systemctl status kubelet’
    – ‘journalctl -xeu kubelet’

    Additionally, a control plane component may have crashed or exited when started by the container runtime.
    To troubleshoot, list all containers using your preferred container runtimes CLI, e.g. docker.
    Here is one example how you may list all Kubernetes containers running in docker:
    – ‘docker ps -a | grep kube | grep -v pause’
    Once you have found the failing container, you can inspect its logs with:
    – ‘docker logs CONTAINERID’
    couldn’t initialize a Kubernetes cluster
    Waiting for etcd bootup…

    怀疑是harbor机器那边出现问题导致的。怎么检查harbor那边是正常的?
    谢谢!

    laozhang1周前 (11-10)回复
  8. #3

    [root@centos7-h1 ~]# docker ps -a
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    3123ffe6479d harbor.io:1180/system/k8s-repo:v1.12.1 “/entrypoint.sh /e…” 9 minutes ago Up 9 minutes 0.0.0.0:80->5000/tcp repo
    [root@centos7-h1 ~]# netstat -na |grep LIST
    tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
    tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
    tcp 0 0 192.168.122.1:53 0.0.0.0:* LISTEN
    tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
    tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
    tcp6 0 0 ::1:25 :::* LISTEN
    tcp6 0 0 :::111 :::* LISTEN
    tcp6 0 0 :::80 :::* LISTEN
    tcp6 0 0 :::22 :::* LISTEN
    tcp6 0 0 ::1:631 :::* LISTEN

    发现不知道为何harbor的80端口是没有监听。

    laozhang1周前 (11-10)回复
    • 你的kubelet启动失败了,建议首先执行journalctl -uf kubelet,随后另开一个终端执行systemctl restart kubelet查看kubelet启动的过程中报了什么错误

      lentil10161周前 (11-11)回复
  9. #2

    1.12搭建完了。三个master里,coredns的podip用docker0,没有用calico。。。这个遇到过没有

    weeknd1周前 (11-13)回复
    • 您好,这是由一个Kubeadm的已知问题造成的,我昨天更新了脚本,对该问题进行了修复,重新执行脚本进行部署后该问题应当不会再出现了

  10. #1

    master2、master3设置–cluster-cidr=10.244.0.0/16,但是部署到master2和master3上时,pod分配的ip确实172.17.0.0/16(docker的所属的网段),不知是什么原因

    nika1周前 (11-13)回复
    • 大兄弟,装的什么版本1.12.1还是1.12.2

      weeknd6天前回复
      • 解决了master2和master3没有启用calico网络

        nika6天前回复
        • 不是daemonset吗。为何没有启动啊。你改了啥地方

          weeknd5天前回复
    • 您好,这是由一个Kubeadm的已知问题造成的,我昨天更新了脚本,对该问题进行了修复,重新执行脚本进行部署后该问题应当不会再出现了