tanke25616429のアウトプット

IT技術の基本を勉強したことをアウトプットします。Linux、Kubernetes、クラウド中心です。百番煎じくらいだけど誰かの役に立てばそれはそれでうれしい。

SSL/TLS

TLSの機能

TLSは2者間(以降はクライアントーサーバ間の通信として記載する)で安全に通信できることが目的である。TLSの機能は大きく以下の2つがある。

  • なりすましの防止
  • 通信の暗号化

それぞれの機能について詳しく記述する。

なりすましの防止

クライアントがサーバにアクセスする際に、そのサーバが本物かどうかを確認したい。サーバ側から見ると、自分が本物であることを証明したい。そこで、サーバ証明書と呼ばれる電子証明書をクライアントに提示し、自身が本物であることを証明する。

そのためには、

  1. アクセス先のサーバが本物であるとサーバ証明書によって証明されていること
  2. サーバ証明書自体の保証(出どころが確かなこと)

の両方が必要である。さらにブレイクダウンして記述する。

1. アクセス先のサーバが本物である証明

現実世界と異なり、コンピュータの世界ではデータは電子的にコピーがいくらでも作られる。したがって、現実の身分証明書等と異なり「原本の証明書を提示しているから相手が本物」という判断はできない。あるサーバ証明書の妥当性は、そのサーバ証明書が電子的に検証できることで示される必要がある。

サーバ証明書には、サーバ独自の(ほかのサーバとは異なる)署名がなされている。この署名は秘密鍵(クライアント側が知らない鍵)によって実現される。サーバ証明書を提示されたクライアントは公開鍵(誰でも持っている)によって検証できる。この検証が失敗した場合は、相手がなりすましの可能性がある。

TLSにおいて、あるサーバと別のサーバを区別するキーはドメイン名である。サーバ証明書ドメインが真正であることを保証する。

2. サーバ証明書自体の保証

サーバ証明書によってドメインが真正であるだけでなく、サーバ証明書自体が正しいことを保証する必要がある。それをする仕組みとしてPKIがある(参考記事参照)。電子証明書サーバ証明書を含む)では、電子署名とそれを検証するための公開鍵が含まれており、公開鍵は何らかのデータによって本人性が保証されているのだった(参考記事参照)。PKIにおいて、公開鍵の本人性はCA(Certificate Authority)と呼ばれる第三者電子署名によって保証される。

PKIでは信頼できる第三者*1サーバ証明書を発行する。サーバ証明書の発行者が前述したCAであり、具体的には、SymantecやGlobalSignなどの企業がそれにあたる。

サーバ証明書に付与されたCAの電子署名により、サーバの公開鍵がサーバ本人のものであることが示される*2

なお、こうしたCAにサーバ証明書の発行を依頼せず、サーバ自信が自分で発行した証明書を利用することもできる(いわゆる、オレオレ証明書、自己証明書)。ちなみに自己証明書をサーバ証明書として使っているWebサイトにアクセスすると、ブラウザから警告が出る。

通信の暗号化

クライアントからサーバに対しTLSでの通信をリクエストすると上述したようにサーバの真正性がクライアントによって確認されるが、同時にTLSのやり取りの中で通信を暗号化するための鍵の交換が行われる*3。この鍵はTLS通信を行うサーバとクライアントの2者しか知らない。この鍵で通信内容を暗号化することにより、盗聴を防ぐことができる。

自己証明書を用いた場合でも通信の暗号化は実現できる。

参考にしたもの

SSL/TLSの基本 - Qiita

電子署名の基礎知識 - Qiita

milestone-of-se.nesuke.com

関連記事

tanke25616429.hatenablog.com

tanke25616429.hatenablog.com

*1:免許証を発行するのは警視庁という「信頼できる」機関である。

*2:CAの電子署名が本物かどうかを確かめる仕組みは本記事では述べない。

*3:この鍵はTLSセッションごとに使い捨てであるはず、と思われるが明確には調べきれていない。

PKI

PKI

PKI(Public Key Infrastructure)とは、公開鍵暗号電子証明書*1(以下、証明書)を用いて安全に通信ができるようにする仕組みのこと

安全に通信を行うためには、まず通信相手が本物であることの保証が必要である。PKIにおける証明書は、現実世界の身分証明書と同じ役割を持つ。ここで、証明書そのものが信頼できない場合、意味がないので、証明書を信頼できる第三者(CA、Certificate Authority)が発行する。

f:id:tanke25616429:20200723115109p:plain
信頼できる第三者と身分証明(JPNICのサイトより引用)

参考にしたもの

PKIとは?|GMOグローバルサイン【公式】

インターネット10分講座 - JPNIC

デジタル証明書(電子証明書)とは - IT用語辞典 e-Words

OpenSSLコマンドの備忘録 - Qiita

関連記事

OpenSSLの仕組みとは?初歩から解説! | CodeCampus

*1:公開鍵証明書、デジタル証明書ともいう。

kubernetesのmanifestにおけるYAMLの配列、ハッシュについて

動機

kubernetesのmanifestファイルを書こうと思って、kubectl explainコマンドで調べるが、配列、ハッシュ周りの記法があやふやで間違えることがよくあった。具体的には

xxx: 
- yyy: YYY
  zzz: ZZZ

と書くべきか

xxx: 
- yyy: YYY
- zzz: ZZZ

と書くべきか

xxx: 
  yyy: YYY
  zzz: ZZZ

と書くべきかが迷うので整理する。

YAMLの配列とハッシュ

前提知識となるYAMLの構文を整理する。

配列

YAMLでは、インデントを揃えたうえで行頭に"- "(半角ハイフンスペース)をつけることで配列を表現する。

- aaa
- bbb
- ccc

この例は配列 [aaa bbb ccc] (Go風に書くと*1)と同値である。

念のため、ハッシュと比較する意味で配列をちゃんと定義しておく。配列とは、0から始まる連続する自然数をキーとするオブジェクトの列のこと。

ハッシュ

ハッシュは、文字列をキーとしたオブジェクトの列のこと。文字列連想配列とかマップとかも呼ばれる。キーとバリュー(値)のペアで構成される。 YAMLでのハッシュは、インデントを揃えたうえで「キー: 値」の形式で並べて表現する。

A: aaa
B: bbb
C: ccc

この例をGoのmap風に書くと、map[A: aaa B: bbb C: ccc] と同値である。

ネスト

ハッシュや配列はネストして入れ子構造にして使われることが多い。

ハッシュのネスト

半角スペースでインデントさせることでハッシュをネストさせる。

A: aaa
B:
  B1: bbb1
  B2: bbb2
C: ccc

この例の場合、Bというキーに対応するのは一個の値ではなく、

  B1: bbb1
  B2: bbb2

という、「キー: 値」のかたまりである。

配列のネスト

配列も半角スペースでインデントさせることでネストできる。

- aaa
-
  - bbb1
  - bbb2
- ccc

aaaの次の行のハイフンの後には何もないが、この要素に対応するのは一個の値ではなく

  - bbb1
  - bbb2

という配列である*2。すなわち[aaa [bbb1 bbb2] ccc]と同値である。

ハッシュと配列のネスト

ハッシュと配列のネストはどちらが外側に来るかで2通り考えられる。それぞれ示す。

ハッシュの中に配列

A: aaa
B:
- bbb1
- bbb2
C: ccc

この例ではBというキーに対応する値は、

- bbb1
- bbb2

という配列である。

配列の中にハッシュ

- aaa
-
  B1: bbb1
  B2: bbb2
- ccc

この例ではaaaの次の要素は、

  B1: bbb1
  B2: bbb2

というハッシュである。なお、ハイフンの次の行にハッシュを持ってこずにいきなりハイフンの後にハッシュを続けて書いてもよいことにYAMLの仕様上なっているため、以下の書き方ができる*3

- aaa
- B1: bbb1
  B2: bbb2
- ccc

kubernetesのmanifestにおける実例

前提知識であるYAMLの構文を踏まえ、kuberntestのmanifestの記載と照らし合わせる。

RoleBindingのmanifest

RoleBindingのmanifestをYAML形式で表示すると下記のようになる。

# kubectl get rolebindings.rbac.authorization.k8s.io -n kube-system kube-proxy -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding

(中略)

roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kube-proxy
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:bootstrappers:kubeadm:default-node-token

roleRef:はハッシュにおけるキーとなっており、それと対応する値が、

  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kube-proxy

というハッシュである。

subjects:もハッシュにおけるキーであるが、対応する値は配列である。この例だと配列には1つの要素だけがある。その要素に格納されている値が、

  apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:bootstrappers:kubeadm:default-node-token

というハッシュである。すなわち、ハッシュ-配列-ハッシュという入れ子になっている。わかりやすく書くと、

subjects: 
- 
  apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:bootstrappers:kubeadm:default-node-token

ということである。

kubectl explainコマンドで調べると、キーroleRefに対応する値が<Object>(オブジェクト)と書かれている。この場合のオブジェクトは単体の値もしくは、入れ子になったハッシュである。 一方、キーsubjectsに対応する値が<[]Object>(配列)と書かれている。キーに対応する値が配列かどうかは、[]があるかどうかでわかる。実行例を下記に示す。

# kubectl explain rolebindings
KIND:     RoleBinding
VERSION:  rbac.authorization.k8s.io/v1

(中略)

   roleRef      <Object> -required-
     RoleRef can reference a Role in the current namespace or a ClusterRole in
     the global namespace. If the RoleRef cannot be resolved, the Authorizer
     must return an error.

   subjects     <[]Object>
     Subjects holds references to the objects the role applies to.

キーsubjectsが配列を値に取るということがよりわかりやすいのは、複数のハッシュのかたまりを要素とする配列というケースである。

subjects: 
- 
  apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: hogehoge
- 
  apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: fugafuga

参考にしたもの

techplay.jp

プログラマーのための YAML 入門 (初級編)

teratail.com

*1:参考にしたサイトはRubyなのだが、Goを勉強中なのでそちらの書き方を例として挙げた。

*2:なお体感であるが、配列の中に配列のパターンのネストはkubernetesのmanifestでの出現頻度が高くない気がする。

*3:kubernetesのmanifestではかなり多い書き方である。

ファイルとストレージのマッピング

この記事で整理したいこと

別の記事(ファイルシステム - Knのアウトプット)で

ファイルシステムがないと、人間やアプリケーションはデータが実際に記録されているストレージ上の位置を指定してデータにアクセスしなくてはならない。ストレージ上の位置は意味も文脈もないただの番地であり扱いにくい。

と書いた。これについて、実際のデータがどのように記録され、ファイルとマッピングされているかを整理する。

ファイルとストレージのマッピング

ざっくりとは、ストレージ上のビット列をある一定の塊として扱い、その塊とファイルがマッピングされている、と理解しておけばよい。

上述の「ある一定の塊」も階層的にまとめられている。小さいほうから順に追っていく。

ビットとバイト

コンピュータで扱うデータの最小単位はビットである。情報はビットの集合体、すなわち1と0の2種類の数字の列、で表現される。8ビットをまとめて1バイトと呼ぶ。記憶装置の容量はビットではなくバイト数で表すことが多い。

ビット/バイトのストレージ上での表現方法

ストレージ上のデータの実体もビット列として記録されている。ビットの表現方法はストレージを構成する記憶装置により異なる。記憶装置の物理的な特性を利用して1と0の2状態を表現する。例えば、HDDであれば磁性体の磁荷の向き、SSDやメモリであれば素子内の電化の状態によって1か0かが変わる。記憶装置上の物理的に連続した8ビットが1バイトとして表現される。

記憶装置への入出力単位

記憶装置への入出力は1ビットや1バイトごとに行うのではない。入出力の性能が落ちないようにまとまった固定長のデータの塊ごとに行う。以下にHDDの場合の入出力単位について説明する。SSDの場合は全く異なる。

HDD

HDDにおいては、この固定長の単位をセクタと呼ぶ*1。昔のセクタのサイズは512バイトが主流だったが、現在は4096バイト(4KiB)が主流である。入出力対象のセクタは物理的なアドレスで指定する。指定方法は複数ある(CHS方式、LBA方式)*2

セクタとブロック

OSのファイルシステムから見た最小単位をブロックもしくはクラスタと呼ぶ*3。HDDにおいては、ブロック/クラスタはセクタをひとまとめにしたものとなる。セクタサイズとブロックサイズ/クラスタサイズが同一の場合は1対1にマッピングされる。

SSDの場合でもOS側から見ればブロックに対し入出力を行っている。ただし、OSから見たブロックとマッピングされる記憶装置側のデータの塊がセクタではない*4

まとめ

記憶装置上の固定長バイトのデータの塊であるセクタと、OSのファイルシステムから見たブロックがマッピングされている。ファイルはファイルシステムにより複数のブロックとマッピングされている。

f:id:tanke25616429:20200630003505p:plain
ビット列がファイルにマッピングされるまでの階層関係

本記事で記載しなかったこと

AFT、ボリューム、LVM、エクステント、SSDにおける入出力単位(ページやブロックの話)等、関連する内容はまだあるが、改めて別記事に切り出して記載することとする。

参考にしたもの

ビットとバイト|基本情報技術者講座

ビットとは - コトバンク

ストレージ 進化するSSD(Solid State Drive) - 富士通

ISO9660 その2 物理セクタ、論理セクタ、論理ブロック: せんべえ焼き、もしくはコースターメーカー

ブロック (データ) - Wikipedia

富士通 やさしい技術講座 磁気ディスク装置

ディスク装置とファイルシステム

ブロックアクセスとファイルアクセス

HDDのセクタサイズ~512セクタと4Kセクタ【パソコン購入術】

Quora なぜコンピュータは1と0しか理解できないのですか?

オペレーティングシステム: 講義案内 ※スライド6 「ファイルシステムAPIとメモリマップドファイル」

「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典 セクタ

セクターサイズとクラスタサイズ(ブロックサイズ)の違い, 不良セクタとfsck/chkdsk について│SEの道標

関連記事

tanke25616429.hatenablog.com

*1:ディスクセクタ、物理セクタ、ブロック、物理ブロックなどと呼ばれることもある

*2:CHS方式は磁気ディスクのどこにいるかをシリンダ、ヘッド、セクタの番号で一意に指定する。これだと記憶装置の種類や物理構造によって指定方法が異なってしまい不便だった。LBA方式は物理構造を気にせず、各セクタに通し番号を振る方式であり、前述の問題点を解消している。

*3:セクタをブロックと呼ぶこともあると別の脚注で書いている通り、ブロックという言葉は多義で使われる。そもそも、ブロックという言葉が一般的に固定長のデータの塊という意味と考えればいろいろな用語で使われるのはやむを得ない気はする。

*4:参考サイトによればSSDでもセクタを仮想的に提供できるらしい。

セクターサイズとクラスタサイズ(ブロックサイズ)の違い, 不良セクタとfsck/chkdsk について│SEの道標

SSD にはセクターという物理要素はありませんが、Advanced Format と同様、論理セクター(製品によっては仮想セクターと呼ぶ)を提供できますし、ものによっては設定でセクターサイズを変更できます。

コンピュータにおける記憶領域

執筆の動機

コンピュータの勉強をしているとデータの置き場所である記憶領域について、「XXへの入出力はYYに比べ遅い」「XXはYYに比べ安価」といった文章が出てくる。初学者からすると、同じような話が複数出てくるので混同しやすい。しかもそれらはたいてい別の文脈で現れるので「あのときのあれの話と同じだっけ? 違うっけ?」のようなことが起きる*1*2。そこで代表的なものを一覧して並べることでどのような概念があるかを明確にする。

記憶領域一覧

コンピュータの仕組みと照らし合わせながら登場人物を理解する。

  • メモリからCPUのレジスタへプログラムやデータを読み出し、レジスタに対し演算を行い、演算結果をメモリに書き込む
  • メモリアクセスを毎回することによる速度低下を防ぐため、CPU上にあるキャッシュメモリ上でデータを読み書きする
  • プログラムは電源オン時やプログラム実行時などに補助記憶装置(HDD/SSD等)から読み込まれ、メモリ上にロードされる

メモリはメインメモリや主記憶装置とも呼ぶ。キャッシュはCPUの種類によって、L1からL3まで存在する(L2までしかないものもある)。電源をオフした際に情報が残る(=不揮発性)のは補助記憶装置だけである。 共通的な傾向として、高くて速い、安くて遅い、という風にまずは理解しておけばよい。したがってコンピュータ上では安い記憶装置ほど大容量で搭載されている。

これまでの話をまとめると以下の通り。

f:id:tanke25616429:20200622010223p:plain
コンピュータにおける記憶領域一覧

参考にしたもの

www.youtube.com

kuina.ch

8vivid.net

*1:こういった、似てるけど違うもの、違っているけど共通点があるもの、などをしっかり意識すると理解が進むと筆者は考えている。メモリもメインメモリと言ったり、主記憶装置と言ったり、呼称もいろいろある。「違う呼び名で呼ばれているものが同じものか、違うものか」を理解するのが大事とも言い換えられる。

*2:HDDよりSSDのほうが速いけど高い、という話まであるのでさらに混乱する。

ファイルシステム

定義

ファイルとは

関連するデータを1つにまとめ、名前をつけて保存したもの

記憶媒体にデータを保存、読み込み、移動、削除などする際に、ファイルを一つのまとまりとして取り扱う。OSの一部であるファイルシステムによって管理される。

ファイルシステムとは

ストレージ上のデータを、ファイルという単位でまとめ、名前をつけて管理する機能*1

ファイルシステムはOSの機能として提供される。

ファイルシステムがあることによって、コンピュータを利用する人間やコンピュータ上で動作するアプリケーションがファイルパス(=ファイルの場所とファイル名の組み合わせ)*2という扱いやすい文字列でストレージ上のデータにアクセス(読み書き)できる。ファイルシステムがないと、人間やアプリケーションはデータが実際に記録されているストレージ上の位置を指定してデータにアクセスしなくてはならない。ストレージ上の位置は意味も文脈もないただの番地であり扱いにくい。ファイルパスは、意味のある(意味づけできる)ため扱いやすい。

参考にしたもの

e-words.jp

www.amazon.co.jp

*1:ファイルの定義を所与とするなら、単にファイルを管理する機能、となるがイメージがわきにくいのでこう書いた

*2:例えば、Linuxであれば/etc/passwd、WindowsであればC:\Windows\System32\drivers\etc\hosts

仮想化

仮想化とは

コンピュータリソースを物理的な構成とは異なる構成に見せて動作させること。

平たく言うと、サーバー、OS、ネットワーク、メモリ等のコンピュータリソースに対して以下を行うこと。

  • 1つのものを複数に見せる
  • 複数のものを1つに見せる
  • M個のものをN個に見せる

  • VLAN(1つのネットワークを複数のブロードキャストドメインに分割)
  • VSAN(複数のディスクを1つに見せる)
  • サーバ仮想化(1台の物理サーバ上に複数のサーバを動作させる)

記事を書いた動機

製品に関する記事や宣伝を読んでいると、「~~仮想化技術」のような言い方をしているが、製品によって違う仮想化を指していることがあってモヤモヤするときがある。なので「1つのものを複数に」パターンか「複数のものを1つに」パターンかを意識しながら読むと、仮想化技術に関する文章を読んでいて混乱しにくい。

参考にしたもの

sp.otsuka-shokai.co.jp