hekiblo

hekki blog

さくらのクラウド - AppRunで画像変換サービスを作ってみた!

さくらインターネットの伊東です。この記事は さくらインターネット Advent Calendar 2024 17日目の記事です。

本エントリーでは、先日リリースされたさくらのクラウドの新サービスである AppRun を一通り使ってみましたので、レポートさせていただきます。

AppRunとは

AppRunは、コンテナ化されたアプリケーションを簡単にデプロイし、自動的にスケーリングを行うサービスです。インフラ管理の複雑さを気にすることなく、開発者が本来の業務であるアプリケーション開発に集中できる環境を提供します。

2024年12月17日時点ではβ版のサービスであり、制約事項があるものの全機能を無料で利用できます。嬉しいですね。

※詳細は https://manual.sakura.ad.jp/cloud/apprun/about.html をご参照ください。

AppRunを使おう

では早速AppRunを使ってみましょう。まずはこれから作るものをざっくりご紹介します。

https://app-6d264259-85f4-4ee7-85dc-77a90a0cadf4.ingress.apprun.sakura.ne.jp/f=webp,w=1024/apprun001.png

サンプルアプリケーションとして、オブジェクトストレージに保管された画像を変換するWebアプリケーションを用意します。 このアプリケーションをAppRunでホスティングしてみます。

また、アプリケーションのビルドとデプロイをGitHub Actionsで行い、アプリケーションの更新時に自動でAppRunへデプロイできるようにします。

1. サンプルアプリケーションを作成する

まずはAppRunにデプロイするためのサンプルアプリケーションを用意して、コンテナイメージにまとめます。

nginxで「Test1」といった文字列を表示するだけでは面白みがないため、ちょっとしたアプリケーションを作ってみました。

github.com

imagineは、当社の画像変換・配信サービス ImageFlux のごく一部の画像変換機能を自作してみたものです。jpeg, webp, png, gif への画像変換と、width/heightを指定したサイズ変換ができます。

なお、私はImageFluxの実装は見たことがなく、あくまでも雰囲気を真似しただけのサンプルアプリケーションだとご理解ください 🙏

2. 変換元画像を用意する

上記でご紹介したimagineの変換元画像を用意しておきます。今回は 1.jpg, 2.jpg, 3.jpg と3枚の画像を用意しました。

これらの画像を オブジェクトストレージバケットに配置します。

3. コンテナレジストリを作成する

サンプルアプリケーションのコンテナイメージをデプロイする先として、コンテナレジストリ を用意します。

このときに、レジストリ自体の公開範囲は「非公開」に設定し、PushとPullの権限を持つユーザーを作っておくのが望ましいです。

4. AppRun Applicationを作成する

前準備はここまでにして、ついにAppRun Applicationを作成します。

4.1. AppRun Applicationの作成手段

Applicationを作成する方法は主に3通りあります。

4.1.1. APIを直接叩く

ひとつめはAppRunが提供する操作用のAPIを直接叩く方法です。

manual.sakura.ad.jp

4.1.2. APIライブラリを使う

ふたつめはGoで実装されたAppRunのAPIライブラリを使う方法です。

僕が頑張って作ったので使ってもらえると嬉しいです!!!

github.com

4.1.3. Terrafrom SakuraCloud Providerを使う

みっつめは、Terrafromを使う方法です。

内部的に上記で紹介したAPIライブラリを利用してAPIを叩いてコントロールをしていますので、ある意味ではふたつめとの合せ技とも言えます。

こちらも僕が頑張って作ったので使ってもらえると嬉しいです!!!

4.2. TerrafromでAppRun Applicationを作成

本エントリーではTerrafrom SakuraCloud ProviderでAppRun Applicationを作ってみます。

以下のようなtfファイルを作成することでAppRun Applicationを作成できます。

gist.github.com

なお、以下の情報を書き換える必要があることに注意してください。(詳細は ドキュメント を参照してください)

  • container_registry にコンテナレジストリ自体のイメージ名とホスト名、username, password に、で設定したPushとPullの権限を持つユーザーの認証情報
  • AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY 環境変数にオブジェクトストレージのアクセスキーの情報
  • BUCKET_NAME はオブジェクトストレージに作成したバケット

また、さくらのクラウドAPIの認証情報を設定しておく必要があります。詳しくは以下の情報を参照してください。

docs.usacloud.jp

5. アクセスする

AppRun Applicationが正しく作成されたら、公開用URLが発行されます。

公開用URLはTerraformでdata sourceを利用するか、APIを叩く方法がありますが、せっかくなのでTerraformで取得してみましょう。

以下のようなtfファイルを作成することで、AppRun Applicationの公開用URLが取得できます。

gist.github.com

実際に動かしてみると以下のようになります。(idはマスクしてあります)

$ terraform apply
data.sakuracloud_apprun_application.imagine: Reading...
sakuracloud_apprun_application.imagine: Refreshing state... [id=xxxxxxxxxxxx]
data.sakuracloud_apprun_application.imagine: Read complete after 1s [id=xxxxxxxxxxxx]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

imagine = "https://app-6d264259-85f4-4ee7-85dc-77a90a0cadf4.ingress.apprun.sakura.ne.jp"

先程の手順でオブジェクトストレージにアップロードした 1.jpg をWebP形式・幅を1024にリサイズして取得してみます。

https://app-6d264259-85f4-4ee7-85dc-77a90a0cadf4.ingress.apprun.sakura.ne.jp/f=webp,w=1024/1.jpg

https://app-6d264259-85f4-4ee7-85dc-77a90a0cadf4.ingress.apprun.sakura.ne.jp/f=webp,w=1024/1.jpg にアクセスすると、AppRun上でホスティングされたアプリケーションにアクセスできるので、ぜひ試してみてください!!

GitHub Actionsでデプロイをしよう

発展して、アプリケーションを更新した際にGitHub Actionsでデプロイをできるようにしてみます。デプロイの流れは以下のようになっています。

  • mainブランチにpushされたときに実行
  • コンテナイメージのビルド
  • ビルドしたコンテナイメージをコンテナレジストリにPush
    • コンテナイメージのタグは latestcommit idの短縮表記 のふたつ
  • AppRunのApplicationに新しいコンテナイメージを反映

作成済みのyamlは先程紹介したサンプルアプリケーションのリポジトリに含まれますので参考にしてください。

github.com

なお、GitHub リポジトリActions secrets and variables から Repository secrets に以下のシークレットが登録してある前提となっていますのでご注意ください。

おわりに

AppRunによるコンテナのホスティングはかなり簡単に行えたので、アプリケーションの実装に注力できてとてもいい感じでした。特に今回サンプルアプリケーションとしてご紹介したようなステートレスなアプリケーションと相性がいいですね。

また、本エントリーでは紹介できませんでしたが、AppRunにはアプリケーションのバージョンを管理する機能があり、バージョン間でトラフィックを分散する機能があります。 この仕組みを使えばカナリアリリースを行うことも可能で、AppRunが正式版としてリリースされれば、実運用にも耐えられると感じました。

AppRun自体の機能や周辺ツールなど「こんな機能があったら便利だな」というアイディアがありましたら、窓口 からフィードバックをお寄せください。

以上、最後まで読んでいただいてありがとうございました!

さくらのクラウドのオブジェクトストレージをaws-sdk-go-v2で使ってみる

どうもこんにちは。今年の7月にさくらインターネットに出戻りしました。 ということでさくらのクラウドで色々と遊ぶために、まずはさくらのクラウドオブジェクトストレージaws-sdk-go-v2 から使ってみましたので、そのやり方をメモしておきます。

ここまででお分かりのとおり、さくらのクラウドのオブジェクトストレージはAWS S3互換です。このため、AWS SDKからバケットやオブジェクトの操作をすることができます。

ちなみに世の中にはこれ以外にもいくつかS3互換オブジェクトストレージが存在しますので、その他のAWS S3互換オブジェクトストレージでも概ね同じような形で扱うことができます。

先にサンプルコードを貼っておきます。 gist.github.com

ポイント

1. BaseEndpointの変更

オブジェクトストレージの サービス仕様 にも記載があるとおり、エンドポイントを変更する必要があります。

aws-sdk-go-v2 s3 packageの NewFromConfig でBaseEndpointを変更することができます。

2. リージョンの変更

環境変数 AWS_REGION を指定することでregionを jp-north-1 に変更します。

また、コード上で変更したい場合はBaseEndpoint同様にs3 packageのNewFromConfigから変更が可能です。

client := s3.NewFromConfig(cfg, func(options *s3.Options) {
    options.BaseEndpoint = &baseEndpoint
    options.Region = "jp-north-1"
})

3. アクセスキーIDとシークレットアクセスキーの設定

オブジェクトストレージ サービス基本情報 | さくらのクラウド マニュアル に従って、オブジェクトストレージにアクセスするための アクセスキーIDシークレットアクセスキー が作成できます。

環境変数 AWS_ACCESS_KEY_ID にアクセスキーID、AWS_SECRET_ACCESS_KEY にシークレットアクセスキーを設定することでAWS SDKがそれぞれの値を使ってくれます。

また、コード上で設定したい場合はcredentials packageの credentials.StaticCredentialsProvider にアクセスキーIDとシークレットアクセスキーをセットすればOKです。

creds := credentials.NewStaticCredentialsProvider(accessKey, secretAccessKey, "")
cfg, err := config.LoadDefaultConfig(ctx, config.WithCredentialsProvider(creds))

TIPS

ちなみに、aws-sdk-go-v2自体のEndpointResolver 等を利用するエントリーもありますが、これはdeprecatedとなっていますのでご注意ください。詳細についてはパッケージのコメントを参照してください。

2023年 振り返り

今更という感じですが、2023年の活動についてまとめておきます。(1年に1エントリーペースでしか書いてない…)

仕事

一応断っておきますが、以下全て個人の感想です。所属組織の意見を代表するものではありません。

全体を通して

引き続き株式会社MIXIに勤務していまして、家族アルバム みてね のSREをやっています。勤続7年目に突入しました。時が過ぎるのはあっという間。

勤続年数が長くなってきたこともあり、サービスのコアとなるような要素技術にもある程度明るくなってきたのでその知識を使って社内勉強会を開いたり、登壇や執筆を積極的に行った1年でした。このあたりはある程度手応えがあって良かったポイントです。

逆に、部屋の中の象といわれるような問題に対しての改善の提案だったり、わりと大きめのアーキテクチャの変更などは上手くコントロールできず成果を出せなかった反省も多い1年でした。いい意味で大きなストレスなく日々の業務に当たれている一方で新卒の頃のような右も左も分からないけどがむしゃらに仕事に打ち込む熱量を失ってしまったなーと思うこともあり、2024年はもっとチャレンジしていきたいです。

登壇 & 執筆

昨年は4回登壇の機会をいただきました。前職ではわりと登壇の機会が多かった一方で、転職後でこんなに登壇したのは初めてでした。加えて2本記事の執筆もしました。

会社やサービスのブランディング、キャリアアップのためのセルフブランディング、技術コミュニティへの貢献など目的は様々だと思いますが、外部露出は目的を持って狙って動かないと割く時間の割には得られるものが少なくなってしまうと感じる事が多く、改めて目的を意識することの大切さが身に沁みました。

また、反響の有無は、内容の質・分かりやすさ、ワードチョイス、ネタの鮮度(リリースしたばかりの注目度の高いなにかを使ってみたとか)など色々と要因がありそうで、個人的には「めちゃくちゃおもしろい!」と思った内容で全く反響がなかったり、逆に意外と反響が大きかったり、自分の思い通りには全くいかず難しいなと感じることが多かったです。

プライベート

現在居住中のマンションを売って、郊外に家を建てることにしました。 2023年の春頃から本格的に動き出して、それ以降プライベートの大半は家のことを考えてました。まだまだ全行程完了していないですが、落ち着いたらまとめるぞ。

2023年1月に保護猫を迎え入れました🐈‍⬛(その後に家の話が出てきてしまい、引っ越しは猫にとってストレスなので申し訳い気持ち。) 元野良猫なので正確な年齢は不明ですが、4歳の黒猫です。ばり可愛い。

ねこ

英語

学生時代から英語が苦手でのらりくらりとやってきたものの、英語の壁を感じてチャレンジできない機会が何回かありました。

さすがに悔しかったので、今年は英語をやっていく所存です。「グローバル人材に俺はなる!!」みたいな謎の目標だといつまで経っても達成出来ずにダレるので、まずは分かりやすいTOEICのスコアアップを目指します。

TOEICでハイスコア取っても英語は喋れるようになれない」的なことを言われがちですが、とにかくハイスコアを目指します。ハイスコアを取れるようになって、それでも全然だめだったらそのときに方針転換するつもり。

おわりに

今年はぼんやりと考えてることを言語化する練習のためにもブログを書くぞ!!!!

Macのターミナル環境再構築メモ

Macの調子が悪く、クリーンインストールをしました。
せっかくなので、ターミナル環境の構築メモを残しておきます。

基本的に、デフォルトの設定からなるべく変更しないことを良しとしているので、あまり面白くないかも。

iTerm2

iterm2.com

他のターミナルソフトもしらべてみたものの、なんだかんだでiTerm2に落ち着きました。

設定はそれほどいじっていませんが、主な変更点はこちら。

Homebrew

brew.sh

みんな大好きHomebrew。

fish shell

shellはbash -> zsh -> fish shell という感じで渡り歩いて、fish shellで今の所は落ち着いています。

fishshell.com

プラグインマネージャーはfisherを使います。
また、プラグインは下記のプラグインを使っています。

  • jethrokuan/z
  • laughedelic/brew-completions
  • matchai/spacefish

tmux

tmux自体はbrewでインストールしています。
プラグインマネージャーはtpmを使います。

詳細はtmux.confにて。


以上!

AWS Systems Manager Session Manager を使って、手元のマシンから楽してEC2へ接続する

概要

AWS Systems Manager Session Manager(以下Session Manager)を使用している環境でEC2 に接続する場合、色々と面倒なことがわかりました。

面倒事

Session Manager はマネジメントコンソールから利用する場合「マネジメントコンソールにログイン -> 接続先のEC2 インスタンスを探す -> Session Manager を使用して接続」という流れになります。
毎回この手順を踏むのは面倒ですし、SSH のように手元のマシンから接続できないのは不便なので、AWS CLI を使いたくなります。

ただし、AWS CLI + Session Manager の場合でも、接続先のEC2 インスタンスインスタンスID を調べるためにマネジメントコンソールから確認する必要がありました。
これは非常に面倒なので、この手順をスキップして接続できるように工夫してみます。

本題

前提

手元のマシンMac を想定しています。ただし、Windows/Linux など他のOS でも適宜読み替えれば同じことができるはずです。 また、予め以下のようなツールがインストールされている必要があります。

また、aws ssm start-sessionaws ec2 describe-instances が実行できる権限が付与されたAWS アクセスキーが手元のマシンに登録されている必要があります。
ここでは hoge-profile という名前付きプロファイルとして、アクセスキーが登録されていることとします。

ツールの用意

下記のシェルスクリプトをパスが通っているディレクトリに作成します。ここではスクリプトのファイル名を awssh とします。
gist.github.com

使ってみる

このようにしてAWS のプロファイルを指定しつつコマンドを実行します。

$ awssh --profile hoge-profile

コマンドを実行すると起動中のEC2 インスタンスの一覧が表示されるので、接続したいインスタンスを選択すると、そのインスタンスのコンソールにログインすることができます。

これで接続先のEC2 インスタンスインスタンスID をマネジメントコンソールから確認しなくてもSession Manager を使ってインスタンスのコンソールにログインすることができるようになりました。やったね!

2020年 振り返り

2020年も終わりが近づいてきたので1年の振り返りをする。

今年も去年と同じく、SREというロールで仕事をしていた。 今年の自分のテーマは「ソフトウェア開発スキルの向上」で、とくにかくこれを念頭に置きながら1年過ごした。

2018年の夏に今の部署に異動して、SREというロールで 家族アルバム みてね というスマートフォンアプリのバックエンドの開発や運用をやるようになった。 それまで物理インフラ畑にずっといたからか、最初の1, 2年は特にコーディングの苦手意識がすごくて(苦手意識というか実際にできなかったんだけど…)、重めの開発タスクがあると嫌だなあーと思って避ける事が多かった。
とはいえそのまま避け続けるわけにはいかないし、せっかくなら自分で開発したものをユーザーに使ってほしいのでなんとかしようといろいろやった1年だった。

具体的には次のようなことをやった。

デザインパターンを身につける

トンチンカンな設計をしたままコーディングに進んでしまって、あとあと大きな手戻りが発生する…みたいな経験を何度かしたので、その問題を克服するためにいくつか本を読んだ。

どちらもまずはパラパラと一周読み、実際に業務で設計しながら使えそうなところを後で何度もじっくり読むようにして、辞書的に使っている。
はじめからじっくり読んでもイメージが湧きにくいし、読み終えるまでにダレるし、一度だけじっくり読んだってすぐに忘れるので。

フレームワークに馴染む

業務でRails を使っていることもあり、とにかくRails way に乗って素早く・(Rails のお作法的に)正しく・美しく実装ができるようにしたくて、Rails に慣れ親しむのを意識した。

初めの方はRails チュートリアルをじっくりこなしたり、今年の夏にパーフェクト Ruby on Rails の改訂版が出たのでそれを読み進めたりした。
初めてRails を学んだ対象が、それなりに歴史のある大きなRails プロジェクトだったこともあり「よく分からんけどなんか動いてる」といった知識の穴が結構多く、その穴を埋めるのにはとても良かったと思う。とはいえ、未だにRails 知らない機能多いけど。

gem のコードをたくさん読む

これは特になにか意識付けがあったわけではないし、どちらかというとバグ調査などで必要があったから読むことが大半ではあったものの、面倒くさがらずにちゃんと読んで理解するのは結構自分のためにはいい経験だった。

また、danger-rubocop というgem のバグに遭遇し、該当の箇所を読んでみたところ直せそうな雰囲気を感じたのでPR を送ってみたところなんとマージしてもらうこともできた。(OSS 初コントリビュート!) 内容的には些細なバグ修正ではあるものの、自分のスキルの向上を感じれたのでこの経験はかなり嬉しかったし、自信にも繋がった。 github.com


来年は引き続きソフトウェア開発のスキルは伸ばして行きたいなーと思いつつ、kubernetes を本格的に触り始めたのでその辺りの開発・運用もガッチリやっていきたい。 また、サービスの性質上膨大な量の画像・動画を取り扱うので、メディアの基礎的な知識も更に蓄えていかねばという感じ。

来年も引き続き頑張っていきましょう!

宣伝

自分が所属する「家族アルバム みてね」ではエンジニアを大募集中です! medium.com

WebP を試す

iOS14 でWebP に対応との情報を見かけたのでこれを機にとりあえずエンコードして試してみることにした。

エンコード環境の作成

docker コンテナ内にImageMagick をインストールして、使うことにする。

Dockerfile を作成する。 簡易的なテストのためのものなので、とりあえずapt でインストールしてみた。

FROM ubuntu:20.04

RUN apt-get -y update && \
    apt-get -y install imagemagick && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

続いてdocker image をビルドして、convert コマンドを実行してみる。

# docker image をビルド
$ docker build -t imagemagick .

# 動作確認
$ docker run -it imagemagick convert --version
Version: ImageMagick 6.9.10-23 Q16 x86_64 20190101 https://imagemagick.org
Copyright: © 1999-2019 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC Modules OpenMP
Delegates (built-in): bzlib djvu fftw fontconfig freetype jbig jng jpeg lcms lqr ltdl lzma openexr pangocairo png tiff webp wmf x xml zlib

ここまでで準備は完了。

エンコード

エンコード対象の画像を /path/to/images/1.jpg とする。

特にパラメータを指定せずエンコードしてみる。

$ docker run -v /path/to/images:/images --rm -it imagemagick convert /images/1.jpg /images/1.webp

これでエンコードできた。 画像を並べて比較してみたところ、色味や粗さなど自分の肉眼では判別できないほど違いが分からなかった。

エンコード結果の確認

ファイルサイズはかなり違いがある。 とはいえ、これはパラメータ次第だと思われるので、大した参考にはならなさそう。

$ docker run -v /path/to/images:/images --rm -it imagemagick ls -l /images
total 6184
-rwx------ 1 root root 4101341 Oct 22  2019 1.jpg
-rw-r--r-- 1 root root 1908796 Sep 24 14:43 1.webp

ImageMagick に同梱されているidentify コマンドで画像の詳細をチェックできる。

$ docker run -v /path/to/images:/images --rm -it imagemagick identify -verbose /images/1.jpg
$ docker run -v /path/to/images:/images --rm -it imagemagick identify -verbose /images/1.webp

パラメータに関してはImageMagick と WebP がよくまとまっていた。 こちらの記事で概要を掴んで、Google の仕様書を読み込んでいくと詳細まで把握することができそう。