沉默和消失是为了更好的复出。

本篇博客旨在以k3s运行wordpress(残血高可用)的任务驱动下进行k8s集群入门。

基础环境为树莓派Raspberry Pi4B *3 +Raspbian(Lite) +Docker

示例为4G RAM*1 + 8G RAM*2

简单的铺垫和回顾。

我们为什么需要集群?针对我们的任务,搭建一个网站,我们可以说集群是一种大大提高网络吞吐量和稳定性的方式,也就是平常说的高可用,高并发。就计算机资源利用的方面,他,尤其是k8s架构,使跨服务器的调度和资源分配来构建产品成为可能。

首先可以看一下这个视频和示例对k8s进行初步了解。Kubernetes一小时入门课程 – 视频配套笔记 | GeekHour讲的很好,这里不提供笔记下载,希望多支持官方!

初步了解后我们就能开始了。因为树莓派的性能确实有些羸弱,我们选择k3s,并且不接入额外的数据库服务器。官网在这里K3s – Lightweight Kubernetes | K3s可以作为参考

0.准备工作

  • 明确硬件分工
  • 硬件准备
  • 操作系统安装
  • cmdline.txt参数修改
  • 关闭交换空间
  • 分配ip地址

I 首先我们明确系统分工。三台树莓派分别为4g0,8g0,8g1在我们的系统当中,4G RAM的树莓派作为Master节点,8g0和8g1作为Slave节点,其中8g1还负责NFS卷的承载,但是NFS服务不在k3s体系内,由人工控制。

II 然后是硬件的准备。笔者准备了五口千兆的交换机,用来扩展网络,路由器负责DHCP,三个ssd+硬盘盒做为三台设备的系统盘加储存。(本来想用PXE网络启动和专门的文件服务器,无奈设备数量和配置不足。)

III 操作系统安装不做赘述,最新的64位Lite就可以,这个没墙也可以找官网,记得扩展储存空间。

IV 安装操作系统并且启动后ssh链接,修改cmdline.txt。注意,请在树莓派完成启动后在修改,不要在烧录完成后在PC修改,因为官方的os第一次启动会自动修改该文件。所以在ssh中直接修改是最便捷和安全的方式。编辑cmdline

sudo nano /boot/firmware/cmdline.txt

在文件末添加 

 cgroup_memory=1 cgroup_enable=memory

然后我们需要关闭交换空间防止抖动

sudo sed -ri 's/.swap./#&/' /etc/fstab

更新下软件包重启。

V 你需要给每台设备分配固定的IP地址,配置路由即可,不再赘述。

*以上操作需要对每个设备都进行

1.开始安装 k3s

I 安装Docker

因为ARM 平台的容器有点bug,可能下载的镜像架构(mysql点名批评)与设备不符,为了方便我导入镜像和在k3s体系外可视化部署,我们选择Docker。因此我们需要在每台设备都安装。执行脚本就行。

使用rancher的脚本,可以指定版本。本次采用24.0.4

https://docs.k3s.io/advanced?_highlight=docker#using-docker-as-the-container-runtime

curl https://releases.rancher.com/install-docker/24.0.4.sh | sh

PS:你可能在实践过程中需要重装docker。这是一些卸载技巧。

sudo docker stop $(sudo docker ps -aq)
sudo docker rm $(sudo docker ps -aq)
sudo docker rmi $(sudo docker images -q)
sudo apt remove docker*
sudo rm -rf /var/lib/docker
sudo apt autoremove

执行完这些就干净了,重新安装就行。

II 安装K3s Master

官方很好,直接一键安装,国内记得加镜像源(INSTALL_K3S_MIRROR=cn)

curl -sfL https://get.k3s.io | sh -s - --docker 

正常情况很快。服务启动不了就卸载重装。服务端一键卸载

/usr/local/bin/k3s-uninstall.sh

然后检查一下是不是已经启动

 sudo kubectl get pods -A

因为pod会生成和修改,换句话说它自己也有安装过程,遇到error不用担心,等待一会,让它继续部署。如果都挂了才会考虑从docker开始重新安装。

III 安装K3s Agent或者叫slave

因为agent和master需要沟通验证,所以你需要获得一些额外的信息就是master的地址和K3S_TOKEN。在master执行,保存你的token

sudo cat /var/lib/rancher/k3s/server/node-token

你会发现一个4g4dfg4jh4hgkj4hjkh542::server:46ghd4hd4fhh4thsz这样的东西,保存好

在你的agent机安装好docker的前提下,执行该命令以部署agent并于server通讯。

curl -sfL https://get.k3s.io | K3S_URL="https://your_masterIP:6443" K3S_TOKEN="<your_token>" sh -s - --docker

没有报错就是没问题,不需要master机那种检查方式,agent全部安装好后看一看master有没有显示就好。

在master执行以下命令查看所有节点

sudo kubectl get node

agent没有role不必担心,在本项目中正常使用。

2.安装配置 portainer

I 配置docker使portainer可以管理到你想直接管理的节点

先登录你想用portainer直接管理的主机,没错,就算Master也可以

查找docker配置文件位置

sudo systemctl show --property=FragmentPath docker

修改,示例为/lib/systemd/system/docker.service

sudo nano /lib/systemd/system/docker.service

找到

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

在 -H 和 fd之间插入,变成

ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H fd:// --containerd=/run/containerd/containerd.sock

保存,再重启变更

sudo systemctl daemon-reload 
sudo systemctl restart docker

等一会查看master的node和pod没有问题就可以下一步了

II 直接在master安装portainer就行

sudo kubectl apply -n portainer -f https://downloads.portainer.io/ce2-19/portainer.yaml

安装完成按照这个登录https://<your_master_IP>:30779,添加k3s就可以可视化管理了

docker添加可以选择环境,standalone,API ,<your_ip>:2375,就可以直接管理docker容器了

该操作有点危险,因为任何人都可以通过网络API无密码直接管理你的docker!切记不要让陌生人链接你的内网!路由要开防火墙!!!效果如下

3.安装配置 NFS

先介绍下使用NFS目的。主要是方便专门对文件进行定位和访问,自然也方便备份和管理了。

选择一台你想要的设备储存你的数据库和网页,但是注意要给每台设备都安装NFS的基本软件

sudo apt-get install nfs-common nfs-kernel-server -y

然后在那台你想让他作为储存的设备配置文件夹和共享和IP范围

sudo mkdir -p /shared/k3s/web
sudo mkdir -p /shared/k3s/db
sudo chmod 777 /shared/k3s/web
sudo chmod 777 /shared/k3s/db
sudo chmod 777 /shared/k3s

然后定义暴漏规则

sudo nano /etc/exports 

末尾添加

/shared <your_ip_range_start_like_10.1.3.9>/<last_part_of_range_like_89>(rw,sync,no_root_squash,no_all_squash)

重启服务

sudo systemctl enable rpcbind
sudo systemctl enable nfs-server
sudo systemctl restart rpcbind
sudo systemctl restart nfs-server

检查暴漏

sudo showmount -e

看到这个就说明NFS共享成功了

Export list for YOUR_NFS_HOST:
/shared <your_ip_range_start_like_10.1.3.9>/<last_part_of_range_like_89>

接着检查其他主机能不能收到

sudo showmount -e YOUR_NFS_HOST

相似输出就没问题

4.安装配置储存卷并绑定

  • 将NFS卷加入K3S(pv)
  • 添加声明(pvc)使其可以被使用

在master机执行。

现在将开始大规模编写yaml文件进行配置。

主要使用几个命令,都能看出来啥意思。注意pvc的大小类型得和pv一样

sudo kubectl create -f xx.yaml
sudo kubectl apply -f xx.yaml
sudo kubectl apply -f ./your_yaml_dir
sudo kubectl get pv,pvc 
sudo kubectl delete pv your_pv_name
sudo kubectl delete pvc your_pvc_name

我们知道Mysql需要储存数据库文件到本地,wordpress需要储存网站根目录到本地。这也为什么我们共享了db和web两个目录,是方便处理。

我们先创建项目结构

wp
└──mystorage/
            ├──nfs-db.yaml
            ├──nfs-web.yaml
            ├──claim-db.yaml
            └──claim-db.yaml

然后编辑配置

#nfs-db.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pvdb50g
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /shared/k3s/db
    server: <NFS_HOST_IP>
  storageClassName: manual
#nfs-web.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pvweb50g
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /shared/k3s/web
    server: <NFS_HOST_IP>
  storageClassName: manual
#claim-db.yaml
#be careful! the "storage" and "storageClassName" and "accessModes" must as the same as in nfs-db.yaml!
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: myclaim-db
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 50Gi
  storageClassName: manual
  volumeName: pvdb50g
#claim-web.yaml
#be careful! the "storage" and "storageClassName" and "accessModes" must as the same as in nfs-web.yaml!
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: myclaim-web
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 50Gi
  storageClassName: manual
  volumeName: pvweb50g

都编辑完成后先 sudo kubectl apply -f 那两个nfs-**.yaml, 再应用那两个claim-**.yaml,最后执行 sudo kubectl get pv,pvc 查看是否创建成功,是否绑定成功。如果哪一步失败请检查pv和pvc类型和位置是否有问题,如果未绑定成功未设置成手动会导致后续所有pod都会pending,请知悉。

5.安装Mysql和wordpress

你需要保证你的镜像是否能下载到,镜像标签是否正确。如果你需要适用于树莓派4b的mysql和wordpress的本地镜像,可以联系我!

感觉无需解释太多,具体请看开篇视频,另外注意secret.yaml的作用以及base64编码,最后注意数据安全。这里直接贴了。

wp
├──mystorage/
|           ├──nfs-db.yaml
|           ├──nfs-web.yaml
|           ├──claim-db.yaml
|           └──claim-db.yaml
├──mysql/
|       ├──configmap.yaml
|       ├──secret.yaml
|       ├──service.yaml
|       └──statefulset.yaml
└──wordpress/
            ├──deployment.yaml
            └──service.yaml

然后分别cd到mysql和wordpress执行 sudo kubectl apply -f ./ 进行部署就ok了

#mysql/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
data:
  my.cnf: |
    [mysqld]
    max_connections = 200
#mysql/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
type: Opaque
data:
  username: <YOUR_USER_NAME_IN_BASE64>
  password: <YOUR_USER_PASSWORD_IN_BASE64>
#mysql/service
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
    - port: 3306
  selector:
    app: mysql
#mysql/statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql/mysql-server:latest
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: password
        - name: MYSQL_DATABASE
          value: wordpress
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: username
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: myclaim-db
#wordpress/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
spec:
  replicas: 2
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
        - name: wordpress
          image: wordpress:latest
          env:
            - name: WORDPRESS_DB_HOST
              value: mysql
            - name: WORDPRESS_DB_NAME
              value: wordpress
            - name: WORDPRESS_DB_USER
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: username
            - name: WORDPRESS_DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: password
          ports:
            - containerPort: 80
              name: wordpress
          volumeMounts:
            # name must match the volume name below
          - name: wordpress-persistent-storage
            # mount path within the container
            mountPath: /var/www/html
      volumes:
        - name: wordpress-persistent-storage
          persistentVolumeClaim:
           claimName: myclaim-web
#wordpress/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress-service
spec:
  type: NodePort
  selector:
    app: wordpress
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080

至此部署已经完成,wordpress已经暴漏在master主机的30080接口(注意接口范围),后续可以添加一些HAproxy 或者nginx进行负载均衡。

——————————————————

一些碎碎念

sudo kubectl describe pod <pod-name>很实用

你可以将wordpress设置为多份而不需要担心数据同步问题

你可以通过nfs直接管理mysql和word press的文件,很方便,设置NFS的ip范围和路由ip池范围有助于阻止不法分子直接访问你的文件。当然,你也可以讲ip范围设置成*,但这是非常危险的。

根据本配置,在k3s内网中mysql的host name就是mysql

没有指出“k3s内网“的情况下,“内网”指你给树莓派物理机所在网段

还有一些错误和不足,大家积极留言指出和补充

另外既然能看到这里,感谢你能完整阅读这篇博文,希望这篇博文能解决你的问题!!

——————————————————

”升华“一下

其实树莓派集群这个想法主要是我无意买了两台树莓派,一个网站另一个vpn和浇花。得益于树莓派这种性能说高不高说低不低的”鸡肋“,我萌生了一个想法:怎样让他们一起工作呢?我就想到了超算这种东西,然后网上冲浪,分布式,云计算,虚拟化,并行计算,docker,k8s,MPI集群这些概念非常吸引人,然后发现树莓派产品价格大跌,回归正常,本着再买一个能让其他两个物( 死 )尽( 得 )其( 其 )用( 所 )的想法便开始了这些架构方面的探索。

虽然大部分是运维相关(有点低端)但是收获也是挺多的。首先是一些概念的。记得以前听大佬说过,现代的计算机解决问题的一大方法就是打包和抽象,一层一层越来越高级。从本博文的实验来看,一个k8s,就涉及到了,扩展,回收,储存(nfs服务器),打包(docker本身),调度编排(pod的调度),网络(k8s虚拟的网络,内部的网络),权限(docker和k8s权限组),各种抽象(容器,进程,主机,储存,网络),局部性原理。这个集群,何尝不是一台完整的计算机?硬盘,处理器,总线,内存一个不缺。当看到管理面板把所有的cpu和内存甚至储存一起算,就感觉很有意思,我还自嘲说头一次打这么富裕的仗。

另外就是动手和选配件硬件计算开销这些方面,也真的很有意思,算是从头到尾自己的project。就是有点浪费树莓派的gpio口,哈哈。

最后我大概会在这上面部署自己的应用?然后再加一套MPI平台?慢慢来吧。

————————————

本文主要借鉴以下文章并进行整合,最后得出数据安全和可定位还有多副本的wordpress站点。

搭建你的 K3s 环境 — 部署 WordPress · 三令五申 (yelsew.net)

WordPress Application Clustering Using Kubernetes with HAProxy and Keepalived | Severalnines

K3s – Lightweight Kubernetes | K3s

kubernetes – Why do pods remain in ‘pending’ status? – Stack Overflow

Fixing – Cannot bind to requested volume: storageClasseName does not match | Jhooq

容器服务 Pod 一直处于 Pending 状态-故障处理-文档中心-腾讯云 (tencent.com)

在Debian上部署NFS服务【详细步骤】_debain 安装配置nfs服务和挂载 es集群备份-CSDN博客

使用portainer远程连接docker_portainer 连接远程-CSDN博客

示例:使用持久卷部署 WordPress 和 MySQL | Kubernetes

容器服务 Pod 一直处于 Pending 状态-故障处理-文档中心-腾讯云 (tencent.com)

win10 挂载NFS(网络文件夹)_windows 挂载 nfs-CSDN博客

技术干货|Docker和 Containerd 的区别,看这一篇就够了 – 知乎 (zhihu.com)

Linux 查看端口占用情况 | 菜鸟教程 (runoob.com)

视频(你可能需要穿过firewall)

Views: 297

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.