🔍

AWS Lambda に deploy した lxml が動かなくなったお話

2023/11/16に公開

発端

2023年11月上旬頃にアプリを修正してDeployしてエラー通知が届く

Couldn't find a tree builder with the features you requested: lxml. Do you need to install a parser library?

これは BeautifulSoup の parser で推奨されてる、lxml が使えない(もしくはインストールされていない) 場合に出るログである。

調査

今回のアプリは serverless framework を利用し、github actions を利用して deploy したものである。

github actions 上で生成した deploy package で再現するか確認

パッケージに含まれるライブラリの更新により、時々 serverless deploy 時にエラーが出てこともあり、github actionsのstepに、 serverless package が成功するか否か確認していた。

今回、そちらの成果物 (.serverless/) を artifact に保存するように修正、実行

- name: test for build package
  run: |
    npx serverless package --verbose --stage dev

# ↓ を追加
# deploy package の保存
- name: Archive deploy package results
  uses: actions/upload-artifact@v3
  with:
    name: deploy-package
    path: ./.serverless/**

実行後正常に成果物がuploadされていることを確認

こちらを手元にdownloadし、中身を確認。

$ mkdir -p /tmp/dist
$ cd /tmp/dist
$ unzip /path/to/deploy-package.zip
$ ls -l
total 30424
-rw-r--r--@  1 tututen  wheel    169934 11 14 09:59 app.zip
-rw-r--r--@  1 tututen  wheel      2077 11 14 09:59 cloudformation-template-create-stack.json
-rw-r--r--@  1 tututen  wheel    308269 11 14 09:59 cloudformation-template-update-stack.json
-rw-r--r--@  1 tututen  wheel  14622486 11 14 09:59 pythonRequirements.zip
drwxr-xr-x@ 64 tututen  wheel      2048 11 14 09:59 requirements
-rw-r--r--@  1 tututen  wheel      2289 11 14 10:01 requirements.txt
-rw-r--r--@  1 tututen  wheel    459051 11 14 10:01 serverless-state.json

serverless-python-requirementscustom.pythonRequirements.layer: true に設定しているので、 pythonRequirements.zip の中身を見ていく。

$ mkdir dist
$ cd dist
$ unzip ../pythonRequirements.zip
$ tree .
.
└── python
    ├── beautifulsoup4-4.12.2.dist-info
    ├── bs4
(.. snip ..)
    ├── lxml
    ├── lxml-4.9.3.dist-info
(.. snip ..)

AWSの用意しているDockerimage、 public.ecr.aws/sam/build-python3.9:latest-x86_64 を利用して、main.pyを実行して再現するか確認してみる

main.py
from bs4 import BeautifulSoup
BeautifulSoup("<p>Hello world!</p>", "lxml")
$ docker run --rm -v .:/var/task public.ecr.aws/sam/build-python3.9:latest-x86_64 python main.py
Traceback (most recent call last):
  File "/var/task/main.py", line 2, in <module>
    BeautifulSoup("<p>Hello world!</p>", "lxml")
  File "/var/task/bs4/__init__.py", line 250, in __init__
    raise FeatureNotFound(
bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: lxml. Do you need to install a parser library?

再現しました

BeautifulSoup の bs4.builder._lxml が読み込めるか

$ docker run --rm -v .:/var/task public.ecr.aws/sam/build-python3.9:latest-x86_64 python -c "from bs4.builder import _lxml"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/var/task/bs4/builder/_lxml.py", line 16, in <module>
    from lxml import etree
ImportError: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by /var/task/lxml/etree.cpython-39-x86_64-linux-gnu.so)

読み込めませんでした。

ImportError: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by /var/task/lxml/etree.cpython-39-x86_64-linux-gnu.so)

GLIBC 2.28が見つからない、とのことなので、runner側でのglibcの互換性が更新されたのかなーという推測ができます。

glibc の version を見てみる

public.ecr.aws/sam/build-python3.9:latest-x86_64 内は 2.26

$ docker run --rm -v .:/var/task public.ecr.aws/sam/build-python3.9:latest-x86_64 /lib64/libc.so.6
GNU C Library (GNU libc) stable release version 2.26, by Roland McGrath et al.
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 7.3.1 20180712 (Red Hat 7.3.1-17).
Available extensions:
	crypt add-on version 2.1 by Michael Glad and others
	GNU Libidn by Simon Josefsson
	Native POSIX Threads Library by Ulrich Drepper et al
	BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.

runner(github actions の runner: ubuntu-20.04) は 2.31

      - name: debug
        run: |
          /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.12) stable release version 2.31.
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 9.4.0.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

まとめ

今回は runner の glibc の更新により、AWS Lambda上で lxml が動かなくなったという結論になりました。

github actions の runnerの更新は結構頻繁に行われいるので、安全に lxml を deploy するのであれば、 public.ecr.aws/sam/build-python を利用して build し、 deployするのがよい。 ただ、2023年11月時点では、 lxml を github actions を利用して、deploy する場合、20分以上のビルド時間を許容できるかどうか考える必要があります。

今回、速度を求めないのであれば、デフォルトの html.parser を指定してしまうのも一つの手だと思います。

BeautifulSoup("<p>Hello world!</p>", "html.parser")

Discussion