美文网首页
树莓派4B+ Centos7 部署k3s集群工具

树莓派4B+ Centos7 部署k3s集群工具

作者: 死鱼 | 来源:发表于2021-05-31 17:48 被阅读0次

    kubernetes用于大型集群管理,而k3s属于kubernetes的一个轻量级版本,常用于嵌入式设备使用。现把它安装到树莓派上使用。

    1 系统准备

    这里用到树莓派的系统是:CentOS-Userland-7-armv7hl-RaspberryPI-Minimal-4-2009-sda.raw,型号是4B+,8g内存。
    树莓派初次启动需要扩容,并且做一些基本调整:

    扩容:
    fdisk /dev/mmcblk0     //使用fdisk工具对磁盘进行分区
    执行命令:p(查看分区)
    执行命令:d(删除分区3)
    执行命令:p(查看分区)
    执行命令:n(添加分区)
    输入:P(主分区)
    分区号:默认3
    起始扇区:填第2个分区的最后一个扇区+1
    结束扇区:默认就可以了,默认为整个磁盘的最后一个扇区。
    执行命令:p
    执行命令:w
    reboot重启设备
    执行命令:resize2fs /dev/mmcblk0p3
    使用df -lh查看磁盘已经扩容完成了
    
    配置cgroup

    cgroup是linux用来对进程分配cpu、内存资源的工具,需要在启动系统时开启他,k3s会用到。
    在/boot/cmdline.txt后加入这个,然后reboot

    cgroup_memory=1 cgroup_enable=memory
    
    按个人习惯装几个常用的
    yum install vim screen ntpdate wget 
    
    yum install docker git
    

    关闭swap

    swapoff -a  # 临时
    sed -ri 's/.*swap.*/#&/' /etc/fstab    # 永久
    

    将桥接的IPv4流量传递到iptables的链

    cat > /etc/sysctl.d/k8s.conf << EOF
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    EOF
    sysctl --system  # 生效
    
    # 使用过程中经常需要清理一下
    iptables --flush
    iptables -tnat --flush
    

    时间同步

    ntpdate -u  cn.ntp.org.cn
    

    2 部署k3s

    2.1 安装 部署Server(Master)结点

    k3s是一个轻量级的k8s,适用于树莓派这种嵌入式设备。

    # 方法1:官方做法
    curl -sfL https://get.k3s.io | sh - 
    
    # 方法2:下载后执行
    curl -o k3s_installer.sh https://get.k3s.io
    bash k3s_installer.sh
    

    这个脚本跑完的时候,会把k3s添加到systemd里面,可以通过systemctl status k3s来查看运作状态。启动成功就可以使用啦


    image.png
    另外,也可以通过手动启动server的方式

    官方参考:https://rancher.com/docs/k3s/latest/en/installation/ha-embedded/

    • 先启动一个主结点A,关掉systemd方式启动的k3s。然后手动开启server服务。
    systemctl stop k3s
    reboot # 重启为了关闭一些关不了的service
    
    # 方法1:第一个结点启动,使用默认命名
    K3S_TOKEN=自己写一个密钥S k3s server --cluster-init
    # 方法2:自定义结点唯一名称
    K3S_TOKEN=自己写一个密钥S K3S_NODE_NAME=自定义唯一节点名称 k3s server --cluster-init
    

    等它重启个好几次之后,基本就成功了。


    ku-system的pod都正常启动了

    如果一直失败,可以输入命令刷一下iptable缓冲
    iptables --flush
    iptables -tnat --flush

    • 接着到第二 第三个结点启动Server(加上--with-node-id,集群会给新结点一个随机结点名称。如果没修改hostname,也不带这个参数,新结点会用默认hostname,非常容易和其他结点发生ID冲突;或者也可以通过K3S_NODE_NAME环境变量来命名)
    # 方法1:随机结点名称启动
    K3S_TOKEN=自己写一个密钥S k3s server --server https://第一个结点IP:6443 --with-node-id
    
    # 方法2:自定义结点名称的方式启动
    K3S_TOKEN=自己写一个密钥S K3S_NODE_NAME=自定义唯一节点名称 k3s server --server https://第一个结点IP:6443
    
    

    等第二个结点加入后,在任意结点执行命令,都能查看到已有的2个Server(Master)结点了


    二人世界

    当Server结点数大于等于3个且为奇数时,集群才可以实现高可用。
    大于等于3是因为k3s使用了Raft算法来实现一致性,而Raft算法的容崩率为1/3,也就是只要集群中有2/3台机器正常运作,集群就能正常运作,所以3台机器是最低要求;要奇数个结点是因为Raft算法过程中有一个很重要的随机投票选Leader的流程,结点们通过定期投票选举出一个Leader角色,然后其他结点在它的任期内就向他同步数据,这个时候如果结点数是偶数,那么容易出现平票问题,选不出leader,并且,崩溃后集群进行数据恢复过程中,实现一致的方法是多数服从少数,如果是偶数Master结点,且刚好被分割成2个结点规模一样的集团,就没办法恢复数据了[裂开],所以需要奇数个结点以避免权力平分问题。
    以上为个人理解。


    一家三口

    有兴趣的同学可以一起探讨这类共识算法,与此类似的还有联盟链的PBFT类算法,比特币PoW算法等等。

    2.2 Worker结点加入网络
    从Server(Master)结点上获取token

    因为集群并非开放式集群,加入集群需要获取一个token作为校验。这个token可以从Master服务器上获取。(手动加入的话,仅需要使用相同的K3S_TOKEN参数启动即可。)

    cat /var/lib/rancher/k3s/server/node-token
    
    方案1:Worker结点利用token加入集群(官方):
    # IP需要修改为自己Master服务器的IP
    curl -sfL http://get.k3s.io | K3S_URL=https://任意Server结点IP:6443 K3S_TOKEN=刚才保存下来的连接令牌 sh -
    
    方案2:利用K3S_TOKEN参数手动加入(推荐)
    # 方法一:像上面Master一样 通过with-node-id来随机生成结点ID
    K3S_TOKEN=自己写一个密钥S k3s agent --server https://任意Server结点IP:6443 --with-node-id
    
    # 方法二:或者给自己一个node name
    K3S_TOKEN=自己写一个密钥S K3S_NODE_NAME=结点唯一命名 k3s agent --server https://任意Server结点IP:6443
    

    这样,结点就正常连接上啦:


    还来了个佣人
    2.3 关闭k3s服务

    关闭k3s进程后,后台还留存一些服务占用着端口,需要用官方脚本关闭他们

    /usr/local/bin/k3s-killall.sh
    
    2.4故障排除:
    server中,一些kube-system pod启动notReady,甚至Error

    可以flush一下iptables,等他自己重启就行了。

    iptables --flush
    iptables -tnat --flush
    
    worker加入密码不正确

    有可能发生了一些冲突,可以试下重装k3s-agent

    /usr/local/bin/k3s-agent-uninstall.sh
    rm -f /etc/rancher/node/password
    
    实在不行,可以把配置数据全部删除。所有结点删除这个文件之后,再重新 --cluster-init 即可
    rm -rf /var/lib/rancher/k3s
    

    3 部署一个普通的Nodejs应用

    目前系统已经伴随k3s安装的一些软件:
    crictl:类似与docker的命令行工具,比如:

    crictl ps
    crictl images
    

    k3s:封装了kubeneters基本工具在里面的集成,如使用kubectl:

    k3s kubectl get nodes
    k3s kubectl get pods
    

    3.1 编写node程序和制作一个docker镜像

    这里示范部署一个最简单的web应用

    找一个空地方,先写一个简单的Node web程序,server.js
    const http = require("http")
    var server = http.createServer(function(req, res) {
        console.log("request url: " + req.url);
        res.writeHead(200);
        res.end("hello ");
    })
    
    server.listen(8080);
    
    然后写个DockerFile:
    FROM node:10
    EXPOST 8080
    COPY server.js .
    CMD node server.js
    
    接下来build一个docker镜像,记得加上最后的路径
    docker build -t 镜像名称 .
    
    构建完成后跑起来:

    --net host 代表与本机享受同一个网络命名空间

    docker run -it -p 8080:8080 --net host samply-node
    
    # 换个screen检查情况:
    curl http://localhost:8080 # 输出hello代表一切正常
    

    这里可以在docker容器内开启ssh服务:https://blog.csdn.net/Leo_csdn_/article/details/96150534

    然后提交镜像到自己的远程仓库
    # 获取正在跑的容器ID
    docker container ls 
    
    # 然后提交到远程容器
    docker login
    docker commit -m "COMMIT_MESSAGE" -a "AUTHER_NAME" CONTAINER_ID 远程仓库/容器名称:版本号
    docker push 远程仓库/容器名称:版本号
    

    3.2 使用kubectl 部署镜像

    做好docker镜像后,就可以部署到集群上了。

    首先使用kubectl run命令直接创建一个带镜像信息的POD,POD是节点上容器集合的概念。
    k3s kubectl run hello-node --image=远程仓库/容器名称:版本号 --port=8080
    

    等一会儿就能在pods列表里面看到了:


    image.png

    但这时候,这个pod并没有对外开放,只能在集群内部相互访问,通过get services命令查看集群的服务,发现并没有我们的hello-node服务。


    image.png
    所以你需要通过expose命令,让他开放出来。
    k3s kubectl expose pod hello-node --type="NodePort"
    

    expose命令其实是创建了一个service,用于给这个pod提供访问入口。
    (如果使用--type=LoadBalancer,则代表一个deployment上管理的所有POD进行均衡负载,但这里还没用上deployment,第四章节会使用到)
    等一会儿,pod上就有一个结点IP的对外端口,供外部访问了。


    本地访问 局域网内其他设备访问
    最后是关闭服务的操作:
    k3s kubectl delete pods,services hello-node
    
    输入删除指令
    另一个screen查看状态,发现POD正在被关闭中

    运行结束后,刚启动过的pod和service就不见了,服务也停止了。

    4 使用Deployment部署一个均衡负载的简单node应用

    docker容器,其实就是一个运行的轻量级系统,里面可以跑我们的业务应用。
    而POD则是代表容器的集合,一个POD可以运行多个容器,一台机器上可以运行多个POD。
    POD未必是一个对外开放的服务,他可能只是内部计算的程序,默认只能集群内部通信,所以还有Service的概念,用于让POD对外开放端口,供外部访问。这里的service本质上是个集群内部的负载均衡器,用来给同一个Deployment分流;对应的还有Ingress,外部负载均衡器,用于给多个Deployment分流。
    而Deployment顾名思义,就是一次部署的抽象实例,比如说,现在需要部署一个3台机器均衡负载的nodejs业务应用,那么这个部署任务则代表一个deployment实例。

    这个实例通过一个 hello-node-deployment.yaml 文件表示出来:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-node-deployment # 部署实例的名字
    spec:
      selector:
        matchLabels:
          app: hello-node-app
      replicas: 3
      template:
        metadata:
          # 实例的查询标签
          # 因为一个实例部署后可能会有多个POD,我们可能要批量获取状态、日志或者删除他们,所以有一个标签字段给我们设置。
          # 部署后查询实例内 pod和service时,可以通过添加参数 -l app=hello-node-app 来查询
          labels:
            app: hello-node-app 
        spec:
          containers:
          - name: hello-node-container
            image: deadfish5/sample-node:1.0 # 业务镜像,这是我的一个公开镜像,建议换成自己的
            ports:
            - containerPort: 8080 # 业务开放的端口,仅容器内部防火墙设置。
    
    部署之前必须启动docker
    systemctl start docker
    systemctl enable docker
    
    然后执行部署:
    k3s kubectl apply -f ./hello-node-deployment.yaml
    

    很快,我们可以看到POD和deployment的部署情况,都已经正常运作。


    部署状态查询
    我们也可以像docker一样进入容器操作
    k3s kubectl exec -it POD_NAME -- sh # --后面跟的是进入容器后执行的命令
    

    进入容器后可以使用基本linux命令,也可见8080端口已经被我们的node应用占用了。


    进入容器并使用sh

    但是此时service还没有他们,也就是正处于无法提供外部服务的状态。

    所以我们还是要通过expose命令来起一下service:(第三节部署是针对单个POD来expose,这里是直接针对deployment来expose了,相当于批量操作了3个POD,并让他们均衡负载)
    k3s kubectl expose deployment hello-node-deployment --type="LoadBalancer"
    

    这里对一个deployment里面的3个pod启动了个默认均衡负载服务,暴露出来的一个端口是30057,访问可通。
    也能够通过logs命令查看控制台输出的日志。


    服务启动后的状态
    完事就关了它:
    k3s kubectl delete deployment,service hello-node-deployment
    
    正在删除

    因为deployment实例中包含了pod的部署配置,所以删除deployment时,k3s就会直接把pod也删除掉。
    但service并不在deployment部署的范围内,所以需要同步删除它,在删除命令中通过","与deployment分割开来即可。
    至此已经把刚起来的服务全部关闭掉了。


    关闭后状态

    综合部署

    这里是给3台Master+1台Agent,使用deployment启动了1个pod的9个副本:
    部署情况
    然后给他们上均衡负载服务:
    service情况
    看看请求效果
    请求测试
    查询状态
    集群状态

    这里我们看到3个Server(Master)结点由于需要维护集群高可用,对CPU持续20%左右的消耗,内存也需要一个G左右。而Agent(Wroker)结点只需要执行部署任务,所以对内存与CPU的需求都相对低一些,仅维持在10%左右的CPU和半个G左右的内存消耗。

    参考:https://zhuanlan.zhihu.com/p/120171512
    参考:http://kubernetes.kansea.com/docs/hellonode/

    相关文章

      网友评论

          本文标题:树莓派4B+ Centos7 部署k3s集群工具

          本文链接:https://www.haomeiwen.com/subject/isiysltx.html