どのように最初のポートは、オープンソースの電源を活用して連続コードの品質を駆動する



導入


あなたの多くが既に知っているように、私はテクノロジーのトップですFirstPort .
私の役割の重要な部分は、FirstPortの「人々最初の」技術のビジョンを届けることです.そのためには、顧客の生活をより楽にするサービスの配信を支えるための正しい技術を選択することが不可欠です.
今日は私の選択について話したいですSonarQube (そして、GitHubアクション、Terraform , Caddyなどの他のクールなツール&サービスのホストは、暗号化したり、Docker & moreとしましょう)
Sonarqubeは継続的にコードの品質とコードベースのセキュリティを検査するための主要なツールであり、コードレビュー中に開発チームの指導

コンテナイメージの作成


私は使いたくなかったSonarCloud 私はVMでこれをホストしたくなかった.それで、私はACI(Azure Containerインスタンス)を決めました
しかし、ACIを外部データベースで使おうとすると、7.7以降のsonarqubeのバージョンがエラーとなります.
ERROR: [1] bootstrap checks failed
[1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
私は、sonarqubeが埋め込まれたものを使うので、これがわかったElasticsearch , したがって、あなたのDockerホスト構成がElasticsearch production mode requirements
上記の要件として、これを修正するためには、ホストOSの設定を変更することでMAXHUNE MAPHERSEカウントを増加させることを意味します.Linux OSでは/etc/sysctlを変更します.confファイルを更新します.
vm.max_map_count=262144
ACIの問題はホストへのアクセスがないということです、それで、これが変わることができないならば、どのように、最新のsonarqube(書き込みのときの最新版は9.0.1)をACIで走らせることができますか.
このブログでは、AzureコンテナインスタンスでSonarqubeを外部のAzure SQLデータベースで実行する方法を詳細に説明します.
ここでFirstportでは、我々も使用するTerraform AzureインフラストラクチャともちろんGithubアクションをビルドします.

次の手順


最初のものはMaxMount MapCountカウント問題に対処することです.以下の設定を含むプロパティーファイル
sonar.search.javaAdditionalOpts=-Dnode.store.allow_mmap=false
この設定では、ホストのVMを変更することができないコンテナ内のsonarqubeを実行するときに必要となる、弾性的な検索でメモリマッピングを無効にする機能を提供します.MAXHUNE MAPHERSEカウント(参照)Elasticsearch documentation )
現在、我々は我々のソナーを持ちます.設定ファイルに追加できるようにカスタムコンテナを作成する必要があります.小さなdockerfileはこれを実現できます:
FROM sonarqube:9.0.1-community
COPY sonar.properties /opt/sonarqube/conf/sonar.properties
RUN chown sonarqube:sonarqube /opt/sonarqube/conf/sonar.properties
このDockerFileはすぐにDockerを使用して構築され、ACR(Azureコンテナレジストリ)にプッシュされます.
コンテナをビルドする方法および/またはACRにプッシュする方法の詳細についてはDocker and Microsoft ドキュメントに従って簡単にドキュメント.
まず最初に、terraformを使ってacrをビルドします.
resource "azurerm_container_registry" "acr" {
  name                = join("", [var.product, "acr", var.location, var.environment])
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  admin_enabled       = true
  sku                 = "Standard"

  tags = local.tags
}
次に、標準のワークフローを使用してテララを実行する
次に、我々のコンテナイメージを上記のACRセットアップに建設して、押してください.注意cd container ライン.これはdockerfileとsonarがあるからです.Containerというフォルダのプロパティファイル( SOARフォルダには、他のインフラストラクチャ用のすべての地形ファイルが含まれています)

name: Build Container Image & Push to ACR
on:
  workflow_dispatch:

jobs:
  build:
    name: Build Container & Push to ACR
    runs-on: ubuntu-latest

    steps:

      - name: Checkout
        uses: actions/checkout@master

      - name: ACR build
        uses: azure/docker-login@v1
        with:
          login-server: acrname.azurecr.io
          username: acrusername
          password: ${{ secrets.REGISTRY_PASSWORD }}

      - run: |
          cd container && docker build . -t acrname.azurecr.io/acrrepo:${{ github.sha }}
          docker push acrname.azurecr.io/acrrepo:${{ github.sha }}

Sonarqubeインフラストラクチャの構築


それで、現在我々はコンテナイメージがACRにアップロードされた容器を持っています.
作成する部分はいくつかあります.
  • ファイル共有
  • 外部データベース
  • コンテナグループ
  • ソナーカル
  • 逆プロキシ
  • FirstPortではIAC(インフラストラクチャとしてのインフラストラクチャ)を使用することになりますので、TerraFormを使用してsonarqubeインフラストラクチャを設定する方法を示します.

    ファイル共有


    ソナチケdocumentation データ、エクステンション、ログのボリュームマウントを設定します.このため、私はazureストレージアカウントとシェアを使用します.
    resource "azurerm_storage_account" "storage" {
      name                     = join("", [var.product, "strg", var.location, var.environment])
      location                 = azurerm_resource_group.rg.location
      resource_group_name      = azurerm_resource_group.rg.name
      account_tier             = "Standard"
      account_replication_type = "RAGZRS"
      min_tls_version          = "TLS1_2"
      tags                     = local.tags
    }
    
    resource "azurerm_storage_share" "data-share" {
      name                 = "data"
      storage_account_name = azurerm_storage_account.storage.name
      quota                = 50
    }
    
    resource "azurerm_storage_share" "extensions-share" {
      name                 = "extensions"
      storage_account_name = azurerm_storage_account.storage.name
      quota                = 50
    }
    
    resource "azurerm_storage_share" "logs-share" {
      name                 = "logs"
      storage_account_name = azurerm_storage_account.storage.name
      quota                = 50
    }
    

    外部データベース


    外部データベースのために、私はAzure SQL Server、SQLデータベースを使用していて、Azureサービスがデータベースにアクセスするのを許すためにファイアウォール規則を設定します.
    無作為のパスワードリソースを使用して、SQLのパスワードは、秘密が含まれて作成する必要はありませんが、パスワードを知っている必要はありませんsonarqubeサーバーはありません.
    resource "azurerm_mssql_server" "sql_server" {
      name                         = join("", [var.product, "sql", var.location, var.environment])
      location                     = azurerm_resource_group.rg.location
      resource_group_name          = azurerm_resource_group.rg.name
      version                      = "12.0"
      administrator_login          = "sonaradmin"
      administrator_login_password = random_password.sql_admin_password.result
      minimum_tls_version          = "1.2"
    
      identity {
        type = "SystemAssigned"
      }
    
      tags = local.tags
    }
    
    resource "azurerm_mssql_server_transparent_data_encryption" "sql_tde" {
      server_id = azurerm_mssql_server.sql_server.id
    }
    
    resource "azurerm_sql_firewall_rule" "sql_firewall_azure" {
    
      name                = "AllowAccessToAzure"
      resource_group_name = azurerm_resource_group.rg.name
      server_name         = azurerm_mssql_server.sql_server.name
      start_ip_address    = "0.0.0.0"
      end_ip_address      = "0.0.0.0"
    }
    
    resource "azurerm_mssql_database" "sonar" {
      name      = "sonar"
      server_id = azurerm_mssql_server.sql_server.id
      collation = "SQL_Latin1_General_CP1_CS_AS"
      sku_name  = "S2"
    
      tags = local.tags
    }
    
    resource "random_password" "sql_admin_password" {
      length           = 32
      special          = true
      override_special = "/@\" "
    }
    

    コンテナグループ


    コンテナグループを設定するには、カスタムのSonarqubeコンテナを実行するために、資格情報をAzureコンテナレジストリにアクセスする必要があります.データリソースを使用すると、変数として渡すことなく詳細を検索できます.
    data "azurerm_container_registry" "registry" {
      name                = "acrname"
      resource_group_name = "acr-rg-name"
    }
    
    このセットアップのために、我々は2つの容器―カスタムSonarqube容器とキャディー容器を持つつもりです.Caddy リバースプロキシとして使用することができます小型軽量、証明書の管理を自動的に提供してLet’s Encrypt .
    Sonarqubeコンテナ構成は、SQLデータベースとAzureストレージアカウントの共有を以前に設定します.
    キャディコンテナー構成は、Sonarqubeインスタンスに逆プロキシを設定します.
    resource "azurerm_container_group" "container" {
      name                = "containergroupname"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      ip_address_type     = "public"
      dns_name_label      = "acrdnslabel"
      os_type             = "Linux"
      restart_policy      = "OnFailure"
      tags                = local.tags
    
      image_registry_credential {
        server   = data.azurerm_container_registry.registry.login_server
        username = data.azurerm_container_registry.registry.admin_username
        password = data.azurerm_container_registry.registry.admin_password
      }
    
      container {
        name   = "sonarqube-server"
        image  = "${data.azurerm_container_registry.registry.login_server}/acrrepo:latest"
        cpu    = "2"
        memory = "4"
        environment_variables = {
          WEBSITES_CONTAINER_START_TIME_LIMIT = 400
        }
        secure_environment_variables = {
          SONARQUBE_JDBC_URL      = "jdbc:sqlserver://${azurerm_mssql_server.sql_server.name}.database.windows.net:1433;database=${azurerm_mssql_database.sonar.name};user=${azurerm_mssql_server.sql_server.administrator_login}@${azurerm_mssql_server.sql_server.name};password=${azurerm_mssql_server.sql_server.administrator_login_password};encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;"
          SONARQUBE_JDBC_USERNAME = azurerm_mssql_server.sql_server.administrator_login
          SONARQUBE_JDBC_PASSWORD = random_password.sql_admin_password.result
        }
    
        ports {
          port     = 9000
          protocol = "TCP"
        }
    
        volume {
          name                 = "data"
          mount_path           = "/opt/sonarqube/data"
          share_name           = "data"
          storage_account_name = azurerm_storage_account.storage.name
          storage_account_key  = azurerm_storage_account.storage.primary_access_key
        }
    
        volume {
          name                 = "extensions"
          mount_path           = "/opt/sonarqube/extensions"
          share_name           = "extensions"
          storage_account_name = azurerm_storage_account.storage.name
          storage_account_key  = azurerm_storage_account.storage.primary_access_key
        }
    
        volume {
          name                 = "logs"
          mount_path           = "/opt/sonarqube/logs"
          share_name           = "logs"
          storage_account_name = azurerm_storage_account.storage.name
          storage_account_key  = azurerm_storage_account.storage.primary_access_key
        }
      }
    
      container {
        name     = "caddy-ssl-server"
        image    = "caddy:latest"
        cpu      = "1"
        memory   = "1"
        commands = ["caddy", "reverse-proxy", "--from", "acrrepo.azurecontainer.io", "--to", "localhost:9000"]
    
        ports {
          port     = 443
          protocol = "TCP"
        }
    
        ports {
          port     = 80
          protocol = "TCP"
        }
      }
    }
    

    最終設定


    ちょうどsonarqubeに続いてくださいdocumentation あなたの特定のソースコントロールのために.次に、アプリケーションコードGithub actionワークフローに必要な手順を追加します.

    次の手順


    コンテナーインスタンスが実行されると、おそらく24/7のようにAzure関数やロジックアプリケーションを使用して停止して起動する必要はありません.私は、08 : 00でコンテナを起動して、コンテナを停止するために、Azure Logicアプリを走らせるつもりです
    私は、あなたが今日新しい何かを学ぶのを手伝うことができて、我々がここで何をするかについて共有することができることを望みますFirstPort .
    任意の質問は、タッチで取得



    アンドリュー[ MVP ]

    ✨チェックリスト✨あなたはAzureのprodに行く準備ができていますか?調べるには、このチェックリストを使用します.azurechecklist.com 呼んでください!このリストをDEVOPSのリストに移動させる❤️
    午前9時24分