如何本地部署 laf - k8s学习篇

如何本地部署 laf - k8s学习篇

在 Ubuntu 服务器自建 laf 测试环境的实践:准备域名和证书、执行部署、调整运行配置,并排查 Kubernetes DNS、镜像访问及 npm 依赖安装问题。

—次点击9分钟阅读

前言

最近做了几个小程序,没有搭建自己的后台服务,全部使用的 serverless,使用的平台是 laf,laf 是一个和微信云开发一样的 serverless 平台,同样集函数、数据库、存储为一体,一个 MVP 版本的小程序可快速基于 laf 构建,同样的服务,微信云开发每个月要 39 块,而 laf 最小版本大概 13 块,当然现在还有基于 sealos 的 laf,每个月成本更低。

之前的做法是会在 laf 上起两个应用,一个用作 production 环境,一个用于 staging 环境,但这样会有两项应用在计费,最近有一些其他小程序的想法,所以萌生了使用之前空置的一台华为云服务器搭建一个自己的 laf 作为测试环境的想法,说干就干!

Laf 云开发

准备工作

前期需要做一些准备工作

  • 域名
  • 服务器(Ubuntu22.0)
  • docker 代理

域名需要准备

假如 web 控制台域名是 a.b.com 则需要准备:

oss.a.b.com,*.oss.a.b.com,*.site.a.b.com,*.a.b.com,a.b.com,需要将这些域名映射到服务器,同样申请证书需要申请上边这些域名的

服务器

服务器需要特别注意,之前服务器安装了 docker 和 nginx 需要全部清空,就是只需要一台完全干净的服务器就可以,不然会有一些预料之中的错误,类似:

错误

卸载 nginx

sh
#卸载 Nginx
sudo systemctl stop nginx
sudo apt-get remove --purge nginx
sudo rm -rf /etc/nginx
#删除 Nginx 配置文件和目录
sudo rm -rf /var/log/nginx

#卸载 docker
sudo systemctl stop docker
sudo systemctl stop docker.socket
#卸载 docker-compose
sudo apt-get remove docker-compose
#删除 docker 数据
sudo rm -rf /var/lib/docker
sudo rm -rf /etc/docker
sudo rm -rf /etc/systemd/system/docker.service
sudo rm -rf /etc/systemd/system/docker.socket

docker 代理

docker.io 在 6 月份之后基本就不能访问了,所以需要自己配置代理,可以找还能运行的代理或者基于 cloudflare 的 worker 自己搭建代理,本次是基于 worker 代理的,比较简单直接部署即可,部署后可自定义自己的域名,部署步骤:GO

部署完成可修改 docker 的访问地址为自定义的域名即可

vim /etc/containers/registries.conf

修改后是这样的:

代码
unqualified-search-registries = ["docker-proxy.b.com"]
prefix = "docker.io"
location = "docker-proxy.b.com"

[engine]
service_destinations = "docker-proxy.b.com:443"

前期准备工作已做完,现在可以开始部署了

部署 laf

1、下载部署脚本

https://github.com/labring/laf/blob/main/deploy/install-on-linux.sh

可通过 wegt 下载,需注意下载完成之后需修改脚本内的 docker.io 为你的代理 docker 地址

2、指定域名

export DOMAIN=laf.a.b.com

3、开始部署

执行 sh install-on-linux.sh

基本上前期都是一键操作的,laf 提供的部署脚本很完善了

sh
#!/usr/bin/env sh
# Intro: start laf with sealos in linux
# Usage: sh ./install-on-linux.sh <domain>

# TIP: use `sh -x install-on-linux.sh` to debug

# set the first param as domain
DOMAIN="$1"
# if domain is empty string, use default domain
if [ -z "$DOMAIN" ]; then
    DOMAIN="127.0.0.1.nip.io"
fi

# Install Sealos

# if apt installed, use `apt` to install
if [ -x "$(command -v apt)" ]; then
  echo "deb [trusted=yes] https://apt.fury.io/labring/ /" | tee /etc/apt/sources.list.d/labring.list
  apt update
  apt install iptables host -y
  apt install sealos=4.3.5 -y
  apt install jq -y
  
  # fix /etc/hosts overwrite bug in ubuntu while restarting
  sed -i "/update_etc_hosts/c \\ - ['update_etc_hosts', 'once-per-instance']" /etc/cloud/cloud.cfg && touch /var/lib/cloud/instance/sem/config_update_etc_hosts
fi

# if yum installed, use `yum` to install
if [ -x "$(command -v yum)" ]; then
  cat > /etc/yum.repos.d/labring.repo << EOF
[fury]
name=labring Yum Repo
baseurl=https://yum.fury.io/labring/
enabled=1
gpgcheck=0
EOF
  # yum update
  yum clean all
  yum install -y bind-utils iptables
  yum install sealos=4.3.7 -y
  yum install jq -y
fi

ARCH=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/)
echo "ARCH: $ARCH"

# if sealos not installed
if [ ! -x "$(command -v sealos)" ]; then
    echo "sealos not installed"
    exit 1
fi

set -e

# pull sealos cluster images
sealos pull labring/kubernetes:v1.24.9
sealos pull labring/flannel:v0.19.0
sealos pull labring/helm:v3.8.2
sealos pull labring/openebs:v1.9.0
sealos pull labring/cert-manager:v1.8.0
sealos pull labring/metrics-server:v0.6.2
sealos pull lafyun/laf:latest
sealos pull docker-proxy.b.com/labring/ingress-nginx:v1.8.1
sealos pull labring/kubeblocks:v0.7.1

# install k8s cluster
sealos run labring/kubernetes:v1.24.9 labring/flannel:v0.19.0 labring/helm:v3.8.2

# taint master node
NODENAME=$(kubectl get nodes -ojsonpath='{.items[0].metadata.name}')
kubectl taint node $NODENAME node-role.kubernetes.io/master- || true
kubectl taint node $NODENAME node-role.kubernetes.io/control-plane- || true

# install required components
sealos run labring/openebs:v1.9.0
sealos run labring/cert-manager:v1.8.0
sealos run labring/metrics-server:v0.6.2
sealos run docker.io/labring/ingress-nginx:v1.8.1 \
  -e HELM_OPTS="--set controller.hostNetwork=true --set controller.kind=DaemonSet --set controller.service.enabled=false"
sealos run labring/kubeblocks:v0.7.1


sealos run --env DOMAIN=$DOMAIN --env DB_PV_SIZE=5Gi --env OSS_PV_SIZE=5Gi --env EXTERNAL_HTTP_SCHEMA=http lafyun/laf:latest

部署后配置

基本上部署是一键的,不需要其他的命令或者操作,部署完成需要一些配置,例如https 和内部的一些配置

修改 runtime-exporter 配置

runtime-exporter 是 laf 的运行时镜像,这个因为使用了 docker.io 的地址,所以部署后肯定会出现 ErrImagePull 类似这样的错误,所以需要手动修改该节点的配置

需要先拉下来 deployment.yaml 配置文件

kubectl get deployment runtime-exporter -o yaml > deployment.yaml -n laf-system

修改 docker.io 为配置的 docker 代理地址后执行:

kubectl apply -f deployment.yaml

可以先删除 runtime-exporter 的 pod,也可以等待执行

kubectl delete pods -l app.kubernetes.io/name=runtime-exporter -n laf-system

这样即可替换

运行完成查看 pod 的状态

kubectl get pods -A

替换完成所有 pod 的运行状态大概是这样的:

此处引用了白夜的部署教程图片
https://forum.laf.run/d/241

修改数据库配置

需要首先映射 mongodb 的端口到宿主机,然后通过 ssh 链接

先获取 mongodb 的密码

kubectl get secrets -n laf-system mongodb-conn-credential -o jsonpath='{.data.password}' | base64 --decode

映射端口到宿主机

kubectl port-forward mongodb-mongodb-0 27017:27017 -n laf-system

通过 mongodb compass链接数据库

数据库的链接是 mongodb://root:你的密码@127.0.0.1:27017/sys_db?authSource=admin&replicaSet=mongodb-mongodb&w=majority

这里需要注意,因为服务器配置了不能通过密码只能使用 ssh key 的方式,这里选择SSH Identity File

这里需要修改 runtime collection 中的 image 字段

需要修改为之前设置的 docker 代理地址,不然新建应用会启不起来

证书配置

其他基本配置完成,现在还需要一个 https 证书,证书一般有两种方式,laf 部署脚本中有安装 cert-manager,我们可以通过 cert-manager 来管理集群的证书,还有一种是直接在手动替换 ingress 的 tls 也就是 laf 使用的网关来完成

cert-manager 部署一直遇到问题,我想使用的是 acme 完成证书的自动更新,但是一直遇到网络问题

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-sys
  namespace: lafyun
spec:
  ingressClassName: nginx
  tls:
  - hosts:
      - www.lafyun.com
    secretName: lafyun-tls-secret
  rules:
  - host: www.lafyun.com
     # ....

所以我通过直接使用 acme 签名证书然后修改 tls 来解决的(后来也知道了该网络问题是因为集群内的 DNS 解析有问题导致的),也就是上述脚本的形式,可查看马老板的回复:https://github.com/labring/laf/issues/88

acme 证书申请

sh
./acme.sh --issue --dns dns_ali -d laf.a.com -d "*.laf.a.com" -d "*.oss.laf.a.com" -d "*.site.laf.a.com" -d "oss.a.com"

需注意这里需要同时申请 oss.a.com

我就是忘了申请,导致云存储访问有问题

证书安装

代码
./acme.sh --install-cert -d laf.a.com -d "*.laf.a.com" -d "*.oss.laf.a.com" -d "oss.a.com" -d "*.site.laf.a.com" --key-file /root/.acme.sh/laf.a.com_ecc/laf.a.com.key --fullchain-file /root/.acme.sh/laf.a.com_ecc/fullchain.cer

导入k8s

sh
kubectl create secret -n laf-system tls laf-cert-secret --cert=/root/.acme.sh/laf.a.com_ecc/fullchain.cer --key=/root/.acme.sh/laf.a.com_ecc/laf.a.com.key

查看 ingress

kubectl get ingress --all-namespaces

这个下面的节点都需要手动替换,已创建的应用可删除重新创建

可通过替换配置文件修改 tls 字段

sh
kubectl get ingress minio-console-ingress -o yaml > laf-minio-ingress.yaml -n laf-system

vim laf-minio-ingress.yaml

kubectl apply -f laf-minio-ingress.yaml

替换 tls 之后,可通过查看 ingress 查看节点端口是否已更新

kubectl get ingress --all-namespaces

修改数据库

这里同样需要修改数据库中的 tls 字段

修改 Region collection 中的 gatewayConf 中 tls 字段

wildcardCertificateSecretName: laf-cert-secret

这里名字需要与前边导入的 secret name 保持一致

更新域名证书

域名证书的更新同样和创建一样的步骤,唯一的区别是需要手动修改 tls

需要先把证书转为base64,然后更新 secret 的形式来完成域名证书的更新

  • 先转 base64
base64 -w 0 /root/.acme.sh/laf.a.com_ecc/fullchain.cer
base64 -w 0 /root/.acme.sh/laf.a.com_ecc/laf.marryto.me.key
  • 获取现有的 secret
kubectl get secret laf-cert-secret -n laf-system -o yaml > laf-cert-secret.yaml
  • 编辑 YAML 文件:tls 字段更新新的 base 编码

验证更新:

kubectl get secret laf-cert-secret -n laf-system -o yaml

其他问题

前边有提到有遇到过集群内访问外网失败问题,最开始是以为间歇性的,后来通过开启测试节点 ping 相应域名发现是集群内访问外网有问题导致的

网络问题

开一个测试节点

kubectl run -it --rm test-dns --image=busybox --restart=Never

执行 ping www.baidu.com 和 ping 39.156.66.10(外部IP,baidu的某一个节点),发现域名无法解析,IP能够Ping通,才找到问题

查了一下网上的解决方案,都是通过修改/etc/resolv.con的方式解决的,我试了下并未解决,后来看到一个取巧的方法,直接修改集群内的 dns 配置,遂试了一下

修改 DNS 配置

kubectl -n kube-system edit cm coredns

将 forward 修改为 8.8.8.8 也就是谷歌的 dns 服务器,然后解决了。。。

最后记得修改完成需要重启 dns 节点

重启 DNS pod

kubectl get pod -n kube-system | grep coredns |awk '{system("kubectl delete pod "$1" -n kube-system")}'

npm 安装问题

这里的 npm 安装问题一部分是网络问题,还有一部分和上边的集群 dns 问题比较相关,因为集群无法访问外网导致 npm 安装失败,最开始以为是 npmjs 网络问题导致的,后来测试节点 ping npm才发现是自己集群 dns 解析问题

这还是设置了NPM_INSTALL_FLAGS

代码
NPM_INSTALL_FLAGS=--registry=https://registry.npmmirror.com --canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas --sharp_binary_host=https://npmmirror.com/mirrors/sharp --sharp_libvips_binary_host=https://npmmirror.com/mirrors/sharp-libvips
需注意,npm还是要设置一下

后来修改了集群 dns 之后安装才成功

最后

到此我们的部署已全部完成,部署工程中基本没啥问题,部署后的配置到时遇到了很大的问题,总结起来基本上是两类问题:网络和k8s,还是需要熟悉k8s的各种操作才能玩转,至于网络问题只是一堵墙罢了。

可以开心的玩转自己的 laf 了。