使用kubeadm建立kubernetes集群并部署Polyaxon详细教程
最近两三周我在学习 Docker 容器相关的知识,想要了解 Kubernetes 容器管理平台,并且使用开源的 Polyaxon 框架来管理集群进行机器学习的实验。目前已经部署成功了,这里记录一下部署过程。首先简单总结一下,就是先安装 Docker,再安装 Kubernetes,最后安装 Polyaxon。Kubernetes 的安装方式非常多,详见官方教程。这里我准备使用比较简单的方法,就是使用 Kubeadm 来自动安装 Kubenetes,但是这个方式与后续的 polyaxon 会有一定的冲突需要解决,请多加注意。
表一 部署命令总结
|
安装 Docker |
安装 Kubeadm |
Kubeadm init |
安装网络插件 |
Kubeadm join |
安装 helm |
安装 NFS |
安装 polyaxon |
Master |
需要 |
需要 |
需要 |
需要 |
不必,该命令只由 slave/worker 节点执行 |
需要 |
查看详情 |
需要 |
Slave/worker |
需要 |
需要 |
不必,该命令只由 Master节点执行 |
不必,加入集群之后会被自动安装 |
需要,且注意更改 hash token |
不必 |
查看详情 |
不必 |
准备工作先说一下。最基本的就是机器需要可以正常访问谷歌,因为 kubernete 相关的镜像文件就放在谷歌的服务器上,如果无法正常访问谷歌,那么后面安装的时候会经常卡到然后失败。当然也可以通过提前把这些需要的镜像下载下来,放在正确的路径以供机器使用,但是我没有这么做过,这个方法需要自己搜索一下怎么做。
- 在开始之前,需要有一台或多台机器运行如下系统之一:
- Ubuntu 16.04+
- Debian 9
- CentOS 7
- RHEL 7
- Fedora 25/26(尽力而为)
- HypriotOS v1.0.1 +
- Container Linux(1576.4.0版本测试过)
- 每台机器2 GB或更多的内存(更少的内存将为您的应用留下很小的空间)
- 2个CPU或更多
- 群集中所有计算机之间的网络互联互通(公网或内网网络都可以)
- 每台机器的唯一主机名,MAC地址和product_uuid。有关详细信息,请参见此处
- 某些端口在您的计算机防火墙上打开。有关详细信息,请参见此处
- 禁用 swap。必须禁用 swap 交换空间才能使 kubelet 正常工作。
我采用的是4台机器运行在同一个内网中,运行 Ubuntu 16.04 系统,每台机器 4GB 内存,2 CPU,关闭了 swap。虽然上面说内网外网互联都行,但是我没有测试过跨网段机器组建集群,只是在同一个子网中配置。
一. 安装 Docker
第一步是在集群中所有服务器上都要进行的工作,安装 Docker,具体来说是安装 docker-ce=17.03.2 的版本。因为 Docker 并不是天生就支持 Kubernetes 管理的,只有经过 Kubernetes 测试过的版本才被官方认为是符合生产环境条件的。官方目前建议使用 17.03 版本。Docker 的官方安装文档在这里,根据官方文档,我把所需要的命令行使用 && 符号合并起来,直接复制粘贴就可以运行了。
sudo apt-get remove docker docker-engine docker.io && sudo apt-get update && sudo apt-get install apt-transport-https ca-certificates curl software-properties-common -y && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && sudo apt-get update && apt-cache madison docker-ce && sudo apt-get install docker-ce=17.03.2~ce-0~ubuntu-xenial -y && sudo docker run hello-world
图一 安装完 docker 之后检查一下版本是否正确
二. 安装 Kubernetes
2.1 安装 kubeadm
第二步是在集群中安装 Kubernetes。再次重申,Kubernetes 的安装方式非常多,详见官方教程。这里我准备使用比较简单的方法,就是使用 Kubeadm 来自动安装。为了使安装过程中的 Kubelet 组件可以正常工作,需要禁用系统 swap,这一点前面已经提到了。如果你还没有禁用 swap,可以用 vi 修改 /etc/fstab 文件,在 swap 分区这行前加 # 禁用掉,保存退出然后重启电脑即可,具体操作方式可以搜索一下。然后安装 kubeadm、kubelet、kubectl 这三个组件。Kubeadm 的官方安装文档在这里,根据官方文档,我把所需要的命令行总结如下。
sudo apt-get update && sudo apt-get install -y apt-transport-https curl && curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - && sudo sh -c "cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF" && sudo apt-get update && sudo apt-get install -y kubelet kubeadm kubectl
图二 安装完 kubeadm 之后检查一下相关信息
注意一下,以前的 kubeadm 版本可能会改变 cgroup 驱动程序,导致跟 docker 使用的不一样,需要额外再配置一下。但是目前版本已经不会有问题了,大概从 kubeadm 1.8.4 版本以上就不需要了。我们使用的是 1.11.1 版本,也是不需要配置的。
2.2 安装集群
现在我们已经安装好了 kubeadm,可以使用它来自动创建 kubernetes 集群了。使用 kubeadm 创建 kubernetes 集群的官方文档在这里。首先需要安装集群,然后在集群上安装 pod 网络,以使 pod 之间可以互相通信。
安装集群非常简单,从你的机器中选择一台作为主节点,就是 Master 节点,在节点上执行初始化指令
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
初始化节点的命令是 kubeadm init <args>,我们上面这里增加了 pod-network-cidr 参数,是为了待会儿安装 pod 网络需要。Pod 网络有很多插件可以选择,详情请参见此处,我们使用 canal 插件,因为后续配置比较简单。上面的初始化指令执行之后,需要等待三到五分钟,Master 节点会自动下载好需要的镜像并且安装,然后会输出安装结果信息,耐心等待即可。例如输出信息如下。
图三 初始化集群的输出信息
最后的输出结果主要告诉我们三件事,一是如何给非 root 权限用户执行集群指令,二是需要安装 pod 网络插件,三是如何加入新的节点到集群来。这些都是我们需要做的。
首先执行它输出的命令,就是把 kubernetes 的配置信息复制到用户路径中,使得非 root 用户可以执行集群指令,不必每次都加一个 sudo 命令。这个代码是不变的,可以直接执行。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
当然,如果你是 root 用户的话,不必执行上面指令,你可以执行这一条指令 export KUBECONFIG=/etc/kubernetes/admin.conf 来把配置加入到环境变量中。
然后是安装 pod 网络插件。因为我们上面初始集群的时候使用了 canal 需要的参数,所以我们这里还是继续安装 canal 插件,命令很简单,直接复制执行即可。
kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/canal.yaml
最后就是集群里面新添加节点,在待加入集群的机器,也就是 slave/worker 机器上执行这条加入指令,并非是 Master 机器。Slave/worker 机器执行了该指令之后,控制台会给出结果,告知是否成功被添加到集群中。如果成功,那么等一段时间就可以在 Master 机器上查看到该节点状态为就绪了。这个因为使用了 hash 值来验证,所以需要记录下来这一段命令并且保存好,以后使用这段命令来将子网中的更多机器加入到集群。再次强调,在 slave/worker 机器上执行这条命令,并且根据 Master 机器的具体输出进行更改。
kubeadm join --token <token> <master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash> #需要更改变量
例如我这边就是在 slave/worker 机器上执行 sudo kubeadm join 10.0.0.7:6443 --token m2ktxb.f6zxea3511szt28r --discovery-token-ca-cert-hash sha256:8c5814124736de2f77a688a75c5a0591a48adc2136ca360d1012d3f433fb367f
节点添加之后,在 Master 机器上检查一下是否所有节点都准备就绪了。不出意外的话,Kubernetes 集群就搭建好了。
图四 集群中有一台机器还未就绪
三. 安装 Polyaxon
3.1 安装 helm
第三步是只需要在集群中 Master 节点上进行一次的工作,前提是你已经安装好了 Kubernetes 集群并且确定集群可用了,这样的话你只需在 Master 节点上安装 Polyaxon,整个集群中的所有节点就可以被自动管理起来了。Polyaxon 的官方安装文档在这里,根据官方文档,我把所需要的命令行总结如下。
首先需要安装 helm 并且配置。Helm 是 kubernetes 的正式的依赖包管理器,安装并且配置好之后,我们使用 helm 来部署 polyaxon。
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash && kubectl --namespace kube-system create sa tiller && kubectl create clusterrolebinding tiller --clusterrole cluster-admin --serviceaccount=kube-system:tiller && helm init --service-account tiller --tiller-namespace kube-system
安装好 helm 之后,我们可以检查一下版本,看看是否有问题。注意,polyaxon 要求 helm 版本最低是2.5,更低版本可能会不支持。如果你使用了较低版本的 helm,可以运行 sudo helm init –upgrade 指令来进行升级。
图五 安装完 helm 之后检查一下相关信息
3.2 添加 polyaxon 相关信息
接下来是部署 polyaxon 了,其实步骤也不难,首先用 kubectl 命令创建一个 polyaxon 的命名空间,把我们接下来的工作都放在这个命名空间中,就算是到时候哪里搞错了也可以简单的删除该命名空间来达到回滚的目的。然后把 polyaxon 的仓库添加到 helm 里面去,这样就可以直接安装 polyaxon。最后就是使用一个配置文件来初始化 polyaxon。
首先执行如下指令初始化命名空间,以及添加 polyaxon 的仓库。
kubectl create namespace polyaxon && helm repo add polyaxon https://charts.polyaxon.com && helm repo update
然后我们需要编写配置文件来配置 PV、PVC、Polyaxon,这些指令都需要指定配置文件来运行。
3.3 安装 NFS 并且创建 persistent volume 与 persistent volume claim
事实上这一步与集群并没有太大关系,通过上述步骤,集群已经安装完毕并且可以正常运行了。但是我们后面的 polyaxon 需要指定路径来进行持久存储,不然实验数据和实验结果都无法保存了。Kubernetes 对于 pv 和 pvc 有详细介绍,位置在这里,摘录一段介绍如下。
PersistentVolume(PV) 是群集中由管理员配置的一块存储。它是集群中的资源,就像节点是集群资源一样。PV 是存储卷插件,基本特性类似存储卷 (Volumes),但具有独立于使用 PV 的任何 pod 的生命周期,就是可以提供持久性存储,数据不会随着 pod 结束而消失。此 API 对象捕获存储实现的详细信息,包括 NFS,iSCSI 或特定于云提供程序的存储系统。
PersistentVolumeClaim(PVC) 是用户存储的请求。它类似于一个 pod。Pod消耗节点 (node) 资源,PVC消耗PV资源。Pod可以请求特定级别的资源 (CPU 和内存)。Pvc 可以请求特定的存储大小和访问模式(例如,可以挂载为一次读/写或多次只读)。
我的理解就是 pvc 对用户请求储存空间进行了一层封装,pv 对于系统提供的存储进行了一层封装,这样就可以很好的解耦。Kubernetes 支持的 pv 实现方式有很多,比如 NFS、iSCSI、AzureFile、CephFS等,我们使用比较常见的 NFS 方式来提供存储空间。
NFS 的安装教程很多,我参考了这一篇。首先找一台电脑作为 NFS 存储空间的提供者,我们可以直接使用集群里面的机器,例如我这里使用 polyaxonvm2 来作为NFS 服务器。在它上面安装相关软件包
sudo apt install nfs-kernel-server
然后编写配置文件
sudo vi /etc/exports
然后添加相关路径和读写配置,根据 polyaxon 的要求,需要有 code、data、logs、outputs、repos、upload 等目录,所以我们在 /etc/exports 里面添加如下内容
/code *(rw,sync,no_subtree_check,no_root_squash)
/data *(rw,sync,no_subtree_check,no_root_squash)
/logs *(rw,sync,no_subtree_check,no_root_squash)
/outputs *(rw,sync,no_subtree_check,no_root_squash)
/repos *(rw,sync,no_subtree_check,no_root_squash)
/upload *(rw,sync,no_subtree_check,no_root_squash)
然后在 NFS 服务器上面创建这些共享目录
sudo mkdir -p /code -m 777
sudo mkdir -p /data -m 777
sudo mkdir -p /logs -m 777
sudo mkdir -p /outputs -m 777
sudo mkdir -p /repos -m 777
sudo mkdir -p /upload -m 777
最后重启 NFS 服务,使得上述的改动生效。
根据上面的教程,NFS 服务器已经在 polyaxonvm2 这台机器上安装好了,接下来我们在Master 机器上安装 NFS 客户端,这样就可以在 Master 机器上创建 PV来挂载 NFS 服务器了。在 Master 上面安装 NFS 客户端的软件包
sudo apt install nfs-common
然后连接到 NFS 服务器,在 Master 机器上检查一下是否可以正常连接到 NFS 服务器 (polyaxonvm2.southeastasia.cloudapp.azure.com)
sudo showmount -e <NFS_server> #需要修改 NFS 服务地址
图六 NFS 客户端连接到服务器验证
可以连接的话基本上就没有问题了,接下来我们在 NFS 客户端上,也就是 Master 机器上安装 PV 和 PVC。
首先编写一个 data-pvc.yml 文件,用来指定 /data 路径的 PV 和 PVC。待会根据这个文件来安装相关信息。其他路径参照这个例子一样的进行安装,记得要安装完全部路径。
图七 data-pvc.yml配置文件内容
这里需要主义的就是 name 字段一定要唯一,不要搞混,path 和 server 也要填写正确。这里仅仅以 data-pvc.yml 为例子,其他的路径也是类似处理。当然也可以把所有的 PV 和 PVC 配置都写到一份文件里面待会儿一次安装就行。
然后在 Master 机器上运行指令,安装这个 PV 和对应 PVC。
kubectl create -f data-pvc.yaml -n polyaxon
这里的 -f 参数是指定配置文件,记得修改你的运行命令以对应实际的文件名。-n 参数是指定命名空间,我们将其放置在刚刚创建的 polyaxon 空间,以防止出现问题。其他的路径安装都是一样的,记得安装完全部路径。这样一来,Polyaxon 所需要的存储空间就安装完毕了。
3.4 配置安装 polyaxon
Polyaxon 本身可以通过默认的配置来安装的,但是我们配置了 PV 和 PVC,所以需要手动修改一部分配置信息,因此需要写一份 polyaxon-config.yml 文件来配置相关信息,具体内容如下。
图八 polyaxon-config.yml 配置文件内容
注意这里 data 和 outputs 都是可以挂载多个 PVC 的,例如我这里就挂载了两个,data1 和 data2。但是,一个 PVC 仅能被 polyaxon 一个地方使用,这个一定要注意不要重复挂载!我在这里踩了好久的坑。然后在 Master 机器上运行指令,根据配置安装 polyaxon。
helm install polyaxon/polyaxon --name=polyaxon --namespace=polyaxon -f polyaxon-config.yml
上面的安装指令执行之后,需要等待三到五分钟,Master 节点会自动下载好 polyaxon 需要的文件并且安装,然后会输出安装结果信息,耐心等待即可。例如输出信息如下。
图九 polyaxon 安装完毕的输出信息
最后的输出结果主要告诉我们三件事,一是如何获取到 polyaxon 的运行地址,二是更新 polyaxon 的配置,三是登陆信息。这里第一点获取运行地址需要更改一下运行命令,否则会出错。我通过多次部署测试,发现上面输出的那个获取服务器 IP 的指令(export POLYAXON_IP=$(kubectl get svc --namespace polyaxon polyaxon-polyaxon-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}'))似乎有问题。搜索路径 jsonpath 中的 .status.loadBalancer.ingress[0].ip 永远都是空值,不论采用默认属性(使用 ingress)还是禁止 ingress 都没用。搜索了一下,作者引用了一个 * 的帖子,该帖子声称是 kubeadm 使用 CNI 网络插件,该插件不支持 ingress 控制器使用的 hostPort,来源在这里。如果这里得不到 POLYAXON_IP 这个变量的话,后面执行指令会提示找不到 host,所以我建议将该条修改为 export POLYAXON_IP=$(kubectl get svc --namespace polyaxon polyaxon-polyaxon-ingress -o jsonpath='{.spec.clusterIP}'),直接把 Master 节点的内部 IP 给它,目前单点 Master 的环境下运行良好。
那我们就直接执行
export POLYAXON_IP=$(kubectl get svc --namespace polyaxon polyaxon-polyaxon-ingress -o jsonpath='{.spec.clusterIP}')
export POLYAXON_HTTP_PORT=80
export POLYAXON_WS_PORT=1337
echo http://$POLYAXON_IP:$POLYAXON_HTTP_PORT
然后在系统中安装 pip,使用 pip 来安装 polyaxon-cli,这样就可以使用 polyaxon 命令了。
sudo apt install python-pip
pip install -U polyaxon-cli
polyaxon config set --host=$POLYAXON_IP --http_port=$POLYAXON_HTTP_PORT --ws_port=$POLYAXON_WS_PORT
最后的那一段获取登陆用户名密码的命令可以运行一下来获取默认的账号密码,默认的账号密码是 root / rootpassword ,直接用来登陆即可。现在可以通过打开 polyaxon dashboard 来查看项目运行情况了。访问 http://<Master_ip>:<polyaxon_port> 就可以进入到主界面中,整个部署过程就完成了。注意这里的 <Master_ip> 应该是 Master 服务器的公网地址,当然如果你和该机器处于同一个子网当中可以使用内网地址,<polyaxon_port> 并不是80 端口或者 1337 端口,这两个端口是 polyaxon 在容器内部的端口号,映射到本地主机是 30000-32767 中随机的一个端口号,具体端口号需要通过在 Master 机器上执行 kubectl get service -n polyaxon 来查看 polyaxon-ingress 服务映射出来的端口号。
欢迎共同探讨。 [email protected]