Skip to content

Instantly share code, notes, and snippets.

@261shimizu
Last active March 2, 2023 01:34
Show Gist options
  • Save 261shimizu/0cf9d656d6f8f6f284f8615e22800027 to your computer and use it in GitHub Desktop.
Save 261shimizu/0cf9d656d6f8f6f284f8615e22800027 to your computer and use it in GitHub Desktop.
仮想化周りの話

コンテナ仮想化

仮想化の種類


OSの仮想化は、大きく分けてホストOS型とハイパーバイザ型に分けられる
ThinkITのこの画像がわかりやすい

  • ホストOS型
    ホストOSの上に仮想化アプリケーション(VirtualBox、VMware workstation、KVM...)などを乗っけて、その上にOSを乗っける形
    ホストOSの上に載っているアプリケーションと仮想化アプリケーションが並列している形
    ゲストOSは、アプリケーションとして動く
    通常のOSとして使用できるので、ホストOS上でアプリケーションを動かしたり監視できるのがメリット
    ハイパーバイザ型とは異なり、ゲストOSだけでなくホストOSの処理にもリソースを割かれるので、処理が遅いことがデメリット

  • ハイパーバイザ型
    ハードウェアの上にハイパーバイザ(仮想化レイヤー:VMware vSphere ESX,Xen,KVM,,,,)を乗っけて、その上にOSを乗っける形
    ホストOS型と異なり、ホストOS+仮想化アプリの二層の上に乗るのではなく、物理ハードウェアの上に仮想化レイヤが乗っかる

    ハイパーバイザー型仮想化とは、仮想化専用OSの上で仮想OSを動作させる手法です。ESX, vSphere, Xenなどが該当します。ハイパーバイザー専用のOSなので、ハイパーバイザー型はホストOS型に比べてオーバーヘッドが少ないと言われます。

    上記のハイパーバイザ専用OSという言葉が結構わかりやすい。
    そしてパフォーマンスの面でホストOSより優れる

    さらにハイパーバイザ型の中でも完全仮想化と準仮想化に分けられる
    完全仮想化は、ゲストOSに改変を加えずに使うもので、
    準仮想化は、ゲストOSに仮想化に適するように改変を加える

    しかし、最近ではCPUに仮想化支援機能がついており、この機能を使うことによって、完全仮想化でも実用上問題ない性能になっている
    Xenはもとは準仮想化から始まっている。しかしIntel-VTなんかの仮想化支援機能の登場によって、
    ソフトウェアがハードウェアをエミュレートしていた部分がCPUによって肩代わりされたことで、改変できないOSも準仮想化環境で扱えるようになった
    KVMなどはこれを使って完全仮想化のデメリットであるオーバーヘッドを減らした

    KVMは、Linuxカーネルをハイパーバイザとして使うので、シンプルで保守性が高い
    KVMのゲストOSはホストのLinuxからみると単一のユーザープロセスであり、通常のプロセス管理の手法が使える
    KVMは完全仮想化のみ

    KVMは、ホスト型という人もハイパーバイザという人もいる
    KVMは仮想化アプリケーションなので、ホスト型。でも、Linuxをハイパーバイザとして扱っているからハイパーバイザ型。という意見

  • コンテナ型
    Google Container Engine がDockerをサポートしたことがきっかけでブームになる
    コンテナ型とハイパーバイザ型と区別するかどうかは人によって意見が分かれる
    ハイパーバイザ型と似ており、コンテナ(ゲストOS)が、ホストOSのカーネルを利用することで、オーバーヘッドが少ないことが特徴
    ホストOSのカーネルを使うので、ゲストOSとか、仮想マシンとかいう言葉を使ってる人も使ってない人もいる
    その代り、隔離空間だとか、ユーザ空間だとか、名前空間だとか、コンテナだとかいう言葉が新しく登場する

    Docker やその他の Linux コンテナの背景にあるコンセプトは堅実なものです。

    • 重複したあるいは不要なOSエレメントをVM本体から排除することで、より高密度のサーバー設置を実現する非常に小さいVM

    • 巧みにパッケージされた VM スタックであり、容易に移動、複製、管理でき、高い移植性が保証される

    • 小さな VM ソフトウェア スタックを構成するため、複製や維持に多くの注意と労力を要する OS やツールのバージョン依存性に起因する面倒な問題を取り除く

    • 準備時間を短縮することができるため、より柔軟なインフラストラクチャを容易に作ることができ、その時々のニーズに応じたより大きな自由度を可能にする

    共有カーネル戦略がセキュリティ的に。。。っていうのと、同じOS(LinuxならLinuxということ、ディストリビューションは不問)しか使えないことがデメリット
    あとは1つのコンテナがミスるとホストOS全体が高負荷になったり、ホストOSがダメになると全コンテナが道ずれになったりする
    ただ、めちゃんこ速いし、コンテナ1つのサイズが小さくて手軽
    一般的なOSのブート手順を必要としない
    ハイパーバイザがハードウェアを仮想的に作り出しているのに対し、
    コンテナ(Docker)はNamespaceとcgroupsという資源管理の仕組みを使うことで、複数のコンテナがプロセスとして稼働するだけなので、オーバーヘッドも、ハードウェア資源の消費も少なくて済む

    KVMの時と同じように、コンテナ型とハイパーバイザ型を区別しないという人や、コンテナ型とホストOS型を区別しないという人がいたりする

Vagrant,chef,Dockerの差


PaaSやInfrastructure as Codeの流行

  • Vagrant
    VirtualBox等の操作を容易にしている+VagrantFIleによる環境構築の容易化、環境共有の容易化
    そのため、仮想化の方法としてはホストOS型
    ちなみにネットワーク関係の設定も楽

  • chef ソフトウェアのインストールを容易にするツール
    ざっくりいえばサーバ設定ツール
    プログラミングによってサーバ構築を行う
    また、chefは何回やっても同じ結果になるという特徴を持つので、既にあるサーバで実行してもchefで記述した設定になる
    このためchefのコードを見ればサーバの状態がわかる

  • Docker Vagrantによく似ている
    VagrantがホストOS型の管理ツールであるのに対し、Dockerはコンテナ型の管理ツール
    なので圧倒的に速い
    Vagrantと同じように、Dcokerfileという設定ファイルがあり、これをもとにコンテナ作成が可能
    よって環境構築、環境共有が簡単
    ただ、ネットワーク関係はVagrantの方が簡単
    gitのように、Dockerは差分の概念がある

組み合わせとしては、Vagrant&chefが結構使われる
Vagrantで仮想環境を楽に操作・構築して、chefでサーバ設定を入れる

Vagrant&Dockerは、DockerがLinuxしか使えないことによってMacやWindowsにVagrantでLinuxを入れた上にDockerを使うみたいなことをしたりする、、かも
仮想環境の方式がホストOSとコンテナ型で違うので、微妙なのかも

Chef&Dockerは、Vagrant&chefと同じようなことが可能
ただ、Dockerfileがプログラムなので、Dockerだけでも自動化はできる

Dockerへの懸念


なんか色々懸念されているらしい
よく言われているのがセキュリティの問題
dockerを使うにはルート権限が必要なこと
デーモンが常に動いているので、dockerのホストでは常にルートのプロセスが動いていることになる
クライアントとデーモンはHTTPでやり取りするので、外部ホストからコマンドを叩ける
上でも書いたカーネルの共有という特徴も合わせて、セキュリティ的に・・・という話が良く出ている
さらに、Docker pull という、外部イメージの取得も安全なのか・・・という話もよく出ている

あとはDockerfileが少し扱いづらかったり、Dockerがベンダーロックインを招くんじゃないかとか、
将来的にもずっと、同じイメージから同じコンテナができるわけではないということとか、
Dockerがプラットフォームを目指しているのでシンプルさが云々かんぬんとか、、、、

いろいろ議論はあるみたい

Dockerに依存しすぎるのはあんましよくないというお話

参考


TinkIT コンテナ技術の基礎知識

Dockerの導入・コマンド

やったこと


  • dockerインストール
  • ホストOSのカーネルアップデート
  • ホストの起動時カーネル選択設定
  • device-mapperアップデート
  • centos:latestの取得
  • centos:centos6.7の取得
  • コンテナへのhttpd,sshdインストール・起動
  • ポートフォワーディング設定を、コンテナ起動時にする
  • ブラウザで表示(httpdの動作確認)
  • dockerコマンドをsudoなしで使えるようにする

CentOS6.5へのDockerの導入


ホストがCentOS7だとyumのレポジトリにdocker.ioがある(確か)けど、CentOS6だとEPELをレポジトリに追加することから始める(もしかしたら必要ないかも)

$ sudo yum -y install http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ sudo yum -y install docker-io
$ sudo service docker start
$ sudo chkconfig docker on ← 起動時に自動的にdockerを起動する

2018/06/26追記
↑のdocker-ioというのはどうやら古そう。
今はdocker-ceをインストールするのが良いみたい(ce:community-edition)
以下、CentOS7にdockerをインストールする手順。

$ sudo yum install yum-utils device-mapper-persistent-data lvm2
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce

ここまで来て躓く。
service docker startとしても、直後にservice docker statusとして状態確認すると起動していない

runしようとしてもdocker deamon起動してますか?と出たりする
(Is 'docker -d' running on this host?)

色々dockerコマンド打ってみるもダメ。
ログ(/var/log/docker)を見ると、どうやらカーネルのバージョンがダメなのと、デバイスマッパー周りがダメっぽい
(You are running linux kernel version 2.6.32-504.8.1.el6.x86_64, which might be unstable running docker. Please upgrade your kernel to 3.8.0.

/usr/bin/docker: relocation error: /usr/bin/docker: symbol dm_task_get_info_with_deferred_remove, version Base not defined in file libdevmapper.so.1.02 with link time reference)

そこで、カーネルのバージョンを上げてみる
(EPELからとってくる)

$ rpm -Uvh http://www.elrepo.org/elrepo-release-6-6.el6.elrepo.noarch.rpm  
$ sudo yum install --enablerepo=elrepo-kernel kernel-ml  

これで、起動時にカーネルを切り替える
起動時のカーネル選択にかかわる設定ファイルは、/boot/grub/grub.conf
このファイルには、カーネルのリストらしきものがある
default=となっているところが、起動時に選択されるブート
リストの何番目にあるカーネルを選択するかを示している
default=0
として(とってきたカーネルが最初にあったため)、カーネル設定終了。リブートする

カーネルの確認は、

$ uname -ar
Linux ~~~~~~~~~~~

とする

さらに、デバイスマッパーをアップグレードしてみる

# yum update device-mapper  

dockerは、ホストとコンテナでカーネルを共有する関係で、カーネルとその周辺モジュール周りのバージョンに結構シビアらしい。dockerが使っているLXCという技術もそうだったりする

これでまたリブートすれば、service docker startがうまくいった

Docker基本操作


Dockerをインストールしてサービススタートさせたあとは、好きなコンテナイメージを引っ張ってくる
イメージの検索は、
# docker search
イメージの取得は、
# docker pull イメージ とする
取得したイメージの一覧は、
# docker images
で確認できる
このイメージをもとにコンテナを作るには、
# docker run イメージとする
このdocker runコマンドにはいろいろオプションがある
たとえば、docker run centos echo "hello world"とすると、
コンテナが立ち上がって、echo "hello world"が実行され、コンテナが終了する
(当然継続的なコマンドを指定すれば、コンテナは終了しない)
(つまり、/bin/bashとしているのはそういうこと。シェルを起動している)
さらに、-iはインタラクティブモード、-tがターミナル開く、-dがバックグラウンドで実行、-pでポートフォワード指定

コンテナのリストは、
# docker ps -a
とする、-aをつけずに実行すると、現在動いているコンテナのみ表示
-aは、終了したコンテナも含めて表示

イメージやコンテナにはそれぞれIDが振られていて、このIDによってコンテナを指定したりする(名前も付けられる)
(cf 差分)
IDは一意に決まるので、指定する際は最初の3文字とかだけでも(一意になっていれば)OK

作ったコンテナにソフトウェアインストールして環境を作って、ってやって、できた環境をイメージにしたいときは、
docker commit コンテナID 名前とすると、
指定した名前のイメージができる

コンテナは、exitすると終了してしまう
中断したいときは、Ctrl+p→Ctrl+q(コンテナ内で実行)
中断から戻りたいときは、docker attach コンテナID(ホストで実行)
docker attachは、バックグラウンドのものをフォアグラウンドにするときにも使える
終了したコンテナを立ち上げるのが、docker start コンテナID(ホストで実行)

コンテナに対して割り振られているIPアドレスや情報を知りたいときは、
ホスト側で、docker inspect コンテナIDとする

dockerfileからイメージを作る時には、docker build 名前 dockerfileがあるディレクトリ

dockerコマンドをsudoなしでできるようにする


dockerコマンドはルート権限が必要
でも、dockerグループに所属するユーザならばsudoなしで実行できる

$ sudo groupadd docker
$ sudo gpasswd -a ユーザ名 docker

dockerサービス再起動、一旦ログアウト→ログインすればOK
以上

dockerfile基礎+dockerコマンドまとめ

dockerfile概要


1行に1命令
コメントアウトは#を使う

 FROM イメージ名                       ⇒何のイメージをもとにするかを指定  
 MAINTAINER 自分の名前                 ⇒自分の名前(+ アドレスを書いているのが多い)を記しておく  
 RUN コマンド                          ⇒ホストのファイルをコンテナ内に取り込むのに使うbuildする(イメージを作る)ときに実行される  
 ADD 元ファイル名パス コピー先パス       ⇒ホストのファイルをコンテナ内に取り込むのに使う  
 CMD ["コマンドの引数1", "引数2" ,....]  ⇒runする(コンテナを作る)時に実行される  

こうやっておくと、buildするとき、runするときに実行される
RUNがbuild時でCMDがrun時というなんかややこしい感じ
RUNに、ソフトウェアインストールのコマンドとかを書いて使うことが多い
CMDには、["/usr/bin/httpd", "-D", "FOREFROUND"]
という感じで、webサーバを起動したりするのに使う(runしたらwebサーバ立ち上がる)

随時追加すること

dockerコマンドまとめ


コマンド オプション 説明 補足
docker serach 検索ワード イメージの検索
dokcer pull イメージ イメージのダウンロード :タグ名も付けられる。省略すると:latestと同じ
docker images イメージの一覧表示
docker commit コンテナ 名前 コンテナからイメージの作成
docker rmi イメージ イメージの削除
docker rm コンテナ -f コンテナの削除 -fは強制削除(起動中でも削除可能)
docker run イメージ コマンド・シェル オプション多数 イメージからのコンテナの起動、コンテナのコマンドを発行 詳しくは別表
dokcer rename 旧コンテナ名 新コンテナ名 コンテナ名の変更
docker restart コンテナの再起動
docker ps -a,l,q,-n=数字 起動中のコンテナの表示 aは終了後も含めて表示、lは最後を表示、qはIDのみ、nは直近何個を表示するか指定
docker attach コンテナ 起動中コンテナへの接続
Ctrl+p→Ctrl+q コンテナ中断 コンテナ内で実行
exit コンテナ停止 コンテナ内で実行
docker stop コンテナ コンテナ停止 ホストで実行、killもある
docker logs コンテナ -f コンテナのログ(コンテナコマンドがターミナルに出力する内容)を確認 -fはtail -fみたいに監視出力する
docker inspect コンテナ -f コンテナ情報を表示 -fでフィルタリングする
docker build -t レポジトリ名:タグ名 fileのあるディレクトリのパス Dockerfileからイメージを作成する
docker start -a コンテナの起動 バックグラウンドで起動、-aでアタッチ
docker exec コンテナ名 コマンド 追加コマンドを発行
docker stats コンテナ名, コンテナ名, .... コンテナがどの程度ホストのリソースを消費しているかを調べる
docker top コンテナ名 コンテナ内のプロセスを表示
docker port コンテナ名 コンテナ内のポート番号 コンテナのポートマッピング情報を表示
docker info コンテナ数やイメージ数やディレクトリなどのホストの状態を知る
docker tag imageID レポジトリ名:新タグ名 タグを付与する
docker push レポジトリ名:タグ名 Ducker Hubにアップロード
docker diff コンテナ名 ファイルシステムの変更状態を確認する(差分表示) commitの際に意図しない変更が含まれていないか確認できる
docker cp コンテナ名:パス ホストのパス コンテナ内のファイルまたはフォルダをホスト側にコピー
docker events --since=数字 サーバからのイベントを取得 オプションの指定はUNIX時間
docker export コンテナ コンテナのファイルシステムのエクスポート
docker history イメージ コンテナイメージの履歴表示

....等々。実際にはバックアップや、マウント、Data Volume Containerの作成等ができるが、これは出会ったときに追記すること
また、docker1.9(確か)で、docker networkコマンドなるものが出てきて、ネットワークをいじれるようになったらしい。これも今後の追記に期待
そんでもってデーモン起動にも大量にオプションがある

docker run コマンドについて


docker runコマンドは、オプションが大量にあるのでそのまとめ

オプション 意味
-i インタラクティブモード(起動時にSTDOUTを開きっぱなしに)
-t tty(ターミナル起動)
-d dettach(バックグラウンドで起動)
--name 名前 名前を付ける
-h ホスト名 ホスト名を付ける
--rm コンテナを停止すると自動的にコンテナ削除
-c 数字 CPU使用率を指定
-m 数字 メモリ容量を指定(数字は単位:b,k,m,g)
-v 絶対パス(ホスト側):絶対パス(コンテナ側) ホストディレクトリをコンテナにマウント
-p ホスト側ポート:コンテナ側ポート ポートフォワーディングを設定できる

他にも、--netとか、--lxc-confとかある

コンテナは、基本的に超シンプルにするのが良いらしい
なので、sshdとか入れない方がいいみたい
だから、runするときのコマンドとか、dockerfileのCMDとか、サーバを一個立ち上げてあとは何もしないみたいなことがいいらしい
コンテナ内で作業したいときは、コンテナからイメージを作る時だけだったりするのかもしれない。その時に/bin/bashとかで開けばよいという感じ

Tips


IDでコンテナを指定することがかなり多い
なので、最後に起動したコンテナIDを取得するコマンドを、エイリアス設定すると便利

alias dl="docker ps -l -q"

(-lは、停止中のコンテナも含む中で最後のもの。-qはIDのみ表示)

public-networkなvagrantでnm_controlled=yesにする

概要


vagrantで、ネットワークをpublicに指定したマシンは、publicに割り当てられたNICの設定がvagrantによって編集される。 そのNICをnm_controlled=yesにしたいのだが、vagrantによって書き換わるために(マシンから)設定ファイルに記述しても無駄。 ⇒vagrantのprovisioningを使う。

解決策(Vagrantfile)


  config.vm.provision "shell", run: "always", inline: <<-SHELL
    nic_path=/etc/sysconfig/network-scripts/ifcfg-eth1
    if grep 'nm_controlled'
    then
      sed -i 's/nm_controlled=no/nm_controlled=yes/g' $nic_path
    else
      echo 'nm_controlled=yes' >> $nic_path
    fi
    service NetworkManager restart
  SHELL

vagrant up 時にAuthentication failure Retrying...というエラーが出る件

結論


  • githubからinsecure key持ってくる。600と700にする。
  • (IDじゃなく)VM名でvagrant packageする。
  • (ポートフォワードを消すなりちゃんと設定すれば解決するかも。。。。)

現象


VirtualBoxで仮想マシンを作り、vagrant packageコマンドで自作boxとする。 authorized_keyの設定はきちんとしたはず。 vagrant upすると、sshの認証で表題のエラーが発生。Retryをループする。

調査


vagrant は、insecure keyを検知すると安全な鍵へ自動で変更してくれる仕様になっているらしい(初回vagrant up時)。 insecure keyは、開発者?のgithubにアップされているので、ダウンロードしてゲストのvagrantユーザのauthorized_keysを上書きすれば良い。 この時の注意は、~/.sshと、~/.ssh/authorized_keysのパーミッション。それぞれvagrant:vagrantで0700,0600。

しかし、今回は上記作業を行ったにも関わらず、失敗する。 しかもメッセージは同じであり、これをググっても上記の対応ばかりなので諦めかける。。。

試行錯誤


色々試した挙句、"VirtualBox"からネットワーク設定ーポートフォワード設定がイケてないのかと思った。
ポートフォワード設定をホストIP・ホストポート・ゲストポートのみ指定したら失敗して、ゲストIPを加えたら成功したので。

これもpakcage化する時に既存のポートフォワード設定がclearされているっぽいメッセージが出るので謎だけど、↑の様な事例があった。

これで解決、と思いきや。。。
自作vagrant boxを更にいじって、そこから別のboxを作った時に同じ事例に遭遇。
今度はほぼ確実にポートフォワードじゃないので(設定していないから)、ほぼ諦めモード。

ぼけーっといろんなサイト見ていて気づく。
vagrantのvmについているIDでvagrant packageコマンドを使っている人がいないことに。
で、同じ設定のまま、~/VirtualBox VMs/配下のVM名を使ってvagrant packageコマンドを実行し、vagrant upしたら、あっさり成功。

vagrant package IDでもvagrant upすれば同じVMが出来上がるのに、何故かVM名でやらないとssh認証が出来ない(insecure keyが置きわからない)ことが発覚。

vagrantのバグ???ちなみに使ったIDは、vagrant global-statusコマンドで表示されるID

Vagrantfileの詳細

大枠


Vagrantfileはrubyで書かれたプログラムになっている。

Vagrant.configure(2) do |config|
  # 設定内容
end

1行目のconfigureに続くカッコ内の数字は、Vagrantの設定バージョンを表す
VagrantにはV1とV2と呼ばれる二つの設定バージョンがあり、Vagrant2.0で使える設定構文がV2バージョン

また、下記の様に一つのVagrantfileにV1・V2設定を混在させることも可能。

Vagrant::Config.run do |config|
  # V1の設定
end

Vagrant.configure("2") do |config|
  # V2の設定
end

設定内容


  • 設定関連のドキュメント

    • # https://docs.vagrantup.com.(11行目)
      なんかあったらここを参照してねということ
      やっぱりなんかあった時のドキュメント参照は大事
  • box関係

    • config.vim.box = "bento/centos-6.7"(15行目)
      ここで使用するboxの指定を行っている。
      ここで指定したboxのOSがインストールされる
      この1行上にhttps://atlas.hashicorp.com/search.
      があって、ここでboxを探してね、ということ

    • config.vm.box_check_update = false(20行目)
      で、boxのアップデートを自動でチェックするか否かを指定している
      falseだとvagrant box outdatedで手動チェックの必要あり。
      falseは非推奨

  • ネットワーク関係

    • Vagrantは、デフォルトではNATを使うことになっている

    • config.vm.network "forwarded_port", guest: 80, host: 8080(25行目)
      の部分で、ポートフォワーディングという設定を行っている。
      これはホストマシンの指定したポート宛のパケットを仮想マシンに転送する機能
      この設定は、ホストマシンの、ポート番号8080番と、ゲストマシンのポート番号80番を対応付けている
      デフォルトではTCPでの接続のみがフォワーディングされるが、
      config.vm.network "forwarded_port", guest: 1024, host: 10240, protocol: 'udp'
      とすることでUDPのパケットを転送するように指定できる

    • config.vm.network "private_network", ip: "192.168.33.10"(29行目)
      の部分では、プライベートネットワークの設定になっている
      このプライベートネットワークは、
      ホストとゲストの間でのみ通信が行える仮想ネットワークインターフェース(仮想NIC)を作成する
      仮想NICはホストとゲスト両方に作成され、それぞれが仮想的に1対1で接続される
      このアドレスは、ゲスト側の仮想NICに割り当てるIPアドレスである
      なお、ホスト側のNICに割り当てるアドレスはVagrantは関知しない
      プライベートネットワークでは、virtualbox_intnet:<内部ネットワーク名>というオプションパラメータを追加することで、
      仮想マシン間を接続した仮想ローカルネットワークを構築することも可能
      ex) config.vm.network "private_network", ip: "192.168.50.4", virtualbox__intnet: "network01"
      この場合、仮想マシン側ではホストオンリーアダプタではなく、内部ネットワーク型のネットワークアダプタが作成される

    • # config.vm.network "public_network"(34行目)
      この部分では、パブリックネットワークの設定を行っている。
      パブリックネットワークは、
      ブリッジ接続を利用して仮想マシンがホストOSとのネットワークと直接通信できるようにする設定
      また、ブリッジ接続に指定できるNICが複数ある場合、;brigeパラメータで使用するNICを指定できる。
      たとえばeth0を利用する場合、以下のようになる
      ex) config.vm.network "public_network", :bridge => 'eth0'

プライベートネットワークおよびパブリックネットワーク設定を利用する場合、仮想マシンに新たなネットワークインターフェイスが追加される。そのため、追加されたネットワークインターフェイスに対するネットワーク設定が自動で行われるよう、利用するboxファイル側であらかじめ設定が行われている。これらに対応していないboxファイルの場合、仮想マシンへのネットワーク接続が行えず、仮想マシンの設定が完了しない場合があるため注意したい。

  • 共有フォルダ関係

    • config.vm.synced_folder "./sync_folder", "/home/vagrant/sync_folder"(40行目)
      この部分で共有フォルダの設定を行っている
      第一引数でホストのフォルダのパスを、第二引数でゲストのフォルダのパスを指定する
      オプションでtypeが指定でき、第三引数で指定する。以下はNFSで共有する場合
      ex) ...folder", type: "nfs"
  • プロバイダ(VirtualBox)のオプション設定(42行目以降)

    • config.vm.provider "virtualbox" do |vb| ~ end(46行目)~(52行目)
      の部分がそれ。この中をいじるならこの2行はコメントアウトを外す

    • vb.gui = true(48行目)
      ここでは、GUIを使用するかどうかの設定を行っている

    • vb.memory = "1024"(51行目)
      の部分が、仮想マシンへのメモリサイズの設定

  • Atlas(他のも使える)関連

    • config.push.define "atlas" do |push| ~ end(60行目)~(62行目)
      この部分でファイル共有にAtlasを使う時の設定を行っている
      他にもFTPHeroku(PaaSの一種 紹介)も使用できる

    • push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME
      ここでAtlassのアカウントを指定

  • プロビジョニング設定

    • config.vm.provision "shell", inline: <<-SHELL ~ SHELL(67行目)~(70行目)
      の部分がそれ(shellプログラムになっている)。
      vagrant up実行と同時にこの部分の処理が実行される
      sudo apt-get update
      sudo apt-get install -y git
      が間に記述されていれば、この2行が実行され、gitがインストールされた環境が手に入る
      vagrant provisionコマンドを実行しても、この部分が実行される。
      shell以外にも、chefpuppetを利用できる

概要


vagrantで、DHCPではなく固定IPにするには、
vm.network :public or :private, ip:~ で指定する。
けど、実際作ってみたら、nmcliコマンドが効かない(cenots7)。
確認すると、/etc/sysconfig/network-scripts/ifcfg-enp ファイル内で、NM_CONTROLLED が no になっている。
これをyesに変更するだけかと思いきや、接続名が変になる。

詳細


例えば、:public, ip:100.20.30.40としてvagrant upすると、
enp0s8が割り当てられ、ip addr showとした時もちゃんと表示される。
が、仮想IPをたそうとして、sudo nmcli con mod enp0s8 +ipv4.addresses~としても、うまくいかない。
nmcli con とすると、enp0s8が表示されない。
nmcli dev とすると、enp0s8は表示されるが、「管理無し」とされる。

次に、/etc/sysconfig/network-scripts/ifcfg-enp0s8の、NM_CONNTROLLEDをコメントアウトすると
nmcli con でもenp0s8が表示される(デバイスはちゃんとenp0s8)。
が、同時にSystem enp0s8という接続名も出現する(こちらのデバイスはなし)。
そこで、nmcli con down enp0s8とすると、デバイスenp0s8が接続名System enp0s8に割り当てられる模様。
で、こうなっていればnmcli con mod "System enp0s8" +ipv4.addressesとか出来る。
接続名はSystem enp0s8,デバイス名はenp0s8となるのでちょっと注意。
※接続名変えればいいのかも。

Vagrantfileでなんとかする


  config.vm.define :test do | test |
    test.vm.hostname = "test"
    test.vm.network :private_network, ip: "192.168.55.30", virtualbox__intnet: "intnet"
    test.vm.provision "shell", run: "always", inline: <<-SHELL
      sed -i -e "s/NM_CONTROLLED/#NM_CONTROLLED/" /etc/sysconfig/network-scripts/ifcfg-enp0s8
      systemctl restart NetworkManager
      nmcli con down enp0s8
      nmcli con mod "System enp0s8" +ipv4.gateway 192.168.55.100
      nmcli con down "System enp0s8"
      nmcli con up "System enp0s8"
      route del default enp0s3
    SHELL
  end

いつも複数サイトを調べてしまうので、まとめておく。

vagrantで管理しているboxから新しいvagrantのboxを作る手順

  • VM名を指定するなら、Vagrantfileに以下の記述を追加。
config.vm.provider :virtualbox do |vb|
	vb.name = "VM名"
end
  • 以下のコマンドを実行
# NICの採番が狂わないようにする
$ ln -s -f /dev/null /etc/udev/rules.d/70-persistent-net.rules
$ rm -rf /dev/.udev/
$ rm -f /lib/udev/rules.d/75-persistent-net-generator.rules

# SSH設定変更 DNSを探しに行って接続が遅くならないようにする
$ sed -i -e "s:^#UseDNS yes:UseDNS no:" /etc/ssh/sshd_config
$ service sshd start
$ chkconfig sshd on

# vagrantの公開鍵をvagrantユーザのauthorized_keysに登録する
$ mkdir /home/vagrant/.ssh
$ chmod 700 /home/vagrant/.ssh
$ curl -k -L -o /home/vagrant/.ssh/authorized_keys 'https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub'
$ chmod 600 /home/vagrant/.ssh/authorized_keys
$ chown -R vagrant:vagrant /home/vagrant/.ssh

# boxをなるべく小さくするため、以下を実行
$ yum clean all
$ rm -r /var/tmp/*
$ rm -rf /var/lib/dhcp/*
$ dd if=/dev/zero of=/EMPTY bs=1M
$ rm -f /EMPTY
$ sudo -u vagrant cat /dev/null >~/.bash_history
$ cat /dev/null >~/.bash_history

# box作成
$ vagrant package --base VM名
### ↑の--baseで指定するものは、(idではなく)VM名にすること!!!
### VM名の確認は~/VirtualBox VMs/配下を確認。

# box追加
$ vagrant box add --name BOX名 package.box

Virtual Boxの(vagrantで管理していない)VMからvagrantのboxを作る手順

  • 仮想マシンの設定からUSBコントローラの有効化を解除
  • 同じくオーディオの有効化を解除
  • rootパスワードをvagrantに。
  • ネットワークは自動起動するようにしておく。
  • 以下のコマンドを実行
# @host
$ VBoxManage controlvm VM名 natpf1 ssh,tcp,,2222,,22
### ↑ゲストIP、ホストIPいらないかどうかは不明。でも最後に消すので問題ないハズ。

### VBGuestAdditionsインストール
# @host
$ VBoxManage storageattach VM名 \
  --storagectl IDE \
  --port 1 \
  --device 0 \
  --type dvddrive \
  --medium "/Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso"

# @guest
$ mount -r /dev/cdrom /mnt
$ sh /mnt/VBoxLinuxAdditions.run

# iptables無効化
$ service iptables stop
$ service ip6tables stop
$ chkconfig iptables off
$ chkconfig ip6tables off

# selinux無効化
$ sed -i -e "s/SELINUX=enforcing/SELINUX=disabled/" /etc/sysconfig/selinux

# NICの採番が狂わないようにする
$ ln -s -f /dev/null /etc/udev/rules.d/70-persistent-net.rules
$ rm -rf /dev/.udev/
$ rm -f /lib/udev/rules.d/75-persistent-net-generator.rules

# SSH設定変更 DNSを探しに行って接続が遅くならないようにする
$ sed -i -e "s:^#UseDNS yes:UseDNS no:" /etc/ssh/sshd_config
$ service sshd start
$ chkconfig sshd on

# vagrant ユーザ作成
$ useradd -m vagrant
$ echo 'vagrant' | passwd --stdin vagrant
$ echo "vagrant ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers

# ttyを必須にしない
$ sed -i "s/^.*requiretty/#Defaults requiretty/" /etc/sudoers

# vagrantの公開鍵をvagrantユーザのauthorized_keysに登録する
$ mkdir /home/vagrant/.ssh
$ chmod 700 /home/vagrant/.ssh
$ curl -k -L -o /home/vagrant/.ssh/authorized_keys 'https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub'
$ chmod 600 /home/vagrant/.ssh/authorized_keys
$ chown -R vagrant:vagrant /home/vagrant/.ssh

# boxをなるべく小さくするため、以下を実行
$ yum clean all
$ rm -r /var/tmp/*
$ rm -rf /var/lib/dhcp/*
$ dd if=/dev/zero of=/EMPTY bs=1M
$ rm -f /EMPTY
$ sudo -u vagrant cat /dev/null >~/.bash_history
$ cat /dev/null >~/.bash_history

# シャットダウン
$ shutdown -h now

# @host
# natのポートフォワードを削除
$ VBoxManage controlvm VM名 natpf1 delete ssh

# マウント解除
$ VBoxManage storageattach VM名 \
  --storagectl IDE \
  --port 1 \
  --device 0 \
  --type dvddrive \
  --medium emptydrive

# box作成
$ vagrant package --base VM名

# box追加
$ vagrant box add --name BOX名 package.box

仮想化環境周りの背景(参考)


  • 仮想化
    仮想・論理(virtual)⇔物理(physical)の対比
    仮想化はハードウェアリソースを、OSやアプリケーションへ柔軟に割り当てるための技術
    サーバ仮想化であれば、1台の物理的なサーバのリソースを分割したり、複数の物理リソースを統合したりして仮想的(論理的)に、何台ものサーバに見せたり、複数のサーバを一台のサーバに見せたりする。
    仮想的なリソースは、アプリケーションなどからはあたかもそれが物理的に存在するように見える
    ハードウェア利用効率の低さの改善、ハードウェアの維持管理にかかるコストや手間を削減していく流れの中で、仮想化が普及 ex ) 電源容量、冷却コスト、設置スペース、運用コストの削減と遊休ハードの効果的な利用、さらに会社の資産として計上する必要がないこともメリット
    デメリットとしては、仮想環境を構築すると物理マシンの性能が少し落ちることがある(ディスクへのアクセスが頻発するような環境では、物理マシンの方が強かったりする)

  • ローカル開発環境
    開発したものは、実際のサーバ(本番環境)にアップしなければならない
    でも、実際のサーバと、自分、または開発チーム全員の環境が同じではない。
    (サーバに多く使われるのはLinux、みんな使っているのはMac,Windows)
    環境が同じでなければ、正しく動作するかわからない。
    なので、本番と同じ環境を作り、そこで開発してテストするのが安心。
    この、実際に開発を進める、本番と同じ環境をローカル開発環境という。
    ローカル開発環境を、各自のマシン上に作るのに、仮想化が使われる。
    本番環境へのアップのことをデプロイリリースという
    注意点としては、ローカル、テスト環境、本番環境へとアップするときに、環境によって変わるもの(IPだとか...)があるので、これを間違えると大変なことになったりする。
    ローカルの環境を、環境ごと丸々(コンテナ)移す技術をコンテナ技術という
    実は、MacはUNIXと似ていたりする。。。なので、Windowsだけが特別で、仮にMacを使っている場合、本番環境と似たような状況で作業することができる。
    しかし、何度も環境を作ったりしていくと環境が汚れてくる。
    こういう場合には、気楽に作れて気兼ねなく壊せる仮想環境が強く、仮想環境を使うメリットがある

  • VirtualBoxとVagrant
    PC上に仮想的なPCを構築、ホストと別の環境を構築するのに使うのが、VirtualBox
    VirtualBoxは、x86仮想化ソフトウェアパッケージの1つ。
    ほかにはVMwareなどがある。
    このVirtualBoxを楽に操作できるようにしたソフトウェアが、Vagrant
    Vagrantは、仮想マシンの作成や設定の自動化を実現。
    簡単なコマンド数行で、仮想マシンに完全な開発環境を構築できてしまう。
    また開発チームなどで、各自同じ開発環境を整えるのには、手順書を作って、多少面倒なコマンドを打ったりしなければならなかった
    Vagrantでは、Vagrantfileと呼ばれる設定ファイルに、仮想マシンの情報が保存されている。なので、このファイルを参照すれば、同じ環境が簡単に作れる。
    このVagrantfileに、プロビジョニングを行う記述も追加することができ、ミドルウェアの設定やインストールも楽。

  • プロビジョニング(Provisioning)

Vagrant入門

プロビジョニングという言葉があります、これは Vagrant の用語ではなく、サーバー構築やネットワーク構築で利用される言葉です。 サーバーを選定したりOSやソフトウェアをインストールするなどして、サーバーがサービスを提供できるようにするまでの一連の作業をプロビジョニングと言います。 Vagrant では、この一連の作業を自動化させるためのプロビジョニング機能を有しています。

例えば Box から仮想マシーンを作成して起動した後に、開発メンバー全員の仮想マシーンに全く同じソフトウェアをインストールしたり設定をしたりしたい場合があります。 従来はそういう設定を手順書などにして開発メンバーにやらせていたりしましたが、そういう単純作業は自動化してしまいたいものです。 そこでプロビジョニング機能を利用し、仮想マシーンが起動すると同時にあらかじめ用意したプロビジョニングコードが実行され、起動が完全に完了した時には全員が同じ仮想マシーンの状態で作業を開始できるようにできます。

このプロビジョニングですが、実際に仮想マシーンに設定したい内容はシェルスクリプトで書くこともできますし、近年注目を集めているプロビジョニングフレームワーク・ソフトウェア (Chef や Puppet など) も利用することができます。 (Chef に関しては、本サイトで今後扱っていこうと思っています。)

サーバの最初の設定をすることをプロビジョニングというが、アプリケーションのアップをデプロイといい、似たようなイメージの作業にはなるが、プロビジョニングは一回走ったらほぼその後再びやることがないのに対し、デプロイは何度もやって更新させていくのが普通

Vagrant


  • 用語説明
用語 説明
BOX 仮想マシンのひな形となるイメージファイル(boxのリストから入手)
プロバイダ 仮想環境のこと(VirtualBoxなど)。デフォルトはVirtualBox。その他はプラグインで対応
プロビジョニング 必要なミドルウェアのインストールや設定を行う処理のこと
プロビジョニングツール プロビジョニングを行うツール(ChefとかPuppet等)
Vagrantfile 仮想マシンを起動するときのスペックや設定、プロビジョニングを記述したファイル
Atlas Boxを共有するためのサービス(cloudみたいなもの)
共有フォルダ(Synced Folder) ホストとゲストで共有できるフォルダのこと
*boxのリストは、公式(HashiCorp)の推奨である上のリンクに行くこと。
さらにそのリストの中でも、Officialだったりして安全なものを取ること。
もう一つリストがある(~.esみたいなやつ)が、こちらは誰でもboxをあげられるし、あまり信頼できない
  • VirtualBox導入
    Vagrantは、VirtualBoxのフロントエンドとしてのツール
    なので、virtualBoxをダウンロード・インストールをする必要がある
    (VMware等でも良い)

  • Vagrantの導入
    さらに、Vagrantをダウンロード・インストールする

  • Vagrantfileの置き場を作る
    好きなディレクトリを作る (以降はこのフォルダでの作業)
    Vagrantは、プロジェクト単位で作業する
    仮想マシンごとにVagrantfille作成(プロジェクトごとにディレクトリをわける)

ex ) mkdir myvagrant
     cd myvagrant
     mkdir mycentos
     cd mycentos
  • Boxの選定・Vagrantfile作成/初期化
    vagrant init Box名
    (box名を指定しなければ、vagrantfile中にはbox="base"となる)
    (そのままvagrant upしようとすると、見つからないと怒られる)

  • Vagrantfileの編集
    config.vm.network "private_network", ip: "192.xx.xx.xx"
    となっているところのコメントアウトを外す

  • vagrant起動
    vagrant up

  • 接続
    SSHで、さっきコメントアウトを外した部分のアドレスを指定して接続すればもう使える

  • コマンド(Vagrantfileがあるディレクトリで実行する)

目的 コマンド
vagrantコマンドリスト表示 vagrant list-commands
Box 追加 vagrant box add USER/BOX
Box list表示 vagrant box list
初期化 vagrant init [box名]
sshログイン vagrant ssh
仮想マシン起動 vagrant up
仮想マシン停止 vagrant halt
仮想マシン再起動 vagrant reload
仮想マシン削除 vagrant destroy
仮想マシンの状態確認 vagrant status
仮想マシンスリープ vagrant suspend
仮想マシンスリープ解除 vagrant resume
既存のVagrant環境のBox化(package.boxファイル作成) vagrant package

*BOX追加のコマンドのUSER/BOXは、アトラスのユーザアカウント名とBOX名ということ。
こう指定するとBOXカタログを探しに行ってくれて、インストールしてくれる

  • 参考
    Thinkit-操作よりも、物自体を説明してる感じ。図があってわかりやすい
    個人ブログ-操作メイン。
    Web arch labo-概念から操作まで。詳しい
@t2ynkmr
Copy link

t2ynkmr commented Apr 20, 2016

おつかれさまでした 👍
以下修正しておいてください:bow:

  • box のリンク先を修正
  • vagrant box add を新しい形式に修正 (vagrant box add _/_ )
  • 接続 のところ、『SSH』にしておいてください。『SSHかなにか』であれば何かも書いておいたほうが良いかな

余裕があれば

  • box がない状態で実行した場合に設定される box について確認してみてくださいー

@261shimizu
Copy link
Author

チェックありがとうございました!

  • 修正箇所直しました
  • システム管理の方の教科書の1章についてもまとめました

NAT、ブリッジ、NIC等のネットワーク関連がまだいまいちピンと来ないので、
ネットワークの方(2章)を進めつつこっちを充実させていく形にしたいと思います

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment