宮水の日記

宮水の日記

主に書評や資格取得について記事を書いています。

「SQL実践入門」を読みました

今月はSQL強化月間ということにして、「SQL実践入門」を読みました。

なぜ読んだのか

  • 普段Active Recordばかり使っていて、SQLに向き合ったことがなかったから。
  • 文法だけじゃなくてSQLの仕組みについてちょっと知りたいと思ったから。

この本で学べること

  • パフォーマンスの良いSQLの書き方、特に大量データを処理するSQLの性能向上の方法
  • データベース内部のアーキテクチャやストレージのようなハードウェアの特性まで含めた総合的な知識

本の概要

第1章:DBMSアーキテクチャ──この世にただ飯はあるか

第1章では、RDBの内部的な動作に関するモデルを理解し、SQLのパフォーマンスに関係する「バッファ」「オプティマイザ」などの概念を理解します。データベースは、その仕組みから「容量・永続性・データの整合性」と「速度」がトレードオフの関係になっていたり、SQLを実行可能な手続きに変換するために実行計画を作っていることがわかりました。

1章で出てきた単語

クエリ評価エンジンユーザーから受け取ったSQLを解釈し、どのような手順で記憶装置のデータへアクセスに行くか決定する。

バッファマネージャメモリ領域の使い方を管理する。ユーザとストレージとの間に割って入り、SQL文のディスクアクセスを減らす役割がある。

ディスク容量マネージャどこにどのようなデータを保存するかを管理し、それに対する読み出し/書き込みを制御する。

トランザクションマネージャとロックマネージャトランザクション同士をうまくデータの整合性を保ちながら実行させたり、データにロックをかけて待機する。

リカバリマネージャ定期的にバックアップを取得し、いざという時にデータを復旧する。

キャッシュユーザーとストレージの中間に位置することでデータの転送遅延を緩和するための機構

オプティマイザインデックスの有無、データの分散や偏りの度合い、DBMSの内部パラメータなどの条件を考慮して、選択可能な多くの実行計画を作成し、それらのコストを計算して、最も低コストな1つに絞り込みます。

LRU(LeastRecentlyUsed) 「参照される頻度が最も少ないものをキャッシュから追い出す」というアルゴリズム。逆に頻繁に参照されるデータが長くキャッシュに留められるため、全体としてのキャッシュヒット率が上昇する。

第2章:SQLの基礎──母国語を話すがごとく

この章では、SQLの基本構文を理解します。

基本の構文については、

  • SELECT句
  • WHERE句 / 複数のOR条件をまとめて書けるINを使った記述
  • GROUP BY句
  • 集計用の関数(COUNT、SUM、AVG、MAX、MIN)
  • HAVING句
  • ORDER BY句

そして、SELECT文をデータベースに保存できるビューという機能や、サブクエリについて解説されていました。

応用として、

  • CASE式
  • UNION(和集合)
  • INTERSECT(積集合)
  • EXCEPT(差集合)
  • ウィンドウ関数

について。

そして最後に INSERT、DELETE、UPDATE構文について解説されていました。意外とSQLの構文って少ないのですね。

第3章:SQLにおける条件分岐──文から式へ

この章では、CASE式がパフォーマンス改善で重要であることを学びます。CASE式で条件分岐を表現できればテーブルへのスキャンを大幅に減らすことができるケース、UNIONで愚直に書いた方がパフォーマンスがいいケースなど、実行計画を読み解くことで明らかにしていきます。

"文"ではなく"式ベース"でクエリを考える大切さを学びました✨

第4章:集約とカット──集合の世界

SQLの特徴的な考え方に、集合指向といって、行の「集合」単位でひとまとめにして記述するというものがあります。集約関数には、COUNT, SUM, AVG, MAX, MINなどがあります。これらは複数行を1行に集約する機能を持っている関数です。カットとは、母集合である元のテーブルを小さな部分集合に切り分けることを言います。この章では、集約関数とカットの効果的な使い方について学びます。手続き型言語だとループや分岐を使って記述しないといけない複雑な処理を、SQLの集約関数を使えばスッキリ簡単に書けるケースがあることがわかりました。

第5章:ループ──手続き型の呪縛

SQLの世界には、ループがありません。SQLの世界に手続き型言語のようにループを持ち込んで処理を書くとパフォーマンスが悪くなってしまうケースがあります。
SQLの世界でループを使うことのデメリットや、その代替となる手段を学びます。

第6章:結合──結合を制する者はSQLを制す

結合のアルゴリズムは大きく分けてNested Loops, Hash, Sort Mergeの3つがあります。この章では、この3つの結合アルゴリズムの実行計画を読み解き、RDBがどのように結合を最適化しているか学びます。ちなみに、この章を読んで初めてなぜ内部結合と外部結合が、なぜ「内部」と「外部」と呼ばれるのかわかりました。

第7章:サブクエリ──困難は分割するべきか

サブクエリとは、SQLの中で生成される一時的なテーブルです。サブクエリとテーブルは機能的観点から見ると違いはありませんが、パフォーマンスの観点から見ると大きな違いが存在します。

サブクエリの問題点は以下です。

  • 実体的なデータを保持していないので、アクセスするたびにデータを作る必要があり、実行コストがかかる。
  • 計算結果を保持するためにI/Oコストがかかる
  • 制約やインデックスのようなメタ情報が存在しないため、最適化を受けられない。

この章では、サブクエリの問題点を解決する方法とサブクエリを使ったほうがパフォーマンスがいいケースを見ていきます。

第8章:SQLにおける順序──甦る手続き型

SQLは昔、順序を持った数を扱うための機能を持っていませんでした。ところが、実務においては適当な集合に対して連番を求められるケースが多くあります。そうした実務的な要望に応えるために、SQLにも順序と連番を扱うための機能が追加されました。

この章では、ウィンドウ関数や相関サブクエリを利用して行に対して連番を振る方法や、それを応用して中央値を求めたりします。

第9章:更新とデータモデル──盲目のスーパーソルジャー

SQL文を変えることよりも、データモデルを変更したほうがパフォーマンスがよくなるケースをみていきます。

第10章:インデックスを使いこなす──秀才の弱点

インデックスの利用方法について学びます。インデックスのアルゴリズムを知り、それを有効活用する方法、どのような条件下で性能向上が難しいかなどを取り上げています。

感想

当たり前ですが、SQLに関してかなり踏み入った話もあったので、難易度は高めの本でした。
それでも今までなんとなく文法だけ覚えて使っていたSQLでしたが、この本を読んで、データベース内部のアーキテクチャや、集合指向の概念、SQLで使われているアルゴリズムなどを知ることができました。SQLの中身を知ることで、アプリケーション側でもデータをどのように扱うのか意識できるので、より良い設計を勉強できるきっかけになったと思います。読んで良かったです。次はデータモデル設計の本を読んでみようと思います。

ここまでお読みいただきありがとうございました!

「nginx実践入門」を読みました

今回は、nginx実践入門を読みました。

なぜ読んだのか

仕事でSLO(※1)を設定した際に、nginxについて触れる機会があり、SREさんに色々教えていただきました。雰囲気でその場で理解して終わってしまったので、こちらの本を読むことにしました。

※1 SLO: サービスレベル目標のこと
cloud.google.com

対象読者

  • これからnginxを使ってみたい人
  • すでにnginxを使っているけどもっと使いこなしたい人

この本で学べること

  • nginxとは何か
  • 静的なサイトの構築
  • nginxとセキュリティ
  • Webアプリケーションサーバの構築
  • 大規模なコンテンツを配信する際の設定
  • nginxのメトリクスについて
  • Luaについて
  • OpenRestyについて

本の概要

第1章 nginxの概要とアーキテクチャ

nginxは、オープンソースのHTTPサーバです。

「HTTPサーバってなに?」って聞かれるとはっきり答えられなかったのでこちらを読みました。MicrosoftIIS(Internet Information Service)や オープンソースソフトウェアのApacheApache HTTP Server)などもHTTPサーバだそうです。

nginxは、他のHTTPサーバ同様、テキストや画像といった静的なコンテンツの配信、もしくはアプリケーションサーバへのリバースプロキシとして動作しますが、イベント駆動、I/O Multiplexing、ノンブロッキングI/O、非同期I/Oなどのテクニックを組み合わせることで、非常に少ないリソースで大量の接続を同時に処理できるのが強みです。

第2章 インストールと起動

nginxのインストール方法、起動方法、オプションなどの解説がありました。

第3章 基本設定

Webサーバの設定は、nginx.confに書きます。この章では、HTTPサーバに関する基本的な設定の書き方、nginx本体の動作に関する基本的な設定について説明があります。また、ディレクティブとコンテキストの概念を理解することで、設定のスコープの範囲を操ることができ、より複雑な設定ができることがわかりました。

第4章 静的なWebサイトの構築

4章では、本番環境に特化した設定を行います。locationディレクティブを使用して異なるURLごとに配信するファイルの指定をしたり、IPアドレスBasic認証によるアクセス制限、returnディレクティブを使って特定のステータスコードでエラーページを表示したりします。

第5章 安全かつ高速なHTTPSサーバの構築

5章では、nginxでHTTPSを利用するための設定方法や、Mozillaの運用セキュリティチームが公開している資料を元に、安全かつ高速なHTTPSを実現するためのポイントについて解説されています。

HTTPS通信にするメリットを本書から引用します。

HTTPSを利用することで、通信内容を暗号化し、盗聴、改ざんを防止するだけでなく正しいサーバかどうか認証することでなりすましを防ぐことができます。

Railsを使用する際に、gemのインストールでOpenSSLのバージョンでハマったことがあったんですが、これはTLSを実現するためのライブラリだったのですね)

第6章 Webアプリケーションサーバの構築

Webアプリケーションにおけるnginxの主な役割はリバースプロキシです。
※リバースプロキシとは、ユーザのリクエストを受け取りそれを上位サーバ(アップストリームサーバ)に転送する機能

この章では、Ruby on Railsを用いたアプリケーションサーバの構築も行なっています。
アプリケーションサーバにnginxを組み合わせると、重要な基本機能をアプリケーションからnginxに委譲することができ、静的ファイルを代わりに処理してくれたり、リクエストを効率よく捌いてくれることがわかりました。

第7章 大規模コンテンツ配信サーバの構築

大量の画像ファイルを配信するケースを想定し、多数のリクエストを処理するうえで注目すること、nginxの機能の解説がありました。負荷のボトルネックには、ファイルの読み込み/書き込み、ネットワークの帯域幅、ネットワークの物理的距離や品質などが挙げられます。これらのボトルネックには、キャッシュやロードバランサなどで対応していきます。nginxにも、キャッシュやロードバランサを設定する機能があるので、その解説がされていました。

第8章 Webサーバの運用とメトリクスモニタリング

ログファイルの取り扱い、メトリクスモニタリングについて解説されていました。

Fluentdによるログ収集基盤を構築すれば、Norikraのようなストリームプロセッシング以外に、TreasureData、GoogleBigQuery、AmazonRedshiftといった外部サービスによるデータ解析や、ElasticsearchとKibanaによるログの可視化も行えるそうです。

また、nginxのバイナリアップグレードにも触れられていました。こまめにアップグレードすることで、動作速度の改善やセキュリティの面の修正を得ることができます。

第9章 Luaによるnginxの拡張 ーEmbed Lua into nginx

nginxのサードパーティモジュールであるngx_luaについての章です。

ngx_luaについては、本書の以下の文を引用します。

ngx_luaはnginxをLuaで拡張するためのサードパーティモジュールです。nginxの主要なAPILuaから利用できるようになっているほか、Luaのコルーチンやnginxのノンブロッキングソケットとイベント駆動アーキテクチャを組み合わせることで、サブリクエストの実行や外部サーバプログラムとの通信処理をノンブロッキングで行うことが可能になっています。

第10章 OpenResty ーnginxベースのWebアプリケーションフレームワーク

最後は、OpenRestyについてです。

OpenRestyについては、本書の以下の文を引用します。

OpenRestyは、nginxに大量のサードパーティモジュール一式をバンドルしたWebアプリケーションフレームワークです。

nginxとngx_luaを基本ベースにmemcached、Redis、MySQLといった各種サーバソフトウェアと通信するためのドライバやJSONエンコード/デコードのためのモジュールなど、Webアプリケーション開発で必要となるモジュールを多数バンドルして簡単に利用できるようになっています。

感想

この本を読んで、nignxは大量の接続を同時に処理するのが得意なHTTPサーバであるということがわかりました。本書は、「実践入門」と書いてある通り、nginx.confに実際に設定を書きながら機能について学べる本でした👍 nginx.confに各種設定が書いてあることがわかったので、nginx documentationでディレクティブを検索すれば少しはファイルが読めるようになりそうです。反省点として、私の場合 nginxに入門する前に、HTTPサーバに入門しないといけませんでした。そのことがわかったのも収穫になりました。

以上です。ここまでお読みいただきありがとうございました!

NextAuthのsessionに任意のプロパティを追加する

簡単な個人開発のログインで、NextAuthを使用しました。

やりたいこと

sessionオブジェクトが用意されているのですが、デフォルトだと以下の値が参照できるようになっています。

session.user.name
session.user.email
session.user.image
session.expires

私のプロダクトでは、user.idを参照できるようにしたいです。

session.user.id

sessionオブジェクトにuser.idを追加する

[...nextauth].ts ファイルのoptions: callbacksに以下のように書き、要素を追加します。

// [...nextauth].ts

import NextAuth from 'next-auth'
  - 中略 - 

const options = {
  - 中略 - 
  callbacks: {
    async session(session, user) {
      session.user.id = user.sub
      return Promise.resolve(session)
    },
  }
}

型をつける

今のままだと参照した際に型エラーになってしまうので、型をつけます。
f:id:kattyan53:20210807183656p:plain

types/next-auth.d.ts を作成し、以下のように書きます。

declare module "next-auth" {
  interface Session {
    user: {
      id: string | null
    }
  }
}

エラーがなくなりました。
f:id:kattyan53:20210807184047p:plain

何をしたのか

ライブラリの中身を見てみると、デフォルトだとDefaultSession型が参照されます。

export interface DefaultSession extends Record<string, unknown> {
  user?: {
    name?: string | null
    email?: string | null
    image?: string | null
  }
  expires?: string
}

export interface Session extends Record<string, unknown>, DefaultSession {}

今回は、独自に定義したSession型を参照するようにしました。

declare module "next-auth" {
  interface Session {
    user: {
      id: string | null
    }
  }
}

ハマったこと

デフォルトでは、Session型はDefaultSessionをextendsしています。

f:id:kattyan53:20210808040126p:plain


てっきり↓こんな感じで拡張されていると思っていたのですが、上記の型定義だとuser.idしか参照できません。

  export interface DefaultSession {
    user?: {
      name?: string | null
      email?: string | null
      image?: string | null
    }
    expires?: string
  }
  
  interface Session {
    user?: {
      id?: string | null
    }
  } 
   
  interface NewSession extends DefaultSession, Session {}
   
  const session: NewSession = {
    user: {
      name: 'a',
      email: 'b',
      id: 'a'
    }
  }
  
  // 参照できると思っていたけど、  session.user.idだけうまく参照できない。
  session.user.id
  session.user.name
  session.user.email
  session.user.image
  session.expires

NewSessionには以下のようなエラーが出ていました。

Interface 'NewSession' cannot simultaneously extend types 'DefaultSession' and 'Session'. Named property 'user' of types 'DefaultSession' and 'Session' are not identical.

ref: github.com

同じ名前のプロパティは継承できないんですね。変な勘違いをしていました。

以上です!

エンジニアが「独学大全」を読みました

f:id:kattyan53:20210614164831p:plain
今日は、「独学大全」を読みました。定期的に読み返したいなと思った部分をメモしました。

なぜ読んだのか

エンジニアって学ぶことがたくさんありますよね。「土日のうちに1冊 本を読んでから or ちょっと手元で動かしてみてからこのタスクに取り掛かりたい!」と思うことはしょっちゅうあります。また、常に新しい技術が出てきて「質問したいけど、わからないこともわからない」といったことが頻繁に起こります。今回は、「新しい技術をできるだけ効率よく学びたい!」というモチベーションでこの独学大全を読みました。

どんな本だった?

一言で言うと、巷に溢れかえっている勉強方法のテクニックがギュッとまとめてあり、そのテクニックを辞書のように読むことができる本です。

本のサブタイトルに、「55の技法」と書いてありますがその通り、独学に関するテクニックやフレームワークが55個紹介されています。最後の部では、これまで学んだ独学の技法を使って、国語、外国語、数学の3つのケースについて独学する事例を取り上げています。

個人的には、「目標へのモチベーションの保ち方」「情報の見つけ方」「情報の整理の仕方」「本の読み方」という点において読んで非常に良かったと思いました。もちろん何か新しいことを学びたい人に役立つテクニックも多く載っていましたが、特に「課題などでレポートを書く学生」に向いている本だと思いました。

どんな人に向いてる?

  • 新しいことを学びたい人
  • 学びたいことが決まっているけど、何から手をつけたらいいかわからない人
  • 学生
  • 課題でレポートを書いている人

本の概要

第1部 なぜ学ぶのかに立ち返ろう
継続は力なり。独学で一番難しいのは「続けること」であり、どうやったら続けられるのか、そのテクニックについて紹介されています。

目標遂行へのモチベーションの保ち方
  • 「どうしてそれを学びたいと思ったのか」強い動機を書き出し、それを定期的に見返して原点に立ち返る。
  • 「今の自分の現状と、学習した後にどうなっていたいか」を考え、具体的な目標に落とし込んでいき、学習ロードマップを作る。
やる気がないとき
  • やる気がなかったらとにかく「3行読む」「1分間だけ勉強する」
  • 小さい習慣から始める。その後本当に習慣にしたいことを始める。(例えば、本当の目標が英単語を一日30個覚えたい、だったら、まずは1日1個覚えることから始めてみる)
  • 人に宣言する。
  • 輪読会に参加する(当日までに読んでおき、感想を言い合うのがオススメ)
時間がないとき
  • 独学する時間がとれないと感じたら、理想の予定と実態の予定を書き出し、どうして時間がないのか分析する。
  • ポモドーロ・テクニックを使う。(25分間にセットし、作業を開始する→5分の休憩は作業に関係のないことをして過ごす(スマホSNS NG)4回ポモドーロをしたら、30分間休憩する。)


第2部 何を学べば良いかを見つけよう
全く知らない技術を学ぶとき、自分のレベルに合った技術書を探したり、同じ技術でも自分が求めていることが書いてあるのか見極めるのが難しかったりしますよね。
この部では、知らないことを探し求めるための技術、調べ物のスキルとノウハウ を学べます。
このブログでは紹介しませんが、図書館で調べ物をしてレポートを書かなければならない学生は絶対読んだ方がいい内容が盛りだくさんでした。

知りたいことの発見の仕方

① 取り組もうとしている分野や課題について、なんでもいいから思いつく限り書き出す
② 知っているものを四角で囲む
③ 調べたものを二重四角で囲む
④ 全体像を線で結んでいく
⑤ 気になったものに丸をつける ← これが学びたいことになる

何がわからないのかを整理するフレームワーク
  • hogeは何の一種か?
  • hogeは同じグループの中で他とどこが違うのか?
  • hogeを構成する部分を列挙すると?
  • hogeとは何か?
  • hogeの語源は?
  • hogeの反対は?
  • hogeを生じさせたものは?
  • hogeから生じたものは?
資料を探し出す
  • インターネットは役に立たない。検索キーワードを色々変えてみる。除外するキーワードも考える。
  • 下位概念、上位概念で探索を行う。(ヘミングウェイアメリカの文学者→英米文学者→文学者→人みたいな感じでどんどん抽象的な言葉、もしくは具体的な言葉で調べていく)
  • 文献を読んでいく。
  • 知っていることを書き出す→知らないことを問いに変換する→調査の過程を記録にとる→しつこく繰り返す
資料の整理

① 独学のテーマごとにマトリクスを作る
② 文献のタイトル、著者などを表の左端のますへ入力する
③ 目次から「見出し」を拾い出し、マスへ入力する
④ 必要なら各省の概略を追記する
⑤ 同じ/似た内容をマーキングしたり囲んでつないだりする
⑥ 文献を横断読みしながら気づいたことを抽出し、整理する

第3部 どのように学べば良いか知ろう
ここでは、本の読み方、暗記の仕方、わからない問題に対する対処法について学びます。特に本の読み方が色々あって非常に参考になりました。

本の読み方
  • 転読 ... ページに目を落としたまま、出来るだけ速くページをめくっていく。
  • 掬読 ... 読むべき部分だけを読む。
  • 問読 ... 文献の見出しを拾い出し、問いの形に変換する。(例えば、「マルサスの罠ってなに?」という問いにする)その後、要約を作る。
  • 限読 ... 読む本を決め、費やす時間をあらかじめ設定する。設定した時間内に読む。
  • 黙読 ... 声を出さずに文章を読む。速度、理解度、記憶という面で優れている。
  • 音読 ... 声を出して文章を読み上げる。学習者の身体に刻み込み、反射的・自動的に用いることができるようにする。
  • 指読 ... 今読んでいる箇所を指やペン先で指す。難しい文章を読むときにおすすめ。
  • 刻読 ... あらかじめざっと読み、全体の構成や概要を掴んでおく。必要なところに印を残しておく。印を残したところを辿っていく。
  • 段落要約 ... 段落ごとに1行にまとめていく。
「わからないルートマップ」で何がわからないのか整理する
  • 不明型のわからない ... わかる部分が全くないかほどんどない。

=> 解決法:部分に分ける→部分ごとの解釈を仮定する

  • 不定型のわからない ... 部分部分は理解できなくはないが、いろんな解釈がありすぎてどれが良いか決められない。

=> 解決法:全体の文脈を仮定する→部分それぞれの解釈を限定する

  • 不能型のわからない ... とりあえずどんな風に理解すればいいのか決まってきたが、まだ不整合や矛盾するところが残っていて首尾一貫した解釈ができていない状態。
難しい問題は...
  • まずは問題を解く→もう一度解いてみる→思考を実況中継しながら解く→誰かに説明する→自分に説明する

第4部 独学の「土台」を作ろう
これまで学んだ独学の道具を使って、国語、外国語、数学について独学する事例を取り上げています。

まとめ

今回は、「新しい技術をできるだけ効率よく学びたい!」というモチベーションでこの本を読みました。
第2部では、何から手をつけたらいいのか考える方法や、自分に合った適切な技術書を探し出す方法を学べました。
第3部では、特に限られた時間で効率よく技術書を読むヒントが得られました。

まずは学びたい技術ごとに学習ロードマップをスプレッドシートに書くところから初めてみようと思います。


以上です。ここまでお読みいただきありがとうございました!

「入門 Kubernetes」を読みました

f:id:kattyan53:20210525204403p:plain

入門 Kubernetesを読みました。

なぜ読んだのか

最近kubernetesの設定ファイルを触ることがあったんですが、コピペして雰囲気でやってしまったので、ちゃんと入門することにしました。全部読んで完全に理解するというよりは、読みながら仕事のコードでよく使う設定ファイルを読んでみようと思います。

対象読者

  • Kubernetes入門したい人
  • (ロードバランサやネットワークストレージの理解があるとより良い)
  • LinuxLinuxコンテナ、Dockerの経験があるとより良い)

この本で学べること

  • Kubernetesクラスタオーケストレータについて
  • 分散アプリケーションの開発、デリバリ、メンテナンスを改善するためにKubernetesのツールおよびAPIがどのように役立つのか

1章 Kubernetes入門

この章では、Kubernetesの利点について学びます。

Kubernetesとは

Kubernetesは、コンテナ化されたアプリケーションをデプロイするための、設定や管理を自動化・自律化するためのシステムのこと。

Kubernetesの利点① 開発速度を上げてくれる

理由① イミュータブルなインフラだから
 Kubernetesは、イミュータブルなインフラです。一度システム上で成果物を作成したら、ユーザによる更新があってもその成果物は変更されません。既存のシステムを更新する代わりに、全く新しいイメージに置き換えます。既存のイメージを変更せずに新しいイメージを構築すると、古いイメージを残しておけるので、ロールバックが簡単になります。

理由② 宣言的設定のオブジェクトだから
 またKubernetesは、宣言的設定のオブジェクトでもあります。「Aを起動、Bを起動、Cを起動してください」とお願いするのではなく、「レプリカ数は3に等しい」という設定を行います。そのため、間違えたときに元に戻すのが簡単です。

理由③ 自己回復するシステムだから
 Kubernetesは、システムが望ましい状態に一致するように継続して動きます。例えばレプリカ数が3になるようにKubernetesに対して操作したとき、私がレプリカをもう一つ増やして4つにすると、Kubernetesは、数を3つに合わせるためにレプリカを一つ削除してくれます。

Kubernetesの利点② サービスもチームもスケールしやすい

Kubernetesでは、Pod、Service、Namespace、Ingress...など、分離されたマイクロサービスアーキテクチャの構築を簡単にする抽象化層やAPIを提供しています。色々分離されているので、サービスも開発もスケールしやすいということみたいです。

2章 コンテナの作成と起動

リポジトリcloneしてきて、Dockerfileもちゃんと書いて立ち上げようと思ったんですけど、結局動かせず...。デバックする気力はありませんでした...😇

この章では、アプリケーションのコンテナ構築について詳しく入門していきます。なぜDockerなのかというと、Kubernetes がサポートしている主要なイメージフォーマットの中で最も使われているのはDockerイメージフォーマットだからのようです。

アプリケーションコンテナ(Dokcerのこと)を使うと、アプリケーションを綺麗に抽象化できます。

(SREさんも「抽象化」という言葉を使っていたのですが、この「抽象化」ってどういう意味なんですかね...。アプリケーションの構成をファイルに落とし込むこと...? )

Dockerを使って、同じOS、同じバージョンのライブラリを使った環境についてビルドもデプロイも配布も簡単になることがわかりました。

3章 Kubernetesクラスタのデプロイ

この章では、先ほど作ったアプリケーションコンテナを、どのようにKubernetesをデプロイするのか、クラスタを作る簡単な方法を学びます。

Google Kubernetes Engine、Azure Container Service、Amazon Web Serviceへのインストール方法や、minikubeを使ったローカルへの Kubernetesのインストール、Raspberry PiKubernetesを動かす方法が紹介されています。

4章 よく使う kubectlコマンド

よく使うkubectlコマンドについて学びます。

Kubernetesオブジェクト

Kubernetes上にあるものは、すべてRESTfulリソースで表せ、これをKubernetesオブジェクトと呼ぶ。

kubectl get pods

Kubernetesオブジェクトをみる一番基本的なコマンド。動作中のPodのステータスを見ることができる。現在のNamespace内のそのリソースのすべてを一覧表示してくれる。
kubectl get <リソース名> <オブジェクト名> とかもみれる。

kubectl describe <リソース名> <オブジェクト名>

オブジェクトの詳細を人間に読めるフォーマットで複数行にわたって表示。

kubectl apply -f obj.yaml

obj.yamlに書かれたオブジェクトをKubernetes上に作成する。

kubectl delete -f obj.yaml

オブジェクトの削除。

kubectl label pods bar color=red

barという名前のPodにcolor=redというLabelをつける。

kubectl logs

デバッグ用コマンド。

kubectl exec -it --bash

コンテナ内でコマンドを実行したいときに使う。

kubectl help

ヘルプ。

5章 Pod

この章ではPodについて学びます。Podマニュフェストを書いて、Podを動かしたり、Podを一覧表示したり、Podにアクセスしたり、ちゃんと動いてるかチェックしたり、リソース管理をしたりします。

Podとは

Kubernetesクラスタ上では、コンテナではなくPodが最小のデプロイ単位。
「このコンテナはそれぞれ違うマシンに配置されても正常に動作するか」で答えが「動作しない」なら、Podとしてまとめて正解。

Podにアクセスする

Kubernetes APIコマンドラインツールには、ポートフォワード機能が備えられており、以下のようなコマンドを実行すると、このコマンドが動いている間はPodにアクセスできる。

kubectl port-forward kuard 8080:8080

Kubernetesのマスタを経由して、ローカルマシンとワーカノードの内の1台で動いているPodのインスタンスの間にセキュアなトンネルを作ってくれる。

livenessProbe

Podが起動しているかどうかのヘルスチェック。

readinessProbe

Podが応答できるかどうかのヘルスチェック。

resources

Podのリソース管理の設定

volumes

永続的なディスクにアクセス可能にする仕組み。

6章 Labelと Annotation

Label

Kubernetesクラスタ上のオブジェクトを識別したり、グループ化したりするのに使う。

Annotation

Labelと似た機能。ツールやライブラリを便利に使用するために必要になる、オブジェクトを特定しない情報を入れられる。

7章 サービスディスカバリ

サービスディスカバリ

何かを見つけるという問題と、その解決策のこと。(?)
サービスディスカバリツールは、どのプロセスがどのアドレスでどのサービスのために待ち受けているのかを見つける際に起きる問題を解決する。(うーん、難しい。)

Serviceオブジェクト

クラスタ内外に対してサービスを公開するための方法。サービス間を接続したり、サービスをクラスタ外に公開したりできる。

8章 ReplicaSet

ReplicaSet

指定したテンプレートに従った正しい数のPodが常に動いているようにする、クラスタ全体のPodマネージャ。冗長化のためにレプリカを複数作り、サービスを作る方法。

水平スケール

レプリカを追加で作成すること。

垂直スケール

あるPodに必要なリソースを増やすこと。

9章 DaemonSet

DaemonSet

Kubernetesクラスタの全ノード、あるいは特定のノードの集合でPodを動かすための、手軽な抽象化の仕組み。

10章 Job

Jobオブジェクト

一回限りの、短時間だけ動かすタスクを扱うもの。

11章 ConfigMapと Secret

ConfigMapとSercret

アプリケーションで動的な設定を使うのに適した方法。これらの機能によって、コンテナイメージを一度作成したら、開発環境、ステージング環境、本番環境で全く同じイメージを使うことも可能。

kubectl get secrets

Namespace内の全Secretを一覧表示できる。

kuubectl get configmaps

Namespace内のConfigMapを一覧表示できる。

12章 Deployment

Deploymentオブジェクト

新しいバージョンのリリースを管理する仕組み。
DeploymentはReplicaSetを管理する。
kind: Deployment と書いてあったらDeploymentの設定ファイル。

kubectl describe deployments nginx

Deploymentの詳細情報を確認できる。

kubectl rollout history deployments nginx

ロールアウトした履歴が表示できる。

13章 ストレージソリューションとKubernetesの統合

まとめは割愛します\(^-^)/

14章 実用的なアプリケーションのデプロイ

まとめは割愛します\(^-^)/

まとめ

今回は、

  • kubectlコマンドの使い方
  • Podについて
  • 仕事のコードで使われているKubernetes オブジェクト

を中心に本書を読みました。実際に(業務に支障のない範囲で)kubectlコマンドを打ってみたり、kubernetesの用語を確認しながらファイルを読んだりできてとても良かったです。個人的には、マニュフェストファイルにある kind: というところがKubernetesオブジェクトなんだ〜ということがわかっただけでも大きな収穫でした。Kubernetesの全体像に一歩近づくことができました。

しかしながら、自分は泥臭くサーバーを立てたり運用したことがないので、ピンと来ない説明も結構ありました。インフラのカタカナ用語が多くて意味が理解できない文章も結構ありました。これに関しては別の本で、インフラやkubernetesの歴史も補っていこうと思います。

ここまでお読みいただきありがとうございました!

ゼロからのOS自作入門 〜画面描画からマウスの入力受付まで〜

みなさんこんにちは!宮水です。今回は、マウスの作成まで(本書の7章まで)を通して自分なりに分かったことを日記として投稿します。

f:id:kattyan53:20210513081239p:plain

環境構築・ブートローダの作成まではこちら!miyamizu.hatenadiary.jp

ゼロからのOS自作入門

ゼロからのOS自作入門

4章 ピクセル描画とmake入門

この章でやること
  • makeを使ってみる
  • OS本体から絵を描く方法を学ぶ

画面に黄緑色の四角を描くことができました。
f:id:kattyan53:20210513125516j:plain

make

コンパイルやリンクなどの作業を自動化するツール

GOP (Graphics Output Protocol)

グラフィックス表示プロトコルの一つ。(ググっても全然情報が出てこなかった…)

System V AMD64 ABI

プログラムとCPUの相互作用を機械語レベルで規定する。プログラムが動作するにあたり必要なレジスタやメモリの使い方が決まっている。重要な項目に呼出規約があり、引数、戻り値、関数の中で変更していいレジスタなどを定めている。

5章 文字表示とコンソールクラス

この章でやること
  • OS本体から画面に文字を表示する
  • フォントを読み込んだりする
  • 出力専用のコンソールを作る

こんな感じで、フォントを適用して文字が表示されるようになりました!
f:id:kattyan53:20210515184014p:plain

バッファ

データを一旦蓄えておける場所のこと。

リンカ

リンカとは、機械語のプログラムの断片を適切に結合し、実行可能なプログラムとして生成するためのプログラムです。

リンカ – プログラミング用語解説|Unity高校&ゲームスクールのG学院

ld.lldコマンド(3章の復習)

オブジェクトファイルから実行ファイルを作成する。

6章 マウス入力とPCI

この章でやること

マウス入力を受け付けられるようにします。

  • マウスカーソルの描画
  • PCIバイスの列挙
  • xHCを探して初期化
  • ポーリング方式でマウスカーソルが動くようにする

USB接続されたマウスでも、ThinkPadタッチパッドでもカーソルが動くようになりました!
f:id:kattyan53:20210515184001p:plain

PS/2のエミュレーション

PS/2は接続の規格。エミュレーションとは、ポインタを動かしたり、クリック操作をしたりマウスを動かす操作のことのようです。

バス

電気信号を送る

シリアル

1本の信号線を使って信号うが1ビットずつ送られるという意味。

ドライバ

制御チップのようなハードウェアを扱うためのソフトウェアのこと。

xHC(Extensible Host Controller Interface)

xHCIと同義…なんですかね…?これもググってもあんまり出てこなかったです…)

xHCIとは、USB接続の周辺機器とコンピュータ本体の通信を制御するUSBコントローラの種類の一つで、USB 3.x規格に対応したもの。

https://e-words.jp/w/xHCI.html


https:/https://e-words.jp/w/xHCI.html
/e-words.jp/w/xHCI.html

PCI(Peripheral Component Interconnect)

部品とマザーボードを繋ぐための規格

PCI コンフィギュレーション空間

PCIバイスのベンダIDやクラスコードなどPCIバイスに関する基礎的な情報が書かれている。

ポーリング方式

イベントが来ているかどうか問い合わせる方式。

7章 割り込みとFIFO

この章でやること
  • 先ほどポーリング方式で作ったマウス入力を割り込み方式にする

割り込み処理は、以下のサイトの図がわかりやすかったです。
「マウスが動きましたか?」と毎回問い合わせるのではなく、マウスが動いたらそのときやっている処理を一時中断してマウスを動かし、元の処理に復帰するようにコードを書き換えていくそうです。
割り込み処理 | 東芝デバイス&ストレージ株式会社 | 日本

割り込み方式

イベントが到達したときにハードウェアがOSに通知する方式。

割り込みハンドラ

割り込み発生時に実行される関数のこと。

割り込みベクタ

割り込みには色々種類がある。割り込みの種類ごとに異なる割り込み要因番号が割り振られている。これを割り込みベクタという。

IDT(割り込み記述子テーブル)

割り込み要因番号と割り込みハンドラを対応付けるための表のこと。

MSI 割り込み

PCI規格が定める割り込みの発生方法。

FIFO

先入れ先出し。キューのこと。本書ではこの方式を使って割り込み処理を高速にする。

FILO

先入れ後出し。スタックのこと。

まとめ

今回は、文字表示やマウス入力の受け付けが終わりました!
画面に何か表示されると達成感があって楽しいですね☺️

また、基本情報でなんとなく丸暗記していた単語が多く出てきました。
実際に実装されているところを見るとより意味がわかったような気がします☺️ それでもやっぱり難しいですが...。

ゼロからのOS自作入門

ゼロからのOS自作入門

ここまでお読みいただきありがとうございました!

ゼロからのOS自作入門 〜環境構築からブートローダの作成まで〜

ゼロからのOS自作入門を購入しました!このブログでは、環境構築からブートローダの作成まで(本書の3章まで)を通して自分なりに分かったことを日記として投稿します。(調べながら書いたので、である調とですます調が混ざってますが、大目にみてください。)

ゼロからのOS自作入門

ゼロからのOS自作入門

f:id:kattyan53:20210430134705p:plain

読んだ理由

この本をTwitterのタイムラインで見かけて、元々〇〇自作にとても興味があり、面白そうだと思ったので購入しました。普段当たり前のようにお世話になっているOSですが、全く知らないのでこの本を通して学んでいきたいと思いました。

対象読者

本書によると、「簡単なプログラムを書いたことがある人」とのこと。

この本で学べること

  • CやC++を使って"全部自分で"OSを自作する

私のスペック

  • 普段はよくRubyを書いており、ソフトウェアエンジニアをしています。CやC++は今回初めてです。
  • よく使っているOSはmacOSです。
  • Vim、Git/Githubは調べながら使えます。
  • 基本情報技術者に2年くらい前にギリギリで合格しました。
  • 自作は全く初めてです。(mountコマンドの意味さえ知りませんでした。)

3章までやった感想としては、「とりあえず動かせるので楽しいけど、前提知識がなさすぎて解説が80%くらい理解できない」という感じです。

開発環境の構築

本書によると、2012年以降に発売されたパソコンを使うことが推奨されており、UbuntuWindowsで仮想環境を作ってLinuxが使えるようになるWSL (Windows Subsystem for Linux) 、QEMU(仮想環境)を使うやり方が紹介されています。

私は最初ベストな環境構築が分からなくて、1週間くらいハマりました。本当はMacで開発しようと思っていたのですが自分がよく分からないものは入れたくなかったので、フリマアプリで壊れてもいいパソコンを買って、本書で紹介されているLinux環境を作ることにしました。パソコンのスペックとUSBは以下です。

Lenovo Thinkpad X121e

  • 8500円
  • CPU:Core i3-2357M 1.3GHz
  • メモリ:DDR3 4GB
  • HDD:320GB
  • wifi繋げられる
  • USB挿せる
  • OS:Windows 10 Home 64bit

② USB

  • 数百円
  • 8GB
  • 規格はUSB3.0(私の買ったLenovo Thinkpad X121e はUSB2.0しか使えないので、3.0のUSBを買っても2.0の速さしか出ないらしいです。よくわかってませんが。)

Windows10を完全に削除してUbuntuをインストールして開発を進めました。以下の記事が参考になりました。
yoshinorin.net

BIOSの設定は、「ThinkPadロゴが出たらF1を長押し」でいけました。私が購入した機種ではセキュアブートは設定されていなかった(設定できない?)ようで、BIOSのStartupのBootの設定から、起動時の設定でUSBの優先度をあげると、USBからでも無事起動できました☺️

試行錯誤した結果、最終的に開発環境と動作確認用端末が一緒になってしまったので、今はQEMUを使って開発を進めています。

1章 PCの仕組みとハローワールド

この章でやること

バイナリファイルを書いてUSBに配置して起動させます。

ブートローダ

ブートローダとは、OSをメインメモリに読み込み、起動させるプログラムのこと。

BOOTX64.EFIファイル

実行可能ファイルといって、CPUが実行可能な機械語を含んだファイルのこと。

CPU

デジタル回路で構成されており、電圧の高低、すなわち2進数を扱う。今回バイナリファイルを16進数で書いたのは、16進数の方が2進数に変換しやすいから。

UEFI

オペレーティングシステム(OS)とプラットフォームファームウェアとの間のソフトウェアインタフェースを定義する仕様のこと。OSを起動するために必要な機能を提供するブートサービスと、OS起動前、起動後どちらでも使える機能を提供するランタイムサービスから構成されている。
Unified Extensible Firmware Interface - Wikipedia(ja)

UEFI BIOS

UEFIという標準仕様に従って作られたBIOSのこと。本書でやったファイルシステムFATでフォーマットされた起動ディスクの \EFI\BOOT\ ディレクトリ下に配置されたファイルで起動するというのは、UEFIの仕様のひとつ。

mount

脳死でumountとかmountとかコマンドを打っていました。
f:id:kattyan53:20210430135226p:plain

どうして普通にUSBにファイルを置くだけでは起動しないのか分からなかったので、teratailで質問してコマンドの丁寧な解説までいただきました😢 USBメモリのルートディレクトリ下にただコピーしただけでは、PCのUEFIからOSを起動することはできないそうです。UEFIの仕様に従ってBIOSを起動するために、USBをFATでフォーマットし、mountして起動ディスクの \EFI\BOOT\ ディレクトリ下にファイルを配置したということでした。(難)
Linux - デバイスファイルにアクセスしてコピーしないと起動しないのはどうしてですか|teratail

mountの説明は以下の通りです。

「mount」は、HDDやUSBメモリ、DVD-ROMなどのフォーマット済みの領域(ファイルシステム)を指定したディレクトリ(マウントポイント)と一時的に結び付けてアクセスできるようにするコマンドです
引用元:
【 mount 】コマンド――ファイルシステムをマウントする:Linux基本コマンドTips(183) - @IT

2章 EDK Ⅱ 入門とメモリマップ

この章でやること
  • EDK Ⅱという開発ツールを使ってみる。C言語で書かれたファイルをBuildして、上記で書いたバイナリファイルと同じものを作り、これをUSBメモリからメインメモリに読み込ませます。
  • UEFIの機能を使ってOSにメモリマップを渡すための準備として、メモリマップを取得したりファイルに一時保存してみたりします。

EDK Ⅱ

UEFI BIOS自体の開発、UEFI BIOS上で動くアプリケーションの開発などにも使える開発キット。

メインメモリ

メインメモリとは、プログラムやデータを一時的に蓄えておくための装置で、CPUの命令で直接アクセスできる装置のことです。

メインメモリとは何? Weblio辞書

メモリマップ

メインメモリのどの部分がどんな用途で使われているか載っている地図のことです。

ポインタ

ポインタとは、変数のアドレスを記憶する変数のことです。

納得C言語 [第13回]ポインタ - ほぷしぃ

構造体

C言語では、複数のデータ型を複数格納することができる箱を作ることができます。

納得C言語 [第14回]構造体 - ほぷしぃ

3章 画面表示の練習とブートローダ

この章でやること
  • main.cppを書く→clang++コマンドでソースコードコンパイルし、オブジェクトファイルmain.oを作成→ld.lldによってオブジェクトファイルから実行可能ファイル(kernel.elfファイル)を作成する。→edk2を使ってブートローダをbuildする→カーネルが起動する

Main.cファイルがブートローダで、main.cppがカーネルなんですね☺️



レジスタ

CPUに内蔵された記憶領域のこと。容量が小さく読み書きが速い。

カーネル

カーネル(英: kernel)は、階層型に設計されたオペレーティングシステム (OS) の中核となる部分である。

カーネル - Wikipedia

オブジェクトファイル

ソースコードコンパイルした結果の機械御命令を含んだファイル。

まとめ

今回は、3章まで進めました。正直なところ、CとC++で書かれたファイルはあんまりちゃんと読めていません。 しかしながら、何をやっているか抽象的に理解しつつ、書き写して実行するだけでも楽しいです👍 これからも少しずつ進めていこうと思います。

ゼロからのOS自作入門

ゼロからのOS自作入門

ここまでお読みいただきありがとうございました!