华为鲲鹏云calico网络组件适配aarch64架构攻关报告
问题现象
华为鲲鹏云环境,解放云盘测试部同事将k8s(1.9.2)集群移植到aarch64架构平台上,使用calico作为集群的网络组件时,集群pods之间无法通信,集群异常。
环境信息
类别 | 子项 | 版本 | 获取地址(方法) |
华为云 | 虚拟机 | RC3(916) | 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 |
定位分析
calico是什么?
calico利用Linux内核原生的路由和iptables防火墙功能。进出各个容器,虚拟机和主机的所有流量都会在路由到目标之前遍历这些内核路由规则。它是一个纯三层路由方案。参考http://ju.outofmemory.cn/entry/367749
calico与k8s的关系,在k8s集群中的角色?
callico可以作为k8s的网络组件,为k8s集群间通信提供解决方案。由以下几部分组成:
etcd: calico后端存储,Calico使用etcd提供组件之间的数据通信,并作为可以保证一致性的数据存储,以确保Calico始终可以构建出一个准确的网络。
Flex:对应容器Calico-node即Calico agent,运行在每台node上,为容器设置网络信息,IP,路由规则,iptable规则等
BIRD: BGP Client: 负责把Felix在各node上设置的路由信息广播到Calico网络(通过BGP协议)。
BGP Route Reflector: 大规模集群的分级路由分发。
calicoctl:calico命令行管理工具
依照官网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,参考下图
完成后保存退出,执行reboot,重启机器,关闭selinux,必须重启主机才能生效
(2)编辑/etc/hosts 写上主机名和ip;集群所有节点之间都能相互解析,参考下图写法
(3)关闭swap分区
执行命令
swapoff -a
命令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 |
完成后执行以下命令
yum clean all yum repolist |
预期会显示Docker源中的rpm包数量
执行以下命令安装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" |
参考下图
编辑完成后,保存退出执行以下命令使修改配置生效
systemctl daemon-reload |
启动docker
systemctl start docker systemctl enable docker |
执行systemctl status docker 查看当前docker服务状态,处于运行中
可以通过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 |
完成后,执行以下命令
yum clean all yum repolist |
预期会显示kubelet源中的rpm包数量
执行以下命令完成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 |
遇到下图的报错
解决方案:
vi编辑文件/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
修改Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=systemd"
为Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=cgroupfs"
完成后执行systemctl daemon-reload 是修改生效
执行rm -f /etc/kubernetes/* 后再次执行kubeadm init --kubernetes-version=v1.9.2 --pod-network-cidr=192.168.0.0/16进行初始化,成功后,保存token
复制kubelet的配置文件
mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config |
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 |
预期见下图
去除master污点将其纳入集群
kubectl taint nodes --all node-role.kubernetes.io/master- |
到此,原则上如果移植成功,那么执行kubectl get pods --all-namespaces -o wide应该看到所有pod都是running状态,
实际结果calico-node容器error,calicoetcd容器异常
执行kubectl get pods 查看 master状态应该是Ready状态。实际结果是Notready
7. 定位分析
对集群中异常状态的三个容器进行分析
##Calico-etcd容器异常
执行journalctl -f 动态查看日志,存在下图中的报错
分析该段日志只是报告了启动容器calico-etcd重启失败了,原因也没有明确的说明。尝试从容器自身入手,寻找原因。
docker ps -a |grep etcd 找到calico-etcd容器
可以看出正式日志中所报重启失败的容器,名称为etcd_calico-etcd-nqvbh 确认后,发现该容器执行/usr/local/bin/etcd命令,那么很有可能是该二进制出问题了
执行dcoker ps -a |grep etcd 拿到id后,即刻复制出来二进制文件etcd,该id随着容器的不断重启会改变。
ls 查看bin目录下有哪些文件
考虑到架构的差异,使用file命看一下etcd和etcdctl的架构,是x86_64架构
解决该容器的二进制架构问题
docker image ls 找到该容器
将该容器运行起来,把容器中/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/* |
更换该容器
wget把calico的yaml文件下载到本地
到docker.hub上查找arm64架构的calico-etcd的镜像
https://hub.docker.com/r/quayio/coreos-etcd
取版本接近的镜像
修改calico.yaml文件v3.1.10标签为v3.2.1-arm64
重新初始化集群,执行
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 |
再次查看各pods状态,发现仍是异常的
同样的办法复制异常容器中的/usr/local/bin/etcd 发现架构没问题,已经是aarch64架构的了
执行journalctl -f 查看相关日志和之前一样也是重启失败
更换容器这条路子行不通
查看异常容器calico-cni的执行脚本,未发现端倪
查看calico-node的容器中文件属性,发现同样是x86_64架构
该容器在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 |
将master纳入集群,查看mater状态已经Ready
kubectl taint nodes --all node-role.kubernetes.io/master- kubectl get nodes -o wide |
将node节点进入集群
kubeadm join --token df2842.dd1c942841b38f1f 10.10.64.71:6443 --discovery-token-ca-cert-hash sha256:69e5e0c33064b8a5017ddc0a20c5ed2eb1fb2d1ccb996f966205e1ad72f40c31 |
到matser节点查看集群状态,所有容器全部running
kubectl get pods --all-namespaces -o wide |
查看master与node是否Ready
kubectl get nodes |
在master节点执行journactl -f动态观察日志打印,无异常错误日志输出
iptables -nL查看路由规则,发现已经部署上了。
整个集群状态已经正常
实例化的nginx已经正常运行10小时
kubectl run --image=nginx nginx-app --port=8099 |
根因分析
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 |
修改Makefile文件
vi编辑Makefile
修改GO_BUILD_VER?=master-arm64
DOCKER_RUN后添加golang的代理
-e GOPROXY=https://goproxy.io \
3. 保存退出Makefile后,执行make build构建二进制
预期在bin目录下会构建出来flexvol-arm64的二进制文件,file 查看为arm64架构
Docker镜像制作
从github下载源码
执行以下命令
git clone https://github.com/projectcalico/pod2daemon.git
2. 进入git clone下来的目录中pod2daemon
cd pod2daemon-3.8.1
修改Makefile文件
vi编辑Makefile
修改GO_BUILD_VER?=master-arm64
DOCKER_RUN后添加golang的代理
-e GOPROXY=https://goproxy.io \
3. 保存退出Makefile后,执行make image构建docker镜像
预期构建成功,并保存本地,使用docker images 可以查看到
- 点赞
- 收藏
- 关注作者
评论(0)