<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>インフラエンジニアway - Powered by HEARTBEATS</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/" />
    <link rel="self" type="application/atom+xml" href="https://heartbeats.jp/hbblog/atom.xml" />
    <id>tag:heartbeats.jp,2016-08-25:/hbblog//2</id>
    <updated>2026-01-05T03:02:33Z</updated>
    <subtitle>株式会社ハートビーツのインフラエンジニアから、ちょっとした情報をお届けします</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 6.2.6</generator>

<entry>
    <title>新年のご挨拶 2026年</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2026/01/-2026.html" />
    <id>tag:heartbeats.jp,2026:/hbblog//2.948</id>

    <published>2026-01-05T03:00:00Z</published>
    <updated>2026-01-05T03:02:33Z</updated>

    <summary>新年あけましておめでとうございます。ハートビーツの藤崎です。おかげさまで昨年末も...</summary>
    <author>
        <name>藤崎正範</name>
        
    </author>
    
        <category term="活動" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>新年あけましておめでとうございます。ハートビーツの藤崎です。<br />おかげさまで昨年末も大きな障害もなく無事に年を越せました。<br />多くの皆様からのご支援・ご指導を賜り、心より感謝申し上げます。</p>
]]>
        <![CDATA[<p>昨年は創業20周年を迎え、「クラウド・アクセラレーション事業部」を中核に、人材育成強化による技術者拡充を継続しながら、創業以来の強みであるMSP（Managed Service Provider）領域の一層の強化、セキュリティ・アドバイザリー分野のサービス拡充、新たなパートナーシップや技術認定の取得などに取り組みました。インフラ運用と多様なサービスを有機的に連携させることで、お客様の課題解決と事業成長に少しでも寄与できるよう努めた一年でもありました。</p>

<p>また昨年は、AI活用の本格フェーズにも踏み出しました。インフラ運用における生成AI活用の内製化を進め、運用品質と生産性を一段引き上げる新たな取り組みを拡大しています。MSPとして蓄積してきた知見とAIの融合により、"止めない・安心な運用"に加え、"より効率的で賢い運用"を実現していきます。</p>

<p>2025年の活動をいくつかご紹介させてください。</p>

<p>・「インフラ運用20年の会社が考える、インフラ運用とAIのこれから」の登壇レポートを公開しました <br/>　<a href="https://heartbeats.jp/topics/10216/" target="_blank" title="「インフラ運用20年の会社が考える、インフラ運用とAIのこれから」の登壇レポートを公開しました">https://heartbeats.jp/topics/10216/</a></p>

<p>・ハートビーツのエンジニア2名がAWSの「2025 Japan All AWS Certifications Engineers」を受賞しました <br/>　<a href="https://heartbeats.jp/info/news/news-20250701-2/" target="_blank" title="ハートビーツのエンジニア2名が AWS の「2025 Japan All AWS Certifications Engineers」を受賞">https://heartbeats.jp/info/news/news-20250701-2/</a></p>

<p>・「Kozutumi」が、帝国データバンクさまの「日本版リモートeシール」実証実験に参画しました<br/>　<a href="https://heartbeats.jp/info/topics/20250409_01/" target="_blank" title="Kozutumiを活用し、帝国データバンクの『リモートeシール』実証実験に協力">https://heartbeats.jp/info/topics/20250409_01/</a></p>

<p>・「一般社団法人日本シーサート協議会」に加盟し、社内CSIRT体制の強化を図りました<br/>　<a href="https://heartbeats.jp/info/pressrelease/20250107_01/" target="_blank" title="日本シーサート協議会に加盟しました">https://heartbeats.jp/info/pressrelease/20250107_01/</a></p>

<p>・首都圏国立大学合同ハッカソンに企業メンターとして参画し、学生チームの活動をサポートしました<br />　<a href="https://heartbeats.jp/info/sponsorship/sponsorship-20251121/" target="_blank" title="首都圏国立大学合同ハッカソンに企業メンターとして参画し、学生チームの活動をサポートしました">https://heartbeats.jp/info/sponsorship/sponsorship-20251121/</a></p>

<p>・『パテレアワード2025』にブロンズスポンサーとして協賛いたしました<br />　<a href="https://heartbeats.jp/info/news/news-20251202/" target="_blank" title="『パテレアワード2025』にブロンズスポンサーとして協賛いたしました">https://heartbeats.jp/info/topics/20240813_01/</a></p>

<p>　</p>

<p>昨年も 様々なところで皆様からチャンスを頂きましたこと、この場をお借りしてお礼申し上げます。<br />その他の活動についてはニュース一覧を御覧ください。</p>

<p>・ニュース 一覧<br />　<a href="https://heartbeats.jp/info/" target="_blank" title="ニュース 一覧">https://heartbeats.jp/info/</a></p>

<p>2026年も更なる成長を目指し、皆様と共に進化してまいります。<br />私どもの得意分野でお困りのことがございましたらお仕事でご一緒できる機会があれば幸いです。</p>

<p>・クラウド・アクセラレーション事業 | 企画から開発、運用まで一貫したサービスを提供<br />　<a href="https://heartbeats.jp/service/" title="クラウド・アクセラレーション事業 | 企画から開発、運用まで一貫したサービスを提供">https://heartbeats.jp/service/</a></p>

<p>・Kozutumi | 脱PPAPに最適な重要ファイル転送プラットフォーム<br />　<a href="https://kozutumi.com" title="Kozutumi | 脱PPAPに最適な重要ファイル転送プラットフォーム">https://kozutumi.com</a></p>

<p>　</p>

<p>皆様と共に、2026年を良い年にすることができるよう邁進してまいります。<br />引き続き、ご指導ご鞭撻ご贔屓の程、宜しくお願い申し上げます。</p>
]]>
    </content>
</entry>

<entry>
    <title>実践で学ぶLogrotate の安全な使い方まとめ！</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2025/12/logrotate-1.html" />
    <id>tag:heartbeats.jp,2025:/hbblog//2.947</id>

    <published>2025-12-11T03:00:00Z</published>
    <updated>2025-12-11T03:31:10Z</updated>

    <summary>こんにちは、運用チームのKimです。 システム運用において、ログファイルの肥大化...</summary>
    <author>
        <name>kim</name>
        
    </author>
    
        <category term="技術" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>こんにちは、運用チームのKimです。</p>

<p>システム運用において、ログファイルの肥大化はディスク容量を圧迫する一般的な課題です。この課題に対して、多くの企業でLinuxの標準ツールLogrotate を使ったログ管理が行われています。</p>

<p>しかし、Logrotateの運用においては、設定項目の理解不足による<strong>意図しない挙動やログの欠損</strong>などが起こることがあり、その取り扱いには細心の注意が必要です。
そこで今回は、Logrotateを安全に使いこなすための実践的な方法と注意点をまとめました。特に、<strong>運用環境での事故を防ぐための検証方法</strong>に焦点を当てて解説します。</p>
]]>
        <![CDATA[<h2>Logrotate とは？</h2>

<p>Logrotateは、LinuxやUnix系OSで広く使われているログ管理ツールです。 増え続けるログファイルを自動的にローテートし（例：現在のログファイルを別名で保存し、新しい空のログファイルを生成すること）、圧縮、削除することで、ディスク容量の肥大化を防ぎます。 </p>

<p>これにより、システムの安定稼働を維持し、ログの管理を効率化することができます。</p>

<h2>Logrotate の導入手順と安全な検証</h2>

<p>ではさっそく手を動かしてみましょう！</p>

<p>ここではLinuxユーザー向けに、実際に手を動かしながらLogrotateの仕組みを理解していきます。例として、Apache HTTP Server（Apache）のログをLogrotateでローテートしてみましょう。</p>

<p>まずはLinux環境を準備してください。Linuxの主要なディストリビューション（CentOS,RHEL, Ubuntu, AlmaLinuxなど）には、Logrotateが<strong>標準でインストールされている</strong>ため、ほとんどの場合、追加の導入作業は不要です。</p>

<p>次に検証のためApacheの環境を利用します。Apacheの導入がまだの方はdnfコマンドまたはaptコマンド等でインストールをお願いします。</p>

<p>※本記事では<code>AlmaLinux9</code>を利用してます。</p>

<pre>
AlmaLinuxの場合
# dnf install httpd -y
</pre>

<p>Logrotateの設定ファイルは/etc/logrotate.confという<strong>親設定ファイル</strong>と、/etc/logrotate.d/というディレクトリ内の<strong>個別設定ファイル</strong>に分かれています。この形式を模倣し、Apacheのログローテートを想定したカスタム設定をしていきます。</p>

<h2>Step1: Logrotateの親設定ファイルの理解</h2>

<p>まず、あらかじめ用意されているLogrotateの設定ファイルであるlogrotate.confの内容を確認してみましょう。</p>

<pre>
$ cat /etc/logrotate.conf
</pre>

<p>私の環境では出力された内容は下記のとおりでした</p>

<pre>
# see "man logrotate" for details

# global options do not affect preceding include directives

# rotate log files weekly
weekly

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# use date as a suffix of the rotated file
dateext

# uncomment this if you want your log files compressed
#compress

# packages drop log rotation information into this directory
include /etc/logrotate.d

# system-specific logs may also be configured here.
</pre>

<h3><strong>ディレクティブの説明</strong></h3>

<p>この親設定ファイルは、Logrotate全体の基本的な設定を定義しており、個別の設定ファイルに共通のデフォルト設定を適用します。</p>

<ul>
<li><strong>weekly</strong>: ログファイルを毎週ローテート</li>
<li><strong>rotate 4</strong>: 4世代分のログファイルを保持し、古いものから自動的に削除</li>
<li><strong>create</strong>:ローテート後に新しい空のログファイルを作成</li>
<li><strong>dateext</strong>:ローテートされたログに、日付（例: <code>access_log-20250917</code>）を付けてリネーム。</li>
<li><strong>compress</strong>:ローテートしたログを gzip で圧縮。</li>
<li><strong>include /etc/logrotate.d</strong>: <strong>この行がポイント</strong>。このディレクティブは、指定されたディレクトリ（この場合はlogrotate.d）内のすべての設定ファイルを読み込み、処理するようLogrotateに指示。これにより、複数のアプリケーションのログ設定を個別のファイルで管理が可能。</li>
</ul>

<h3><strong>※注意</strong></h3>

<p>これからApache用の個別設定ファイルを設定していきます。
親設定ファイルlogrotate.confで定義しているディレクティブの設定とApache用の個別設定に記載したディレクティブが共通する場合、Apache用の個別設定のディレクティブ設定が優先されます。また、個別設定にないディレクティブが親設定ファイルに定義されている場合は、全体の設定として反映されます。</p>

<ul>
<li><strong>個別設定が優先</strong>: 親設定ファイル (/etc/logrotate.conf) と個別設定ファイル (/etc/logrotate.d/httpdなど) で同じディレクティブが重複して定義されている場合、個別設定ファイルの設定が優先</li>
<li><strong>親設定から引き継ぎ</strong>: 個別設定ファイルで定義されていないディレクティブは、親設定ファイルの基本的な設定が引き継がれる</li>
</ul>

<h3>個別設定が親設定の影響を受けないようにする方法</h3>

<p>個別設定が親設定の影響を完全に受けないようにするには、必要な設定項目をすべて個別設定ファイル内に記述する必要があります。これにより、親設定ファイルのグローバルな設定を個別設定で上書きできます。</p>

<p>たとえば、親設定ファイルに createディレクティブがあり、これを個別設定で適用したくない場合は、個別設定ファイルに明示的に nocreateディレクティブと記述します。</p>

<h2>Step2: 検証用ログファイルの準備</h2>

<p>今回は、アクセスログ（<code>access_log</code>）とエラーログ（<code>error_log</code>）を以下の条件でローテートします。</p>

<ul>
<li><strong>ローテートされたファイルは日付でリネームする</strong></li>
<li><strong>5世代分のログファイルを保持する</strong></li>
<li><strong>当日分を除きローテートされたログをgzipで圧縮する</strong></li>
</ul>

<p>まず、Apacheのログを模倣したファイルを用意します。通常、Apacheのログは/var/log/httpd/（CentOS/RHEL系/AlmaLinux）や/var/log/apache2/（Debian/Ubuntu系）にあります。今回はCentOS/RHEL/AlmaLinux系を想定し、/var/log/httpd/ディレクトリにログファイルを作成します。</p>

<pre>
# Apacheのログディレクトリに過去1週間分のログファイルを擬似的に作成 
$ sudo tee -a /var/log/httpd/access_log <<< "Initial access log entry" > /dev/null && sudo tee -a /var/log/httpd/error_log <<< "Initial error log entry" > /dev/null && for i in {1..7}; do date=$(date --date="${i} days ago" +%Y%m%d); echo "Dummy access log entry from ${date}" | sudo tee -a "/var/log/httpd/access_log-${date}" > /dev/null; echo "Dummy error log entry from ${date}" | sudo tee -a "/var/log/httpd/error_log-${date}" > /dev/null; done

# ファイルが正しく作成されたか確認 
$ sudo ls -l /var/log/httpd/
total 64
-rw-r--r--. 1 root root  50 Nov 13 11:39 access_log
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251106
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251107
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251108
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251109
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251110
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251111
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251112
-rw-r--r--. 1 root root 732 Nov 13 11:39 error_log
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251106
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251107
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251108
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251109
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251110
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251111
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251112
</pre>

<p>lsコマンドを実行すると、アクセスログ（<code>access_log</code>）とエラーログ（<code>error_log</code>）に加え、過去7日分のファイルが作成されているのが確認できます。</p>

<h2>Step3: Apacheログファイル操作用のローテート個別設定ファイル編集</h2>

<p>次に、親設定ファイルとApacheのローテート個別設定ファイルを編集します。通常、/etc/logrotate.d/ディレクトリ内に個別の設定ファイルを編集します。</p>

<p>Logrotateの設定を1つの設定ファイルに全て記載することもできますが（例えば親設定ファイルに全て記載するとか）、複数の設定内容を/etc/logrotate.d/ディレクトリ内に<strong>複数の設定ファイルを作成し、目的別に分割して管理することもできます。</strong> 設定ファイルを分割して管理することで、設定内容の整理がしやすくなり、特定のログ設定だけを変更・管理する際も容易になります。</p>

<p>Apacheのローテート個別設定ファイルを編集（/etc/logrotate.d/httpd）</p>

<p>※Apacheインストール時に自動で作成されているはずです。</p>

<pre>
$ sudo vim /etc/logrotate.d/httpd
</pre>

<p>以下の内容を開いたvimエディターの中に記述します。</p>

<pre>
/var/log/httpd/access_log /var/log/httpd/error_log {
    # 親設定で有効化されている create を明示的に無効化
    nocreate
    # 親設定のweeklyをdailyに上書き
    daily
    rotate 5
    # 親設定を上書き
    compress
    # その他の必須オプション
    delaycompress
    missingok
    notifempty
    dateext
    postrotate
        # HUPシグナルでApacheに新しいログファイルを開かせ、同時に新規ファイル作成も任せる
        /bin/kill -HUP $(cat /var/run/httpd/httpd.pid)
    endscript
}
</pre>

<h3>ディレクティブの説明</h3>

<p>この設定は、<code>access_log</code> と <code>error_log</code> の両方をまとめて管理するためのものです。 これにより、同じローテートルールを2つのファイルに簡単に適用できます。</p>

<p><strong>補足</strong>： 本記事で紹介しているのは主要なディレクティブのみです。Logrotateの設定ファイルには他にも多数のディレクティブが存在します。他の設定項目や詳細な仕様を確認したい場合は、Linuxのターミナルで man logrotate コマンドを実行して、マニュアル（manページ）を参照してください。</p>

<ul>
<li><code>/var/log/httpd/access_log</code>, <code>/var/log/httpd/error_log</code>: ローテートの対象となるファイルへのパス。</li>
<li><strong>nocreate</strong>: ローテート後に新しい空のログファイルを作成しないようにする。
<ul>
<li>今回はpostrotateディレクティブで定義したスクリプト処理より、Apache設定ファイルの再読み込みが発生し、httpd.confの設定に基づきログファイルを作成するためcreateディレクティブは不要</li>
</ul></li>
<li><strong>daily</strong>: ログファイルを毎日ローテートする。</li>
<li><strong>rotate 5</strong>:5世代分のログファイルを保持し、古いものから自動的に削除する。</li>
<li><strong>compress</strong>: ローテートしたログを gzip で圧縮する。</li>
<li><strong>delaycompress</strong>: compressの処理を次回のローテート時まで遅らせる。これにより、直近にリネームされたログがすぐに圧縮されるのを防ぎ、アプリケーションの書き込みを妨げないようにする。</li>
<li><strong>missingok</strong>: 対象のログファイルが存在しなくてもエラーにしない。</li>
<li><strong>notifempty</strong>: ログファイルが空の場合はローテートしない。</li>
<li><strong>dateext</strong>: ローテートされたログに、日付（例: <code>access_log-20250917</code>）を付けてリネームする。</li>
<li><strong>postrotate</strong>: ログローテートが完了した後に実行されるスクリプトを定義する。
<ul>
<li>Apacheでは/bin/kill -HUP $(cat pidファイル)のスクリプトを定義しApacheがログファイルを再読み込みできるように設定する例が多い。</li>
<li><strong>HUPシグナル</strong>とはLinuxやUNIX系OSで使用されるソフトウェアシグナルの一つで、「<strong>SIGHUP</strong> (Signal Hang Up)」とも表記される。</li>
<li>/bin/kill -HUP $(cat pidファイル)が必要になる理由はApacheはHUPシグナルを受け取ると、<strong><font color="red">Apacheのプロセスを再起動せず</font></strong>に設定ファイルを再読み込みし、同時に現在開いているログファイルへのハンドル（ファイル記述子）を閉じ、新しいファイルを開き直す動作をする。これにより新しく作成された空の <code>access_log</code> には何も書き込まれないという状態を回避する。</li>
<li>endscript: postrotateなどのスクリプトを定義するブロックの終了を示すディレクティブ。</li>
<li><strong>補足</strong>：上記定義しているkillコマンドについて
<ul>
<li>AlmaLinux9 のApacheのローテート個別設定ファイルのデフォルト設定では、killコマンドの代わりにsystemctl httpd reloadを利用。停止を挟まない条件は同じなので、どちらを利用しても問題なし。</li>
<li>実装例：/bin/systemctl reload httpd > /dev/null 2>/dev/null || true</li>
</ul></li>
<li><strong>postrotate</strong>ディレクティブをなぜ利用するかについては後半の方で詳しく解説。</li>
</ul></li>
</ul>

<h2>Step4: debugモードで安全に設定を検証</h2>

<p>設定ファイルを更新したら、--debugオプションで<strong>debugモード</strong>と呼ばれる機能（実行した時の一連の挙動を確認する機能）を実施し、シミュレーションします。</p>

<p>これから利用するdebugモードでは、Logrotateコマンドを実際に実行した際に出力されるメッセージを確認できます。実際のファイル操作は行われないため、設定内容の適切さを安全に検証することが可能です。</p>

<p>Logrotateは通常、親設定ファイル（/etc/logrotate.conf）を起点として、そこから全ての個別設定ファイル（/etc/logrotate.d/*）を読み込んで実行されます。
今回は実際の運用環境と同じような条件で正確に検証するためにも、シミュレーションは<strong>親設定ファイルを指定して実行します。</strong></p>

<p>（<strong>※親設定ファイルを指定して実行する理由についてはStep4の最後にまとめています</strong>）</p>

<p>以下のコマンドを実行して、作成した設定が意図通りに動くか確認してみましょう。</p>

<pre>
# 親設定ファイルを指定してdebugモードを実行
$ sudo logrotate --debug /etc/logrotate.conf
</pre>

<p><strong>出力の読み解き方</strong>:</p>

<p>コマンドを実行すると、以下のようなメッセージが表示されます。 出力を略していますが、下記「does not exist -- skipping」を見ると検証の結果が上手く行ってなさそうです。</p>

<p>親設定ファイル経由で全ての設定が読み込まれますが、httpd の検証結果に注目します。</p>

<p>（全出力のうち、一部を省略しています）</p>

<pre>
(略)
reading config file /etc/logrotate.conf
including /etc/logrotate.d
reading config file btmp
reading config file chrony
reading config file dnf
reading config file httpd
reading config file psacct
reading config file sssd
reading config file wtmp
Reading state from file: /var/lib/logrotate/logrotate.status
Allocating hash table for state file, size 64 entries
(略)
Handling 7 logs
(httpの出力のみ抜粋)
rotating pattern: /var/log/httpd/hoge_log /var/log/httpd/error_log after 1 days (5 rotations) empty log files are not rotated, old logs are removed 
considering log /var/log/httpd/hoge_log 
    <font color="red">log /var/log/httpd/hoge_log does not exist -- skipping Creating new state</font>
considering log /var/log/httpd/error_log
    Now: 2025-11-13 11:42
    Last rotated at 2025-11-13 11:00
    log does not need rotating (log has already been rotated)
(略)
</pre>

<h3>実行結果の読み解き方</h3>

<ul>
<li><strong>reading config file httpd</strong>: 
<ul>
<li>親設定ファイル（/etc/logrotate.conf）が、作成したApacheの設定ファイルを正しく読み込んでいることを示す。</li>
</ul></li>
<li><code>rotating pattern: /var/log/httpd/hoge_log /var/log/httpd/error_log after 1 days (5 rotations)</code>: 
<ul>
<li>設定ファイルで指定したローテート対象のローテーション頻度（daily→after 1 days）および保存世代数（rotate 5）が正しく認識されたことを示す。</li>
</ul></li>
<li><strong>empty log files are not rotated, old logs are removed</strong>: 
<ul>
<li>notifempty ディレクティブが有効になっているため、ファイルが空の場合はローテートしないこと、および古いログファイルは削除されること（rotateディレクティブの働き）が確認された。</li>
</ul></li>
<li><strong><font color="red">log /var/log/httpd/hoge_log does not exist -- skipping</strong></font>: 
<ul>
<li>赤字で記載した上記出力が今回の問題となった部分について</li>
<li><code>access_log</code>ではなく<code>hoge_log</code>というファイルが存在しないため、このファイルのローテートをスキップしたことを意味する。今回は意図的にパス名をミスしてみた。</li>
</ul></li>
<li><strong>log does not need rotating (log has already been rotated)</strong>: 
<ul>
<li>ローテートの条件を満たしていないため、ローテートが必要ではないと判断。</li>
<li>理由は、無の状態からログファイルを手動で作成したため、最後にローテートを実行してから日付が経過したというローテートステータスが存在しない。よって、ローテートを実行する条件を満たしていないことを意味する。</li>
<li>参照しているローテートステータスファイルはlogrotate.status。
今回の出力では意図した内容なので問題はなし。</li>
<li>ローテートの条件を満たしてた場合はlog needs rotatingと出力される。</li>
</ul></li>
</ul>

<p>「<strong>does not exist -- skipping</strong>」の出力を確認致しました。
この出力は、設定したパスにファイルが存在しないためスキップしたことを示しています。 今回の場合、設定したローテート対象のパスが間違っていたため、発生したエラーであることが<strong>debugモードのシミュレーション結果から判明しました</strong>。</p>

<p>パスを修正し、再度検証コマンドを実行してみます。</p>

<pre>
$ sudo vim /etc/logrotate.d/httpd
$ sudo logrotate --debug /etc/logrotate.conf
</pre>

<h3>実行結果の読み解き方</h3>

<p>コマンドを実行すると、以下のようなメッセージが表示されました。 成功していそうですね。</p>

<pre>
warning: logrotate in debug mode does nothing except printing debug messages! Consider using verbose mode (-v) instead if this is not what you want.
(略)
rotating pattern: /var/log/httpd/access_log /var/log/httpd/error_log after 1 days (5 rotations) 
empty log files are not rotated, old logs are removed considering log　/var/log/httpd/access_log 
    Now: 2025-11-13 11:57
    Last rotated at 2025-11-13 11:00
    log does not need rotating (log has already been rotated)
considering log /var/log/httpd/error_log
    Now: 2025-11-13 11:57
    Last rotated at 2025-11-13 11:00
    log does not need rotating (log has already been rotated)
not running postrotate script, since no logs were rotated
(略)
</pre>

<p>先程のdebugの実行では<strong>出力結果を省略しましたが</strong>、実行するとwarning（警告）メッセージが表示されます。一見するとwarning（警告）が出ているため不安に感じるかもしれませんが、最初のwarningメッセージは、「--debugモードは、デバッグメッセージの表示以外には何も実行しない」という、このオプションの仕様を説明しているものです。</p>

<p>成功した出力内容について確認してみます。</p>

<ul>
<li><code>considering log /var/log/httpd/access_log</code>: 
<ul>
<li>今回は does not exist のようなエラーは表示されていない。</li>
<li>ローテート対象のファイル名を正しく認識。</li>
</ul></li>
<li><strong>log does not need rotating (log has already been rotated)</strong>: 
<ul>
<li>ローテートの条件を満たしていないため、ローテートが必要ではないと判断。</li>
<li>理由は、無の状態からログファイルを手動で作成したため、最後にローテートを実行してから日付が経過したというローテートステータスが存在しない。よってローテートを実行する条件を満たさないことを意味する。</li>
<li>参照しているローテートステータスファイルはlogrotate.status。</li>
<li>今回の出力では意図した内容なので問題はなし。</li>
<li>満たしていた場合はlog needs rotatingと出力される。</li>
</ul></li>
<li><strong>not running postrotate script, since no logs were rotated</strong>:
<ul>
<li>ローテート条件を満たしていないため実行されなかった。</li>
<li>成功していた場合running postrotate scriptと出力。</li>
</ul></li>
</ul>

<p>--debugモードは、このように実行前に問題を特定できるため、本番環境で「思ったように動かない！」といったトラブルを未然に防ぐことができる非常に重要なStepでした。 このStepで問題がなければ、次の段階に進みましょう。</p>

<h3>注意</h3>

<p>「<strong>does not exist -- skipping</strong>」はよく見かけるエラーです。
簡単な例の場合は以下の状況が考えられます。</p>

<ul>
<li>ファイル名のスペルミス
<ul>
<li>設定ファイルに記載したファイル名が間違っていると、 Logrotateはファイルを見つけられずにエラーを返す。</li>
<li><strong>原因</strong>: <code>access_log</code>を<code>hoge_log</code>のように誤ってタイプした、など。</li>
<li><strong>対策</strong>: 設定ファイル内のファイルパスをもう一度確認し、正しいパスに修正する。</li>
</ul></li>
<li>ファイルの削除
<ul>
<li>なんらかの理由で、サービスがログを出力する前にログファイルが削除されてしまうと、Logrotateがファイルを見つけられなくなる。</li>
<li><strong>原因</strong>: 手動でログファイルを削除してしまった、など。</li>
<li><strong>対策</strong>: Logrotateのdebugモード前に処理前にファイルが存在しているか確認する。</li>
</ul></li>
<li>ログの出力先が異なる
<ul>
<li>サービスの設定（例：Apacheの設定ファイルhttpd）で指定されているログファイルの出力先が、Logrotateの設定と異なっている場合もこのエラーが発生する。</li>
<li><strong>原因</strong>: サービスは<code>/var/log/httpd/access_log</code>にログを出力しているのに、Logrotateの設定は<code>/etc/httpd/logs/access_log</code>になっている、など。</li>
<li><strong>対策</strong>: サービスの設定とLogrotateの設定の両方を確認し、ログの出力先を一致させる。</li>
</ul></li>
</ul>

<h3>※親設定ファイルを指定して実行する理由について</h3>

<p>実際の運用環境では、ローテート設定を編集した後、cronなどによってローテートが自動的に実行されるのを待ち、結果が反映されるのを待つことが多いです。</p>

<p>すぐに実行する場合でも、logrotate.dディレクトリ内の個別ファイルで実行するのではなく、logrotate.confという親設定ファイルを起点に実行するのが一般的です。個別ファイルでローテートを実行すると、親ファイルで定義された共通の設定が適用されず、実際の運用時の挙動と異なる可能性があります。そのため、本番環境で試す場合は親設定ファイルを指定して実行するか、もしくはローテートのcronの自動実行を待つのが最も安全です。</p>

<p>良くない例を簡単に紹介します。</p>

<p><strong>良くない設定例</strong>：
ローテートの親設定にApacheのローテート個別設定の代わりにdailyディレクティブが設定されているとします。</p>

<pre>
# rotate log files daily
daily
# packages drop log rotation information into this directory
include /etc/logrotate.d
</pre>

<p>また、下記Apacheのローテート個別設定ファイルにてdailyディレクティブが設定されていないとします。</p>

<pre>
/var/log/httpd/access_log /var/log/httpd/error_log {
    nocreate
    rotate 5
    compress
    delaycompress
    missingok
    notifempty
    dateext
    postrotate
        /bin/kill -HUP $(cat /var/run/httpd/httpd.pid)
    endscript
}
</pre>

<p>※上記設定状態でApacheの個別設定ファイルのみを指定してlogrotateを実行。</p>

<pre>
# Apacheの個別設定ファイルのみを指定してコマンドを実行
$ logrotate --debug /etc/logrotate.d/httpd
</pre>

<p>本来であれば上記親設定のローテートが実行されることによりdailyディレクティブの設定がApacheのローテート個別設定ファイルにも読み込まれるはずです。</p>

<p>しかし、Apacheのローテート個別設定ファイルを単体で実行してしまった場合、dailyディレクティブが適応されずに、意図しないローテート結果となってしまいます。この挙動は、以下の--debugモードの実行結果からも確認できます。</p>

<p>※<font color="red">赤字に注目</font>に注目</p>

<pre>
[root@ip-172-31-46-155 ~]# logrotate --debug /etc/logrotate.d/httpd
...(略)
Handling 1 logs
<font color="red">rotating pattern: /var/log/httpd/access_log /var/log/httpd/error_log  1048576 bytes (5 rotations)</font>
...(略)
considering log /var/log/httpd/error_log
...(略)
log does not need rotating (log size is below the 'size' threshold)
</pre>

<p>dailyディレクティブがない状態で個別ファイルを実行すると、上記<font color="red">rotating pattern</font>:に（1048576 bytes）ファイルサイズ1MBの判定が適用され、サイズ指定でローテートの判定が行われてしまいました。</p>

<p>以上のことから、このような予期しない挙動を防ぎ、安全かつ予測可能な結果を得るためにも、ローテートは必ず親設定ファイル（/etc/logrotate.conf）を起点に実行するか、ローテートが自動実行されるまで待つ必要があります。</p>

<h2>Step5: 実際にローテートを実行してみる</h2>

<p>--debugモードでのシミュレーション結果に問題がないことを確認したら、いよいよ実際にローテートを実行します。通常、Logrotateはcronやsystemd のタイマー機能によって自動的に実行されますが、今すぐローテートの挙動を確認したい場合は、手動でコマンドを実行する必要があります。</p>

<h3>--forceオプションについて補足</h3>

<p>--forceオプションは、dailyやweeklyといった設定ファイルに記述されたローテートのタイミングを無視して、強制的にローテートを実行するためのものです。</p>

<p><strong>メリット</strong>:</p>

<ul>
<li>即時検証: 設定変更が正しく機能するかを、日次や週次の自動実行を待たずにすぐに確認できる。</li>
<li>緊急対応: ディスク容量がひっ迫しているなど、緊急でログファイルをローテートする必要がある場合に役立つ。</li>
</ul>

<p><strong>デメリット</strong>:</p>

<ul>
<li><strong>運用から乖離</strong>: 実際の運用環境では--forceオプションはあまり使わない。本来のローテートタイミングを無視するため、本番環境でのテストは基本的に使わないようにする。</li>
<li><strong>意図しない挙動</strong>: 複数のログファイルがローテート対象になっている場合、--forceによって全てのログファイルが一度にローテートされてしまい、意図しないタイミングで別のログファイルのローテートが行われる可能性がある。</li>
</ul>

<p>前置きが長くなりましたが、ローテートの実行結果を確認しましょう。</p>

<pre>
# 親設定ファイルを指定して実行
$ sudo logrotate --force /etc/logrotate.conf
# 実行後のファイルを確認
$ sudo ls -l /var/log/httpd/
total 44
-rw-r--r--. 1 root root    0 Nov 13 12:01 access_log
-rw-r--r--. 1 root root   60 Nov 13 11:39 access_log-20251109.gz
-rw-r--r--. 1 root root   60 Nov 13 11:39 access_log-20251110.gz
-rw-r--r--. 1 root root   59 Nov 13 11:39 access_log-20251111.gz
-rw-r--r--. 1 root root   60 Nov 13 11:39 access_log-20251112.gz
-rw-r--r--. 1 root root   50 Nov 13 11:39 access_log-20251113
-rw-r--r--. 1 root root 1206 Nov 13 12:01 error_log
-rw-r--r--. 1 root root   59 Nov 13 11:39 error_log-20251109.gz
-rw-r--r--. 1 root root   59 Nov 13 11:39 error_log-20251110.gz
-rw-r--r--. 1 root root   58 Nov 13 11:39 error_log-20251111.gz
-rw-r--r--. 1 root root   59 Nov 13 11:39 error_log-20251112.gz
-rw-r--r--. 1 root root  856 Nov 13 12:01 error_log-20251113
</pre>

<p>実行後、<code>access_log</code>と<code>error_log</code>がそれぞれ<code>access_log-20251113</code>、<code>error_log-20251113</code>にリネームされ、 過去のファイルが圧縮されたり削除されたりしているのが確認できます。</p>

<p>一連の手順を通じて、複数のログファイルを一元管理する方法があるということが理解できたのではないでしょうか？</p>

<h2>現場で「ハマらない」ための重要ポイント</h2>

<h3>ログローテートはどのタイミングで実行される？</h3>

<p>Logrotate は、cron や systemd のタイマー機能を使って定期的に実行されるように設定されています。 </p>

<p>多くの Linux ディストリビューションでは、/etc/cron.daily/logrotate のようなスクリプトが用意されており、これが定期的に Logrotate コマンドを実行します。この仕組みがあるため、手動でコマンドを実行しなくても、設定ファイルに記述されたルール（例：dailyディレクティブやweeklyディレクティブ）に基づいて自動的にログローテートが行われるのです。</p>

<p>「設定ファイルを作成したのに動かない」という場合は、まずこの自動実行の仕組みが正しく動作しているか確認することも念頭に入れると良いです。</p>

<h3>ログが追記されない！？postrotate ディレクティブの重要性</h3>

<p>postrotateディレクティブ は、ログが途切れることなく記録されるようにするための、Logrotate で重要な設定の一つです。</p>

<h3>なぜ postrotateディレクティブが必要か？</h3>

<p>Apacheやphp-fpmのような多くのミドルウェアは、一度ログファイルを開くと、そのファイルハンドルを保持し続けます。Logrotateがファイルをリネームしたり削除したりしても、ミドルウェアは古いファイルハンドルを参照し続けるため、ログが新しいファイルに追記されなくなる問題が発生します。</p>

<p>この問題を解決するのが、postrotate ディレクティブです。</p>

<h3>postrotateディレクティブが問題を解決する！</h3>

<p>postrotateディレクティブは、ログローテート完了後に実行されるスクリプトやコマンドを定義するディレクティブです。</p>

<p>postrotateディレクティブに、ミドルウェアが新しいログファイルに正しくログを追記できるよう、<strong>ログファイルを再読み込みさせる</strong>ためのスクリプト、コマンドなどを記述します。今回の検証に利用したApacheであればHUPシグナルを利用できるため、ローテート実行後に、Apacheのプロセスを再起動せずに設定ファイルを再読み込みし、同時に現在開いているログファイルへのハンドル（ファイル記述子）を閉じ、新しいファイルを開き直す動作を実現できます。これにより、クライアントとのサービスを維持したまま、ログが途切れることなく新しいファイルに正しく記録されます。</p>

<h3>prerotate ディレクティブの設定について</h3>

<p>prerotateディレクティブは、postrotateディレクティブとは逆で、ログファイルがローテートされる直前に実行されるスクリプトを定義するディレクティブです。主な利用方法としては、ローテート処理中のログ欠損やファイル破損を防ぐ際に利用します。</p>

<p><strong>主な役割</strong></p>

<p>ログファイルに書き込みを行っているサービス、プロセスが存在する場合、そのサービス、プロセスを停止させずにローテート処理を実行すると、一部ログデータの欠損やファイル破損を招く可能性があるため、prerotateディレクティブが使用されるケースがあります。</p>

<ul>
<li><strong>利用方法</strong>: ログを出力しているサービスを一時的に停止し、postrotateディレクティブと併用しサービスを再開する運用が行われるケースがある。</li>
<li><strong>注意点</strong>: リアルタイム性が求められるWebサービスにおいて、サービスの一時停止はユーザーへの影響が大きいため利用は推奨されない。この運用は、バッチ処理やメンテナンス期間がある環境に推奨。</li>
<li><strong>推奨される環境</strong>：
<ul>
<li>定期的に実行停止されるバッチ処理やcronジョブ</li>
<li>開発・ステージング環境</li>
<li>重要度の低いバックグラウンドサービス</li>
<li>HUPシグナルを利用できるApacheやNginxとは違い、HUPシグナルを利用できないサービス</li>
</ul></li>
</ul>

<p>記述形式方法はpostrotateディレクティブと似ています。
endscriptディレクティブまでの間に実行したいスクリプトを下記のとおり記述します。</p>

<pre>
prerotate
    # ここに実行したいスクリプトやコマンドを記述
    /usr/bin/systemctl stop some-service.service
endscript
</pre>

<h2>Logrotate対象にならないログとは？</h2>

<p>Logrotateは、ログファイルへの追記のみを行うプレーンテキスト形式のログに最適です。以下のログはLogrotateの適用対象外、または利用が推奨されません。</p>

<p><strong>1. ログの「形式」：バイナリである（プレーンテキストではない）</strong></p>

<p>これは技術的にLogrotateが処理できないケースです。</p>

<ul>
<li><strong>対象</strong>: ログファイルの内容がテキストエディタで開いても読めない、または構造化されたバイナリデータ</li>
<li><strong>理由</strong>: Logrotateはファイルの読み書きを直接行わず、ファイル名のリネームやシグナル送信に依存します。しかし、バイナリ形式のログは、その構造上、システムやアプリケーション独自のツールでなければ安全に管理（パース、分割）ができないため</li>
<li><strong>例</strong>: systemd-journaldのようなジャーナル形式のログ（バイナリログ）</li>
</ul>

<p><strong>2. ログの「管理主体」：アプリケーション自身がファイル操作を行う</strong></p>

<p>これはLogrotateの操作と競合するため、適用が推奨されないケースです。</p>

<ul>
<li><strong>対象</strong>: アプリケーション（ミドルウェア）自身が、容量や時間に応じてログファイルをリネーム、圧縮、削除する機能（つまり、独自のローテート機能）を持っている場合。</li>
<li><strong>理由</strong>: Logrotateがログファイル名をリネームした直後に、アプリケーションもログファイルをリネームしようとするなど、操作が競合し、ログの欠損やファイルハンドルのエラーを引き起こすリスクがあるため</li>
<li><strong>例</strong>: Javaロギングフレームワーク (Logback/Log4j)など、フレームワーク自身がローテート機能を担う物</li>
</ul>

<h2>おわりに：Logrotateを使いこなすための3つのポイント</h2>

<p>Logrotate を安全かつ効果的に運用するには、以下の3つのポイントを押さえることが重要です。</p>

<ul>
<li><strong>検証の徹底</strong>: 本番環境に適用する前に、必ず--debug（debugモード）で設定をシミュレーションし、問題がないことを確認する。</li>
<li><strong>仕組みの理解</strong>: Logrotateの自動実行の仕組みと、postrotateの役割を把握することが不可欠。これにより、ログの欠損を防いだり、ログのアプリケーションが正常に動作し続けることを確認する。</li>
<li><strong>ログの特性把握</strong>: すべてのログがLogrotateで管理できるわけではない。対象のログが、Logrotateが処理できないバイナリ形式であったり、アプリケーションが独自のログ管理機能を持っていないかを確認する。</li>
</ul>

<p>本記事が、日々のログ管理の一助となれば幸いです。最後までお読みいただき、ありがとうございました！</p>

<h2>参照情報源</h2>

<p>logrotateのmanページ(公式ドキュメント)※manコマンドより確認</p>

<p><a href="https://httpd.apache.org/docs/current/stopping.html">Apache HTTP Server（Apache）公式ドキュメント</a></p>
]]>
    </content>
</entry>

<entry>
    <title>AWS Lambda Web Adapterを利用したWebアプリケーションの開発</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2025/07/aws-lambda-web-adapter.html" />
    <id>tag:heartbeats.jp,2025:/hbblog//2.945</id>

    <published>2025-07-28T00:30:00Z</published>
    <updated>2025-07-28T00:33:38Z</updated>

    <summary>こんにちは、技術開発チームの小嶋です。 本記事では、AWS Lambdaを利用し...</summary>
    <author>
        <name>小嶋 宏幸</name>
        <uri>https://heartbeats.jp/</uri>
    </author>
    
        <category term="技術" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>こんにちは、技術開発チームの小嶋です。</p>

<p>本記事では、AWS Lambdaを利用してWebアプリケーションを開発するために導入した <a href="https://github.com/awslabs/aws-lambda-web-adapter">AWS Lambda Web Adapter</a> について、その導入経緯や簡単な利用方法を紹介します。</p>
]]>
        <![CDATA[<p>AWS LambdaはAWSが提供しているサーバレスなコンピューティングサービスです。また、AWS Lambda Web AdapterはAWSが中心となって開発しているOSSライブラリです。AWS Lambda Web Adapterを使用することで、Dockerfileに1行の設定を追加するだけで、AWS Lambda上で動作するWebアプリケーションを簡単に開発できます。</p>

<h1>AWS Lambda Web Adapterを利用した経緯</h1>

<p>私が所属するチームではコンテナによる開発・運用を積極的に取り入れています。本番環境においては、クラウドのマネージド・サービスを利用して運用負荷を軽減したいという要望もあり、社内システムをAmazon ECS上で稼働させているケースが多くあります。Amazon ECSはAWSが提供しているコンテナオーケストレーションサービスの1つです。</p>

<p>今回開発した社内システムについても、当初はAmazon ECSによる稼働を想定していました。しかしながら、今回開発した社内システムは実験的な位置づけということもあり、スモールスタートでコストを抑えて運用をしたいという要望がありました。そのため、将来的にはAmazon ECSによる運用を想定しつつも、運用開始時はAWS Lambdaを利用してコストを抑える方針をとりました。</p>

<p>AWS Lambdaを利用してWebアプリケーションを開発する場合、特定の形式に従ったハンドラ関数を定義する必要があります。そのため、通常のWebアプリケーションのコードをそのままAWS Lambda上で動作させることはできず、ハンドラ関数のシグネチャを満たすようにコードを修正する必要があります。また、私が所属するチームではAWS LambdaをWebアプリケーションの基盤として本格的に利用するのが初めてだったため、ローカル開発環境の整備も必要な状況でした。</p>

<p>こうした課題を解決する手段を調査する中で、AWS Lambda Web Adapterの存在を知りました。以降はAWS Lambda Web Adapterで解決できる課題と簡単な利用方法について紹介します。</p>

<h1>AWS Lambda Web Adapterとは</h1>

<p>AWS Lambda Web AdapterはAWS社が中心となって開発しているOSSライブラリです。
　
AWS Lambda特有のハンドラ関数を定義せずに通常のWebアプリケーションをAWS Lambda上で実行できる点がAWS Lambda Web Adapterを利用する大きなメリットです。また、ローカルの開発環境についても通常のWebアプリケーション開発と同様の環境を利用できる点もメリットの1つです。</p>

<p>AWS Lambda Web AdapterはAWS LambdaランタイムとWebアプリケーションの間で動作するアダプターです。具体的な動作としては、AWS LambdaランタイムとWebアプリケーションの間で通信を仲介し、リクエスト・レスポンスを変換します。そのため、AWS Lambda特有のハンドラ関数を定義する必要がなく、通常と同じWebアプリケーションとしてコードを作成するだけでAWS Lambda上でアプリケーションを実行できます。</p>

<p><img src="/hbblog/2025/07/11/aws-lambda-web-adapter01.png" alt="AWS Lambda Web Adapter" title="" /></p>

<h1>AWS Lambda Web Adapterの使い方</h1>

<p>AWS Lambda Web Adapterの説明のため、コンテナ化されたWebアプリケーションについて考えます。例えば、Pythonと<a href="https://fastapi.tiangolo.com/ja/">FastAPI</a>フレームワークを利用してWebアプリケーションを開発する場合、Dockerfileは下記のようなイメージとなります。</p>

<pre>
FROM python:3.13

WORKDIR /code

# ライブラリをインストールする
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

# アプリケーションコードをコピーする
COPY ./app /code/app

# アプリケーションを起動する
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]
</pre>

<p>AWS Lambda Web Adapterはコンテナ化されたWebアプリケーションと合わせて利用します。具体的にはAWS Lambda Web Adapterのコードをコピーする設定をDockerfileに1行追加します。</p>

<pre>
FROM python:3.13

WORKDIR /code

# -- この行を追加する --
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.1 /lambda-adapter /opt/extensions/lambda-adapter

# ライブラリをインストールする
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

# アプリケーションコードをコピーする
COPY ./app /code/app

# アプリケーションを起動する
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]
</pre>

<p>上記のように、Dockerfileのその他の内容は通常のWebアプリケーション開発と同じものを利用できます。そのため、AWS Lambda特有のハンドラ関数のシグネチャを満たすように修正する場合と比較して、修正を大幅に簡略化できます。また、AWS Lambda Web Adapterの利用をやめる際にもDockerfileから設定を1行削除するのみで対応が完了します。Amazon ECSなどへ運用基盤を移行する際にも修正が容易です。</p>

<p>AWS Lambda Web Adapterはいくつかの項目を環境変数で設定できます。環境変数の設定は、ローカルで開発する場合はターミナルで設定し、Lambdaで実行する場合はAWSマネジメントコンソールでLambda環境変数として設定します。例えば、Webアプリケーションのポート番号（<code>AWS_LWA_PORT</code>）やヘルスチェックのパス（<code>AWS_LWA_READINESS_CHECK_PATH</code>）といった項目です。今回開発したWebアプリケーションでは、AWS Lambda Web Adapterがデフォルトで利用するポート番号（8080）を変更する必要があったため、<code>AWS_LWA_PORT</code>を利用してポート番号を設定しました。設定項目の一覧はGitHubリポジトリの<a href="https://github.com/awslabs/aws-lambda-web-adapter?tab=readme-ov-file#configurations">ドキュメント</a>を参照してください。</p>

<p>以上のように、Dockerfileへ設定を1行追加するだけでAWS Lambda上で動作するWebアプリケーションを開発できます。今回開発した社内システムについても通常のWebアプリケーション開発と同じ感覚で開発を進めることができ、開発者体験としてもよいものだったと感じています。</p>

<h2>おわりに</h2>

<p>本記事では、AWS Lambdaを利用してWebアプリケーションを開発するために導入した <a href="https://github.com/awslabs/aws-lambda-web-adapter">AWS Lambda Web Adapter</a> について、その導入経緯や簡単な利用方法を紹介しました。AWS LambdaでWebアプリケーションを開発する際に便利なのでぜひ試してみてください。</p>
]]>
    </content>
</entry>

<entry>
    <title>Nginx連載記事から13年で変わったこと</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2025/06/nginx-13-years-on-whats-changed.html" />
    <id>tag:heartbeats.jp,2025:/hbblog//2.938</id>

    <published>2025-06-09T06:00:00Z</published>
    <updated>2025-06-09T06:22:12Z</updated>

    <summary>こんにちは、開発グループの鈴木です。 このブログ内で2012年に公開した全6回の...</summary>
    <author>
        <name>鈴木 隆世</name>
        
    </author>
    
        <category term="技術" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>こんにちは、開発グループの鈴木です。</p>

<p>このブログ内で2012年に公開した全6回のnginx連載は、今なお多くの方に見ていただけています。
そこで今回は、連載当時から現在までで内容のアップデートがあった箇所をピックアップして紹介します。  </p>

<p>結果としては、基本的な設定方法などはほとんど変わっておらず、連載で紹介した設定が今でも利用可能であることがわかりました。
その一方で、新しいプロトコルへの対応やnginx自体を取り巻く状況などが変わっていましたので紹介します。</p>
]]>
        <![CDATA[<h2>nginxの概要</h2>

<p>連載時（2012年）のnginxの安定版バージョンは1.0.12でした。2025年6⽉現在の最新安定バージョンは1.28.0になっています。</p>

<p>nginx連載当時はまだnginxが日本で流行り始めたころであり、webサーバーのシェアとしては訪問者数トップ100万サイトのサーバーで10%程度と紹介しています。
連載時にも参照したNetCraft社による調査の2024年版である「<a href="https://www.netcraft.com/blog/september-2024-web-server-survey">september-2024-web-server-survey</a>」によると、2024年9月時点ではnginxはトップサーバーで20.29％のシェアになっています。
nginxは一時期26％のシェアを持っていましたが、近年はシェアが減少傾向となっています。
これは簡単にウェブページを公開できる様々なwebホスティングサービスが増え、新たにwebサーバーを自前で管理し公開するケースが全体的に減少し、nginxやApache HTTP Serverなどのシェア減少につながっていると考えられます。</p>

<p>また、nginxはNginx.Incによる管理でしたが、Nginx.IncがF5 Networks.Incに買収されたことにより、F5 Networks.Incの管理となっています。
2024年にコア開発者がF5社との方向性の違いなどによりnginxの開発から離れ、<a href="https://freenginx.org">freenginx</a>というnginxフォークが開発されていたりします。</p>

<h2>nginx連載時から設定の変更があった点</h2>

<p>nginx連載で紹介した設定のうち、変更があった点を紹介します。
ただ冒頭でも書いたように、以前の連載から大きな変更はなく、<a href="https://heartbeats.jp/hbblog/2012/06/nginx06.html">連載6回目</a>で紹介しているSSL/TLS周りの設定で少し変更があったのみでした。</p>

<h3>sslディレクティブの削除</h3>

<p><a href="https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl">sslディレクティブ</a>がver1.25.1で削除されました。
ver1.25.1以降はlistenディレクティブ内でだけsslが指定できるようになっています。</p>

<p>ver1.15.0からすでにsslディレクティブはdeprecatedになっており、sslディレクティブを利用すると警告が出る状態になっていました。
しかし、ver1.25.1からsslディレクティブが削除され利用できなくなりました。</p>

<pre><code>listen 443;
ssl on;
</code></pre>

<p>ver1.25.1以降は下記のようにlistenディレクティブでのみ指定するようになりました。</p>

<pre><code>listen 443 ssl;</code></pre>

<h3>TLS1.3の追加とデフォルトでの有効化</h3>

<p><a href="https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols">ssl_protocols</a>では、ver1.13.0から指定できるプロトコルにTLS1.3が追加され、ver1.23.1からデフォルトでTLS1.3が有効になりました。</p>

<pre><code>ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;</code></pre>

<h2>新しくできるようになったこと</h2>

<p>以前の連載からここ数年まででの大きな変更点は、HTTP2、HTTP3、QUICプロトコルに対応したことです。
また、ver1.25.1まではHTTP2を有効にする際、listenディレクティブでhttp2と指定していましたが、ver1.25.1以降は別途<a href="https://nginx.org/en/docs/http/ngx_http_v2_module.html#http2">http2ディレクティブ</a>で<code>on|off</code>を指定するようになりました。</p>

<pre><code>;; ver1.25.0以前
listen 443 ssl http2;
</code></pre>

<pre><code>;; ver1.25.1以降
listen 443 ssl;
http2 on;
</code></pre>

<p>QUICとHTTP3はver1.25以降であればビルドせずに利用できます。
ただし、2025年6月現在ではどちらも実験的サポートである点には注意が必要です。
HTTP3はHTTP2と同様に<a href="https://nginx.org/en/docs/http/ngx_http_v3_module.html#http3">http3ディレクティブ</a>で<code>on</code>を指定することで有効化できます。
また、QUICはlistenディレクティブで指定することによって有効化できます。</p>

<pre><code>http3    on;
listen 443 quic;
</code></pre>

<p>HTTP3とQUICの設定については、下記公式ドキュメントを参考にしてください。</p>

<ul>
<li><a href="https://nginx.org/en/docs/http/ngx_http_v3_module.html">Module ngx<em>http</em>v3_module</a></li>
<li><a href="https://nginx.org/en/docs/quic.html">Support for QUIC and HTTP/3</a></li>
</ul>

<h2><code>ngx_stream_pass_module</code>の追加</h2>

<p>nginx連載では触れていない部分ですが、<code>stream</code>ディレクティブ内で<code>pass</code>ディレクティブが使える様になったので紹介します。
以前から<code>stream</code>ディレクティブでサーバーを設定した場合に、<code>proxy_pass</code>ディレクティブを利用することで通信をプロキシさせることは可能でした。
しかし、ver1.25.5より<a href="https://nginx.org/en/docs/stream/ngx_stream_pass_module.html"><code>ngx_stream_pass_module</code></a>が追加され、<code>pass</code>ディレクティブを利用することでプロキシではなくクライアントからの通信を直接上流に渡せることができるようになりました。</p>

<p>実際に<code>pass</code>ディレクティブを使用したときの動作を下記の環境で確認してみました。</p>

<ul>
<li>nginxサーバー（クラウド上の仮想サーバー）
<ul>
<li>OS: AlmaLinux OS 8.10</li>
<li>nginx: nginx 1.26.0</li>
</ul></li>
<li>アクセス元（ローカルPC）
<ul>
<li>curl 8.7.1</li>
</ul></li>
</ul>

<p>今回の検証では、<code>stream</code>ディレクティブ以外のnginx設定については、nginxインストール時のデフォルトのものを利用します。
そのため、80番ポートにHTTPアクセスすることでnginxのウェルカムページが表示されるようになっています。</p>

<p>nginx.confの末尾に下記設定を追記してstreamでリクエストを受け付け、80番ポートで受け付けている仮想サーバーに通信を受け渡すように設定します。
また、<code>proxy_pass</code>と<code>pass</code>の挙動の違いを確認するため、両方の設定を追加して確認していきます。</p>

<pre><code># /etc/nginx/nginx.confに追記

http {
    ## コンテンツ用(一部抜粋)
    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        ...
    }
}

stream {
    ## 検証用(passディレクティブ)
    server {
        listen 8443 ssl;
        error_log /var/log/nginx/stream.log info;

        # 自己証明書を作成・指定
        ssl_certificate     /etc/nginx/ssl/crt.pem;
        ssl_password_file   /etc/nginx/ssl/password;
        ssl_certificate_key /etc/nginx/ssl/private.key;

        # ngx_stream_pass_moduleで追加されたpassディレクティブを利用する
        pass 127.0.0.1:80;
    }

    ## 検証用(proxy_passディレクティブ)
    server {
        listen 8843 ssl;
        error_log /var/log/nginx/stream_proxy.log info;

        # 自己証明書を作成・指定
        ssl_certificate     /etc/nginx/ssl/crt.pem;
        ssl_password_file   /etc/nginx/ssl/password;
        ssl_certificate_key /etc/nginx/ssl/private.key;

        # proxy_passディレクティブを利用する
        proxy_pass 127.0.0.1:80;
    }
}
</code></pre>

<p>設定ができたので、まずは従来どおりプロキシを行う場合でのアクセスをしてみます。
アクセスは<code>curl</code>で行いますが、テスト用に自己証明書でサーバーを設定しているため、<code>-k</code>オプションをつけて証明書の検証をスキップさせています。</p>

<pre><code>curl https://&lt;nginxサーバーのIPアドレス&gt;:8843 -k
</code></pre>

<p>ウェルカムページのアクセスログとstreamサーバーのログを確認すると、正常に通信がプロキシされていることがわかります。
また、通信がプロキシされているため、アクセスログのアクセス元IPアドレスがローカルループバックアドレスになっていることも確認できます。</p>

<pre><code>### ウェルカムページのアクセスログ
127.0.0.1 - - [24/Nov/2024:14:38:16 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.7.1" "-"

### streamログ
2024/11/24 14:38:16 [info] 11467#11467: *2 client <ローカルPCのIPアドレス>:64922 connected to 0.0.0.0:8843
2024/11/24 14:38:16 [info] 11467#11467: *2 proxy 127.0.0.1:38972 connected to 127.0.0.1:80
</code></pre>

<p>今度は、<code>pass</code>ディレクティブを利用しているポートへアクセスしてみます。</p>

<pre><code>curl https://&lt;nginxサーバーのIPアドレス&gt;:8443 -k
</code></pre>

<p>ウェルカムページのアクセスログではアクセス元のIPアドレスがローカルループバックアドレスではなくなり、ローカルPCのIPアドレスが表示されていることが確認できました。
また、streamのログを確認すると<code>proxy_pass</code>を利用した場合と異なり通信をプロキシしたログがなく、通信がプロキシ処理されずに直接上流のサーバーへと渡されていることがわかります。</p>

<pre><code>### ウェルカムページのアクセスログ
<ローカルPCのIPアドレス> - - [24/Nov/2024:14:41:27 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.7.1" "-"

### streamログ
2024/11/24 14:41:27 [info] 11467#11467: *5 client <nginxサーバーのIPアドレス>:65029 connected to 0.0.0.0:8443
</code></pre>

<p><code>pass</code>ディレクティブを使うことでプロキシ処理をせずに通信が受け渡されるようになるため、streamで受け付けるサーバーでの分散や単純な後続サーバーへの通信の受け渡しだけを行っている場合は、通信のオーバーヘッドが減り処理性能向上などが見込めそうです。</p>

<h2>おわりに</h2>

<p>今回はnginx連載のうち主に変更があった点を紹介しました。基本的な設定は変わっておらず、引き続き運用や管理ができるのは嬉しいところです。ただ、新しいプロトコルの対応や機能の追加などもありますので、引き続き情報の収集を怠らず利用していきたいです。</p>

<p>参考として過去のnginx連載の記事URL一覧を記載します。
よろしければ、あわせてご覧ください。</p>

<ul>
<li><a href="https://heartbeats.jp/hbblog/2012/01/nginx01.html">連載1回目: nginxの紹介</a></li>
<li><a href="https://heartbeats.jp/hbblog/2012/02/nginx02.html">連載2回目: nginxのインストール</a></li>
<li><a href="https://heartbeats.jp/hbblog/2012/02/nginx03.html">連載3回目: nginxの設定、その1</a></li>
<li><a href="https://heartbeats.jp/hbblog/2012/04/nginx04.html">連載4回目: nginxの設定、その2 - バーチャルサーバの設定</a></li>
<li><a href="https://heartbeats.jp/hbblog/2012/04/nginx05.html">連載5回目: nginxの設定、その3 - locationディレクティブ</a></li>
<li><a href="https://heartbeats.jp/hbblog/2012/06/nginx06.html">連載6回目: nginxの設定、その4 - TLS/SSLの設定</a></li>
</ul>
]]>
    </content>
</entry>

<entry>
    <title>認証維持で終わらない！ISMSを取得している企業で避けがちな2項目に対処した話</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2025/06/isms-1.html" />
    <id>tag:heartbeats.jp,2025:/hbblog//2.944</id>

    <published>2025-06-05T04:00:00Z</published>
    <updated>2025-06-05T04:15:52Z</updated>

    <summary>こんにちは、事業基盤グループ情報セキュリティ担当の岩屋です。 今回は、ISMSを...</summary>
    <author>
        <name>岩屋 美紀</name>
        
    </author>
    
        <category term="活動" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>こんにちは、事業基盤グループ情報セキュリティ担当の岩屋です。</p>

<p>今回は、ISMSを取得している企業で避けがちな2項目に対処した話を紹介します。前回投稿した「<a href="https://heartbeats.jp/hbblog/2024/10/isms.html">情報セキュリティマネジメントシステム（ISMS）認証取得までの取り組み</a>」に続き、認証取得後の情報セキュリティ強化に関する活動をまとめました。</p>
]]>
        <![CDATA[<h2>ISMS認証取得後の情報セキュリティ強化</h2>

<p>ISMSは認証取得がゴールではなく、PDCAサイクルに沿って継続的に運用・改善することが求められます。情報セキュリティを取り巻く環境や脅威は常に変化するため、認証取得当初の運用が将来的にも有効であるとは限りません。そこで、弊社では認証取得後もさらなる情報セキュリティの強化を目指し、以下の取り組みを実施しました。</p>

<ol start='1'>
<li>BCP訓練の強化</li>
<li>クラウドサービスアカウント管理の仕組み化</li>
</ol>

<h2>1. BCP訓練の強化</h2>

<p>BCPとは、事業継続計画（Business Continuity Planning）の略称であり、自然災害やクラウドサービスの障害、個人情報漏えいなどのインシデントが発生した場合に、被害を最小限に抑え、事業を継続するための計画です。</p>

<p>「そのようなインシデントは自分の周りでは起こらないだろう」と考えがちですが、<strong>実際にはいつ発生しても不思議ではありません</strong>。いざという時に適切な連携を取り、対応できるよう、日頃からの訓練が重要です。防災訓練で火災が起きた場合を想定し、消火活動の訓練や避難経路の確認をするように、情報漏えいを想定し、報告先や報告手順を事前に訓練しておくことで、いざというとき冷静に行動できます。</p>

<h3>具体的な実施内容</h3>

<p>部署別に関連性の高いインシデントの例（以下に記載）を用意し、少人数制のワーキンググループ形式で訓練を実施しました。訓練を円滑に進められるよう、事前に参加者へBCPの重要性や目的をまとめた資料を共有しました。また、訓練当日はISMS事務局が進行を担当することで、参加者間の活発な議論が行えるよう工夫しました。</p>

<p>訓練は、インシデントが発生した際の初動対応から応急対応までの流れを中心に確認を行います。具体的には社内ドキュメントや報告手順の確認と被害拡大を防止する対応策について議論をしました。応急対応までの流れを確認した後に、当日の振り返りを行い、<strong>インシデントが発生した場合は速やかに報告することの重要性</strong>を再確認し終了となります。</p>

<h4>【インシデントの例】</h4>

<ul>
<li>PCがランサムウェアに感染した場合</li>
<li>イベント参加中にPCを紛失した場合</li>
<li>提供しているサービスの顧客から、意図しないファイルの受信報告を受けた場合</li>
<li>お客様から情報漏えいの疑いがあるとの報告を受けた場合</li>
</ul>

<h3>実施した気づき</h3>

<p>自由な意見交換を通じて、対応手順や留意点を参加者全体で共有することができました。部署ごとに具体的なインシデントの例を用いたことで、実際の状況を想定した手順確認が可能となり、効果的な訓練となりました。
一方で、今回の訓練では初動対応や応急対応の実践的な行動は含まれておらず、対応力の強化には実践を伴う訓練も必要であることに気づきました。実践型の要素を加えることで、さらに実効性のある訓練になるよう、今後の訓練に反映していきます。</p>

<p>また、訓練中に実際の対応手順と照らし合わせながら進めたことで、手順の不備や曖昧な点に気づき、手順の継続的な見直しと更新の重要性を再認識する機会となりました。
インシデント発生時には迅速かつ的確な判断が求められるため、平時から実践に近い形で訓練を行うことが、組織全体の対応力向上につながるという重要な気づきを得ました。</p>

<h2>2. クラウドサービスアカウント管理の仕組み化</h2>

<p>弊社では業務上多くのクラウドサービスを利用しています。クラウドサービスの選定基準については<a href="https://heartbeats.jp/hbblog/2024/10/isms.html">前回の記事</a>で触れていますので、今回はクラウドサービスのアカウントを適切に管理するための取り組みを紹介します。</p>

<p>弊社では独自のID管理システムでアカウントの管理をしています。APIやSCIMに対応したクラウドサービスはID管理システムに連携させ、アカウントの新規発行や削除を自動で行っています。しかし、APIやSCIMに対応していない多くのクラウドサービスではID管理システムが使えず、手作業でアカウントの管理を行うしかありませんでした。手作業の場合は作業の抜け漏れが発生しやすく、結果として<strong>不要な権限やアカウントが棚卸のタイミングまで残存し続け、情報漏えいのリスクが高まる</strong>ことが課題でした。</p>

<p>まずはアカウント管理を強化するため、ID管理用のSaaSサービスの検討を始めました。しかし、APIやSCIMの利用が前提になっているものばかりで、弊社のID管理システムの代替になり得ませんでした。</p>

<p>そこで、削除漏れを通知することを目的として、Google Apps Script（以下「GAS」）を活用し、アカウントを管理する仕組みを自前で構築することにしました。</p>

<h3>具体的なアカウントの管理方法</h3>

<p>まず、クラウドサービス別にアカウント情報を一元管理するスプレッドシートを作成します。次に、このシートを社内システムと連携させ、アカウントの新規発行と削除依頼をSlackに自動で通知する仕組みをGASで構築しました。</p>

<p><img src="/hbblog/72abcb73e7dc24c7a87ca65a564f4e690d33201b.png" alt="クラウドサービスアカウント管理シート" title="" /></p>

<p>　　　　　　　　</p>

<p>シート上の「ハートビーツ 次郎」さんの退職を例に、具体的な流れを解説します。</p>

<ol start='1'>
<li>次郎さんが退職日を迎える</li>
<li>社内従業員の人事システム等の社員マスターデータから次郎さんのアカウントを削除する</li>
<li>次郎さんの退職をGASで検知し、 関連するアカウントをシートから収集し、サービスA,C,Dの担当者宛に削除依頼をSlackに通知する</li>
<li>通知を受けたクラウドサービスの担当者は、クラウドサービス上でアカウントを削除した後、シートから退職者のレコードを自身で削除する</li>
<li>シート上のアカウント発行数が自動的に1つ減る</li>
<li>シートの管理者は次郎さんのアカウント発行数が「0」になったことを確認できたら、シートから次郎さんの行を管理者が削除することで完了となる</li>
</ol>

<p>このような仕組みを取り入れてアカウント管理の仕組みを半自動化したことで、<strong>アカウントの削除漏れがなくなり、セキュリティリスクを低減</strong>することができました。</p>

<h2>おわりに</h2>

<p>情報セキュリティはサイバー攻撃の進化など情勢に応じて、絶えず変化します。ISMS取得や維持が目的ではなく、企業の情報資産を適切に保護し利用することが本来の目的なので、目的を見失わずに情報セキュリティレベルを向上し続けるよう活動していきます。ISMS認証を取得されている方や、同じように情報セキュリティを担当されている方の参考になれば幸いです。</p>
]]>
    </content>
</entry>

<entry>
    <title>TLSプロトコル拡張機能のServer Name Indication（SNI）を理解する</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2025/05/tlsserver-name-indicationsni.html" />
    <id>tag:heartbeats.jp,2025:/hbblog//2.942</id>

    <published>2025-05-29T01:00:00Z</published>
    <updated>2025-05-29T01:08:31Z</updated>

    <summary>こんにちは。24年度に新卒入社した運用チームの又吉です。 普段サーバの監視業務を...</summary>
    <author>
        <name>又吉 雄斗</name>
        
    </author>
    
        <category term="技術" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>こんにちは。24年度に新卒入社した運用チームの又吉です。</p>

<p>普段サーバの監視業務をする中で、HTTPS通信中にクライアントがWebサーバに対してどのホスト名で接続したいかを伝える、TLSプロトコルの拡張機能である「Server Name Indication（以降SNIとする）」を知りました。そこで、今回は運用エンジニア1年生である私の学習も兼ねてSNIの仕組みについて、検証しながら記します。</p>

<p>この記事ではSNIについて実験するために、著者が手馴れている<a href="https://www.nagios.org/">Nagios</a>のHTTP監視プラグインである<a href="https://github.com/nagios-plugins/nagios-plugins/blob/master/plugins/check_http.c">check_http</a>コマンドを利用していますが、多くの方に試してもらえるようにopensslコマンドでの確認方法もところどころで併記します。</p>

<p>CDNを利用したWebページの場合、なぜSNIを使う必要があるのか、そしてそもそもSNIとは何か理解したかったため調査・検証しました。</p>

<p>SNIについてよりイメージしやすいよう、本稿はコマンドのデバッグやパケットキャプチャ等でSNIの具体的な姿を確認できる内容になっています。本稿がSNIをより深く理解する助けになれば幸いです。</p>
]]>
        <![CDATA[<h2>Server Name Indication（SNI）とは</h2>

<p>SNIは一つのWebサーバで複数のドメインをホストする際に利用するための仕組みです。
SNIではHTTPS通信のTLSハンドシェイク時にクライアントがサーバに対し接続したいホスト名を伝えることができます。そうすることでWebサーバがどのSSL/TLS証明書を使うのか切り替えるようにできます。SNIはTLSプロトコルの拡張機能の一つで、<a href="https://datatracker.ietf.org/doc/html/rfc6066">RFC6066</a>で標準化されています。</p>

<p>複数のドメイン名をホストする具体例としてWebサーバのソフトウェアであるnginxやApacheのバーチャルホストの機能が挙げられます。SNIを利用することによりSSL/TLS層でドメイン名を判別できるため、ドメイン名ごとにSSL/TLS証明書の使い分けが可能になります。</p>

<h2>SNIを利用することのできるコマンド</h2>

<p>以下ではSNIを利用する方法を説明します。</p>

<h3>check_httpコマンドでSNIを利用する</h3>

<p>check_httpの使い方については<a href="https://heartbeats.jp/hbblog/2023/01/check-http.html">Nagios Pluginsのcheck_httpを使いこなそう</a>を参考にしてみてください。</p>

<p>ここではSNIを利用するための--sniオプションに注目します。--sniオプションについて、check_httpコマンドの--helpオプションでは以下のように説明されています。</p>

<pre>
$ check_http --help
〜省略〜
 --sni
    Enable SSL/TLS hostname extension support (SNI)
〜省略〜
</pre>

<p>SNIはTLSの拡張機能なので次のように--sslオプションと併用します。</p>

<pre>
$ check_http -H example.com -f follow --ssl --sni
HTTP OK: HTTP/1.1 200 OK - 17291 bytes in 0.582 second response time |time=0.582172s;;;0.000000 size=17291B;;;0
</pre>

<p>Amazon CloudFrontやCloudflare CDNといったContents Delivery Network（以降CDNとする）を利用したWebページに対してcheck_httpコマンドを実行する場合、--sniオプションを付けずに実行すると以下のようにCannot make SSL connectionが応答します。</p>

<pre>
$ check_http -H example.com -f follow --ssl
CRITICAL - Cannot make SSL connection.
139844870334400:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:769:
</pre>

<h3>opensslコマンドでSNIを利用する</h3>

<p>openssl s_clientのヘルプには-servernameオプションが次のように説明されています。</p>

<pre>
$ openssl s_client -help
～省略～
 -servername val            Set TLS extension servername (SNI) in ClientHello (default)
～省略～
</pre>

<p>opensslでSNIを利用する場合は、次のようにコマンドを実行します。</p>

<pre>
$ openssl s_client -connect example.com:443 -servername example.com -quiet
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root G3
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert Global G3 TLS ECC SHA384 2020 CA1
verify return:1
depth=0 C = US, ST = California, L = Los Angeles, O = Internet Corporation for Assigned Names and Numbers, CN = *.example.com
verify return:1
^C  (CTRL+Cで止める)
</pre>

<p>以下からは実際にWebサーバを構築し、RFCの文書を参考にしつつ、コマンドのデバッグ、パケットキャプチャを通して--sniオプションおよびSNIの理解を深めていきます。</p>

<h2>検証環境の構築</h2>

<p>今回はAmazon EC2のAmazon Linux2のインスタンスを2台起動して次の名前で構築します。</p>

<ul>
<li>web-sandbox（Webサーバをインストールするインスタンス）</li>
<li>nagios-sandbox（check_httpコマンドをインストールするインスタンス）</li>
</ul>

<p>以下に今回利用するソフトウェアのバージョン情報を示します。</p>

<table border="1">
    <tr>
        <td>ソフトウェア</td>
        <td>バージョン情報</td>
    </tr>
    <tr>
        <td>nginx</td>
        <td>nginx/1.22.1</td>
    </tr>
    <tr>
        <td>Nagios Plugins check_http</td>
        <td>2.4.9</td>
    </tr>
    <tr>
        <td>openssl</td>
        <td>1.0.2k</td>
    </tr>
    <tr>
        <td>gdb</td>
        <td>8.0.1</td>
    </tr>
    <tr>
        <td>wireshark-cli</td>
        <td>2.6.2</td>
    </tr>
</table>

<p>次にそれぞれのサーバでのインストール作業や設定を示します。なお、EC2インスタンスやセキュリティグループ等の設定の説明は省略します。</p>

<h3>web-sandboxインスタンス</h3>

<p>web-sandboxインスタンスにはnginx、SSL/TLS証明書作成に必要なopenssl、そしてパケットキャプチャをするためのwireshark-cliをインストールします。</p>

<pre>
### nginxのインストールと起動
$ sudo amazon-linux-extras enable nginx1
$ sudo yum -y install nginx
$ sudo systemctl enable --now nginx

### opensslのインストール
$ sudo yum -y install openssl-devel

### wireshark-cliのインストール
$ sudo yum install -y wireshark-cli
</pre>

<p>nginxで複数のドメイン名をホストするよう、以下のように設定を追加します。
/usr/share/nginx/html/index.htmlや/usr/share/nginx/html2/index.htmlもそれぞれ別のコンテンツが表示されるように作成しておきます。設定の追加後はnginxの再起動をして設定を反映させましょう。</p>

<pre>
server {
    listen       80;
    listen       [::]:80;
    server_name  example.com;
    root         /usr/share/nginx/html;
    listen 443 ssl;
    ssl_certificate     /home/ec2-user/server.crt;
    ssl_certificate_key /home/ec2-user/server.key;
}
server {
    listen       80;
    listen       [::]:80;
    server_name  cert1.example.com;
    root         /usr/share/nginx/html2;
    listen 443 ssl;
    ssl_certificate     /home/ec2-user/server1.crt;
    ssl_certificate_key /home/ec2-user/server1.key;
}
</pre>

<p>今回はSSL/TLS接続を行いたいのでopensslコマンドでSSL/TLS証明書を作成します。ドメイン名が二つあるので二つ作成しておきます。CSRを作成する際に色々と情報の入力を求められますが、今回の検証においてはCommon Name（CN）のみ設定します。</p>

<pre>
$ openssl genrsa 2048 > server.key
$ openssl req -new -key server.key > server.csr
$ openssl x509 -in server.csr -days 365000 -req -signkey server.key > server.crt

$ openssl genrsa 2048 > server1.key
$ openssl req -new -key server1.key > server1.csr
$ openssl x509 -in server1.csr -days 365000 -req -signkey server1.key > server1.crt
</pre>

<h3>nagios-sandboxインスタンス</h3>

<p>nagios-sandboxインスタンスにはNagios Pluginsのcheck_http、SSL/TLS証明書確認のためのopensslと、 コマンドをデバッグするためのgdbをインストールします。なお、デバッグ情報無しでgdbでデバッグしようとすると「Missing separate debuginfos, use: debuginfo-install nagios-plugins-http-2.4.9-1.el7.x86_64」のようなメッセージが表示されるのでそれに従いデバッグ情報をインストールしておきます。</p>

<pre>
### check_httpのインストール
$ sudo amazon-linux-extras install epel -y
$ sudo yum -y install nagios-plugins-http
$ export PATH=$PATH:/usr/lib64/nagios/plugins

### opensslのインストール
$ sudo yum -y install openssl-devel

### gdbのインストール
$ sudo yum -y install gdb
$ sudo debuginfo-install nagios-plugins-http-2.4.9-1.el7.x86_64 -y
</pre>

<p>web-sandboxインスタンスに対してドメイン名で接続等できるように/etc/hostsに以下のように追記しておきます。</p>

<pre>
&lt;web-sandboxのIPアドレス&gt; example.com       # Nginxでの検証に使用
&lt;web-sandboxのIPアドレス&gt; cert1.example.com # Nginxでの検証に使用
&lt;web-sandboxのIPアドレス&gt; cert2.example.com # --verify-hostオプション検証に使用
</pre>

<h2>--sniオプションを付けると何が起きるか理解する</h2>

<p>まずはcheck_httpコマンドをデバッグして、--sniオプションを付けた場合に何が起きるか確認してみます。</p>

<p>nagios-sandboxにて以下のようにcheck_http関数をブレークポイントに設定し処理をたどります。setでcheck_httpコマンドのオプションを指定しており、-tでタイムアウト時間を5000秒とすることでデバッグ中にコマンドがタイムアウトすることを防ぎます。</p>

<pre>
$ gdb /usr/lib64/nagios/plugins/check_http
(gdb) set args -H example.com -f follow --sni --ssl -t 5000
(gdb) b check_http
(gdb) r
</pre>

<p>そのようにして処理を追うとssl3_ctrlという関数に辿り着きます。ssl3_ctrl関数はcase文で分岐しており、--sniオプションを付けた際の処理はcase SSL_CTRL_SET_TLSEXT_HOSTNAMEの部分にあります。例外処理等を除くと下記3327行目の処理にてSSL構造体のtlsext_hostnameにホスト名（今回の場合はexample.com）を設定していることがわかります。また3312行目から、これらの処理はlargがTLSEXT_NAMETYPE_host_nameの場合に実行されることがわかります。</p>

<pre>
3311        case SSL_CTRL_SET_TLSEXT_HOSTNAME:
3312            if (larg == TLSEXT_NAMETYPE_host_name) {
〜省略〜
3327                if ((s->tlsext_hostname = BUF_strdup((char *)parg)) == NULL) {
(gdb) n
3243            break;
(gdb) p s
$11 = (SSL *) 0x55555564efc0
(gdb) p s.tlsext_hostname
$10 = 0x555555650480 "example.com"
</pre>

<p>まとめると、「--sniオプションを付けるとTLSEXT_NAMETYPE_host_nameの場合の処理が実行され、SSL構造体のtlsext_hostnameにホスト名が設定される」ということになります。</p>

<p>次に、WiresharkでSSL構造体から作成された実際のパケットをキャプチャして確認してみます。</p>

<h2>パケットキャプチャでSNIを確認する</h2>

<p>wireshark-cliをインストールするとCLIでパケットキャプチャできるtsharkコマンドが利用できるようになります。web-sandboxにて以下のように実行してパケットキャプチャを起動します。&lt;IPアドレス&gt;にはnagios-sandboxのIPアドレスを設定します。また、-wオプションを指定しpcap-formatのキャプチャファイルを作成します。</p>

<pre>
$ sudo tshark -i eth0 -f "host &lt;IPアドレス&gt;" -w /tmp/sni.cap
Capturing on 'eth0'
</pre>

<p>キャプチャを開始したらnagios-sandbox側でcheck_httpコマンドを実行します。</p>

<pre>
$ check_http -H example.com -f follow --ssl --sni
</pre>

<p>実行が完了したらweb-sandboxでCtrl+C等でキャプチャを終了し、作成されたキャプチャファイルを確認してみます。キャプチャファイルを手元のPC等にダウンロードしてからGUIのWiresharkで開くと見やすいです。SNIはClient Helloパケットに設定されるので、Client Helloパケットの内容を確認します。すると以下画像のように、SNIは長さの情報を除くと「Server Name Type」と「Server Name」で構成されていることがわかります。</p>

<p><a href="https://heartbeats.jp/hbblog/assets_c/2025/04/sni_client_hello-2755.html" onclick="window.open('https://heartbeats.jp/hbblog/assets_c/2025/04/sni_client_hello-2755.html','popup','width=512,height=189,scrollbars=yes,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="https://heartbeats.jp/hbblog/assets_c/2025/04/sni_client_hello-thumb-512x188-2755.png" width="512" height="188" alt="sni_client_hello.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></p>

<p>先ほどデバッグで確認した「--sniオプションを付けるとTLSEXT_NAMETYPE_host_nameの場合の処理が実行され、SSL構造体のtlsext_hostnameにホスト名が設定される」がパケットにも反映されていることが確認できました。この時点でまだわかっていないのは「Server Name Typeが何か」です。次にRFCでSNIについて確認してみます。</p>

<h2>RFCを読んでServer Name Typeを理解する</h2>

<p>まずSNIの構造を確認します。RFC6066の「<a href="https://datatracker.ietf.org/doc/html/rfc6066#section-3">3.  Server Name Indication</a>」で示されているServerName構造体を見ると、先ほどパケットキャプチャで確認した「Server Name Type」と「Server Name」に対応する「NameType」と「HostName」が含まれています。「NameType」はcase文で表現されているものの、「host_name」一種類のみであることがわかります。</p>

<pre>
     struct {
          NameType name_type;
          select (name_type) {
              case host_name: HostName;
          } name;
      } ServerName;
</pre>

<p>RFC6066の「<a href="https://datatracker.ietf.org/doc/html/rfc6066#section-3">3.  Server Name Indication</a>」にてNameTypeについて以下の記述があります。</p>

<blockquote>
  <p>Currently, the only server names supported are DNS hostnames; however, this does not imply any dependency of TLS on DNS, and other name types may be added in the future (by an RFC that updates this document).  The data structure associated with the host_name NameType is a variable-length vector that begins with a 16-bit length.  For backward compatibility, all future data structures associated with new NameTypes MUST begin with a 16-bit length field.  TLS MAY treat provided server names as opaque data and pass the names and types to the application.</p>
</blockquote>

<p>要約すると、「現在Server Nameとして利用できるのはDNSのホスト名のみだが、DNSに依存せず将来的に他の形式のServer Nameも利用できるようにNameTypeがある」といった内容です。そのため現在（2025年5月時点）NameTypeに設定されるタイプはDNSのホスト名であることを示す「host_name」のみです。</p>

<p>以上、check_httpコマンドのデバッグ、パケットキャプチャ、RFC読みを通してSNIの具体的な姿を確認できました。ここからはSNIによってWebサーバがどのように動作するかを確認していきます。</p>

<h2>SNIによるWebサーバの動作を理解する</h2>

<h3>SNIが設定されている場合のnginxの動作</h3>

<p>opensslコマンドを使って確認します。nagios-sandboxインスタンスで以下のようにコマンドを実行します。</p>

<pre>
$ openssl s_client -quiet -connect example.com:443 -servername example.com
depth=0 C = XX, L = Default City, O = Default Company Ltd, CN = example.com
〜省略〜
$ openssl s_client -quiet -connect cert1.example.com:443 -servername cert1.example.com
depth=0 C = XX, L = Default City, O = Default Company Ltd, CN = cert1.example.com
〜省略〜
</pre>

<p>-servernameオプションでSNIを指定しています。それぞれホスト名に対応したSSL/TLS証明書が使用されていることがわかります。</p>

<h3>SNIが設定されていない場合のnginxの動作</h3>

<p>では、SNIが設定されていない場合はどのような動作になるのでしょうか。opensslコマンドにて以下のように-servernameオプションを指定せずに実行して確認します。</p>

<pre>
$ openssl s_client -quiet -connect example.com:443
depth=0 C = XX, L = Default City, O = Default Company Ltd, CN = example.com
〜省略〜
$ openssl s_client -quiet -connect cert1.example.com:443
depth=0 C = XX, L = Default City, O = Default Company Ltd, CN = example.com
〜省略〜
</pre>

<p>cert1.example.comで接続しているにもかかわらず、example.comのSSL/TLS証明書が使用されていることがわかります。なお、check_httpコマンドで--sniオプションを付けずにコンテンツを確認してみると、コンテンツはホスト名に対応したバーチャルホストのものが応答していることがわかります。</p>

<pre>
$ check_http -H example.com -f follow --ssl --string "Contents of example.com"
HTTP OK: HTTP/1.1 200 OK - 255 bytes in 0.009 second response time |time=0.009181s;;;0.000000 size=255B;;;0
$ check_http -H cert1.example.com -f follow --ssl --string "Contents of cert1.example.com"
HTTP OK: HTTP/1.1 200 OK - 261 bytes in 0.010 second response time |time=0.009922s;;;0.000000 size=261B;;;0
</pre>

<p>nginxはSNIが設定されていない場合はデフォルトサーバのSSL/TLS証明書が使われるようです。筆者はApacheでも同様の検証を行いましたが、同様にDefault Virtual HostのSSL/TLS証明書が使用されました。</p>

<p>以上の検証から、WebサーバがSSL/TLS接続でホスト名に対応したSSL/TLS証明書を利用するためにSNIのHostNameを用いることがわかりました。また、そのHostNameを設定するためにcheck_httpの--sniオプションが必要であることがわかりました。</p>

<h2>補足情報</h2>

<p>以下は今回検証する中で知ったSNIやcheck_httpコマンドに関する補足的な情報です。</p>

<h3>SNIが設定されていない場合に接続を拒否する</h3>

<p>CDNを利用したWebページに対し--sniオプションなしでcheck_httpコマンドを実行した際はCannot make SSL connectionが応答します。しかし、nginxでは--sniオプションを付けない場合、デフォルトサーバのSSL/TLS証明書が使用されるもののSSL接続は成功します。</p>

<p>nginxでSNIが設定されていない場合にCannot make SSL connectionを応答するには以下の設定を追加する必要があります。</p>

<pre>
server {
    listen 443 ssl;
    ssl_reject_handshake on;
}
</pre>

<p>Apacheの場合は以下の設定を追加します。nginxと違いSNIがない場合にHTTP 403 Forbiddenが応答します。</p>

<pre>
SSLStrictSNIVHostCheck on
</pre>

<h3>check_http --verify-hostオプションでSSL/TLS証明書を検証する</h3>

<p>check_httpコマンドのオプションに--verify-hostがあります。--ssl、--sniオプションと併用し、-Hで指定したホスト名に対してSSL/TLS証明書が正しいものかチェックできます。ホスト名とSSL/TLS証明書のCommon Nameが一致しない場合、CRITICAL - Hostname mismatchが応答します。</p>

<pre>
$ check_http -H cert2.example.com -f follow --ssl --sni --verify-host
CRITICAL - Hostname mismatch.
</pre>

<h3>SNIを暗号化するEncrypted Client Hello</h3>

<p>SNIは平文でドメイン名が保持されるため、パケットキャプチャ等でSNIを確認することで通信している先を誰でも判別できてしまいます。完全に秘匿された通信を実現するためにはSNIを暗号化して隠す必要があります。それを実現するのがEncrypted Client Hello（以降ECHとする）です。ECHは現在（2025年5月時点）<a href="https://datatracker.ietf.org/doc/draft-ietf-tls-esni/24/">draft-ietf-tls-esni-24</a>にてRFC策定が進められています。</p>

<p>ECHについて個人的に追いかけてみたいと思いましたので、次回はECHまわりの検証についてブログを書こうかと思っています。</p>

<h2>参考文献</h2>

<ul>
<li><a href="https://datatracker.ietf.org/doc/html/rfc6066">RFC 6066 - Transport Layer Security (TLS) Extensions</a></li>
<li><a href="https://datatracker.ietf.org/doc/draft-ietf-tls-esni/24/">draft-ietf-tls-esni-24 - TLS Encrypted Client Hello</a></li>
<li><a href="https://heartbeats.jp/hbblog/2023/01/check-http.html">Nagios Pluginsのcheck_httpを使いこなそう - インフラエンジニアway - Powered by HEARTBEATS</a></li>
<li><a href="https://qiita.com/clown0082/items/551d7c081ff6b41b1717">SSLを利用するための自己証明書（オレオレ証明書）の設定メモ - Qiita</a></li>
<li><a href="https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslstrictsnivhostcheck">mod_ssl - Apache HTTP Server Version 2.4</a></li>
<li><a href="https://trac.nginx.org/nginx/ticket/195">#195 (Close connection if SSL not enabled for vhost) - nginx</a></li>
<li><a href="https://heartbeats.jp/hbblog/2012/06/nginx06.html">nginx連載6回目: nginxの設定、その4 - TLS/SSLの設定 - インフラエンジニアway - Powered by HEARTBEATS</a></li>
<li><a href="https://knowledge.sakura.ad.jp/6311/">Wiresharkを使った通信監視（後編）――コマンドラインベースでのパケットキャプチャ | さくらのナレッジ</a></li>
</ul>
]]>
    </content>
</entry>

<entry>
    <title>株式会社ハートビーツ　創業20周年のご挨拶</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2025/04/20250415.html" />
    <id>tag:heartbeats.jp,2025:/hbblog//2.943</id>

    <published>2025-04-15T00:31:22Z</published>
    <updated>2025-04-15T02:45:39Z</updated>

    <summary>こんにちは。株式会社ハートビーツ 代表取締役の藤崎です。 さて、本日、2025年...</summary>
    <author>
        <name>藤崎正範</name>
        
    </author>
    
        <category term="採用・広報" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="活動" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>こんにちは。株式会社ハートビーツ 代表取締役の藤崎です。</p>

<p>さて、本日、2025年4月15日に株式会社ハートビーツは創業20周年を迎えることができました。
ひとえに、20年間のあいだにハートビーツに関わっていただいた社員のみんな、そしてその陰で支えてくださったご家族の皆さま、私たちを信じて仕事を任せてくださったお客様の皆さま、そして応援をいただいてきたパートナーやIT業界のコミュニティの皆さまのおかげです。ハートビーツを代表して、心より感謝申し上げます。</p>
]]>
        <![CDATA[<p>「ハートビーツ」という名称は、私が個人事業主２年目から使用していた屋号でした。この名前は、当時私が利用していた、インフラ冗長化を実現するオープンソース・ソフトウェア "heartbeat" に由来しています。2005年4月15日の法人化の際に「株式会社ハートビーツ」として活動を開始いたしました。</p>

<p>法人化を決めたとき、「法人ってなんだ？」「法人格ってなんだ？」と調べたことがあります。法人格とは、法的に定められた人格であり、「権利・義務の主体となることのできる資格」を有するとのことです。ゆえに、会社はモノやお金を所有する権利があり、契約の主体となることができるわけです。</p>

<p>つまり、個人事業主の屋号としてのハートビーツは私自身を指していましたが、株式会社ハートビーツと法人化した場合、その人格は私から切り離されるんだと理解しました。これはまさに、バーチャルな0歳の赤ちゃんを生み出す感覚でした。そうなると、まだ赤ちゃんのハートビーツさんを育てて、自立して成長していけるようにしていくことが、私の目標となりました。</p>

<p>お陰様で、そんなハートビーツさんをみんなでコツコツと育ててくることができました。そして、20歳という大きな節目を迎えられたことを本当に喜ばしく思うとともに、改めて皆さまに感謝申し上げます。</p>

<p>本日、20年という大きな節目の日を迎えましたが、これは次の中間地点でもある「30年」に向けた、新たな10年間のスタートでもあります。</p>

<p>新型コロナが終わったと思えば、生成AIの登場やトランプショックなど、世の中は常に目まぐるしく変化しています。そんな中でも、私たちは「みんな仲良く」「プライドを持って」「変化を楽しむ」という、ハートビーツの企業理念を体現しながら、日々の活動を続けてまいります。</p>

<p>次の10年、私たちは「止めないインフラ」の実現に加え、"攻めの技術支援"による顧客価値の創出に注力してまいります。インフラ運用・セキュリティ・開発基盤といった領域において、クラウドネイティブな技術やAIの活用を進め、お客様の変化に強いIT基盤づくりを、上流から伴走できるパートナーを目指します。</p>

<p>社内では、技術者一人ひとりが継続的に学び挑戦できる仕組みを強化し、人と組織の両面で"強い技術チーム"を育てることにも引き続き取り組んでまいります。</p>

<p>次の10年が楽しみでなりません。皆さまのご期待に応えられるよう、さらなる成長と挑戦を重ねながら、これからもベストを尽くしてまいります。</p>

<p>今後とも、ご指導ご鞭撻、そしてご贔屓のほど、何卒よろしくお願い申し上げます。</p>

<div style="text-align: right;">
株式会社ハートビーツ 代表取締役 藤崎正範
</div>
]]>
    </content>
</entry>

<entry>
    <title>入社して感銘を受けたこと：社内ナレッジ共有の場「ナレッジためぞう」がすごい</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2025/02/knowledge-tamezou.html" />
    <id>tag:heartbeats.jp,2025:/hbblog//2.940</id>

    <published>2025-02-28T03:00:00Z</published>
    <updated>2025-02-28T03:17:24Z</updated>

    <summary>はじめに こんにちは。MSPグループエンジニアリングチームの川邉（かわべ）と申し...</summary>
    <author>
        <name>川邉 晶子</name>
        
    </author>
    
        <category term="活動" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<h2>はじめに</h2>

<p>こんにちは。MSPグループエンジニアリングチームの川邉（かわべ）と申します。2024年7月に中途採用で入社いたしました。</p>

<p>このブログでは、私がハートビーツに入社して一番「すごい」と思っている「ナレッジためぞう」についてお伝えします。</p>
]]>
        <![CDATA[<h2>「情報共有ツールがすごい」</h2>

<p>入社の一週間ほど前のことです。オンラインで内定者座談会を開催していただきました。内定者座談会はハートビーツのオンボーディング施策の1つで、一緒に働くチームメンバーと顔合わせをしてコミュニケーションを取り、入社前の不安感を軽減するというものです。私からの質問にも答えていただきました。</p>

<p>そのとき書いたメモに、こう書いてあります。「情報共有ツールが、なんかすごい、便利そう！」</p>

<p>私が「長時間のデスクワークが苦手なのですが、みなさんはどのようなイスを使っていますか？」という質問をしたときのことです。チームメンバーの方々に答えていただいた後、「こういうページもありますよ！」と画面を共有して見せてもらったのが、「僕の机」というタイトルのページ。たくさんの社員の方々が自分の作業環境を紹介していました。モニタやイス、机、キーボードなど人それぞれのこだわりを垣間見ることができて興味深く、またそれにたくさんコメントがついているのがおもしろく感じられました。ページの中でこんなふうに交流しているなんて、仲が良くて楽しそうな会社だなという印象を受けました。</p>

<p>同時に、「このページを載せている情報共有ツールはなんだろう？」と興味を惹かれました。</p>

<p>その情報共有ツールが「ナレッジためぞう」でした。</p>

<h2>「ナレッジためぞう」とは？</h2>

<p>「ナレッジためぞう」は、株式会社Helpfeelが提供するScrapboxというナレッジ共有サービスを利用した、ハートビーツの社内Wikiです。
誰でも簡単に新しいページを作ることができて、書いた内容は即反映され、誰でも閲覧して編集できます。ほかのページへのリンクも簡単です。階層構造がなく、ページを探したいときは検索します。</p>

<p>「ナレッジためぞう」の利用ポリシーのページにはこのように書かれています。</p>

<ul>
<li>整理しなくていい</li>
<li>書きかけでいい</li>
<li>誰でも書き換えていい</li>
<li>迷わずに書く</li>
<li>ページは小分けに</li>
<li>ページをどんどんつなげる</li>
</ul>

<p>実際、膨大な数のコンテンツが「ナレッジためぞう」には、あります。執筆時点（2024年12月）で、19641ページもあります。
業務に必要な案件の情報、記録、議事録などが集約されているのはもちろん、技術的な情報もたくさんあります。そして、最初に紹介した「僕の机」のようなページもあり、会社周辺の飲食店、健康診断や人間ドックの体験記、料理のレシピ、本の紹介、など多岐にわたります。各ページの下の方には関連ページも表示されるので、どんどんリンクをたどって読んでいると楽しくて時間を忘れるほどです。</p>

<p>ちなみにこの社内Wikiを「ナレッジためぞう」と呼ぶ人は少なく、サービス名の「Scrapbox（スクラップボックス）」がよく使われています。Scrapboxは2024年5月に「Helpfeel Cosense」とサービス名が変わりましたが、ハートビーツ社内では使い慣れた「Scrapbox」の方で定着しているようです。</p>

<h2>書くことを推奨するカルチャー</h2>

<p>たくさんの情報が「ナレッジためぞう」に集まっているのは、なんでも記録し、検索して読めるようにしておくことが社員に習慣づけられているからです。
入社するとまず「ナレッジためぞう」に自分のプロフィールページを作ります。研修が始まると、毎日日誌を記録していきます。社内ミーティングの記録も、案件ごとの記録も、個人の業務日誌も蓄積されていきます。研修や業務で学んだ知識は「Scrapboxで書いておくとよいですよ」と先輩エンジニアに勧められます。</p>

<p>ハートビーツに入社して驚いたのが、作業の手順を前もって詳細に書いておき、作業時に表示された内容なども記録していることです。最初は「そんなに細かいところまで？」と思いましたが、丁寧に手順を書いてダブルチェックを経ることで確実に作業を遂行できます。また、出力の記録も、エラーメッセージやファイル名などで「ナレッジためぞう」を検索することがあるので、誰かの役に立ちます。</p>

<p>以前は、技術的なことを調べたいときはあたり前のようにGoogleで検索していました。しかし入社してしばらくしてからは「何か社内の情報があるかな」と、先に「ナレッジためぞう」で検索することが多くなりました。実際それで見つかることも多く、そのたびに「『ナレッジためぞう』は、やっぱりすごいな」と驚き、たくさんの先輩エンジニアの情報に日々助けられていると感じます。</p>

<h2>資格取得の体験記をシェア</h2>

<p>私も、書きたいことがふっと湧いてきて「これは『ナレッジためぞう』に書いておけばよいのでは？」と思うことがよくあります。
最近私は、資格試験の体験記を書きました。資格試験の受験体験記は、私が「ナレッジためぞう」でよく見るコンテンツの1つです。</p>

<p>ハートビーツでは資格取得支援制度があり、受験料はもちろん、勉強のためのテキストやオンライン教材の費用も会社が負担してくれます。たくさんの社員が資格取得にチャレンジし、その体験が「ナレッジためぞう」には蓄積されています。勉強方法、準備期間、抑えるべきポイントなど、先に同じ試験を受けた人の情報はとても役に立ちました。</p>

<p>特に多いのがAWS認定試験の受験体験記です。一人で複数の資格を取る方もいます。私もAWS認定資格はできるだけ多く取得したいので、参考にして今後もチャレンジしていきたいです。</p>

<h2>おわりに</h2>

<p>業務の遂行になくてはならない存在であり、また技術や知識をシェアできる場であり、さらに社員どうしのコミュニケーションも仲立ちしている「ナレッジためぞう」。入社前の「すごい」という印象は、入社して実務を知るにつれ、単なる「すごい」ではなく「なくてはならない」存在だとわかりました。</p>

<p>しかし、すごいのは「ナレッジためぞう」ではなく、その中身を書いているハートビーツ所属エンジニアの技術力と、それを活用してフルリモートでも円滑に業務を進めるしくみが確立されているところではないでしょうか。たくさんのナレッジが社内に蓄積されていて簡単に参照できると、圧倒的な安心感をもって働くことができます。これはハートビーツで働くうえでの魅力の1つであると思いました。</p>

<p>そんなハートビーツについてもっと知りたい、自分も働いてみたいと思った方はぜひ、カジュアル面談（<a href="https://recruit.heartbeats.jp/recruit/">https://recruit.heartbeats.jp/recruit/</a>）から、お気軽にご応募ください！</p>
]]>
    </content>
</entry>

<entry>
    <title>新年のご挨拶 2025年</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2025/01/-2025.html" />
    <id>tag:heartbeats.jp,2025:/hbblog//2.941</id>

    <published>2025-01-06T03:00:00Z</published>
    <updated>2025-12-24T06:25:56Z</updated>

    <summary>新年あけましておめでとうございます。ハートビーツの藤崎です。おかげさまで昨年末も...</summary>
    <author>
        <name>藤崎正範</name>
        
    </author>
    
        <category term="活動" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>新年あけましておめでとうございます。ハートビーツの藤崎です。<br />おかげさまで昨年末も大きな障害もなく無事に年を越せました。<br />多くの皆様からのご支援・ご指導を賜り、心より感謝申し上げます。</p>
]]>
        <![CDATA[<p>昨年は「クラウド・アクセラレーション事業部」を中核に、人材育成強化による人材拡充を図りつつ、創業以来の強みであるMSP（Managed Service Provider）領域の強化、および、アドバイザリーサービス・システム開発などがインフラ運用と有機的に連携することで、お客様の課題に寄り添い、少しでもそのお役に立てるよう活動することができました。</p>

<p>2024年の活動をいくつかご紹介させてください。</p>

<p>・AWSの提供するセキュリティサービスの高い専門性を証明する「Level 1 MSSP コンピテンシー」を取得<br/>　<a href="https://heartbeats.jp/info/pressrelease/20241126_01/" target="_blank" title="AWSの提供するセキュリティサービスの高い専門性を証明する「Level 1 MSSP コンピテンシー」を取得">https://heartbeats.jp/info/pressrelease/20241126_01/</a></p>

<p>・重要ファイル転送プラットフォーム「Kozutumi」利用企業数が2,000社を突破<br/>　<a href="https://heartbeats.jp/info/pressrelease/20241010_01/" target="_blank" title="重要ファイル転送プラットフォーム「Kozutumi」利用企業数が2,000社を突破">https://heartbeats.jp/info/pressrelease/20241010_01/</a></p>

<p>・トレンドマイクロ CSPパートナーに認定されました<br/>　<a href="https://heartbeats.jp/info/pressrelease/20241114_01/" target="_blank" title="トレンドマイクロ CSPパートナーに認定されました">https://heartbeats.jp/info/pressrelease/20241114_01/</a></p>

<p>・中学生の職場体験受け入れを行いました<br />　<a href="https://heartbeats.jp/info/topics/20241025_01/" target="_blank" title="中学生の職場体験受け入れを行いました">https://heartbeats.jp/info/topics/20241025_01/</a></p>

<p>・「LAPRAS HR TECH LAB」でハートビーツの採用活動を記事にしていただきました<br />　<a href="https://heartbeats.jp/info/topics/20240813_01/" target="_blank" title="「LAPRAS HR TECH LAB」でハートビーツの採用活動を記事にしていただきました">https://heartbeats.jp/info/topics/20240813_01//</a></p>

<p>　</p>

<p>昨年も 様々なところで皆様からチャンスを頂きましたこと、この場をお借りしてお礼申し上げます。<br />その他の活動についてはニュース一覧を御覧ください。</p>

<p>・ニュース 一覧<br />　<a href="https://heartbeats.jp/info/" target="_blank" title="ニュース 一覧">https://heartbeats.jp/info/</a></p>

<p>2025年も更なる成長を目指し、皆様と共に進化してまいります。<br />私どもの得意分野でお困りのことがございましたらお仕事でご一緒できる機会があれば幸いです。</p>

<p>・クラウド・アクセラレーション事業 | 企画から開発、運用まで一貫したサービスを提供<br />　<a href="https://heartbeats.jp/service/" title="クラウド・アクセラレーション事業 | 企画から開発、運用まで一貫したサービスを提供">https://heartbeats.jp/service/</a></p>

<p>・Kozutumi | 脱PPAPに最適な重要ファイル転送プラットフォーム<br />　<a href="https://kozutumi.com" title="Kozutumi | 脱PPAPに最適な重要ファイル転送プラットフォーム">https://kozutumi.com</a></p>

<p>　</p>

<p>皆様と共に、2025年を良い年にすることができるよう邁進してまいります。<br />引き続き、ご指導ご鞭撻ご贔屓の程、宜しくお願い申し上げます。</p>
]]>
    </content>
</entry>

<entry>
    <title>リモートワーク環境でみんなが最大限パフォーマンスを出すために何ができるのか</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2024/12/training-part3.html" />
    <id>tag:heartbeats.jp,2024:/hbblog//2.934</id>

    <published>2024-12-27T01:00:00Z</published>
    <updated>2024-12-27T05:20:28Z</updated>

    <summary>こんにちは。事業基盤グループ 人材開発チームの佐野です。 人材育成の観点で、テレ...</summary>
    <author>
        <name>佐野裕</name>
        <uri>https://heartbeats.jp/</uri>
    </author>
    
        <category term="活動" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>こんにちは。事業基盤グループ 人材開発チームの佐野です。</p>

<p>人材育成の観点で、テレワークという環境下の中、みんなが最大限パフォーマンスを出すために何ができるのかは大きな課題の一つでした。そこで本屋でいろいろな本を物色していた中、<strong>「遊ばせる技術 チームの成果をワンランク上げる仕組み」</strong>という本で次の3つのフレーズ、「テレワークにおけるパフォーマンス低下の問題」、「社員の自律やモチベーションの低下に悩む管理職は多い」、および「仕事における面白さをどのように醸成するのか」が目に入り、私の感じている課題感にマッチしていたので読んでみました。</p>

<pre>
参考文献
- 遊ばせる技術 チームの成果をワンランク上げる仕組み
- 神谷 俊 著
- 発行年月：2020年04月
- 頁数：208
- <a href="https://bookplus.nikkei.com/atcl/catalog/2021/9784532324001/" target="_blank" rel="noopener noreferrer">https://bookplus.nikkei.com/atcl/catalog/2021/9784532324001/</a>
</pre>

<p>著者の神谷さんは、リモート環境下の「職場」を研究するバーチャルワークプレイスラボを設立し、数多くの企業のテレワーク移行支援を手掛け、継続的にオンライン環境における組織マネジメントの知見を蓄積されています。<br></p>

<p>※注意。本ブログでは参考文献を要約としてまとめたものではなく、本を読んだ上で我々にとって必要と感じた部分を引用する形としています。参考文献について興味を持たれた方はぜひ直接原著を読んでみてください。</p>
]]>
        <![CDATA[<h3>弊社におけるこれまでのリモートワークの取り組みと課題</h3>

<p>新型コロナウィルスの大流行を契機として、弊社では2020年にリモートワーク体制に完全移行しました。オフィス勤務前提の業務体系を一気にリモートワーク体制に変えることになったわけですから、他社同様に弊社としても挑戦的な取り組みとなりました(私が⼊社する少し前に完全移⾏となりました)。</p>

<p>それまでの一緒に対面しながら同僚達と仕事をする業務スタイルから、インターネットを介し協調して業務を進める業務スタイルへ突然変更になったので、最初はとまどった人が多かったようです。しかし現在はリモートワークが完全に定着して、リモートワークならではの特性を生かした取り組みも進んでおります。特に、これまで東京にしか拠点がなくて難しかった地方採用を積極的に行うようになり、現在は北海道、東北、関西、九州、沖縄等、全国的な採用が進み、地域の多様化につながったことは完全リモートワーク化の副産物として結果的に大成功でした。</p>

<p>リモートワーク体制では、一般的にメンバー間の交流が希薄化されがちです。この問題については例えば次のようなことが社内で広く実施されています。</p>

<pre>
・対面で実施するワークショップや会議(地方勤務者は東京に出張して実施する)
・オンラインで実施する月例朝会、ランチ会、もしくは打ち上げ等
・各地域毎に行われるリアル会食(大阪飲み会、福岡飲み会等)
</pre>

<p>このように、今ではリモートワーク体制が定着していますが、一方でリモートワーク環境を継続するにあたり、みんながもっとパフォーマンスを出せるようにしていくという観点では、リモートワークならではの効果的な働き方がもっとできるのではないか、もしくはリモートワーク下でのマネジメントをもっと体系化できるのではないか等、まだまだやれることがあるのではないかと考えています。</p>

<p>今回そういう視点を持ちながら参考文献を読んでみました。</p>

<h3>テレワークと「型」</h3>

<p>参考文献には、テレワークのようにメンバーが分散した状況で協働を進めるためには、<strong>個々の社員が達成すべき成果目標や役割などの業務構造やルール、チーム内での会議や面談の頻度などの活動</strong>をパターン化することが不可欠と書かれています。本書ではこのパターンのことを<strong>「型」と定義</strong>しています。</p>

<p>「型」は社員がテレワーク環境で自律的に働きやすいように構築されます。しかし、自律を促すための「型」が反対に社員の自律的な思考や活動を縛り、強制的に方向づけるようなコントロールを生み出した結果、「テレワークになり仕事はしやすくなったけど、自由度は下がった」などと感じるようになります。</p>

<p>そして部下が「型」によってコントロールされているにもかかわらず、上司が「自律を促している」「チームは自律が進んでいる」と解釈して、誤ったマネジメントが継続されるケースが見られるようです。</p>

<p>このように、単に「型」を作り、それを適用することだけでは不十分なようです。</p>

<h3>「型」の緩和をしても成果が出ないことがある</h3>

<p>テレワークが長期化するなかで「型」が過剰に生まれていることに気づき、徐々に「型」を緩和した事例が紹介されていました。しかしこの事例では「型」を緩和したにも関わらず自律や生産性が思うように高まっていませんでした。</p>

<p>成果目標をすり合わせた上で仕事の進め方は部下に任せていく方法で「型」の緩和をした結果、自律的に動くどころか、個々の社員の気が緩んでしまい、むしろ最低限の成果にとどまる結果となったようです。</p>

<p>そこで、社員の成果が最低限に留まるなら最低限の基準を高めればよいのではないかと目標水準を引き上げる方向に設定すると、今度は「プレッシャーを感じた」「労働時間の顕著な増加が見られた」「部下からの問い合わせや相談が増えてかなり負担が増えた」という結果となり、結果的に自律は促されなかったようです。</p>

<p>このように、「型」を減らす代わりに「成果目標」をすり合わせて「目標水準」を引き上げる形も、みんなが最大限パフォーマンスを出す結果にはならないようです。</p>

<h3>「真面目」について</h3>

<p>ところで、オフィス環境を前提とした職場環境では、上司や同僚が見えている環境の中で「真面目」に働くことが有効に機能していたとのことです。オフィス環境においては、相手の状況に合わせてタイミングよくアドバイスや補完をしあうという関係性が構築できていたことや、「真面目」に頑張っていれば上司から気遣い・励まし、褒め・承認を得られることでやる気にもつながっていました。</p>

<p>しかしテレワーク下では、周囲の状況が見えないため、結果注視のマネジメントに切り替えるスタイルが増えています。その結果、プロセスや努力よりも結果を注視されるようになりました。</p>

<p>このように、テレワーク環境下では「真面目」な努力を求めて部下を動機づけたり「型」を精致に運用するだけでは成果を高めることは難しいかもしれず、<strong>より高次の自律レベルを目指しながらチームを整えていくことが求められる</strong>とのことです。</p>

<h3>楽しさに刺激を受けた自律</h3>

<p>別の事例では、成果目標をすり合わせた上で仕事の進め方は部下に任せていく方法であってもメンバーが生き生きと自律的に動いている様子が紹介されていました。</p>

<p>この事例では、成果目標も詳細に擦り合わせをし、上司との進捗を共有するための面談も週次で行われていました。しかしこの事例ではヒアリング対象から「コントロールされている」といったニュアンスの言葉は⼀切出てこず、むしろ高いレベルで自律的に仕事をしている様子が伝わってきていました。</p>

<p>ヒアリング対象は、成果目標で定められている内容以外に、独自に営業チームと連携を強めたりメール文面の改良を試みるなど、とくに規定されていない仕事を自ら見つけて進めていて、さらには関連する領域の勉強を自分なりに行っているという状況です。ヒアリング対象からは、「楽しい」「自分のため」「自分の進む道」というキーワードが発言されていました。<strong>自分を起点に仕事を組み立て、「楽しさ」に刺激を受けながら仕事を自律的に行っている</strong>ことが読み取れます。</p>

<p>このように、<strong>各メンバーへの動機付け次第では、楽しくかつ高次の自律レベルで行動していく状況を作り出していくことが可能</strong>とのことです。</p>

<h3>セルフマネジメントとセルフリーダーシップの違い</h3>

<p>「社員が自律的に働くとはどういうことか」に対して、上記2つの事例の違いが「セルフマネジメント」と「セルフリーダーシップ」の違いにあるとのことでした。</p>

<p>・<strong>セルフマネジメント</strong><br>
　「それぞれの部下が自分の仕事をプライドを持ってちゃんと進められるようになってほしい」という意図から、会社が提示した目標をひとりで達成できるようになることを促している。「やるべき」「しなければならない」という義務感や責任感を醸成するようなアプロ―チとなる。</p>

<p>・<strong>セルフリーダーシップ</strong><br>
　「自分がその仕事にどんな意味を見出すのか、それが見えなければ自律なんてできない」という意図から、自分が「したい」「やろう」と思いながら取り組むことを「<strong>自律</strong>」としている。部下がどのような志向を持っていて、仕事をどのように位置付けているのか、何に興味や関心を抱いているのかなどを細かく把握することが求められるため、部下との対話が基本になる。</p>

<p>セルフマネジメントは、「タスクが来たら真面目にこなす」というような受け身にもなりがちな状況になり、一方、<strong>セルフリーダーシップは、本質的な目的や方向性について自ら考えながら動くので、高次の自律レベルが期待できかつ高いパフォーマンスを発揮できる</strong>とのことです。</p>

<h3>5段階の自律レベル</h3>

<p>自律について、下記のように5段階に整理して説明されていました。レベルが高ければ高くなるほど自律レベルも高くなります。詳細説明は省きますので詳しく知りたい方は参考文献を実際に読んでみてください。</p>

<pre>
LEVEL1: ルール・規則に従う
LEVEL2: 責任感・プライドを感じる
LEVEL3: 仕事の価値を理解する
LEVEL4: 気持ちが動かされる
LEVEL5: 楽しさ・面白さを感じる

※LEVEL1～3: セルフマネジメント
※LEVEL4～5: セルフリーダーシップ
</pre>

<p><strong>LEVEL4～5がセルフリーダーシップのレベル感とのことなので、このレベルのメンバーを多く増せることが理想的です</strong>。</p>

<h3>どうしたらセルフリーダーシップの自律レベルに到達できるか</h3>

<p>参考文献の後半では、どうしたらセルフリーダーシップの自律レベルに到達できるかを、個人の視点と、管理者(上司)からの視点で記されています。</p>

<p>個人の視点は第3章にまとめられています。ここでは具体的なアクションを示しながら、<strong>仕事に「遊び」を呼び込むためのポイント</strong>が記載されています。</p>

<pre>
第3章: 自分に合わせて仕事をクラフトする
[1]自分の仕事を整える
[2]オーナーシープを高めるアクション
[3]ジョブ・クラフティングの実践
[4]能力を発揮するためのチューンナップ
[5]ネットワークの活用と構築
[6]仕事を面白くするための六つの実践ポイント
</pre>

<p>管理者(上司)からの視点は第4章にまとめられています。ここでは<strong>管理者の視点で自律を促すために、どのような支援をしていけばよいか</strong>について提示されています。</p>

<pre>
第4章: 管理者は仕事を面白くできる
[1] 「自律させる」ではなく「勝手に自律する」
[2] 部下を知ることから始める
[3] 部下のタイプに合わせたマネジメントの検討
[4] 仕事に対する注力姿勢が低い部下への対応（線引き型・停滞型）
[5] 現実的「制約」を持った部下へ対応するための三つの視点
[6] 頑張っているが、仕事を楽しめていない部下への対応（真面目型）
[7] 自律レベルの高い部下への対応（自律型）
[8] マネジメントは矛盾してよい
</pre>

<p>セルフリーダーシップでは、先ほど「部下がどのような志向を持っていて、仕事をどのように位置付けているのか、何に興味や関心を抱いているのかなどを細かく把握することが求められるため、部下との対話が基本になる」と記しました。第4章では様々な観点からどのように部下を知り、対話していけばよいかのヒントが山のように示されていました。</p>

<p>なお本項の「どうしたらセルフリーダーシップの自律レベルに到達できるか」について、本文からではなく目次からの引用に留めているのは、内容の密度が高くて該当箇所を引用しようとすると、ほぼほぼ全て引用となりそうだったためです。これは部下とのコミュニケーションから高次の自律レベルを導くためには、こまめにやらないといけないポイントが多数あるとも言えそうです。</p>

<h3>気付きとまとめ</h3>

<p>「テレワークという環境下の中、みんなが最大限パフォーマンスを出すために何ができるのか」という大きな課題の一つに対して、仕事をする上での意義を自分で見出し楽しさを感じる、セルフリーダーシップの自律レベルに到達することで部下(社員)が自律的に動けるようになるという考え方が大変参考になりました。</p>

<p>現時点ですでにこのレベルまで到達している社員もいれば、そうでない社員もいます。全社的な底上げを考えるうえで、参考文献にて管理者(上司)と部下との対話が重要であると書かれていることから、すでにセルフリーダーシップの自律レベルに到達している社員を中心に管理者(上司)の役割を担うことで全社的な自律レベルを上げていく必要があります。</p>

<p>そのような流れを人材育成プログラム作成などの手段で仕組み化できると、結果的に全社的に自律レベルが上がり、最大限のパフォーマンスが出せるようになると考えられます。もちろん我々人材育成部門メンバーも同様に「楽しさ」に刺激を受けながら仕事を自律的に行えてなければならないのは言うまでもありません。</p>
]]>
    </content>
</entry>

<entry>
    <title>VS CodeとPlaywrightを使ったE2Eテストの実施</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2024/11/vscodeplaywrighte2e.html" />
    <id>tag:heartbeats.jp,2024:/hbblog//2.933</id>

    <published>2024-11-20T01:00:00Z</published>
    <updated>2024-11-20T01:02:16Z</updated>

    <summary>技術開発チーム・運用技術開発担当（通称opdev）の辰已です。 opdevは社内...</summary>
    <author>
        <name>辰已 聡一朗</name>
        
    </author>
    
        <category term="技術" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>技術開発チーム・運用技術開発担当（通称opdev）の辰已です。</p>

<p>opdevは社内のさまざまなプロダクトの開発・保守運用を行っており、日々業務効率改善、ハートビーツの価値向上に繋がる技術開発・情報発信を行っています。</p>

<p>先日、opdevで開発した社内向けのプロダクトに対して、<a href="https://code.visualstudio.com/">Visual Studio Code（以下VS Code）</a>と<a href="https://playwright.dev/">Playwright</a>を使ってE2Eテストを実施しました。
セットアップが簡単で、使い勝手も良かったので、今回はVS CodeとPlaywrightを使ったE2Eテストの実施方法を紹介します。</p>
]]>
        <![CDATA[<h2>Playwrightとは</h2>

<p>PlaywrightはE2Eテストやブラウザ自動操作用のフレームワークで、Microsoftがオープンソースで開発をしています。
他によく使われるE2Eテストフレームワークには、Selenium、Puppeteer、Cypressがあります。npmパッケージのダウンロード数の推移を確認できる<a href="https://npmtrends.com/cypress-vs-playwright-vs-puppeteer-vs-selenium-webdriver">npm trend</a>を見ると、Playwrightは2024年5月中頃に首位だったCypressを追い越し、パッケージのダウンロード数がトップになっています。</p>

<p>Playwrightの特徴は以下の通りです。</p>

<ul>
<li>Any browser • Any platform • One API <br />
クロスブラウザ、クロスプラットフォーム、複数言語で利用可能</li>
<li>Resilient • No flaky tests <br />
自動ウェイトによりタイミングの調整が不要</li>
<li>No trade-offs • No limits（※1） <br />
複数ブラウザ、タブにも対応</li>
<li>Full isolation • Fast exec <br />
高速な実行、認証状態保持による繰り返しログインの排除</li>
<li>Powerful Tooling <br />
テストコード生成のための操作記録、テスト失敗時のさまざまな解析ツール群</li>
</ul>

<p>Playwrightは後発のフレームワークであり、他のテストフレームワークの課題を改善している点が大きな特徴です。</p>

<p>※1. おそらく<code>trade-offs</code>の単語はCypressの<a href="https://docs.cypress.io/guides/references/trade-offs">Trade-offs</a>を意識しているのでしょう。</p>

<h2>Playwrightの導入</h2>

<p>実際にVS CodeにPlaywrightを導入してみましょう。
MicrosoftはPlaywrightだけでなく、VS Code向けのPlaywright拡張機能も提供してくれています。周辺環境まで整備してくれているのは嬉しいですね。
なお、VS Codeの操作方法については本筋から外れるため割愛します。</p>

<ul>
<li>拡張機能をインストールする <br />
VS Codeで<a href="https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright">Playwright Test for VSCode</a>を検索し、 installボタンをクリックして拡張機能をインストールします。
<img src="/hbblog/2024/09/playwright_vscode_install_plugin.png" alt="拡張機能" title="" />  </li>
<li>プロジェクトを開く <br />
テスト用プロジェクトを作成するディレクトリを開いておきます。今回はディレクトリ名をplaywright_sampleという名前で作成しました。 
<img src="/hbblog/2024/09/playwright_vscode_empty.png" alt="プロジェクトを開く" title="" />  </li>
<li>Playwrightのインストール <br />
コマンドパレットから<code>test: Install Playwright</code>を選択してPlaywrightをインストールします。 <br />
<img src="/hbblog/2024/09/playwright_vscode_install_playwright.png" alt="Playwrightのインストール" title="" /> <br />
選択肢はそのままで問題ありません。Firefox不要、WebKit不要などがあれば適宜変更してください。 
<img src="/hbblog/2024/09/playwright_vscode_select_settings.png" alt="Playwrightインストール時の選択" title="" />  </li>
</ul>

<p>これだけで環境構築が完了です。とても簡単ですね！</p>

<h2>動作確認</h2>

<p>実際にPlaywrightを動かしてみましょう。実行対象のテストコードは<code>tests</code>ディレクトリ以下（※2）のファイルになります。
VS Codeのアクティブバーからテストエクスプローラーを開き、実行したいテスト名の横にある再生マークをクリックしてください。テスト結果が<code>Test Result</code>ターミナルに表示されたらOKです。 <br />
<img src="/hbblog/2024/09/playwright_vscode_run_test_run.png" alt="テスト実行" title="" />  </p>

<p>また、デバッガーを起動したい場合は、実行したいテスト名の横にある虫付き再生マークをクリックしてください。 <br />
<img src="/hbblog/2024/09/playwright_vscode_run_test_run_debug.png" alt="デバッグ実行" title="" />  </p>

<p>これだけでデバッガーが使えます！<code>launch.json</code>の作成・パスの調整など、いろいろな設定をすることなくデバッグ環境まで構築できるのはとても嬉しいですね。</p>

<p>※2. <code>playwright.config.ts</code>の<code>testDir</code>にデフォルトで<code>./tests</code>が指定されているためです。</p>

<h2>テストへの適用</h2>

<p>実際にフロントエンドとバックエンドを分離した構成のアプリケーションをテストしてみましょう。
テスト対象のサンプルシステムは<a href="https://heartbeats.jp/hbblog/2023/05/openapi.html">以前のブログ</a>にて作成したものがあるため、それを利用します。</p>

<p>サンプルシステムの構成は以下のようになっています。</p>

<table border="1">
    <tr>
        <td>種類</td>
        <td>URL</td>
        <td>備考</td>
    </tr>
    <tr>
        <td>バックエンド</td>
        <td>http://127.0.0.1:8081</td>
        <td>/item のエンドポイントでアイテムの情報を返す</td>
    </tr>
    <tr>
        <td>フロントエンド</td>
        <td>http://127.0.0.1:8080</td>
        <td>バックエンドの/itemエンドポイントで取得したデータをブラウザに表示する</td>
    </tr>
</table>

<p>サンプルシステムの起動方法は以下の各リポジトリのREADMEを参照してください。</p>

<ul>
<li><a href="https://github.com/heartbeatsjp/openapi_front_sample?tab=readme-ov-file#%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E8%B5%B7%E5%8B%95">フロントエンド:アプリケーションの起動</a>  </li>
<li><a href="https://github.com/heartbeatsjp/openapi_server_sample?tab=readme-ov-file#%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E8%B5%B7%E5%8B%95">バックエンド:アプリケーションの起動</a>  </li>
</ul>

<h3>レコード機能を使ってテストコードを作成する</h3>

<p>ゼロからテストコードを手で書くことも可能ですが、非常に手間がかかってしまうためオススメできません。Playwrightのレコード機能を利用しましょう。
レコード機能は、ブラウザでの操作を記録してくれる機能です。実施したいテストを画面上で操作するだけで、Playwrightが自動的に操作に対応するテストコードを作成してくれます。
以下で表示の確認、表示文字列の確認、設定値の確認を行うテストの例を作成します。</p>

<ul>
<li><p>記録の開始 <br />
VS Codeのアクティブバーからテストエクスプローラーを開き、PlaywrightのアコーディオンからRecord newを選択してブラウザを起動します。 <br />
<img src="/hbblog/2024/09/playwright_vscode_record_start.png" alt="記録の開始" title="" />  </p></li>
<li><p>テスト対象のページにアクセス <br />
表示されたブラウザのURLに127.0.0.1:8080を入力してフロントエンドにアクセスします。 <br />
<img src="/hbblog/2024/09/playwright_vscode_record_test_access_frontend.png" alt="テスト対象のページにアクセス" title="" />  </p></li>
<li><p>ブラウザに<code>openapi_front_sample</code>が表示されていることを確認するテストの作成</p>

<p>ブラウザ上部中央のパレットから<code>Assert visibility</code>を選択し、表示確認対象の要素を選択します。 <br />
<img src="/hbblog/2024/09/playwright_vscode_record_test_select_assert_visibility_palette.png" alt="AssertVisibility選択" title="" />  </p>

<p>選択し終えるとテストコードが追加されます。 <br />
<img src="/hbblog/2024/09/playwright_vscode_record_test_select_assert_visibility_tag.png" alt="AssertVisibilityテストコード追加" title="" />  </p></li>
<li><p>ブラウザに想定した文字列が正しく表示されているかを確認するテストの作成</p>

<p>ブラウザ上部中央のパレットから<code>Assert text</code>を選択し、比較対象の要素を選択します。 
<img src="/hbblog/2024/09/playwright_vscode_record_test_select_assert_text_palette.png" alt="AssertText選択" title="" />  </p>

<p>比較対象に表示される想定の文字列を設定します。 <br />
<img src="/hbblog/2024/09/playwright_vscode_record_test_select_assert_text_string.png" alt="AssertText文字列設定" title="" />  </p>

<p>設定し終えるとテストコードが追加されます。 <br />
<img src="/hbblog/2024/09/playwright_vscode_record_test_select_assert_text_tag.png" alt="AssertTextテストコード追加" title="" />  </p></li>
<li><p>ブラウザに想定したInputの値が正しく設定されているかを確認するテストの作成</p>

<p>ブラウザ上部中央のパレットから<code>Assert value</code>を選択し、比較対象の要素を選択します。 <br />
<img src="/hbblog/2024/09/playwright_vscode_record_test_select_assert_value_palette.png" alt="AssertValue選択" title="" />  </p>

<p>選択し終えるとテストコードが追加されます。必要な場合は適宜値を設定してください。 <br />
<img src="/hbblog/2024/09/playwright_vscode_record_test_select_assert_value_tag.png" alt="AssertValueテストコード追加" title="" />  </p></li>
<li><p>記録の終了 <br />
ブラウザ上部中央のパレットから<code>Record</code>の赤丸をクリックします。  </p></li>
</ul>

<p>上記操作後、<code>tests/test-1.spec.ts</code>には以下のようなテストコードが生成されます。</p>

<pre>
import { test, expect } from '@playwright/test';

test('test', async ({ page }) => {
  await page.goto('http://127.0.0.1:8080/');
  await expect(page.getByRole('heading', { name: 'openapi_front_sample' })).toBeVisible();
  await expect(page.getByRole('main')).toContainText('{"name":"test","description":"description","price":10,"tax":1}');
  await expect(page.getByRole('textbox')).toHaveValue('10');
});
</pre>

<p>もちろん、このテストコードを手で修正することも可能です。
とりあえずレコード機能を使ってざっくりテストを作り、細かな修正は後ほど手で直す、とすれば毎回DOMを調べなくても良いので、効率よくテストコードが作成できます。</p>

<h2>レスポンスをモックしてみる</h2>

<p>E2Eテストでは他システムも含め、できる限り本番と同じ環境でテストを行うことが理想です。しかし、実際にデータが書き込まれてしまうと困る、意図的にエラーを発生させることが難しい場合など、どうしてもモックを利用せざるを得ないケースもあります。そのようなときに便利なのが<a href="https://playwright.dev/docs/api/class-route#route-fulfill">fulfill</a>です。<a href="https://playwright.dev/docs/api/class-route#route-fulfill">fulfill</a>は、指定したURLのレスポンスをモックする関数です。Playwrightにデフォルトで含まれている関数なので、追加のパッケージをインストールする必要はありません。</p>

<p>試しに、APIサーバーのレスポンスを<code>mock-data</code>に変更して実行してみましょう。</p>

<pre>
import { test, expect } from '@playwright/test';

test('test', async ({ page }) => {
  await page.route('http://127.0.0.1:8081/item', async (route) =>{await route.fulfill({json:'mock-data'})}); // この1行を追加

  await page.goto('http://127.0.0.1:8080/');
  await expect(page.getByRole('heading', { name: 'openapi_front_sample' })).toBeVisible();
  await expect(page.getByRole('main')).toContainText('{"name":"test","description":"description","price":10,"tax":1}');
  await expect(page.getByRole('textbox')).toHaveValue('10');
});
</pre>

<p>APIサーバーのitemエンドポイントのレスポンスを<code>mock-data</code>に書き換えました。URLを指定し、そのレスポンスを定義するだけです。
この状態で、先ほどのテストを実行してみましょう。</p>

<pre>
Error: expect(locator).toContainText(expected)


Locator: getByRole('main')
Expected string: "{\"name\":\"test\",\"description\":\"description\",\"price\":10,\"tax\":1}"
Received string: "\"mock-data\""
</pre>

<p>以前はパスしていたテストがエラーになります。
Expectedが変更前のAPIのJSONになっていますが、Receivedは<code>mock-data</code>になっています。APIサーバーのレスポンスを上書きできていますね。</p>

<p>Playwrightには他にもさまざまな便利な機能があります。興味がある方は<a href="https://playwright.dev/docs/intro">公式ドキュメント</a>をご覧ください。</p>

<h2>おわりに</h2>

<p>本記事では、VS CodeとPlaywrightを使ったE2Eテストの実施方法を紹介しました。他にもさまざまなテスト用関数や、アクション機能などがありますが、今回はグラフィカルに操作可能な部分に焦点を当てて紹介してみました。
簡単な例でしたが、少しでも参考になれば幸いです。</p>
]]>
    </content>
</entry>

<entry>
    <title>フルリモート勤務メンバーとの座談会を開催！～コミュニケーション、情報のオープンさ、評価制度など...たくさん聞いちゃいました～</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2024/10/remotework.html" />
    <id>tag:heartbeats.jp,2024:/hbblog//2.937</id>

    <published>2024-10-18T05:00:00Z</published>
    <updated>2024-10-21T06:02:15Z</updated>

    <summary>こんにちは。 ハートビーツの採用広報担当、工藤です。 ハートビーツには北海道から...</summary>
    <author>
        <name>工藤かおり</name>
        
    </author>
    
        <category term="採用・広報" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="活動" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>こんにちは。
ハートビーツの採用広報担当、工藤です。</p>

<p>ハートビーツには北海道から沖縄まで、全国に暮らすフルリモート勤務のメンバーがたくさんいます。
今回はそんなフルリモート勤務をする3人のメンバーに座談会形式でお話を聞いてみました！</p>
]]>
        <![CDATA[<h2>フルリモート勤務をするメンバーの自己紹介</h2>

<p><a href="https://heartbeats.jp/hbblog/assets_c/2024/10/ca8825e5e9a955f00777466d8c9bfb6e0d185401-2743.html" onclick="window.open('https://heartbeats.jp/hbblog/assets_c/2024/10/ca8825e5e9a955f00777466d8c9bfb6e0d185401-2743.html','popup','width=1155,height=506,scrollbars=yes,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="https://heartbeats.jp/hbblog/assets_c/2024/10/ca8825e5e9a955f00777466d8c9bfb6e0d185401-thumb-1000xauto-2743.png" width="1000" height="437" alt="たつみさん紹介.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a><a href="https://heartbeats.jp/hbblog/assbyets_c/2024/10/a9f7f7b73b398526bb099ca742301a238da4a1a3-2742.html" onclick="window.open('https://heartbeats.jp/hbblog/assets_c/2024/10/a9f7f7b73b398526bb099ca742301a238da4a1a3-2742.html','popup','width=1146,height=508,scrollbars=yes,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="https://heartbeats.jp/hbblog/assets_c/2024/10/a9f7f7b73b398526bb099ca742301a238da4a1a3-thumb-1000xauto-2742.png" width="1000" height="442" alt="鈴木さんsyoukai.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a><a href="https://heartbeats.jp/hbblog/assets_c/2024/10/2ad2710d46c0efde701f0e808756290cf1c2c054-2741.html" onclick="window.open('https://heartbeats.jp/hbblog/assets_c/2024/10/2ad2710d46c0efde701f0e808756290cf1c2c054-2741.html','popup','width=1155,height=514,scrollbars=yes,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="https://heartbeats.jp/hbblog/assets_c/2024/10/2ad2710d46c0efde701f0e808756290cf1c2c054-thumb-1000xauto-2741.png" width="1000" height="444" alt="今井さん紹介.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></p>

<h2>ハートビーツに入社を決めた理由は？</h2>

<p>―　まずは皆さんがハートビーツに入社を決めた理由を教えてください！</p>

<p>たつみさん：<br>「新しい技術に触れてみたいなあ」と思う一方、前職では年季の入ったシステムを触ることが多く、新技術を導入することはなかなか難しい環境でした。
そんな時にハートビーツからスカウトで声をかけてもらったことが転職を考えるようになった最初のきっかけです。<br>そして<strong>入社しようと思ったのは、最新の技術を身につけることができるところがマッチした</strong>からです。あとは、<strong>ハートビーツは面接の印象が良かった</strong>ですね！他社の面接も受けましたが、「スカウト送られてきたけど全然採用する気なさそうだな...」と思うような面接もあったので...。</p>

<p>―　フルリモート勤務に不安はなかったですか？</p>

<p>たつみさん：<br>前職では2,３回くらいしかフルリモートで働いたことがなかったので、最初はちょっとどんな感じか不安もありましたが、<strong>オンボーディング施策がちゃんとあって、入社前にチームメンバーとの座談会をしたり、入社後もコミュニケーションをとる機会がたくさんあったので、あんまり苦労せずに馴染むことができましたよ。</strong></p>

<p>すずきさん：<br>私は前職ではオンプレ環境がメインだったので、クラウドを触ってみたいと思っていました。転職先はフルリモートを条件にして3,4社の選考を同時に受けていました。<br>
その中でハートビーツに決めた理由は、<strong>選考のスピード感が圧倒的に早かったことです。レスポンスも早かったので、「この会社だったら、社内の課題や困りごともスピーディに解決するのではないか」と思って入社を決めました。</strong></p>

<p>いまいさん：<br>私はキャリアに悩んでいた時期に、当時の採用広報チームのマネージャーに声を掛けてもらったことと、もともとハートビーツのことをよく知っていて、<strong>業界の中でも技術力が高くてエンジニアファーストなイメージがあったので、採用担当として心から「良い会社だよ」と候補者さんに伝えられるハートビーツの採用担当になりたいと思い、転職を決めました。</strong></p>

<p>―　いまいさんは初めてのフルリモート勤務に不安はなかったですか？</p>

<p>いまいさん：<br>実は、内定承諾するかを悩むくらいめちゃくちゃ不安がありました！<br>
前職はコロナ禍でもフル出社していたのでフルリモート勤務のイメージができなかったのと、さらに東京の会社なので、「東京の人とオンラインでコミュニケーション取れるのかな...東京の人怖そう...！」と、思っていました(笑）</p>

<p>一同：（笑）</p>

<h2>実際にフルリモートで働いてみてどうでしたか？</h2>

<p>―　入社後、実際にフルリモートで働いてみてどうでしたか？</p>

<p>いまいさん：<br>先ほど、たつみさんがお話ししたのと同じで、<strong>入社前からメンバーと話す機会があったり、きめ細かにキャリアステップについてお話を聞かせてもらえたり、オンボーディングをきめ細かくしてもらえた</strong>ので安心することができました。<br>
そして実際に入社したら、一瞬で慣れることができました！もちろん、東京の人は怖くなかったです(笑)。特に私のチームは入社した時もすごく密なコミュニケーションを取ってフォローしてくれたので良かったです。</p>

<p>すずきさん：<br>私はもともとフルリモートで働いてたので抵抗はなかったんですが、コミュニケーション面での不安はありました。実際に入社してみると、チーム内外の人と話せる機会が多いですし、作業でもSlackの音声通話を繋いでメンバーと一緒に確認作業をするなどして、<strong>最初からスムーズにコミュニケーションをとれたので不安は消えていました。</strong></p>

<p>たつみさん：<br><strong>フルリモートでも特に違和感がなかったです。</strong>困ったこともないです。
なんなら、初めて実出社した時、会議室でプロジェクターに画面を映してモブプロしたんですが「なんかやりにくいねー」ってなって、結局みんないつものフルリモートと同じ環境(Visual Studio CodeのLive Share)でコードを書いてました(笑)</p>

<p>いまいさん：<br>今ってツールが本当に充実していますよね。だから、オフラインでうしろから相手の画面見ながら「ここがちがうよ」とか話すよりも、オンラインの画面共有で同じ画面見ながら話す方がやりやすかったりもしますよね。</p>

<p>―　たつみさんは初めての実出社でも和気あいあいとした雰囲気だったんですね！チームの人とどうやって親睦を深めていたんですか？</p>

<p>たつみさん：<br>うちのチームは毎日朝会を実施してて、業務の話や相談はもちろん、オフの話などの雑談もたくさんしてたんです。</p>

<h2>フルリモートでよかったこと、困ったことはある？</h2>

<p>―　フルリモート勤務のメリットを感じたことってありますか？</p>

<p>たつみさん：<br>そうですね、やっぱり<strong>時間の融通が利く</strong>ってところでしょうか。家族に小さい子供がいるので、保育園の送り迎えや、<strong>突発的な何かがあったときにさっと対応して、そのあと作業に戻ることができてとても助かります。</strong><br>
あとは<strong>通勤がないことが圧倒的に楽</strong>ですね。今から通勤しろと言われたら...無理かな...。あと、宅配便を受け取れることがありがたい(笑)</p>

<p>一同：<br>宅配便わかる！家族にもあてにされたりしますよね(笑)</p>

<p>すずきさん：<br>私が個人的に一番大きかったのは、通勤がなくなったことですかねー。前職は品川の方に勤務してたので、毎日満員電車で。</p>

<p>―　それは超満員ですよね...。</p>

<p>すずきさん：<br>もう、夏場とかなんて...（遠い目）。朝も電車の遅延を考えて早めに家を出てましたし、そういう<strong>ストレスがなくなったことが良かったです。</strong></p>

<p>―　逆に困ったことはありませんか？</p>

<p>いまいさん：<br>服が...。正直ラフな格好でお仕事できるので、そんな服ばっかりになってしまいました(笑)
うちのチームの女性陣はみんなでユニクロTシャツが被って、ユニフォームみたいになってるときあります(笑)</p>

<p>たつみさん：<br>僕は運動量が減ったことですね～。ちょっとくらい外に出て太陽光を浴びたほうがいいなと思ったりします。</p>

<p>すずきさん：<br>私も同じく運動不足です。でも通勤がなくなった分、睡眠時間は長くなりました。</p>

<p>―　健康のためにしてることはありますか？</p>

<p>たつみさん：<br>保育園がちょっと遠いので、朝送るときに、行きは歩いて帰りは走っています。あとはなるべく階段を使うようにしたり...。</p>

<p>すずきさん：<br>私は、スタンディングデスク使ってます。</p>

<p>いまいさん：<br>立って作業している人も多いですよね～！
<a href="https://heartbeats.jp/hbblog/assets_c/2024/10/e66c5df1d1c46e45ad32e9242215e0488992dc2c-2750.html" onclick="window.open('https://heartbeats.jp/hbblog/assets_c/2024/10/e66c5df1d1c46e45ad32e9242215e0488992dc2c-2750.html','popup','width=1000,height=406,scrollbars=yes,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="https://heartbeats.jp/hbblog/assets_c/2024/10/e66c5df1d1c46e45ad32e9242215e0488992dc2c-thumb-1000x405-2750.png" width="1000" height="405" alt="ようす.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></p>

<h2>入社して感じる、ハートビーツのいいところ</h2>

<p>たつみさん：<br><strong>「技術に明るいところ」ですね。新しい技術でも「やってみよー」って感じで触れる</strong>し、特に社内で使うツールをつくるときだったら、<strong>そこまでメジャーな技術じゃなくてもチャレンジしてみようとなる。</strong>入社を決めた理由でもあるので、それをリアルに感じられることはとてもうれしいですね。<br>
あとは優しい人が多いですね～。話しかけやすいし。</p>

<p>すずきさん：<br><strong>私がまず最初に入ってすごく感じたのが「研修が手厚いな」ということでした。</strong>今までの会社ではあまり研修はなくて、いきなりタスクを任されることもあったので。<br>
あとは<strong>コミュニケーションが活発なことと、情報共有も活発</strong>だと思いました。<strong>業務のちょっとしたことも、売上のような情報も、オープン</strong>ですよね。</p>

<p>いまいさん：<br>たしかに、<strong>情報はすごくオープンだし、透明性も高い</strong>ですよね。取締役会の議事録でさえもそう思います。今の状況を透明性高く教えてくれるので<strong>、会社の課題も自分事として捉えやすいし、経営陣の動きも分かって良い</strong>ですよね。安心してハートビーツという船に乗っていられるなと思います。<br>
他には、<strong>評価制度が整っているなと思いました。かなり細かくて明瞭なので、評価する方もされる方も納得感ありますよね。</strong></p>

<p>すずきさん：<br>その話で転職活動していた頃を思い出しました。私は前職での経験を踏まえて評価制度を1つの軸として転職活動をしていたのですが、その中でも<strong>ハートビーツの評価制度は明瞭でモチベーションを維持しやすい環境だと感じました。</strong>それが入社した決め手の一つになりました！</p>

<p>たつみさん：<br>最初の目標を立てるときに大変な思いをして目標を立てたのに、その後評価されるときはフィードバックがなくて「どうなってるのかな？」というのはよくありますよね。<strong>ハートビーツではフィードバックがしっかりあるのはすごいなと思います。</strong></p>

<p>―　何ならハートビーツは期の中間にもフィードバック時間を設けてますもんね。</p>

<p>一同：<br>うんうん。いいよね。</p>

<p>いまいさん：<br>あと、みんないい人。100人いたら、合わない人がいるのも普通だと思うんですけど、本当にいい人ばかり。<br>
社内の誰かが言ってた<strong>「ありがとうが飛び交う環境」</strong>というのを聞いて、本当にそうだなと思いました。Slackのコメントや絵文字でもたくさんの「ありがとう」が飛び交っていて、オンラインでもそれを感じられますよね。</p>

<p>―　<strong>フルリモート勤務には環境や制度を整えることが大切ですが、メンバーの関係性や雰囲気も重要ですよね。</strong><br>
みなさん、今日はありがとうございました！</p>

<p>▼▼▼</p>

<p>以上、座談会の様子をお送りしました。</p>

<p>今回の座談会を通じて、「フルリモート勤務を支えているのは、ハートビーツメンバーの人柄やコミュニケーション力なんだな」ということに気付きました。</p>

<p>そんなハートビーツが気になった方は、ぜひいちど、カジュアル面談でざっくばらんにお話しましょう！</p>

<p>・カジュアル面談は採用サイトからお申込みいただけます<br>
<a href="https://recruit.heartbeats.jp/recruit/">https://recruit.heartbeats.jp/recruit/</a></p>
]]>
    </content>
</entry>

<entry>
    <title>情報セキュリティマネジメントシステム(ISMS)認証取得までの取り組み</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2024/10/isms.html" />
    <id>tag:heartbeats.jp,2024:/hbblog//2.932</id>

    <published>2024-10-10T01:00:00Z</published>
    <updated>2024-10-10T05:42:44Z</updated>

    <summary>こんにちは、情報セキュリティ担当の岩屋です。 今回は弊社が2023年に取得した「...</summary>
    <author>
        <name>岩屋 美紀</name>
        
    </author>
    
        <category term="活動" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>こんにちは、情報セキュリティ担当の岩屋です。</p>

<p>今回は弊社が2023年に取得した「情報セキュリティマネジメントシステム(以下ISMSと略)認証取得までの取り組み」の中で、特に大変だった情報資産とクラウドサービスの管理について紹介します。</p>

<p>弊社は会社設立の間もない時期から個人情報保護の規格であるプライバシーマークを取得していましたが、リモートワークの導入と今後の事業拡大も見据え、自社の情報セキュリティ強化のためにISMS認証を取得することになりました。</p>

<p><a href="/hbblog/assets_c/2024/10/6da4ccdddcebfe3b2acdf3bde388800d1793edb8-2723.html" onclick="window.open('https://heartbeats.jp/hbblog/assets_c/2024/10/6da4ccdddcebfe3b2acdf3bde388800d1793edb8-2723.html','popup','width=1102,height=898,scrollbars=yes,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="https://heartbeats.jp/hbblog/assets_c/2024/10/6da4ccdddcebfe3b2acdf3bde388800d1793edb8-thumb-270xauto-2723.png" width="300" height="220" alt="ICMS認証マーク（ISMS）_カラー.png" class="mt-image-none" style="" /></a>
　</p>

<p>弊社が認証を取得した背景や、認証の詳細は以下をご参照ください。
<a href="https://heartbeats.jp/info/pressrelease/20230621_01/">https://heartbeats.jp/info/pressrelease/20230621_01/</a></p>
]]>
        <![CDATA[<h2>ISMS認証とは</h2>

<p>ISMSとは、組織が保有する情報資産を安全に利用し、リスクを管理するためのしくみを指します。
ISMSはISOが制定した国際的な規格である「ISO/IEC 27001」の要求事項に基づき運用されます。ISMSの認証を維持するためには、ISMS取得後、1年後と2年後はサーベイランス審査（維持審査）、3年後には更新審査、という周期で3年毎に審査が繰り返されます（規格が更新された場合は、加えて更新審査も受ける必要があります）。</p>

<p>「ISO/IEC 27001」では、責任者の明確化、情報の分離、アカウント管理...など、最新の規格で93項目の要求事項が定められています。
これらの要求事項に沿いPDCAサイクルに基づき運用し、第三機関の審査を受け、基準を満たす組織にISMS認証が与えられます。</p>

<p>※PDCAとは、Plan（計画）、Do（実行）、Check（評価）、Act（改善）の頭文字を取った略称です。</p>

<ul>
<li>Plan（計画）...ルールを明文化し、リスクに応じた対策を計画する</li>
<li>Do（実行）...ルールや計画に従い運用し、記録をする</li>
<li>Check（評価）...実施状況を監査し評価する</li>
<li>Act（改善）...評価結果を改善する</li>
</ul>

<h2>認証取得に向けた文書作成</h2>

<p>弊社ではすでに個人情報保護の認証であるプライバシーマークを取得していたため、プライバシーマークの基準に沿った、情報を適切に保護し管理するしくみは運用されていました。</p>

<p>ただし、プライバシーマークとISMSはどちらも情報セキュリティに関する認証ですが、規格で定めた保護する情報の対象が異なります。
プライバシーマークは個人情報を保護対象としているのに対し、ISMSは個人情報を含む機密情報全般を対象としています。
そのため、個人情報に当たらない財務情報や技術情報などの機密情報全般を対象とした運用プロセスを作り、文書を追加で作成する必要がありました。</p>

<p>ISMSの外部コンサルタントに文書のベースを作成してもらい、弊社の運用に合わせて細かに修正を重ね次の文書を作成しました。</p>

<ul>
<li>情報セキュリティポリシー</li>
<li>情報を適切に取り扱い管理するための方針、体制、およびルールをまとめた文書</li>
<li>災害、障害、もしくは情報漏洩などのインシデントが起きた時に事業を継続する手順</li>
<li>社内システム部門や事務所を管理する部門など各部門の役割や定義を定めた文書</li>
<li>従業員むけにISMSのルールを定めたマニュアル</li>
<li>情報資産と情報資産別にリスク分析をした台帳</li>
<li>内部監査、マネジメントレビュー、もしくは年度計画などの運用記録</li>
</ul>

<h2>情報資産の再度棚卸し</h2>

<p>ISMS、プライバシーマークのいずれにおいても、社内で扱う情報資産を洗い出した管理台帳を作成します。管理台帳はプライバシーマーク運用のために既に作成していましたが、ISMS審査に向け、下記の手順で再度洗い直しました。</p>

<p><strong>1.資産ごとのCIAと資産レベルの算出</strong></p>

<p>まずは、顧客情報や会社概要などの粒度で特徴や目的が同じ資産別に分類し、情報セキュリティの三要素であるCIAを数値化し、その合計値から資産レベルを算出します。</p>

<p>※CIAとは、情報セキュリティの三要素と呼ばれる機密性(Confidentiality)、完全性(Integrity)、可用性(Availability)の略称です。</p>

<ul>
<li>機密性(Confidentiality)...アクセスを許可されたものだけが、必要な情報資産を利用できる</li>
<li>完全性(Integrity)...情報が正確で完全な状態で利用できる</li>
<li>可用性(Availability)...アクセスを許可されたものだけが、必要なときに利用できる</li>
</ul>

<p>例えば社外秘である顧客情報は、従業員の中でも顧客対応に関連する担当者のみに利用は限定され、データは改ざんされない正確な状態である必要があり、必要な時に利用できないと事業に影響を及ぼす可能性があります。この場合は資産レベルも高くなります。</p>

<p>一方、会社概要などの対外向けの情報は公開されている情報のため機密性は下がり、顧客情報に比べると必要なときにすぐアクセスできずとも影響は軽微です。この場合は資産レベルの値も低くなります。</p>

<p><strong>2.脆弱性の評価</strong></p>

<p>洗い出した情報資産が災害やサイバー攻撃などのインシデントに対して、どれほどの弱点があるかを脆弱性の値として数値化します。
想定されるインシデントに対して正しく対応できていれば脆弱性の数値は下がり、一方で対応策を取っていないものは脆弱性の数値は上がります。</p>

<p><strong>3.リスク値の算出</strong></p>

<p>ここまで算出した資産レベルと脆弱性の評価値をもとに、リスク値を算出します。
資産レベルが高くても対策が取られていれば脆弱性の数値は下がり、リスク値も抑えられます。
一方資産レベルが高いにも関わらず、対応策を講じていなければ脆弱性の値は上がり、リスク値も上がります。</p>

<p><strong>4.リスクの値の評価</strong></p>

<p>受容できるリスクのレベルを定め、基準を上回った資産に対してリスクを認識し、組織の状況を加味してリスクを受け入れるかを判断します。</p>

<h2>社内で利用している外部クラウドサービス（SaaSサービスとパブリッククラウド）の管理上の課題</h2>

<p>資産を洗い出す中で、大きな課題となったのがクラウドサービスの管理です。
弊社は業務の特性上、クラウドサービスの利用が欠かせません。全社的に利用頻度が高いものや重要な機密情報を扱うクラウドサービスは厳格な管理をしていましたが、それ以外のクラウドサービスは情報が各所に散らばっていました。</p>

<p>そのため、誰がどのような目的で、どのようなクラウドサービスを利用しているかを一覧にした、クラウドサービスの台帳を作成することにしました。</p>

<p><strong>1.利用許可基準や利用方法をまとめた社内ルールの作成</strong></p>

<p>まずは台帳を作成するにあたり、クラウドサービスの利用許可基準や利用方法を社内ルールとしてまとめるところから始めました。
利用許可基準には、情報セキュリティに関する認証を取得しているか、解約後にデータ削除がされるか...など安全なクラウドサービスだと判定できる項目を定めました。</p>

<p><strong>2.申請フローの整備</strong></p>

<p>整備前はチャットツールで確認を取り利用を開始していたため、申請フォームを整え、情報セキュリティ担当の承認を得てから利用する運用に変更しました。
申請フォームを整えることで、「いつ」「だれが」許可したか証跡を残すことができ、内部統制の強化にもつながりました。</p>

<p><strong>3.台帳への洗い出し</strong></p>

<p>社内ルールとフローを整備した後は、部署ごとに利用しているクラウドサービスを洗い出してもらいました。
洗い出し後にサービス名やサービスの管理責任者、担当者などの情報を台帳化し、全従業員が閲覧できる場所に保管し情報を集約しました。</p>

<p>一覧で洗い出した結果、弊社では100社近いクラウドサービスを利用していることが判明しました。
こういった情報が整備されていないと、どこを見ればよいかわからないだとか、誰に聞けばよいの分からないといった状況が発生します。ISMS取得に向けた取り組みが、情報を整備する良いきっかけになりました。</p>

<h2>最後に</h2>

<p>こうして社内ルールの整備や文書作成に始まり、PDCAに基づいた運用を行い、ISMS認証を取得することができました。
しかし、ISMS認証は取得したら終了ではなく毎年定期的な審査を繰り返し、継続して確認し改善する必要があります。
ISMSの要求事項に沿って正しく情報を取り扱うためには、情報セキュリティ担当だけでなく、全従業員が情報セキュリティに関するルールを理解し運用してもらうことが重要です。</p>

<p>今回整備した社内ルールや手順は、一度作成後に周知をしただけでは中々社内に根付きません。
定期的な教育に加え、啓蒙資料の作成や手順のこまめな整備を繰り返し、より従業員に伝わりやすく発信することを意識し運用してまいります。</p>

<div style="text-align: right;">
※ISMS認証マークの内容など記事に記載された内容は公開当時のものです。</div>
]]>
    </content>
</entry>

<entry>
    <title>go-retryablehttpを利用したHTTPリクエストのリトライ処理の実装</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2024/09/go-retryablehttphttp.html" />
    <id>tag:heartbeats.jp,2024:/hbblog//2.931</id>

    <published>2024-09-20T01:00:00Z</published>
    <updated>2024-09-20T00:45:32Z</updated>

    <summary>こんにちは、技術開発チームの小嶋です。 とある社内ツールの開発において、HTTP...</summary>
    <author>
        <name>小嶋 宏幸</name>
        <uri>https://heartbeats.jp/</uri>
    </author>
    
        <category term="技術" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>こんにちは、技術開発チームの小嶋です。</p>

<p>とある社内ツールの開発において、HTTPリクエストのリトライ処理の実装に<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>を利用しました。<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>はHashiCorp社が中心となって開発しているOSSライブラリです。本記事ではリトライ処理の概要や<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>を利用した経緯について紹介します。</p>
]]>
        <![CDATA[<h2>なぜリトライ処理が必要なのか</h2>

<p>はじめに、リトライ処理の必要性について簡単に触れます。クライアントとサーバがネットワークで接続されている環境において、クライアントがサーバへリクエストを送信する処理について考えてみます。このような環境ではリクエストが失敗する要因をいくつか想定できます。例えば、次のような要因があります。</p>

<ul>
<li>クライアントのリクエストが誤った内容であり、リクエストが実行エラーとなった</li>
<li>ネットワークで一時的な接続障害が発生し、リクエストがサーバに届かなかった</li>
<li>利用者の一時的な急増に伴ってサーバが過負荷になり、リクエストがタイムアウトになった</li>
</ul>

<p>リクエストの失敗につながるこれらの要因は恒久的に発生するエラーと一時的に発生するエラーに分類できます。</p>

<ul>
<li>恒久的に発生するエラー：クライアントのリクエストの誤りによるエラーが恒久的に発生するエラーを指す。リクエストの内容を修正するなど根本的な対策を施さなければ回復が見込めない。</li>
<li>一時的に発生するエラー：ネットワークの一時的な接続障害によるエラーや、利用者の一時的な急増に伴うサーバ過負荷によるタイムアウトが一時的に発生するエラーを指す。一定の時間内に回復が見込める。</li>
</ul>

<p><img src="/hbblog/2024/08/20/go-retryablehttp01.png" alt="リクエストが失敗する要因" title="" /></p>

<p>一時的に発生するエラーは時間を置いて処理を再実行すれば成功する場合も少なくありません。すなわち、処理を繰り返し実行していれば最終的には成功に至ります。このように成功するまで処理を繰り返し実行する操作をリトライ処理と呼びます。サーバがクラウドサービスや自社管理外APIなどの環境ではサーバを直接変更できないため、クライアントによるリトライ処理が一時的に発生するエラーへの有効な対策の1つとなります。</p>

<p><img src="/hbblog/2024/08/20/go-retryablehttp02.png" alt="リトライ処理" title="" /></p>

<h2>リトライ処理の実装における考慮点</h2>

<p>リトライ処理を実装するうえで考慮すべき点がいくつかあります。</p>

<p>1つ目の考慮点として、リトライ条件の判定があります。前述のようにエラーには恒久的なものと一時的なものがあります。恒久的なエラーは処理を繰り返し実行しても回復が見込めないため、一時的なエラーに限ってリトライ処理を実行しなければいけません。HTTPリクエストにおいてはコネクションエラーやHTTPステータスコードの429 Too Many Request/5xx台のものが一時的なエラーに該当します。</p>

<p>2つ目の考慮点として、処理の再実行の間に挟む待ち時間があります。待ち時間を挟まずに処理を繰り返し実行し続けた場合、多数のリクエストがサーバに送信されます。その結果、サーバが過負荷になるなど悪影響を与える恐れがあります。サーバが過負荷になっているシナリオにおいてはまさに泣きっ面に蜂の状況です。</p>

<p><img src="/hbblog/2024/08/20/go-retryablehttp03.png" alt="リトライ処理による影響" title="" /></p>

<p>リトライ処理による影響を防ぐためには処理の再実行の間に待ち時間を挟むことが有効です。この待ち時間を計算するアルゴリズムの1つとして<code>Exponential Backoff</code>があります。<code>Exponential Bakckoff</code>は「1秒, 2秒, 4秒, 8秒」のようにリトライ回数に応じて待ち時間を指数関数的に増加させます。そのうえで最大リトライ回数や最大待ち時間になるまで処理を繰り返し実行するアルゴリズムです。待ち時間を指数関数的に増加させることでリトライ処理による影響をより効果的に防げます。</p>

<p><img src="/hbblog/2024/08/20/go-retryablehttp04.png" alt="Exponential Backoff" title="" /></p>

<h2>go-retryablehttpによるHTTPリクエストのリトライ処理</h2>

<p>前述のようにリトライ処理を実装するうえでは考慮すべき点があり、注意深く実装を進める必要があります。今回はリトライ処理の実装をOSSライブラリにまかせる方針をとり、社内ツールの開発言語としてGoを利用していたことからGoのOSSライブラリをいくつか調査しました。結果として、後述の理由のとおり<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>を選択しました。<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>はHashiCorp社が中心となって開発しているOSSライブラリです。詳細は<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>のリポジトリやドキュメントを参照してください。</p>

<p>その他のOSSライブラリの候補としては、<a href="https://github.com/avast/retry-go">retry-go</a>や<a href="https://github.com/cenkalti/backoff">backoff</a>がありました。これらのOSSライブラリは<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>と比べてよりシンプルな機能を提供しています。そのため、リトライ処理の内容がHTTPリクエストに限らない一般的な処理の場合やリトライ条件を明示的に指定したい場合に利用するとよいでしょう。</p>

<p>ここからは<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>を選択した理由と簡単な利用方法について触れます。<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>を選択した1つ目の理由として、リトライ処理が実装されたHTTPクライアントをGo標準パッケージのHTTPクライアントへ変換できる点が挙げられます。下記のようにリトライ処理が実装されたHTTPクライアント（<code>retryablehttp.Client</code>）を設定し、その後でGo標準パッケージのHTTPクライアント（<code>http.Client</code>）へ変換できます。既存のコードで<code>http.Client</code>を利用している部分を差し替えるだけでHTTPリクエストのリトライ処理を簡単に実装できます。<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>を選択した最大のポイントです。</p>

<pre>
// retryablehttp.Clientの設定
retryClient := retryablehttp.NewClient()
retryClient.RetryMax = 3
retryClient.RetryWaitMin = 1_000 * time.Millisecond
retryClient.RetryWaitMax = 10_000 * time.Millisecond

// retryablehttp.Clientをhttp.Clientへ変換
standardClient := retryClient.StandardClient()

// http.ClientでHTTPリクエストの送信
req, _ := http.NewRequest(...)
res, err := standardClient.Do(req)
</pre>

<p><a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>を選択した2つ目の理由として、リトライ条件の判定が実装されている点が挙げられます。<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>のデフォルトのリトライ条件の判定は<a href="https://pkg.go.dev/github.com/hashicorp/go-retryablehttp?utm_source=godoc#DefaultRetryPolicy">DefaultRetryPolicy</a>として実装されています。コネクションエラーやHTTPステータスコードが5xx台の場合（501 Not Implementedを除く）にリトライ処理が実行されます。</p>

<p><a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>を利用した理由の3つ目の理由として、複数の待ち時間アルゴリズムが実装されている点が挙げられます。<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>のデフォルトの待ち時間アルゴリズムは<a href="https://pkg.go.dev/github.com/hashicorp/go-retryablehttp?utm_source=godoc#DefaultBackoff">DefaultBackoff</a>として実装されています。<a href="https://pkg.go.dev/github.com/hashicorp/go-retryablehttp?utm_source=godoc#DefaultBackoff">DefaultBackoff</a>は<code>Exponential Backoff</code>を実装しており、最大リトライ回数や最小・最大の待ち時間を指定できます。その他の待ち時間アルゴリズムとしては<a href="https://pkg.go.dev/github.com/hashicorp/go-retryablehttp?utm_source=godoc#LinearJitterBackoff">LinearJitterBackoff</a>が実装されています。また、待ち時間アルゴリズムが満たすべき関数の型（<a href="https://pkg.go.dev/github.com/hashicorp/go-retryablehttp?utm_source=godoc#Backoff">Backoff</a>）が公開されているので、独自の待ち時間アルゴリズムを実装して利用できます。</p>

<p>以上のような点を踏まえ、<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>を利用してHTTPリクエストのリトライ処理を実装しました。<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>を利用した感想として、HTTPリクエストのリトライ処理がクライアントの責務として抽象化されているのが良い点だと感じました。Go標準パッケージのHTTPクライアントを利用している箇所では既存のコードにほぼ修正を加えずにリトライ処理を実装できるため、他の社内ツールの開発でも積極的に利用していきたいです。</p>

<h2>おわりに</h2>

<p>本記事ではリトライ処理の概要や<a href="https://github.com/hashicorp/go-retryablehttp">go-retryablehttp</a>を利用した経緯について紹介しました。お手軽に利用できるOSSライブラリなのでぜひ試してみてください。</p>
]]>
    </content>
</entry>

<entry>
    <title>「研修開発入門」という本を読んで勉強してみた</title>
    <link rel="alternate" type="text/html" href="https://heartbeats.jp/hbblog/2024/09/training-part3.html" />
    <id>tag:heartbeats.jp,2024:/hbblog//2.930</id>

    <published>2024-09-03T05:00:00Z</published>
    <updated>2024-09-03T05:41:21Z</updated>

    <summary>こんにちは。事業基盤グループ 人材開発チームの倉持です。 今までに新入社員向けの...</summary>
    <author>
        <name>倉持亘</name>
        
    </author>
    
        <category term="活動" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://heartbeats.jp/hbblog/">
        <![CDATA[<p>こんにちは。事業基盤グループ 人材開発チームの倉持です。</p>

<p>今までに新入社員向けの研修を開発することが何回かあったのですが、感覚で行っていた部分が大きかったため、社内全体の研修をするうえであらためて研修開発の基本を学び直そうと思い、「研修開発入門」という本を読んでみました。</p>

<p>※今回の参考文献</p>

<ul>
<li>研修開発入門 ー 会社で「教える」、競争優位を「つくる」</li>
<li>中原 淳 著</li>
<li>発行年月：2014年03月</li>
<li>頁数：352</li>
<li><a href="https://www.diamond.co.jp/book/9784478027257.html" target="_blank" rel="noopener noreferrer">https://www.diamond.co.jp/book/9784478027257.html</a></li>
</ul>

<p>※注意。本ブログでは参考文献を要約としてまとめたものではなく、本を読んだうえで我々にとって必要と感じた部分を引用する形としています。参考文献について興味を持たれた方はぜひ直接原著を読んでみてください。</p>
]]>
        <![CDATA[<h2>研修開発のプロセス</h2>

<p>本書では、研修開発とは「研修を考え、学習者に届け、効果を生み出すまでのプロセス」と書かれており、具体的には下記のようなプロセスとなっています。</p>

<ol start='1'>
<li>研修企画</li>
<li>研修デザイン</li>
<li>研修講師選定</li>
<li>研修広報</li>
<li>研修準備</li>
<li>研修実施</li>
<li>研修フォローとレポーティング</li>
</ol>

<p>今回は、私自身の経験が浅い「研修企画」「研修デザイン」に焦点を当てて、印象に残った部分について触れていきます。</p>

<h2>研修企画</h2>

<p>経営や現場のニーズに合致した研修企画を行うためには、下記の4つのポイントを実行していく必要があるとのことです。</p>

<ol start='1'>
<li>ニーズの探索 </li>
<li>人材マネジメント施策の検討</li>
<li>学習者の分析</li>
<li>経営陣と現場トップのステークホルダー化 </li>
</ol>

<p>「ニーズの探索」では、経営陣や現場とコミュニケーションを取りどういったニーズがあるのかを探索します。ここで注意することは、ヒアリングしたニーズが個人の思い込みである可能性もあるということです。そのため、経営陣や現場のマネージャーの声に真摯にかつ、積極的に耳を傾けつつも何が真の問題であるかを検証することが大切であると書かれていました。また、新しいニーズを追加するだけでなく、ニーズが失われたものをやめることも必要とのことです。弊社の研修も定期的に見直しを行っていますがそれでも遅いと感じることはあるので、より短いスパンで最新のニーズを探索することが大切だと感じました。</p>

<p>「人材マネジメント施策の検討」では、抽出された問題を「採用」「人材育成」「配置」「処遇」などのさまざまな人事マネジメント施策の、どの手段で解決するのが最適かを考えていきます。研修開発のプロフェッショナルとは「研修でこそ解決できるもの」を選択的に選び取り研修に落とし込むこと、あるいは研修と他の人材マネジメント施策とを組み合わせて解決できる人のことを指すと書かれていました。</p>

<p>「学習者の分析」では、研修対象となる学習者を決定し、プロファイリングしていきます。コスト面や研修後の成果などを考慮して、現場の社員を対象とするのか、その上司であるマネージャーを対象とするのか、といったように研修対象を決めていきます。ただ研修対象となる学習者を決めるだけでなく、その学習者についてよく知ることが重要とのことです。今までの経験や保有している知識やスキル、学習者本人がもっとも知りたいことなどを把握しておくことで、学習者に合わせた研修を行うことができます。</p>

<p>「経営陣と現場トップのステークホルダー化」では、研修の利害関係者に事前の情報提供、提案活動などを行い、後で協力が得られるようにしておきます。</p>

<h2>研修のデザイン</h2>

<h3>研修の目的と行動目標化</h3>

<p>研修をデザインする際最初に行うべきことは目的を決めることです。研修の目的とは、「現場で成果につながる行動を取ることができるようにすること」と書かれていました。そのため、「研修で何を獲得しその結果どういった行動ができるようになるのか」という観点で目的を決めることが大切です。さらに、その目的を細分化し、現場でどのような行動を取ることができれば良いかを具体的にリスト化（行動目標化）していきます。</p>

<h3>評価方法の検討</h3>

<p>次に、行動目標それぞれが達成できたかを評価するための方法を検討していきます。この段階で評価方法を検討することで、行動目標の妥当性をチェックできるとのことです。</p>

<p>評価については、下記ブログが参考になりますので併せて読んでいただければと思います。</p>

<p><a href="https://heartbeats.jp/hbblog/2024/06/%20training-part1.html">より効果的な研修を作成するために 〜研修開発における研修評価について勉強してみた〜</a></p>

<h3>学びの原理・原則</h3>

<p>研修の目的を決めて行動目標化し評価方法を決めることができたら、実際の研修の内容をデザインしていきます。その際に、今までの長い学習研究によってつくられた「学びの原理・原則」を意識すると良いと書かれています。</p>

<h4>目的の原理</h4>

<p>大人は「なぜ、研修で学ばなければならないのか（目的）」「この研修を受けるメリットとは何か（メリット）」「この研修は、どんなふうに自分の仕事と関連するのか（業務への関連）」といった「目的」が十分に意識できていないと、安心して学ぶことができないとのことです。</p>

<p>確かに、通常業務がある中で時間を割いて研修に参加するには、目的に納得感がないと研修に参加するモチベーションが上がらないですよね。研修する前に研修の目的やメリットを理解してもらうことが大切だと感じました。</p>

<h4>学習者中心の原理</h4>

<p>学習内容は、学習者の既存の知識や経験に応じて教えられなければならないとのことです。教える側は「教授者中心」にものを考えがちらしいのですが、もっとも大切なのは「学習者の立場に立ち、学習者の現在の状況に合った学習内容を選択すること」とのことです。そのためにも、研修の企画段階で学習者の分析をしっかり行っておく必要がありそうです。</p>

<h4>多様性と螺旋の原理　</h4>

<p>大人は子ども以上に飽きやすいらしいです。大人に学びを提供するときには学習目標を見据えたうえで、多種多様な活動を組み合わせ、徐々に低次の活動から高次の活動にステップアップさせ、飽きない工夫をする必要があるようです。例えば、最初は座学で学び、次にグループワークを行い、最後に実践する、のようにステップアップさせていきます。</p>

<h4>知識と体験の原理</h4>

<p>「概念的な知識を学ぶこと」と「体験や実習すること」のバランスを取りながら、学習を組み立てなければならないという原理のようです。知識だけ積み重ねても実際の行動には結びつかず、体験だけさせても反知識主義に陥ってしまう可能性があるため、「知識」と「体験」のバランスを取ることが大切です。</p>

<h4>学習者共同体の原理</h4>

<p>人は学ぶときに他者を必要とするとのことです。学習を促す際には、学習者共同体を組織し他者と共に学べるようにする工夫が必要です。学習研究では、基本的に学習というのは他者の中にあると考えられているそうです。そのため、共同体の中で共に学んでいけることや、みんなで価値あるものを探求していくこと、その中で試行錯誤していきながら学ぶ、ということも大切です。</p>

<h4>フィードバックと内省の原理</h4>

<p>学習した内容は、学習者自ら実践しそれに対して他者からフィードバックを与えられ、内省する機会を設ける必要があるとのことです。そのためには、学習目標を明確に定義し、実践の機会を設け、じっくり内省するための時間をカリキュラム内に確保しておく必要があります。</p>

<h4>エンパワーメントの原理</h4>

<p>大人の学習には、過去の自分のやり方を否定し新たなものを生み出していくこともあり、混乱や葛藤が生じることもあります。そしてネガティブな感情になることもあります。そういったネガティブな感情をそのままにするのではなく、研修の最後には学習者が立ち上がり、何かを実践していけるように心理的状態をゆるやかにコントロールする必要があるとのことです。最後は学習者を元気付けて（エンパワーメント）現場に帰すということが大切なようです。</p>

<h2>最後に</h2>

<p>本書を読んで、無意識で行っていたことを実感でき、基本的なことを疎かにしていたことに気づくことができました。また、当たり前に思えるようなことでも、今までの行動を振り返ってみると実践できていないことが多いと感じました。成果につながる行動ができるようになるための研修を行えるように、学んだことを実践していきたいと思います。</p>
]]>
    </content>
</entry>

</feed>
