Sử dụng và Phát triển Plugin Riêng cho Traefik Proxy 2.5

Traefik Proxy được thiết kế là một bộ định tuyến mô-đun hóa, cho phép bạn thêm các trung gian vào các tuyến đường của mình và thay đổi yêu cầu trước khi chúng đến đích là dịch vụ sau cuối. Traefik cung cấp nhiều trung gian tích hợp sẵn và cũng hỗ trợ việc tải các trung gian dưới dạng plugin.

  • https://doc.traefik.io/traefik/middlewares/overview/

Cách đơn giản nhất để tìm và cài đặt các plugin trung gian là thông qua Traefik Pilot. Traefik Pilot là một nền tảng SaaS cung cấp hệ thống chỉ số toàn cầu và cảnh báo cho tất cả các phiên bản Traefik Proxy của bạn, cùng với một cửa hàng plugin tích hợp sẵn có thể sử dụng miễn phí. Trong cửa hàng, bạn có thể duyệt qua tất cả các plugin mã nguồn mở có sẵn và cài đặt bằng cách nhấn nút.

  • https://doc.traefik.io/traefik-pilot/
  • https://pilot.traefik.io/plugins

Khi Traefik Proxy v2.5 ra mắt, có một phương pháp mới cho phép tải plugin trực tiếp từ lưu trữ cục bộ mà không cần kích hoạt Traefik Pilot. Chỉ cần đặt mã nguồn plugin của bạn vào thư mục mới gọi là /plugins-local. (Bạn sẽ tạo thư mục này tương đối với thư mục làm việc hiện tại [trừ khi bạn đang sử dụng hình ảnh Docker traefik, nơi đầu vào luôn là thư mục gốc /].) Traefik Proxy sẽ tự động xây dựng (giải thích) plugin của bạn, do đó bạn chỉ cần viết mã nguồn và cung cấp nó ở đúng thư mục để Traefik Proxy có thể tải nó. Mỗi lần khởi động, plugin chỉ được tải một lần (tức là, bạn phải khởi động lại traefik mỗi khi muốn cập nhật mã nguồn plugin).

  • https://github.com/traefik/traefik/pull/8224

Ví dụ về việc xây dựng hình ảnh Docker riêng và gói mã nguồn plugin vào

Dưới đây là một ví dụ về Dockerfile kết hợp lại hình ảnh Docker chuẩn traefik:v2.5 và thêm một plugin được tự động sao chép từ kho lưu trữ Git có thể cấu hình.

Tạo một thư mục tạm thời ở đâu đó và tạo một tệp mới tên là Dockerfile.demo:

# Dockerfile.demo - Ví dụ về Traefik Proxy và plugin demo từ git:
FROM alpine:3
ARG PLUGIN_MODULE=github.com/traefik/plugindemo
ARG PLUGIN_GIT_REPO=https://github.com/traefik/plugindemo.git
ARG PLUGIN_GIT_BRANCH=master
RUN apk add --update git && \
    git clone ${PLUGIN_GIT_REPO} /plugins-local/src/${PLUGIN_MODULE} \
      --depth 1 --single-branch --branch ${PLUGIN_GIT_BRANCH}

FROM traefik:v2.5
COPY --from=0 /plugins-local /plugins-local

Mặc định, các tham số xây dựng tải plugin demo do Traefik Labs phát hành, bản chất nó là bản sao của trung gian headers.customRequestHeaders nhưng dưới dạng plugin.

  • https://github.com/traefik/plugindemo
  • https://doc.traefik.io/traefik/middlewares/headers/#customrequestheaders

Trong cùng thư mục với Dockerfile.demo, hãy xây dựng hình ảnh:

docker build -f Dockerfile.demo --tag traefik-with-demo-plugin .

Bây giờ bạn đã xây dựng một hình ảnh Docker chứa Traefik v2.5 và plugin demo. Bạn có thể chạy hình ảnh này để kiểm tra:

docker run --rm -it traefik-with-demo-plugin \
  --log.level=DEBUG \
  --experimental.localPlugins.demo.moduleName=github.com/traefik/plugindemo

Log sẽ hiển thị rằng plugin đã được tải và cấu hình của Traefik Proxy sẽ chạy. Bạn có thể chắc chắn rằng nó hoạt động bằng cách dừng container bằng Ctrl-C, sau đó chạy lại lệnh thay đổi moduleName= thành github.com/something/different, bạn sẽ nhận được lỗi nói rằng nó không tồn tại và thoát ngay lập tức.

Xây dựng hình ảnh Docker Traefik Proxy với plugin tùy chỉnh

Để tạo plugin mới dựa trên thiết kế của bạn, hãy fork kho lưu trữ demo này. (Để thực hiện trực tiếp trên GitHub, bạn có thể nhấn nút xanh với nhãn Use this template, hoặc bạn có thể sao chép kho lưu trữ đến máy chủ khác). Bạn có thể chọn công khai hoặc riêng tư cho kho lưu trữ mới, nhưng hướng dẫn sẽ khác nhau tùy thuộc vào việc nó có cần xác thực để sao chép hay không, do đó sẽ giới thiệu từng trường hợp.

  • https://github.com/traefik/plugindemo

Sao chép kho lưu trữ fork của bạn đến máy tính cá nhân và đọc các hướng dẫn phát triển trong tệp readme.md. Tạo mã plugin của bạn, cập nhật dòng import trong .traefik.yml để khớp với tên kho lưu trữ của bạn, commit các thay đổi vào git, sau đó đẩy các thay đổi trở lại máy chủ git (GitHub) của bạn. Nếu bạn chỉ muốn thử mã nguồn plugin demo, bạn không cần commit bất kỳ thay đổi nào. Ngoài ra, Traefik không cần biên dịch mã nguồn plugin: plugin được tải thông qua mã nguồn gốc và được giải thích tại thời điểm chạy bởi Yaegi.

  • https://github.com/traefik/plugindemo/blob/master/readme.md
  • https://github.com/traefik/yaegi

Từ kho lưu trữ công khai xây dựng hình ảnh

Nếu bạn công khai kho lưu trữ, việc xây dựng hình ảnh rất dễ dàng. Mở terminal shell của bạn và tạo các biến môi trường tạm thời dưới dạng tham số xây dựng:

## Tạo các biến môi trường tạm thời cho plugin và kho lưu trữ git:
## Có thể lưu chúng vào build-env.sh và chạy "source build-env.sh" sau.
export DOCKER_IMAGE=traefik-with-my-plugin
export PLUGIN_MODULE=github.com/TÊN_CỦA_BẠN/KHO_LƯU_TRỮ_CỦA_BẠN
export PLUGIN_GIT_REPO=https://github.com/TÊN_CỦA_BẠN/KHO_LƯU_TRỮ_CỦA_BẠN.git
export PLUGIN_GIT_BRANCH=master

Thay đổi các biến này phù hợp với kho lưu trữ plugin fork của bạn:

  • DOCKER_IMAGE là tag cho hình ảnh Docker mới của bạn, sẽ bao gồm cả Traefik và mã nguồn plugin của bạn.
  • PLUGIN_MODULE là tên mô-đun Go của plugin (ví dụ github.com/traefik/plugindemo). Sử dụng tên máy chủ, tổ chức và kho lưu trữ fork của bạn.
  • PLUGIN_GIT_REPO là URL đầy đủ git clone tới kho lưu trữ trung tâm của plugin. (Ví dụ này giả định rằng sử dụng kho lưu trữ công khai và không cần xác thực, nếu không, xem phần tiếp theo.)
  • PLUGIN_GIT_BRANCH là tên nhánh git bạn muốn sao chép và cài đặt.

Tại thư mục gốc của kho lưu trữ đã sao chép, tạo một tệp mới tên là Dockerfile.public:

## Dockerfile.public - Gói một plugin Traefik từ kho lưu trữ git công khai
FROM alpine:3
ARG PLUGIN_MODULE=github.com/traefik/plugindemo
ARG PLUGIN_GIT_REPO=https://github.com/traefik/plugindemo.git
ARG PLUGIN_GIT_BRANCH=master
RUN apk update && \
    apk add git && \
    git clone ${PLUGIN_GIT_REPO} /plugins-local/src/${PLUGIN_MODULE} \
      --depth 1 --single-branch --branch ${PLUGIN_GIT_BRANCH}

FROM traefik:v2.5
COPY --from=0 /plugins-local /plugins-local

Xây dựng và gắn thẻ hình ảnh, truyền các tham số từ môi trường:

docker build -f Dockerfile.public \
  --tag ${DOCKER_IMAGE} \
  --build-arg PLUGIN_MODULE \
  --build-arg PLUGIN_GIT_REPO \
  --build-arg PLUGIN_GIT_BRANCH .

Từ kho git riêng tư xây dựng hình ảnh

Xây dựng hình ảnh từ kho git riêng tư khó khăn hơn vì bạn cần chuyển các thông tin xác thực SSH vào quá trình xây dựng Docker để sao chép từ kho git riêng tư theo kịch bản trong Dockerfile.

Bạn cần cập nhật cài đặt Docker lên phiên bản >=18.09, điều này cho phép các tính năng nâng cao BuildKit thử nghiệm cần thiết để tải khóa SSH từ ssh-agent và sử dụng tạm thời tài khoản người dùng máy tính để xây dựng hình ảnh Docker.

  • https://docs.docker.com/develop/develop-images/build_enhancements

Trong shell của bạn, thiết lập các biến môi trường:

## Có thể lưu chúng vào build-env.sh và chạy "source build-env.sh" sau.
## Docker BuildKit là bắt buộc để chuyển tiếp ssh-agent:
export DOCKER_BUILDKIT=1
## Chỉnh sửa các biến này cho plugin và kho lưu trữ git của bạn:
export DOCKER_IMAGE=traefik-with-my-plugin
export PLUGIN_MODULE=github.com/TÊN_CỦA_BẠN/KHO_LƯU_TRỮ_CỦA_BẠN
export PLUGIN_GIT_REPO=git@github.com:TÊN_CỦA_BẠN/KHO_LƯU_TRỮ_CỦA_BẠN.git
export PLUGIN_GIT_BRANCH=master

Chuyển tiếp ssh-agent của máy chủ cần chỉnh sửa Dockerfile. Tạo một tệp mới tên là Dockerfile.private:

# syntax=docker/dockerfile:1.0.0-experimental
# Dòng trên là bắt buộc để bật các tính năng thử nghiệm BuildKit.
# Dockerfile.private - Xây dựng Traefik và plugin từ kho git riêng tư.
# Tải các khóa SSH từ ssh-agent của máy chủ để cho phép sao chép git.
FROM alpine:3

# Sao chép các kho lưu trữ git plugin của bạn:
ARG PLUGIN_MODULE=github.com/traefik/plugindemo
ARG PLUGIN_GIT_REPO=git@github.com:traefik/plugindemo.git
ARG PLUGIN_GIT_BRANCH=master
RUN apk add --update git openssh && \
    mkdir -m 700 /root/.ssh && \
    touch -m 600 /root/.ssh/known_hosts && \
    ssh-keyscan github.com > /root/.ssh/known_hosts
RUN --mount=type=ssh git clone \
    --depth 1 --single-branch --branch ${PLUGIN_GIT_BRANCH} \
    ${PLUGIN_GIT_REPO} /plugins-local/src/${PLUGIN_MODULE} 
    
FROM traefik:v2.5
COPY --from=0 /plugins-local /plugins-local

Xây dựng hình ảnh sử dụng tùy chọn bổ sung --ssh default. Điều này sẽ kết nối quá trình xây dựng với ssh-agent đang chạy trên máy chủ, cho phép bạn sử dụng khóa SSH trong quá trình xây dựng và sao chép kho git riêng tư:

docker build -f Dockerfile.private \
  --ssh default --tag ${DOCKER_IMAGE} \
  --build-arg PLUGIN_MODULE \
  --build-arg PLUGIN_GIT_REPO \
  --build-arg PLUGIN_GIT_BRANCH .

Lưu ý: Hiện tại do có một vấn đề chưa giải quyết trong docker-compose, bạn không thể sử dụng tùy chọn --ssh (và kết nối với ssh-agent sẽ thất bại) nếu bạn muốn sử dụng Dockerfile đã chỉnh sửa này cùng với docker-compose, do đó bạn phải xây dựng hình ảnh container thủ công bằng lệnh docker build liệt kê ở trên. Nếu bạn xây dựng hình ảnh theo cách này trước, docker-compose có thể phụ thuộc vào bộ nhớ đệm xây dựng hoặc tên hình ảnh cụ thể mà không cần xây dựng lại.

  • https://github.com/docker/compose/issues/7025

Sử dụng docker-compose như môi trường phát triển plugin

Bạn có thể sử dụng docker-compose như một môi trường phát triển plugin đơn giản.

  • https://docs.docker.com/compose/

Sao chép kho lưu trữ plugin của bạn đến máy tính cá nhân, sau đó tạo các tệp mới vào thư mục gốc của kho lưu trữ:

Tạo Dockerfile:

FROM traefik:v2.5
## Tên mô-đun mặc định (đặt cài đặt của bạn trong .env để ghi đè)
ARG PLUGIN_MODULE=github.com/traefik/plugindemo
ADD . /plugins-local/src/${PLUGIN_MODULE}

Tạo tệp cài đặt .env:

## Tệp .env cho plugin Traefik Proxy địa phương
## Cấu hình tên plugin của bạn:
PLUGIN_NAME=demo
## Cấu hình không gian tên mô-đun:
PLUGIN_MODULE=github.com/traefik/plugindemo
## Cấu hình tên miền whoami cho thử nghiệm tuyến:
WHOAMI_TRAEFIK_HOST=whoami.example.com
## Cấu hình Địa chỉ email cho Let's Encrypt:
## Chỉ bỏ chú thích và cấu hình cho sản phẩm:
# ACME_CA_EMAIL=you@example.com

Tạo docker-compose.yaml:

# docker-compose.yaml cho phát triển plugin Traefik Proxy địa phương
version: "3.3"
networks:
  traefik-proxy:
volumes:
  traefik-proxy:

services:
  traefik-proxy:
    build:
      context: .
      args:
        PLUGIN_MODULE: ${PLUGIN_MODULE}
    restart: unless-stopped
    networks:
    - traefik-proxy
    security_opt:
    - no-new-privileges:true
    command:
    #- "--log.level=DEBUG"
    - "--providers.docker=true"
    - "--providers.docker.exposedbydefault=false"
    - "--providers.docker.network=traefik-proxy"
    ## Điểm cuối:
    - "--entrypoints.web.address=:80"
    - "--entrypoints.websecure.address=:443"
    - "--entrypoints.traefik.address=:9000"
    ## Chuyển hướng HTTP sang HTTPS tự động:
    - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
    ## Cấu hình TLS ACME:
    - "--certificatesresolvers.default.acme.storage=/data/acme.json"
    ## Bỏ chú thích cho chứng chỉ TLS sản phẩm (Let's Encrypt):
    # - "--certificatesresolvers.default.acme.tlschallenge=true"
    # - "--certificatesresolvers.default.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
    # - "--certificatesresolvers.default.acme.email=${ACME_CA_EMAIL}"
    ## Kích hoạt bảng điều khiển chỉ có sẵn từ localhost docker:9000:
    - "--api.dashboard=true"
    - "--api.insecure=true"
    ## Kích hoạt plugin địa phương:
    - "--experimental.localPlugins.${PLUGIN_NAME}.moduleName=${PLUGIN_MODULE}"
    ports:
    - "80:80"
    - "443:443"
    - "127.0.0.1:9000:9000"
    volumes:
    - "traefik-proxy:/data"
    - "/var/run/docker.sock:/var/run/docker.sock:ro"

  ## Container whoami sẽ chạy plugin demo để thử nghiệm:
  whoami:
    image: traefik/whoami
    networks:
      - traefik-proxy
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`${WHOAMI_TRAEFIK_HOST}`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      # Cấu hình plugin như một trung gian mới:
      - "traefik.http.routers.whoami.middlewares=whoami-demo"
      # Thêm một tiêu đề kiểm tra vào tất cả các yêu cầu đến:
      # (có sự hiện diện của tiêu đề này trong phản hồi whoami cho thấy plugin hoạt động:)
      - "traefik.http.middlewares.whoami-demo.plugin.${PLUGIN_NAME}.headers.DoesPluginWork=YES"
      - "traefik.http.routers.whoami.tls.certresolver=default"

Tạo .dockerignore để loại trừ thư mục .git khỏi việc xây dựng hình ảnh:

# .dockerignore loại trừ các tệp khỏi việc xây dựng hình ảnh:
.git

Xây dựng hình ảnh và khởi động phiên bản thử nghiệm:

docker-compose up

Chỉnh sửa tệp /etc/hosts của bạn (hoặc máy chủ DNS cục bộ) và thêm tên miền tuyến whoami:

# ... đoạn trích từ /etc/hosts
# Tên miền cho Traefik:
# Chỉ đến địa chỉ IP của máy chủ docker của bạn:
127.0.0.1 whoami.example.com app1.example.com app2.example.com

Sử dụng curl để kiểm tra DNS của bạn có hoạt động không và plugin đã được kích hoạt (sử dụng cùng tên miền bạn đã cấu hình cho WHOAMI_TRAEFIK_HOST/etc/hosts):

curl -k https://whoami.example.com

Bạn nên nhận được phản hồi từ whoami và thấy tiêu đề kiểm tra trong đầu ra:

Doespluginwork: YES

Đây là cấu hình plugin để chèn tiêu đề và giá trị giống như yêu cầu, và phản hồi từ whoami hiển thị. Nếu bạn thấy nó, bạn biết rằng plugin của bạn đã được cấu hình thành công.

Cấu hình dịch vụ DNS cục bộ cho công việc phát triển thông thường

Khi bạn cần thử nghiệm nhiều tên miền phụ và quy tắc định tuyến Host của Traefik Proxy, một giải pháp DNS tốt hơn so với việc chỉnh sửa liên tục tệp /etc/hosts là chạy dnsmasq trên máy tính cá nhân của bạn như một máy chủ DNS cục bộ, phản hồi các truy vấn bản ghi DNS A đại diện cho toàn bộ tên miền gốc hoặc tên miền phụ.

Cấu hình dnsmasq là tùy chọn và bổ sung cho tệp /etc/hosts. Hướng dẫn cài đặt dnsmasq phụ thuộc vào hệ điều hành của bạn, nhưng có thể được cài đặt từ hầu hết các trình quản lý gói. dnsmasq sẽ làm cho công việc phát triển của bạn mượt mà hơn và là cách tốt để làm sạch tệp /etc/hosts. Đây là một ví dụ tệp cấu hình /etc/dnsmasq.conf để thiết lập dịch vụ DNS cục bộ với tên miền đại diện. Bạn cũng cần chỉnh sửa tệp /etc/resolv.conf theo hướng dẫn trong chú thích:

# /etc/dnsmasq.conf
# Sử dụng điều này nếu bạn đã chán việc chỉnh sửa tệp /etc/hosts của mình.
# Đây là dịch vụ DNS cục bộ chỉ ràng buộc với thiết bị vòng tắt trên localhost.
# Để sử dụng điều này yêu cầu một tệp /etc/resolv.conf 
# với một dòng duy nhất (không có khoảng trắng đầu): nameserver 127.0.0.1
# Để ngăn chặn bất kỳ thay đổi nào đến cấu hình DNS máy chủ,
# chạy: sudo chattr +i /etc/resolv.conf
#      (bây giờ tất cả các truy vấn DNS của bạn sẽ đi qua dnsmasq)
interface=lo
listen-address=::1,127.0.0.1
bind-interfaces
cache-size=1000
# Sử dụng các máy chủ DNS cloudflare phía trước:
server=1.1.1.1
server=1.0.0.1
# Các tên miền đại diện ví dụ
# Tất cả các tên *.example.com trỏ đến một địa chỉ IP máy chủ docker duy nhất:
address=/example.com/127.0.0.1
# dnsmasq cũng tải tệp /etc/hosts của bạn, vì vậy các tên máy chủ đó vẫn hoạt động.

Kiểm tra hướng dẫn hệ điều hành của bạn để kích hoạt dịch vụ dnsmasq, nhưng thường sử dụng Systemd:

sudo systemctl enable --now dnsmasq.service

Chỉnh sửa /etc/resolv.conf để sử dụng máy chủ dnsmasq cho tất cả các truy vấn DNS hệ thống:

domain your.domain.example.com
search domain.example.com
nameserver 127.0.0.1

Sometimes other services (systemd-resolved) muốn ghi đè lên tệp này, bạn có thể ngăn chặn điều này bằng cách áp dụng cờ không thể chỉnh sửa lên tệp:

# Điều này ngăn chỉnh sửa tệp, sử dụng -i để kích hoạt chỉnh sửa:
chattr +i /etc/resolv.conf

Bạn có thể sử dụng các tiện ích dig, drill hoặc nslookup để kiểm tra xem máy chủ DNS có hoạt động không:

# dig hoặc drill:
dig test.example.com | grep -A1 "SECTION PHẢN HỒI"
# hoặc nslookup:
nslookup test.example.com

Kết quả của bất kỳ công cụ nào cũng nên báo cáo địa chỉ IP chính xác của máy chủ docker của bạn, bây giờ bạn có thể sử dụng bất kỳ tên miền phụ nào bạn muốn trong định tuyến Traefik Proxy.

Thẻ: traefik-proxy plugin-development docker docker-compose dnsmasq

Đăng vào ngày 21 tháng 5 lúc 09:42