Rancher 到 Portainer

2018/07/09

今年年初,在网上买了一台大公鸡(4C2G),一开始的时候是想着就用这台机子来部署个 k8s 集群来玩,然而一直抽不出时间。后来因为懒,所以就在上面部署了一个 Rancher,方便管理自己的博客站点。虽然 Rancher 好用,但是对资源的消耗还是挺大的,光是把 Rancher 运行起来就花掉了 1G 左右的内存。尽管如此,我还是坚持用了下去,不过体验确实挺不错的。不过前几天大公鸡突然失去网络连接,向主机商提交了工单后过了大半个星期一直没有回复,我这才断了继续使用大公鸡的念头,于是就着手把博客站点迁移到一台小鸡(1C1G)上面,这种小鸡当然是没法运行 Rancher 的,所以我就使用了 Portainer 作为替代品。

docker stack / docker swarm

Portainer 基本上就是 docker 命令行工具的 GUI。可以直接在网页上填写一个 docker-compose.yml 文件,然后 Portainer 就会使用 docker stack deploy 指令来把应用部署到 swarm 集群中。所以如果要熟练的使用 Portainer 界面,那么就至少要对 docker stackdocker swarm 有一定了解。

docker stack 可以用来根据 docker-compose.yml 文件来创建 stack,以我个人的理解,stack 就是一个聚合根,将多个微服务、微容器定义为一个整体,方便我们管理。

docker swarm 则为 stack 提供了底层的容器运行环境,通过 docker swarm 指令,我们可以在多个主机节点上创建集群,stack 中定义的服务可以被 swarm 智能的部署到集群中的各个节点中,通过 swarm 集群中的 overlay 网络,同一个 stack 中的服务可以相互通信。

Portainer 部署过程

考虑到以后大公鸡可能会重新复活,所以我就选择了使用 swarm 集群的方式来部署 Portainer,所以需要先创建一个 swarm 集群。接下来需要执行的操作就比较少了,创建一个 yml 文件:

# portainer-compose.yml
version: '3'

services:
  agent:
    image: portainer/agent
    environment:
      # REQUIRED: Should be equal to the service name prefixed by "tasks." when
      # deployed inside an overlay network
      AGENT_CLUSTER_ADDR: tasks.agent
      AGENT_PORT: 9001
      # LOG_LEVEL: debug
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - agent_network
    deploy:
      mode: global

  portainer:
    image: portainer/portainer
    command: -H tcp://tasks.agent:9001 --tlsskipverify
    ports:
      - "2333:9000"
    volumes:
      - ./data:/data
    networks:
      - agent_network
      - app
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]

networks:
  agent_network:
    driver: overlay
  app:
    driver: overlay

这份配置文件是从官方文档中的 docker-compose 样例修改而来的。因为要在集群中部署,为了能够让 Portainer 获取集群中各个节点的信息,所以需要使用 agent,agent 的默认端口需要设置为 9001,这样 Portainer 才能连接到 agent,同一个 stack 中的服务可以通过 task.server_name 来访问。

接着在定义 Portainer 服务的时候,可以在 manager 节点上 bind 一个端口,方便我们在反向代理 GG 的时候还能管理集群。

我让 Portainer 加入了两个 overlay 网络,一个用来跟 agent 通信,另一个用来跟反向代理连接。

接下来,就只需要运行:

docker stack deploy --compose-file=portainer-compose.yml portainer

然后 Portainer 就在本地的 Swarm 集群中运行起来了。

反向代理

我一直都挺喜欢使用 Caddy 作为反向代理服务器,他的全自动 HTTPS 功能真的非常好使,而且配置文件也非常简单(至少比 Nginx 简单多了🙃)。

Caddy 也可以使用 docker stack 的方式来部署,我也比较喜欢这样的方式,因为这样所有的配置文件都可以保存在 yml 中。通过下面的 docker-compose.yml 的配置,把 Caddy 加入 portainer_app overlay 网络,让 Caddy 可以对集群中的任何应用进行反向代理:

services:
  caddy-server:
    networks:
      - app
networks:
  app:
    external:
      name: portainer_app

对于同一 overlay 网络中的其他容器,在 Caddy 中就可以直接通过 service_name 来访问。