web-technical-blog

web開発に関する技術メモ

SREについて

SREをはじめるには

近年、何かと話題に上がるSRE(Site Reliability Engineering)

しかし「自分たちのチーム・組織に関係する話なのかよく分からない」「具体的に何をやればいいのか?」といった感想を持つ方が多い

参考文献

はじめに

  • SREって何?
  • これまでのシステム運用やDevOpsとは何が違うの?
  • SREに取り組む前に考えるべきこと

SRE

  • SREは、Googleが提唱したエンジニアの役割。
  • また、Site Reliability Engineeringという名称の通り、システムの信頼性に焦点を置いている

Google社 VP of EngineeringのBen Treynor氏によるSREの説明を、書籍「Google - Site Reliability Engineering」より引用

 My explanation is simple: SRE is what happens when you ask a software engineer to design an operations team.(筆者訳:私の説明は簡潔です。SREは、ソフトウェアエンジニアに運用チームの設計を依頼した時にできあがるものです。) - 引用:Google - Site Reliability Engineering

enter image description here

ソフトウェアエンジニアがシステム運用を設計することで、これまでのシステム運用と具体的にどのような違いが生まれるかについて考えてみる

システム運用とは何か

  • ソフトウェアが稼働するサーバーの準備が必要
  • ネットワークの設定・構築も必要
  • サーバー内でソフトウェアが稼働する状態を設定しなければならない
  • ソフトウェアに変更があれば修正を反映する作業も行う
  • 障害が発生した場合には、サーバー、ネットワーク、ミドルウェアやのどこに原因があるかを突き止め、解消しなければならない

ソフトウェア開発の一連の流れは、 ソフトウェアを開発する役割(Dev)と ソフトウェアの価値をユーザーに届け続ける役割(Ops)が存在している 後者の役割を担うのが、システム運用

従来のシステム運用のデメリット

直接的なコスト

  • システム運用を手作業で行っていた場合、システムが大きくなればなるほど、比例して作業量が増加する
  • ユーザー増えれば、それに伴い管理するサーバーは増える、開発に関わるソフトウェアエンジニアが増えれば、変更頻度が増えることにより障害発生頻度も増加する。それにより、システム管理者をたくさん雇用しなければならない

間接的なコスト

  • 従来のシステム運用では、DevとOpsが、時に対立的にならざるを得ない場面がある
  • 開発をした修正を次々にリリースしたいDevに対して、安定してシステム運用するために変更頻度を減らしたいOpsとでは、修正変更を行うことに対するスタンスが真逆
  • 時に利害関係解消のための、コミュニケーションコストが発生することがある。これをSRE本では、間接的なコストと呼んでいる

SREと従来のシステム運用との違い

SREは従来のシステム運用が抱えるこれらのデメリットを解消するための方法論を持っている

  • システム運用に伴う作業の多くをエンジニアリングによって効率化・自動化を行う
  • エンジニアリングによって効率化・自動化された作業には、人手による作業を削除・もしくは撲滅することができる
  • システムが大きくなることに伴う直接的なコスト(人件費)の増加速度を低減させることができる
  • SREでは、エラーバジェット(エラー予算)の考え方を採用することで、前述した対立構造を解消できる
    • エラーバジェットは文字通り、エラーの発生を予算のように扱う考え方
    • エラーが発生すると予算が減り、予算が無くなりそうになると、Devは新しい変更をリリースせずに、既存のエラーに優先対応する
    • こうすることで、DevとOpsもエラーバジェットという共通目標に向き合うことで、協力的な関係が生まれる

SREは、従来のシステム運用に置ける問題を解消するための、延長線上にある考え方だと分かる

「SREは、ソフトウェアエンジニアに運用チームの設計を依頼した時ににできあがるもの」という意味を少しでも感じ取れる

SREとDevOpsの違いに対するGoogleの解説

What's the Difference Between DevOps and SRE?

この動画の中で、「class SRE implements DevOps」というメッセージが登場する。つまり、SREがDevOpsを実装しているという考え方で、動画内では、「DevOpsを哲学とするならば、SREはその哲学を達成するための規範的な方法です」とも解説されている

enter image description here

動画の後半では、「しかし、プログラミングのクラスがそうであるのと同様、class SREには、追加の機能やメソッドがあるかもしれない」と補足されている。 要するに、SREは、DevOpsを推進するための実装を行うが、それだけではなく、上記で述べてきたような従来のシステム管理の役割も担うということ

SREに取り組む前に考えるべきこと

SREを取り入れるメリットについての期待値コントロールを行う

  • SREを取り入れるメリットを改めて整理すること
    • 例えば、みなさんの会社が、システムの運用に関わる人月計算でビジネスが動いているとした場合
      • 「SREを取り入れて、運用工数を削減しましょう」と提案しても、「そんなことをしたらうちのビジネスが縮小するだけでは?」と、SREに否定的な態度を取られてしまう可能性だってある
    • ソフトウェアエンジニアが運用を設計することのメリットは、必ずしも効率化や自動化だけではない
    • メリット・デメリットの整理は自身の組織やチームを見渡しながら考えてみる
      • 「今、組織でこういう問題が起きているけど、SREの考え方を取り入れれば解消するのでは?」
      • 「うちの場合は、SREを取り入れるメリットが適切に発揮できそうだ」などきっと色んなアイデアが思い浮かぶはず

SREを取り入れる際に組織規模は関係はない。 ソフトウェアエンジニアの考え方を似てシステム運用を設計する原理原則に従うことに、組織やチーム規模は関係ないから。

Google SREとの差分を意識しよう

  • SRE本、各章それぞれがエッセイで構成されている
  • SREの原理原則に従いGoogle社内で実践されてきたプラクティスだが、厳密で学術的なものではない
  • Googleのプラクティスはもちろん大いに参考にすべきだが、必ずしもGoogle SREと同じ実践する必要はない
  • Gooogle SREと自分たちとの差分を意識するとよい

SRE本の出版は、世の中の他の企業からもたくさんSREに関するプラクティスを生み出して欲しいというGoogleの想いが込められている

さいごに

Googleと言えば、エンジニアリングばかり注目されがだが、SREに関して理解を深めると、組織運営のプラクティスも非常に先進的な企業であることが分かる

  • Googleのカンファレンスにて
    • Google社員の方が、Googleボトルネックを発見し、それを解消するために0から考えることを厭わない(いとわない)企業である」
    • 「また、そのためのボトルネック発見が非常にうまい企業だと中から見ていて感じる」と発言していらっしゃるのを聞いたことがある

世の中のすべての企業が、SREという役割や名称を引き継ぐかどうかは分からないが、多かれ少なかれ、SREの考え方に影響を受ける企業は増えていくと感じる


SREをはじめるには、まずどうすればいいですか? SREに必要なスキルと取り組み方

はじめに

  • SREに必要なスキルセット
  • SREに取り組むために
  • サービス信頼性階層

SREに必要なスキルセット

「SREは、ソフトウェアエンジニアに運用チームの設計を依頼した時にできあがるもの」というBen Treynor氏(Google VP of Engineering:SREの考案者)の言葉を紹介した

書籍『Site Reliability Engineering』のChapter 1の中で、「SREがすべきこと」(Tenets of SRE)について紹介されている。

In general, an SRE team is responsible for the availability, latency, performance, efficiency, change management, monitoring, emergency response, and capacity planning of their service(s).

筆者訳

 一般的に、SREチームは、「サービスの可用性」「レイテンシ」「パフォーマンス」「効率性」「変更管理」「モニタリング」「緊急対応」「キャパシティプランニング」に責任を持ちます。 - 引用:Chapter 1 - introductionGoogle - Site Reliability Engineering)

SREの責務から考える

「サービスの可用性」を保つには

  • 冗長構成を設計および実装できる必要がある
  • パブリッククラウドを利用している場合は、利用するサービス自体の可用性を考慮するためには仕様の深い理解が求められるケースもある

「パフォーマンス」を向上させるには、どのようなスキルが必要か

  • データ構造やアルゴリズムをふまえ、非効率なプログラムの改修を行えば、パフォーマンスは改善できそう
  • パフォーマンスの向上のため、キャッシュ層をどう活用するかを考える必要もある

「変更管理」について

  • 変更管理は、システムに対する変更内容を管理すること
  • 例えば、ミドルウェアのconfigファイルの変更を行った際には、変更内容をどこかに記録する
    • 変更内容をExcelシートに1行ずつ記録しても構わないが、「SREは、ソフトウェアエンジニアに運用チームの設計を依頼した時にできあがるもの」なので、できればプログラマブルに管理したい。そこで、DevOpsの文脈でよく語られるIaC(Infrastructure as Code)を実践することが重要となる
  • SREはシステム運用とサービス開発の思想・スキル双方が必要
  • また、責務を満たすために扱うツール群も多く、かつ、それらを協調させることが求められる

SREが使うツール

SREツール

AWSのサービスをメインで紹介

Infrastructure as Code

  • インフラリソース作成
    • Terraform
    • AWS CloudFormation
  • プロビジョニング
    • Ansible
    • Chef
  • インフラテスト
    • Serverspec
  • マシンイメージ作成
    • Packer

Monitoring

  • NewRelic
  • DataDog
  • AWS CloudWatch
  • GCP Stackdriver
  • Mackerel
  • Promethus
  • Zabbix
  • Elasticsarch/Kibana

Log

  • fluentd
  • Beats/Logstash

ChatOps

  • Slackなどのチャットツールから、コマンドなどを入力することで何かしらの作業を行う
    • Hubot

CI/CD

  • Cicle CI
  • Travis CI
  • Spinnaker
  • Jenkins
  • AWS Codeシリーズ

Development Environment

Infrastructure Automation

  • イベント駆動アーキテクチャで、インフラ操作自動化することを意図して記載 「〇〇が起きたら、XXXが起動し、△△する」のXXX部分
    • AWS Lambda
    • StackStorm

Security

  • IDS
    • OSSEC
  • IPS
  • IDS/IPS
    • Deep Security
  • WAF
  • Audit
    • AWS CloudTrail

Data

  • DWH
    • Redshift
    • BigQuery
  • Storage + Query
    • AWS S3 + Athena
  • 前処理
    • AWS Kinesis Family
      • GCPの類似ツールは設計思想に癖があるので、サブセットではないとご理解ください
  • BI
    • Redash
    • Metabase
    • DOMO
    • AWS QuickSight

Incident Management

  • インシデント管理
    • PagerDuty
  • ステータス管理
    • Statuspage

Performance Test

プログラマブルに運用を行う

  • SREとして仕事をしていくにあたり、一番はじめに変えるべきことは、プログラマブルに運用をしていく意思統一
  • SREは「ソフトウェアエンジニアに運用チームの設計をした時にできあがるもの」なので、プログラマブルに問題解決を行うことが本質的な部分だから
  • 前述した「変更管理」にInfrastructure as Codeの考え方を適用するのはわかりやすい例
  • 他にも、コーディングすることで、特定の運用業務こ効率化・自動化していくこともプログラマブルに運用を行うことの分かりやすい例
  • プログラマブルに運用を行うべき範囲は各社異なっていると思うので、まずは現状を俯瞰してみる

運用業務の土台を整える

  • コードを書いて運用業務を効率化・自動化していくには、時間が必要
  • 運用業務の現状がボロボロになっている状態であれば、SREを実践していくにあたり、まずは土台整備から行うべき
  • 運用業務の土台が整備できない状態とは
    • サービス稼働に必要不可欠な運用業務が1人しか実施できない状態かつ、その業務のドキュメントが整備されていない
    • サービス稼働に問題が起こったことを検知できず、かつ問題の原因究明が行われない(また原因究明を行う時間がない、もしくは原因究明を行う技術力が自社で不足している)
    • 上記のような状態にも関わらず、サービス運用の改善に対する問題意識が薄い

バス因子に対処する

  • まず第一にやらなければならないことは、バス因子に対処すること
  • バス因子とは、書籍『エラスティックリーダーシップ』に登場する表現で、バスに轢かれてしまい、いなくなってしまったらプロジェクトに大きな影響を与えてしまう人物のこと
  • つまり、プロジェクトにとって必要不可欠な人のこと

バス因子に対処するとはどういう意味でしょうか。簡潔に書くと「その人に依存しなければならない状況を可能な限り減らすこと」です。

PDCAではなくOODA

サービス稼働に問題があった際に検知できる環境を整備する必要がある。これは端的に書くと、モニタリングを整備すること。モニタリング結果から分かったことを元に、実際に改善を行っていくことで、サービスの信頼性を向上させる

SREは、PDCAではなくOODAを回すことが重要

OODAは、アメリカ空軍のジョン・ボイド大佐によって提唱された理論で、指揮官のあるべき意思決定プロセスを分かりやすく理論化したもの

OODAとは

  • 観察・監視(Observe)
  • 情勢への適応(Orient)
  • 意思決定(Decide)
  • 行動(Act)

運用業務に関わっている読者の方は、身をもって体感されていると思うが、サービス運用業務では、不確実性が高い状況に度々直面する。そのため、どこからどうやって手をつけていくかをPlanするよりも、まずObserveするべき

OODAループ OODAループ

サービス信頼性階層

信頼性という抽象的な概念を、どのような要素として理解すればよいかについて補足

以下は、書籍『Site Reliablity Engineering』に登場する「Service Reliablity Hierarchy(サービス信頼性階層)」の図です

enter image description here

  • モニタリングが重要である点は前述下が、その次に整備すべきは、Incident Response(インシデント対応)
  • ここで言う「インシデント」とは、セキュリティインシデントに限定した話ではなく、障害対応全般だと理解ください
  • ここで言うIncident Responseは、単に問題に対応すればよいと言うものではなく、「インシデント管理プロセスが、チームで共通化された効率的な対応フローになっているかどうか」という観点が重要
  • 例えば、問題が発生した際に、まずどういう行動をとるべきかは、チームで共有されているでしょうか。トリアージ[1]は誰でも同じ基準で行うことができるでしょうか。こういった観点を突き詰めていくと、一言でIncident Responseといっても、実にさまざまな論点が含まれていることが分かります。

[1] トリアージ:事象の緊急度に従って優先順をつけ、可能な範囲で問題の影響を緩和すること。詳しくは以下を参照。 - クラウド時代のトラブルシューティング : 解決に役立つプロバイダーとのコミュニケーション(後編)Google Cloud Platform Japan Blog)

参考URL

# SREをはじめるには、まずどうすればいいですか? SREに必要なスキルと取り組み方

pythonでのフォーマットや型変換について

pythonのフォーマット関数について

  • dict型であれば、以下のようにしてフォーマットできる
  • 変数「dict」をfor分などで使いまわす場合は、del関数で削除しないとデータがおかしくなるので注意
# ディクショナリ
dict = {"name": "John", "age": 20}
# アンパックしてキーワード引数に
"My name is {name}. I'm {age} years old.".format(**dict)

*:複数の引数をタプルとして受け取る
**:複数のキーワード引数を辞書として受け取る

参考URL


文字列を辞書型に変換する

Redshiftからデータ取得した際は、JSON文字列は文字型(str)になっているので、 上記フォーマットを使いたい為、ディクショナリ型に変換が必要だった

import ast

sql = "select * from log.kpi_log WHERE created_at >= %s"
cursor = conn.cursor()
cursor.itersize = 10000
cursor.execute(sql, (digdag.env.params['target_date'],))

for row in cursor:
  # 文字列型からディクショナリ型へ変換する
  json_data = ast.literal_eval(row[3])

参考URL

VSCでJupyterが使用できるということで試してみた

動作環境

  • windows10

設定したこと

python -m pip install jupyter
python -m pip install matplotlib
#%%
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np

x = np.linspace(0, 20, 100)
plt.plot(x, np.sin(x))
plt.show() 

結果

f:id:yoshitachi:20181112142144p:plain

参考URL

https://news.mynavi.jp/article/20181109-721502/

(Python)並行処理と並列処理について

並行・並列

  • 並行は英語でConcurrent、並列はParallelと表現される
  • 並行と並列は別ものである by RobPike

並行(Concurrent)

  • 複数のスレッドを使って処理を走らせる
  • スレッドは共有のメモリ領域を利用する
  • 同時にいつくかの質の異なることを扱う

並列(Parallel or Parallelism)

  • 複数のプロセスを使った処理
  • プロセスは専用のメモリ領域を利用する
  • 同時にいくつかの質の同じことを扱う

f:id:yoshitachi:20181112114605p:plain

プロセス作成とスレッド作成

f:id:yoshitachi:20181112114222p:plain

複数のスレッドを使った処理をする場合、同一のプロセス内でスレッドが切り替わりながら処理が進む。

Apacheの設定にあるpreforkとworkerは、プロセス、スレッドのどちらかで動かすかの違い

複数のプロセスを使って処理をする場合

  • コアが1つだけのCPUであれば、やはりプロセスを切り替えながら処理が進むが
  • コアが複数であったり、CPU自体が複数ある場合は、1つのコアに1つのプロセスが処理できるため、同時的に処理が進む

ライス、みそ汁、焼き魚の定食を作るとすると

  • 1人の人間が進める場合

    • 湯を沸かしている間に炊飯器をセットし、魚をやくためのグリルを温める...というように
    • 作業を切り替えながら同時進行させていくのが並行処理に相当する
  • 3人の人間が進める場合

    • それぞれの品を担当して同時進行させていくのが並列処理に相当する

1人の人間が作業を切り替えながら料理を進行していくのは3人で進める場合に比べて忙しそうだがすべて自分好みの味にできる。 これは処理対象の情報を自分の中で共有できているから。

pythonではmultithread,multiprocess,asyncioを使ったプログラミングでは細やかな多重処理の制御が行えるが、 そもそも並列処理プログラミング自体がなかなか複雑になりやすい面もある

Pythonで比較的扱いやすいライブラリであるconcurrent.Futureを使ってみる

concurrent.Futureライブラリについて

Futureとは他の言語やライブラリではpromise,delayなどとも呼ばれ、 ある処理の結果が後で取得されることを前提に処理の実装が行えるようにするもの

並列処理をマルチスレッドで行いたい場合

  • ThreadPoolExecutorメソッドを使用する
    • スレッドを使って並列タスクを実行する
    • ネットワークアクセスなどCPUに負荷がかからない処理の並列実行に適している

マルチプロセスで行いたい場合

  • ProcessPoolExcutorメソッドを使用する
    • プロセスを使って並列タスクを実行する
    • CPUに負荷がかかる計算処理などの並列実行に適している

必要なライブラリ

pip install futures
pip install requests
"""
音楽ファイルの並列ダウンロード
"""
import concurrent.futures
from os import path
from urllib import parse
import requests
import mylogger
import shutil

# ログ設定
logger = mylogger.get_my_logger(__name__)

MUSIC_URLS = ['https://archive.org/download/ThePianoMusicOfMauriceRavel/01PavanePourUneInfanteDfuntePourPianoMr19.mp3',
              'https://archive.org/download/ThePianoMusicOfMauriceRavel/02JeuxDeauPourPianoMr30.mp3',
              'https://archive.org/download/ThePianoMusicOfMauriceRavel/03SonatinePourPianoMr40-Modr.mp3',
              'https://archive.org/download/ThePianoMusicOfMauriceRavel/04MouvementDeMenuet.mp3',
              'https://archive.org/download/ThePianoMusicOfMauriceRavel/05Anim.mp3']

def download(url, timeout=180):
    # mp3のファイル名をURLから取り出す
    parse_url = parse.urlparse(url)
    file_name = path.basename(parse_url.path)

    # ダウンロード開始をログ出力
    logger.info("[download start] {file_name}".format(file_name=file_name))

    # 音楽ファイルのダウンロード
    r = requests.get(url,timeout=timeout)

    # ダウンロードの終了ログをログ出力する
    logger.info("[download finished] {file_name}".format(file_name=file_name))

    with open(file_name, "wb") as file:
        shutil.copyfileobj(r.raw, file)

    return

if __name__ == '__main__':
    # 同時に2つの処理を並行実行するためのexecutorを作成
    with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
    ##with concurrent.futures.ProcessPoolExecutor(max_workers=2) as executor:
        logger.info("[main start]")

        # executor.submit()によりdownload関数を並行実行する。download関数の引数にmusic_urlを与えている
        # 並行実行処理のまとまりを futures 変数に入れておく
        futures = [executor.submit(download, music_url) for music_url in MUSIC_URLS]

        # download()関数の処理が完了したものから future 変数に格納する
        for future in concurrent.futures.as_completed(futures):
            # download関数の実行結果を resultメソッドで取り出す
            music = future.result()

        logger.info("[main finished]")
"""
loggerは別パッケージ
"""
import logging
from logging import getLogger, StreamHandler, Formatter

def get_my_logger(name):
    # loggerオブジェクトの宣言
    logger = getLogger(name)

    # loggerのログレベル設定(ハンドラに渡すエラーメッセージのレベル)
    logger.setLevel(logging.DEBUG)

    # handlerの生成
    stream_handler = StreamHandler()

    # handlerのログレベル設定(ハンドラが出力するエラーメッセージのレベル)
    stream_handler.setLevel(logging.DEBUG)

    # ログ出力フォーマット設定
    handler_format = Formatter('[%(levelname)s]\t%(asctime)s\tprocess:%(process)d\tthread:%(thread)d\tmodule:%(module)s\t%(pathname)s:%(lineno)d\t%(message)s')
    stream_handler.setFormatter(handler_format)

    # loggerにhandlerをセット
    logger.addHandler(stream_handler)

    return logger
  • 出力結果(ThreadPoolExecutor)
[INFO]  2018-11-12 11:07:23,600 process:17648   thread:14680    module:multi2   multi2.py:50    [main start]
[DEBUG] 2018-11-12 11:07:23,601 process:17648   thread:16028    module:multi2   multi2.py:33    [download start] sleep: 2.0 01PavanePourUneInfanteDfuntePourPianoMr19.mp3
[DEBUG] 2018-11-12 11:07:23,601 process:17648   thread:15308    module:multi2   multi2.py:33    [download start] sleep: 3.5 02JeuxDeauPourPianoMr30.mp3
[INFO]  2018-11-12 11:07:53,104 process:17648   thread:16028    module:multi2   multi2.py:39    [download finished] 01PavanePourUneInfanteDfuntePourPianoMr19.mp3
[DEBUG] 2018-11-12 11:07:53,105 process:17648   thread:16028    module:multi2   multi2.py:33    [download start] sleep: 1.5 03SonatinePourPianoMr40-Modr.mp3
[INFO]  2018-11-12 11:07:54,921 process:17648   thread:15308    module:multi2   multi2.py:39    [download finished] 02JeuxDeauPourPianoMr30.mp3
[DEBUG] 2018-11-12 11:07:54,923 process:17648   thread:15308    module:multi2   multi2.py:33    [download start] sleep: 2.0 04MouvementDeMenuet.mp3
[INFO]  2018-11-12 11:08:05,049 process:17648   thread:16028    module:multi2   multi2.py:39    [download finished] 03SonatinePourPianoMr40-Modr.mp3
[DEBUG] 2018-11-12 11:08:05,050 process:17648   thread:16028    module:multi2   multi2.py:33    [download start] sleep: 2.0 05Anim.mp3
[INFO]  2018-11-12 11:08:13,564 process:17648   thread:15308    module:multi2   multi2.py:39    [download finished] 04MouvementDeMenuet.mp3
[INFO]  2018-11-12 11:08:17,042 process:17648   thread:16028    module:multi2   multi2.py:39    [download finished] 05Anim.mp3
[INFO]  2018-11-12 11:08:17,043 process:17648   thread:14680    module:multi2   multi2.py:61    [main finished]

ログの時刻に注目すると、最初に2つのファイルのダウンロードが開始され、 そのうち1つ終了すると、次のファイルのダウンロードが開始される

  • 出力結果(ProcessPoolExecutor)
[INFO]  2018-11-12 11:09:59,411 process:14408   thread:13500    module:multi2   multi2.py:50    [main start]
[DEBUG] 2018-11-12 11:09:59,553 process:16508   thread:948      module:multi2   multi2.py:33 [download start] sleep: 3.5 01PavanePourUneInfanteDfuntePourPianoMr19.mp3
[DEBUG] 2018-11-12 11:09:59,553 process:16928   thread:1588     module:multi2   multi2.py:33 [download start] sleep: 2.5 02JeuxDeauPourPianoMr30.mp3
[INFO]  2018-11-12 11:10:23,491 process:16508   thread:948      module:multi2   multi2.py:39 [download finished] 01PavanePourUneInfanteDfuntePourPianoMr19.mp3
[DEBUG] 2018-11-12 11:10:23,493 process:16508   thread:948      module:multi2   multi2.py:33 [download start] sleep: 2.5 03SonatinePourPianoMr40-Modr.mp3
[INFO]  2018-11-12 11:10:34,172 process:16928   thread:1588     module:multi2   multi2.py:39 [download finished] 02JeuxDeauPourPianoMr30.mp3
[DEBUG] 2018-11-12 11:10:34,173 process:16928   thread:1588     module:multi2   multi2.py:33 [download start] sleep: 2.0 04MouvementDeMenuet.mp3
[INFO]  2018-11-12 11:10:37,539 process:16508   thread:948      module:multi2   multi2.py:39 [download finished] 03SonatinePourPianoMr40-Modr.mp3
[DEBUG] 2018-11-12 11:10:37,541 process:16508   thread:948      module:multi2   multi2.py:33 [download start] sleep: 2.5 05Anim.mp3
[INFO]  2018-11-12 11:10:46,934 process:16508   thread:948      module:multi2   multi2.py:39 [download finished] 05Anim.mp3
[INFO]  2018-11-12 11:10:47,823 process:16928   thread:1588     module:multi2   multi2.py:39 [download finished] 04MouvementDeMenuet.mp3
[INFO]  2018-11-12 11:10:47,824 process:14408   thread:13500    module:multi2   multi2.py:61    [main finished]
  • ProcessPoolExecutorはプロセス間によって実現しているため、いつくか制限がある
    • 関数の引数および戻り値は、pickleを使ってシリアライズ可能なオブジェクトでなければいけない
    • 関数自体もプロセス間で渡さなければならない。インスタンスメソッドもNG。ラムダ式はOK
    • 関数の中で副作用としてグローバル変数を書き換えるなどしても、呼び元のプロセスには反映されない
補足
  • pickleモジュールはPythonのオブジェクトを直列化・非直列化するための機能を提供している 直列化(Serialize)というのはプログラミング言語においてオブジェクトをバイト配列などの表現に変換すること
参考URL

VagrantのGuest GuestAdditionsについて

共有フォルダを作成したいときに、 「Guest Additions Version」と「VirtualBox Version」が違うとエラーが発生する

環境

>vagrant plugin install vagrant-vbguest
Installing the 'vagrant-vbguest' plugin. This can take a few minutes...
Installed the plugin 'vagrant-vbguest (0.16.0)'!
  • VagrantFile
#
# Note: set environment vars "HOSTNAME" and "IP", or replace the below
#

Vagrant.configure("2") do |config|
  config.vm.box = "bento/centos-7.3"
  config.vm.hostname = "redash"
  config.ssh.insert_key = false
  config.vm.network "private_network", ip: "192.168.56.203"
  config.vbguest.auto_update = false
  config.vbguest.no_remote = true
  config.vm.provider "virtualbox" do |vb|
    vb.name = config.vm.hostname
    vb.memory = "2048"
    vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
    vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
    vb.customize ["setextradata", :id, "VBoxInternal/Devices/VMMDev/0/Config/GetHostTimeDisabled", 0]
    vb.customize ["modifyvm", :id, "--cableconnected1", "on"]
  end
  config.vm.provision "shell", inline: <<-SHELL
    sudo systemctl restart network.service
    sudo yum -y update
    sudo yum install -y zsh vim tree telnet dstat git tig
    sudo gpasswd -a vagrant vboxsf
  SHELL
end

Guest Additionsのアップデートと再起動

>vagrant vbguest
>vagrant reload
>vagrant vbguest --status
Got different reports about installed GuestAdditions version:
Virtualbox on your host claims:   5.1.26
VBoxService inside the vm claims: 5.2.12
Going on, assuming VBoxService is correct...
[default] GuestAdditions 5.2.12 running --- OK.
>vagrant halt

virtualbox側で、共有フォルダの設定を正しくする(不要かもしれないが...)

  • [設定] -> [共有フォルダ] -> 自動マウントの設定

  • vagrantの起動

>vagrant up

上記で起動しないと、共有フォルダは設定されない

参考URL

https://qiita.com/isaoshimizu/items/e217008b8f6e79eccc85

vagrantのshared folderのmountに失敗してしまった場合

VirtualBoxディレクトリ共有を行うために使っているVirtualboxGuestAdditionというツールのバージョンが, ホストとゲストでずれているとこのような問題がおこるらしい

$ vagrant plugin install vagrant-vbguest
$ vagrant vbguest

https://qiita.com/ak-ymst/items/bdc37aaf53f857d37fcc

vagrant reloadコマンドから起動しないと、 共有フォルダは設定されない

rootかvboxsfグループのユーザーしかアクセスできないため、 既存ユーザーをvboxsfグループに追加しておく。有効にするため一度再起動したら、 共有できるようになっているはず。 単に共有さえできればいいならここまでで設定は終わり。

# gpasswd -a vagrant vboxsf
# reboot

共有フォルダの設定

https://qiita.com/centipede/items/5b3cb4965618993cefec