Azure Container Appsを試してみる(1)

2021年11月にAzure Container Appsというものがパブリックプレビューとして公開されました。パブリックプレビューなので、まだ色々と環境が整っていない感じがするのですが、お試しでやってみました。

Kubernetes上で動作しているようですが、Kubernetesの知識がなくても簡単に扱えるようになっているようです。

techcommunity.microsoft.com

拡張機能のインストール

例によってクイックスタートがありますので、それをやってみます。今回はCLIで。

docs.microsoft.com

試した時点(2022年1月)においては、以下のコマンドで拡張機能をインストールする必要があるようです。

az extension add \
  --source https://workerappscliextension.blob.core.windows.net/azure-cli-extension/containerapp-0.2.0-py2.py3-none-any.whl

Azure CLI拡張機能の各種コマンドなどは以下で説明があります。

docs.microsoft.com

ロケーション

拡張機能をインストールしたら、手順通りに実施していきます。

サンプルではロケーションはCanada Centralになっています。これも試した時点(2022年1月)ではまだ試すことができるリージョンが限られています。ポータルで選択できるのはCanada Central以外にNorth Europeがありますが、ここでは上記クイックスタートで示されたcanadacentralを設定します。

f:id:miyohide:20220116160730p:plain

環境

Azure Container Apps固有の概念で環境というものがあります。詳細な説明は以下のもの。

docs.microsoft.com

あまりピンと来なかったのですが、同じ仮想ネットワークにデプロイされ、同じLog Analyticsにログを書き込むものと認識しておけばよさそうです。

環境を作るにはaz containerapp env createを使えばできるようです。

アプリをデプロイする

ここまでできたらあとはコンテナーイメージをデプロイします。ここではサンプルアプリであるmcr.microsoft.com/azuredocs/containerapps-helloworld:latestをデプロイします。az containerapp createを実行すればOK。

URLとして、名前 + . + ランダムな文字列 + . + リージョン + . + azurecontainerapps.ioというURLが払い出されるのでブラウザでアクセスするとAzure Container Appsのロゴが表示されます。

感想

とりあえず簡単なサンプルを動かしてみました。ここまでだとAzure Container InstanceやAzure Web Appsとの違いがあまり分からないので、もう少し検証を進めてみようと思います。

次回以降

次回以降は以下のことをやってみようかと思います。

  • Azure Container Registryを使った自作コンテナーイメージのデプロイ
  • 環境変数の設定

Azure Container Instances上で動くJavaアプリにApplication InsightsのAgentを入れる

はじめに

Azure Container Instancesには「監視」という項目の下に「メトリック」という項目があります。ただ、ここに移動しても見れる情報は以下のスクリーンショットのようにごくわずかです。

f:id:miyohide:20220109150458p:plain

そこで、Application InsightsのAgentを導入することで、さらに多くの情報を参照するようにしたいと思います。

実装

サポートされている言語としては、2022年1月9日時点でC#JavaJavaScript、Node.js、Pythonが挙げられています。

docs.microsoft.com

そこで今回はSpring Bootで作った簡単なWebアプリにApplication Insightsを導入したいと思います。

全体的な流れは以下のドキュメントに記載があるので基本はそれに従います。

docs.microsoft.com

Java向けのApplication Insightsは以下のGitHubにて開発が進んでいます。

github.com

Releasesページに移動して、3.x系のjarファイル(執筆時点ではapplicationinsights-agent-3.2.4.jar)をダウンロードしてsrc/main/jib/aiディレクトリに格納します。

その後、jibの設定を行います。jibのFAQにjavaagentの設定方法について記述があるので、それに従ってbuild.gradleファイルを編集します。

github.com

今回の例はsrc/main/jib/ai以下にjarファイルを格納したので、以下の記述をbuild.gradleに追加しました。

jib.container.jvmFlags = ['-javaagent:/ai/applicationinsights-agent-3.2.4.jar']

あとは、./gradlew jibDockerBuildでイメージを作成したらOKです。

Azure Container Instances上での設定

Application Insightsにデータを送るために、Azure Container Instancesを設定するとき、環境変数APPLICATIONINSIGHTS_CONNECTION_STRINGにApplication InsightsのConnection String(InstrumentationKeyから始まる文字列)を設定します。

設定は以上で終了です。設定が間違ってなければ、WebアプリにアクセスするとApplication Insightsにデータが溜まります。

Application Insightsを見てみる

Application InsightsのLogsページを見るとrequestsにはアクセスログ、tracesにはアプリケーションのログ、customMetricsにはSpring Actuatorから得られたデータが出力されていました。下のスクリーンショットは、customMetricsのデータを参照したものです。同じnameのものが複数ありますが、customDimensionsごとに違うレコードとして送信されるようです。

f:id:miyohide:20220109153348p:plain

Application InsightsのMetricsには各メトリックをグラフとして表示する機能があるのですが、customDimensionsを考慮しない感じなので、ちょっと使うには注意が必要な気がします。

f:id:miyohide:20220109154814p:plain

なお、メトリック名前空間には色々な種類があるようです。

f:id:miyohide:20220109154901p:plain

この違いがあまり分かっていないのですが、以下の記事が参考になりそうです。

docs.microsoft.com

取れるデータとしてはApplication Insights SDKJava版のドキュメントにざっくりとした説明があります。

docs.microsoft.com

Actuatorのデータはnameのピリオドを_に変更したものに対応しているようです。例えば、Actuatorでactuator/metrics/jvm.memory.used?tag=area:heap&tag=id:Survivor%20Spaceで得られる値とcustomMetricsのテーブルにあるデータのうち、name欄がjvm_memory_usedでcustomDimensionsにSurvivorが含まれているものが一致していました。

f:id:miyohide:20220109155429p:plain

いろいろとデータを深掘りしていきたいなと思いますが、今日はここまで。

Azure Container Instancesで複数コンテナのデプロイを実装

今年もコツコツと学んだことを記していきます。

はじめに

Azure Container Instancesではひとつのコンテナだけでなく複数のコンテナを動かすことができます。チュートリアルも用意されています。

docs.microsoft.com

複数のコンテナを動かすシナリオとしては以下のページに記載されています。

docs.microsoft.com

引用すると、

  • Web アプリケーションにサービスを提供するコンテナーとソース管理から最新のコンテンツをプルするコンテナー。
  • アプリケーション コンテナーとログ記録コンテナー。
  • アプリケーション コンテナーと監視コンテナー。
  • フロントエンド コンテナーとバックエンド コンテナー。

があるようです。

また、今回は試しませんでしたがアプリケーションのTLS接続を有効にするという例もあるようです。

docs.microsoft.com

チュートリアルをそのまま動かしてもあまり理解が進まなかったので、今日は「アプリケーションコンテナーと監視コンテナー」の例を独自のアプリで実装してみることにします。

アプリ/監視コンテナーの実装

アプリケーションコンテナーの実装

アプリケーションコンテナーはSpring Bootで実装しました。監視コンテナーのアクセス先として、Actuatorを追加しました。

docs.spring.io

監視コンテナー

監視コンテナーはwatchコマンドで定期的にアプリケーションコンテナーのMetricsを取得するようにしました。

en.wikipedia.org

コンテナの通信は、

コンテナー グループ内では、コンテナー インスタンスは任意のポートの localhost を通じて相互にアクセスできます。それらのポートがグループの IP アドレスまたはコンテナーで外部に公開されていなくてもかまいません。

とあるので、http://localhost:8080/actuator/metricscurlコマンドでアクセスします。

docs.microsoft.com

処理を行うスクリプトは以下のように実装しました。

#!/bin/bash

watch -n 10 curl http://localhost:8080/actuator/metrics

コンテナ化するためのDockerfileは以下のような感じ。

FROM alpine:3.15.0
RUN apk add --update curl ca-certificates
COPY watchactuator.sh .
RUN chmod +x watchactuator.sh
CMD ["/bin/sh", "watchactuator.sh"]

Azure Container Instancesで動かす

Azure Container Instancesで複数のコンテナを動かしたい場合、ポータル上では設定ができなさそうだったのでTerraformで実装してみることにします。単純にcontainerを必要な数だけ並べる形になります。

resource "azurerm_container_group" "aci" {
  location            = data.azurerm_resource_group.rg.location
  name                = var.aci_name
  os_type             = "linux"
  resource_group_name = data.azurerm_resource_group.rg.name
  ip_address_type = "Public"
  dns_name_label = var.aci_dns_name_label

  image_registry_credential {
    password = data.azurerm_container_registry.acr.admin_password
    server   = data.azurerm_container_registry.acr.login_server
    username = data.azurerm_container_registry.acr.admin_username
  }

  container {
    cpu    = 0.5
    image  = "${data.azurerm_container_registry.acr.login_server}/aci_java_app:latest"
    memory = 1.0
    name   = "aci-java-app"
    ports {
      port = 8080
      protocol = "TCP"
    }
  }

  container {
    cpu = "0.5"
    image  = "${data.azurerm_container_registry.acr.login_server}/sidecar:latest"
    memory = 1.0
    name   = "sidecar"
  }
}

動かしてみる

実際に動かしてみます。

デプロイ後、Azure Container Instancesをみると、二つのコンテナが動いていることが確認できました。

f:id:miyohide:20220102173127p:plain

監視コンテナーとして見立てたものからのログを見ると、データが取れていることが確認できました。

f:id:miyohide:20220102174108p:plain

『Azure定番システム設計・実装・運用ガイド 改訂新版』が発売されていた

今週は軽めのネタで。

『Azure定番システム設計・実装・運用ガイド 改訂新版』という本が先日発売されました。

2018年に発行された『Azure定番システム設計・実装・運用ガイド』の改訂版という位置付けです。

最近、Azure関係のシステム構築が多く、時折各サービスを使ってみてはいますが体型的にシステム構築に必要なものを得るために購入してみました。

目次は以下の通り。

  • 第1章 Azureの基本と特徴
  • 第2章 リフト&シフトによる既存環境の移行
  • 第3章 データベースサービスを使う
  • 第4章 App Serviceを使う
  • 第5章 負荷分散と地理冗長
  • 第6章 イントラネットをAzureに延伸する
  • 第7章 Azureサポートチームからのベストプラクティスの紹介

ざっと目を通したところ、第2章から5章までは既存環境をAzureで構築することを順を追って構築する構成、第6章はオンプレミス環境とAzure環境を結ぶシナリオで、ドメインコントローラーの構築なども含まれていました。

実際にAzure環境を使って構築することができる構成になっているのと同時に、各設定項目の解説や注意点などが丁寧に書かれていたので、色々な読み方ができる本だと感じました。

ただ、Azure環境をつかて構築できるのはいいのですが、大体の料金が書かれていないのでそこが書かれるとなお良かったのかなと思います。

読み応えがある一冊になっているのでゆっくりと読んでいこうかと思います。

Azure Cache for RedisのベストプラクティスをSpring Bootで検証する(3)

はじめに

先日からAzure Cache for Redisのベストプラクティスを検証しています。

Azure Cache for Redisのドキュメントを見ていると、「接続の回復力に関するベストプラクティス」というドキュメントを見つけました。

docs.microsoft.com

以前、Spring BootアプリからAzure Cache for Redisへの接続をするためのブログ記事を載せたのですが、それをもう少し発展させてより有益な情報としていきたいと思います。

miyohide.hatenablog.com

これまでのエントリーは以下のものです。

前回の疑問解決

spring.redis.connect-timeoutの単位は何か?

前回中途半端になっていたものを解決していきます。spring.redis.connect-timeoutの単位です。

Spring Boot 2.6.1の場合、spring.redis.connect-timeoutの設定をしているのが以下のところです。

github.com

Spring Bootの機能でプロパティとして設定しているDurationのデフォルト単位はミリ秒です。

docs.spring.io

このため、spring.redis.connect-timeoutの単位はミリ秒です。

spring.redis.timeoutの単位は何か?

同様にspring.redis.timeoutの単位を調べます。

Spring Boot 2.6.1の場合、spring.redis.timeoutの設定をしているのが以下のところです。

github.com

先程のspring.redis.connect-timeoutと同様にSpring Bootの機能でプロパティとして設定しているDurationのデフォルト単位はミリ秒なので、spring.redis.connect-timeoutの単位はミリ秒です。

具体的な設定値

以上を踏まえて、Azure Cache for Redisのドキュメントにある設定値を指定してみます。下記ドキュメントには、接続タイムアウトは5秒、コマンドタイムアウトは5秒未満が推奨だそうです。

docs.microsoft.com

application.propertiesには以下の設定をすれば良さそうです。

# connect-timeoutはRedisの接続タイムアウト時間
spring.redis.connect-timeout=5000
# timeoutはRedisの各コマンドのタイムアウト時間
spring.redis.timeout=4500

あまり進捗がありませんが、今日はここまで。

Apache Log4j2脆弱性CVE-2021-44228 に関する各種情報の私的まとめ

Apache Log4j脆弱性CVE-2021-44228に関する各種情報の私的まとめです。あくまで私的なまとめで、すべてを網羅しているわけではないです。順不同。

JPCERT

概要や回避策などが日本語で書かれている。

www.jpcert.or.jp

Springからの見解

デフォルトのロギングを明示的にLog4J2に変えていない限り問題ないという見解っぽい。

spring.io

Dockerイメージのチェック

www.docker.com

Oracle製品の影響

www.oracle.com

RedHat製品の影響

access.redhat.com

AWSサービスの影響

aws.amazon.com

Microsoft 365関係での影響

www.microsoft.com

Azureサービスの影響

msrc-blog.microsoft.com

Log4J2を使用しているかどうか やりかた1

irof.hateblo.jp

Log4J2を使用しているかどうか やりかた2

JVM-verbose:classという起動オプションをつけて確認する方法。

yusuke.blog

バージョンアップの方法

irof.hateblo.jp

AWS WAFのマネージドルールに追加されたLog4JRCEの検証

dev.classmethod.jp

Spring Bootアプリケーションの検証

dev.classmethod.jp

Azure Cache for RedisのベストプラクティスをSpring Bootで検証する(2)

はじめに

先日からAzure Cache for Redisのベストプラクティスを検証しています。

Azure Cache for Redisのドキュメントを見ていると、「接続の回復力に関するベストプラクティス」というドキュメントを見つけました。

docs.microsoft.com

以前、Spring BootアプリからAzure Cache for Redisへの接続をするためのブログ記事を載せたのですが、それをもう少し発展させてより有益な情報としていきたいと思います。

miyohide.hatenablog.com

これまでのエントリーは以下のものです。

訂正

さっそくの訂正です。前回のエントリーでは、Azure Cache for Redisに接続する時に以下のようなコードを書く必要があると書きました。

package com.example.demo;

// import文は省略

@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
  @Value("${spring.redis.host}")
  private String redis_host;
  @Value("${spring.redis.password}")
  private String redis_pass;
  @Value("${spring.redis.port}")
  private String redis_port;
  @Bean
  public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
      return new GenericJackson2JsonRedisSerializer();
  }
  @Bean
  public static ConfigureRedisAction configureRedisAction() {
      return ConfigureRedisAction.NO_OP;
  }

  @Bean
  public LettuceConnectionFactory connectionFactory() {
      RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
      redisStandaloneConfiguration.setHostName(this.redis_host);
      redisStandaloneConfiguration.setPassword(this.redis_pass);
      redisStandaloneConfiguration.setPort(Integer.parseInt(this.redis_port));
      LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder().useSsl().build();
      return new LettuceConnectionFactory(redisStandaloneConfiguration, lettuceClientConfiguration);
  }
}

このうち、connectionFactoryは必要なく、application.propertiesspring.redis.ssl=trueを書けば良かったです。ということで、SessonConfigクラスは以下のような実装になります。

package com.example.demo;

// import文は省略

@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
  @Bean
  public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
      return new GenericJackson2JsonRedisSerializer();
  }
  @Bean
  public static ConfigureRedisAction configureRedisAction() {
      return ConfigureRedisAction.NO_OP;
  }
}

Linux でホストされるクライアント アプリケーションのための TCP の設定

さて、次に書かれているのが「Linux でホストされるクライアント アプリケーションのための TCP の設定」というものですが、正直どのように実装すれば良いかわかりませんでした。

lettuceの6.1からIntroduce extended Keep-Alive options · Issue #1437 · lettuce-io/lettuce-core · GitHubでそんなに細かく実装しなくても良いのでは?と思っているのですが、Spring Data RedisやSpring Sessionとの組み合わせ方があまりピンときてなくて、とりあえず保留。

適切なタイムアウトを構成する

次は「適切なタイムアウトを構成する」です。ドキュメントにあるようにConnect timeoutとコマンドタイムアウトの二種類の設定をするのが良さそうです。Spring Bootには、以下のプロパティ一覧を見るとそれぞれspring.redis.connect-timeoutspring.redis.timeoutに該当するようです。

docs.spring.io

デフォルト値が書いてなく、単位もよくわからない...

Lettuce 6.1.5.RELEASEのAPIドキュメントを見るとDEFAULT_CONNECT_TIMEOUT10LDEFAULT_TIMEOUT60Lみたい。

Constant Field Values (Lettuce 6.1.5.RELEASE API)

Spring BootのAutoconfigureのテストでも正しそうです。

github.com

ただ、単位があまりよくわからず。秒なのかミリ秒なのか...

だいぶ中途半端な感じですが、今日はここまでということで。