/home/tnishinaga/TechMEMO

日々行ったこと、面白かったことを書き留めます。

vagrant-azureとansibleを使ってRaspberry PiのLinux Kernelをビルドしてみた話

vagrant-azureを使ってAzureの上にVMを建てることを前回行いました。

vagrant-azureを使ってAzureに仮想マシンを建ててみたメモ - /home/tnishinaga/TechMEMO

今回はこれに加えてansibleを使ってRaspberry PiLinux Kernelをビルドすることを行ってみたいと思います。

スクリプトの修正とLinux Kernelのビルド

ansibleを使ったプロビジョンの追加

前回書いたVagrantfileのVagrant.configureのところに以下を追記します。

# ansible provision
config.vm.provision 'ansible' do |ansible|
  ansible.playbook = "provisioning/playbook.yml"
end

これでprovisioning/playbook.ymlの記述に従って、Ansibleを使ったプロビジョンを行えるようになります。

追記した後のVagrantfileはこんな感じになります。

require 'dotenv'
Dotenv.load

Vagrant.configure('2') do |config|
  # ansible provision
  config.vm.provision 'ansible' do |ansible|
    ansible.playbook = "provisioning/playbook.yml"
  end

  config.vm.box = 'azure'

  # use local ssh key to connect to remote vagrant box
  config.ssh.private_key_path = '~/.ssh/id_rsa'
  config.vm.provider :azure do |azure, override|

    # each of the below values will default to use the env vars named as below if not specified explicitly
    azure.tenant_id = ENV['AZURE_TENANT_ID']
    azure.client_id = ENV['AZURE_CLIENT_ID']
    azure.client_secret = ENV['AZURE_CLIENT_SECRET']
    azure.subscription_id = ENV['AZURE_SUBSCRIPTION_ID']
    azure.location = ENV['AZURE_LOCATION']
  end
end

その他必要なファイルは前回の記事を参照してください。

Ansible-Playbookを作る

  • Ubuntu のアップデート
  • ビルドに必要なパッケージのインストール
  • ロスコンパイラの取得とインストール
  • Linux kernel sourceの取得
  • Raspberry Pi(BCM2835)用configの設定
  • Linux Kernelのビルド

以上を行うAnsible playbookをつくります。

hostsのところはallにしておけば、inventoryファイルはいらないようです。

# update
- hosts: all
  tasks:
    - name: install basic packages
      apt: name={{ item }} update_cache=yes state=latest
      with_items:
        - git
        - build-essential
        - bc
      become: true
    - name: install cross-compiler
      unarchive:
        src: https://releases.linaro.org/components/toolchain/binaries/latest/arm-eabi/gcc-linaro-6.3.1-2017.05-x86_64_arm-eabi.tar.xz
        dest: /usr/local/
        remote_src: True
      become: true
    - name: add /usr/local/gcc-linaro-6.3.1-2017.05-x86_64_arm-eabi/bin to path
      lineinfile:
        dest: .bashrc
        insertafter: EOF
        line: "export PATH=$PATH:/usr/local/gcc-linaro-6.3.1-2017.05-x86_64_arm-eabi/bin"
    - name: clone linux source
      git:
        repo: https://github.com/torvalds/linux
        dest: linux
        version: master
        depth: 1
    - name: load bcm2835_defconfig
      command: "make bcm2835_defconfig"
      args:
        chdir: ./linux
      environment:
        PATH: "{{ ansible_env.PATH }}:/usr/local/gcc-linaro-6.3.1-2017.05-x86_64_arm-eabi/bin"
        ARCH: arm
        CROSS_COMPILE: arm-eabi-
    - name: make linux-kernel
      command: "make -j4 zImage dtbs"
      args:
        chdir: ./linux
      environment:
        PATH: "{{ ansible_env.PATH }}:/usr/local/gcc-linaro-6.3.1-2017.05-x86_64_arm-eabi/bin"
        ARCH: arm
        CROSS_COMPILE: arm-eabi-

ビルドしてみる

前回同様、Vagrantfileのあるディレクトリで以下のコマンドを実行するとクラウド上のVM起動からLinux Kernelのビルドまでが行われます。

vagrant up

使い終わったら vagrant destroy でマシンを潰すのを忘れないようにしてください。

性能計測

このスクリプトを使ったビルドに必要な時間を計測して、より速くビルドするにはどうすればよいかを考えてみたいと思います。

ビルド時間の概要

今回のビルドにかかる時間は、大まかに以下の2つに分けることができると考えています。

  • Azure上でVMを用意して立ち上げるまでの時間
  • ansibleのプロビジョンにかかる時間

VM立ち上げとプロビジョン完了までの時間はtimeコマンドを使えば計測可能です。 なので、後者のプロビジョン時間を知ることができれば、計算でVM立ち上げまでの時間を得ることができるでしょう。

VM立ち上げの時間はこちら側で速くすることは難しそうなので、後者のプロビジョン時間を速くする方向性で考えていきたいと思います。

プロビジョン時間の計測

ansibleのプロビジョンの各タスクの実行にかかった時間はansible-profileプラグインを使うことで調べることができるようです。

このプラグインは現在ansibleにデフォルトで入っているので、少し設定を追記するだけで利用可能です。

ansibleの設定は、Vagrantfileと同じディレクトリにanisble.cfg というファイルを作り、そこに書き込めば良いようです。 以下の内容を書いた anisble.cfg を作ってください。

[defaults]
callback_whitelist = profile_tasks

そして、再度 vagrant up を行うと、今度はプロビジョンにかかった詳細な時間が表示されるはずです。

計測結果の確認と検討

私の環境でのプロビジョン時間の結果の概要を以下に示します。

PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************
Friday 04 August 2017  00:47:21 +0900 (0:00:00.144)       0:00:00.144 ********* 
ok: [default]

TASK [install basic packages] **************************************************
Friday 04 August 2017  00:47:25 +0900 (0:00:03.483)       0:00:03.628 ********* 
changed: [default] => (item=[u'git', u'build-essential', u'bc'])

TASK [install cross-compiler] **************************************************
Friday 04 August 2017  00:48:00 +0900 (0:00:35.629)       0:00:39.257 ********* 
changed: [default]

TASK [add /usr/local/gcc-linaro-6.3.1-2017.05-x86_64_arm-eabi/bin to path] *****
Friday 04 August 2017  00:50:04 +0900 (0:02:03.371)       0:02:42.628 ********* 
changed: [default]

TASK [clone linux source] ******************************************************
Friday 04 August 2017  00:50:06 +0900 (0:00:01.734)       0:02:44.363 ********* 
changed: [default]

TASK [load bcm2835_defconfig] **************************************************
Friday 04 August 2017  00:51:01 +0900 (0:00:55.154)       0:03:39.517 ********* 
changed: [default]

TASK [make linux-kernel] *******************************************************
Friday 04 August 2017  00:51:07 +0900 (0:00:06.207)       0:03:45.725 ********* 
changed: [default]

PLAY RECAP *********************************************************************
default                    : ok=7    changed=6    unreachable=0    failed=0   

Friday 04 August 2017  00:57:02 +0900 (0:05:54.616)       0:09:40.341 ********* 
=============================================================================== 
make linux-kernel ----------------------------------------------------- 354.62s
install cross-compiler ------------------------------------------------ 123.37s
clone linux source ----------------------------------------------------- 55.15s
install basic packages ------------------------------------------------- 35.63s
load bcm2835_defconfig -------------------------------------------------- 6.21s
Gathering Facts --------------------------------------------------------- 3.48s
add /usr/local/gcc-linaro-6.3.1-2017.05-x86_64_arm-eabi/bin to path ----- 1.73s

結果を見ると、以下の順に時間がかかっているようです。

  1. Linux Kernelのビルド(354秒)
  2. ロスコンパイラのダウンロード(123秒)
  3. Linux Kernel Sourceのクローン(ダウンロード)(55秒)

(4位のUbuntuのアップデートとパッケージのインストールは高速化が難しいのでパスします。)

一番時間のかかっているLinux Kernelのビルドは、使用するVMの性能を上げれば短縮できそうです。 もちろん、性能の良いマシンはお金がかかるので、費用対効果も考える必要がありそうです。

2番目に時間のかかっているクロスコンパイラのダウンロードは、永続ディスクなどを作ってそこに保存しておいたものを使うといったことを行えれば速くできそうです。現在は何度も実行するとダウンロード先に負荷をかけてしまうかもしれないので、この改善は早めに行ったほうが良さそうです。

3番目のSourceのクローンも2番めと同様に、永続ディスクを作って保存しておいて、差分だけpullしてくれば速くできそうな気がします。

おわり

今回はvagrant-azureとansibleを使って、Azure上でLinux Kernelのビルドを行い、その実行時間を測ることと、どうすれば改善できそうかを考えました。

次回はより速くビルドできるよう、工夫してみようと思います。