在MacBook Pro(M1芯片)上部署Apinto开源网关

发布时间 2023-03-23 16:57:53作者: Ken-L

最近在学习API网关的知识,查询资料了解到了Apinto开源网关,抱着学习的态度部署Apinto开源网关来玩一下。

看官方介绍推荐部署在Linux服务器,成本太高,先部署在本地玩玩吧,在此做一些记录。

部署步骤

从github上,了解到我们需要部署两个产品

  • Apinto:API开源网关节点,提供OpenAPI进行网关配置,负责代理请求等核心网关功能。

  • Apinto-Dashboard:Apinto可视化控制台,通过OpenAPI与Apinto进行配置交互。

部署Apinto-Dashboard

在这里,我使用docker-compose进行一键部署,官方提供的docker-compose.yml文件内容如下

version: '3'
services:
  mysql:
    image: mysql:5.7.21
    privileged: true
    restart: always
    container_name: apinto_mysql
    hostname: apinto_mysql
    ports:
      - "33306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD={MYSQL_PWD}
      - MYSQL_DATABASE=apinto
    volumes:
      - /var/lib/apinto/mysql:/var/lib/mysql
    networks:
      - apinto
  apinto-dashboard:
    image: eolinker/apinto-dashboard
    container_name: apinto-dashboard
    privileged: true
    restart: always
    networks:
      - apinto
    ports:
      - "18080:8080"
    depends_on:
      - mysql
      - redis_cluster
    environment:
      - MYSQL_USER_NAME=root
      - MYSQL_PWD={MYSQL_PWD}
      - MYSQL_IP=apinto_mysql
      - MYSQL_PORT=3306                 #mysql端口
      - MYSQL_DB="apinto"
      - ERROR_DIR=/apinto-dashboard/work/logs  # 日志放置目录
      - ERROR_FILE_NAME=error.log          # 错误日志文件名
      - ERROR_LOG_LEVEL=info               # 错误日志等级,可选:panic,fatal,error,warning,info,debug,trace 不填或者非法则为info
      - ERROR_EXPIRE=7d                    # 错误日志过期时间,默认单位为天,d|天,h|小时, 不合法配置默认为7d
      - ERROR_PERIOD=day                  # 错误日志切割周期,仅支持day、hour
      - REDIS_ADDR=172.100.0.1:7201,172.100.0.1:7202,172.100.0.1:7203,172.100.0.1:7204,172.100.0.1:7205,172.100.0.1:7206 #Redis集群地址 多个用,隔开
      - REDIS_PWD={REDIS_PWD}                         # Redis密码
    volumes:
      - /var/log/apinto/apinto-dashboard/work:/apinto-dashboard/work   #挂载log到主机目录
  redis_cluster:
    container_name: redis_cluster
    image: eolinker/cluster-redis:6.2.7
    hostname: redis_cluster
    privileged: true
    restart: always
    environment:
      - REDIS_PWD={REDIS_PWD}
      - PORT=7201
      - HOST={HOST}
    volumes: 
      - /var/lib/apinto/redis-cluster/data:/usr/local/cluster_redis/data
    network_mode: host
networks:
  apinto:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.100.0.0/24

在Mac M1上运行docker,有几点我们需要注意

1、新增配置platform: linux/amd64

由于镜像的基础运行架构是linux/amd64,在文件配置时,我们需要加上platform: linux/amd64才能保证镜像在Mac M1上运行。如下图

image.png

上图仅展示了apinto-dashboard的修改,剩余两个容器也应该做此修改。

2、将容器挂载目录改为当前用户可读写的目录

由于Mac文件夹权限的限制,防止镜像启动失败,我们需要修改容器的挂载目录为当前用户可读写的目录。

挂载路径如下:

  • mysql容器:./apinto/mysql:/var/lib/mysql

  • apinto-dashboard容器:./apinto/apinto-dashboard/work:/apinto-dashboard/work

  • redis_cluster容器:./apinto/redis-cluster/data:/usr/local/cluster_redis/data

部署遇到的问题

若按照官方教程部署镜像mysql:5.7.21,容器启动失败。

image.png

执行命令查看报错:

docker logs apinto_mysql

报错信息如下:

runtime: failed to create new OS thread (have 2 already; errno=22)
fatal error: newosproc

runtime stack:
runtime.throw(0x524da0, 0x9)
        /usr/local/go/src/runtime/panic.go:527 +0x90
runtime.newosproc(0xc82002a000, 0xc820039fc0)
        /usr/local/go/src/runtime/os1_linux.go:150 +0x1ab
runtime.newm(0x555ce8, 0x0)
        /usr/local/go/src/runtime/proc1.go:1105 +0x130
runtime.main.func1()
        /usr/local/go/src/runtime/proc.go:48 +0x2c
runtime.systemstack(0x5c4300)
        /usr/local/go/src/runtime/asm_amd64.s:262 +0x79
runtime.mstart()
        /usr/local/go/src/runtime/proc1.go:674

goroutine 1 [running]:
runtime.systemstack_switch()
        /usr/local/go/src/runtime/asm_amd64.s:216 fp=0xc820024770 sp=0xc820024768
runtime.main()
        /usr/local/go/src/runtime/proc.go:49 +0x62 fp=0xc8200247c0 sp=0xc820024770
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1696 +0x1 fp=0xc8200247c8 sp=0xc8200247c0
runtime: failed to create new OS thread (have 2 already; errno=22)
fatal error: newosproc

runtime stack:
runtime.throw(0x524da0, 0x9)
        /usr/local/go/src/runtime/panic.go:527 +0x90
runtime.newosproc(0xc82002a000, 0xc820039fc0)
        /usr/local/go/src/runtime/os1_linux.go:150 +0x1ab
runtime.newm(0x555ce8, 0x0)
        /usr/local/go/src/runtime/proc1.go:1105 +0x130
runtime.main.func1()
        /usr/local/go/src/runtime/proc.go:48 +0x2c
runtime.systemstack(0x5c4300)
        /usr/local/go/src/runtime/asm_amd64.s:262 +0x79
runtime.mstart()
        /usr/local/go/src/runtime/proc1.go:674

goroutine 1 [running]:
runtime.systemstack_switch()
        /usr/local/go/src/runtime/asm_amd64.s:216 fp=0xc820024770 sp=0xc820024768
runtime.main()
        /usr/local/go/src/runtime/proc.go:49 +0x62 fp=0xc8200247c0 sp=0xc820024770
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1696 +0x1 fp=0xc8200247c8 sp=0xc8200247c0
runtime: failed to create new OS thread (have 2 already; errno=22)
fatal error: newosproc

runtime stack:
runtime.throw(0x524da0, 0x9)
        /usr/local/go/src/runtime/panic.go:527 +0x90
runtime.newosproc(0xc82002a000, 0xc820039fc0)
        /usr/local/go/src/runtime/os1_linux.go:150 +0x1ab
runtime.newm(0x555ce8, 0x0)
        /usr/local/go/src/runtime/proc1.go:1105 +0x130
runtime.main.func1()
        /usr/local/go/src/runtime/proc.go:48 +0x2c
runtime.systemstack(0x5c4300)
        /usr/local/go/src/runtime/asm_amd64.s:262 +0x79
runtime.mstart()
        /usr/local/go/src/runtime/proc1.go:674

goroutine 1 [running]:
runtime.systemstack_switch()
        /usr/local/go/src/runtime/asm_amd64.s:216 fp=0xc820024770 sp=0xc820024768
runtime.main()
        /usr/local/go/src/runtime/proc.go:49 +0x62 fp=0xc8200247c0 sp=0xc820024770
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1696 +0x1 fp=0xc8200247c8 sp=0xc8200247c0
runtime: failed to create new OS thread (have 2 already; errno=22)
fatal error: newosproc

runtime stack:
runtime.throw(0x524da0, 0x9)
        /usr/local/go/src/runtime/panic.go:527 +0x90
runtime.newosproc(0xc82002a000, 0xc820039fc0)
        /usr/local/go/src/runtime/os1_linux.go:150 +0x1ab
runtime.newm(0x555ce8, 0x0)
        /usr/local/go/src/runtime/proc1.go:1105 +0x130
runtime.main.func1()
        /usr/local/go/src/runtime/proc.go:48 +0x2c
runtime.systemstack(0x5c4300)
        /usr/local/go/src/runtime/asm_amd64.s:262 +0x79
runtime.mstart()
        /usr/local/go/src/runtime/proc1.go:674

goroutine 1 [running]:
runtime.systemstack_switch()
        /usr/local/go/src/runtime/asm_amd64.s:216 fp=0xc820024770 sp=0xc820024768
runtime.main()
        /usr/local/go/src/runtime/proc.go:49 +0x62 fp=0xc8200247c0 sp=0xc820024770
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1696 +0x1 fp=0xc8200247c8 sp=0xc8200247c0
runtime: failed to create new OS thread (have 2 already; errno=22)
fatal error: newosproc

runtime stack:
runtime.throw(0x524da0, 0x9)
        /usr/local/go/src/runtime/panic.go:527 +0x90
runtime.newosproc(0xc82002a000, 0xc820039fc0)
        /usr/local/go/src/runtime/os1_linux.go:150 +0x1ab
runtime.newm(0x555ce8, 0x0)
        /usr/local/go/src/runtime/proc1.go:1105 +0x130
runtime.main.func1()
        /usr/local/go/src/runtime/proc.go:48 +0x2c
runtime.systemstack(0x5c4300)
        /usr/local/go/src/runtime/asm_amd64.s:262 +0x79
runtime.mstart()
        /usr/local/go/src/runtime/proc1.go:674

goroutine 1 [running]:
runtime.systemstack_switch()
        /usr/local/go/src/runtime/asm_amd64.s:216 fp=0xc820024770 sp=0xc820024768
runtime.main()
        /usr/local/go/src/runtime/proc.go:49 +0x62 fp=0xc8200247c0 sp=0xc820024770
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1696 +0x1 fp=0xc8200247c8 sp=0xc8200247c0

头疼.....M1芯片好多怪事......应该是版本不兼容,那换一个最新的镜像试试,将mysql镜像改成了mysql:5.7.34

重启执行docker-compose命令

docker-compose up -d

运行docker ps命令查看执行结果

image.png

访问控制台

image.png

Docker-Compose完整配置

docker-compose.yml完整文件示例如下

version: '3'
services:
  mysql:
    image: mysql:5.7.34
    privileged: true
    platform: linux/amd64
    restart: always
    container_name: apinto_mysql
    hostname: apinto_mysql
    ports:
      - "33306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - MYSQL_DATABASE=apinto
    volumes:
      - ./apinto/mysql:/var/lib/mysql
    networks:
      - apinto
  apinto-dashboard:
    image: eolinker/apinto-dashboard
    container_name: apinto-dashboard
    privileged: true
    platform: linux/amd64
    restart: always
    networks:
      - apinto
    ports:
      - "18080:8080"
    depends_on:
      - mysql
      - redis_cluster
    environment:
      - MYSQL_USER_NAME=root
      - MYSQL_PWD=123456
      - MYSQL_IP=apinto_mysql
      - MYSQL_PORT=3306                 #mysql端口
      - MYSQL_DB="apinto"
      - ERROR_DIR=/apinto-dashboard/work/logs  # 日志放置目录
      - ERROR_FILE_NAME=error.log          # 错误日志文件名
      - ERROR_LOG_LEVEL=info               # 错误日志等级,可选:panic,fatal,error,warning,info,debug,trace 不填或者非法则为info
      - ERROR_EXPIRE=7d                    # 错误日志过期时间,默认单位为天,d|天,h|小时, 不合法配置默认为7d
      - ERROR_PERIOD=day                  # 错误日志切割周期,仅支持day、hour
      - REDIS_ADDR=172.100.0.1:7201,172.100.0.1:7202,172.100.0.1:7203,172.100.0.1:7204,172.100.0.1:7205,172.100.0.1:7206 #Redis集群地址 多个用,隔开
      - REDIS_PWD=123456                         # Redis密码
    volumes:
      - ./apinto/apinto-dashboard/work:/apinto-dashboard/work   #挂载log到主机目录
  redis_cluster:
    container_name: redis_cluster
    image: eolinker/cluster-redis:6.2.7
    platform: linux/amd64
    hostname: redis_cluster
    privileged: true
    restart: always
    environment:
      - REDIS_PWD=123456
      - PORT=7201
      - HOST=127.0.0.1
    volumes:
      - ./apinto/redis-cluster/data:/usr/local/cluster_redis/data
    network_mode: host
networks:
  apinto:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.100.0.0/24

部署Apinto

官方提供了安装包和docker两种方式部署,我这里还是继续选择使用安装包来部署Apinto节点。

1、下载Apinto安装包并解压

由于Mac M1芯片是ARM64架构,因此我这里选择下载apinto_v0.12.4_darwin_arm64.tar.gz

wget https://github.com/eolinker/apinto/releases/download/v0.12.4/apinto_v0.12.4_darwin_arm64.tar.gz && tar -zxvf apinto_v0.12.4_darwin_arm64.tar.gz && cd apinto

更多版本安装包可以访问网址:https://github.com/eolinker/apinto/releases/tag 进行获取

2、编辑运行配置文件apinto.yml

执行编辑文件命令

vi apinto.yml

文件内容

# 数据文件放置目录
data_dir: ./work/data

# pid文件放置地址
pid_dir: ./work/run

# 日志放置目录
log_dir: ./work/log

# socket放置目录
socket_dir: ./work/socket

# apinto运行配置地址
config: config.yml

# 扩展仓库目录
extends_dir: ./work/extenders/

# 错误日志文件名
error_log_name:  error.log

# 错误日志等级
error_log_level: error

# 错误日志过期时间,默认单位为天,d|天,h|小时
error_log_expire: 7d

# 错误日志切割周期,仅支持day、hour
error_log_period: day

编辑完成后,保存到当前目录。

3、编辑配置文件config.yml

执行编辑文件命令

vi config.yml

文件内容

version: 2
#certificate: # 证书存放根目录
#  dir: /etc/apinto/cert
client:
  #advertise_urls: # open api 服务的广播地址
  #- http://127.0.0.1:9400
  listen_urls: # open api 服务的监听地址
    - http://0.0.0.0:9400
  #certificate:  # 证书配置,允许使用ip的自签证书
  #  - cert: server.pem
  #    key: server.key
gateway:
  #advertise_urls: # 转发服务的广播地址
  #- http://127.0.0.1:9400
  listen_urls: # 转发服务的监听地址
    - https://0.0.0.0:8099
    - http://0.0.0.0:8099
peer: # 集群间节点通信配置信息
  listen_urls: # 节点监听地址
    - http://0.0.0.0:9401
  #advertise_urls: # 节点通信广播地址
  # - http://127.0.0.1:9400
  #certificate:  # 证书配置,允许使用ip的自签证书
  #  - cert: server.pem
  #    key: server.key

编辑完成后,保存到当前目录。

4、启动程序

./apinto start

查看执行结果

ps -ef | grep apinto

得到下图所示结果,运行正常

image.png

Apinto-Dashboard绑定Apinto

虽然程序全部部署完成,但我发现好像两个程序没有交互,怎么保证Dashboard的配置能同步到Apinto呢?

为此,我再查了一下相关文档,发现还需要再新建集群并绑定节点,再花些时间在此记录。

1、点击导航栏的基础设施 -> 集群管理,点击新建集群

image.png

2、编辑集群配置后点击测试

image.png

当测试通过后点击保存,集群便新建完成。

注意:由于Dashboard是容器运行,Apinto是在宿主机上运行,因此Dashboard需要使用docker.for.mac.host.internal才可以访问宿主机的端口

总结

虽然因为Mac M1的奇奇怪怪的兼容问题,安装部署花了点时间,接下来就可以继续深入使用Apinto开源网关了,先体验一波再说。