テスターちゃん【4コマ漫画】

ソフトウェアテストの用語、やり方などを4コマ漫画でわかりやすく説明する(予定の)ブログです。脱線も多いです。



【初心者向け】kubernetesを使ってselenium gridを動かしてみよう【mac】

【初心者向け】kubernetesを使ってselenium gridを動かしてみよう【mac】【k8s

 

こんにちは!作者です。

 

巷ではやれdockerだkubernetesだと騒がれていますが、聞いたことはあってもよくわからん状態でした。

dockerとはなんぞ…と調べていたのですが、調べるうちにkubernetesまで行きついて、selenium gridでテストの並列実行まで試してみました。

そんなわけで、今日は作者が行ったdockerからのkubernetes化を説明したいと思います。

難しい設定はしていないので(そこまで行きついていないので)最初の最初、kubernetes化して、同じテストを並列でひとまず動かしてみるところまでの説明をしようと思います。

 

dockerって何?kubernetesって何?

この辺の詳細は他サイトでおねがいできたらです。

2019年12月のアドベントカレンダーでテスターちゃんでこの辺をわかりやすく描けたらと思っています。

とりあえず簡単にいうと……

dockerは仮想的なサーバーをサクッと作るツール。

細かく言うと仮想的と言っても今までのvirtualboxなどと違い……なんてなってくるのですが、ひとまずはこれくらいで覚えておいて良いかと思いますw

サーバーを立てるときはこれまでとっても面倒だったのですが、dockerには設定のファイルなんかも最初からあって、誰でも同じような環境をお手軽に立ち上げることができるようになりました。

kubernetes(クバネティス/クバネテス/k8sケーエイツ)はdockerをイイカンジに取りまとめてくれるツール(説明雑!

例えば何かサービスとか作るときはwebサーバーやらDBやら色んなモノが必要で、それらが連携して一つのサービスができています。

dockerが出てからはその1つ1つをコンテナ(dockerでサクッと作った仮想的なサーバー)にするところが出てきました。

けどこのコンテナがいっぱいあると超大変!

それら設定やらコンテナの管理をやってくれるのがkubernetes

コンテナオーケストレーションツールと呼ばれています。

(ちなみにkubernetesが有名だけど、docker swarmというのもある。マイナー)

 

名前の通りオーケストラに例えるとわかりやすいかもしれません。

例えばバイオリン奏者、フルート奏者それぞれの単位がコンテナ。

それら全体をしっかりとイイカンジのハーモニーで音楽が成り立つように指揮するのがkubernetesといったところ(説明雑!

 

最初の準備

さて、やっていきましょう。

まずは……作者は最初にdockerのお試しから始めました。

その時、以下のsikkimtemi様のgithubを使用させていただきました。

github.com

こちらのリポジトリをベースにしますのでzipダウンロードやcloneをお願いします。

Dockerfileの説明

ダウンロードしてくると、「selenium」というフォルダができあがります。

その中の「python-selenium」というフォルダの中に「Dockerfile」というファイルがあります。

これは変更が必要ないのですが、説明をしておきます。

FROM python:3

RUN set -x && \
  apt-get update && \
  apt-get install -y vim && \
  pip install selenium

Docerfileは何かというと、これを使って「Docker image」を作ります。

Docker imageは「こういうサーバー作るよ」っていうレシピみたいなものです。

FROMの部分は、すでに配布されているpython3のイメージを持ってきて使うよ、と言う意味です。

その後のコマンドは、ファイルのアップデートやツールのインストールを行っています。

今回重要なのは「pip install selenium」部分くらい。

vim好きに怒られそうですねw)

なのでこのDockerfileの意味は「python3のイメージを持ってきて、seleniumインストールするよ」といったところです。

 

docker-compose.ymlの変更

このファイルがkubernetes化のときに非常に大事なファイル。

ガッツリと変更します。

version: "3.7"
 
services:
  selenium-hub:
    image: selenium/hub:latest
    ports:
      - 4444:4444
 
  chrome:
    image: selenium/node-chrome-debug:latest
    environment:
      - HUB_PORT_4444_TCP_ADDR=selenium-hub
      - HUB_PORT_4444_TCP_PORT=4444
    depends_on:
      - selenium-hub
    ports:
      - 5901:5900
    deploy:
      replicas: 4
 
  python:
    image: python-selenium:v1
    build:
      context: ./python-selenium
    depends_on:
      - selenium-hub
    working_dir: '/root/script/'
    volumes:
      - ./script/:/root/script/
    environment:
      - 'TZ=Asia/Tokyo'
    tty: true

docker composeは、複数のコンテナをまとめて操作を行うツールです。

ここでは「selenium-hub」「chrome」「python」という3つのコンテナを作るための情報が書かれています。

ざっくりいうと

pythonのサーバー(プログラムを実行する場所)→selenium-hubのサーバー(分配する場所)→chromeのサーバー(実際にブラウザが動いて実行される場所)

という構成が書かれています。

一つずつ説明します。

python

これがプログラムを実行するためのコンテナ(仮想的なサーバー)を作る情報部分です。

まずはimageとbuildの部分の説明。

先ほど見た通り、「python-selenium」のフォルダの中にDockerfileがありました。

それを使ってbuild(Dockerfileからイメージ作成)を行ってpython-selenium:v1というイメージ名で使うよ、と言う意味です。

depend-onは、上の方にある「selenium-hub」とつながってるよーということを書いています。

working_dirは、コンテナ上での作業フォルダです。

volumesがとっても大事な場所。

今見ているフォルダに「script」というフォルダがあるかと思います。

そこのフォルダがコンテナ上の「/root/script」と同期しています。

なので、そこにファイルを入れたらコンテナ上でそのファイルにアクセスできるし、コンテナ上で作ったファイルがscriptのフォルダに入るし……といった感じになります。

environmetでは、タイムゾーンを東京に設定しています。

ttyはコンテナの標準出力を表示させるようにする設定です。

selenium-hub

selenium-hubはプログラムを動かすサーバー(ここでは「python」のサーバー)から「こういうテストして」って要請があると「あいよ!」とその後に続くnode(複数のchromeのサーバー)にイイカンジに振り分けてくれる場所です。

imageは、もうすでに世の中にhubのimageがあるので、それを取ってくるということを書いています。

portsは「ホスト側(kubernetesを実行するパソコン)のポート:コンテナ側のポート」と紐づける役割をしています。

実行しているパソコンの4444のポートを、コンテナの4444のポートにつなげるよ、といった感じです。

chrome

ここは要は実際にブラウザを動かして実行する部分です。

ここを増やすと並列してテストが実行できたりします。

imageは、これまたすでに世の中にchromeのイメージがあるので持ってくることを書いています。

environmentは環境変数の設定です。

selenium-hubと接続が必要なので、接続するための環境変数を書いています。

depend_onもselenium-hubとつながっていることを書いています。 

portsも先ほどと同じです。実行するパソコンの5901のポートと、コンテナ側の5900ポートをつなげる、ということを書いています。

なんで5901?となるのですが、どうやらmacだと5900がもうvncで使われているらしく。

なのでひとつずらしましたw

次のdeploy:replicasは、chromeのコンテナを何個作るかです。

ここでは4つ作成します。イメージとしては4つサーバーができあがって、そこで並列してテストできるイメージです。

sample.pyの変更

「script」というファイルの中に「sample.py」というファイルが入っているかと思います。

これがテストを実行のサンプルのファイルです。

#!/usr/local/bin/python3
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from time import sleep
import datetime
import threading
import random

NODE_NUM = 4

def execSearch(browser: webdriver):
    """
    Googleで検索を実行する
    :param browser: webdriver
    """
    # スクリーンショットのファイル名用に日付を取得
    dt = datetime.datetime.today()
    dtstr = dt.strftime("%Y%m%d%H%M%S")

    # Googleにアクセス
    browser.get('https://www.google.co.jp/')
    sleep(1)

   # キーワードの入力
    search_box = browser.find_element_by_name("q")
    search_box.send_keys('docker selenium')

    # 検索実行
    search_box.submit()
    sleep(1)

    # スクリーンショット
    browser.save_screenshot('images/' + dtstr + '_' + str(random.randrange(10000)) + '.png')

def start_webdriver():
    try:
        browser = webdriver.Remote(
            command_executor='http://selenium-hub:4444/wd/hub',
            desired_capabilities=DesiredCapabilities.CHROME)
        # Googleで検索実行
        execSearch(browser)
    finally:
        browser.close()
        browser.quit()

if __name__ == '__main__':
    for i in range(NODE_NUM):
        thread = threading.Thread(target=start_webdriver)
        thread.start()

並列実行用にファイルを変更しました。

……雑な変更でして、同じテストを4並列で実行する感じになっています。

今回は簡単なkubernetesの動作チェックみたいなものなので、ちゃんとした並列分散のようなテストは別のサイトを見ていただけたらです。

実行が終わると「image」フォルダの中に4つのスクリーンキャプチャが入ります。

ついでに自作ファイルも追加しておきましょう。

sampleが動いても自分のファイルはどう動かすの!?ってなったりしますので、一つ「test.py」の名前でファイルを作ってみましょうか。

#!/usr/local/bin/python3
print('Hello Testerchan!')

画面に「Hello Testerchan!」と表示させるだけのプログラムです。

ちなみに1行目はshebang。(#!から始まる行をそういうよ)

これがないと動かないので要注意です。

これでkubernetes化する準備は完了です!

kubernetesをインストールしよう。

ここではmacの説明をしていきます。

macにすでにdocker for macが入っている前提です。(インストールはダウンロードして実行すればいいだけ)

そうしたら、dockerの「prefereces...」→「kubernetes」とクリックしてください。

f:id:m_training:20191113232054p:plain

これの「Enable Kubernetes」にチェックしてApplyを押すだけでインストールが始まります。

インストールは長いので、紅茶でも飲みながら気長に待ちましょう。

Dockerfileをbuildしよう

ここは初回だけでOKの場所です。

docker-compose.ymlをいじるときに「python」のところで「buildしてimageつくるよ」って場所があったと思います。

そのimageを作るための作業です。

まずはターミナルを立ち上げて、seleniumフォルダがあるところまで移動しましょう。

そしたら…

$ docker-compose build

これでオッケーです。

f:id:m_training:20191113232637p:plain

ビャーっと文字が流れていきます。

f:id:m_training:20191113232711p:plain

最後にSuccessfullyがでたらimageが完成です。

kubernetes起動!

では、ようやくkubernetesを起動です。

ここでは「compose on kubernetes」という、docker-compose.ymlからkubernetesにdeployしてくれる、というものです。

$ docker stack deploy --orchestrator=kubernetes -c docker-compose.yml 任意のstackの名前

任意のstackの名前は、まぁ、特に気にせず好きな名前を付ければいいです。

以下では「kube」とつけてdeployをしました。

f:id:m_training:20191113233216p:plain

「Stack 名前 is stable and running」と出れば起動完了です。

簡単!

selenium gridの様子を見てみよう。

起動確認として、ブラウザを立ち上げてアドレスに「localhost:4444/grid/console」と打ち込みましょう。

そうすると以下のような画面が見られるかと思います。

f:id:m_training:20191113233724p:plain

chromeのサーバーが4つ立ち上がっていますね!

test.pyを実行してみよう

プログラムの実行をしていきます。

その前に以下を入力してください。

$ kubectl get pods

これはkubernetes上で動いているpodを確認するものです。

podは、コンテナの集合体みたいなものなのですが説明割愛。(自動車みたいな感じ。コンテナが複数載った乗り物みたいなもの。今の場合は1pod1コンテナ。)

f:id:m_training:20191113234525p:plain

ここのpythonのとこの名前をコピりましょう。

そうしたら……

$ kubectl exec -it コピった名前 python /root/script/test.py

と入力してエンターです。

Hello Testerchan!

と出れば成功です。 f:id:m_training:20191114003014p:plain

execは実行コマンドです。

引数の-itは標準入力とttyの設定です。docker-compose側でttyは設定しているので、特に不要ではあります。

最後の/root/scriptは、「script」フォルダがコンテナ側の「/root/script」と同期しています。

そこのtest.pyを実行となります。

selenium gridで並列テスト実行!

ではでは、テスト実行をしてみましょう!!

$ kubectl exec -it コピった名前 python /root/script/sample.py

これでテストが実行されます!

実行したらちょっとselenium gridを見てみましょう。

f:id:m_training:20191113235258p:plain

chromeのマークが薄くなっていたら、そこで実際にブラウザが立ち上がってテスト実行がされています。

ちなみに自動で画面に反映されないのでリロード連打をしましょう(爆)

上の画像だと4か所に振り分けられてテスト実行されていることがわかります。

最後に「image」フォルダに4枚の画像が保存されたら完了です。(テスト内でスクリーンキャプチャしてる)

f:id:m_training:20191114000251p:plain

動いている様子も見たいよね

実際にブラウザが動いている様子、自動化やってると見たくなっちゃいますよね!w

では見てみましょう。

スポットライト(commandとspace同時おし)を開いて「画面共有」と打ち込んでください。

青い画面のアイコンがあるのでそれを実行です。

そしたら接続先に「localhost:5901」と入力しましょう。

docker-composeのchromeportsで打ち込んだ数字です。

f:id:m_training:20191113235736p:plain

パスワードを聞かれるので「secret」と入力してください。

そうすると何やら黒い画面が立ち上がるかと思います。

その状態で実行してみましょう。

$ kubectl exec -it コピった名前 python /root/script/sample.py

f:id:m_training:20191114000049p:plain こんな感じで確認ができます。

終了

終了するには以下のコマンドを入力しましょう。

$ docker stack rm --orchestrator=kubernetes deployのときにつけた名前

f:id:m_training:20191114000236p:plain

これで完了です。

その他のコマンド

簡単にだけ紹介。

$ docker stack ls --orchestrator=kubernetes

起動中のstackのリストが見れます。

f:id:m_training:20191114000525p:plain

$ docker stack ps --orchestrator=kubernetes deployのときにつけた名前

stackで動いているものが見れます。

f:id:m_training:20191114000744p:plain

$ docker stack services --orchestrator=kubernetes deployのときにつけた名前

stackで動いているサービスを見ることができます。

f:id:m_training:20191114000859p:plain

実はgithubも用意しておいた

実はgithubも用意しているので、以下参考いただけたらですw

github.com

docker-composeとkubernetesの違い

やっていて思ったのが、docker composeでもまとめてコンテナ扱えるし、kubernetesとどう違うんだろうでした。 以下のスライドがわかりやすかったです。

speakerdeck.com