DevOps (4)| 反向代理服务器选择

个人服务器维护小书·发布于 4 年前
3 分钟阅读

个人服务器中一般会开启很多服务,例如 wiki.example.com,blog.example.com 。这个时候就需要反向代理服务器(也叫 Edge Router 边缘路由器)来转发这些请求。

反向代理

在日常使用中,我们一般会在一台服务器上部署多个服务。例如一个 web 服务和一个 api 服务。我们可能需要给 web 服务和 api 服务配置不同的域名,并且需要管理域名的 tls 证书。

之前一直使用的 nginx 来将不同的域名请求反向代理到 web 服务和 api 服务。使用 acme.sh 来自动化管理 tls 证书。不过每次新增服务都需要往 nginx 下面添加配置。

后来尝试了 caddy 服务器。相对 nginx 来说,caddy 会自动帮我们配置 tls 证书。当然,如果想要使用自己的证书,也可以在配置中覆盖 tls 配置。caddy 整体的配置比 nginx 简洁一些,不过每次新增服务,仍然需要往 caddy 下添加配置。

traefik 与 nginx 相比最大的特点是,traefik 会自动发现服务配置,每次新增服务时,无需更新 traefik 配置,traefik 会将请求转发给特定配置的服务。traefik 原生支持所有的集群服务,例如 Docker,Kubernetes,Docker Swarm 等。另外,traefik 提供了一个友好的仪表盘,可以直观地看到 traefik 的服务状态。

traefik 也可以很方便地添加 tls 配置。

traefik 的特性使它更多地被应用到微服务集群中,不过用它来管理个人服务器上的服务也很合适。

快速上手

traefik 提供了多种安装方式,如果电脑上已经安装了 docker 的话,建议以 docker 的形式启动,可以使用 docker 命令启动或者使用 docker-compose 文件

docker run -d -p 8080:8080 -p 80:80 traefik --api.insecure=true --api=true --log.level=debug --providers.docker=true

使用 docker-compose up -d 来启动 traefik

version: 3.3

services:
    traefik:
        image: traefik
        container_name: traefik
        command:
            - --api.insecure=true
            - --api=true
            - --log.level=debug
            - --providers.docker=true
        ports:
            - 80:80
            - 8080:8080

启动成功后,可以打开 localhost:8000 查看 traefik 仪表盘

Cent OS 上安装 traefik

version: 3.3

services:
    traefik:
        image: traefik
        container_name: traefik
        restart: always
        command:
            - --api=true
            - --log.level=debug
            - --api.dashboard=true
            - --providers.docker=true
            - --entrypoints.web.address=:80
            # https 配置
            - --entrypoints.websecure.address=:443
            - --certificatesresolvers.myresolver.acme.httpchallenge=true
            - --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web
            - --certificatesresolvers.myresolver.acme.email=haloislet@gmail.com
            - --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json
        labels:
            # 全局 http 跳 https
            - traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)
            - traefik.http.routers.http-catchall.entrypoints=web
            - traefik.http.routers.http-catchall.middlewares=redirect-to-https
            - traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
            # auth
            - traefik.http.routers.dashboard.rule=Host(`traefik.haloislet.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))
            - traefik.http.routers.dashboard.service=api@internal
            # 注意密码可以使用 htpasswd -nb 命令生成
            # 参考 https://docs.traefik.io/operations/dashboard/
            - traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xxxx/X$$xxxx/xxxx
            # https
            - traefik.port=8080
            - traefik.frontend.headers.forceSTSHeader=true
            - traefik.frontend.headers.STSSeconds=31536000
            - traefik.http.routers.dashboard.entrypoints=websecure
            - traefik.http.routers.dashboard.tls.certresolver=myresolver
            - traefik.docker.network=traefik
            # gzip
            - traefik.http.routers.dashboard.middlewares=test-compress,auth
            - traefik.http.middlewares.test-compress.compress=true
        ports:
            - 80:80
            - 443:443
        networks:
            - traefik
        volumes:
            - ./certs:/letsencrypt
            - /var/run/docker.sock:/var/run/docker.sock:ro
networks:
    traefik:
        external: true

docker.sock 挂载权限处理

REPL 系的的系统,例如 centos 中使用了 SELinux 来加固容器,所以直接挂载 docker.sock 会报权限错误,

可以使用 selinux-dockersock 脚本来解决这个问题

报错信息

ERROR: for test_proxy_1  Cannot start service proxy: OCI runtime create failed: container_linux.go:349: starting container process caused "process_linux.go:449: container init caused \"rootfs_linux.go:58: mounting \\\"/Volumes/work/test/traefik.toml\\\" to rootfs \\\"/var/lib/docker/overlay2/310a239ca1c7ded9af2a42a10eff65740937ca22b6e5b99a6b899d1fce6660da/merged\\\" at \\\"/var/lib/docker/overlay2/310a239ca1c7ded9af2a42a10eff65740937ca22b6e5b99a6b899d1fce6660da/merged/traefik.toml\\\" caused \\\"not a directory\\\"\"": unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type

解决方案

dnf install policycoreutils policycoreutils-python checkpolicy -y
git clone https://github.com/dpw/selinux-dockersock.git
cd selinux-dockersock && make
semodule -i dockersock.pp
  • 反向代理
  • 快速上手
  • Cent OS 上安装 traefik
    • docker.sock 挂载权限处理