华为鲲鹏云calico网络组件适配aarch64架构攻关报告

敏敏君主 发表于 2019/10/25 16:45:20 2019/10/25
【摘要】 华为鲲鹏云环境,解放云盘测试部同事将k8s(1.9.2)集群移植到aarch64架构平台上,使用calico作为集群的网络组件时,集群pods之间无法通信,集群异常,针对此问题进行定位,并分析其根因,提出解决方案,并针对这一问题进行扩展,深入剖析x86与arm架构之间的差异...

 

问题现象

    华为鲲鹏云环境,解放云盘测试部同事将k8s1.9.2)集群移植到aarch64架构平台上,使用calico作为集群的网络组件时,集群pods之间无法通信,集群异常。

环境信息

类别

子项

版本

获取地址(方法)

华为云

虚拟机

RC3916

NA

OS

 

CentOS

 

7.6.1810


Kernel

4.14.0-49.el7a.aarch6464

iso 自带

软件包

 

kubelet

 

1.9.2

https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-aarch64/

 

docker-ce

 

18.06.03

https://mirrors.aliyun.com/docker-ce/linux/centos/7/aarch64/stable/Packages/docker-ce-18.06.3.ce-3.el7.aarch64.rpm

Calico

v3.2

https://docs.projectcalico.org/v3.8/introduction/

  

定位分析

calico是什么?

calico利用Linux内核原生的路由和iptables防火墙功能。进出各个容器,虚拟机和主机的所有流量都会在路由到目标之前遍历这些内核路由规则。它是一个纯三层路由方案。参考http://ju.outofmemory.cn/entry/367749

 

calicok8s的关系,在k8s集群中的角色?

 

callico可以作为k8s的网络组件,为k8s集群间通信提供解决方案。由以下几部分组成:

 

etcd: calico后端存储,Calico使用etcd提供组件之间的数据通信,并作为可以保证一致性的数据存储,以确保Calico始终可以构建出一个准确的网络。

Flex:对应容器Calico-nodeCalico agent,运行在每台node上,为容器设置网络信息,IP,路由规则,iptable规则等

BIRD:  BGP Client 负责把Felix在各node上设置的路由信息广播到Calico网络(通过BGP协议)

BGP Route Reflector 大规模集群的分级路由分发。

calicoctlcalico命令行管理工具

 

 

依照官网https://docs.projectcalico.org/v3.2/getting-started/kubernetes/requirements

指导文档给出的x86_64平台部署方法(k8s 1.9版本适配calico3.1或者3.2版本),在华为鲲鹏云上进行部署,移植过程中遇到问题再进行解决。

部署环境:master节点和node节点 centos7.5 arm64

 

1.     部署基础环境

1)部署之前关闭selinux和防火墙

   终端执行getenforce 如果返回Disabled说明selinux已经关闭;否则修改配置文件后,重启后生效,具体方法如下

   vi 编辑/etc/selinux/config,修改其中的SELINUX值为disabled,参考下图

   image.png

   完成后保存退出,执行reboot,重启机器,关闭selinux,必须重启主机才能生效

 (2)编辑/etc/hosts 写上主机名和ip;集群所有节点之间都能相互解析,参考下图写法

   image.png

(3)关闭swap分区

   执行命令

    swapoff -a

image.png

     命令free -h 看到的swap总量一定是0

   

2.     执行以下命令关闭防火墙,并设置开机不自启

   

systemctl stop   firewalld.service

systemctl disable   firewalld.service

 

3.     安装docker

配置docker的阿里云repo源,请确保你的主机能够访问外网

vi编辑 /etc/yum.repos.d/docker.repo,该文件默认没有,需要自行编写保存

依次写入

[Docker]

name=Docker repo

baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/aarch64/stable/

gpgcheck=0

 image.png

 完成后执行以下命令

yum clean all

yum repolist

 预期会显示Docker源中的rpm包数量


image.png

执行以下命令安装docker 18.06.03

yum install   docker-ce-18.06*

预期安装成功

 

添加谷歌代理进行加速

vi 编辑/usr/lib/systemd/system/docker.service,在[Service]标签后添加以下内容

Environment=PATH=/usr/libexec/docker:/usr/bin:/usr/sbin

Environment="HTTPS_PROXY=socks5://10.10.64.7:1080"

Environment="HTTP_PROXY=socks5://10.10.64.7:1080"

Environment="NO_PROXY=localhost,127.0.0.0/8,10.0.0.0/8,::1,/var/run/docker.sock"

      参考下图

image.png

编辑完成后,保存退出执行以下命令使修改配置生效

systemctl   daemon-reload

启动docker

systemctl start   docker

systemctl enable   docker

执行systemctl status docker 查看当前docker服务状态,处于运行中


image.png

可以通过docker info命令获取docker详细信息

4.     安装kubelet

配置kubelet的阿里云repo源,请确保你的主机能够访问外网

vi编辑 /etc/yum.repos.d/kubelet.repo,该文件默认没有,需要自行编写保存

依次写入

[kubelet]

name=Kubelet repo

baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-aarch64/

gpgcheck=0

  

image.png

 完成后,执行以下命令

yum clean all

yum repolist

 

 预期会显示kubelet源中的rpm包数量

image.png

image.png

执行以下命令完成kubelet 1.9.2版本的安装,请分别安装,否则会报错

yum install   kubelet-1.9.2 -y

yum install   kubectl-1.9.2 kubeadm-1.9.2 -y

 完成后执行以下命令设置开机自启动

systemctl enable   kubelet

 5.     初始化k8s集群

执行

kubeadm init   --kubernetes-version=v1.9.2    --pod-network-cidr=192.168.0.0/16

    image.png

 

    遇到下图的报错

   image.png

   解决方案:

   vi编辑文件/etc/systemd/system/kubelet.service.d/10-kubeadm.conf

修改Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=systemd"

Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=cgroupfs"

   image.png

   完成后执行systemctl daemon-reload 是修改生效

   执行rm -f /etc/kubernetes/* 后再次执行kubeadm init --kubernetes-version=v1.9.2  --pod-network-cidr=192.168.0.0/16进行初始化,成功后,保存token

image.png 

 复制kubelet的配置文件

mkdir -p   $HOME/.kube

cp -i   /etc/kubernetes/admin.conf $HOME/.kube/config

image.png

kubectl get pods --all-namespaces -o wide 查看各pod的状态kube-dns处于Pending状态,是由于还没安装网络组建

 

6.     安装网络组件calico

calico 3.1版本,该版本是x86_64架构上与kubelet 1.9.2匹配的版本

执行

kubectl apply -f \

https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/kubeadm/1.7/calico.yaml

预期见下图


image.png

 去除master污点将其纳入集群

kubectl taint   nodes --all node-role.kubernetes.io/master-

 到此,原则上如果移植成功,那么执行kubectl get pods --all-namespaces -o wide应该看到所有pod都是running状态,



实际结果
calico-node容器errorcalicoetcd容器异常

image.png

执行kubectl get pods 查看 master状态应该是Ready状态。实际结果是Notready

image.png

 

7. 定位分析

对集群中异常状态的三个容器进行分析

##Calico-etcd容器异常

执行journalctl -f 动态查看日志,存在下图中的报错

image.png

分析该段日志只是报告了启动容器calico-etcd重启失败了,原因也没有明确的说明。尝试从容器自身入手,寻找原因。

docker ps -a |grep etcd 找到calico-etcd容器

image.png

可以看出正式日志中所报重启失败的容器,名称为etcd_calico-etcd-nqvbh 确认后,发现该容器执行/usr/local/bin/etcd命令,那么很有可能是该二进制出问题了

执行dcoker ps -a |grep etcd 拿到id后,即刻复制出来二进制文件etcd,该id随着容器的不断重启会改变。

image.png

 

  ls 查看bin目录下有哪些文件

image.png

  考虑到架构的差异,使用file命看一下etcdetcdctl的架构,是x86_64架构

image.png

 

  解决该容器的二进制架构问题

 

  docker image ls 找到该容器

image.png

  将该容器运行起来,把容器中/usr/local/bin目录复制到本地重命名为test,使用file命令查看二进制架构,为x86_64

执行以下操作

docker run   --name test -itd quay.io/coreos/etcd:v3.1.10

docker cp   test:/usr/local/bin/ ./test

file test/*

 

image.png

更换该容器

wgetcalicoyaml文件下载到本地

image.png

docker.hub上查找arm64架构的calico-etcd的镜像

https://hub.docker.com/r/quayio/coreos-etcd

取版本接近的镜像

image.png

修改calico.yaml文件v3.1.10标签为v3.2.1-arm64

image.pngimage.png

 

重新初始化集群,执行

kubeadm reset

iptables -F

kubeadm init   --kubernetes-version=v1.9.2    --pod-network-cidr=192.168.0.0/16

cp -i   /etc/kubernetes/admin.conf $HOME/.kube/config

kubectl apply -f   calico.yaml

image.png

 

 

image.png

再次查看各pods状态,发现仍是异常的

同样的办法复制异常容器中的/usr/local/bin/etcd 发现架构没问题,已经是aarch64架构的了

image.png

执行journalctl -f 查看相关日志和之前一样也是重启失败

image.png

更换容器这条路子行不通

 

查看异常容器calico-cni的执行脚本,未发现端倪

image.png

查看calico-node的容器中文件属性,发现同样是x86_64架构

image.png

该容器在dockerhub上暂无arm64架构,二进制calico-felix容易编译,其他二进制文件编译起来,工量较大,且是否可用也未知。

 

根据在k8s 1.15.2上使用calico3.8版本,移植arm64平台成功的经验,采用calico 3.8来适配k8s 1.9.2

 

使用calico最新版本3.8

重新初始化集群,执行

kubeadm reset

iptables -F

kubeadm init   --kubernetes-version=v1.9.2    --pod-network-cidr=192.168.0.0/16

cp -i   /etc/kubernetes/admin.conf $HOME/.kube/config

kubectl apply -f   https://docs.projectcalico.org/v3.8/manifests/calico.yaml

 

查看节点状态全部running

kubectl get pods   --all-namespaces -o wide

 

image.png

master纳入集群,查看mater状态已经Ready

kubectl taint   nodes --all node-role.kubernetes.io/master-

kubectl get   nodes -o wide

 

image.png

 

node节点进入集群

kubeadm join   --token df2842.dd1c942841b38f1f 10.10.64.71:6443   --discovery-token-ca-cert-hash   sha256:69e5e0c33064b8a5017ddc0a20c5ed2eb1fb2d1ccb996f966205e1ad72f40c31

 

image.png

matser节点查看集群状态,所有容器全部running

kubectl get pods   --all-namespaces -o wide

 

image.png

查看masternode是否Ready

kubectl get   nodes

 

image.png

master节点执行journactl -f动态观察日志打印,无异常错误日志输出

 

iptables -nL查看路由规则,发现已经部署上了。

image.png

 

整个集群状态已经正常

 

实例化的nginx已经正常运行10小时

kubectl run   --image=nginx nginx-app --port=8099

 

image.png

 

根因分析

calico 3.2 版本,官方提供的calico.yaml文件,所获取的镜像,仅适配x86_64架构,未提供aarch64架构的容器镜像。

解决方案

k8s 1.9.2版本建议使用calico版本3.8作为网络组件。

问题扩展

尝试k8s最高版本1.15,适配calico3.8版本进行测试,发现依然存在问题?pod2daemon-flexvol容器中的flexvol架构为x86_64,需要手动编译出arm64架构的二进制文件去替换镜像中的x86架构的flexvol。或者重新制作pod2daemon-flexvol容器镜像。

二进制文件flexvol编译

1.       github下载源码

执行以下命令

git clone https://github.com/projectcalico/pod2daemon.git

2.       进入git clone下来的目录中pod2daemon

cd pod2daemon-3.8.1


image.png


修改Makefile文件

vi编辑Makefile

修改GO_BUILD_VER?=master-arm64

image.png

DOCKER_RUN后添加golang的代理

-e GOPROXY=https://goproxy.io \

image.png

3.       保存退出Makefile后,执行make build构建二进制

image.png

预期在bin目录下会构建出来flexvol-arm64的二进制文件,file 查看为arm64架构

image.png

Docker镜像制作

  1.        github下载源码

 执行以下命令

 git clone https://github.com/projectcalico/pod2daemon.git

2.       进入git clone下来的目录中pod2daemon

cd pod2daemon-3.8.1

image.png

修改Makefile文件

vi编辑Makefile

修改GO_BUILD_VER?=master-arm64

image.png

DOCKER_RUN后添加golang的代理

-e GOPROXY=https://goproxy.io \

image.png

3.       保存退出Makefile后,执行make image构建docker镜像

预期构建成功,并保存本地,使用docker images 可以查看到

image.png

image.png


 

 

 

 


spacer.gif

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。