20200721のLinuxに関する記事は5件です。

Linuxコマンド#3

Linuxコマンドの基礎3です。

リダイレクト

標準入出力先を変更する機能

[wataru@localhost testgo]$ ls -l > lstext.txt
# >記号を使用して、リダイレクトを行う
#今回の例でいうと、lsの結果をlstext.txtに保存する

[wataru@localhost testgo]$ ls -l
total 4
drwxrwxr-x. 2 wataru wataru  25 Jul  7 16:25 2020dir
-rw-rw-r--. 1 wataru wataru 225 Jul 15 04:47 lstext.txt
-rw-rw----. 1 wataru wataru   0 Jul  5 04:26 testtest.txt
-rw-rw-r--. 1 wataru wataru   0 Jul 11 01:55 work.txt

[wataru@localhost testgo]$ cat lstext.txt 
total 0
drwxrwxr-x. 2 wataru wataru 25 Jul  7 16:25 2020dir
-rw-rw-r--. 1 wataru wataru  0 Jul 15 04:47 lstext.txt
-rw-rw----. 1 wataru wataru  0 Jul  5 04:26 testtest.txt
-rw-rw-r--. 1 wataru wataru  0 Jul 11 01:55 work.txt

[wataru@localhost testgo]$ ls xxxxx 2> error.txt
#標準エラー出力のリダイレクトは2>記号を使用する
[wataru@localhost testgo]$ cat error.txt 
ls: cannot access 'xxxxx': No such file or directory
[wataru@localhost testgo]$ ls xxx >error2.txt  2>&1 
#標準出力と標準エラー出力をまとめるには、2>&1を使用する
#結果とエラーメッセージを合わせて1つのログファイルとしておくときに使用する
[wataru@localhost testgo]$ ls > co.txt
[wataru@localhost testgo]$ ls -F >> co.txt 
#>>記号を使用することで、ファイルに追記することが出来る

[wataru@localhost testgo]$ cat co.txt 
2020dir
co.txt
error2.txt
error.txt
lstext.txt
testtest.txt
work.txt
2020dir/
co.txt
error2.txt
error.txt
lstext.txt
testtest.txt
work.txt

パイプライン

コマンドの標準出力を別のコマンドの標準入力につなぐ

[wataru@localhost testgo]$ history | wc -l
#コマンド履歴を出力するhistoryコマンドの結果を
#行数を数えるwcコマンドで行数を出力する
729
[wataru@localhost testgo]$ history | head -n 10 
#headコマンドで上から10行目を出力する
    1  date
    2  exit
    3  date
    4  bash
    5  exit
    6  pwd
    7  ls -l
    8  cd Music
    9  ls -l
   10  date
[wataru@localhost testgo]$ history | tail -n 5 
#tailコマンドで末尾から5行出力する
  727  hostory
  728  hostory | wc -l
  729  history | wc -l
  730  history | head -n 10 
  731  history | tail -n 5 
[wataru@localhost testgo]$ history | tac
#tacコマンドで逆順に出力する
  732  history | tac
  731  history | tail -n 5 
  730  history | head -n 10 
  729  history | wc -l
  728  hostory | wc -l
  727  hostory

wcコマンド

バイト数、単語数、行数を数える

[wataru@localhost testgo]$ ls | wc
      7       7      69
#左から「行数」、「単語数」、「バイト数」を表している
#-l -w -cオプションで指定可能
[wataru@localhost testgo]$ ls
2020dir  co.txt  error2.txt  error.txt  lstext.txt  testtest.txt  work.txt

sortコマンド

行を並び替える

[wataru@localhost testgo]$ cat word.txt 
wan
aiueo
fgh
cde

[wataru@localhost testgo]$ sort word.txt 
#アルファベット順に並び替えられる
aiueo
cde
fgh
wan
[wataru@localhost testgo]$ cat sort.txt 
99999
4321
564
67
684
681
20
[wataru@localhost testgo]$ sort -n sort.txt 
#-nオプションを使用すると、数値順にソートする
20
67
564
681
684
4321
99999
[wataru@localhost testgo]$ sort -r word.txt 
#-rオプションを使用すると、逆順にソートする
wan
fgh
cde
aiueo

uniqコマンド

重複行を取り除く(連続した同じ内容の行を省く)

[wataru@localhost testgo]$ cat word.txt 
akira
tanaka
tanaka
sasaki
tanaka
akira
akira
yamamoto

[wataru@localhost testgo]$ uniq word.txt 
#連続した「tanaka」「akira」の重複行が省かれている
#一番先頭行の「akira」は省かれていない
akira
tanaka
sasaki
tanaka
akira
yamamoto
wataru@localhost testgo]$ sort word.txt | uniq
#sortコマンドをしてから、uniqコマンド実行すると全体から重複行が省かれる
akira
sasaki
tanaka
yamamoto
wataru@localhost testgo]$ sort word.txt | uniq -c
#-cオプションを使用すると、重複行をカウントする
      1 
      3 akira
      1 sasaki
      3 tanaka
      1 yamamoto

cutコマンド

入力の一部分を切り出す
cut -d <区切り文字> -f <フィールド番号> <ファイル名>

[wataru@localhost testgo]$ cat word.txt 
akira,124,459,root
tanaka,523,756,akira
tanaka,789,465,tanaka
sasaki,100,200,sasaki
tanaka,200,600,aida

[wataru@localhost testgo]$ cut -d , -f 2 word.txt 
#,(カンマ)で区切り、フィールド番号2を切り出している
124
523
789
100
200
[wataru@localhost testgo]$ cut -d , -f 2,4 word.txt 
#フィールド番号を複数指定することも可能
124,root
523,akira
789,tanaka
100,sasaki
200,aida

trコマンド

文字を変換、削除する
1文字単位の文字置換

wataru@localhost work]$ ls
gogodur  work.02.txt  work.04.txt  work.06.txt  work.08.txt
testgo   work.03.txt  work.05.txt  work.07.txt  work.09.txt
[wataru@localhost work]$ ls | tr a-z A-Z
#小文字a-zを大文字A-Zに変換
GOGODUR
TESTGO
WORK.02.TXT
WORK.03.TXT
WORK.04.TXT
WORK.05.TXT
WORK.06.TXT
WORK.07.TXT
WORK.08.TXT
WORK.09.TXT
[wataru@localhost work]$ ls | tr -d txt
#-dオプションを使用すると、文字の削除ができる
#今回では、txtを削除している
gogodur
esgo
work.02.
work.03.
work.04.
work.05.
work.06.
work.07.
work.08.
work.09.

tailコマンド

末尾部分を表示する

[wataru@localhost work]$ ls | tail -n 3
#-nオプションを使用すると、行数指定する
#headコマンドも同様
work.07.txt
work.08.txt
work.09.txt

diffコマンド

差分を表示する

[wataru@localhost work]$ diff work.02.txt work.04.txt 
#diff <比較元ファイル> <比較先ファイル>
3,4c3
#「3,4」1つ目のファイルの3、4行目を
#「3」2つ目のファイルの3行目に
#「c」変更
< 123445
< 
# < は削除された行
---
> 2345
# > は追加された行
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux の名前空間が共有されるとはどういうことなのか $ podman pod create --share namespace を通して理解する。

前回 podman での複数コンテナの連携のために pod の扱いについて調べていたら、 podman-pod-create コマンドの --share オプションによる「名前空間が共有される」とは具体的にどういう現象なのかよくわからなかったので、簡単なハンズオンで直感的に理解できるようにしてみました。

はじめに

この記事は読み終わる頃に以下のことが分かるようになるよう目指して書きました。

  • コンテナ技術の実現に利用されている、 Linux の名前空間とは何か。
  • 名前空間が共有 / 分離されるとは具体的にはどういう状況か。
  • Podman によるポッド作成時に共有 / 分離が指定可能な ipc, net, pid, user, uts の 5 種類の名前空間は何を管理しているのか。

--share namespace とは

podman pod create コマンドでポッドを作成する際に使えるオプションの一つです。
役割と書式については、libpod リポジトリの説明によるとこうです。

--share=namespace

A comma delimited list of kernel namespaces to share. If none or "" is specified, no namespaces will be shared. The namespaces to choose from are ipc, net, pid, user, uts.

  • ポッド内で共有する名前空間を指定するためのオプション。
  • コンマ区切りのリストで複数指定。
  • none か、空集合が指定された場合何も共有されない。
  • ipc, net, ipd, user, uts の 5 つの名前空間から指定可能。

あー、なるほど。完全に理解しました。過不足ない説明ですが、理解するにはいくらかの前提知識が必要そうです。

そもそも名前空間とは

おばあちゃんが言っていた。何かを調べるときは必ず一次ソースから見ろと。
namespaces の man ページ によると以下の通りです。

名前空間は、 グローバルシステムリソースを抽象化層で覆うことで、 名前空間内のプロセスに対して、 自分たちが専用の分離されたグローバルリソースを持っているかのように見せる仕組みである。 グローバルリソースへの変更は、 名前空間のメンバーである他のプロセスには見えるが、 それ以外のプロセスには見えない。 名前空間の一つの利用方法はコンテナーの実装である。

ふ、ふーん。そういうことだったんですね。いや知ってましたよ。本当ですよ!なら PID 名前空間を例に説明しますね!?

  • ホスト上のリソースは抽象化レイヤーで覆い隠されるため、コンテナ内のプロセスはホスト上で動作しているプロセスの PID が見えません。
  • コンテナのプロセスには、自分たちがホストから隔離されているという認識はなく、むしろシステム全体を占有していると思っています。
  • ホスト上に systemd が PID 1 で動作しているにも関わらず、コンテナ上で PID 1 で別のプロセスが動作できるのはプロセスが異なる PID 名前空間に属しているからです。

つまり、ある学校の同じクラス内にゆうた君が 二人いたら、呼ばれた時にどちらを指すか一意に定まらない ので困りますが、 二人のゆうた君が A 組と B 組に分かれて存在している分には衝突しない ということです。

名前空間の利用例

この仕組みを使って、プロセスだけではなく様々なリソースについてホストから切り離された空間を確保していくと……なんかハードウェアのエミュレーションをしているわけでもないのにホスト上で動作する 仮想マシンみたいなものが作れそう な予感がしませんか?別個のマシンかのように振る舞うのですから、例えば以下のような特長を持っていてもおかしくはないはず……というかそうではないとおかしいですよね。名前空間を分離によって、これらは実現できるはずです。

  • 独自の NIC, IP, ファイアウォール設定、ルーティングテーブル を持ち、ホストマシンをネットワーク上の他のマシンとして認識する。(ホストからの network namespace の分離。)
  • 独自のユーザ、ホストネームを持つ。(ホストからの user namespace, uts namespace の分離。)
  • 独自にプロセス同士が通信するための共有メモリを持つ。(ホストからの ipc namespace の分離。)

さて、もうお気づきかと思いますが 様々なリソースについてホストから切り離された空間内でプロセスを実行すること こそコンテナ技術の正体です。しかし、「ホストから切り離すのはともかく、なんでもかんでもコンテナ間でキッチリ分離していると複数のプロセスで連携したいときに不便だなあ」ということで、複数のコンテナ間で一部の名前空間を共有して便利に扱えるようにしたのがポッドです。

次の章からは、ある名前空間が共有されている時とそうでない時の違いについて、Podman でポッドを作成してポッド内のコンテナの振る舞いの違いを比較することで見ていきます。

network namespace

network namespace は NIC やルーティングテーブル、ファイアウォールのポリシー設定などのネットワークに関する情報を分離させるための仕組みです。

最初に OS 上に存在している network namespace を以下のコマンドで確認します。
何も出力されません。まだ network namespace が作られていないことを意味します。

# ip netns

--share net ポッドの場合

podman で network namespace を共有するポッド netshared を作成します。ホスト側の 8080 番から ポッドの 80 番へ転送するポートフォワーディングも設定します。
ポッド内では net1 という名前の Apache コンテナが動作しています。

# podman pod create --name netshared --share net -p 8080:80
# podman run --pod netshared --rm -d -name net1 httpd

インフラコンテナと httpd コンテナが作られていることが確認できます。
インフラコンテナはポッドと関連付けられている名前空間を保持するための、ポッド管理用コンテナです。常にスリープ状態にあり、基本的に何もしません。

# podman container ls -a
CONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS                         PORTS                 NAMES
6d320abc7fa5  docker.io/library/httpd:latest  httpd-foreground  41 seconds ago  Up 40 seconds ago              0.0.0.0:8080->80/tcp  net1
76630b31f5c6  k8s.gcr.io/pause:3.1                              51 seconds ago  Up 41 seconds ago              0.0.0.0:8080->80/tcp  d1d99b6ed720-infra

インフラコンテナと net1 コンテナの IP アドレスを調べてみます。
インフラコンテナには IP アドレス 10.88.0.83/16 が割り振られていますが、net1 コンテナにはありません。

# podman inspect d1d99b6ed720-infra | grep -E "^.*\"IPAddress" -A1
            "IPAddress": "10.88.0.83",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
# podman inspect net1  | grep -E "^.*\"IPAddress" -A1
            "IPAddress": "",
            "IPPrefixLen": 0,

ポッドを作成したところで、今一度 network namespace を確認してみます。
新しい network namespace が 1 つ作成されていることがわかります。

# ip netns
cni-07de2651-2761-c638-a1fd-2af594ad9503 (id: 0)

この network namespace は、先ほど作成したポッド netshared が利用しているものです。
この network namespace 上で ip a コマンドを実行すると、netshared の仮想 NIC の情報が返ってきます。

# ip netns exec cni-07de2651-2761-c638-a1fd-2af594ad9503 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
3: eth0@if85: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:71:25:ce:de:49 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.88.0.83/16 brd 10.88.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::71:25ff:fece:de49/64 scope link
       valid_lft forever preferred_lft forever

eth0@if8510.88.0.83/16 の IP アドレスを持っていますね。先ほど確認したインフラコンテナの IP と一致します。

ポートフォワーディングも機能するか確認してみます。

# curl localhost:8080
<html><body><h1>It works!</h1></body></html>

Apache のテストページが返ってきました。 Apache コンテナが IP アドレスを持っていなかったにも関わらず応答が返ってくるのは、Apache コンテナがインフラコンテナの仮想 NIC を共有しているためです。

--share none ポッドの場合

同じ要領で今度は 名前空間を何も共有しないポッドを作成します。ポートフォワーディングが 9090->80 になったことと、--share none になったこと以外特に変わったことはありません。

# podman pod create --name none --share none -p 9090:80
# podman run --pod none --rm -d --name none1 -d httpd
# podman start 55db2b908174-infra
# podman container ls -a
CONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS             PORTS                 NAMES
8b91672858a9  docker.io/library/httpd:latest  httpd-foreground  4 minutes ago   Up 4 minutes ago                         none1
f4069bf6aad1  k8s.gcr.io/pause:3.1                              4 minutes ago  Up 3 minutes ago   0.0.0.0:9090->80/tcp  55db2b908174-infra
6d320abc7fa5  docker.io/library/httpd:latest  httpd-foreground  10 minutes ago  Up 40 seconds ago              0.0.0.0:8080->80/tcp  net1
76630b31f5c6  k8s.gcr.io/pause:3.1                              10 minutes ago  Up 41 seconds ago              0.0.0.0:8080->80/tcp  d1d99b6ed720-infra

PORTS 列に着目すると、 netshared ポッドの時とは違い Apache コンテナに ポートフォワーディングの設定がありません。ポッド作成時に指定した -p オプションによるポートフォワーディングの設定は、実際にはインフラコンテナへのフォワーディング設定のようです。加えて、インフラコンテナと Apache コンテナの仮想 NIC が共有されていないため Apache コンテナにはポートフォワーディングされないようです。共有されていない時、Apache コンテナの仮想 NIC ってどうなっているんでしょう。

none ポッドに属するコンテナの IP を調べてみます。

# podman inspect 55db2b908174-infra | grep -E "^.*\"IPAddress" -A1
            "IPAddress": "10.88.0.85",
            "IPPrefixLen": 16,
# podman inspect none1 | grep -E "^.*\"IPAddress" -A1
            "IPAddress": "10.88.0.84",
            "IPPrefixLen": 16,

netshared ポッドではインフラコンテナのみが IP アドレスを持っていましたが、今度はどちらのコンテナも IP アドレスを持っています。Apache コンテナは独自の仮想 NIC を持っているようです。もしかして、ポッド内で network namespace が共有されない場合、コンテナが作られるたびに独自のネットワーク名前空間が増え続けるのでは?

ip netns で確認してみましょう。

# ip netns 
cni-209074d8-5a08-7f59-bb73-6b258c228cf4 (id: 2)
cni-dc45758c-a9e2-91a2-db2c-a0f3406b9568 (id: 1)
cni-07de2651-2761-c638-a1fd-2af594ad9503 (id: 0)

先ほどの netshared ポッド用の network namespace に加えて 2 つの network namespace が作成されています。

id: 1 の network namespace には末尾 84 のアドレスを持つ仮想 NIC が確認できます。これは none ポッドのインフラコンテナのものです。

id1
# ip netns exec cni-dc45758c-a9e2-91a2-db2c-a0f3406b9568 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
3: eth0@if86: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 7a:11:aa:8e:52:ef brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.88.0.84/16 brd 10.88.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::7811:aaff:fe8e:52ef/64 scope link
       valid_lft forever preferred_lft forever

id: 2 の network namespace には末尾 85 のアドレスを持つ仮想 NIC が確認できます。これは Apache を動作させている none1 コンテナのものです。

id2
# ip netns exec cni-209074d8-5a08-7f59-bb73-6b258c228cf4 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
3: eth0@if87: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether b2:93:94:3c:05:7e brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.88.0.85/16 brd 10.88.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::b093:94ff:fe3c:57e/64 scope link
       valid_lft forever preferred_lft forever

ポートフォワーディングの動作も確認します。
netshared ポッドと違い、localhost:9090 への curl で Apache から応答が返りません。スリープ状態にあるインフラコンテナへの curl となるからです。
そういう点で言えば確かに netshared ポッドで行った localhost:8080 への curl も同じインフラコンテナへの curl と言えますが、netshared ポッドはインフラコンテナと Apache コンテナが仮想 NIC を共有していたので Apache コンテナへリクエストが届いていました。まるで複数のコンテナが繋がって、 1 つの仮想マシンとして動作しているかのようですね。

なお、Apache が動作している none1(10.88.0.84) に直接 curl すると応答が返るので Apache 自体は動作しているようです。

# curl localhost:9090
curl: (7) Failed to connect to localhost port 9090: 接続を拒否されました
# curl 10.88.0.84
<html><body><h1>It works!</h1></body></html>
# curl 10.88.0.85
curl: (7) Failed to connect to 10.88.0.85 port 80: 接続を拒否されました

念のため確認しますが、 firewalld によって弾かれたものではなさそうです。

# firewall-cmd --list-all --zone=public | grep -E "^\s*ports"
  ports: 8080/tcp 9090/tcp

コンテナ間で network namespace が共有されない場合の挙動について確認できました。

uts namespace

ホスト名やNISドメイン名を分離する名前空間です。

UTS は Unix Time-sharing System(UNIX で採用されていた、一台のコンピュータを複数のユーザで扱うための仕組み)の略ですが、今はその意味は失われているようです。時間も特に関係ありません。

NIS は複数のコンピュータを一元管理するために用いられる仕組みで、NIS ドメインはその仕組み用の識別子です。
今回は hostname の分離について着目していきます。

--share uts ポッドの場合

uts namespace を共有するポッド utsshared を作成し、中に Apache コンテナ uts1 と CentOS7 コンテナ uts2 を作成します。

# podman pod create --name utsshared --share uts
# podman run -d --pod utsshared --name uts1 --rm httpd
# podman run -it -d --pod utsshared --name uts2 --rm centos:7

uts1 と uts2 のホスト名を表示します。ポッド名と同じ、utsshared が返りました。確かに uts namespace が共有されているようです。

# podman exec uts1 hostname
utsshared
# podman exec uts2 hostname
utsshared

--share none ポッドの場合

先ほど作成した none ポッドで同様の環境を作ってホスト名を表示させてみます。

# podman exec none1 hostname
8b91672858a9
# podman exec none2 hostname
692b66d45c4a

none1 と none2 のホスト名は自身のコンテナ ID と同じ内容でした。uts namespace は共有されていないと言えます。

ipc namespace

プロセス間通信 (Inter-Process Communication) の名前空間です。
ipc namespace が共有されているとプロセス間での通信が行えます。同じポッドに属さないコンテナ同士、およびコンテナ-ホスト間では通常分離されますが、同一ポッド内に属するコンテナ同士は ipc namespace を共有するためプロセス間通信が行えます。

同一ポッド内の IPC 通信のデモを行うためこちらのイメージをお借りしました。
https://github.com/allingeek/ch6_ipc/tree/e9fa9a13198903bebcd983bf88bcb75950823d85

allingeek/ch6_ipc
FROM ubuntu:latest
RUN apt-get update && apt-get -y install gcc libc-dev
COPY . /work/ipc
WORKDIR /work/ipc
RUN gcc -o ipc ipc.c -lrt
ENTRYPOINT ["./ipc"]

中に ipc という実行ファイルが入った Ubuntu イメージです。
ipc の実行時に -producer を引数にすると ランダムな数字メッセージと終了メッセージが送信されます。
ipc の実行時に -consumer を引数にすると -producer が出力したメッセージを受信し、標準出力へ表示します。

--share ipc ポッドの場合

例によって、 ipc namespace を共有したポッド ipcshared を作成し、中に -producer となる ipc1 と、-consumer となる ipc2 を作成します。

# podman pod create --name ipcshared --share ipc
# podman run -d --pod ipcshared --name ipc1 --entrypoint /work/ipc/ipc ch6_ipc -producer
# podman run -d --pod ipcshared --name ipc2 --entrypoint /work/ipc/ipc ch6_ipc -consumer

送受信が行えているか、ログファイルから確認します。

# podman logs --tail 5 ipc1 | tac
Produced: 86 
Produced: 86
Produced: 67
Produced: 2b 
Produced: b9 

# podman logs --tail 6 ipc2 | tac
Consumed: 86
Consumed: 86
Consumed: 67
Consumed: 2b
Consumed: b9
Consumed: done

producer と consumer が出力している数字が一致しています。送受信が正しく行えていることを確認できました。

--share none ポッドの場合

ipc namespace を共有していない none ポッドでも同様の手順を実行します。こちらは consumer がメッセージの受け取りに失敗しています。

# podman pod create --name none --share none
# podman run -d --pod ipcshared --name ipc1 --entrypoint /work/ipc/ipc ch6_ipc -producer
# podman run -d --pod ipcshared --name ipc2 --entrypoint /work/ipc/ipc ch6_ipc -consumer
# podman logs --tail 5 ipc_unshare1
Produced: 9c
Produced: 98
Produced: 53
Produced: b9
Produced: 45
# podman logs --tail 6 ipc_unshare2
Either the producer has not been started or maybe I cannot access the same memory...

ipc namespace の分離によってポッド内のプロセスが通信できなくなりました。

user namespace

UID や GID を分離させる名前空間です。
ドキュメントを見る感じこれもいじれそうだったのですが、未実装のようです。

# podman pod create --name usershared --share user
Error: unable to create pod: User sharing functionality not supported on pod level
# podman pod create --share help
Error: unable to create pod: Invalid kernel namespace to share: help. Options are: net, pid, ipc, uts or none

pid namespace

冒頭でも触れた、プロセス番号に関する名前空間です。

--share pid ポッドの場合

pid namespace が共有されたポッド pidshared を作成します。
Apache コンテナを pid1, MySQL コンテナを pid2, CentOS7 コンテナを pid3 とし、 pid3 の中に入ります。

# podman pod create --share pid --name pidshared
# podman run -d --pod pidshared --name pid1 --rm httpd
# podman run -d --pod pidshared --name pid2 --rm -e MYSQL_ROOT_PASSWORD=password mysql
# podman run -it --pod pidshared --name pid3 --rm centos:7 /bin/bash
[container_id /]#

プロセスを確認します。

[container_id /]# ps -ef
root         1     0  0 01:33 ?        00:00:00 /pause
root       114     0  0 01:44 ?        00:00:00 httpd -DFOREGROUND
bin        120   114  0 01:44 ?        00:00:00 httpd -DFOREGROUND
bin        121   114  0 01:44 ?        00:00:00 httpd -DFOREGROUND
bin        122   114  0 01:44 ?        00:00:00 httpd -DFOREGROUND
999        284     0  1 01:48 ?        00:00:02 mysqld
root       484     0  4 01:51 pts/0    00:00:00 /bin/bash
root       499   484  0 01:51 pts/0    00:00:00 ps -ef

他のコンテナで動作している httpd と mysqld のプロセスが見えます。

--share none ポッドの場合

none ポッドで同様の手順を実行します。

# podman pod create --name none
# podman run -d --pod none --name none1 --rm httpd
# podman run -d --pod none --name none2 --rm -e MYSQL_ROOT_PASSWORD=password mysql
# podman run -it --pod none --name none3 --rm centos:7 /bin/bash
[container_id /]#
[container_id /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0 12 02:02 pts/0    00:00:00 /bin/bash
root        14     1  0 02:02 pts/0    00:00:00 ps -ef

pid3 コンテナ内で動作しているプロセスしか見えません。pid namespace が共有されていないためですね。

さいごに

Podman によって作成されたポッドで、デフォルトで共有されている名前空間は net,uts,ipc の 3 つです。
よって、デフォルトのポッドは以下の特徴を持ちます。

  • ポッド内のコンテナはインフラコンテナと仮想 NIC を共有する。(network namespace の共有)
  • ポッド名と同じホスト名を持つ。(uts namespace の共有)
  • 同一ポッド上に存在するプロセス同士でプロセス間通信が可能。(ipc namespace の共有)
  • ポッド外のコンテナおよびホスト上に存在するユーザは見えない。(user namespace の分離)
  • ポッド外のコンテナおよびホスト上に存在するプロセスは見えない。(pid namespace の分離)

つまり、ポッド内のコンテナたちは、ポッドに属さないバラバラのコンテナ群とは違い ネットワーク的には同じマシン のように見え、プロセス間通信 (IPC) によるやり取りが可能 であるということです。1 つのコンテナでは 1 つのプロセスを動作させるべきという原則によって生じる不便を、一部の名前空間をコンテナ間で共有することで克服しているわけですね。1 コンテナ 1 プロセスの原則については、PID 1 問題や、コンテナを使い捨てる前提で運用した時に都合がいいとか色々理由はあるのですが、それを書くには余白が狭すぎるのでこのあたりで。

参考

IPC 通信のデモの際参考にさせていただきました。

Kubernetesによる同一Pod内コンテナのプロセス間通信
https://qiita.com/mamorita/items/15437a1dbcc00919fa4e

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ブートマネージャーの問題

ブートローダー

ブートローダは記憶装置内のカーネルをロードし、カーネルに制御を移す役割を果たします。
ブートローダは第一段階と第二段階に分かれています。
第一段階部分はMBR(Master Boot Record)に格納、第二段階部分は記憶装置内(HDD)の別の場所に格納されています。
第一段階のブートローダはMBRの先頭446バイトの領域にインストールされます。
→起動時に呼び出されて、OSを動かすプログラムなんだな。
/boot/grub/menu.lstに入ってる。
ディストリビューションによっては「/boot/grub/grub.conf」

例)「/dev/hda」にGRUBをインストールする場合

grub-install /dev/hda = 例)「/dev/hda」にGRUBをインストールする場合

GRUBのバージョンが0.9x系のものを「GRUB Legacy」、1.9以降のものを「GRUB2」と呼びます。
どちらのバージョンもインストールは、grub-installコマンドを利用します。

・GRUB2の場合
GRUB2の設定ファイルは「/boot/grub/grub.cfg」です。しかし、「/boot/grub/grub.cfg」ファイルを直接編集することはありません。設定内容は「/etc/default/grub」ファイルおよび「/etc/grub.d」ディレクトリ内のファイルに記述し、「grub-mkconfig」コマンドで設定内容を「/boot/grub/grub.cfg」ファイルに反映させます。

GRUB

名称未設定.pngokoo.png
ブートローダであるGRUBのバージョンが0.9x系のものを「GRUB Legacy」、1.9以降のものを「GRUB2」と呼びます。
パーティション番号は、GRUB Legacyは0から、GRUB2は1から数えるディスク番号はGRUB Legacy/GRUB2どちらでも0から数えます。

GRUBに代表されるブートローダはHDDの最初のセクタ(512バイト)にあるMBR(マスターブートレコード)に格納されています。MBRは以下のように使用する領域が決まっており、ブートローダは先頭の446バイトの領域に格納されています。

ルートパーティションを設定する。

GRUB2の場合、以下のようにして起動オプションを指定します。
grub> linux カーネルイメージ [オプション]

・init=/dev/sda2
initの代わりに指定コマンドを実行する起動オプションです
・root=/dev/sda2
rootパーティションを設定する。

systemdの起動時のターゲットを指定する

systemdが動作するシステムにおいて、起動時のターゲットを指定するカーネルパラメータは systemd.unit です。systemd.unit パラメータの値に起動時のターゲットを指定します。ターゲット名は .target を省略することができます。

起動中のカーネルから出力される情報を抑制したい

quietを使う。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CUTコマンドの使い方

動画

動画はこちらから(画像クリックでyoutubeへ)
head&tailの使い方

CUTコマンド

CSVやTSVなどデリミタで区切られたデータの特定の列を取り出したり出来るコマンド。

ユースケース

  • DBから取り出したテーブルデータのカラムを取り出したい。
  • DBに取り込むときに失敗したファイルの中身を見て確認したい。 →ぱっと思いつかず、基本DBになってますが、ほかのユースケースも結構ありそう。

構文

cut オプション ファイル名

覚えておきたいオプション

  • -f:取り出すカラムの番号を指定。ex :-f1,5(filedで覚える)
  • -d: フィールドのデリミタを指定する(delimiterで覚える)
  • --complement:-fで指定する番号以外のカラムのデータを取り出す。 (ほかにもありますが、覚えるのはこれだけで十分)

サンプルコマンド

  • cat sample.txt | cut -d' ' -f1,5 → sample.txtからスペースを区切り文字として1,5カラム目のデータを取り出す。
  • cut -d',' sample.txt -f1 → CSVファイルの1カラム目のデータを取り出す
  • cat sample.txt | grep 'a' | cut -d' ' -f1 → grepした結果から特定の列を絞り込む。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CUTコマンドの使い方(サンプルあり)

動画

動画はこちらから(画像クリックでyoutubeへ)
head&tailの使い方

CUTコマンド

CSVやTSVなどデリミタで区切られたデータの特定の列を取り出したり出来るコマンド。

ユースケース

  • DBから取り出したテーブルデータのカラムを取り出したい。
  • DBに取り込むときに失敗したファイルの中身を見て確認したい。 →ぱっと思いつかず、基本DBになってますが、ほかのユースケースも結構ありそう。

構文

cut オプション ファイル名

覚えておきたいオプション

  • -f:取り出すカラムの番号を指定。ex :-f1,5(filedで覚える)
  • -d: フィールドのデリミタを指定する(delimiterで覚える)
  • --complement:-fで指定する番号以外のカラムのデータを取り出す。 (ほかにもありますが、覚えるのはこれだけで十分)

サンプルコマンド

  • cat sample.txt | cut -d' ' -f1,5 → sample.txtからスペースを区切り文字として1,5カラム目のデータを取り出す。
  • cut -d',' sample.txt -f1 → CSVファイルの1カラム目のデータを取り出す
  • cat sample.txt | grep 'a' | cut -d' ' -f1 → grepした結果から特定の列を絞り込む。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む