Lambdaからseleniumが乗っているFargateを実行する


Lambdaからboto3でseleniumが乗っているFargateを実行するときの注意点です。

Local環境でコンテナを生成して確認したときは何も問題がでていなかったのですが、
Fargate上で動かすと以下のようなエラーがでました。

selenium.common.exceptions.WebDriverException: Message: chrome not reachable
(Session info: headless chrome=83.0.4103.97)

「Chromeに到達できません」

というエラーのようです。
seleniumの設定はこんな感じでした。

selenium.py
from selenium.webdriver import Chrome, ChromeOptions, Remote
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

chrome_options = ChromeOptions()
chrome_options.add_argument("start-maximized");
chrome_options.add_argument("disable-infobars")
chrome_options.add_argument("--disable-extensions")
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument("--disable-setuid-sandbox")
chrome_options.add_argument('--window-size=1420,1080')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')

driver = Chrome(chrome_options=chrome_options)

chromedriverの場所がわからないようなので、webdriver.Chromeを設定するところで、executable_path='/usr/bin/chromedriver'を追加します。

selenium.py

#〜〜〜〜〜省略〜〜〜〜〜〜〜〜〜〜〜

#driver = Chrome(chrome_options=chrome_options)
driver = Chrome(executable_path='/usr/bin/chromedriver',chrome_options=chrome_options)

これで到達するようにはなりましたが、、

以下のエラーが発生。

selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: was killed.
(chrome not reachable)
(The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)

翻訳すると以下の内容です。

メッセージ:不明なエラーです。Chrome の起動に失敗しました:殺されました。
(クロームには到達できません)
(chromeの場所/usr/bin/google-chromeから起動したプロセスはもう実行されていないので、ChromeDriverはChromeがクラッシュしたと仮定しています)

いろいろググると、Chromedriverのバージョンが、google-chromeのバージョンを追い越してしまったときに起こるようです。

ただ、私はselenium/standalone-chromeイメージを使ってコンテナ作っているので、バージョンはもともとあっているはず。。
念の為、コンテナを調べましたが、当然のようにimage自体がきっちりバージョンを合わせてくれてます。

$ google-chrome --version
Google Chrome 83.0.4103.97 

$ chromedriver --version
ChromeDriver 83.0.4103.61 (94f915a8d7c408b09cc7352161ad592299f384d2-refs/branch-heads/4103@{#561})

そこで失敗したタスクの状況を調べてみました。

状況の理由がOutOfMemoryError: Container killed due to memory usageとなっています。そしてメモリも64になっているような・・。
以下がboto3のecsのrun_taskででFargateを呼び出しているところです。

selenium.py
client = boto3.client('ecs')
response = client.run_task(
    capacityProviderStrategy=[
        {
            'capacityProvider': 'FARGATE_SPOT',
            'weight': 1,
            'base': 1
        },
    ],
    cluster='selenium',
    taskDefinition='selenium',
    count=1,
    networkConfiguration={
        'awsvpcConfiguration': {
            'subnets': [
                'subnet-99999999999999998',
                'subnet-99999999999999999'
            ],
            'securityGroups': [
                'sg-99999999999999999'
            ],
            'assignPublicIp': 'ENABLED'
        }
    },
    overrides={
        'containerOverrides': [
            {
                'name': 'sel',
                'command': ["python3",
                            "main.py",
                            "start"]
                ,
                'memory': 64 # コンテナーに設定されたメモリーのハード制限(MiB単位)
            }
        ],
            'taskRoleArn': "arn:aws:iam::999999999999:role/ecsTaskExecutionRole"
    },
    platformVersion='LATEST'
)

memoryが64になっている。。

タスク定義でメモリは512を設定していましたが、boto3でコンテナをオーバライドするときに、メモリのハード制限をかけてしまっていた模様。

memory:コンテナーに設定されたメモリーのハード制限(MiB単位)

memoryを512にして、再度実行すると無事Fargate上でSeleniumが動きました。
なぜ64を設定していたのかは謎です。。
こんなことする人はほぼいないと思いますが、ハマっている人の参考になれば幸いです。