サイドカー コンテナーを使用して Azure Container Instances をデプロイする
顧客の現在の API では、アプリケーション API へのトラフィックは暗号化されずに実行されています。 顧客は、アプリケーションで HTTP ではなく HTTPS を使用することを望んでいます。 HTTPS をサポートするようにアプリケーション コードを更新することはできますが、元のアプリケーションにはアクセスできません。
代替策は、アプリケーション コードを変更することなく必要な SSL 機能でアプリケーションを強化する "サイドカー" コンテナーを使用することです。 サイドカー パターンは、コンテナーベース アーキテクチャにおける強力な概念であり、アプリケーションの機能を、同じコンテナー グループ内で一緒に実行されるさまざまなコンテナー イメージに分解できます。
Azure Container Instances コンテナー グループでは、各コンテナーがアプリケーションで必要な機能の一部を引き受けることができます。 サイドカー コンテナーでは、アプリケーション コンテナーから (ことなるイメージ リポジトリからでも) のさまざまなコンテナー イメージを使用できます。 同じコンテナー グループ内のコンテナーは、根底のネットワーク スタックなど、いくつかのプロパティを共有しています。
注意
コンテナー グループの概念は、Kubernetes における "ポッド" に相当します。
このユニットでは、コンテナーの 1 つが Secure Sockets Layer (SSL) の暗号化と解読を行い、もう 1 つのコンテナーがアプリケーション API 機能を提供するコンテナー グループをデプロイします。 Secure Sockets Layer (SSL) 機能をオフロードするために、オープンソースの Web サーバーである NGINX を Web アプリケーションの前のリバース プロキシとして使用します。 暗号化されたトラフィックは NGINX コンテナー内の Azure Container Instances コンテナー グループに入り、NGINX が解読されたトラフィックを実際のアプリケーション コンテナーに渡します。
次の図に、このトポロジを示します。
NGINX 構成を作成する
まず、データ暗号化用のデジタル証明書を作成してから、NGINX 構成を含むファイルを作成します。 構成ファイルのすべての詳細を理解する必要はありませんが、以下の点が重要です。
proxy_pass
プロパティは、アプリケーション コンテナーの場所であるhttp://127.0.0.1:8080
を指します。 コンテナー グループ内の NGINX コンテナーとアプリケーション コンテナーは同じネットワーク名前空間を共有するため、localhost
または127.0.0.1
アドレスを使用することでお互いと通信できます。- 証明書ファイルとキーは /etc/nginx/ ディレクトリから読み取られるため、コンテナーをデプロイするときに、生成された証明書ファイルをそのディレクトリに入れる必要があります。
- サイドカー コンテナーは TCP ポート 443 をリッスンします。
Azure portal の Cloud Shell で、次のコードを実行して、データ暗号化用のデジタル証明書を取得します。 このユニットでは、自己署名証明書を使用しますが、運用時には証明機関 (CA) によって生成された証明書を使用することになります。
# Create self-signed certs openssl req -new -newkey rsa:2048 -nodes -keyout ssl.key -out ssl.csr -subj "/C=US/ST=WA/L=Redmond/O=AppDev/OU=IT/CN=contoso.com" openssl x509 -req -days 365 -in ssl.csr -signkey ssl.key -out ssl.crt
次のコードを実行して NGINX 構成ファイルを作成します。
# Create nginx.conf for SSL nginx_config_file=/tmp/nginx.conf cat <<EOF > $nginx_config_file user nginx; worker_processes auto; events { worker_connections 1024; } pid /var/run/nginx.pid; http { server { listen [::]:443 ssl; listen 443 ssl; server_name localhost; ssl_protocols TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; # a 1mb cache can hold about 4000 sessions, so you can hold 40000 sessions ssl_session_timeout 24h; keepalive_timeout 75; # up from 75 secs default add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains'; ssl_certificate /etc/nginx/ssl.crt; ssl_certificate_key /etc/nginx/ssl.key; location / { proxy_pass http://127.0.0.1:8080 ; proxy_set_header Connection ""; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$remote_addr; proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; } } } EOF
次のコードを実行して、base64 エンコードされた変数に、NGINX サイドカー コンテナーに渡したいファイルを収集します。
# Encode to Base64 nginx_conf=$(cat $nginx_config_file | base64) ssl_crt=$(cat ssl.crt | base64) ssl_key=$(cat ssl.key | base64)
NGINX サイドカーを使用してコンテナー グループをデプロイする
サイドカーなどの複雑な構成では、Azure CLI ではなく YAML を使用する必要があります。 YAML を使用してコンテナー グループを定義します。
変数に格納したすべての情報を組み合わせることで、サイドカー コンテナーのプロパティを指定する YAML ファイルを作成します。 以下の点に注意してください。
- SQL パスワードは安全な環境変数として渡されるため、コンテナー インスタンスの作成後も非公開のままになります。
- NGINX コンテナーは、証明書が見つかると想定される /etc/nginx/ ディレクトリに構成ボリュームをマウントします。 ボリューム コンテンツはシークレットとして指定されます。これが先に変数を base64 でエンコードした理由です。
- NGINX コンテナーではポート 443 が公開され、アプリケーション コンテナーではポート 8080 が公開されます。 しかし、コンテナー グループはポート 443 のみを公開し、NGINX サイドカー コンテナー経由でしかアプリケーションに到達できないようにします。
# Create YAML aci_subnet_id=$(az network vnet subnet show -n $aci_subnet_name --vnet-name $vnet_name -g $rg --query id -o tsv) aci_yaml_file=/tmp/aci_ssl.yaml cat <<EOF > $aci_yaml_file apiVersion: '2023-05-01' location: $location name: $aci_name properties: subnetIds: - id: $aci_subnet_id containers: - name: nginx properties: image: nginx ports: - port: 443 protocol: TCP resources: requests: cpu: 1.0 memoryInGB: 1.5 volumeMounts: - name: nginx-config mountPath: /etc/nginx - name: sqlapi properties: image: erjosito/yadaapi:1.0 environmentVariables: - name: SQL_SERVER_USERNAME value: $sql_username - name: SQL_SERVER_PASSWORD secureValue: $sql_password - name: SQL_SERVER_FQDN value: $sql_server_fqdn ports: - port: 8080 protocol: TCP resources: requests: cpu: 1.0 memoryInGB: 1 volumes: - secret: ssl.crt: "$ssl_crt" ssl.key: "$ssl_key" nginx.conf: "$nginx_conf" name: nginx-config ipAddress: ports: - port: 443 protocol: TCP type: Private osType: Linux tags: null type: Microsoft.ContainerInstance/containerGroups EOF
必要なすべての構成で YAML ファイルを作成した後、次の Azure CLI コマンドを実行してコンテナー インスタンスを作成します。
# Deploy ACI az container create -g $rg --file $aci_yaml_file
構成をテストするには、コンテナー インスタンスのプライベート IP アドレスを抽出し、テスト VM から HTTPS 経由でこれにアクセスします。 このユニットでは自己署名証明書を使用するので、証明書検証を無効にするために
curl
でフラグ-k
を使用します。 追加された curl フラグ-s
は、curl の出力の詳細を減らすために使用されます。# Test aci_ip=$(az container show -n $aci_name -g $rg --query 'ipAddress.ip' -o tsv) && echo $aci_ip ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $vm_pip "curl -ks https://$aci_ip/api/healthcheck"
API の
api/healthcheck
エンドポイントは、OK
で応答するはずです。