OpenvSwitchとnamespaceで仮想ネットワークにVLANを構築する
■概要
今回はOpen vSwitchとnetwork namespaceの機能を使って一台のマシンの中に仮想的なVLANネットワークを構築します。
今回作る構成は下の図のような感じです。
OS : Ubuntu16.04
■参考
http://app.f.m-cocolog.jp/t/typecast/1766421/1776113/88010845
■Open vSwitchのインストール
Open vSwitchをインストールし、サービスを起動します。
$ sudo -i # apt install openvswitch-switch # systemctl start openvswitch-switch
■仮想VLANの構築
この章では、namespaceとOVSブリッジを用いて仮想的なVLANを構築し、同一VLANタグを持つインターフェース同士が通信できることを確認します。
OVSブリッジの作成
VLANインターフェースを持つovs1とovs2を作成します。
# ovs-vsctl add-br ovs1 # ovs-vsctl add-br ovs2
namespaceの作成
OVSブリッジに接続するnamespaceを作成します。
# ip netns add ns1 # ip netns add ns2 # ip netns add ns3 # ip netns add ns4
vethの作成
OVSブリッジとnamespaceを接続するveth(仮想的なLANケーブル)を作成します。
※指定されている2つの名前(ns1ovs1, ovs1ns1など)はLANケーブルの両端を表します。
※今回の命名規則は「接続元」+「接続先」となっています。
# ip link add name ns1ovs1 type veth peer name ovs1ns1 # ip link add name ns2ovs1 type veth peer name ovs1ns2 # ip link add name ns3ovs2 type veth peer name ovs2ns3 # ip link add name ns4ovs2 type veth peer name ovs2ns4
OVSブリッジ同士を接続するvethを作成します。
# ip link add name ovs1ovs2 type veth peer name ovs2ovs1
vethの接続
namespaceとOVSブリッジをvethで接続します。
namespaceにvethを接続
# ip link set ns1ovs1 netns ns1 # ip link set ns2ovs1 netns ns2 # ip link set ns3ovs2 netns ns3 # ip link set ns4ovs2 netns ns4
OVSブリッジにvethを接続
ns1,ns3を接続するポートにはVLANタグ10を、ns2,ns4を接続するポートにはVLANタグ20を割り当てます。
# ovs-vsctl add-port ovs1 ovs1ns1 tag=10 # ovs-vsctl add-port ovs1 ovs1ns2 tag=20 # ovs-vsctl add-port ovs2 ovs2ns3 tag=10 # ovs-vsctl add-port ovs2 ovs2ns4 tag=20
OVSブリッジ同士を接続
# ovs-vsctl add-port ovs1 ovs1ovs2 # ovs-vsctl add-port ovs2 ovs2ovs1
デバイスをUP
OVSブリッジをUPします。
# ip link set ovs1 up # ip link set ovs2 up
OVSブリッジ同士を接続しているvethをUPします。
# ip link set ovs1ovs2 up # ip link set ovs2ovs1 up
OVSに接続したvethをUPします。
# ip link set ovs1ns1 up # ip link set ovs1ns2 up # ip link set ovs2ns3 up # ip link set ovs2ns4 up
namespaceに接続したvethをUPします。
# ip netns exec ns1 ip link set ns1ovs1 up # ip netns exec ns2 ip link set ns2ovs1 up # ip netns exec ns3 ip link set ns3ovs2 up # ip netns exec ns4 ip link set ns4ovs2 up
namespace内のループバックアドレスをUPします。
# ip netns exec ns1 ip link set lo up # ip netns exec ns2 ip link set lo up # ip netns exec ns3 ip link set lo up # ip netns exec ns4 ip link set lo up
IPアドレスの割当
namespaceに接続したvethにIPアドレスを割り当てます。
# ip netns exec ns1 ip addr add 192.168.122.10/24 dev ns1ovs1 # ip netns exec ns2 ip addr add 192.168.122.20/24 dev ns2ovs1 # ip netns exec ns3 ip addr add 192.168.122.30/24 dev ns3ovs2 # ip netns exec ns4 ip addr add 192.168.122.40/24 dev ns4ovs2
動作確認
同じVLANタグを持つインターフェース同士が通信できることを確認します。
tag=10を持つns1とns3の通信
# ip netns exec ns1 ping 192.168.122.30 # ip netns exec ns3 ping 192.168.122.10
tag=20を持つns2とns4の通信
# ip netns exec ns2 ping 192.168.122.40 # ip netns exec ns4 ping 192.168.122.20
異なるVLANタグを持つインターフェース同士が通信できないことを確認します。
ns1(tag=10)からns2,ns4(tag=20)への通信
# ip netns exec ns1 ping 192.168.122.20 # ip netns exec ns1 ping 192.168.122.40
ns2(tag=20)からns1,ns3(tag=10)への通信
# ip netns exec ns2 ping 192.168.122.10 # ip netns exec ns2 ping 192.168.122.30
■インターネットに接続
この章では、先ほど作ったnamespaceからインターネットにアクセスできるようにする設定を行います。
外部ネットワーク接続用ブリッジの作成
ホストのnic(ens3)に接続するためのブリッジを作成します。
# ip link add br-ex type bridge
ホストのnic(ens3)にbr-exを接続します。
# ip link set ens3 master br-ex
ホストのnic(ens3)に割り当てられているIPアドレスを削除します。
# ip addr del 192.168.122.6/24 dev ens3
OVSブリッジとbr-exの接続
OVSブリッジとbr-exを接続するためのvethを作成します。
# ip link add name tag10brex type veth peer name brextag10 # ip link add name tag20brex type veth peer name brextag20
OVSブリッジとbr-exを接続します。
# ip link set brextag10 master br-ex # ip link set brextag20 master br-ex # ovs-vsctl add-port ovs1 tag10brex tag=10 # ovs-vsctl add-port ovs1 tag20brex tag=20
デバイスをUP
br-exをUPします。
# ip link set br-ex up
OVSブリッジに接続したvethをUPします。
# ip link set tag10brex up # ip link set tag20brex up
br-exに接続したvethをUPします。
# ip link set brextag10 up # ip link set brextag20 up
ルーティングの設定
namespace内にデフォルトゲートウェイ(192.168.122.1)を設定します。
# ip netns exec ns1 ip route add default via 192.168.122.1 # ip netns exec ns2 ip route add default via 192.168.122.1 # ip netns exec ns3 ip route add default via 192.168.122.1 # ip netns exec ns4 ip route add default via 192.168.122.1
インターネットに接続できるか確認
それぞれのnamespaceからインターネットに接続できるか確認してみます。
# ip netns exec ns1 curl -kIL www.google.com # ip netns exec ns2 curl -kIL www.google.com # ip netns exec ns3 curl -kIL www.google.com # ip netns exec ns4 curl -kIL www.google.com
■後片付け
OVSブリッジを削除します。
# ovs-vsctl del-br ovs1 # ovs-vsctl del-br ovs2
ipコマンドで作った資材はリブートすると揮発します。
# reboot
Ubunu16.04でOpenVPNサーバーを作る
■概要
今回は図のような構成でVPNサーバーを立て、外のネットワークから、自宅のネットワークに安全に接続できるようにします。 サーバーOS : Ubuntu16.04 クライアントOS : Ubuntu16.04
■参考資料
■ルーターの設定
外部ネットワークから、自宅のネットワークへの接続を許可するためにグローバルIPの1194番ポート宛の通信をVPNサーバーの1194番ポート(192.168.10.11:1194)にフォワーディングする必要があります。
※設定の仕方はルーターによって異なりますが、私が使っているルーターだと下のような感じになりました。
■VPNサーバーの設定
OpenVPNのインストール
$ sudo -i # apt update # apt install -y openvpn easy-rsa
設定ファイルを準備します。
# mkdir /etc/openvpn/easy-rsa/ # cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/ # cd /etc/openvpn/easy-rsa
認証局の準備
今回は自己認証局を利用するので、VPNサーバー内で認証局証明書と認証局秘密鍵を作成します。
はじめに、認証局の所在地や組織名を決めます。(任意の値で良いです)
# vim vars
以下の内容を設定します。
export KEY_COUNTRY="JP" export KEY_PROVINCE="Saitama" export KEY_CITY="Niiza" export KEY_ORG="Example Company" export KEY_EMAIL="hoge@example.com" export KEY_OU="MyVPN" export KEY_NAME="MyVPN" export KEY_CN="MyVPN" export KEY_ALTNAMES="MyVPN"
環境変数を読み込み、認証局証明書(ca.crt)、認証局秘密鍵(ca.key)作成します。
(/etc/openvpn/easy-rsa/keysにca.crtとca.keyが生成されます。)
# source vars # ./clean-all # ./build-ca
./build-caを実行するといくつか質問されますが、すべてEnterを押してください。
Generating a 2048 bit RSA private key (中略) Country Name (2 letter code) [JP]: ★Enter State or Province Name (full name) [Saitama]: ★Enter Locality Name (eg, city) [Niiza]: ★Enter Organization Name (eg, company) [Example Company]: ★Enter Organizational Unit Name (eg, section) [MyVPN]: ★Enter Common Name (eg, your name or your server's hostname) [MyVPN]: ★Enter Name [MyVPN]: ★Enter Email Address [hoge@example.com]: ★Enter
サーバーで必要な鍵の作成
サーバー秘密鍵(server.key)、サーバー証明書(server.crt)を作成します。
(/etc/openvpn/easy-rsa/keysにserver.crtとserver.keyが生成されます。)
# ./build-key-server server
実行するといろいろ聞かれますが、すべてEnterを押してください。[y/n]の質問にはyと答えてください。
Generating a 2048 bit RSA private key (中略) Country Name (2 letter code) [JP]: ★Enter State or Province Name (full name) [Saitama]: ★Enter Locality Name (eg, city) [Niiza]: ★Enter Organization Name (eg, company) [Example Company]: ★Enter Organizational Unit Name (eg, section) [MyVPN]: ★Enter Common Name (eg, your name or your server's hostname) [server]: ★Enter Name [MyVPN]: ★Enter Email Address [hoge@example.com]: ★Enter Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: ★Enter An optional company name []: ★Enter (中略) Sign the certificate? [y/n]: ★y 1 out of 1 certificate requests certified, commit? [y/n] ★y Write out database with 1 new entries Data Base Updated
DH鍵を作成します。※時間がかかります
(/etc/openvpn/easy-rsa/keysにdh2048.pemが生成されます。)
# ./build-dh
tls-auth鍵を作成します。
(/etc/openvpn/easy-rsa/keysにta.keyが生成されます。)
# cd keys # openvpn --genkey --secret ta.key
サーバー証明書、サーバー秘密鍵、認証局証明書、DH鍵、tls-auth鍵を/etc/openvpnにコピーします。
# cp server.crt server.key ca.crt dh2048.pem ta.key /etc/openvpn
クライアントで必要な鍵の作成
クライアント秘密鍵(client.key)、クライアント証明書(client.crt)を作成します。
(/etc/openvpn/easy-rsa/keysにclient1.crtとclient1.keyが生成されます。)
# cd /etc/openvpn/easy-rsa # source vars # ./build-key client1
実行するといろいろ聞かれますが、すべてEnterを押してください。[y/n]の質問にはyと答えてください。
Generating a 2048 bit RSA private key (中略) Country Name (2 letter code) [JP]: ★Enter State or Province Name (full name) [Saitama]: ★Enter Locality Name (eg, city) [Niiza]: ★Enter Organization Name (eg, company) [Example Company]: ★Enter Organizational Unit Name (eg, section) [MyVPN]: ★Enter Common Name (eg, your name or your server's hostname) [server]: ★Enter Name [MyVPN]: ★Enter Email Address [hoge@example.com]: ★Enter Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: ★Enter An optional company name []: ★Enter (中略) Sign the certificate? [y/n]: ★y 1 out of 1 certificate requests certified, commit? [y/n] ★y Write out database with 1 new entries Data Base Updated
ここまで完了したら、/etc/openvpn/easy-rsa/keys配下のca.crt, ta.key, client1.key, client1.crtを安全な方法でクライアントとなる端末に転送してください。
コンフィグファイルの編集
# cd /etc/openvpn/ # vim /etc/openvpn/server.conf
下記を設定
port 1194 proto tcp dev tun ca ca.crt cert server.crt key server.key dh dh2048.pem server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt keepalive 10 120 mode server tls-server tls-auth ta.key 0 cipher AES-128-CBC comp-lzo user nobody group nogroup persist-key persist-tun status openvpn-status.log verb 3
その他設定
ipv4のフォワーディングを有効にします。
# echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf # sysctl -p
ログの初期設定を行います。
# journalctl --identifier ovpn-server
OpenVPNサーバー起動
openvpnサービスを起動します。
# systemctl start openvpn # systemctl start openvpn@server
サービスが正常に起動しているか確認します。
# systemctl status openvpn # systemctl status openvpn@server
トンネルデバイスが生成されているか確認します。
# ifconfig tun0
■VPNクライアントの設定
OpenVPNのインストール
$ sudo -i # apt update # apt install -y openvpn
先ほどサーバーから転送したca.crt, ta.key, client1.crt, client1.keyを/etc/openvpn配下に配置します。
※下記パーミッションとなっていることを確認してください。
-rw-r--r-- 1 root root 1704 11月 3 19:19 ca.crt -rw-r--r-- 1 root root 5437 11月 3 22:09 client1.crt -rw------- 1 root root 1704 11月 3 22:09 client1.key -rw------- 1 root root 636 11月 3 21:42 ta.key
コンフィグファイルの編集
# cd /etc/openvpn/ # vim /etc/openvpn/client.conf
下記を設定
client dev tun proto tcp remote xx.xx.xx.xx 1194 resolv-retry infinite nobind user nobody group nogroup persist-key persist-tun ca ca.crt cert client1.crt key client1.key remote-cert-tls server tls-auth ta.key 1 cipher AES-128-CBC comp-lzo verb 3
※xx.xx.xx.xxにはVPNサーバーがあるネットワークのグローバルIPを設定してください。
グローバルIPを調べるにはVPNサーバーで下記コマンドを実行してください。
$ curl inet-ip.info
OpenVPNの起動
※VPNサーバーとは異なるネットワークで起動してください。 openvpnを起動します。
# systemctl start openvpn # systemctl start openvpn@client
サービスが正常に起動しているか確認します。
# systemctl status openvpn # systemctl status openvpn@client
トンネルデバイスが生成されているか確認します。
$ ifconfig tun0
pign 10.8.0.1
■おまけ
上記の設定だと、VPNサーバー以外のノードにアクセスするには、一旦VPNサーバーにログインしたあとにアクセスしなければいけません。 以下の設定に変更すると、クライアントから、VPNサーバー以外のノードに直接アクセスできるようになります。
サーバー側の設定
サーバー側の設定ファイルを下記のように変更します。
# vim /etc/openvpn/server.conf
port 1194 proto udp dev tun ca ca.crt cert server.crt key server.key dh dh2048.pem server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt push "route 192.168.10.0 255.255.255.0" push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 192.168.10.1" keepalive 10 120 mode server tls-server tls-auth ta.key 0 cipher AES-128-CBC comp-lzo user nobody group nogroup persist-key persist-tun status openvpn-status.log verb 3 fragment 1280 mssfix 1280 link-mtu 1400
IPマスカレードの設定を行います。※この設定は再起動すると揮発します。
下記はソースアドレスが10.8.0.0/24で、eth0(vpnで直接繋ぎたいセグメント)を通過するパケットのソースアドレスをeth0に設定されているアドレスに書き換える設定です。 これによって、vpnクライアントから内部ネットワークへのパケットはvpnサーバーを経由してクライアント返ってくるようになります。
# iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
openvpnサービスを起動します。
# systemctl start openvpn # systemctl start openvpn@server
サービスが正常に起動しているか確認します。
# systemctl status openvpn # systemctl status openvpn@server
トンネルデバイスが生成されているか確認します。
# ifconfig tun0
クライアント側の設定
サーバー側の設定ファイルを下記のように変更します。
※xx.xx.xx.xxにはVPNサーバーがあるネットワークのグローバルIPを設定してください。
# vim /etc/openvpn/client.conf
client proto udp dev tun remote xx.xx.xx.xx 1194 resolv-retry infinite nobind user nobody group nogroup persist-key persist-tun ca ca.crt cert client1.crt key client1.key ns-cert-type server remote-cert-tls server tls-auth ta.key 1 cipher AES-128-CBC comp-lzo verb 3 fragment 1280 mssfix 1280 link-mtu 1400
※下記はVPNサーバーとは異なるネットワークで行ってください。
openvpnを起動します。
# systemctl start openvpn # systemctl start openvpn@client
サービスが正常に起動しているか確認します。
# systemctl status openvpn # systemctl status openvpn@client
トンネルデバイスが生成されているか確認します。
$ ifconfig tun0
pign 192.168.10.11
pign 192.168.10.12
仮想ディスクでLVMの操作をしてみる
今回は、ファイルを仮想ディスク(ブロックデバイス)化し、LVMの作成、拡張、削除などを行う。 OS : Ubuntu16.04
■準備
$ sudo -i # mkdir /tmp/lvm_test # cd /tmp/lvm_test
■仮想ディスクの作成
ブロックデバイスにするファイルを作成する。
# dd if=/dev/zero of=disk.img bs=1M count=1200
作成したdisk.imgを空いているループバックデバイスに割り当てる
# losetup -f disk.img
確認
★disk.imgにループバックデバイスが割り当てられているか確認 # losetup -l NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE /dev/loop0 0 0 0 0 /tmp/lvm_test/disk.img
ディスクラベルを作成
# parted -s -a optimal /dev/loop0 mklabel gpt
パーティションを作成。
今回は基本パーティションを3つ作成する。
# parted -s -a optimal /dev/loop0 mkpart primary 0% 30% # parted -s -a optimal /dev/loop0 mkpart primary 30% 60% # parted -s -a optimal /dev/loop0 mkpart primary 60% 100%
各パーティションのディスクフォーマットをlinux lvmに設定する。
# parted -s -a optimal /dev/loop0 set 1 lvm on # parted -s -a optimal /dev/loop0 set 2 lvm on # parted -s -a optimal /dev/loop0 set 3 lvm on
確認
★フラグlvmの基本パーティションが3つ作成されている。 # parted /dev/loop0 p モデル: Loopback デバイス (loopback) ディスク /dev/loop0: 1258MB セクタサイズ (論理/物理): 512B/512B パーティションテーブル: gpt ディスクフラグ: 番号 開始 終了 サイズ ファイルシステム 名前 フラグ 1 1049kB 377MB 376MB primary lvm 2 377MB 755MB 377MB primary lvm 3 755MB 1257MB 502MB primary lvm ★作成されたパーティションと同数の仮想デバイスファイルが生成されている。 # lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 119.2G 0 disk ├─sda1 8:1 0 487M 0 part /boot ├─sda2 8:2 0 1K 0 part └─sda5 8:5 0 118.8G 0 part ├─ubuntu--vg-root 252:0 0 114.9G 0 lvm / └─ubuntu--vg-swap_1 252:1 0 3.9G 0 lvm [SWAP] loop0 7:0 0 1.2G 0 loop ├─loop0p1 259:0 0 359M 0 loop ├─loop0p2 259:1 0 360M 0 loop └─loop0p3 259:2 0 479M 0 loop
■LVMの作成
LVMの作成は下の様な手順で行う [PVの作成]->[PVをVGに登録]->[VGからLVを作成]->[LVをマウント]
PV(フィジカルボリューム)の作成
/dev/loop0p1と/dev/loop0p2をPVとして登録する
# pvcreate /dev/loop0p1 /dev/loop0p2
確認
★/dev/loop0p1と/dev/loop0p2がPVに登録されている。 # pvdisplay "/dev/loop0p1" is a new physical volume of "359.00 MiB" --- NEW Physical volume --- PV Name /dev/loop0p1 VG Name PV Size 359.00 MiB Allocatable NO PE Size 0 Total PE 0 Free PE 0 Allocated PE 0 PV UUID xihABl-WX3v-1JYW-lV4v-EL4A-P8VK-fqkrts "/dev/loop0p2" is a new physical volume of "360.00 MiB" --- NEW Physical volume --- PV Name /dev/loop0p2 VG Name PV Size 360.00 MiB Allocatable NO PE Size 0 Total PE 0 Free PE 0 Allocated PE 0 PV UUID 74Pt3v-oXmk-RGyx-ynEk-VyAY-5aRZ-L31j0M
VG(ボリュームグループ)の作成
先ほど作成したPVをtest_vgという名前のVGに登録する。
# vgcreate test_vg /dev/loop0p1 /dev/loop0p2
確認
★test_vgという新しいVGが作成されている。 vgdisplay --- Volume group --- VG Name test_vg System ID Format lvm2 Metadata Areas 2 Metadata Sequence No 1 VG Access read/write VG Status resizable MAX LV 0 Cur LV 0 Open LV 0 Max PV 0 Cur PV 2 Act PV 2 VG Size 712.00 MiB PE Size 4.00 MiB Total PE 178 Alloc PE / Size 0 / 0 Free PE / Size 178 / 712.00 MiB VG UUID Qapao3-sI8J-1TFN-5lFW-HFlN-P3fJ-A9QU7k ★PVを確認してもtest_vgに登録されたことがわかる。 # pvdisplay --- Physical volume --- PV Name /dev/loop0p1 VG Name test_vg PV Size 359.00 MiB / not usable 3.00 MiB Allocatable yes PE Size 4.00 MiB Total PE 89 Free PE 89 Allocated PE 0 PV UUID xihABl-WX3v-1JYW-lV4v-EL4A-P8VK-fqkrts --- Physical volume --- PV Name /dev/loop0p2 VG Name test_vg PV Size 360.00 MiB / not usable 4.00 MiB Allocatable yes PE Size 4.00 MiB Total PE 89 Free PE 89 Allocated PE 0 PV UUID 74Pt3v-oXmk-RGyx-ynEk-VyAY-5aRZ-L31j0M
LV(ロジカルボリューム)を作成する
先ほど作成したtest_vgからtest_lvというロジカルボリュームを切り出す。
# lvcreate -L 600M -n test_lv test_vg
確認
★ロジカルボリュームを作成すると、/dev/<VG名>/<LV名>というデバイスマッパー生成される。 # lvdisplay --- Logical volume --- LV Path /dev/test_vg/test_lv LV Name test_lv VG Name test_vg LV UUID LFYF2y-S49k-jrdn-pwaY-jLAs-qlqE-mtnJwk LV Write Access read/write LV Creation host, time dynabook, 2016-10-12 08:29:34 +0900 LV Status available # open 0 LV Size 600.00 MiB Current LE 150 Segments 2 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 252:2
マウント
先ほど作成したLVのファイルシステムをext4にフォーマットする。
# mkfs.ext4 /dev/test_vg/test_lv
マウント
# mount -t ext4 /dev/test_vg/test_lv /mnt/work-mido/lvm/
確認
★/mnt/work-mido/lvmに/dev/test_vg/test_lvがマウントされている # df -Th Filesystem Type Size Used Avail Use% Mounted on udev devtmpfs 1.9G 0 1.9G 0% /dev tmpfs tmpfs 385M 6.2M 379M 2% /run /dev/mapper/ubuntu--vg-root ext4 113G 55G 53G 51% / tmpfs tmpfs 1.9G 316K 1.9G 1% /dev/shm tmpfs tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup /dev/sda1 ext2 472M 155M 293M 35% /boot cgmfs tmpfs 100K 0 100K 0% /run/cgmanager/fs tmpfs tmpfs 385M 60K 385M 1% /run/user/1000 /dev/mapper/test_vg-test_lv ext4 575M 468K 533M 1% /mnt/work-mido/lvm
アンマウント
# umount /mnt/work-mido/lvm
■VGとLVの拡張
/dev/loop0p3を新たにtest_vgに登録し、test_lvを900MBに拡張する。
/dev/loop0p3をPVに登録する
# pvcreate /dev/loop0p3
test_vgに/dev/loop0p3を追加する
# vgextend test_vg /dev/loop0p3
test_lvを拡張する
# lvextend -L 900M /dev/test_vg/test_lv
■LVの縮小
test_lvを300MBに縮小する。
ファイルシステムのチェックを行う。
# e2fsck -f /dev/test_vg/test_lv
ファイルシステムを300MBに縮小する
# resize2fs /dev/test_vg/test_lv 300M
test_lvを縮小する。
# lvreduce -L 300M /dev/test_vg/test_lv
■VGの縮小
test_vgから/dev/loop0p3を削除する。
# vgreduce test_vg /dev/loop0p3
■PVの削除
/dev/loop0p3のPVとしての登録を解除する。
# pvremove /dev/loop0p3
■LVの削除
test_lvを削除する。
# lvremove /dev/test_vg/test_lv
■VGの削除
test_vgを削除する。
# vgremove test_vg
■後片付け
# pvremove /dev/loop0p1 /dev/loop0p2 # losetup -d /dev/loop0 # rm disk.img
仮想ディスクでパーティションの作成とマウント
今回は、ファイルを仮想ディスク(ブロックデバイス)化し、パーティションとファイルシステムを作成する。(おまけでマウントまで行う)
OSはUbuntu16.04
準備
$ sudo -i # mkdir /tmp/sample # cd /tmp/sample
仮想ディスクを作成する
仮想ディスクとなるファイルdisk.imgを作成し、ddコマンドで1000MBまでファイルをゼロ埋め。
# touch disk.img # dd if=/dev/zero of=disk.img bs=1M count=1000
先ほど作成したdisk.imgをループバックデバイスとして登録する。
# losetup /dev/loop0 disk.img
ループバックデバイスがブロックデバイスとして認識されているか確認。
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 119.2G 0 disk ├─sda1 8:1 0 487M 0 part /boot ├─sda2 8:2 0 1K 0 part └─sda5 8:5 0 118.8G 0 part ├─ubuntu--vg-root 252:0 0 114.9G 0 lvm / └─ubuntu--vg-swap_1 252:1 0 3.9G 0 lvm [SWAP] loop0 7:0 0 1000M 0 loop ★認識されている
パーティションを作成する
先ほど作成したループバックデバイス(/dev/loop0)にディスクラベルを作成する。(今回はmsdos)
ディスクサイズが2TBを超える場合は、ディスクラベルにgptを設定する。
# parted -s -a optimal /dev/loop0 mklabel msdos
続いてパーティションを作成する。今回は基本パーティションを3つ作成。
# parted -s -a optimal /dev/loop0 mkpart primary 0% 30% # parted -s -a optimal /dev/loop0 mkpart primary 30 60% # parted -s -a optimal /dev/loop0 mkpart primary 60% 100%
パーティションが作成されているか確認する。
# parted /dev/loop0 p モデル: Loopback デバイス (loopback) ディスク /dev/loop0: 1049MB セクタサイズ (論理/物理): 512B/512B パーティションテーブル: msdos ★ディスクラベルはmsdos ディスクフラグ: 番号 開始 終了 サイズ タイプ ファイルシステム フラグ 1 1049kB 315MB 314MB primary ★0%-30%までの基本パーティション 2 315MB 629MB 315MB primary ★30%-60%までの基本パーティション 3 629MB 1049MB 419MB primary ★60%-100%までの基本パーティション
パーティションを作成すると、ループバックデバイスにもパーティションに対応するデバイスが自動的に生成される。
# ls -alF /dev/loop0p* brw-rw---- 1 root disk 259, 0 10月 5 22:18 /dev/loop0p1 brw-rw---- 1 root disk 259, 1 10月 5 22:18 /dev/loop0p2 brw-rw---- 1 root disk 259, 2 10月 5 22:18 /dev/loop0p3
ファイルシステムを作成する。
ubuntu16.04のデフォルトのファイルシステムであるext4で各パーティションをフォーマットする。
# mkfs -t ext4 /dev/loop0p1 # mkfs -t ext4 /dev/loop0p2 # mkfs -t ext4 /dev/loop0p3
ファイルシステムができているか確認する。
# parted /dev/loop0 p モデル: Loopback デバイス (loopback) ディスク /dev/loop0: 1049MB セクタサイズ (論理/物理): 512B/512B パーティションテーブル: msdos ディスクフラグ: 番号 開始 終了 サイズ タイプ ファイルシステム フラグ 1 1049kB 315MB 314MB primary ext4 ★ext4で作成されている 2 315MB 629MB 315MB primary ext4 3 629MB 1049MB 419MB primary ext4
パーティションをマウント
マウント用のディレクトリを作成する。
# mkdir part{1,2,3}
# mount -t ext4 /dev/loop0p1 /tmp/sample/part1 # mount -t ext4 /dev/loop0p2 /tmp/sample/part2 # mount -t ext4 /dev/loop0p3 /tmp/sample/part3
マウントされているか確認する。
# df -Th Filesystem Type Size Used Avail Use% Mounted on udev devtmpfs 1.9G 0 1.9G 0% /dev tmpfs tmpfs 385M 6.2M 379M 2% /run /dev/mapper/ubuntu--vg-root ext4 113G 54G 54G 50% / tmpfs tmpfs 1.9G 4.8M 1.9G 1% /dev/shm tmpfs tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup /dev/sda1 ext2 472M 200M 249M 45% /boot cgmfs tmpfs 100K 0 100K 0% /run/cgmanager/fs tmpfs tmpfs 385M 76K 385M 1% /run/user/1000 /dev/loop0p1 ext4 282M 2.1M 261M 1% /tmp/sample/part1 ★マウントされている /dev/loop0p2 ext4 283M 2.1M 262M 1% /tmp/sample/part2 /dev/loop0p3 ext4 380M 2.3M 354M 1% /tmp/sample/part3
ということで、今回はこんなところで一通り終了。
後片付け
パーティションをアンマウントする。
# umount /tmp/sample/part1 # umount /tmp/sample/part2 # umount /tmp/sample/part3
ループバックデバイスを解除する。
# losetup -d /dev/loop0
確認
# losetup -l ★何も表示されなければうまく解除出来ている
virtualenvでPython3.5の隔離環境を作成する
今回はubuntu16.04にvirtualenvをインストールしてPython3.5の隔離環境を作成する。
よくやり方を忘れるので、、、
python3.5にpipをインストール
ルートユーザーになる
sudo -i
リポジトリを更新してpipをインストール
apt update apt install python3-pip
virtualenvをインストール
pipをアップデートしてvirtualenvをインストール
pip3 install --upgrade pip pip3 install virtualenv
virtualenvを使って隔離環境を作成する
~/myenvに隔離環境を作成
virtualenv -p /usr/bin/python3 ~/myenv
隔離環境をアクティベート
source ~/myenv/bin/activate
以後、Pythonインタープリタの起動や、Pythonスクリプトを実行、pipによるパッケージのインストールは、全て隔離環境のPythonで行われる。
確かめたい人は以下のコマンドでPythonのパスがどこにあるか見てみると良い。
which python
隔離環境の使用を終了するときは
deactivate
隔離環境を削除するときは
rm -r ~/myenv
Ubuntu15.04でpipでMatplotlibがインストールできない件
matplotlibのドキュメント(Installing — Matplotlib 1.4.3 documentation)にはこんな感じで書いてありました。
Linux : using your package manager
If you are on Linux, you might prefer to use your package manager. matplotlib is packaged for almost every major Linux distribution.
- Debian / Ubuntu : sudo apt-get install python-matplotlib
- Fedora / Redhat : sudo yum install python-matplotlib
Ubuntuでインストールするときはapt-get使おうねってことなんですが、ここで問題が、、、
この方法だと、どうやってもvirtualenv環境にはインストールできないですね。
pipでのインストール方法を探すと、ありました。さすがスタックオーバーフロー。
python - Pip install Matplotlib error with virtualenv - Stack Overflow
どうやら先に、libpng-devとlibjpeg8-devとlibfreetype6-devをapt-getでインストールしておくと、うまくいくみたいです。
:~$ sudo apt-get install libpng-dev libjpeg8-dev libfreetype6-dev
:~$ workon hoge
(hoge):~$pip3 install matplotlib
うまくインストール出来ました。
CodeKata第二問 : 素数判定 @Python3.4
今日は素数判定ということで、与えられた数字が素数かどうかを判定するプログラムを作って行きたいと思います。
例によって、いい書き方があれば教えてください。m(_ _)m
問題
与えられた数が素数であるかどうかを調べなさい。
また、与えられた数までの素数を列挙しなさい。
考え方
まず素数の定義は「1と対象となる数以外には約数がない正の整数」です。
ちなみに「1」は素数ではありません。
この時点で、「負の整数」、「0」、「1」、「2以外の偶数」は素数となりえません。
よって、上記の数が入力された場合は「素数ではない」と判断します。
上記以外の整数nに関しては、nを2~(n-1)までの数で順に割っていって、あまりが0になるパターンがあれば「素数ではない」、なければ「素数」というように判断していきます。
コード
def prime_num(n):
#n=2であったら「素数」
if n == 2:
return True
#nが2より小さい or 偶数であれば「素数ではない」
if (n < 2) or (n % 2 == 0):
return False
#nを2~(n-1)までの数で割り、あまりが0となるパターンがあれば「素数ではない」
for i in range(2,n):
if n % i == 0:
return False
#「if n % i == 0:」に引っかからずfor文が終われば「素数」
return True
if __name__ == "__main__":
for n in range(101): #1〜100までの数を素数判定する
print("{} {}".format(n,prime_num(n)))
解説
引数に取った数が素数であればTrue、素数でなければFalseを返す関数を作成しました。
1〜100までの数を素数判定し、順に出力していくコードはmainに記述しました。
今回は、考え方で書いた内容をそのままコードに起こした、という感じです。
ただ、偶数を判定するときに2を除外しておかないと、2をFalse と判定してしまうため、2のみ一番初めにif文で判定するようにしています。
あとは特筆すべきところは特にない気がします。
今回使用した要素
>>>"hello {}".format("world") #文字列の中の{}に引数に取った値を代入する
'hello world'
>>>for i in range(5):
... "{}".format(i)
...
'0'
'1'
'2'
'3'
'4'