daemon.json配置docker容器日志大小及错误排查

docker日志目录:/var/lib/docker/containers/<容器id>/

docker容器的运行日志,如果不加以限制,会越来越大,占用非常大的磁盘空间。可以通过daemon.json配置docker日志文件大小,全局有效。

    docker安装后默认没有daemon.json这个配置文件,需要进行手动创建,docker不管是在哪个平台以何种方式启动, 默认都会来这里读取配置,使用户可以统一管理不同系统下的 docker daemon 配置。

    如果在daemon.json文件中进行配置,需要docker版本高于1.12,配置文件的默认径为:/etc/docker/daemon.json      

    该文件作为 Docker Engine 的配置管理文件, 里面几乎涵盖了所有 docker 命令行启动可以配置的参数。

如果没有daemon.json,新建一个,添加以下内容:

{
"exec-opts": [""],
"log-driver":"json-file",
 "log-opts": {
   "max-size": "300m",
   "max-file": "1"
 }
}

然后重启docker守护进程:

systemctl daemon-reload
systemctl restart docker

如果docker无法启动报错,使用dockerd查看输出错误信息:

dockerd

在网上看到docker无法启动后,systemctl status docker.service、cat /lib/systemd/system/docker.service等等,各种排查,其实都不能有效的找出错误原因,只有dockerd才是输出有效的错误信息。

另外需要注意,改动了daemon.json后,都一定是要运行systemctl daemon-reload和systemctl restart docker来重启docker。

如果是docker-compose来运行容器的,也可以在 docker-compose.yml 中添加:

logging:
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "3"

APISIX网关部署使用教程

APISIX是一个具有动态、实时、高性能等特点的云原生 API 网关。你可以使用 APISIX 网关作为所有业务的流量入口,它提供了动态路由、动态上游、动态证书、A/B 测试、灰度发布(金丝雀发布)、蓝绿部署、限速、防攻击、收集指标、监控报警、可观测、服务治理等功能。

安装APISIX

部署apisix最简单的方法就是docker部署,直接使用官方的example配置。

git clone https://github.com/apache/apisix-docker.git
cd apisix-docker/example

example下的docker-compose.yml和docker-compose-arm64.yml分别对应的是X86和ARM服务器。

查看yml文件会发现,会启动了多个docker服务:

  • apisix:主程序,api网关;
  • etcd:APISIX 使用 etcd 作为配置中心进行保存和同步配置;
  • prometheus:开源的监控程序;
  • grafana:开源的看板程序;

web1和web2是测试程序,可以直接去掉。

另外,如果我们要使用apisix的UI控制面板,可以在docker-compose.yml中再加一个apisix-dashboard的docker服务:

  apisix-dashboard:
    image: apache/apisix-dashboard:3.0.1-alpine
    restart: always
    volumes:
    - ./dashboard_conf/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml
    ports:
    - "9000:9000"
    networks:
      apisix:

最终的docker-compose.yml文件为:

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

version: "3"

services:
  apisix-dashboard:
    image: apache/apisix-dashboard:3.0.1-alpine
    restart: always
    volumes:
    - ./dashboard_conf/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml
    ports:
    - "9000:9000"
    networks:
      apisix:

  apisix:
    image: apache/apisix:${APISIX_IMAGE_TAG:-3.6.0-debian}
    restart: always
    volumes:
      - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro
    depends_on:
      - etcd
    ##network_mode: host
    ports:
      - "9180:9180/tcp"
      - "9080:9080/tcp"
      - "9091:9091/tcp"
      - "9443:9443/tcp"
      - "9092:9092/tcp"
    networks:
      apisix:

  etcd:
    image: bitnami/etcd:3.4.15
    restart: always
    volumes:
      - etcd_data:/bitnami/etcd
    environment:
      ETCD_ENABLE_V2: "true"
      ALLOW_NONE_AUTHENTICATION: "yes"
      ETCD_ADVERTISE_CLIENT_URLS: "http://etcd:2379"
      ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
    ports:
      - "2379:2379/tcp"
    networks:
      apisix:

  prometheus:
    image: prom/prometheus:v2.25.0
    restart: always
    volumes:
      - ./prometheus_conf/prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"
    networks:
      apisix:

  grafana:
    image: grafana/grafana:7.3.7
    restart: always
    ports:
      - "3000:3000"
    volumes:
      - "./grafana_conf/provisioning:/etc/grafana/provisioning"
      - "./grafana_conf/dashboards:/var/lib/grafana/dashboards"
      - "./grafana_conf/config/grafana.ini:/etc/grafana/grafana.ini"
    networks:
      apisix:

networks:
  apisix:
    driver: bridge

volumes:
  etcd_data:
    driver: local

通过修改本地example/dashboard_conf/conf.yaml 文件,来修改控制面板的配置。需要修改users中的用户名和密码,用于登录控制面板。

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

conf:
  listen:
    host: 0.0.0.0     # `manager api` listening ip or host name
    port: 9000          # `manager api` listening port
  allow_list:           # If we don't set any IP list, then any IP access is allowed by default.
    - 0.0.0.0/0
  etcd:
    endpoints:          # supports defining multiple etcd host addresses for an etcd cluster
      - "http://etcd:2379"
                          # yamllint disable rule:comments-indentation
                          # etcd basic auth info
    # username: "root"    # ignore etcd username if not enable etcd auth
    # password: "123456"  # ignore etcd password if not enable etcd auth
    mtls:
      key_file: ""          # Path of your self-signed client side key
      cert_file: ""         # Path of your self-signed client side cert
      ca_file: ""           # Path of your self-signed ca cert, the CA is used to sign callers' certificates
    # prefix: /apisix     # apisix config's prefix in etcd, /apisix by default
  log:
    error_log:
      level: warn       # supports levels, lower to higher: debug, info, warn, error, panic, fatal
      file_path:
        logs/error.log  # supports relative path, absolute path, standard output
                        # such as: logs/error.log, /tmp/logs/error.log, /dev/stdout, /dev/stderr
    access_log:
      file_path:
        logs/access.log  # supports relative path, absolute path, standard output
                         # such as: logs/access.log, /tmp/logs/access.log, /dev/stdout, /dev/stderr
                         # log example: 2020-12-09T16:38:09.039+0800	INFO	filter/logging.go:46	/apisix/admin/routes/r1	{"status": 401, "host": "127.0.0.1:9000", "query": "asdfsafd=adf&a=a", "requestId": "3d50ecb8-758c-46d1-af5b-cd9d1c820156", "latency": 0, "remoteIP": "127.0.0.1", "method": "PUT", "errs": []}
  security:
      # access_control_allow_origin: "http://httpbin.org"
      # access_control_allow_credentials: true          # support using custom cors configration
      # access_control_allow_headers: "Authorization"
      # access_control-allow_methods: "*"
      # x_frame_options: "deny"
      content_security_policy: "default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; frame-src *"  # You can set frame-src to provide content for your grafana panel.

authentication:
  secret:
    secret              # secret for jwt token generation.
                        # NOTE: Highly recommended to modify this value to protect `manager api`.
                        # if it's default value, when `manager api` start, it will generate a random string to replace it.
  expire_time: 3600     # jwt token expire time, in second
  users:                # yamllint enable rule:comments-indentation
    - username: username   # username and password for login `manager api`
      password: password

plugins:                          # plugin list (sorted in alphabetical order)
  - api-breaker
  - authz-keycloak
  - basic-auth
  - batch-requests
  - consumer-restriction
  - cors
  # - dubbo-proxy
  - echo
  # - error-log-logger
  # - example-plugin
  - fault-injection
  - grpc-transcode
  - hmac-auth
  - http-logger
  - ip-restriction
  - jwt-auth
  - kafka-logger
  - key-auth
  - limit-conn
  - limit-count
  - limit-req
  # - log-rotate
  # - node-status
  - openid-connect
  - prometheus
  - proxy-cache
  - proxy-mirror
  - proxy-rewrite
  - redirect
  - referer-restriction
  - request-id
  - request-validation
  - response-rewrite
  - serverless-post-function
  - serverless-pre-function
  # - skywalking
  - sls-logger
  - syslog
  - tcp-logger
  - udp-logger
  - uri-blocker
  - wolf-rbac
  - zipkin
  - server-info
  - traffic-split

运行docker compose启动docker:

docker-compose -p docker-apisix up -d

配置APISIX

通过修改本地 ./conf/config.yaml 文件,完成对 APISIX 服务本身的基本配置。建议修改 Admin API 的key,保护 APISIX 的安全。同时可以限制IP访问API,增加安全性:

deployment:
  admin:
    allow_admin:               # https://nginx.org/en/docs/http/ngx_http_access_module.html#allow
      - 127.0.0.0/24              # We need to restrict ip access rules for security. 0.0.0.0/0 is for test.
      - 本机IP

    admin_key:
      - name: "admin"
        key: newpassword
        role: admin                 # admin: manage all configuration data

上述限制IP的策略,主要是考虑apisix-dashboard控制面板来访问api,其它应用场合根据实际情况修改。

使用APISIX

访问http://ip:9000,用上述用户名和密码就可以登录API控制面板了。具体使用过程比较简单,这里不详述,只说下在使用容易踩坑的地方。

apisix最常用的就是对访问进行限速控制,主要涉及到三个插件:

  • limit-conn:并发请求数
  • limit-count:指定时间窗口内的请求数量
  • limit-req:请求速率

而限速又涉及到访客IP,只有获取到用户的真实IP才能有效地限速,所以这里就又涉及到real ip插件。

  1. APISIX官方文档中,说real IP插件需要重新编辑APISIX-Base,但实际上,现在新版本的apisix docker镜像,都已经是运行在APISIX-Base上的。
  2. APISIX传递real IP给上游,需要自行配置,plugin字段中添加如下代码:
    "real-ip": {
      "source": "http_x_forwarded_for",
      "trusted_addresses": [
        "0.0.0.0/0"
      ]
    }

source必须为http_x_forwarded_for才有效,使用官方文档中的$remote_addr、$remote_port测试都无效,这是我踩过很久的坑。

trusted_addresses为信任的回源IP,可以根据实际情况修改。比如,如果使用nginx反代了apisix网关,则trust IP是反代服务器IP:

    "real-ip": {
      "source": "http_x_forwarded_for",
      "trusted_addresses": [
        "反代服务器IP"
      ]
    }

3. 在上述3个插件的配中,key的值必须为remote_addr,才能获取到访客真实IP,使用官方文档中的http_x_real_ip、http_x_forwarded_for都无效,也不知道是哪里的问题。

4. 如果你的APISIX前面还运行了一层nginx,或者是还套了一层cloudflare(访客访问域名 – cloudflare CDN – nginx – APISIX),那么就需要递归传递用户的真实IP,特别注意的是因为apisix运行在docker,所以set_real_ip_from需要添加docker内网IP段:

docker inspect 容器id
set_real_ip_from 172.18.0.0/24

可以参考前面的文章:https://www.168itw.com/web-server/cloudflare-cdn-real-ip/
也可以参考:https://github.com/apache/apisix/discussions/4793

其它更多功能还没有测试,后期继续补充完善该教程。