我是一名正在搞serverless相关内容的研究生,大类是云计算、分布式。这类论文大概可以分成两类,一类是使用仿真脚本模拟集群,实现优化算法;另一类是基于真实平台部署。我的第一个工作是实现了一个serverless仿真平台 https://github.com/340Lab/serverless_sim,并基于它做扩缩容和调度策略的研究,但在投论文时遭遇了针对仿真的可靠性的质疑。相比之下,真实平台有更多的dirty work和对不同影响因素的tradeoff,工作量更大,含金量也更高。因此想试一试做更实在的工作,进行真实框架的优化研究。 由于当前大部分开源serverless框架都需要k8s,因此需要在实验室里搭起一片小集群,装上k8s。小集群是用实验室角落里积灰的pc机组的。大概是下面这个粗糙的样子:
添加图片注释,不超过 140 字(可选)
k8s就不多赘述了,前身是borg,也是现在云原生核心基建。在此之前我只尝试过单机k8s kind以及使用GitHub - KubeOperator/KubeOperator: KubeOperator 是一个开源的轻量级 Kubernetes 发行版,专注于帮助企业规划、部署和运营生产级别的 K8s 集群。部署k8s。kind这种单机只能做做完整性测试,性能测试是没法用的。kubeoperator是用的ansible,相较于手动部署成功率高一些,但是还是偶尔会出问题,同时部署端无法成为集群一员。因此这次将实现看向了k3s,之前也有所耳闻,具体去了解后发现他确实很轻量。每个节点只要有一个基本agent就行,agent管控每一个节点的基本配置,安装也是一键脚本。再也不用装这装那,配这配那了。
最后的完整方案脚本:paTools/k3s at main · ActivePeter/paTools · GitHub,修改config.yml配置好集群ip,按顺序执行脚本即可。
首先我试了autok3s图形界面设置,发现不行。然后我试了k3sup,发现对部署节点具有访问外网的要求,一时没找到代理方法。最后直接去看k3s文档了,发现k3s有一个离线部署方案,也就是只要把bin,镜像下载好,传到每一个节点上,执行下安装,就完事了。离线安装 | Rancher文档 让我们来把这个过程自动化一点吧
跟着教程来就行,对应到我的脚本的 1.prepare_local.py 准备k3s安装相关资源,此处如果网不好可以先export一下代理HTTP_PROXY和HTTPS_PROXY。最终我们准备好k8s, k3s-airgap-images-amd64.tar.gz 和 install.sh
为了实现把必要文件上传到对应节点执行就能达到安装的效果,我对安装脚本进行了封装。首先我们将必要的安装文件传输到了/tmp/k3s中,安装脚本负责做的事情是1将其复制到真正需要的位置,2配置好安装环境变量,3执行安装脚本。install_server.py 中心节点安装,k3s叫server
# prepare env
os_system_sure("cp /tmp/k3s/k3s /usr/local/bin/k3s")
os_system_sure("chmod +x /usr/local/bin/k3s")
os_system_sure("mkdir -p /var/lib/rancher/k3s/agent/images/")
os_system_sure("cp /tmp/k3s/k3s-airgap-images-amd64.tar.gz /var/lib/rancher/k3s/agent/images/")
# install
os.chdir("/tmp/k3s")
os.environ['INSTALL_K3S_SKIP_DOWNLOAD']="true"
os_system_sure("bash ./install.sh")
install_worker.py k3s叫agent,更复杂一点,因为传入k3s_token和server_ip 这两个都是动态的,根据具体的配置有差异,因此我先准备了一个install_woker_tmp.py,对应变量留空,后续替换实际内容
K3S_TOKEN=
SERVER_IP=
# prepare env
os_system_sure("cp /tmp/k3s/k3s /usr/local/bin/k3s")
os_system_sure("chmod +x /usr/local/bin/k3s")
os_system_sure("mkdir -p /var/lib/rancher/k3s/agent/images/")
os_system_sure("cp /tmp/k3s/k3s-airgap-images-amd64.tar.gz /var/lib/rancher/k3s/agent/images/")
# install
os.chdir("/tmp/k3s")
os.environ['INSTALL_K3S_SKIP_DOWNLOAD']="true"
# K3S_URL=https://myserver:6443 K3S_TOKEN=mynodetoken
os.environ['K3S_URL']=f"https://{SERVER_IP}:6443"
os.environ['K3S_TOKEN']=f"{K3S_TOKEN}"
os_system_sure("bash ./install.sh")
首先我定义了一个config.yml,表示集群成员,is_master 标注是中心节点
lab1:
ip: 192.168.31.162
is_master:
lab2:
ip: 192.168.31.87
lab7:
ip: 192.168.31.89
....
后续远程指令以及上传文件要让节点间能够不使用密码互信才方便,对应0.ssh_direct.py,就是ssh-keygen生成密钥,ssh-copy-id拷贝到远程,只需要输入一次密码即可。
然后首先安装server,对应2.up_master.py,把必要的文件传到tmp,然后执行安装脚本即可
# prepare remote
os_system_sure(f"ssh root@{master_ip} 'mkdir -p /tmp/k3s'")
os_system_sure(f"scp k3s root@{master_ip}:/tmp/k3s/k3s")
os_system_sure(f"scp k3s-airgap-images-amd64.tar.gz root@{master_ip}:/tmp/k3s/k3s-airgap-images-amd64.tar.gz")
os_system_sure(f"scp install.sh root@{master_ip}:/tmp/k3s/install.sh")
os_system_sure(f"scp install_server.py root@{master_ip}:/tmp/k3s/install_server.py")
os_system_sure(f"ssh root@{master_ip} 'ls /tmp/k3s/'")
# remote run
os_system_sure(f"ssh root@{master_ip} 'python3 /tmp/k3s/install_server.py'")
然后安装每一个agent,对应3.up_worker.py,这里首先要获取一下k3s token,替换一下tmp中对应的环境变量, 然后和master一样,上传必要的文件,执行安装脚本
for node, conf in config_data.items():
if 'is_master' in conf:
continue
ip=conf['ip']
# prepare remote
os_system_sure(f"ssh root@{ip} 'mkdir -p /tmp/k3s'")
os_system_sure(f"scp k3s root@{ip}:/tmp/k3s/k3s")
os_system_sure(f"scp k3s-airgap-images-amd64.tar.gz root@{ip}:/tmp/k3s/k3s-airgap-images-amd64.tar.gz")
os_system_sure(f"scp install.sh root@{ip}:/tmp/k3s/install.sh")
os_system_sure(f"scp install_worker.py root@{ip}:/tmp/k3s/install_worker.py")
os_system_sure(f"ssh root@{ip} 'ls /tmp/k3s/'")
# remote run
os_system_sure(f"ssh root@{ip} 'python3 /tmp/k3s/install_worker.py'")
对应5.kubectl_local.py,需要把server的配置拿过来,把ip换成server节点的局域网ip
# copy /etc/rancher/k3s/k3s.yaml to ~/.kube/config
os_system_sure(f"scp root@{master_ip}:/etc/rancher/k3s/k3s.yaml k3s.yaml")
with open("k3s.yaml", 'r') as stream:
k3s_config = stream.read()
stream.close()
if k3s_config.find("server: https://127.0.0.1")==-1:
print("unsupported k3s config, please check")
exit(1)
k3s_config=k3s_config.replace("server: https://127.0.0.1", f"server: https://{master_ip}")
stream = open("k3s.yaml", 'w')
stream.write(k3s_config)
stream.close()
# set to ~/.kube/config
os_system_sure("mkdir -p ~/.kube")
os_system_sure("cp k3s.yaml ~/.kube/config")
在起openwhisk时候遇到了代理问题,k3s文档里提到配一下服务环境变量即可,server和agent服务名不一样,对应6.setup_proxy.py。https://docs.k3s.io/zh/advanced#%E9%85%8D%E7%BD%AE-http-%E4%BB%A3%E7%90%86
for node, conf in config_data.items():
ip=conf['ip']
PROXY="http://192.168.31.53:7890"
export=f"""
HTTP_PROXY={PROXY}
HTTPS_PROXY={PROXY}
NO_PROXY=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
"""
# prepare remote
if 'is_master' in conf:
os_system_sure(f"ssh root@{ip} 'echo \"{export}\" >> /etc/systemd/system/k3s.service.env'")
os_system_sure(f"ssh root@{ip} 'systemctl daemon-reload'")
os_system_sure(f"ssh root@{ip} 'systemctl restart k3s'")
else:
os_system_sure(f"ssh root@{ip} 'echo \"{export}\" >> /etc/systemd/system/k3s-agent.service.env'")
os_system_sure(f"ssh root@{ip} 'systemctl daemon-reload'")
os_system_sure(f"ssh root@{ip} 'systemctl restart k3s-agent'")
但是还是遇到了pod内没有走代理的问题,提issue问了后发现,对containerd的代理并不会传递到真实pod实例的环境变量,因此最后的办法只有给路由器上。https://github.com/k3s-io/k3s/issues/10110