CIサーバ自身のCI/CD(GWアドベントカレンダー 1日目)
この記事はGWアドベントカレンダーの1日目の記事です。
Infrastructure as Codeの考えでは、アプリケーションだけでなくインフラ部分(OSやミドルウェアなど)についてもCI/CDの対象として扱います。 この記事では、IaCに取り組もうと考えて最初に悩む(?)CIサーバ自身のCI/CDについて説明します。
CIサーバというのは、JenkinsやGitlabのようにコミットやプッシュを契機(trigger)に自動的にジョブを実行する機能を持つサーバのことです。 CIサーバ自身も様々な設定を持つ重要なサーバであり、管理対象です。
本記事では簡単のためにCIを自動構築と自動テストと定義します。また、CDを自動デプロイと定義します。 CI/CDのパイプラインとして自動にすべき部分や手動にすべき部分がありますが、本記事ではすべて自動で実施する場合としています。
前提
IaCの文脈で、各サーバをImmutable Serverとして扱う場合を想定しています。 環境としてテスト環境と本番環境があります。CIサーバはテスト環境と本番環境の両方にアクセスできるので、便宜上CI環境に配置されているとします。 CIとして、テスト環境の再構築とテストを実施し、CDとして本番環境の再構築とテストを実施するものとします。
CIサーバをCDの対象とすべきかどうか
CIサーバをCDの対象とするということは、CI環境のCIサーバを再構築(破棄、作成)することになります。 CIサーバをImmutable Serverとして扱うと、パイプラインの途中でCIサーバの再構築が行われるため、必ず途中で中断することになりCDの対象とすることはできません。 CIサーバをいくつものコンポーネントに分けて、一部の機能のみCDの対象とすることはできると思います。
CIサーバはImmutable Serverではない(Mutable Server)として扱うとCIサーバをCDの対象とすることができます。しかし、パイプラインを実行中のCIサーバを変更するというのは複雑で、避けるべきと思います。
したがって、CIサーバはCDの対象とすべきではないと考えます。
CIサーバをCIの対象とすべきかどうか
CIの対象(以下、CI管理対象)というのは理想的にはすべてのサーバです。したがってCIサーバもCI管理対象とすべきと考えられます。
CIサーバのテスト用インスタンスを作成し、テストを実施することは有効です。ただし、テスト用インスタンスを使って実際のパイプラインを実行してはいけません。 実際のパイプラインはテスト用のCIサーバインスタンスの再構築を含んでいたり、テスト環境や本番環境のサーバ再構築を含んでいます。実行して良いのは接続確認のような環境に変更を加えない内容のものだけです。
結論
CIサーバはCIの対象としますが、CDの対象外とします。 CIのパイプラインではテスト用インスタンスを作成し、自動テストを実行します。自動テストによってCIサーバの構築手順の妥当性を確認できます。
明日はCIサーバのデプロイ方法についての予定です。
Oracle CloudのCompute インスタンスが起動後すぐ停止する
Oracle CloudのCompute インスタンスが起動できなくなってしまいました。 正確にはインスタンスを開始させると、起動中というステータスになりますが、少し経つと今度は停止中となり、停止済みとなってしまいます。
以前は起動できたのにできなくなってしまいました。困った。。 しかもそれらしきログも出ずに原因究明ができません。 コマンドラインインタフェース(コマンドは後述)から起動してみても、開始要求は正常に行われるのでエラーになりません。
新しいインスタンスを作成用しようにも、以下のメッセージが出て作成もできません。
困った困った。。
可用性ドメインjRHI:AP-TOKYO-1-AD-1のシェイプVM.Standard.E2.1.Microの容量が不足しています。 後で再試行してください。
oci compute instance action --action=start --instance-id=
「インフラCI 実践ガイド」を読んだ
インフラCI 実践ガイドを読みました。 以前読んだInfrastructure as Code(以下、IaC書籍)に対し、具体的な実装方法について説明しており今の自分に欲しい情報がたくさん得られて非常に満足しました。
本書はこれからインフラCIを始めようとする方向けの本です。インフラCIの具体的な実装の説明と、インフラCIの外側にある要素についても説明しています。 インフラCIの外側にある要素というのはシステムのデザインやリリースに関する制約やチームメンバのスキルなどです。インフラCIを導入し成功させるためにはインフラCIの外側にある要素も非常に重要です。
実際にインフラCIの環境を読者が実際に動かすことができるよう、演習環境としての構築方法とそれに必要な構成定義ファイルを提供しており、まさにこれから始める人にはうってつけの内容と思います。 また、インフラCIの技術的な側面だけでなく、インフラCIを実践するために必要な非技術的な要素についても随所で触れており、インフラCIをこれから導入しようとする場合のポイントについても理解ができるようになっています。 実際に最後の方の章では、技術的な観点というよりはインフラCIよりも広い範囲を考えた場合の導入方法についても述べられています。
IaC書籍は本書の中でも参照されており、より抽象的な概念の理解のためにIaC書籍を読んでおくと、本書の理解もより深まると思います。 実際に私もIaC書籍を読んでから本書を読みましたが、IaC書籍の内容ともリンクしてわかりやすかったです。
記述のスタイルとして、結果をまず述べてからその仕組みについて説明する形になっており、構成定義ファイルの中身についての説明が後回しになっていたり、省略されていたりします。そのため、具体的な構成定義ファイルの中身を見た方がイメージしやすい読者の場合には、ここに記載されている構成定義ファイルをPC上で見ながら本書を読むのも良いかと思います。
「しくみがわかるKubernetes」を読んだ。
「しくみがわかるKubernetes」を読みました。
ほんとに仕組みがわかった気になりました。 これまでminikubeでhello worldをやっただけの経験でしたが、kubernetesがどういう仕組みになっているかの全体像を掴むことができました。
この本ではDockerなどのコンテナそのものについての説明はほとんどありません。
コンテナそのものを知らないとそもそもkubernetesの良さもわからないかもしれませんが、
この本で説明しているのはコンテナの管理をするkubernetesの仕組みです。 コンテナがどのような仕組みのものなのか、コンテナイメージはどのように作るのかというようなことは知らなくても読み進めることができると思います。
しくみを説明する本ですので、kubernetsの全体像としてどのようなコンポーネントで構成されているのかや、それぞれのコンポーネントの役割が説明されています。
また、Infrastructure as Codeの観点から、すべての定義をファイルに残すべきということも随所で述べてあります。
本文中に登場する定義ファイルはダウンロードできるようになっており、実際に試すことも可能です。
読者自身が実機で試す際も、細かな定義はすべてファイルに記載されているので、実際に打つコマンドはそれを適用するためのコマンドばかりです。
Kubernetesの環境を自分で構築するのは大変ですが、Azureで提供されているAKS(Azure Kebernetes Service)を使うことで簡単に利用を開始できます。
提供されているサンプルコードもAKS向けのものとなっているので、手軽に動作確認ができるようになっています。
この本ではKubernetesの主要コンポーネントの紹介と構成検討のポイントなどが述べられています。
含まれていないのは構築手順やオプションのコンポーネント等です。
例えば、ネットワークやストレージのコンポーネントについてはあまり説明がありません。
そのため、この本だけを見て自分でKubernetesを構築したいという方には向きませんが、クラウド上のマネージドサービスとしてKubernetesを使いたいという人には向いていると思います。
自分で環境を構築したいという人でも、この本を読むことで全体像がイメージできるようになりますので、具体的な検討へのステップとしては有効と思います。
「Infrastructure as Code」を読んだ
「Infrastructure as Code」を読みました。
タイトル通り、システムのインフラ(アプリケーションの土台部分)をコードとして表現することについての本です。
アプリケーションはそもそもコードとして定義されているのが普通ですが、インフラは設計書や手順書によって表現されることが多くあります。
インフラをコードとして表現することで、様々な恩恵を得られるということを謳っています。
この本の中で繰り返し述べられていることは、以下のことです。
- 常に同じやり方をすること
- すべてコードに表現すること
- VCSを使ってコードを管理すること
- 繰り返しそのコードを使ってインフラを構築すること
- 人による判断が必要な個所以外は自動化すること
どんなツールを使うかやコードの管理や自動テストの行い方や管理単位の分割の仕方といった実現方法は、使う組織や運用に合わせて柔軟に変える必要があります。
この本では具体的なツールの使い方にはほとんど触れず、ツールの特徴の紹介と運用パターンの選び方(や選択肢)の紹介が多いです。
言い方を変えると特定のツールによらない普遍的な考え方を中心に述べており、Infrastructure as Codeの概念やメリットを理解したい人に向いています。
具体的なツールの使い方についての説明はありませんが、ツールの名前や特徴については簡単に触れられているので、ツールについて調べる取っ掛かりにもなります。
Infrastructure as Codeをこれから始めようと考えている人にとっては、良い参考書となると思います。
ゼロから仕組みを構築したいときには、考慮すべき観点のチェックリストにもなりますし、既に仕組みがある場合でもより効率化するためのヒントが得られるように思います。
Goのnet/httpでWebサーバを作って確認したこと
Go のnet/httpパッケージを使うと簡単にWebサーバが構築できます。 実際に動作を確認した内容について備忘録としてメモしています。
並列処理可能
特に何も工夫せずにWebサーバとして動作させるだけで、goroutineによる並列処理が可能です。
動作確認のため、Apache Bench(ab)を使って確認しましたが、1000セッション同時に処理できていました。
動作確認の際は、リクエストの応答にsleepを1秒入れて1000セッションが10リクエストを発行しました。
すると、10秒くらいですべてのリクエストが処理されました。
動作確認に使ったコマンドは以下です。
実行すると約1秒毎に1000リクエストが処理されて、約10秒後に完了します。
結果のサマリを見ても、ほとんどのリクエストが約1秒で完了していました。
ab -c 1000 -n 10000 http://localhost:8080/
レスポンスのContent-Type自動設定
レスポンスをhtmlにすると、自動的にContent-Typeがtext/htmlになりました。
レスポンスをダブルクォートで囲んだ文字列にすると、中身がhtmlでもtext/plainになりました。
強制的に変更したいときは、以下のようにして指定できます。
w.Header().Set("Content-Type", "text/html; charset=utf-8")
コード
実際の動作確認の際は、不要なものを削除したりコメントアウトしたりしながら実施していますが、
上記の確認に必要なものはこれで足りると思います。
package main
import (
"fmt"
"html"
"log"
"net/http"
"time"
)
func main() {
http.HandleFunc("/", uploader)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func uploader(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-type" , "text/html; charset=utf-8")
time.sleep(1 * time.Second)
fmt.Fprintf(w, "%s", html.EscapeString(r.URL.Path)
}
Docker Desktop for Windowsの導入
Docker Desktop for Windowsを導入してみました。
dockerコンテナを作って動かしたいのが目的です。 Windowsを使うのは、普段使っているOSがWindowsだからで、コンテナはLinuxのものを使います。 そうしたときに、docker Engineをどこで動かすかの選択肢があります。
- Windows (Docker Desktop for Windows)
- Windows上のLinux VM(Hyper-VやVirtual Box上のLinux VMでLinux用のDocker Engineを動かす)
開発用にLinux VMを動かしているのでそちらでDockerを使っても良いのですが、わざわざVMを起動して使うのも面倒そうなのでWindows上で動かすことにしました。 ただ、Windows上で動かすと言っても、実際にはDocker用のLinux VMがHyper-Vを使って起動します。 そのため、自分でLinux VMを用意して動かすのと仕組みはそれほど変わりません。
Docker Desktop for Windowsの場合、Docker ClientはWindows上で動きますが、Docker EngineはLinux VM上で動きます。 自分でLinux VMを用意して使う場合はDocker ClientもDocker EngineもLinux VM上で動きます。 コンテナそのものはどちらもLinux VM上で動きます。
Docker Desktop for Windowsを使う場合、DockerfileやコンテナにコピーするファイルをLinux VMから利用できるようにする必要があります。 どのドライブをアクセス可能にするかは、settingsから設定できます。 なお、コンテナからマウントして使うようなデータ領域としてはWindows上の領域は不向きで、data volumeやdata containerを使う方が良いようです。これには二つの理由があって、一つはWindows上の領域はLinux上からみて、rwxrwxrwxのモードで見えます。もう一つは、SMBを使ってLinux VMに領域を見せる際、NOBRLオプションが付いているため、ロックができない場合がある点です。 これらはDocker Desktop for Windowsのドキュメントの最初の方(Shared drives)に書いてあります。
と、ここまでやってから大事なことに気づきました。 開発用にLinux VMを動かしていますが、そちらはVirtual Boxを使っています。 Docker Desktop for WindowsはHyper-Vを使います。 これらの共存はできないので、どちらを使うか選ぶ必要があります。。つづく。。
「エンジニアのための マネジメントキャリアパス」を読んだ
「エンジニアのための マネジメントキャリアパス」を読んだ。
エンジニアが管理される側から管理する側になっていく話、、というか、管理者とはどういう役割かをきちんと説明した本でした。 そして、管理者にも段階があり、メンターとして一人を指導する立場からテックリードとしてチームを率いる立場、チーム管理者として管理する立場、チーム管理者を管理する立場といった具合に、それぞれの管理者が何をすべきかということが書かれています。よくあるダメな上司の例も交えて説明しており、イメージしやすい記述になっています。
管理する側に必要なものとして、対人スキルについても多く記述されています。技術的なスキルも当然必要ですが、チームメンバーや部下とうまくコミュニケーションを取るスキルが重要であること、プロジェクトをうまく進めるために、タスクを細かく分割し、具体化するスキルが必要であることなどが重要であることを述べています。
それぞれの段階の管理者がやるべきことが記載されており、本文中にもあるようにリファレンス的に利用されることを想定して記述されているため、自分の置かれている状況に合わせて適宜参照しやすい構成になっています。 時々読み返しては自分の行動を顧みることにも使える一冊だと思います。
「入門 UML 2.0」を読んだ
「入門 UML 2.0」を読んだ。 UMLってユースケースを表現するためのものでしょ?と思っていて、図を使ってユースケースを書く必要に迫られることも無かったのであまり勉強する気にもなっていなかったのですが、Plant UMLというテキストでUMLを既述できるものを知り、図を描くのにテキストで記述できるのは便利そうということで読んでみることにしました。
読んでみると、そもそもユースケース図を描くたものものという認識が誤りで、ユースケース図を表現することにも使えるが、それ以外の様々なものを表現するために使えるものであるということがわかりました。また、表現の仕方が定義されていて、UMLを知っている人であれば書き方を説明せずに記述できるということもよく分かりました。そのため、記述ルールについての凡例を書く必要もないのです。
UMLは既述したい目的毎に図の書き方がいくつも用意されています。そして、その目的や使い分けについて説明しています。しかし、その使い方は限定的ではありません。ある特定の種類の図ですべてを表現する必要はなく、その図で表現したい箇所だけをその図で表現し、そのほかの場所は異なる種類の図で表現しても良いとされています。結局は表現すべき重要な事柄を、それを表現するのに適切な図を使って表現すべきとしています。 つまり、何を表現すべきかを考えて使い分けるということです。
この本を読むことで、システム設計においてどのような情報を表現するべきかということがわかると思います。全体の概要を示したい場合や、特定部分の詳細について説明したい場合がありますが、それらがどのような種類の情報であるか、また混ぜるべきではない情報というのはどういうものかというのがなんとなくわかると思います。実際に書いて表現することを繰り返すことで、システムのどの部分をどのように表現するべきかというのがより直感的にわかるようになってくるのだと思います。
ところで、Plant UMLはテキストで記述したものをUML図に変換する仕組み(Webサービス、Javaプログラムとして提供されています)ですが、テキストをエディタで変更すると即座にその結果のUML図が変更されるという使い方ができます。
Vimでは、previmというpluginを使うことで実現できます。 previmはそもそもMarkdownに対してのプレビューを提供するものでしたが、PlantUMLにも対応したのです。
これを使いたかったという気持ちもあります。
そんなわけで、今後、図を記述する必要がある場合にはPlantUMLを積極的に使っていきたいと思っています。