Azure App ServiceのRubyサポートが2023年4月12日に終わるらしい

ちょっと残念なニュース。

Azure App ServiceのRubyサポートが2023年4月12日に終了となるようです。

azure.microsoft.com

現状でもサポートしているRubyは2.7しかなかったり、

Ruby SDKがメンテ終了となったりと

github.com

嫌な予感はしていたのですが...

移行としてはコンテナ化して動かすことを推奨しているようです。

github.com

う〜ん、残念です。

Azure Container AppsのVNet統合を試す(その2)

以前、Azure Container AppsのVNet統合を試してみたのですが、うまく動きませんでした。

miyohide.hatenablog.com

ある程度時間も経っているのでリベンジしてみることにしました。

公式ドキュメント

公式ドキュメントにやり方が書かれているのでContainer Appsの作成はその通りにします。

learn.microsoft.com

これで作成した時点では、インターネットから接続できないのはもちろんのこと、同じVNet上にある仮想マシンからでも接続できないでいます。

これを解決するには、「その他の技術情報」に書かれている「内部サービスの DNS 名前解決を設定するには、専用の DNS サーバーを設定する必要があります。」を実施します。

リンク先がAzure DNSのリンク先であるのが若干不親切ですが、プライベートDNSを作成すれば良いです。

具体的な手順は以下のブログを参考にしました。

kogelog.com

各種設定値は、Container Apps環境のJSONビューを参照しました。

接続

これで接続してみると...あっさりと接続できました。

少しわかりにくいですが、左側に赤丸・黄色丸・緑色丸があるのがローカルのMacから接続したものです。こちらは接続できていません。 一方で、角張ったWindowのものは仮想マシン上のEdgeからアクセスしたもので、これは接続できています。

TerraformでYYYYMMDD_hhmmss形式の文字列をファイル名に追記する

今日は小ネタ。

Terraformでいわゆるタイムスタンプを「YYYYMMDD_hhmmss」形式で出力して、ファイルなどに出力することをやってみました。

Terraformはクラウド上にリソースを作成するという機能が注目されていますが、ローカルファイルを作成することもできます。

registry.terraform.io

タイムスタンプを取得するにはtimestamp()を呼び出します。

www.terraform.io

ここで得られた値をいわゆる「YYYYMMDD_hhmmss」形式で出力するにはformatdate()を呼び出せばよさそうです。

www.terraform.io

これを使って以下のようなものを作りました。

locals {
    ts = formatdate("YYYYMMDD_hhmmss", timestamp())
}

resource "local_file" "helloworld" {
    #content = "hello world! at ${formatdate("YYYYMMDD_hhmmss", timestamp())}"
    content = "hello world! at ${local.ts}\n"
    filename = pathexpand("~/hello_${local.ts}.txt")
}

あとはいつも通り、terraform initして、terraform planterraform applyをするとホームディレクトリ以下にhello_+YYYYMMDD_hhmmss.txtというファイルが作成できます。

azureuser@myVM:~/work/tf$ ls -l ~/
total 8
-rwxrwxr-x 1 azureuser azureuser   32 Sep 18 06:52 hello_20220918_065255.txt
drwxrwxr-x 4 azureuser azureuser 4096 Sep 18 05:41 work
azureuser@myVM:~/work/tf$ cat ~/hello_20220918_065255.txt
hello world! at 20220918_065255
azureuser@myVM:~/work/tf$

時刻はUTCなのが注意点ですね。

Azure Container InstanceでAzure Database for PostgreSQL flexible serverに対してpg_dumpを実行してみる(2)

先日試しに動かしてみたAzure Container Instanceでpg_dumpを実行してみることの続きをやってみました。

miyohide.hatenablog.com

Terraform

環境構築を逐一手で行うのが面倒くさかったので、Terraformで構築することにします。

PostgreSQLはこんな感じで用意します。

resource "azurerm_postgresql_flexible_server" "main" {
  name                   = "pg-${var.prefix}-${random_string.name.result}"
  resource_group_name    = azurerm_resource_group.main.name
  location               = azurerm_resource_group.main.location
  version                = "13"
  administrator_login    = var.postgresql_admin
  administrator_password = var.postgresql_password
  storage_mb             = 32768
  sku_name               = "B_Standard_B1ms"
}

resource "azurerm_postgresql_flexible_server_database" "main" {
  name      = var.postgresql_database
  server_id = azurerm_postgresql_flexible_server.main.id
}

resource "azurerm_postgresql_flexible_server_firewall_rule" "main" {
  name                = "allowazure1"
  server_id           = azurerm_postgresql_flexible_server.main.id
  start_ip_address    = "0.0.0.0"
  end_ip_address      = "0.0.0.0"  
}

本当は「Azure内の任意のAzureサービスにこのサーバーへのパブリックアクセスを許可する」を設定する必要があるのですが、どうもTerraformでの設定はうまく動きませんでしたので手で設定することにしました。 単純にazurerm_postgresql_flexible_server_firewall_ruleazurerm_postgresql_firewall_ruleに間違えただけでした...

バックアップファイルをFileShareに格納するためにStorageアカウントを作ります。

resource "azurerm_storage_account" "main" {
  name                     = "st${var.prefix}${random_string.name.result}"
  resource_group_name      = azurerm_resource_group.main.name
  location                 = azurerm_resource_group.main.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_storage_share" "main" {
  name                 = var.fileshare_name
  storage_account_name = azurerm_storage_account.main.name
  quota                = 5
}

あとはAzure Container Instanceを作成するようにします。

data "terraform_remote_state" "backend" {
  backend = "local"

  config = {
    path = "../99_tfstate/terraform.tfstate"
  }
}

data "azurerm_resource_group" "main" {
  name = data.terraform_remote_state.backend.outputs.resource_group_name
}

data "azurerm_postgresql_flexible_server" "main" {
  name                = data.terraform_remote_state.backend.outputs.postgres_server_name
  resource_group_name = data.azurerm_resource_group.main.name
}

data "azurerm_storage_account" "main" {
  name                = data.terraform_remote_state.backend.outputs.storage_account_name
  resource_group_name = data.azurerm_resource_group.main.name
}

resource "azurerm_container_group" "main" {
  name                = "aci-${var.prefix}-name"
  location            = data.azurerm_resource_group.main.location
  resource_group_name = data.azurerm_resource_group.main.name
  ip_address_type     = "None"
  os_type             = "Linux"
  restart_policy      = "Never"

  container {
    name     = "postgres"
    image    = "postgres:13"
    cpu      = "0.5"
    memory   = "1.0"
    commands = ["pg_dump", "-f", "/aci/backups/pgdump.bin"]
    secure_environment_variables = {
      PGHOST     = data.azurerm_postgresql_flexible_server.main.fqdn
      PGDATABASE = var.postgresql_database
      PGUSER     = data.azurerm_postgresql_flexible_server.main.administrator_login
      PGPASSWORD = data.terraform_remote_state.backend.outputs.postgres_password
    }

    volume {
      name       = "backups"
      mount_path = "/aci/backups"
      read_only  = false
      share_name = var.fileshare_name

      storage_account_name = data.azurerm_storage_account.main.name
      storage_account_key  = data.azurerm_storage_account.main.primary_access_key
    }
  }
}

Terraformのremote_stateってものを使うと、Outputで出力したものを読み込んで使えるようです。今回はランダムに設定したPostgreSQLのデータベース名とかパスワードなどをremote_stateの機能を使って取得するようにしました。

www.terraform.io

Azure Container InstanceはFile Shareをマウントすることができます。今回はpg_dumpコマンドで出力した結果をFile Shareに出力するようにします。コマンドオプションを見ると、-fオプションを指定するとよさそうなので、設定します。

www.postgresql.jp

commandsの部分を["pg_dump", "-f", "/aci/backups/pgdump.bin"]としておくとよさそうです。

実行

Terraformで実行してみると、きちんと動いてくれました。

File Shareにバックアップも格納されていました。

Terraformの全体像

以下に格納しました。

github.com

Terraformでランダムな文字列を生成したい

今日は小ネタ。

Terraformで何かのリソースを作ろうとしたとき、ランダムな文字列を生成したいということがよくあります。例えばAzureのストレージアカウント名はグローバルで一意である必要があるのですが、それを生成するのはちょっと面倒くさいです。

docs.microsoft.com

何かいい方法ないかなと思ったら、random providerのrandom_stringリソースを見つけました。

registry.terraform.io

使い方は上記のページを参照すれば概ね理解できるかなと思います。

lengthで文字数を設定し、大文字・小文字・記号などを使うか使わないかを設定します。こんな感じで記述します(4文字で小文字を使う設定。デフォルトで数字(numeric)も使う)。

resource "random_string" "name" {
  length  = 4
  upper   = false
  lower   = true
  special = false
}

生成された値は、random_string.name.resultで得られます。

同様にランダムなパスワードを生成するrandom_passwordやランダムな数値を取得するrandom_integerなどがあるようです。

registry.terraform.io random_passwordのマニュアル

registry.terraform.io random_integerのマニュアル

Azure Container InstanceでAzure Database for PostgreSQL flexible serverに対してpg_dumpを実行してみる

はじめに

Azure Database for PostgreSQL flexible serverを使っているとき、用意されているバックアップ機能は最大35日しか取れず、あとは手動で実行しなければなりません。

docs.microsoft.com

バックアップのために仮想マシンを立てるのもなあ...と思い、Azure Container InstanceでPostgreSQLのバックアップコマンドであるpg_dumpが実行できないか試してみました。なお、この内容は不完全版です。

pg_dumpコマンド

PostgreSQLのバックアップを取るpg_dumpコマンドをドキュメントで確認します。

www.postgresql.jp

-hオプションでホスト名、-Uでユーザー名、-dでデータベース名、-fで出力ファイル名を指定できます。実際には以下のようなコマンドになるでしょう。

$ pg_dump -h xxxxxxxxxx.postgres.database.azure.com -U ユーザー名 -d データベース名 -f /home/azureuser/pg_dump001
Password:
$

パスワードを入力しなければいけないので、バッチ的な使い方をするには一工夫必要です。色々と調べると、環境変数PGPASSWORDに値を設定すれば良いようです。

www.postgresql.jp

ただし、この環境変数はセキュリティ上非推奨のようです。が、今回はこの環境変数を使ってみることにします。

Dockerイメージ

DockerイメージはDocker Official Imageのpostgresを使い、コマンドでpg_dumpを実行してみます。

hub.docker.com

実行

Azure Container Instanceで各種環境変数値を設定して実行します。環境変数の設定は「安全としてマーク」に「はい」を設定しておくと良いかと思います。

あとはAzure Container Instanceで設定して実行します。細かい設定は以下の感じで。

今回は確認のためファイルに出力はせず標準出力に出してみることにします。

無事実行することができているようです。

あとはこれをファイル出力したいのですがPortalでお気軽に設定できなかったので、次週にということで。

Apple Silicon(M2 MacBook Air)でAzure Functions Core Tools+Java言語でうまく動かなかった(未解決)

はじめに

先日、M2 MacBook Airを買い、色々とセットアップしました。 Apple Sillicon搭載マシンがでたのが2020年11月で、1年半以上経っていることもあって多くのツールはApple Silliconに対応していましたが、Azure Functionsのローカル実行用として使われるAzure Functions Core ToolsJavaではまだ未対応ということではまったので、ここでその内容を記します。

サンプル

Durable Functionsの動作検証のため、Quick Startにあるコードを実行しようとしました。すると、以下のエラーメッセージが出て起動できませんでした。

Azure Functions Core Tools
Core Tools Version:       4.0.4736 Commit hash: N/A  (64-bit)
Function Runtime Version: 4.8.1.18957

[2022-08-21T05:41:47.806Z] A host error has occurred during startup operation 'e87c7af2-7243-4df8-b9cd-142cac9bc1fb'.
[2022-08-21T05:41:47.806Z] Grpc.Core: Error loading native library. Not found in any of the possible locations: /Users/miyohide/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle.Preview/4.2.1/bin/libgrpc_csharp_ext.arm64.dylib,/Users/miyohide/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle.Preview/4.2.1/bin/runtimes/osx-arm64/native/libgrpc_csharp_ext.arm64.dylib,/Users/miyohide/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle.Preview/4.2.1/bin/../../runtimes/osx-arm64/native/libgrpc_csharp_ext.arm64.dylib.
Value cannot be null. (Parameter 'provider')

> Task :azureFunctionsRun FAILED

Issue

色々と検索してみると、以下のIssueを見つけました。

github.com

このIssueに書かれているものによると、Javaに関しては以下の記述がありました。

Java: blocked because the Java worker only supports Java 8 & 11 and AFAIK Java itself doesn't support Apple Silicon until at least Java 17

JavaApple Siliconサポートは少なくともJava 17以降ということなので、Java版の直近の対応はちょっと難しそうですね...

やるとすれば、Azure上にWindows/Linux仮想マシンを立てて開発するか、言語を変えるかかと。