「AZ-305 Microsoft Azure Infrastructure Solutionsの設計」に合格した

2022年6月25日(土)に「AZ-305 Microsoft Azure Infrastructure Solutionsの設計」を受験し、合格しました。ここではその勉強方法などについて記します。

勉強方法

まずはAZ-305に関連したMicrosoft Learnを一通り目を通します。

docs.microsoft.com

自分の苦手分野としてAzure Key VaultやAzure SQL Database/Managed Instance、Data Factory、Databricksなどが弱点ということが分かったので(弱点多すぎ...)、実際に触ったりドキュメントを読んだりして勘所を掴むようにしました。

また、Udemyの「Exam AZ-305 - Designing Azure Infrastructure Solutions 2022」を購入しサービスの概要を掴むようにしました。

www.udemy.com

英語ということでハードルが上がりますが、英語字幕とAzure Portalでの画面操作を動画で見ることができることから大体のことは理解できました。

試験対策

試験対策としては、上記Udemyの講座についてあった問題とmeasureupの問題集を購入し問題を解きました。

www.measureup.com

問題も解説も英語なので、初見で問題や解説を理解するのは難しかったです。問題を繰り返し解いたり、翻訳サイトを使ったりして理解を深めることにしました。ただ、3回目ぐらいになってくると問題と答えを覚えてしまっていることも多かったです。

試験

もう何回もAzureの試験を受けているのでどのような問題形式が出るか把握していましたが、ねんのため問題の種類を以下のページで把握するようにしました。

docs.microsoft.com

試験時間はたっぷりとあるので、問題をじっくり読んで早とちりしないように気をつけました。なんだかんだで1時間程度かかりました。

試験は難しくこれはダメかなと思っていたのですが、結果は882点で合格することができました。

Linux上でのAzure FunctionsでもAzure Portal上での開発ができるようになっていた

今日は小ネタ。

なんとなくAzureの更新情報を見ていたら、Linux上でのAzure FunctionsでもAzure Portal上での開発がプレビューとして公開されたというものを見かけました。

azure.microsoft.com

これまではWindowsのものだけができていたんですが、Linux上でのAzure Functionsでもできるようになったみたい。Azure Functionsの簡単な動作検証をしたい時にPortal上で作業できるのは便利な面も多いので、ちょっと試してみました。

「関数」にある「作成」をクリックすると、テンプレートの選択が出てくるので、適当なものを選び名前などを入力したらすぐ作成されます。

オレンジ色の背景にて「サードパーティの依存関係の追加は、〜」という記述があります。本格的なものを作る際にはローカル環境をセットアップした方が後々よいかなと思います。

「テストと実行」というものがあるので動かしてみます。

クエリパラメータやヘッダー、ボディもそれぞれ編集できます。「実行」ボタンを押すと結果が「出力」タブに表示されます。

以下のドキュメントによると、2022年6月19日現在において、ポータルでの編集は以下に限られるようです。

docs.microsoft.com

お試しという形で利用すると良いかなと思います。

Service ConnectorをAzure Web Apps + MySQL flexible serverで試す(2)Key Vaultと連携する

はじめに

先週、Service ConnectorがGAになった記念で簡単に試してみた記事を書きました。

miyohide.hatenablog.com

今日はその続きの記事で、「シークレットをKey Vaultに格納する」を試してみました。

ドキュメント

ドキュメントとしては以下があるのですが、実際読んでもあまりピンと来なかったので試してみることにしました。

docs.microsoft.com

実装

環境としては、Azure Web Apps + MySQL flexible server。今回はこれにAzure Key Vaultが加わります。あらかじめAzure Key Vaultを作成しておいて、Azure Web Apps上にAzure Key Vaultに接続するService Connectorを作っておきます。

上記のドキュメントを読みながら画面で項目を選択するだけなので特に迷うところはないかなと思います。

その後、Azure Web Apps上でMySQL flexible serverに接続するService Connectorを作ります。このとき、「シークレットをKey Vaultに格納する」にチェックを入れて先ほど作成したKey Vaultに接続するService Connectorを指定しておきます。

設定としては以上です。

Azure Web Apps上の「構成」には各種環境変数が設定されています。前回のものと違って、azure.keyvault.scopeとazure.keyvault.urlが追加されています。また、値欄を表示させると、spring.datasource.passwordにMySQL flexible serverのパスワードが入っているのではなくAzure Key Vault内の格納先が設定されています。

Azure Key Vaultのシークレットを見ると、MySQL flexible serverのパスワードが入っていることが確認できます。

これだけで動くのかな?と疑心暗鬼でしたが、無事動きました。

Service ConnectorをAzure Web Apps + MySQL flexible serverで試す

先日のBuildでService ConnectorがGAとなったようです。

techcommunity.microsoft.com

ドキュメントをみてもあまりピンとこなかったので、実際に試してみました。

docs.microsoft.com

サンプルアプリ

サンプルアプリとしては、Springが公開しているMySQLを使ったサンプルアプリを使ってみます。

spring.io

MySQLはflexible serverで作成します。今回の本論とは関係ありませんが、Azure Portal上でデータベースを作成できることを知りました。

JavaアプリはAzure Web Appsで動かします。Azure Portal上で「サービス コネクタ」というものがあるので、そこから「Create」ボタンを押します。

試した時点ではご覧のサービスがサポートされているようです。

現れる各項目に対して必要な情報を入れたらOKです。一番最後の「Client type」に「SpringBoot」というものがあったのでそれを選択しておきます。

保存したらデーターベース接続に必要な情報が登録されていました。

環境変数にも登録されていました。

ここらへんの挙動は、以下のドキュメントに記載がありました。

docs.microsoft.com

以上の設定でアプリも無事動きました。Azure Web Appsのログストリームに流れているログをみると、データベースに接続できていることが確認できます。

2022-06-05 08:16:59.160  INFO 167 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-06-05 08:16:59.168  INFO 167 --- [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 7966 ms
2022-06-05 08:17:00.154  INFO 167 --- [main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2022-06-05 08:17:00.481  INFO 167 --- [main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.6.9.Final
2022-06-05 08:17:01.613  INFO 167 --- [main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2022-06-05 08:17:02.168  INFO 167 --- [main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2022-06-05 08:17:03.737  INFO 167 --- [main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2022-06-05 08:17:03.952  INFO 167 --- [main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
2022-06-05 08:17:07.249  INFO 167 --- [main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2022-06-05 08:17:07.399  INFO 167 --- [main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2022-06-05T08:17:11.320Z INFO  - Waiting for response to warmup request for container xxxxxxxxxxxxxx_b9b31849. Elapsed time = 30.6847269 sec
2022-06-05 08:17:08.882  WARN 167 --- [main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2022-06-05 08:17:10.823  INFO 167 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 80 (http) with context path ''
2022-06-05 08:17:10.903  INFO 167 --- [main] .g.m.a.AccessingDataWithMysqlApplication : Started AccessingDataWithMysqlApplication in 23.331 seconds (JVM running for 25.611)
2022-06-05T08:17:12.302Z INFO  - Container xxxxxxxxxxxxxx_b9b31849 for site app-miyohide-mysql initialized successfully and is ready to serve requests.
2022-06-05 08:17:11.627  INFO 167 --- [http-nio-80-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-06-05 08:17:11.657  INFO 167 --- [http-nio-80-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-06-05 08:17:11.664  INFO 167 --- [http-nio-80-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms

アプリも無事データを取得できていることが確認できました。

Cloud Native Buildpacksをちょっとだけ触る

はじめに

Dockerfileを書くことなく、ソースコードからDockerイメージを作ることができると言うCloud Native Buildpacksという存在を知りました。

buildpacks.io

Dockerfileを色々と調べながら書くのはあんまり好きじゃなく、できれば楽できたらなと思ったところに知ったものなので、早速試してみました。

packコマンドのインストール

まず、packコマンドのインストールを行います。やり方は公式サイトにドキュメントがあるので、それを参考に。

buildpacks.io

私が試した時には、0.26.0というバージョンでした。

azureuser@myVM:~$ pack --version
0.26.0
azureuser@myVM:~$

また、Docker環境も整えておきます。

docs.docker.com

Javaのサンプルアプリを動かす

チュートリアルが用意されているので、それに従ってやってみます。

buildpacks.io

サンプルリポジトリをcloneして、packコマンドを実行します。

azureuser@myVM:~/work/samples/apps/java-maven$ pack build myapp --builder cnbs/sample-builder:bionic
bionic: Pulling from cnbs/sample-builder
(省略)
===> ANALYZING
===> DETECTING
[detector] samples/java-maven 0.0.1
===> RESTORING
[restorer] Restoring metadata for "samples/java-maven:jdk" from app image
[restorer] Restoring metadata for "samples/java-maven:maven_m2" from cache
[restorer] Restoring data for "samples/java-maven:jdk" from cache
[restorer] Restoring data for "samples/java-maven:maven_m2" from cache
===> BUILDING
[builder] ---> Java buildpack
[builder] ---> Installing JDK
[builder] ---> Running Maven Wrapper
[builder] [INFO] Scanning for projects...
[builder] [INFO]
[builder] [INFO] --------------------< io.buildpacks.example:sample >--------------------
[builder] [INFO] Building sample 0.0.1-SNAPSHOT
[builder] [INFO] --------------------------------[ jar ]---------------------------------
[builder] [INFO]
(省略)
[builder] [INFO] ------------------------------------------------------------------------
[builder] [INFO] BUILD SUCCESS
[builder] [INFO] ------------------------------------------------------------------------
[builder] [INFO] Total time:  2.827 s
[builder] [INFO] Finished at: 2022-05-29T08:05:21Z
[builder] [INFO] ------------------------------------------------------------------------
===> EXPORTING
[exporter] Reusing layer 'samples/java-maven:jdk'
[exporter] Adding 1/1 app layer(s)
[exporter] Reusing layer 'launcher'
[exporter] Reusing layer 'config'
[exporter] Reusing layer 'process-types'
[exporter] Adding label 'io.buildpacks.lifecycle.metadata'
[exporter] Adding label 'io.buildpacks.build.metadata'
[exporter] Adding label 'io.buildpacks.project.metadata'
[exporter] Setting default process type 'web'
[exporter] Saving myapp...
[exporter] *** Images (d8a7e88bd822):
[exporter]       myapp
[exporter] Reusing cache layer 'samples/java-maven:jdk'
[exporter] Adding cache layer 'samples/java-maven:maven_m2'
Successfully built image myapp
azureuser@myVM:~/work/samples/apps/java-maven$

Mavenによるビルドが実行され、Dockerイメージが作成されました。

azureuser@myVM:~/work/samples/apps/java-maven$ docker images
REPOSITORY               TAG       IMAGE ID       CREATED        SIZE
heroku/pack              20        187818685cd8   8 hours ago    602MB
cnbs/sample-stack-run    bionic    0aa0fb9222a5   5 months ago   70.2MB
hello-world              latest    feb5d9fea6a5   8 months ago   13.3kB
buildpacksio/lifecycle   0.13.1    76412e6be4e1   42 years ago   16.4MB
heroku/buildpacks        20        51904c87109f   42 years ago   1.56GB
cnbs/sample-builder      bionic    83509780fa67   42 years ago   181MB
myapp                    latest    d8a7e88bd822   42 years ago   300MB  ## ← 作られたDockerイメージ
azureuser@myVM:~/work/samples/apps/java-maven$

アプリを動かしてみます。

azureuser@myVM:~/work/samples/apps/java-maven$ docker run --rm -p 8080:8080 myapp
    |'-_ _-'|       ____          _  _      _                      _             _
    |   |   |      |  _ \        (_)| |    | |                    | |           (_)
     '-_|_-'       | |_) | _   _  _ | |  __| | _ __    __ _   ___ | | __ ___     _   ___
|'-_ _-'|'-_ _-'|  |  _ < | | | || || | / _` || '_ \  / _` | / __|| |/ // __|   | | / _ \
|   |   |   |   |  | |_) || |_| || || || (_| || |_) || (_| || (__ |   < \__ \ _ | || (_) |
 '-_|_-' '-_|_-'   |____/  \__,_||_||_| \__,_|| .__/  \__,_| \___||_|\_\|___/(_)|_| \___/
                                              | |
                                              |_|

:: Built with Spring Boot :: 2.1.18.RELEASE

2022-05-29 08:09:28.225  INFO 1 --- [           main] i.b.example.sample.SampleApplication     : Starting SampleApplication v0.0.1-SNAPSHOT on c6e7f160ad2c with PID 1 (/workspace/target/sample-0.0.1-SNAPSHOT.jar started by cnb in /workspace)
2022-05-29 08:09:28.229  INFO 1 --- [           main] i.b.example.sample.SampleApplication     : No active profile set, falling back to default profiles: default
2022-05-29 08:09:29.912  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-05-29 08:09:29.975  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-05-29 08:09:29.976  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.39]
2022-05-29 08:09:30.096  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-05-29 08:09:30.097  INFO 1 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1766 ms
2022-05-29 08:09:30.377  INFO 1 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2022-05-29 08:09:30.463  INFO 1 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2022-05-29 08:09:30.635  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-05-29 08:09:30.639  INFO 1 --- [           main] i.b.example.sample.SampleApplication     : Started SampleApplication in 3.089 seconds (JVM running for 3.708)

ブラウザでアクセスしてみると、以下のような画面が出てきました。

Rubyのサンプルアプリを試す

サンプルリポジトリにはruby-bundlerというSinatraで作られたアプリがあるので、これを試してみます。

Javaの時と同じようにpackコマンドを使ってDockerイメージを作成します。

azureuser@myVM:~/work/samples/apps/ruby-bundler$ pack build myapp-ruby --builder cnbs/sample-builder:bionic
bionic: Pulling from cnbs/sample-builder
Digest: sha256:f9aa933450900df3a91a5f405c4a55ed3bb9decc9ee503b2dd85ff728db75e22
Status: Image is up to date for cnbs/sample-builder:bionic
bionic: Pulling from cnbs/sample-stack-run
Digest: sha256:7b0946aa031f1ddd30bda8963eb33431458a25a576208646348ce89536fef59a
Status: Image is up to date for cnbs/sample-stack-run:bionic
0.13.1: Pulling from buildpacksio/lifecycle
Digest: sha256:f2cb410c8e204e6d2c6d86b1a171862595d8dccefc35197804eff09ab9221219
Status: Image is up to date for buildpacksio/lifecycle:0.13.1
===> ANALYZING
===> DETECTING
[detector] samples/ruby-bundler 0.0.1
===> RESTORING
[restorer] Restoring metadata for "samples/ruby-bundler:bundler" from app image
[restorer] Restoring metadata for "samples/ruby-bundler:ruby" from app image
[restorer] Restoring data for "samples/ruby-bundler:bundler" from cache
===> BUILDING
[builder] ---> Ruby Buildpack
[builder] ---> Downloading and extracting Ruby 2.5.0
[builder] ---> Installing bundler
[builder] Successfully installed bundler-2.3.14
[builder] 1 gem installed
[builder] ---> Reusing gems
[builder] Your RubyGems version (2.7.6.2) has a bug that prevents `required_ruby_version` from working for Bundler. Any scripts that use `gem install bundler` will break as soon as Bundler drops support for your Ruby version. Please upgrade RubyGems to avoid future breakage and silence this warning by running `gem update --system 3.2.3`
[builder] Your RubyGems version (2.7.6.2) has a bug that prevents `required_ruby_version` from working for Bundler. Any scripts that use `gem install bundler` will break as soon as Bundler drops support for your Ruby version. Please upgrade RubyGems to avoid future breakage and silence this warning by running `gem update --system 3.2.3`
===> EXPORTING
[exporter] Reusing layer 'samples/ruby-bundler:bundler'
[exporter] Reusing layer 'samples/ruby-bundler:ruby'
[exporter] Adding 1/1 app layer(s)
[exporter] Reusing layer 'launcher'
[exporter] Reusing layer 'config'
[exporter] Reusing layer 'process-types'
[exporter] Adding label 'io.buildpacks.lifecycle.metadata'
[exporter] Adding label 'io.buildpacks.build.metadata'
[exporter] Adding label 'io.buildpacks.project.metadata'
[exporter] Setting default process type 'web'
[exporter] Saving myapp-ruby...
[exporter] *** Images (360bd2e06828):
[exporter]       myapp-ruby
[exporter] Reusing cache layer 'samples/ruby-bundler:bundler'
Successfully built image myapp-ruby
azureuser@myVM:~/work/samples/apps/ruby-bundler$

docker runコマンドを使って動かします。

azureuser@myVM:~/work/samples/apps/ruby-bundler$ docker run --rm -p 8080:8080 myapp-ruby
Hello from .profile
Your RubyGems version (2.7.6.2) has a bug that prevents `required_ruby_version` from working for Bundler. Any scripts that use `gem install bundler` will break as soon as Bundler drops support for your Ruby version. Please upgrade RubyGems to avoid future breakage and silence this warning by running `gem update --system 3.2.3`
[2022-05-29 08:18:51] INFO  WEBrick 1.4.2
[2022-05-29 08:18:51] INFO  ruby 2.5.0 (2017-12-25) [x86_64-linux]
== Sinatra (v2.0.7) has taken the stage on 8080 for development with backup from WEBrick
[2022-05-29 08:18:51] INFO  WEBrick::HTTPServer#start: pid=1 port=8080

ブラウザでアクセスしてみます。大変簡素な画面ですが、無事動きました。

Rubyサンプルアプリのバージョンアップを行う

サンプルアプリのRubyのバージョンは2.5だったので最新バージョンである3.1.2で動かすことにします。

最初は.ruby-versionを変更すれば良いだけでしょと思っていたのですが、それだけではうまく動きませんでした。

まずはローカルで動かす

まずはローカルで動かしてみます。ruby app.rbを実行すると、以下のようなメッセージが出てうまく動きません。

azureuser@myVM:~/work/samples/apps/ruby-builder3$ ruby app.rb
/home/azureuser/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/rack-2.2.3.1/lib/rack/handler.rb:45:in `pick': Couldn't find handler for: thin, puma, reel, HTTP, webrick. (LoadError)
    from /home/azureuser/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sinatra-2.2.0/lib/sinatra/base.rb:1503:in `run!'
    from /home/azureuser/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sinatra-2.2.0/lib/sinatra/main.rb:45:in `block in <module:Sinatra>'
azureuser@myVM:~/work/samples/apps/ruby-builder3$

これはwebrickが最近のRubyでは標準ではインストールされないために起こる問題です。gem "webrick"をGemfileに追加してbundle installします。また、bundle update --bundlerbundle updateを実行して、大量に出てくるdeprecatedを消しておきます。これでローカルで動かすことができます。

azureuser@myVM:~/work/samples/apps/ruby-builder3$ ruby app.rb
[2022-05-29 08:37:43] INFO  WEBrick 1.7.0
[2022-05-29 08:37:43] INFO  ruby 3.1.2 (2022-04-12) [x86_64-linux]
== Sinatra (v2.2.0) has taken the stage on 8080 for development with backup from WEBrick
[2022-05-29 08:37:43] INFO  WEBrick::HTTPServer#start: pid=34563 port=8080

Dockerイメージを作成する

続いてpackコマンドでDockerイメージを作成してみます。これまでと同じようにイメージ名だけ変えて動かしてみたら以下のメッセージが出てDockerイメージは作られませんでした。

azureuser@myVM:~/work/samples/apps/ruby-builder3$ pack build myapp-ruby3 --builder cnbs/sample-builder:bionic
bionic: Pulling from cnbs/sample-builder
(省略)
Status: Image is up to date for buildpacksio/lifecycle:0.13.1
===> ANALYZING
[analyzer] Previous image with name "myapp-ruby3" not found
===> DETECTING
[detector] samples/ruby-bundler 0.0.1
===> RESTORING
===> BUILDING
[builder] ---> Ruby Buildpack
[builder] ---> Downloading and extracting Ruby 3.1.2
[builder] ---> Installing bundler
[builder] <internal:/layers/samples_ruby-bundler/ruby/lib/ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:85:in `require': libyaml-0.so.2: cannot open shared object file: No such file or directory - /layers/samples_ruby-bundler/ruby/lib/ruby/3.1.0/x86_64-linux/psych.so (LoadError)
(省略)
[builder] ERROR: failed to build: exit status 1
ERROR: failed to build: executing lifecycle. This may be the result of using an untrusted builder: failed with status code: 51
azureuser@myVM:~/work/samples/apps/ruby-builder3$

これを解決するには--builderで指定した値を変えます。どの値を指定していいかわかりませんでしたが、以下のマニュアルにあるようにpack builder suggestコマンドで提示されたものを指定してみます。

buildpacks.io

今回は、heroku/buildpacks:20を指定してみることにします。

azureuser@myVM:~/work/samples/apps/ruby-builder3$ pack build myapp-ruby3 --builder heroku/buildpacks:20
20: Pulling from heroku/buildpacks
(省略)
Status: Image is up to date for heroku/pack:20
===> ANALYZING
Previous image with name "myapp-ruby3" not found
===> DETECTING
1 of 2 buildpacks participating
heroku/ruby 0.1.3
===> RESTORING
===> BUILDING
-----> Installing bundler 2.2.21
-----> Removing BUNDLED WITH version in the Gemfile.lock
-----> Compiling Ruby/Rack
-----> Using Ruby version: ruby-2.7.4
-----> Loading Bundler Cache
-----> Installing dependencies using bundler 2.2.21
       Running: BUNDLE_WITHOUT='development:test' BUNDLE_PATH=/layers/heroku_ruby/gems/vendor/bundle BUNDLE_BIN=vendor/bundle/bin BUNDLE_DEPLOYMENT=1 bundle install -j4
       Fetching gem metadata from https://rubygems.org/
       Fetching gem metadata from https://rubygems.org/....
(省略)
-----> Detecting rake tasks

###### WARNING:

       You have not declared a Ruby version in your Gemfile.

       To declare a Ruby version add this line to your Gemfile:

       ```
       ruby "2.7.4"
       ```

       For more information see:
         https://devcenter.heroku.com/articles/ruby-versions



===> EXPORTING
(省略)
Saving myapp-ruby3...
*** Images (163a27f2364c):
      myapp-ruby3
Adding cache layer 'heroku/ruby:gems'
Successfully built image myapp-ruby3

今度はうまくDockerイメージが作られましたが、Rubyのバージョンが2.7.4になっています。ログの警告にあるようにGemfileRubyのバージョンが書かれていないのが原因のようです。このため、Gemfile内にruby "3.1.2"と書いておきます。bundle updateもして再度pack buildしてみます。

azureuser@myVM:~/work/samples/apps/ruby-builder3$ pack build myapp-ruby3 --builder heroku/buildpacks:20
20: Pulling from heroku/buildpacks
(省略)
===> BUILDING
-----> Installing bundler 2.2.21
-----> Removing BUNDLED WITH version in the Gemfile.lock
-----> Compiling Ruby/Rack
-----> Using Ruby version: ruby-3.1.2
-----> Loading Bundler Cache
-----> Installing dependencies using bundler 2.2.21
       Running: BUNDLE_WITHOUT='development:test' BUNDLE_PATH=/layers/heroku_ruby/gems/vendor/bundle BUNDLE_BIN=vendor/bundle/bin BUNDLE_DEPLOYMENT=1 bundle install -j4
(省略)
Successfully built image myapp-ruby3
azureuser@myVM:~/work/samples/apps/ruby-builder3$

無事イメージが作られました。

あとはdocker runすればいいだけと思っていたのですが、まだ動きません。

azureuser@myVM:~/work/samples/apps/ruby-builder3$ docker run --rm -p 8080:8080 myapp-ruby3
Hello from .profile
configuration /workspace/config.ru not found
azureuser@myVM:~/work/samples/apps/ruby-builder3$

動かすためには、Procfileを作成します。Procfileについては以下を参照。

devcenter.heroku.com

今回は次のような内容にします。

web: ruby app.rb

Procfileを作成後、再度pack buildを実行し、docker runすると無事動かすことができました。

azureuser@myVM:~/work/samples/apps/ruby-builder3$ docker run --rm -p 8080:8080 myapp-ruby3
Hello from .profile
[2022-05-29 08:57:06] INFO  WEBrick 1.7.0
[2022-05-29 08:57:06] INFO  ruby 3.1.2 (2022-04-12) [x86_64-linux]
== Sinatra (v2.2.0) has taken the stage on 8080 for production with backup from WEBrick
[2022-05-29 08:57:06] INFO  WEBrick::HTTPServer#start: pid=1 port=8080

Azure Toolkit for IntelliJを入れてみた

今日は小ネタ。

ふとしたきっかけでIntelliJ向けのAzure操作をするためのプラグインを見つけました。

plugins.jetbrains.com

日本語のドキュメントもマイクロソフトにていくつか提供しているようです。

docs.microsoft.com

ものは試しとインストールしてみました。

プラグインのインストールはIntelliJのドキュメントに書かれている手順に従い実施します。

pleiades.io

検索欄に「Azure」と入れたら出てきたAzure Toolkit for IntelliJをインストールします。

インストールが完了してIntelliJを再起動したら、左端に「Azure Explorer」右端に「Azure Resource Connector」というものができていました。「Azure Explorer」からサインインの作業を実行します。具体的な手順は以下のドキュメントを参考に。

docs.microsoft.com

サインインが完了したら、それぞれ作成しているリソースが表示されました。

既存のリソースだけでなく、新規作成もできるようです。

作成したリソースに対しても色々と操作できるようです。対象を右クリックしたら色々とメニューが現れました。

きちんとするにはCI/CDを整備するべきかと思いますが、簡単な検証ではこういうIDEプラグインを使うと色々と捗りそうです。

Azure App Configurationを試す(4)プッシュ更新による動的な構成を使用する...がうまく動かなかった

はじめに

先日より試してみている機能の一つとして、アプリの設定や機能フラグを一元的に管理するためのサービスとしてAzure App Configurationというものがあります。

docs.microsoft.com

上のドキュメントを読んでもあまり嬉しさがわからないのですが、その嬉しさを理解するためにもSpring Bootアプリで試してみることにしました。今回はプッシュ更新による動的な構成を試してみました...が、結果としてうまく動きませんでした。

これまで試した記事は以下の通り。

サンプル

例によってチュートリアルが用意されているのでそれを参考にします。

docs.microsoft.com

サンプルの記述はあっさりしすぎていたので、いくらか確認しながら実装していきます。

ライブラリの追加

Spring Actuatorを使うようです。build.gradleに以下の記述を追加します。

implementation 'org.springframework.boot:spring-boot-starter-actuator'

com.azure.spring:azure-spring-cloud-appconfiguration-config-webと合わせて使うことで、Spring Actuatorにappconfiguration-refreshというエンドポイントができるようです。

チュートリアルを眺めてみると、Azure App Configurationから値が変更されたらそれをEvent Grid経由でWebHookが起動されるという流れ。ドキュメントにはEvent Grid では、HTTPS Webhook エンドポイントのみがサポートされています。と書かれています。

docs.microsoft.com

このため、ローカルで実行することはやめてAzure Web Appsにてデプロイすることにしました。JavaアプリをAzure Web AppsへのデプロイはAzure Gradle Pluginsを使うと楽です。

github.com

アプリケーションの設定

アプリケーションの設定も行います。Spring Actuatorのappconfiguration-refreshのWebエンドポイントを使えるようにします。bootstrap.propertiesにて

management.endpoints.web.exposure.include=appconfiguration-refresh

と記述します。チュートリアルにあるように二重引用符付きだとうまく動きませんでした。

また、spring.cloud.azure.appconfiguration.stores[0].monitoring.push-notification.primary-token.namespring.cloud.azure.appconfiguration.stores[0].monitoring.push-notification.primary-token.secretのそれぞれの値はWebHooksのパラメータとして使うだけみたいなので、テスト目的だとあまり真面目に考えなくても良さそうです。

あとはAzure Portal上で設定すればできるはずが...

あとはAzure Portal上で設定すればできるはずとたかを括っていたのですが、うまく動かず。

Eventは送信されているようですし...

実際、Application Insightsにてログを確認するとPOST /actuator/appconfiguration-refreshが発行されているのですが、アプリケーションへ変更が反映されず...

"2022/5/15 6:38:09.629","POST /actuator/appconfiguration-refresh",True,200,"15.642","<250ms",request,,,"POST /actuator/appconfiguration-refresh"
"2022/5/15 6:38:15.728","GET /",True,200,"28.683","<250ms",request,,,"GET /"

う〜〜〜ん、もうちょっと見直します。