- 投稿日:2020-07-21T20:40:25+09:00
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 hostorywcコマンド
バイト数、単語数、行数を数える
[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.txtsortコマンド
行を並び替える
[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 aiueouniqコマンド
重複行を取り除く(連続した同じ内容の行を省く)
[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 yamamotowataru@localhost testgo]$ sort word.txt | uniq #sortコマンドをしてから、uniqコマンド実行すると全体から重複行が省かれる akira sasaki tanaka yamamotowataru@localhost testgo]$ sort word.txt | uniq -c #-cオプションを使用すると、重複行をカウントする 1 3 akira 1 sasaki 3 tanaka 1 yamamotocutコマンド
入力の一部分を切り出す
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,aidatrコマンド
文字を変換、削除する
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.txtdiffコマンド
差分を表示する
[wataru@localhost work]$ diff work.02.txt work.04.txt #diff <比較元ファイル> <比較先ファイル> 3,4c3 #「3,4」1つ目のファイルの3、4行目を #「3」2つ目のファイルの3行目に #「c」変更 < 123445 < # < は削除された行 --- > 2345 # > は追加された行
- 投稿日:2020-07-21T16:05:40+09:00
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@if85
が10.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-infraPORTS 列に着目すると、 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 foreverid: 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:7uts1 と 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 692b66d45c4anone1 と none2 のホスト名は自身のコンテナ ID と同じ内容でした。uts namespace は共有されていないと言えます。
ipc namespace
プロセス間通信 (Inter-Process Communication) の名前空間です。
ipc namespace が共有されているとプロセス間での通信が行えます。同じポッドに属さないコンテナ同士、およびコンテナ-ホスト間では通常分離されますが、同一ポッド内に属するコンテナ同士は ipc namespace を共有するためプロセス間通信が行えます。同一ポッド内の IPC 通信のデモを行うためこちらのイメージをお借りしました。
https://github.com/allingeek/ch6_ipc/tree/e9fa9a13198903bebcd983bf88bcb75950823d85allingeek/ch6_ipcFROM 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: doneproducer と 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 nonepid 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 -efpid3 コンテナ内で動作しているプロセスしか見えません。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
- 投稿日:2020-07-21T10:18:09+09:00
ブートマネージャーの問題
ブートローダー
ブートローダは記憶装置内のカーネルをロードし、カーネルに制御を移す役割を果たします。
ブートローダは第一段階と第二段階に分かれています。
第一段階部分は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
ブートローダである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を使う。
- 投稿日:2020-07-21T00:11:36+09:00
CUTコマンドの使い方
動画
動画はこちらから(画像クリックでyoutubeへ)
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した結果から特定の列を絞り込む。
- 投稿日:2020-07-21T00:11:36+09:00
CUTコマンドの使い方(サンプルあり)
動画
動画はこちらから(画像クリックでyoutubeへ)
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した結果から特定の列を絞り込む。