革命のブログ

フレボワークスの社員がブログを通じて情報発信します。

タブロー買収 1.7兆円!

こんにちは、ささくらです。

BIツールについて、久しぶりに情報収集してみました。BIツール自体を自分たちが使うことはないので、提案活動に役立ちそうなエッセンスを抽出するという観点になります。

個別製品の説明はしませんが(下記URL参照)、全体的にUIや使いやすさなどはかなり洗練されており、ここから先は中身のあるコンテンツとのコラボに移り変わるのかなという印象でした。おそらくは、自社で保有していないビッグデータとの連携やAIを利用した集計以上の付加価値が求められるのだろうな、と。今後の展開も楽しみな分野です。

 MicroStrategy https://www.microstrategy.com/jp/product
 Sisense https://www.sisense.com/


先日の買収ニュース、
Salesforceによる、この分野のリーディングカンパニーの1社であるTableauの買収は
金額1.7兆円と大規模でした。
https://thebridge.jp/2019/06/salesforce-is-buying-data-visualization-company-tableau-for-15-7b-in-all-stock-deal-pickupnews

そんなにも企業価値が大きくなっているんだと驚きました。夢がありますね。
M&Aで事業拡大がうまくいくと、強い企業がどんどん強くなりますね。


#情報収集を通して、拝借できそうな機能案も見つけました!
#タイミングを見て提案したいと思います、些細な内容ですが楽しみです~

人工知能

こんにちは、ささくらです。
先日、人工知能サミット2019に参加してきました。

サブタイトルが「新時代を迎えたAI経営の展望と課題」ということもあり
Developer向けのセミナーと比較すると受講者の年齢層はやや高かったように感じます。
基本、写真も撮影禁止(一部のセミナーは可)だったので、画像はありません。

全体を通して、面白そうなキーワードとしては、以下のようなものがありました。
・燃料タンク残量、燃費把握
 →タンク残量を正確に測れる状況になっているようです。
  自動運転も実用化に向けてカウントダウンが始まっているので
  AIもモビリティの分野が最先端になるのでしょうか。
  Maasは収益化しづらいという話を聞いたことがありますが、参画している企業は多いような。。

・災害時の通れた道マップ
 →スマホから自動収集されるとしても有効活用されるならありかなと。

・顔認証で乗車管理
 バス乗車時に病院受付も兼ねるという実証実験のお話はとても面白かったです。
 公益性が高いと思うので、全国的に実現して欲しいですね。

・e-Palette(トヨタが2018年に発表したコンセプト)
 すごい世界ですね。想像を超えていて、良いのかよくわかりません。。
 e-paletteをわかりやすく説明してくれているサイトがありましたので、興味があれば。
  https://jidounten-lab.com/u_toyota-e-palette

・AIの学習データは他社データとのコラボが大切
 一社で収集できる範囲のデータでは差別化できないという時代のようです。
 高いレベルで連携しているグループ企業は強そうですね。

・データを提供しても良いと思われる企業になる
 データの価値の高さを示している内容だと思い、印象に残りました。


現時点では、人工知能を業務に活用する必要性は低いのですが
近い将来には活用する想定なので、目的・目標を明確にして扱っていきたいですね。
それまで、情報収集は怠らず。。

Oracle Code Tokyo 2019に行ってきました

f:id:frevo-works:20190520100449j:plain

どうも、小野です。

5/17に行われたOracle主催のイベント「Oracle Code Tokyo 2019」に参加してきました。

昨年までは、「Java Day Tokyo」として開催されていましたが、 Javaだけではなく、他の技術なども取り入れたいという思いもあり、今年からタイトルが変わったそうです。

個人的には、Javaのセッションが減ってしまったので、最初は参加するつもりはありませんでしたが、 和田卓人さんの「過去を知り、未来に備える - 技術選定の審美眼2019」がどうしても聞きたかったので、当日の午前中に参加を決めました。

今回はセッション内容を簡単に共有したいと思います。

続きを読む

ホームページをロリポップからGithub Pagesに移行しました

どうも、GWは家族サービスで終わりそうな小野です。

今回は、弊社で運用しているホームページをロリポップからGIthub Pagesに移行したので、手順を書き留めて置こうと思います。

移行に至ったのは以下の理由です。

  • Github PagesでもHTTPS化、独自ドメインの設定が可能である。
  • ホームページのソースをGithubで管理しており、ホームページを公開する場合、手作業でロリポップサーバにFTPアップロードしている。
  • Githubの有料プランを契約している。
  • 信頼性(Microsoft + Github)

弊社ではドメイン管理サービスにお名前.comを利用しているので、他のサービスを利用している場合は、置き換えてください。

続きを読む

感情分析アプリのEmpathセミナーに参加しました。

今日は、声からその人の感情がわかるソフトウェアで有名なEmpath様のセミナーへ

参加しました。

f:id:frevo-works:20190419175838j:plain

今一番、イノベータースタートアップ企業で元気がある会社です。

最初は、色々な方の声を録音し聴いて、「この人は喜んでる」とか「悲しんでる」

など、アナログ的に作り始めたそうです。

新しい物を作り上げる事は、改めて膨大な作業が必要なんだと感じました。

当社も何か始めないといけないと思った刺激を受けたセミナーでしたね。

皆さん頑張りましょう!

 

AWS Fargateを使って、マイクロサービス環境を実現する

どうも、小野です。 今回はAWS Fargateを使って、下図のような構成で作っていきます。

AWS Fargate

AWS Fargateは元々あるECSからEC2の管理を除外したサービスになります。 つまり、ECSをよりマネージドにしたものです。

Fargateについて知りたい方は公式サイトを確認してください。 aws.amazon.com

説明するにあたりAWSコンソールでもよいのですが、UIが頻繁に変わったりするので、今回はCLIベースで説明していきます。

※動作確認を行うターミナルは、コマンド実行時に変数を利用している関係上、最後まで閉じないようにしてください。

動作環境

  • Mac maxOS Mojave

前提

  • AWS CLIがインストール済み、かつバージョンが最新であること。
  • aws configreが設定済みであること。
  • Dockerコマンドが利用できること。
  • jqコマンドが利用できること。

準備

ロールの作成

assume-role-policy.json

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Principal": { "AWS": "arn:aws:iam::<アカウントID>:root" },
        "Action": "sts:AssumeRole"
    }
} 
ROLE_ARN=$(aws iam create-role --role-name fargate-helloworld-role --assume-role-policy-document file://./assume-role-policy.json | jq -r '.Role.Arn')
aws iam attach-role-policy --role-name fargate-helloworld-role --policy-arn "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"

コンテナイメージのリポジトリ作成

コンテナのリポジトリはDockerHubなどがありますが、今回はAWSのECRを使います。

HELLO_REPO_URI=$(aws ecr create-repository --repository-name helloworld/hello | jq -r '. repository. repositoryUri')
WORLD_REPO_URI=$(aws ecr create-repository --repository-name helloworld/world | jq -r '. repository. repositoryUri')
NGINX_REPO_URI=$(aws ecr create-repository --repository-name helloworld/nginx | jq -r '. repository. repositoryUri')

ECRにログインしておく

$(aws ecr get-login --no-include-email --region ap-northeast-1)

Webサーバのコンテナ作成

Webサーバにはnginxを使います。 nginxはALBからリクエストを受けて、サービスディスカバリを利用してアプリケーションにリクエストをします。

mkdir helloworld-nginx
cd helloworld-nginx

nginxの設定

default.confを作成します。

server {
    
    listen       80;
    server_name  localhost;
    
    proxy_set_header    Host    $host;
    proxy_set_header    X-Real-IP    $remote_addr;
    proxy_set_header    X-Forwarded-Host       $host;
    proxy_set_header    X-Forwarded-Server    $host;
    proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
    
    location ^~ /hello/ {
        # パスの先頭が「/hello/」の場合に helloアプリケーションにリクエスト
        proxy_pass    http://hello.helloworld:8080/hello/; 
    }

    location ^~ /world/ {
        # パスの先頭が「/world/」の場合に worldアプリケーションにリクエスト
        proxy_pass    http://world.helloworld:8080/world/;
    }

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

「hello.helloworld」、「world.helloworld」はサービスディスカバリの機能によってDNS解決されます。

Dockerfileを作成

FROM nginx

# 作成したdefault.confをnginxサーバに置きます
ADD "default.conf" "/etc/nginx/conf.d/"

Dockerリポジトリにプッシュ

docker build -t helloworld-nginx .
docker tag helloworld/nginx:latest ${NGINX_REPO_URI}:latest
docker push ${NGINX_REPO_URI}:latest

アプリケーションのコンテナ作成

今回作成するアプリケーションは、JavaEE + Payara Microで作ります。 アプリケーションは、Hello、Worldの2つ作ります。

Helloサービス

@Path("hello")
public class HelloResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getText() {
        // Worldサービスのホストは環境変数から取得
        String host = System.getenv("WORLD_HOST");

        String url = "http://" + host + ":8080/world/webresources";

        // Worldアプリケーションから文字列を受け取り、Helloと結合して返却する
        return "Hello " + ClientBuilder.newClient()
                .target(url)
                .path("world")
                .request()
                .get(String.class);
    }
}

pom.xmlの編集

buildタグ内に追加

<build>
  <finalName>hello</finalName> ←追加

Dockerファイルを作成する。

FROM payara/micro

# curlをインストールするため一時的にrootユーザに変更
USER root
RUN apk add --no-cache curl
USER payara
ADD "target/hello.war" "/tmp/"
ENTRYPOINT ["java", "-jar", "payara-micro.jar","--deploy","/tmp/hello.war"]

Dockerリポジトリにプッシュ

mvn clean package
docker build -t helloworld-hello .
docker tag helloworld/hello:latest ${HELLO_REPO_URI}:latest
docker push ${HELLO_REPO_URI}:latest

Worldサービス

@Path("world")
public class WorldResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getText() {
        return "World!";
    }
}

pom.xmlの編集

<build>
  <finalName>world</finalName> ←追加

Dockerfileの作成

FROM payara/micro

# curlをインストールするため一時的にrootユーザに変更
USER root
RUN apk add --no-cache curl
USER payara
ADD "target/world.war" "/tmp/"
ENTRYPOINT ["java", "-jar", "payara-micro.jar","--deploy","/tmp/world.war"]

Dockerリポジトリにプッシュ

mvn clean package
docker build -t helloworld-world .
docker tag helloworld/world:latest ${WORLD_REPO_URI}:latest
docker push ${WORLD_REPO_URI}:latest

タスク定義の設定

タスク定義の登録をCLIで実行する際に、オプション値にjsonで渡すものがあり、シンタックスベースの場合ダブルクォートのエスケープが必要になるので、JSONで設定します。

サービスのコンテナは、内部でヘルスチェックを行うようにします。

Helloサービス

task-hello.jsonの作成

{
    "family": "helloworld-hello", 
    "networkMode": "awsvpc", 
    "taskRoleArn": "<ROLE_ARN>",
    "executionRoleArn": "<ROLE_ARN>",
    "containerDefinitions": [
        {
            "name": "helloworld-hello", 
            "image": "<リポジトリURI>", 
            "portMappings": [
                {
                    "containerPort": 8080, 
                    "hostPort": 8080, 
                    "protocol": "tcp"
                }
            ], 
            "essential": true,
            "healthCheck": {
              "retries": 3,
              "command": [
                "CMD-SHELL",
                "curl http://localhost:8080/hello/index.html || exit 1"
              ],
              "timeout": 5,
              "interval": 30,
              "startPeriod": 120
            },
            "environment": [
              {
                "name": "WORLD_HOST",
                "value": "world.helloworld"
              }
            ]
        }
    ], 
    "requiresCompatibilities": [
        "FARGATE"
    ], 
    "cpu": "512", 
    "memory": "1024"
}

Worldサービス

task-world.jsonの作成

{
    "family": "helloworld-world", 
    "networkMode": "awsvpc", 
    "taskRoleArn": "<ROLE_ARN>",
    "executionRoleArn": "<ROLE_ARN>",
    "containerDefinitions": [
        {
            "name": "helloworld-world", 
            "image": "<リポジトリURI>", 
            "portMappings": [
                {
                    "containerPort": 8080, 
                    "hostPort": 8080, 
                    "protocol": "tcp"
                }
            ], 
            "essential": true,
            "healthCheck": {
              "retries": 3,
              "command": [
                "CMD-SHELL",
                "curl http://localhost:8080/world/index.html || exit 1"
              ],
              "timeout": 5,
              "interval": 30,
              "startPeriod": 120
            }
        }
    ], 
    "requiresCompatibilities": [
        "FARGATE"
    ], 
    "cpu": "512", 
    "memory": "1024"
}

Nginx

task-nginx.jsonの作成

{
    "family": "helloworld-nginx", 
    "networkMode": "awsvpc", 
    "taskRoleArn": "<ROLE_ARN>",
    "executionRoleArn": "<ROLE_ARN>",
    "containerDefinitions": [
        {
            "name": "helloworld-nginx", 
            "image": "<リポジトリURI>", 
            "portMappings": [
                {
                    "containerPort": 80, 
                    "hostPort": 80, 
                    "protocol": "tcp"
                }
            ], 
            "essential": true,
            "healthCheck": {
              "retries": 3,
              "command": [
                "CMD-SHELL",
                "curl http://localhost/ || exit 1"
              ],
              "timeout": 5,
              "interval": 30,
              "startPeriod": 0
            }
        }
    ], 
    "requiresCompatibilities": [
        "FARGATE"
    ], 
    "cpu": "256", 
    "memory": "512"
}

環境構築

では、準備が整ったので、CLIベースに順を追って構築していきます。 作業ディレクトリは、上記で作成したtask-xxxx.jsonがある場所に移動してください。

VPCの設定

# VPC作成
VPC_ID=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 | jq -r '.Vpc.VpcId')

# DNS hostname resolutionを有効
aws ec2 modify-vpc-attribute --vpc-id ${VPC_ID} --enable-dns-support
aws ec2 modify-vpc-attribute --vpc-id ${VPC_ID} --enable-dns-hostnames

# インターネットゲートウェイの作成
IGW_ID=$(aws ec2 create-internet-gateway | jq -r '.InternetGateway.InternetGatewayId')

# VPCにインターネットゲートウェイを追加
aws ec2 attach-internet-gateway --internet-gateway-id ${IGW_ID} --vpc-id ${VPC_ID}

# サブネット(パブリック:2、プライベート:2)を作成
PUBLIC_SUBNET_A_ID=$(aws ec2 create-subnet --vpc-id ${VPC_ID} --availability-zone ap-northeast-1a --cidr-block 10.0.0.0/24 | jq -r '.Subnet.SubnetId')
PUBLIC_SUBNET_C_ID=$(aws ec2 create-subnet --vpc-id ${VPC_ID} --availability-zone ap-northeast-1c --cidr-block 10.0.1.0/24 | jq -r '.Subnet.SubnetId')
PRIVATE_SUBNET_A_ID=$(aws ec2 create-subnet --vpc-id ${VPC_ID} --availability-zone ap-northeast-1a --cidr-block 10.0.2.0/24 | jq -r '.Subnet.SubnetId')
PRIVATE_SUBNET_C_ID=$(aws ec2 create-subnet --vpc-id ${VPC_ID} --availability-zone ap-northeast-1c --cidr-block 10.0.3.0/24 | jq -r '.Subnet.SubnetId')

# パブリックのルートテーブル作成
PUBLIC_ROUTE_TABLE_ID=$(aws ec2 create-route-table --vpc-id ${VPC_ID} | jq -r '.RouteTable.RouteTableId')
aws ec2 create-route --route-table-id ${PUBLIC_ROUTE_TABLE_ID} --destination-cidr-block 0.0.0.0/0 --gateway-id ${IGW_ID}

PUBLIC_A_ASSOCITATE_ID=$(aws ec2 associate-route-table --subnet-id ${PUBLIC_SUBNET_A_ID} --route-table-id ${PUBLIC_ROUTE_TABLE_ID} | jq -r '.AssociationId')
PUBLIC_C_ASSOCITATE_ID=$(aws ec2 associate-route-table --subnet-id ${PUBLIC_SUBNET_C_ID} --route-table-id ${PUBLIC_ROUTE_TABLE_ID} | jq -r '.AssociationId')

#Elastic IPを発行
ALLOCATION_ID=$(aws ec2 allocate-address --domain vpc | jq -r '.AllocationId')

# NATゲートウェイを作成
NAT_GATEWAY_ID=$(aws ec2 create-nat-gateway --subnet-id ${PUBLIC_SUBNET_A_ID} --allocation-id ${ALLOCATION_ID} | jq -r '.NatGateway.NatGatewayId')

# プライベートのルートテーブル作成
PRIVATE_ROUTE_TABLE_ID=$(aws ec2 create-route-table --vpc-id ${VPC_ID} | jq -r '.RouteTable.RouteTableId')
aws ec2 create-route --route-table-id ${PRIVATE_ROUTE_TABLE_ID} --destination-cidr-block 0.0.0.0/0 --nat-gateway-id ${NAT_GATEWAY_ID}

PRIVATE_A_ASSOCITATE_ID=$(aws ec2 associate-route-table --subnet-id ${PRIVATE_SUBNET_A_ID} --route-table-id ${PRIVATE_ROUTE_TABLE_ID} | jq -r '.AssociationId')
PRIVATE_C_ASSOCITATE_ID=$(aws ec2 associate-route-table --subnet-id ${PRIVATE_SUBNET_C_ID} --route-table-id ${PRIVATE_ROUTE_TABLE_ID} | jq -r '.AssociationId')

セキュリティグループの設定

# ロードバランサ、Nginx用のセキュリティグループ作成
WEB_SG_ID=$(aws ec2 create-security-group --group-name helloworld-web-sg --description "web security group" --vpc-id ${VPC_ID} | jq -r '.GroupId')

# インバウンド設定で80を許可する
aws ec2 authorize-security-group-ingress --group-id ${WEB_SG_ID} --protocol tcp --port 80 --cidr 0.0.0.0/0

# サービス用のセキュリティグループ作成
APP_SG_ID=$(aws ec2 create-security-group --group-name helloworld-app-sg --description "application security group" --vpc-id ${VPC_ID} | jq -r '.GroupId')

# インバウンド設定で8080を許可する
aws ec2 authorize-security-group-ingress --group-id ${APP_SG_ID} --protocol tcp --port 8080 --cidr 0.0.0.0/0

ロードバランサの設定

# ターゲットグループの作成
# ロードバランサがリクエストを送るターゲットを登録
TARGET_GROUP_ARN=$(aws elbv2 create-target-group --name helloworld-nginx --protocol HTTP --port 80 --vpc-id ${VPC_ID} --target-type ip | jq -r '.TargetGroups[0].TargetGroupArn')

# ロードバランサ作成
LB_ARN=$(aws elbv2 create-load-balancer --name alb-helloworld  --subnets ${PUBLIC_SUBNET_A_ID} ${PUBLIC_SUBNET_C_ID} --security-groups ${WEB_SG_ID} | jq -r '.LoadBalancers[0].LoadBalancerArn')

# リスナー登録
aws elbv2 create-listener --load-balancer-arn ${LB_ARN} --protocol HTTP --port 80 --default-actions Type=forward,TargetGroupArn=${TARGET_GROUP_ARN}

ECSの設定

# タスク定義作成
TASK_HELLO_REVISION=$(aws ecs register-task-definition --cli-input-json file://./task-hello.json | jq -r '.taskDefinition.revision')

TASK_WORLD_REVISION=$(aws ecs register-task-definition --cli-input-json file://./task-world.json | jq -r '.taskDefinition.revision')

TASK_NGINX_REVISION=$(aws ecs register-task-definition --cli-input-json file://./task-nginx.json | jq -r '.taskDefinition.revision')

# クラスタ作成
CLUSTER_NAME=fargate-helloworld
aws ecs create-cluster --cluster-name ${CLUSTER_NAME}

# サービス検出ネームスペース作成
OPERATION_ID=$(aws servicediscovery create-private-dns-namespace --name helloworld --vpc ${VPC_ID} | jq -r '.OperationId')

# 作成したネームスペースのIDを確認
NAMESPACE_ID=$(aws servicediscovery get-operation --operation-id ${OPERATION_ID} | jq -r '.Operation.Targets.NAMESPACE')

ネームスペース作成に時間がかかるので、1分ほど待つ。

# Helloサービス名登録
HELLO_SERVICE_ID=$(aws servicediscovery create-service --name hello --dns-config "NamespaceId=${NAMESPACE_ID},RoutingPolicy=MULTIVALUE,DnsRecords=[{Type=A,TTL=60}]" | jq -r '.Service.Id')
HELLO_REGISTRY_ARN=$(aws servicediscovery get-service --id ${HELLO_SERVICE_ID} | jq -r '.Service.Arn')

# Worldサービス名登録
WORLD_SERVICE_ID=$(aws servicediscovery create-service --name world --dns-config "NamespaceId=${NAMESPACE_ID},RoutingPolicy=MULTIVALUE,DnsRecords=[{Type=A,TTL=60}]" | jq -r '.Service.Id')
WORLD_REGISTRY_ARN=$(aws servicediscovery get-service --id ${WORLD_SERVICE_ID} | jq -r '.Service.Arn')

# Nginxサービス名登録
NGINX_SERVICE_ID=$(aws servicediscovery create-service --name nginx --dns-config "NamespaceId=${NAMESPACE_ID},RoutingPolicy=MULTIVALUE,DnsRecords=[{Type=A,TTL=60}]" | jq -r '.Service.Id')
NGINX_REGISTRY_ARN=$(aws servicediscovery get-service --id ${NGINX_SERVICE_ID} | jq -r '.Service.Arn')

# Helloサービス作成
aws ecs create-service --cluster ${CLUSTER_NAME} --service-name hello-service --task-definition helloworld-hello:${TASK_HELLO_REVISION} --desired-count 1 --launch-type "FARGATE" --network-configuration "awsvpcConfiguration={subnets=["${PRIVATE_SUBNET_A_ID}","${PRIVATE_SUBNET_C_ID}"],securityGroups=["${APP_SG_ID}"],assignPublicIp=DISABLED}" --service-registries "registryArn=${HELLO_REGISTRY_ARN},containerName=helloworld-hello"

# Worldサービス作成
aws ecs create-service --cluster ${CLUSTER_NAME} --service-name world-service --task-definition helloworld-world:${TASK_WORLD_REVISION} --desired-count 1 --launch-type "FARGATE" --network-configuration "awsvpcConfiguration={subnets=["${PRIVATE_SUBNET_A_ID}","${PRIVATE_SUBNET_C_ID}"],securityGroups=["${APP_SG_ID}"],assignPublicIp=DISABLED}" --service-registries "registryArn=${WORLD_REGISTRY_ARN},containerName=helloworld-world"

# Nginxサービス作成
aws ecs create-service --cluster ${CLUSTER_NAME} --service-name nginx-service --task-definition helloworld-nginx:${TASK_NGINX_REVISION} --desired-count 1 --launch-type "FARGATE" --network-configuration "awsvpcConfiguration={subnets=["${PRIVATE_SUBNET_A_ID}","${PRIVATE_SUBNET_C_ID}"],securityGroups=["${WEB_SG_ID}"],assignPublicIp=DISABLED}" --service-registries "registryArn=${NGINX_REGISTRY_ARN},containerName=helloworld-nginx" --load-balancers "targetGroupArn=${TARGET_GROUP_ARN},containerName=helloworld-nginx,containerPort=80"

動作確認

以下のコマンドを実行する。

open http://$(aws elbv2 describe-load-balancers --load-balancer-arns ${LB_ARN} | jq -r '.LoadBalancers[0].DNSName')/hello/webresources/hello

表示された画面に「Hello World!」が表示されるか確認してください。 環境構築後、ヘルスチェックが通すまでに時間がかかるので、時間をおいてから確認してください。

環境削除

最後に構築した環境をお片づけしましょう。

# ECSサービスの起動タスク数を0に更新
aws ecs update-service --cluster fargate-helloworld --service nginx-service --desired-count 0
aws ecs update-service --cluster fargate-helloworld --service hello-service --desired-count 0
aws ecs update-service --cluster fargate-helloworld --service world-service --desired-count 0

# ECSサービスを削除
aws ecs delete-service --cluster fargate-helloworld --service nginx-service
aws ecs delete-service --cluster fargate-helloworld --service hello-service
aws ecs delete-service --cluster fargate-helloworld --service world-service

# ECSクラスタを削除
aws ecs delete-cluster --cluster fargate-helloworld

# サービスディスカバリのサービス名を削除
aws servicediscovery delete-service --id ${HELLO_SERVICE_ID}
aws servicediscovery delete-service --id ${WORLD_SERVICE_ID}
aws servicediscovery delete-service --id ${NGINX_SERVICE_ID}

# サービスディスカバリのネームスペースを削除
aws servicediscovery delete-namespace --id ${NAMESPACE_ID}

# ロードバランサを削除
aws elbv2 delete-load-balancer --load-balancer-arn ${LB_ARN}

# ターゲットグループを削除
aws elbv2 delete-target-group --target-group-arn ${TARGET_GROUP_ARN}

# NATゲートウェイを削除
aws ec2 delete-nat-gateway --nat-gateway-id ${NAT_GATEWAY_ID}

# ルートテーブルを削除
aws ec2 delete-route --route-table-id ${PRIVATE_ROUTE_TABLE_ID} --destination-cidr-block 0.0.0.0/0
aws ec2 disassociate-route-table --association-id ${PRIVATE_A_ASSOCITATE_ID}
aws ec2 disassociate-route-table --association-id ${PRIVATE_C_ASSOCITATE_ID}
aws ec2 delete-route-table --route-table-id ${PRIVATE_ROUTE_TABLE_ID}

aws ec2 delete-route --route-table-id ${PUBLIC_ROUTE_TABLE_ID} --destination-cidr-block 0.0.0.0/0
aws ec2 disassociate-route-table --association-id ${PUBLIC_A_ASSOCITATE_ID}
aws ec2 disassociate-route-table --association-id ${PUBLIC_C_ASSOCITATE_ID}
aws ec2 delete-route-table --route-table-id ${PUBLIC_ROUTE_TABLE_ID}

# インターネットゲートウェイをデタッチ
aws ec2 detach-internet-gateway --internet-gateway-id ${IGW_ID} --vpc-id ${VPC_ID}

# Elastic IPを解放
aws ec2 release-address --allocation-id ${ALLOCATION_ID}

# サブネットを削除
aws ec2 delete-subnet --subnet-id ${PUBLIC_SUBNET_A_ID}
aws ec2 delete-subnet --subnet-id ${PUBLIC_SUBNET_C_ID}
aws ec2 delete-subnet --subnet-id ${PRIVATE_SUBNET_A_ID}
aws ec2 delete-subnet --subnet-id ${PRIVATE_SUBNET_C_ID}

# セキュリティグループを削除
aws ec2 delete-security-group --group-id ${WEB_SG_ID}
aws ec2 delete-security-group --group-id ${APP_SG_ID}

# VPCを削除
aws ec2 delete-vpc --vpc-id ${VPC_ID}

おわりに

AWS CLIのみでFargateを使った環境構築を行いました。 今回はオートスケーリングなどの設定を行いませんでしたが、負荷に応じてタスクごとにスケールが可能なので、 コンピューティングリソースを有効に使いつつ、柔軟に対応ができそうです。 サービスごとにアプリケーションの更新が可能なので、他のサービスに影響を与えずにデプロイが可能になります。

もし、マイクロサービスに手をつけたいけど、インフラ環境をどうすればいいか悩んでいる方は、試してみてください。

参考

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/create-service-discovery.html